Skip to content

Commit

Permalink
Merge pull request #364 from dflook/ephemeral
Browse files Browse the repository at this point in the history
Add support for ephemeral variables in terraform >= 1.10.0
  • Loading branch information
dflook authored Jan 14, 2025
2 parents 4d4081d + ab290b0 commit 506e008
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 20 deletions.
97 changes: 97 additions & 0 deletions .github/workflows/test-apply.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1430,3 +1430,100 @@ jobs:
uses: ./terraform-apply
with:
path: tests/workflows/test-apply/outputs

ephemeral:
runs-on: ubuntu-24.04
name: Apply a plan with ephemeral variables
permissions:
contents: read
pull-requests: write
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false

- name: Plan using default ephemeral value
uses: ./terraform-plan
with:
label: test-apply ephemeral
path: tests/workflows/test-apply/ephemeral

- name: Apply using default ephemeral value
uses: ./terraform-apply
id: apply
with:
label: test-apply ephemeral
path: tests/workflows/test-apply/ephemeral

- name: Verify outputs
env:
OUTPUT_STRING: ${{ steps.apply.outputs.v }}
run: |
if [[ "$OUTPUT_STRING" != "non-ephemeral" ]]; then
echo "::error:: output s not set correctly"
exit 1
fi
##

- name: Plan using explicit ephemeral value
uses: ./terraform-plan
with:
label: test-apply ephemeral 2
path: tests/workflows/test-apply/ephemeral
variables: |
region = "eu-west-1"
mv = "hello"
- name: Apply using explicit ephemeral value
uses: ./terraform-apply
id: apply2
with:
label: test-apply ephemeral 2
path: tests/workflows/test-apply/ephemeral
variables: |
region = "eu-west-1"
mv = "hello"
- name: Verify outputs
env:
OUTPUT_STRING: ${{ steps.apply2.outputs.v }}
run: |
if [[ "$OUTPUT_STRING" != "hello" ]]; then
echo "::error:: output s not set correctly"
exit 1
fi
##

- name: Plan using explicit non-ephemeral value
uses: ./terraform-plan
with:
label: test-apply ephemeral 3
path: tests/workflows/test-apply/ephemeral
variables: |
region = "eu-west-2"
mv = "goodbye"
- name: Apply using mismatched explicit non-ephemeral value
uses: ./terraform-apply
continue-on-error: true
id: apply3
with:
label: test-apply ephemeral 3
path: tests/workflows/test-apply/ephemeral
variables: |
region = "eu-west-2"
mv = "mismatch"
- name: Check failed to apply
env:
OUTCOME: ${{ steps.apply3.outcome }}
run: |
if [[ "$OUTCOME" != "failure" ]]; then
echo "Apply did not fail correctly"
exit 1
fi
34 changes: 25 additions & 9 deletions image/actions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ function set-common-plan-args() {
}

