diff --git a/images/actions_example.png b/images/actions_example.png new file mode 100644 index 00000000..04209da6 Binary files /dev/null and b/images/actions_example.png differ diff --git a/images/config_panel_example.png b/images/config_panel_example.png new file mode 100644 index 00000000..5665a3c9 Binary files /dev/null and b/images/config_panel_example.png differ diff --git a/images/config_panel_toml_example.png b/images/config_panel_toml_example.png new file mode 100644 index 00000000..c72e0baf Binary files /dev/null and b/images/config_panel_toml_example.png differ diff --git a/packaging_apps_actions.md b/packaging_apps_actions.md new file mode 100644 index 00000000..595b30db --- /dev/null +++ b/packaging_apps_actions.md @@ -0,0 +1,144 @@ +# Applications Actions + +
For now, all those features are EXPERIMENTAL +and aren't ready for production and are probably going to change again, if you +still decide to use them don't expect them to be stable and follow to core +development of YunoHost otherwise they might randomly breaks on your apps +
+ +Applications "actions" is a packaging feature that allow you to ship with your +application a list of "actions" executable from both the cli and the admin +interfaces. + +"actions" are a list of custom commands that, optionally, has arguments (like +the installation script of an application has arguments) and once called will +called a specific selected command with those arguments. Like an "actions" +restart service with a argument "service name" could called the command +`systemctl restart $some_service` (but don't that specific action in your app, +it's just for example purpose). + +Like the installation page generated from the manifest those actions can accept +a list of arguments. + +Their main purpose is to expose procedures that a sysadmin would normally do on +CLI but that your application user would want to do but don't have the +knowledge to do by themselves via ssh (or are just too lazy for that). + +For example those could be: + +* importing data in a application +* generate a custom backup +* start a procedure like synchronising file with the file system (nextcloud for example) +* purge a local cache +* restart some services +* modify a theme + +Actions looks like this in the admin interface: + +![actions admin screenshot](images/actions_example.png) + +## How to add actions to your application + +Adding actions to your application is pretty simple as it is very similar to +writing your manifest for the application installation. + +You need to write an `actions.toml` file in your application at the root level +like the `manifest.toml`/`manifest.json`. + +The general pattern looks like this: + +```toml +[first_action] +name = "some name" +description = "some description that will be displayed" + +# can be a bash command like so: +command = "echo pouet $YNH_ACTION_FIRST_ARGUMENT" +# or a path to a script like +command = "/path/to/some/stuff --some-flag $YNH_ACTION_FIRST_ARGUMENT" + +user = "root" # optional +cwd = "/" # optional, "current working directory", by default it's "/etc/yunohost/apps/the_app_id" + # also the variable "$app" is available in this variable and will be replace with the app id + # for example you can write "/var/www/$app" +accepted_return_codes = [0, 1, 2, 3] # optional otherwise only "0" will be a non enorous return code + + [first_action.arguments] + # here, you put a list of arguments exactly like in manifest.toml/json + [first_action.arguments.first_argument] + type = "string" + ask = "service to restart" + example = "nginx" + + ... # add more arguments here if needed + # you can also have actions without arguments + +[another_action] +name = "another name" +command = "systemctl restart some_service" + + [another_action.arguments] + [another_action.arguments.argument_one] + type = "string" + ask = "some stuff" + example = "stuff" + + ... # add more arguments here if needed + # you can also have actions without arguments +``` + +You can have as much actions as you want and from zero to as many arguments you want. + +If you prefer, you can also write your actions in json like manifest.json: + +```json +[{ + "id": "restart_service", + "name": "Restart service", + "command": "echo pouet $YNH_ACTION_SERVICE", + "user": "root", # optional + "cwd": "/", # optional + "accepted_return_codes": [0, 1, 2, 3], # optional + "description": { + "en": "a dummy stupid exemple or restarting a service" + }, + "arguments": [ + { + "name": "service", + "type": "string", + "ask": { + "en": "service to restart" + }, + "example": "nginx" + } + ] +}, +{ + ... # other action +}] +``` + +## How to use actions + +### In the admin + +
For now since those features are still +experimental you won't find any direct links to the app actions on the app +page
+ +The actions are located on https://some_domain.tld/yunohost/admin/#/apps/$app_id/actions + +## With the CLI + +The CLI API is very similar to application installation. You have 2 commands: + +* `yunohost app list $app` +* `yunohost app run $app $action_id` ("$action_id" is the this between "[]" + like "[another_action]" in the example) + +`list` will obviously give you all actions for an application. + +`run` will run an existing action for an application and will ask, if needed, +values for arguments. Like with `yunohost app install` you can use the `-a` and +pass arguments in the HTTP POST arguments format (like +`&path=/app&domain=domain.tld&other_value=stuff`) diff --git a/packaging_apps_advanced.md b/packaging_apps_advanced.md new file mode 100644 index 00000000..c2bb905e --- /dev/null +++ b/packaging_apps_advanced.md @@ -0,0 +1,40 @@ +# Advanced features of apps packaging + +
For now, all those features are EXPERIMENTALS +and aren't ready for production and are probably going to change again, if you +still decide to use them don't expect them to be stable and follow to core +development of YunoHost otherwise they might randomly breaks on your apps +
+ +## Actions + +Actions allow you to ship a list of executables "actions" related to your +application, for example that could be: + +* import data +* generate a custom backup +* start a procedure +* regenerate a local cache + +[Full documentation](#/packaging_apps_actions) + +Example in the admin: + +![actions admin screenshot](images/actions_example.png) + +## Configuration Panel + +Configuration or "config_panel" allow you to offer a custom configuration panel +for your application integrated into YunoHost administration panel. This allow +you to expose whatever configuration you want for your application and this is +generally used to handle an application configuration file when this is not +possible inside the application itself. + +This is generally also the place where you want to add the option to make an +application public or not. + +[Full documentation](#/packaging_apps_config_panel) + +Example in the admin: + +![actions admin screenshot](images/config_panel_example.png) diff --git a/packaging_apps_config_panel.md b/packaging_apps_config_panel.md new file mode 100644 index 00000000..29d48e55 --- /dev/null +++ b/packaging_apps_config_panel.md @@ -0,0 +1,298 @@ +# Applications Configuration Panel + +
For now, all those features are EXPERIMENTAL +and aren't ready for production and are probably going to change again, if you +still decide to use them don't expect them to be stable and follow to core +development of YunoHost otherwise they might randomly breaks on your apps +
+ +Configuration panel, or "config_panel", is a way for an application to ship a +custom configuration panel available in the YunoHost's admin interface for the +application. This is generally used to replace the "you need to manually edit +this configuration file (or files) in whatever format/language for this +application in cli and do all those complex commands" to "just use to +configuration panel to change the options of the application". + +Yes, this is one place to add this so asked "how can I make my application from +public to private and vice versa" user request. + +config_panel is probably the most complex YunoHost apps feature as you'll need +to write both a description of the panel in toml and a script that will need to +both work in a "display mode" and "handle inputs" mode. But this is still very +doable and very worth it if you need it. + +Here how it looks like in the admin interface: + +![actions admin screenshot](images/config_panel_example.png) + +## Usage + +### Admin interface + +The configuration panel for an application can be accessed with this url: + + https://my_domain.tld/yunohost/admin/#/apps/$app_id/config-panel + +
For now since those features are still +experimental you won't find any direct links to the app actions on the app +page
+ +### CLI + +For now the CLI API for the config panel is not very good at all, you can still +use it but it's really impracticable. + +* `yunohost app config show-panel $app_id` will show the panel. **But for now +it's very broken and will asked question for unfilled value of the panel**. + +* `yunohost app config apply` will call the script with apply and... no values + since you aren't passing them, except if you are ready to play with the `-a` + flag and pass every global value in the HTTP POST format (protip: you don't) + +In conclusion: don't use the CLI for now, we need to design something better. + +## How to add a config_ panel to your application + +### config_panel.toml + +Firs, you need to write a `config_panel.toml` (or `config_panel.json` if you +REALLY wants it but we really don't recommend it has it is very error prone and +frustrating to write by hand) that will be located at the root of you +application, next to the manifest.json/toml. It looks like this: + +```toml +version = "0.1" # version number, not used yet but important +name = "name that will be displayed on the admin" + +[section_id] +name = "name of the section that will be displayed" + + [section_id.sub_section_id] + name = "sub section" + + # those arguments are in yunohost argument format like manifest.json + [section_id.sub_section_id.option_id] + ask = "the text displayed for the option" + type = "argument_option" + default = true + help = "A public Leed will be accessible for third party apps.
By turning on 'anonymous readers' in Leed configuration, you can made your feeds public." + + [section_id.sub_section_id.another_option_id] + ... + + [section_id.another_sub_section_id] + name = "stuff" + +[another_section_id] +name = "stuff" + +... +``` + + +And a real world example with the rendered admin: + +![config_panel_toml_example](images/config_panel_toml_example.png) + +As a text format: + +```toml +version = "0.1" +name = "Leed configuration panel" + +[main] +name = "Leed configuration" + + [main.is_public] + name = "Public access" + + # those arguments are in yunohost argument format + [main.is_public.is_public] + ask = "Is it a public website ?" + type = "boolean" + default = true + help = "A public Leed will be accessible for third party apps.
By turning on 'anonymous readers' in Leed configuration, you can made your feeds public." + + + [main.overwrite_files] + name = "Overwriting config files" + + [main.overwrite_files.overwrite_nginx] + ask = "Overwrite the nginx config file ?" + type = "boolean" + default = true + help = "If the file is overwritten, a backup will be created." + + [main.overwrite_files.overwrite_phpfpm] + ask = "Overwrite the php-fpm config file ?" + type = "boolean" + default = true + help = "If the file is overwritten, a backup will be created." + +... +``` + +### the scripts/config script + +To make your configuration panel functional you need write a "config" script +that will be location in the "script" folder like the "install" script. This +script will be called at 2 different occasions: + +* when the configuration panel is displayed and yunohost needs to fill the values +* when the configuration is modified by the user + +Every option of the configuration panel will be send to the script +following this naming convention: + +```bash +YNH_{section_id}_{sub_section_id}_{option_id} (everything in upper case) +``` + +For example, this option value: + +```toml +[main] +name = "Leed configuration" + + [main.is_public] + name = "Public access" + + # those arguments are in yunohost argument format + [main.is_public.is_public] + ... +``` + +Will be available under this name in the config script: + +``` +YNH_CONFIG_MAIN_IS_PUBLIC_IS_PUBLIC +``` + +Also, the same "scripts/config" script is called in both situation. To differentiate +those situation the first argument passed to the config script is either "show" +or "apply". + +A common pattern to handle that is to write your script following this pattern: + +```bash +show_config() { + # do stuff +} + +apply_config() { + # do stuff +} + +case $1 in + show) show_config;; + apply) apply_config;; +esac +``` + +#### The "show" part + +The show part is when the user ask to see the current state of the +configuration panel (like opening to configuration panel page on the admin +interface). The role of the scripts/config script here is to gather all the +relevant information, by for example parsing a configuration file or querying a +database, and communicate it to YunoHost. To do so, you need to use the helper +`ynh_return` like so: + +```bash +ynh_return "YNH_CONFIG_SOME_VARIABLE_NAME=some_value" +``` + +For example, for this config_panel: + +```toml +[main] +name = "Leed configuration" + + [main.is_public] + name = "Public access" + + # those arguments are in yunohost argument format + [main.is_public.is_public] + ... +``` + +You would do: + +```bash +ynh_return "YNH_CONFIG_MAIN_IS_PUBLIC_IS_PUBLIC=1" +``` + +If you don't provide any value for a configuration **the default value will be used**. + +Expanding our previous example you would have this scripts/config script: + +```bash +show_config() { + ynh_return "YNH_CONFIG_MAIN_IS_PUBLIC_IS_PUBLIC=1" +} + +apply_config() { + # do stuff +} + +case $1 in + show) show_config;; + apply) apply_config;; +esac +``` + +#### The "apply" part + +The "apply" part is called when the user click on "submit" on the configuration +page on the admin interface. This part is simpler to write: + +- the scripts/config will be called with "apply" +- all the value in the config panel (modified or not) are available as global + variable in the script following the format `YNH_{section_id}_{sub_section_id}_{option_id}` + (exactly the same than for show) +- the script is responsible for doing whatever it wants with those information +- once the script as succeeded, the admin interface display the config panel + again so the script is called again in "show" mode + +Expanding the previous script that could look like that: + +```bash +show_config() { + ynh_return "YNH_CONFIG_MAIN_IS_PUBLIC_IS_PUBLIC=1" +} + +apply_config() { + value=$YNH_CONFIG_MAIN_IS_PUBLIC_IS_PUBLIC + # do some stuff with value +} + +case $1 in + show) show_config;; + apply) apply_config;; +esac +``` + +Or if you want a full useless simple script that store the value in a file, +this can looks like this: + +```bash +dummy_config_file="dummy_config_file.ini" + +show_config() { + if [ -e $dummy_config_file ] + then + ynh_return "YNH_CONFIG_MAIN_IS_PUBLIC_IS_PUBLIC=$(cat $dummy_config_file)" + fi + + # the default value will be used +} + +apply_config() { + echo $YNH_CONFIG_MAIN_IS_PUBLIC_IS_PUBLIC > $dummy_config_file +} + +case $1 in + show) show_config;; + apply) apply_config;; +esac +```