Last active
June 29, 2018 19:11
-
-
Save BluSyn/71a2040d610e06bf8ee06a9480d17fd3 to your computer and use it in GitHub Desktop.
Update docker swarm secrets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
## Update specific secret by name | |
## (Seriously, this is annoying and should be baked in docker stack deploy) | |
## Call with env + secret file path, exactly as defined in docker-compose.yml | |
## Eg: ./update-secret.sh master ./secrets/worker/worker.json | |
## Dependencies: yq and jq | |
## yq - pip install yq | |
## jq - pacman -Sy jq | |
ENV=$1 | |
SFILE=$2 | |
if [[ -z $ENV || -z $SFILE ]]; then | |
echo "Must specify deployment environment and secret file." | |
echo "Example: update-secret.sh master ./secrets/worker/worker.conf" | |
exit | |
fi | |
COMPOSE="./docker-compose.yml" | |
# Connects local docker to swarm | |
# Replace with "docker-machine env <SWARM>" in most setups | |
source ~/.deploy_profile | |
SECRET=`yq 'path(.secrets[] | select(.file == "'$SFILE'"))[1]' $COMPOSE | tr -d '"'` | |
SERVICES=`docker service ls --format '{{.Name}}'` | |
LIST=() | |
TARGET="" | |
if [ -z $SECRET ]; then | |
echo "Could not find secret using that file" | |
exit | |
fi | |
SECRETNAME="${ENV}_${SECRET}" | |
echo "Found secret: $SECRET" | |
echo "Probing service list for secret..." | |
for SERVICE in ${SERVICES[@]} | |
do | |
SPEC=`docker service inspect $SERVICE | jq '.[].Spec.TaskTemplate.ContainerSpec.Secrets[]? | select(.SecretName | startswith("'$SECRETNAME'"))'` | |
TARGET=`echo "$SPEC" | jq '.File.Name' | head -n1 | tr -d '"'` | |
if [[ $TARGET ]]; then | |
echo "Found: $SERVICE" | |
LIST+=("$SERVICE:$TARGET") | |
# SecretName may have been changed due to previous update | |
SECRETNAME=`echo "$SPEC" | jq '.SecretName' | head -n1 | tr -d '"'` | |
fi | |
done | |
if [ -z $LIST ]; then | |
echo "Could not find any services using this secret. Nothing to do." | |
exit | |
fi | |
# Randomly generate a secret name for duplicate secret | |
NEWSECRET="${ENV}_${SECRET}_${RANDOM}" | |
echo "Creating duplicate secret... ($NEWSECRET)" | |
docker secret create $NEWSECRET $SFILE | |
for INSTANCE in ${LIST[@]} | |
do | |
readarray -td ':' SPLIT <<< "$INSTANCE" | |
declare SPLIT | |
echo "Updating service ${SPLIT[0]}" | |
docker service update --update-parallelism 0 --secret-rm $SECRETNAME --secret-add source=$NEWSECRET,target=${SPLIT[1]} ${SPLIT[0]} | |
done | |
# Must delete old secret or future calls to "docker stack deploy" will fail | |
docker secret rm $SECRETNAME |
Agreed this does make a lot of assumptions based around my current setup. Could easily be made more generic for other setups as you mentioned. The idea was to be able to run the cmd with as few params as possible so updates could be done with little effort.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for the contribution. I haven't tried this yet, but some thoughts:
This seems to make some assumptions (but which aren't always true):
docker-compose.yml
.However, to work around 1 & 2, I supposed one could:
Also, consider tweaking the example command so that the argument meanings are more self-evident. (My example, above, attempts to do so.)