function set-variable-args() {
VARIABLE_ARGS=""

if [[ -n "$INPUT_VAR_FILE" ]]; then
for file in $(echo "$INPUT_VAR_FILE" | tr ',' '\n'); do

Expand All @@ -368,32 +370,46 @@ function set-variable-args() {
exit 1
fi

PLAN_ARGS="$PLAN_ARGS -var-file=$(relative_to "$INPUT_PATH" "$file")"
VARIABLE_ARGS="$VARIABLE_ARGS -var-file=$(relative_to "$INPUT_PATH" "$file")"
done
fi

if [[ -n "$INPUT_VARIABLES" ]]; then
echo "$INPUT_VARIABLES" >"$STEP_TMP_DIR/variables.tfvars"
PLAN_ARGS="$PLAN_ARGS -var-file=$STEP_TMP_DIR/variables.tfvars"
VARIABLE_ARGS="$VARIABLE_ARGS -var-file=$STEP_TMP_DIR/variables.tfvars"
fi
}

function set-plan-args() {
set-common-plan-args
function set-deprecated-var-args() {
DEPRECATED_VAR_ARGS=""

if [[ -n "$INPUT_VAR" ]]; then
for var in $(echo "$INPUT_VAR" | tr ',' '\n'); do
PLAN_ARGS="$PLAN_ARGS -var $var"
DEPRECATED_VAR_ARGS="$DEPRECATED_VAR_ARGS -var $var"
done
fi
}

function masked-deprecated-vars() {
if [[ -n "$DEPRECATED_VAR_ARGS" ]]; then
echo "-var <masked>"
else
echo ""
fi
}

function set-plan-args() {
set-common-plan-args
set-deprecated-var-args
set-variable-args

export PLAN_ARGS
}

function set-remote-plan-args() {
set-common-plan-args
VARIABLE_ARGS=""
DEPRECATED_VAR_ARGS=""

local AUTO_TFVARS_COUNTER=0

Expand Down Expand Up @@ -466,11 +482,11 @@ function plan() {
fi

# shellcheck disable=SC2086
debug_log $TOOL_COMMAND_NAME plan -input=false -no-color -detailed-exitcode -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT_ARG '$PLAN_ARGS' # don't expand PLAN_ARGS
debug_log $TOOL_COMMAND_NAME plan -input=false -no-color -detailed-exitcode -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT_ARG $PLAN_ARGS "$(masked-deprecated-vars)" $VARIABLE_ARGS

set +e
# shellcheck disable=SC2086
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME plan -input=false -no-color -detailed-exitcode -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT_ARG $PLAN_ARGS) \
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME plan -input=false -no-color -detailed-exitcode -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT_ARG $PLAN_ARGS $DEPRECATED_VAR_ARGS $VARIABLE_ARGS ) \
2>"$STEP_TMP_DIR/terraform_plan.stderr" \
| $TFMASK \
| tee /dev/fd/3 "$STEP_TMP_DIR/terraform_plan.stdout" \
Expand All @@ -494,11 +510,11 @@ function plan() {

function destroy() {
# shellcheck disable=SC2086
debug_log $TOOL_COMMAND_NAME destroy -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS
debug_log $TOOL_COMMAND_NAME destroy -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS "$(masked-deprecated-vars)" $VARIABLE_ARGS

set +e
# shellcheck disable=SC2086
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME destroy -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS) \
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME destroy -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS $DEPRECATED_VAR_ARGS $VARIABLE_ARGS) \
2>"$STEP_TMP_DIR/terraform_destroy.stderr" \
| tee /dev/fd/3 \
>"$STEP_TMP_DIR/terraform_destroy.stdout"
Expand Down
22 changes: 16 additions & 6 deletions image/entrypoints/apply.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,33 @@ function apply() {
set +e
if [[ -n "$PLAN_OUT" ]]; then

# With Terrraform >= 1.10 Ephemeral variables must be specified again in the apply command.
# Non-ephemeral variables may be specified again, but may not be different from the plan.
# Terraform < 1.1.0 must not specify any variables when applying a saved plan.

SAVED_PLAN_VARIABLES=""
if [[ "$TOOL_PRODUCT_NAME" == "Terraform" ]] && test-terraform-version ">=" "1.10.0"; then
SAVED_PLAN_VARIABLES="$VARIABLE_ARGS"
fi

# shellcheck disable=SC2086
debug_log $TOOL_COMMAND_NAME apply -input=false -no-color -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT
debug_log $TOOL_COMMAND_NAME apply -input=false -no-color -lock-timeout=300s $PARALLEL_ARG $SAVED_PLAN_VARIABLES $PLAN_OUT
# shellcheck disable=SC2086
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME apply -input=false -no-color -lock-timeout=300s $PARALLEL_ARG $PLAN_OUT) \
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME apply -input=false -no-color -lock-timeout=300s $PARALLEL_ARG $SAVED_PLAN_VARIABLES $PLAN_OUT) \
2>"$STEP_TMP_DIR/terraform_apply.stderr" \
| $TFMASK \
| tee "$STEP_TMP_DIR/terraform_apply.stdout"
APPLY_EXIT=${PIPESTATUS[0]}
>&2 cat "$STEP_TMP_DIR/terraform_apply.stderr"

else
# There is no plan file to apply, since the remote backend can't produce them.
# Instead we need to do an auto approved apply using the arguments we would normally use for the plan

# shellcheck disable=SC2086,SC2016
debug_log $TOOL_COMMAND_NAME apply -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS "$(masked-deprecated-vars)" $VARIABLE_ARGS
# shellcheck disable=SC2086
debug_log $TOOL_COMMAND_NAME apply -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG '$PLAN_ARGS' # don't expand plan args
# shellcheck disable=SC2086
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME apply -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS) \
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME apply -input=false -no-color -auto-approve -lock-timeout=300s $PARALLEL_ARG $PLAN_ARGS $DEPRECATED_VAR_ARGS $VARIABLE_ARGS) \
2>"$STEP_TMP_DIR/terraform_apply.stderr" \
| $TFMASK \
| tee "$STEP_TMP_DIR/terraform_apply.stdout"
Expand Down Expand Up @@ -95,7 +105,7 @@ if [[ "$INPUT_PLAN_PATH" != "" ]]; then
exit 1
fi

