From 3a885e5e475ae7673312eb2458d0292b7c6050a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Carlos=20Mej=C3=ADas=20Rodr=C3=ADguez?= Date: Mon, 19 Nov 2018 14:16:44 -0500 Subject: [PATCH] first commit --- Dockerfile | 24 ++++++++++ deploy.sh | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++ undeploy.sh | 59 +++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 Dockerfile create mode 100755 deploy.sh create mode 100755 undeploy.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d3b9952 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM alpine + +ENV LANG="en_US.UTF-8" \ + LC_ALL="C.UTF-8" \ + LANGUAGE="en_US.UTF-8" \ + TERM="xterm" \ + PORTAINER_USER="root" \ + PORTAINER_PASSWORD="password" \ + PORTAINER_URL="http://example.com:9000" \ + PORTAINER_PRUNE="false" \ + PORTAINER_ENDPOINT="1" + +RUN apk --update add \ + bash \ + ca-certificates \ + httpie \ + jq \ + && \ + rm -rf /tmp/src && \ + rm -rf /var/cache/apk/* + +WORKDIR /scripts + +COPY *.sh ./ diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..930d612 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,133 @@ +#!/usr/bin/env bash + +PORTAINER_USER=${PORTAINER_USER:-"user"} +PORTAINER_PASSWORD=${PORTAINER_PASSWORD:-"password"} +PORTAINER_URL=${PORTAINER_URL:-"https://portainer.example.com"} +PORTAINER_PRUNE=${PORTAINER_PRUNE:-"false"} +PORTAINER_ENDPOINT=${PORTAINER_ENDPOINT:-"1"} + +if [ -z ${1+x} ]; then + echo "Error: Parameter #1 missing (stack name)" + exit 1 +fi +STACK_NAME="$1" + +if [ -z ${2+x} ]; then + echo "Error: Parameter #2 missing (path to yaml)" + exit 1 +fi +STACK_YAML_PATH="$2" + +STACK_YAML_CONTENT=$(cat "$STACK_YAML_PATH") + +# Escape carriage returns +STACK_YAML_CONTENT="${STACK_YAML_CONTENT//$'\r'/''}" + +# Escape double quotes +STACK_YAML_CONTENT="${STACK_YAML_CONTENT//$'"'/'\"'}" + +# Escape newlines +STACK_YAML_CONTENT="${STACK_YAML_CONTENT//$'\n'/'\n'}" + +echo "Getting auth token..." +AUTH_TOKEN=$(http \ + --ignore-stdin \ + --verify=no \ + $PORTAINER_URL/api/auth \ + username=$PORTAINER_USER \ + password=$PORTAINER_PASSWORD \ + | jq -r .jwt) + +if [ -z "$AUTH_TOKEN" ]; then + echo "Error: Authentication error." + exit 1 +fi +echo "Done" + +echo "Getting stack $STACK_NAME..." +STACKS=$(http \ + --ignore-stdin \ + --verify=no \ + "$PORTAINER_URL/api/stacks" \ + "Authorization: Bearer $AUTH_TOKEN") + +STACK=$(echo "$STACKS" \ + | jq --arg STACK_NAME "$STACK_NAME" -jc '.[] | select(.Name == $STACK_NAME)') + +if [ -z "$STACK" ]; then + echo "Result: Stack $STACK_NAME not found." + + echo "Getting swarm cluster (if any)..." + SWARM_ID=$(http \ + --ignore-stdin \ + --verify=no \ + "$PORTAINER_URL/api/endpoints/$PORTAINER_ENDPOINT/docker/info" \ + "Authorization: Bearer $AUTH_TOKEN" \ + | jq -r ".Swarm.Cluster.ID // empty") + + echo "Creating stack $STACK_NAME..." + if [ -z "$SWARM_ID" ];then + DATA_PREFIX="{\"Name\":\"$STACK_NAME\",\"StackFileContent\":\"" + DATA_SUFFIX="\"}" + echo "$DATA_PREFIX$STACK_YAML_CONTENT$DATA_SUFFIX" > json.tmp + + CREATE=$(http \ + --ignore-stdin \ + --verify=no \ + --timeout=300 \ + "$PORTAINER_URL/api/stacks" \ + "Authorization: Bearer $AUTH_TOKEN" \ + type==2 \ + method==string \ + endpointId==$PORTAINER_ENDPOINT \ + @json.tmp) + else + DATA_PREFIX="{\"Name\":\"$STACK_NAME\",\"SwarmID\":\"$SWARM_ID\",\"StackFileContent\":\"" + DATA_SUFFIX="\"}" + echo "$DATA_PREFIX$STACK_YAML_CONTENT$DATA_SUFFIX" > json.tmp + + CREATE=$(http \ + --ignore-stdin \ + --verify=no \ + --timeout=300 \ + "$PORTAINER_URL/api/stacks" \ + "Authorization: Bearer $AUTH_TOKEN" \ + type==1 \ + method==string \ + endpointId==$PORTAINER_ENDPOINT \ + @json.tmp) + fi + + rm json.tmp + + if [ -z ${CREATE+x} ]; then + echo "Error: stack $STACK_NAME not created" + exit 1 + fi +else + echo "Result: Stack $STACK_NAME found." + + STACK_ID="$(echo "$STACK" | jq -j ".Id")" + STACK_ENV_VARS="$(echo -n "$STACK"| jq ".Env" -jc)" + DATA_PREFIX="{\"Id\":\"$STACK_ID\",\"StackFileContent\":\"" + DATA_SUFFIX="\",\"Env\":"$STACK_ENV_VARS",\"Prune\":$PORTAINER_PRUNE}" + echo "$DATA_PREFIX$STACK_YAML_CONTENT$DATA_SUFFIX" > json.tmp + + echo "Updating stack $STACK_NAME..." + UPDATE=$(http \ + --ignore-stdin \ + --verify=no \ + --timeout=300 \ + PUT "$PORTAINER_URL/api/stacks/$STACK_ID" \ + "Authorization: Bearer $AUTH_TOKEN" \ + endpointId==$PORTAINER_ENDPOINT \ + @json.tmp) + + rm json.tmp + + if [ -z ${UPDATE+x} ]; then + echo "Error: stack $STACK_NAME not updated" + exit 1 + fi +fi +echo "Done" diff --git a/undeploy.sh b/undeploy.sh new file mode 100755 index 0000000..918427f --- /dev/null +++ b/undeploy.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash + +PORTAINER_USER=${PORTAINER_USER:-"user"} +PORTAINER_PASSWORD=${PORTAINER_PASSWORD:-"password"} +PORTAINER_URL=${PORTAINER_URL:-"https://portainer.example.com"} +PORTAINER_PRUNE=${PORTAINER_PRUNE:-"false"} +PORTAINER_ENDPOINT=${PORTAINER_ENDPOINT:-"1"} + +if [ -z ${1+x} ]; then + echo "Error: Parameter #1 missing (stack name)" + exit 1 +fi +STACK_NAME="$1" + +echo "Getting auth token..." +AUTH_TOKEN=$(http \ + --ignore-stdin \ + --verify=no \ + $PORTAINER_URL/api/auth \ + username=$PORTAINER_USER \ + password=$PORTAINER_PASSWORD \ + | jq -r .jwt) + +if [ -z "$AUTH_TOKEN" ]; then + echo "Error: Authentication error." + exit 1 +fi +echo "Done" + +echo "Getting stack $STACK_NAME..." +STACKS=$(http \ + --ignore-stdin \ + --verify=no \ + "$PORTAINER_URL/api/stacks" \ + "Authorization: Bearer $AUTH_TOKEN") + +STACK=$(echo "$STACKS" \ + | jq --arg STACK_NAME "$STACK_NAME" -jc '.[] | select(.Name == $STACK_NAME)') + +if [ -z "$STACK" ]; then + echo "Result: Stack $STACK_NAME not found." + exit 1 +fi +echo "Result: Stack $STACK_NAME found." + +STACK_ID="$(echo "$STACK" | jq -j ".Id")" + +echo "Deleting stack $STACK_NAME..." +DELETE=$(http \ + --ignore-stdin \ + --verify=no \ + DELETE "$PORTAINER_URL/api/stacks/$STACK_ID" \ + "Authorization: Bearer $AUTH_TOKEN") + +if [ -z ${DELETE+x} ]; then + echo "Error: stack $STACK_NAME not deleted" + exit 1 +fi +echo "Done"