diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 9bccec6..c617f54 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -9,7 +9,7 @@ jobs: steps: - name: Generate Matrix id: matrix - uses: Invicton-Labs/terraform-module-testing/matrix@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/matrix@dev with: minimum_tf_version: '1.10.3' additional_runners: 'macos-13, windows-2019' @@ -29,89 +29,89 @@ jobs: steps: - name: Initialize - Pass id: init-pass - uses: Invicton-Labs/terraform-module-testing/initialize@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/initialize@dev with: tf_path: tests/pass - name: Run Tests - Pass id: tests-pass - uses: Invicton-Labs/terraform-module-testing/apply-destroy@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/apply-destroy@dev with: tf_path: tests/pass - name: Initialize - Pass (With Output) id: init-pass-output - uses: Invicton-Labs/terraform-module-testing/initialize@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/initialize@dev with: tf_path: tests/pass-output - name: Run Tests - Pass (With Output) id: tests-pass-output - uses: Invicton-Labs/terraform-module-testing/apply-destroy@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/apply-destroy@dev with: tf_path: tests/pass-output - name: Initialize - Pass - Condition Delayed id: init-pass-condition-delayed - uses: Invicton-Labs/terraform-module-testing/initialize@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/initialize@dev with: tf_path: tests/pass-condition-delayed - name: Run Tests - Pass - Condition Delayed id: tests-pass-condition-delayed - uses: Invicton-Labs/terraform-module-testing/apply-destroy@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/apply-destroy@dev with: tf_path: tests/pass-condition-delayed - name: Initialize - Pass - Message Delayed id: init-pass-message-delayed - uses: Invicton-Labs/terraform-module-testing/initialize@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/initialize@dev with: tf_path: tests/pass-message-delayed - name: Run Tests - Pass - Message Delayed id: tests-pass-message-delayed - uses: Invicton-Labs/terraform-module-testing/apply-destroy@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/apply-destroy@dev with: tf_path: tests/pass-message-delayed - name: Initialize - Fail id: init-fail - uses: Invicton-Labs/terraform-module-testing/initialize@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/initialize@dev with: tf_path: tests/fail - name: Run Tests - Fail id: tests-fail - uses: Invicton-Labs/terraform-module-testing/apply-failure@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/apply-failure@dev with: tf_path: tests/fail - name: Initialize - Fail (Output) id: init-fail-output - uses: Invicton-Labs/terraform-module-testing/initialize@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/initialize@dev with: tf_path: tests/fail-output - name: Run Tests - Fail (Output) id: tests-fail-output - uses: Invicton-Labs/terraform-module-testing/apply-failure@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/apply-failure@dev with: tf_path: tests/fail-output - name: Initialize - Fail - Condition Delayed id: init-fail-condition-delayed - uses: Invicton-Labs/terraform-module-testing/initialize@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/initialize@dev with: tf_path: tests/fail-condition-delayed - name: Run Tests - Fail - Condition Delayed id: tests-fail-condition-delayed - uses: Invicton-Labs/terraform-module-testing/apply-failure@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/apply-failure@dev with: tf_path: tests/fail-condition-delayed - name: Initialize - Fail - Message Delayed id: init-fail-message-delayed - uses: Invicton-Labs/terraform-module-testing/initialize@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/initialize@dev with: tf_path: tests/fail-message-delayed - name: Run Tests - Fail - Message Delayed id: tests-fail-message-delayed - uses: Invicton-Labs/terraform-module-testing/apply-failure@v0.2.0 + uses: Invicton-Labs/terraform-module-testing/apply-failure@dev with: tf_path: tests/fail-message-delayed diff --git a/README.md b/README.md index 4649d15..09454f6 100644 --- a/README.md +++ b/README.md @@ -30,3 +30,25 @@ var.error_message is "This Terraform configuration can only be run on Unix-based // Ignore this part There is no function named "SEE_ABOVE_ERROR_MESSAGE". ``` + +## Plan, Apply, and Unknown Values + +There are several edge cases regarding conditions that aren't known until apply and error messages that aren't known until apply. + + +### Conditions not known during planning + +When the `condition` variable doesn't have a known value during the plan step, the assertion will not be checked during the plan step. The `error_message` variable will not be used or evaluated. + +The `condition` _will_ still be checked during the apply step, and the `error_message` variable will be used if `condition` evaluates to `false`. + + +### Error messages not known during planning + +When the `error_message` variable doesn't have a known value during the plan step, the behaviour will vary depending on whether the `condition` value is known during the plan step. + +If `condition` is not known during planning, then the `error_message` will not be evaluated/used until the apply step, and only if `condition` evaluates to `false`. + +If the `condition` _is_ known during planning and it evaluates to `false`, then the Terraform operation will fail during the plan step and the output error message will explain that the `error_message` variable value is invalid (not known). + +If `condition` evaluates to `true` as soon as it's known, then `error_message` will never be used or evaluated, so it doesn't matter if it's known or not. diff --git a/outputs.tf b/outputs.tf index 5e61c6d..d7dbd48 100644 --- a/outputs.tf +++ b/outputs.tf @@ -10,5 +10,6 @@ output "condition" { output "checked" { description = "Whether the condition has been checked (used for assertion dependencies)." - value = local.evaluation == true ? true : true //var.condition == true ? true : true + value = var.condition == true ? true : true + //value = local.evaluation == "" ? true : true //var.condition == true ? true : true } diff --git a/tests/fail-message-delayed/main.tf b/tests/fail-message-delayed/main.tf index 32f9b91..eae5749 100644 --- a/tests/fail-message-delayed/main.tf +++ b/tests/fail-message-delayed/main.tf @@ -1,6 +1,6 @@ module "fail" { source = "../../" // Use a condition that isn't known until the apply step - condition = false + condition = uuid() == "" error_message = "sample error: ${uuid()}" } diff --git a/tests/pass-message-delayed/main.tf b/tests/pass-message-delayed/main.tf index 932f2a3..dd73eea 100644 --- a/tests/pass-message-delayed/main.tf +++ b/tests/pass-message-delayed/main.tf @@ -1,6 +1,6 @@ module "pass" { source = "../../" // Use a condition that isn't known until the apply step - condition = true + condition = uuid() != "" error_message = "sample error: ${uuid()}" } diff --git a/variables.tf b/variables.tf index d89ad19..9ebd4e4 100644 --- a/variables.tf +++ b/variables.tf @@ -7,16 +7,16 @@ variable "error_message" { variable "condition" { description = "The condition to ensure is `true`." type = bool - # validation { - # // We have to use var.error_message != null to force the evaluation to wait - # // until var.error_message is known. Otherwise, it can fail during the validation - # // phase but won't output the proper error message. - # // https://github.com/hashicorp/terraform/issues/35397 - # condition = var.error_message == "" ? var.condition : var.condition - # error_message = var.error_message - # } + validation { + // We have to use var.error_message != null to force the evaluation to wait + // until var.error_message is known. Otherwise, it can fail during the validation + // phase but won't output the proper error message. + // https://github.com/hashicorp/terraform/issues/35397 + condition = var.error_message == "" ? var.condition : var.condition + error_message = var.error_message + } } -locals { - evaluation = var.condition ? null : SEE_ERROR_MESSAGE(var.error_message) -} +# locals { +# evaluation = var.condition ? "" : SEE_ABOVE_ERROR_MESSAGE(true ? null : "ERROR: ${var.error_message}") +# }