Merge pull request #8 from tortuetorche/patch-1

Add custom stack environment variables
This commit is contained in:
Juan Carlos Mejías Rodríguez 2019-05-10 20:42:30 -07:00 committed by GitHub
commit d90eb42ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 43 deletions

View File

@ -10,6 +10,7 @@ ENV LANG="en_US.UTF-8" \
PORTAINER_URL="" \
PORTAINER_STACK_NAME="" \
DOCKER_COMPOSE_FILE="" \
ENVIRONMENT_VARIABLES_FILE="" \
PORTAINER_PRUNE="false" \
PORTAINER_ENDPOINT="1" \
HTTPIE_VERIFY_SSL="yes" \

View File

@ -44,6 +44,7 @@ This is particularly useful for CI/CD pipelines.
- `PORTAINER_URL` (string, required): URL to Portainer
- `PORTAINER_STACK_NAME` (string, required): Stack name
- `DOCKER_COMPOSE_FILE` (string, required if action=deploy): Path to doker-compose file
- `ENVIRONMENT_VARIABLES_FILE` (string, optional, only used when action=deploy or action=update): Path to file with environment variables to be used by the stack. See [stack environment variables](#stack-environment-variables) below.
- `PORTAINER_PRUNE` ("true" or "false", optional): Whether to prune unused containers or not. Defaults to `"false"`.
- `PORTAINER_ENDPOINT` (int, optional): Which endpoint to use. Defaults to `1`.
- `HTTPIE_VERIFY_SSL` ("yes" or "no", optional): Whether to verify SSL certificate or not. Defaults to `"yes"`.
@ -60,6 +61,7 @@ export PORTAINER_PASSWORD="password"
export PORTAINER_URL="http://portainer.local"
export PORTAINER_STACK_NAME="mystack"
export DOCKER_COMPOSE_FILE="/path/to/docker-compose.yml"
export ENVIRONMENT_VARIABLES_FILE="/path/to/env_vars_file"
./psu
```
@ -84,6 +86,7 @@ This is more suitable for standalone script usage.
- `-l` (string, required): URL to Portainer
- `-n` (string, required): Stack name
- `-c` (string, required if action=deploy): Path to doker-compose file
- `-g` (string, optional, only used when action=deploy or action=update): Path to file with environment variables to be used by the stack. See [stack environment variables](#stack-environment-variables) below.
- `-r` ("true" or "false", optional): Whether to prune unused containers or not. Defaults to `"false"`.
- `-e` (int, optional): Which endpoint to use. Defaults to `1`.
- `-s` ("yes" or "no", optional): Whether to verify SSL certificate or not. Defaults to `"yes"`.
@ -94,13 +97,26 @@ This is more suitable for standalone script usage.
#### Examples
```bash
./psu -a deploy -u admin -p password -l http://portainer.local -n mystack -c /path/to/docker-compose.yml
./psu -a deploy -u admin -p password -l http://portainer.local -n mystack -c /path/to/docker-compose.yml -g /path/to/env_vars_file
```
```bash
./psu -a undeploy -u admin -p password -l http://portainer.local -n mystack
```
### Stack environment variables
There can be set environment variables for each stack, be it a new deployment or an update. For example:
```bash
touch .env
echo "MYSQL_ROOT_PASSWORD=agoodpassword" >> .env
echo "ALLOWED_HOSTS=*" >> .env
./psu -a deploy -u admin -p password -l http://portainer.local -n django-stack -c /path/to/docker-compose.yml -g env_vars
```
Stack environment variables can be enabled through [ENVIRONMENT_VARIABLES_FILE envvar](#with-envvars) or [-g flag](#with-flags).
### Verbose mode
In verbose mode the script prints execution steps.

115
psu
View File

@ -66,26 +66,27 @@ main() {
exit 1
}
##########################
# Set globals #
# Globals: #
# ACTION #
# PORTAINER_USER #
# PORTAINER_PASSWORD #
# PORTAINER_URL #
# PORTAINER_STACK_NAME #
# DOCKER_COMPOSE_FILE #
# PORTAINER_ENDPOINT #
# PORTAINER_PRUNE #
# HTTPIE_VERIFY_SSL #
# VERBOSE_MODE #
# DEBUG_MODE #
# STRICT_MODE #
# Arguments: #
# None #
# Returns: #
# None #
##########################
################################
# Set globals #
# Globals: #
# ACTION #
# PORTAINER_USER #
# PORTAINER_PASSWORD #
# PORTAINER_URL #
# PORTAINER_STACK_NAME #
# DOCKER_COMPOSE_FILE #
# ENVIRONMENT_VARIABLES_FILE #
# PORTAINER_ENDPOINT #
# PORTAINER_PRUNE #
# HTTPIE_VERIFY_SSL #
# VERBOSE_MODE #
# DEBUG_MODE #
# STRICT_MODE #
# Arguments: #
# None #
# Returns: #
# None #
################################
set_globals() {
# Set arguments through envvars
ACTION=${ACTION}
@ -94,6 +95,7 @@ set_globals() {
PORTAINER_URL=${PORTAINER_URL}
PORTAINER_STACK_NAME=${PORTAINER_STACK_NAME}
DOCKER_COMPOSE_FILE=${DOCKER_COMPOSE_FILE}
ENVIRONMENT_VARIABLES_FILE=${ENVIRONMENT_VARIABLES_FILE}
PORTAINER_ENDPOINT=${PORTAINER_ENDPOINT:-"1"}
PORTAINER_PRUNE=${PORTAINER_PRUNE:-"false"}
HTTPIE_VERIFY_SSL=${HTTPIE_VERIFY_SSL:-"yes"}
@ -102,7 +104,7 @@ set_globals() {
STRICT_MODE=${STRICT_MODE:-"false"}
# Set arguments through flags (overwrite envvars)
while getopts a:u:p:l:n:c:e:rsvdt option; do
while getopts a:u:p:l:n:c:e:g:rsvdt option; do
case "${option}" in
a) ACTION=${OPTARG} ;;
u) PORTAINER_USER=${OPTARG} ;;
@ -111,6 +113,7 @@ set_globals() {
n) PORTAINER_STACK_NAME=${OPTARG} ;;
c) DOCKER_COMPOSE_FILE=${OPTARG} ;;
e) PORTAINER_ENDPOINT=${OPTARG} ;;
g) ENVIRONMENT_VARIABLES_FILE=${OPTARG} ;;
r) PORTAINER_PRUNE="true" ;;
s) HTTPIE_VERIFY_SSL="no" ;;
v) VERBOSE_MODE="true" ;;
@ -130,6 +133,7 @@ set_globals() {
echo_debug "PORTAINER_URL -> $PORTAINER_URL"
echo_debug "PORTAINER_STACK_NAME -> $PORTAINER_STACK_NAME"
echo_debug "DOCKER_COMPOSE_FILE -> $DOCKER_COMPOSE_FILE"
echo_debug "ENVIRONMENT_VARIABLES_FILE -> $ENVIRONMENT_VARIABLES_FILE"
echo_debug "PORTAINER_ENDPOINT -> $PORTAINER_ENDPOINT"
echo_debug "PORTAINER_PRUNE -> $PORTAINER_PRUNE"
echo_debug "HTTPIE_VERIFY_SSL -> $HTTPIE_VERIFY_SSL"
@ -145,6 +149,10 @@ set_globals() {
check_argument "$PORTAINER_STACK_NAME" "portainer stack name" "PORTAINER_STACK_NAME" "n"
if [ $ACTION == "deploy" ]; then
check_argument "$DOCKER_COMPOSE_FILE" "docker compose file" "DOCKER_COMPOSE_FILE" "c"
if [ -n "$ENVIRONMENT_VARIABLES_FILE" ] && [[ ! -f "$ENVIRONMENT_VARIABLES_FILE" ]]; then
echo_error "Error: File path \"$ENVIRONMENT_VARIABLES_FILE\" not found for \"ENVIRONMENT_VARIABLES_FILE\" environment variable or the \"-g\" flag."
exit 1
fi
fi
}
@ -254,21 +262,22 @@ echo_debug() {
fi
}
##########################
# Create/update a stack #
# Globals: #
# STACK #
# DOCKER_COMPOSE_FILE #
# PORTAINER_STACK_NAME #
# PORTAINER_URL #
# HTTPIE_VERIFY_SSL #
# PORTAINER_ENDPOINT #
# AUTH_TOKEN #
# Arguments: #
# None #
# Returns: #
# None #
##########################
################################
# Create/update a stack #
# Globals: #
# STACK #
# DOCKER_COMPOSE_FILE #
# PORTAINER_STACK_NAME #
# PORTAINER_URL #
# ENVIRONMENT_VARIABLES_FILE #
# HTTPIE_VERIFY_SSL #
# PORTAINER_ENDPOINT #
# AUTH_TOKEN #
# Arguments: #
# None #
# Returns: #
# None #
################################
deploy() {
# Read docker-compose file content
local docker_compose_file_content
@ -310,8 +319,13 @@ deploy() {
echo_verbose "Swarm cluster not found."
echo_verbose "Preparing stack JSON..."
local stack_envvars
stack_envvars="[]"
if [ -n "$ENVIRONMENT_VARIABLES_FILE" ]; then
stack_envvars=$(env_file_to_json)
fi
local data_prefix="{\"Name\":\"$PORTAINER_STACK_NAME\",\"StackFileContent\":\""
local data_suffix="\"}"
local data_suffix="\",\"Env\":"$stack_envvars"}"
echo "$data_prefix$docker_compose_file_content$data_suffix" > json.tmp
echo_debug "Stack JSON -> $(echo $data_prefix$docker_compose_file_content$data_suffix | jq -C .)"
@ -335,8 +349,13 @@ deploy() {
echo_verbose "Swarm cluster found."
echo_verbose "Preparing stack JSON..."
local stack_envvars
stack_envvars="[]"
if [ -n "$ENVIRONMENT_VARIABLES_FILE" ]; then
stack_envvars=$(env_file_to_json)
fi
local data_prefix="{\"Name\":\"$PORTAINER_STACK_NAME\",\"SwarmID\":\"$swarm_id\",\"StackFileContent\":\""
local data_suffix="\"}"
local data_suffix="\",\"Env\":"$stack_envvars"}"
echo "$data_prefix$docker_compose_file_content$data_suffix" > json.tmp
echo_debug "Stack JSON -> $(echo $data_prefix$docker_compose_file_content$data_suffix | jq -C .)"
@ -370,7 +389,12 @@ deploy() {
local stack_id
stack_id="$(echo "$STACK" | jq -j ".Id")"
local stack_envvars
stack_envvars="$(echo -n "$STACK"| jq ".Env" -jc)"
stack_envvars="$(echo -n "$STACK" | jq ".Env" -jc)"
if [ -n "$ENVIRONMENT_VARIABLES_FILE" ]; then
local new_stack_envvars
new_stack_envvars=$(env_file_to_json)
stack_envvars="$(echo -n "${new_stack_envvars}${stack_envvars}" | jq -sjc 'add | unique_by(.name)')"
fi
local data_prefix="{\"Id\":\"$stack_id\",\"StackFileContent\":\""
local data_suffix="\",\"Env\":"$stack_envvars",\"Prune\":$PORTAINER_PRUNE}"
echo "$data_prefix$docker_compose_file_content$data_suffix" > json.tmp
@ -436,4 +460,17 @@ undeploy() {
echo_debug "Delete action response -> $(echo $delete | jq -C .)"
}
###################################################
# Convert environment variables from file to JSON #
# Globals: #
# ENVIRONMENT_VARIABLES_FILE #
# Arguments: #
# None #
# Returns: #
# JSON string #
###################################################
env_file_to_json() {
echo "$(env -i $(cat $ENVIRONMENT_VARIABLES_FILE) jq -n 'env | to_entries | map({name: .key, value: .value})')"
}
main "$@"