SensorsIot / IOTstack

Docker stack for getting started on IOT on the Raspberry PI
GNU General Public License v3.0
1.45k stars 308 forks source link

[enhancement] CLI development #505

Open ukkopahis opened 2 years ago

ukkopahis commented 2 years ago

I'm working on a CLI interface and a proper back-end API for stack modification and upgrades.

Design goals:

Template specification (service.yml)

The service.yml-templates are currently yaml-snippets, with a custom variable replacement scheme (%var%). Docker compose files natively allow for variables using the variable substitution syntax, e.g. ${VARIABLE:?error message} or ${VARIABLE:-default_value}. The custom notation will be migrated to use compose variables.

Thus a service.yml-file is defined as:

The menu should store user-entered variable values into .env, where they are read from when re-running menu to show the previously made choices.

Special templating variables

service.yml variable assumed meaning
IOTSTACK_SERVICE_PASSWORD or IOTSTACK_SERVICE_INITIAL_PASSWORD generate random password or use an user defined password
IOTSTACK_SERVICE_VARNAME_CHECKLIST space-separated default values user may deselect
IOTSTACK_SERVICE_VARNAME_CHECKLIST_UNSELECTED per default unselected values available to be selected
IOTSTACK_SERVICE_VARNAME_BOOL boolean choice, values 'true' or 'false'
IOTSTACK_SERVICE_VARNAME_INT integer value choice
IOTSTACK_SERVICE_VARNAME string value choice
# comment on the same yaml-line as a variable provide UI description for the value choice
IOTSTACK_TZ Use /etc/timezone, but detect if TZ is defined in shell-env or .env
IOTSTACK_HOSTNAME replaced using the hostname
IOTSTACK_LAN_IP constant resolving to the IP of eth0 or wlan0, print warning if this is an ip obtained by DHCP
IOTSTACK_LAN_MAC constant resolving to the MAC address of eth0 or wlan0
IOTSTACK_UID user id
IOTSTACK_GID group id

Example (combining many different service use-cases):

environment:
  - TZ=${IOTSTACK_TZ:-Etc/UTC}
  - WEBPASSWD=${IOTSTACK_PIHOLE_INITIAL_PASSWORD:-IOtSt4ckP1Hol3}
  - TOKEN=${IOTSTACK_DUCKDNS_TOKEN:?token from duckdns.org required}
  - PLUGINS=${IOTSTACK_NODERED_PLUGINS_CHECKLIST:-node-pi-gpiod contrib-influxdb contrib-boolean-logic node-rbe configurable-ping dashboard} # Addons available for NodeRed
  - DUMMY_PLUGINS_NON_DEFAULT=${IOTSTACK_NODERED_PLUGINS_CHECKLIST_UNSELECTED:-ode-openweathermap contrib-discord node-email ...} # This defines a dummy variable in order to add the list of unselected items.
ports:
  - ${IOTSTACK_HEIMDALL_HTTP_INT:-8880}:80 # HTTP port
  - ${IOTSTACK_HEIMDALL_HTTPS_INT:-8883}:8080 # HTTPS port
entrypoint:
  - ash
  - -c
  - |
    cd /usr/src/node-red
    for a in $$PLUGINS ; do npm install --save  node-red-$$a ; done
    npm start --cache /data/.npm -- --userDir /data

In this example menu would only require user to enter the duckdns_token, rest of the variables would be their default values. Note: the entrypoint is an example how to implement dynamic functionality based on variable values.

Manual use without menu

Additionally operation without using the menu is possible (when restoring proper indentation to service.yml-files and appending "services:" to env.yml/docker-compose-base.yml) by e.g.:

$ cat .templates/docker-compose-base.yml .templates/pihole/service.yml > docker-compose.yml
$ echo "IOTSTACK_PIHOLE_INITIAL_PASSWORD=trulysecret" >> .env
$ docker-compose up

Development

Current WIP version: template.py

Feel free to take a look and give feedback or comment if something doesn't look right.

Tasks:

Container changes/fixes (that are much easier):

Definition of Done:

Additional ideas for the future: