From 589db6f514aa3e83bf5cdfad4256a6198e2030c5 Mon Sep 17 00:00:00 2001 From: Myy Miouyouyou Date: Sun, 7 Aug 2022 16:35:30 +0200 Subject: [PATCH] Making the software a bit more user-friendly There's still a lot to do before it becomes really user-friendly, but at least, this thing won't spout weird Debug messages for nothing at the moment. Also, you can now specify the execution mode using '--mode=' The DESIGN.md now looks more like a "First module guide" but some parts are now missing... I'll try to fix that when possible. Signed-off-by: Myy Miouyouyou --- DESIGN.md | 95 ++++++++++++++++------- configurator | 89 ++++++++++++++++----- modules/docker/configuration/default.yaml | 2 +- 3 files changed, 136 insertions(+), 50 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 93de36c..08d2f5d 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,39 +1,78 @@ Version: 1 Status: DRAFT +# Status + +While this tutorial will explain you how to start coding your own +module, it won't be prepared for packaging... + +TODO : Add a 'build' script example that make the whole thing ready +for packaging. + # Main design -## Adding a simple module directly on your system +## Coding your own CLI module -For each module you want to add : +1. Create a directory where you'll put the CLI module code and `cd` into it. + Example : +```bash +mkdir -p ~/Documents/my_armbian_module +cd ~/Documents/my_armbian_module +``` -1. Create the following subdirectory : -`/usr/share/armbian/configurator/modules/${module_name}/cli` . -2. Copy your module executable file to : -`/usr/share/armbian/configurator/modules/${module_name}/cli/module` . -The file can actually be an absolute symlink to a system executable -file too. -3. Write a short description of the module in -`/usr/share/armbian/configurator/modules/${module_name}/DESC` . +2. Create a file named `DESC` and write a short description + for this module. +```bash +echo "Best module ever" > DESC +``` -That's about it. +3. Add a `module` file and ensure it is executable. This file + will be the one executed by the configurator when running + your module. +```bash +echo '#!/bin/bash' > module +echo "echo 'I told you, best module ever \!'" >> module +chmod +x module +``` -For deveopment purposes, you might want to actually symlink -`/usr/share/armbian/configurator/modules/${module_name}` to -a development directory inside your home directory. -For example : -`sudo ln -s /usr/share/armbian/configurator/modules/${module_name} /home/YourUserName/module_name` +4. Create the directory `/usr/share/armbian/configurator/modules/${module_name}/cli` + Example, if your module is named 'my_module' : +```bash +module_name=my_module +sudo mkdir -p "/usr/share/armbian/configurator/modules/${module_name}" +``` +5. Link the `DESC` file to `/usr/share/armbian/configurator/modules/${module_name}/DESC` +```bash +module_name=my_module +sudo ln -s "${PWD}/DESC" "/usr/share/armbian/configurator/modules/${module_name}/DESC" +``` +6. Link the directory itself to `/usr/share/armbian/configurator/modules/${module_name}/cli` +```bash +module_name=my_module +sudo ln -s "${PWD}" "/usr/share/armbian/configurator/modules/${module_name}/cli" +``` -## Adding a GUI (X11/Wayland) to a module +Now, the module is recognized by the configurator. -1. Create the directory : -`/usr/share/armbian/configurator/modules/${module_name}/gui` +Launch the configurator without arguments to see your module in the list. +Launch the configurator with the name of your module to launch it : -2. Add at least the executable file to : -`/usr/share/armbian/configurator/modules/${module_name}/gui/module` +```bash +module_name=my_module +configurator ${module_name} +``` -Then copy all the files required by the GUI into its specific folder, -`/usr/share/armbian/configurator/modules/${module_name}/gui`. +``` +I told you, best module ever ! +``` + +## Adding a GUI (X11/Wayland) to your module + +1. Create a directory where you'll put the GUI executable of your module. +2. Make sure your GUI executable name is named `module` +3. Link it to `/usr/share/armbian/configurator/modules/${module_name}/gui` + +You're done ## Adding a translation to the short description @@ -49,8 +88,8 @@ avoid using precise locales names when you can. Let's say you want to add a French translation for a module description. -French locales start with `fr`. -French locale for people living in France specifically is : `fr_FR`. +French locales start with `fr`. +French locale for people living in France specifically is : `fr_FR`. French locale for people living in Canada specifically is : `fr_CA`. So, if you want to add a french translation, add either a @@ -58,17 +97,17 @@ So, if you want to add a french translation, add either a If you add both `DESC.fr_FR` and `DESC.fr`, the system will use : -* `DESC.fr_FR` for people using the `fr_FR` locale. +* `DESC.fr_FR` for people using the `fr_FR` locale. * `DESC.fr` for people using `fr_CA` locale. If you only add `DESC.fr`, the system will use : -* `DESC.fr` for people using the `fr_FR` locale. +* `DESC.fr` for people using the `fr_FR` locale. * `DESC.fr` for people using `fr_CA` locale. if you only add `DESC.fr_FR`, the system will use : -* `DESC.fr_FR` for people using the `fr_FR` locale. +* `DESC.fr_FR` for people using the `fr_FR` locale. * `DESC` (default english version) for people using the `fr_CA` locale. ## Prepare for packaging diff --git a/configurator b/configurator index 234e3b0..2059350 100755 --- a/configurator +++ b/configurator @@ -1,8 +1,9 @@ #!/usr/bin/env python3 +from argparse import ArgumentParser, RawDescriptionHelpFormatter import logging -from pathlib import Path import os +from pathlib import Path import stat import subprocess import sys @@ -16,7 +17,7 @@ class Helpers: @staticmethod def get_logger(name: str = 'default'): logger = logging.getLogger(name) - logger.setLevel(logging.DEBUG) + logger.setLevel(logging.INFO) # Avoid messages duplication after multiple Jupyter Lab runs handler_console = None @@ -164,8 +165,8 @@ class Configurator: def print_modules(self): for module_name in self.modules: - modes = self.module_modes(module_name) - desc = self.module_desc(module_name) + modes = ', '.join(self.module_modes(module_name)) + desc = self.module_desc(module_name).strip() self.logger.info(f'\t{module_name}\t{modes}\t{desc}') def system_can_handle_gui(self): @@ -173,7 +174,8 @@ class Configurator: def execute_module(self, module_name: str, arguments: list, mode: str = '') -> int: if not self.module_exist(module_name): - self.logger.critical(f'{module_name} does not exist !') + self.logger.critical(f'Module {module_name} does not exist !') + return -1 modes = self.module_modes(module_name) @@ -188,13 +190,13 @@ class Configurator: mode = 'cli' else: if not mode in modes: - self.logger.critical(f'{module_name} has no {mode} mode') - sys.exit(1) + self.logger.critical(f'The module {module_name} has no {mode} mode') + return -1 subprocess.run([self.module_path(module_name) / mode / 'module'] + arguments) -if __name__ == '__main__': +def parse_arguments(arguments: list): # TODO Make it configurable through config files # AND command line arguments @@ -205,17 +207,62 @@ if __name__ == '__main__': configurator = Configurator(modules_dirpath=modules_dirpath) - # Not using ArgParser at the moment since I need to keep - # track of the position of the arguments. - # All the arguments passed after the module name are passed - # to the module 'as-is' and should not be interpreted in any - # way. - # Parsing the arguments before with ArgParser should not - # be THAT hard... still, this will be for the next time. - arguments = sys.argv - n_args = len(arguments) - if n_args < 2: + epilog = 'The modules are all installed in /usr/share/armbian/configurator/modules\n\n' + epilog += 'Example usage :\n' + epilog += ' configurator docker\n' + + + parser = ArgumentParser( + description='Armbian configurator') + #formatter_class=RawDescriptionHelpFormatter, + #epilog=epilog) + parser.add_argument('module') + parser.add_argument('--mode', nargs=1, choices=['cli', 'tui', 'gui'], help='Launch a module in a specific mode') + + + # Basically, ArgParse should only manage the arguments that + # are passed to the configurator. + # The other arguments must be passed "as-is" to the module. + # So : + # * We search for the first argument that doesn't start with + # a dash + # * We consider that to be the module name + # * We cut the array after the module name. + # This new array is considered to be the arguments to + # the module. + configurator_args = arguments[1:] + module_args = [] + for i in range(1,len(arguments)): + if not (arguments[i].startswith("-")): + next_arg = i + 1 + configurator_args = arguments[1:next_arg] + module_args = arguments[next_arg:] + break + + result = [] + try: + result = parser.parse_args(configurator_args) + except: + print('\nAvailable modules are :\n') configurator.print_modules() - else: - module_name = arguments[1] - configurator.execute_module(module_name, arguments=arguments[2:]) + print(epilog) + sys.exit(1) + + mode = '' + if result.mode: + mode = mode.join(result.mode) + + sys.exit(configurator.execute_module(result.module, arguments=module_args, mode=mode)) + +if __name__ == '__main__': + + + parse_arguments(sys.argv) + sys.exit(0) + #arguments = sys.argv + #n_args = len(arguments) + #if n_args < 2: + #configurator.print_modules() + #else: + #module_name = arguments[1] + #configurator.execute_module(module_name, arguments=arguments[2:]) diff --git a/modules/docker/configuration/default.yaml b/modules/docker/configuration/default.yaml index 47289e3..b67009f 100644 --- a/modules/docker/configuration/default.yaml +++ b/modules/docker/configuration/default.yaml @@ -1,6 +1,6 @@ version: 1 # Directory containing the docker-compose templates to install -templates_dir: "/usr/share/armbian/configurator/modules/docker/softwares" +templates_dir: "/usr/share/armbian/configurator/modules/docker/cli/softwares" # Directory where docker-compose installations are install_dir: "/opt/armbian/docker" # The name of the docker service