PLAN_OUT=$(realpath $INPUT_PLAN_PATH)
PLAN_OUT=$(realpath "$INPUT_PLAN_PATH")
PLAN_EXIT=2
else
plan
Expand Down
5 changes: 2 additions & 3 deletions image/entrypoints/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ function set-test-args() {

function test() {

debug_log $TOOL_COMMAND_NAME test -no-color $TEST_ARGS '$PLAN_ARGS' # don't expand PLAN_ARGS
debug_log $TOOL_COMMAND_NAME test -no-color $TEST_ARGS $VARIABLE_ARGS

set +e
# shellcheck disable=SC2086
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME test -no-color $TEST_ARGS $PLAN_ARGS) \
(cd "$INPUT_PATH" && $TOOL_COMMAND_NAME test -no-color $TEST_ARGS $VARIABLE_ARGS) \
2>"$STEP_TMP_DIR/terraform_test.stderr" \
| tee /dev/fd/3 \
>"$STEP_TMP_DIR/terraform_test.stdout"
Expand All @@ -59,7 +59,6 @@ function test() {
}

set-test-args
PLAN_ARGS=""
set-variable-args

test
5 changes: 3 additions & 2 deletions image/src/github_pr_comment/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,6 @@ def main() -> int:

debug(f'diff {proposed_plan_path} {approved_plan_path}')
diff_complete = subprocess.run(['diff', proposed_plan_path, approved_plan_path], check=False, capture_output=True, encoding='utf-8')
sys.stdout.write(diff_complete.stdout)
sys.stderr.write(diff_complete.stderr)

if diff_complete.returncode != 0:
sys.stdout.write("""Performing diff between the pull request plan and the plan generated at execution time.
Expand All @@ -652,6 +650,9 @@ def main() -> int:
Plan differences:
""")

sys.stdout.write(diff_complete.stdout)
sys.stderr.write(diff_complete.stderr)

if comment.headers.get('plan_text_format', 'text').endswith('trunc'):
sys.stdout.write('\nThe plan text was too large for a PR comment, not all differences may be shown here.')

Expand Down
25 changes: 25 additions & 0 deletions tests/workflows/test-apply/ephemeral/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
variable "region" {
type = string
default = "eu-west-2"
}

variable "mv" {
type = string
default = "non-ephemeral"
}

provider "aws" {
region = var.region
}

output "v" {
value = var.mv
}

resource "random_string" "add" {
length = 5
}

terraform {
required_version = ">=1.10"
}

0 comments on commit 506e008

Please sign in to comment.