From 07e7988cdf1e0422ad5314cbc1aad2783c2bef79 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Wed, 30 Dec 2020 05:48:29 -0500 Subject: [PATCH] feat: add sigil templating to CHECKS files This enables general templating capabilities, in addition to environment variable access. Closes #3974. --- docs/deployment/zero-downtime-deploys.md | 32 +++++++++++++++++++++ plugins/scheduler-docker-local/check-deploy | 9 ++++++ tests/apps/nodejs-express/web.js | 4 +++ tests/unit/checks.bats | 13 +++++++++ tests/unit/test_helper.bash | 14 +++++++++ 5 files changed, 72 insertions(+) diff --git a/docs/deployment/zero-downtime-deploys.md b/docs/deployment/zero-downtime-deploys.md index 88e2b296a..343c4eb9f 100644 --- a/docs/deployment/zero-downtime-deploys.md +++ b/docs/deployment/zero-downtime-deploys.md @@ -157,6 +157,38 @@ https://static.dokku.me/logo.png While a full URL may be used in order to invoke checks, if you are using relative URLs, the port *must* be omitted. +> Changed as of 0.22.5 + +Please note that dollar sign bracket characters (`{` and `}`) must be escaped when used within a `CHECKS` file. Escaping follows golang template rules. The proper way to do this is via one of the following methods: + +``` +# escaping the `{` character +# using double-quotes +{{"{"}} + +# using raw string constants +{{`{`}} + +# escaping the `}` character +# using double-quotes +{{"}"}} + +# using raw string constants +{{`}`}} +``` + +### Templating Checks Files + +> New as of 0.22.5 + +An app's `CHECKS` file is sent through a single pass of the [`sigil`](https://github.com/gliderlabs/sigil/) templating tool. This enables usage of Golang templating within application `CHECKS` files. In addition to general templating access, access to app environment variables is also allowed via the `var` function: + +``` +{{ var "SOME_ENV_VAR" }} +``` + +This may be useful if certain zero-downtime checks require access to an app-specific value, such as a domain name. + ### Check settings The default behavior is to wait for `5` seconds before running the checks, to timeout the checks after `30` seconds, and to attempt the checks `5` times. If the checks fail `5` times, the deployment is considered failed and the old container will continue serving traffic. diff --git a/plugins/scheduler-docker-local/check-deploy b/plugins/scheduler-docker-local/check-deploy index e88995891..de7f49a9d 100755 --- a/plugins/scheduler-docker-local/check-deploy +++ b/plugins/scheduler-docker-local/check-deploy @@ -115,6 +115,15 @@ trigger-scheduler-docker-local-check-deploy() { dokku_log_verbose "Default container check successful!" && exit 0 fi + local NEW_CHECKS_FILENAME=${CHECK_DEPLOY_TMP_WORK_DIR}/$(mktemp dokku-${FUNCNAME[0]}-CHECKS.XXXX) + template_checks() { + eval "$(config_export app "$APP" --merged)" + sigil -f "$CHECKS_FILENAME" | cat -s >"$NEW_CHECKS_FILENAME" + } + + template_checks + CHECKS_FILENAME="$NEW_CHECKS_FILENAME" + # Reads name/value pairs, sets the WAIT and TIMEOUT variables exec <"$CHECKS_FILENAME" local line diff --git a/tests/apps/nodejs-express/web.js b/tests/apps/nodejs-express/web.js index d1d386c60..e08a9c530 100644 --- a/tests/apps/nodejs-express/web.js +++ b/tests/apps/nodejs-express/web.js @@ -6,6 +6,10 @@ app.get('/', function(request, response) { response.send('nodejs/express'); }); +app.get('/healthcheck', function(request, response) { + response.send(process.env.HEALTHCHECK_ENDPOINT); +}); + var port = process.env.PORT || 5000; app.listen(port, function() { console.log("Listening on " + port); diff --git a/tests/unit/checks.bats b/tests/unit/checks.bats index d0ae98d40..e337dad56 100644 --- a/tests/unit/checks.bats +++ b/tests/unit/checks.bats @@ -249,3 +249,16 @@ teardown() { echo "status: $status" assert_success } + +@test "(checks) checks:templated" { + run /bin/bash -c "dokku config:set $TEST_APP HEALTHCHECK_ENDPOINT=/healthcheck" + echo "output: $output" + echo "status: $status" + assert_success + + run deploy_app nodejs-express dokku@dokku.me:$TEST_APP template_checks_file + echo "output: $output" + echo "status: $status" + assert_output_contains "/healthcheck" 2 + assert_success +} diff --git a/tests/unit/test_helper.bash b/tests/unit/test_helper.bash index 379bb184f..cebb96fce 100644 --- a/tests/unit/test_helper.bash +++ b/tests/unit/test_helper.bash @@ -484,6 +484,20 @@ some lame nginx config EOF } +template_checks_file() { + local APP="$1" + local APP_REPO_DIR="$2" + [[ -z "$APP" ]] && local APP="$TEST_APP" + echo "injecting templated CHECKS file -> $APP_REPO_DIR/CHECKS" + cat <"$APP_REPO_DIR/CHECKS" +WAIT=2 # wait 2 seconds +TIMEOUT=5 # set timeout to 5 seconds +ATTEMPTS=2 # try 2 times + +{{ var "HEALTHCHECK_ENDPOINT" }} {{ var "HEALTHCHECK_ENDPOINT" }} +EOF +} + add_release_command() { local APP="$1" local APP_REPO_DIR="$2"