greenled / portainer-stack-utils

CLI client for Portainer
https://hub.docker.com/r/greenled/portainer-stack-utils/
GNU General Public License v3.0
74 stars 16 forks source link

Custom stack environment variables #7

Closed greenled closed 5 years ago

greenled commented 5 years ago

The script only supports keeping stack envvars between stack updates, not changing them. Even worse, new deployments go without envvars. It would be desirable to allow the user to set ennvars at will.

They could be taken from a file like:

MYSQL_ROOT_PASSWORD=password
ALLOWED_HOSTS=*

Envvars set through the script should overwrite existing ones with the same name, and keep the others.

The Portainer API already has a Env field for this purpose:

[
  {
    "name": "MYSQL_ROOT_PASSWORD",
    "value": "password"
  }
]
tortuetorche commented 5 years ago

Hi @greenled,

Any news on this issue? I'll be very useful.

Have a good day, Tortue Torche

greenled commented 5 years ago

Hi @tortuetorche,

I'm afraid I can not work on this in an immediate future. Too much work here and some health issues :( Feel free to contribute a solution if you want to :muscle: Have a good day too.

tortuetorche commented 5 years ago

Hi @greenled,

Here a starting point:

Create a .env file, which contains the Docker Stack environment variables:

HOSTNAME=bfaecdeb0cd2
HOME=/root
_BASH_VERSION=5.0
_BASH_PATCH_LEVEL=0
_BASH_LATEST_PATCH=7
TERM=xterm
foo=d=cc

Then execute this jq command:

env -i $(cat .env) jq -n 'env | to_entries | map({name: .key, value: .value})'

This will output:

[
  {
    "name": "HOSTNAME",
    "value": "bfaecdeb0cd2"
  },
  {
    "name": "HOME",
    "value": "/root"
  },
  {
    "name": "_BASH_VERSION",
    "value": "5.0"
  },
  {
    "name": "_BASH_PATCH_LEVEL",
    "value": "0"
  },
  {
    "name": "_BASH_LATEST_PATCH",
    "value": "7"
  },
  {
    "name": "TERM",
    "value": "xterm"
  },
  {
    "name": "foo",
    "value": "d=cc"
  }
]

I hope you'll be better soon, Tortue Torche

greenled commented 5 years ago

Thanks @tortuetorche, this is a very good starting point.

Stack envvars are set in the deploy() function. When a new stack is deployed it gets no envvars, and when an existing one is updated its envvars are reused (extracted from its stack definition into the stack_envvars variable and set back again). For the first case it would be just a matter of loading the content of the envvars file and transform it into JSON using the command you provided, and set it as the stack_envvars value. For the second case, though, the script should update the current stack envvars rather than setting them from scratch, keeping any value not previously set in the .env file.

I would also make the environment variables file path customizable with a flag, like -g (could be any of the remaining bfghijkmoqwxyz), and a script configuration envvar, like ENVIRONMENT_VARIABLES_FILE.

tortuetorche commented 5 years ago

Hi @greenled ,

Thank you for your explanations.

Here some snippets to merge two environment variable JSON files with jq:

jq -s 'add | unique_by(.name)' env_new.json env_old.json

Or:

jq -n '[inputs] | add | unique_by(.name)' env_new.json env_old.json

Have a good day, Tortue Torche