From 43148c5485b5b83cc858abb39f2033f579d2030c Mon Sep 17 00:00:00 2001 From: Timo Furrer <tfurrer@gitlab.com> Date: Mon, 27 May 2024 14:13:52 +0200 Subject: [PATCH] Auto URL-encode state name This change set implements auto url-encoding for the state name when it's used as a URL. This allows to seamlessly define a state name like `production/aws`. The feature is behind a feature flag that can be disabled. You can define the `TF_FF_AUTO_URLENCODE_STATE_NAME` variable as `false` in your pipeline configuration to disable this behavior. Changelog: added --- src/gitlab-tofu.sh | 17 +++++++++++-- tests/unit.gitlab-ci.yml | 55 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/gitlab-tofu.sh b/src/gitlab-tofu.sh index aa62e13..d168c58 100644 --- a/src/gitlab-tofu.sh +++ b/src/gitlab-tofu.sh @@ -8,6 +8,14 @@ if [ "${DEBUG_OUTPUT}" = "true" ]; then set -x fi +# Feature Flags +# ============= +# Below are a bunch of variables that we use as "feature flags". + +if [ -z "$TF_FF_AUTO_URLENCODE_STATE_NAME" ]; then + TF_FF_AUTO_URLENCODE_STATE_NAME=true +fi + # Helpers # Evaluate if this script is being sourced or executed directly. @@ -45,8 +53,13 @@ if [ -z "${TF_PASSWORD}" ]; then fi # If TF_ADDRESS is unset but TF_STATE_NAME is provided, then default to GitLab backend in current project -if [ -n "${TF_STATE_NAME}" ]; then - TF_ADDRESS="${TF_ADDRESS:-${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}}" +if [ -n "${TF_STATE_NAME}" ] && [ -z "${TF_ADDRESS}" ]; then + # auto url-encode TF_STATE_NAME when FF is enabled + if $TF_FF_AUTO_URLENCODE_STATE_NAME; then + TF_STATE_NAME="$(jq -rn --arg x "${TF_STATE_NAME}" '$x|@uri')" + fi + + TF_ADDRESS="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME}" fi # If TF_ROOT is set then use the -chdir option diff --git a/tests/unit.gitlab-ci.yml b/tests/unit.gitlab-ci.yml index 7490a01..c51ee83 100644 --- a/tests/unit.gitlab-ci.yml +++ b/tests/unit.gitlab-ci.yml @@ -160,7 +160,7 @@ gitlab-tofu-init-with-prepared-registry-token: - | cat <<'EOF' > test.sh set -x - # NOTE: as part of the tst fixture, we need to overwrite the CI_SERVER_HOST, + # NOTE: as part of the test fixture, we need to overwrite the CI_SERVER_HOST, # so that this test also properly works on GitLab self-managed. export CI_SERVER_HOST=gitlab.example.com export TF_TOKEN_gitlab_example_com=mysecrettoken @@ -189,7 +189,7 @@ gitlab-tofu-init-without-prepared-registry-token: - | cat <<'EOF' > test.sh set -x - # NOTE: as part of the tst fixture, we need to overwrite the CI_SERVER_HOST, + # NOTE: as part of the test fixture, we need to overwrite the CI_SERVER_HOST, # so that this test also properly works on GitLab self-managed. export CI_SERVER_HOST=gitlab.example.com . $(which gitlab-tofu) @@ -340,3 +340,54 @@ gitlab-tofu-no-wrapper: - cat /tmp/output.txt - test $FAILED = true - 'grep "Error: Backend initialization required, please run \"tofu init\"" /tmp/output.txt' + +gitlab-tofu-state-name-auto-urlencode: + extends: + - .gitlab-tofu-test + stage: test + variables: + OPENTOFU_VERSION: $LATEST_OPENTOFU_VERSION + script: + - apk add --update $PKG + - | + cat <<'EOF' > test.sh + set -x + export TF_STATE_NAME=production/europe + . $(which gitlab-tofu) + test "$TF_STATE_NAME" = "production%2Feurope" + EOF + - $SHELL test.sh + parallel: + matrix: + - SHELL: "bash" + PKG: "bash" + - SHELL: "zsh" + PKG: "zsh" + - SHELL: "ksh" + PKG: "loksh" + +gitlab-tofu-state-name-auto-urlencode-ff-disabled: + extends: + - .gitlab-tofu-test + stage: test + variables: + OPENTOFU_VERSION: $LATEST_OPENTOFU_VERSION + script: + - apk add --update $PKG + - | + cat <<'EOF' > test.sh + set -x + export TF_FF_AUTO_URLENCODE_STATE_NAME=false + export TF_STATE_NAME=production/europe + . $(which gitlab-tofu) + test "$TF_STATE_NAME" = "production/europe" + EOF + - $SHELL test.sh + parallel: + matrix: + - SHELL: "bash" + PKG: "bash" + - SHELL: "zsh" + PKG: "zsh" + - SHELL: "ksh" + PKG: "loksh" -- GitLab