add documentation on how to write config panel and actions

This commit is contained in:
Laurent Peuch 2020-04-27 13:39:35 +02:00
parent 3117a2aa83
commit 08414c24aa
6 changed files with 482 additions and 0 deletions

BIN
images/actions_example.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

144
packaging_apps_actions.md Normal file
View file

@ -0,0 +1,144 @@
# Applications Actions
<div class="alert alert-warning">For now, all those features are <b>EXPERIMENTAL</b>
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 <b>they might randomly breaks on your apps</b>
</div>
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
<div class="alert alert-warning">For now since those features are still
experimental you won't find any direct links to the app actions on the app
page</div>
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`)

View file

@ -0,0 +1,40 @@
# Advanced features of apps packaging
<div class="alert alert-warning">For now, all those features are <b>EXPERIMENTALS</b>
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 <b>they might randomly breaks on your apps</b>
</div>
## 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)

View file

@ -0,0 +1,298 @@
# Applications Configuration Panel
<div class="alert alert-warning">For now, all those features are <b>EXPERIMENTAL</b>
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 <b>they might randomly breaks on your apps</b>
</div>
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
<div class="alert alert-warning">For now since those features are still
experimental you won't find any direct links to the app actions on the app
page</div>
### 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.<br>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.<br>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
```