From 694d10b8ead8b2af0c84d1bcb8b780d9420fc571 Mon Sep 17 00:00:00 2001 From: Samsondeen Dare Date: Tue, 7 Jan 2025 12:02:07 +0100 Subject: [PATCH] address comments, change attr name --- internal/command/test_test.go | 4 +- .../tests/plan_mocked_provider.tftest.hcl | 2 +- ...erride_computed_invalid_boolean.tftest.hcl | 2 +- .../tests/plan_mocked_overridden.tftest.hcl | 4 +- .../tests/plan_mocked_provider.tftest.hcl | 4 +- ...plan_mocked_provider_overridden.tftest.hcl | 10 ++-- internal/configs/mock_provider.go | 52 +++++++++---------- internal/moduletest/eval_context.go | 2 +- internal/moduletest/mocking/values.go | 4 +- 9 files changed, 42 insertions(+), 42 deletions(-) diff --git a/internal/command/test_test.go b/internal/command/test_test.go index 87327a00fc42..a41a39a9dede 100644 --- a/internal/command/test_test.go +++ b/internal/command/test_test.go @@ -225,7 +225,7 @@ func TestTest_Runs(t *testing.T) { "mocking-invalid": { expectedErr: []string{ "Invalid outputs attribute", - "The override_computed attribute must be a boolean.", + "The override_target attribute must be a value of plan or apply.", }, initCode: 1, }, @@ -1763,7 +1763,7 @@ condition depended on is not known until after the plan has been applied. Either remove this value from your condition, or execute an %s command from this %s block. Alternatively, if there is an override for this value, you can make it available during the plan phase by setting %s in the %s block. -`, "`run`", "`command = plan`", "`apply`", "`run`", "`override_computed\n= true`", "`override_`"), +`, "`run`", "`command = plan`", "`apply`", "`run`", "`override_target\n= plan`", "`override_`"), }, "unknown_value_in_vars": { code: 1, diff --git a/internal/command/testdata/test/mocking-error/tests/plan_mocked_provider.tftest.hcl b/internal/command/testdata/test/mocking-error/tests/plan_mocked_provider.tftest.hcl index 70754a888b3d..f1cd355ca98a 100644 --- a/internal/command/testdata/test/mocking-error/tests/plan_mocked_provider.tftest.hcl +++ b/internal/command/testdata/test/mocking-error/tests/plan_mocked_provider.tftest.hcl @@ -19,7 +19,7 @@ run "test" { assert { condition = test_resource.secondary[0].id == "ffff" - error_message = "plan should use the mocked provider value when override_computed is true" + error_message = "plan should use the mocked provider value when override_target is plan" } } diff --git a/internal/command/testdata/test/mocking-invalid/tests/override_computed_invalid_boolean.tftest.hcl b/internal/command/testdata/test/mocking-invalid/tests/override_computed_invalid_boolean.tftest.hcl index 59ce59f3f3e8..d35a7eecfff3 100644 --- a/internal/command/testdata/test/mocking-invalid/tests/override_computed_invalid_boolean.tftest.hcl +++ b/internal/command/testdata/test/mocking-invalid/tests/override_computed_invalid_boolean.tftest.hcl @@ -1,6 +1,6 @@ mock_provider "test" { alias = "primary" - override_computed = foo // This should be a boolean value, therefore this test should fail + override_target = baz // This should either be plan or apply, therefore this test should fail mock_resource "test_resource" { defaults = { diff --git a/internal/command/testdata/test/mocking/tests/plan_mocked_overridden.tftest.hcl b/internal/command/testdata/test/mocking/tests/plan_mocked_overridden.tftest.hcl index a65be82f4a77..2e2372894817 100644 --- a/internal/command/testdata/test/mocking/tests/plan_mocked_overridden.tftest.hcl +++ b/internal/command/testdata/test/mocking/tests/plan_mocked_overridden.tftest.hcl @@ -9,7 +9,7 @@ mock_provider "test" { override_resource { target = test_resource.primary - override_computed = true + override_target = plan values = { id = "bbbb" } @@ -26,7 +26,7 @@ run "test" { assert { condition = test_resource.primary[0].id == "bbbb" - error_message = "plan should override the value when override_computed is true" + error_message = "plan should override the value when override_target is plan" } } diff --git a/internal/command/testdata/test/mocking/tests/plan_mocked_provider.tftest.hcl b/internal/command/testdata/test/mocking/tests/plan_mocked_provider.tftest.hcl index bae107b89175..d293d4248581 100644 --- a/internal/command/testdata/test/mocking/tests/plan_mocked_provider.tftest.hcl +++ b/internal/command/testdata/test/mocking/tests/plan_mocked_provider.tftest.hcl @@ -1,6 +1,6 @@ mock_provider "test" { alias = "secondary" - override_computed = true + override_target = plan mock_resource "test_resource" { defaults = { @@ -20,7 +20,7 @@ run "test" { assert { condition = test_resource.secondary[0].id == "ffff" - error_message = "plan should use the mocked provider value when override_computed is true" + error_message = "plan should use the mocked provider value when override_target is plan" } } diff --git a/internal/command/testdata/test/mocking/tests/plan_mocked_provider_overridden.tftest.hcl b/internal/command/testdata/test/mocking/tests/plan_mocked_provider_overridden.tftest.hcl index 354ce2b7b2cf..847438b47b48 100644 --- a/internal/command/testdata/test/mocking/tests/plan_mocked_provider_overridden.tftest.hcl +++ b/internal/command/testdata/test/mocking/tests/plan_mocked_provider_overridden.tftest.hcl @@ -1,6 +1,6 @@ mock_provider "test" { alias = "primary" - override_computed = true + override_target = plan mock_resource "test_resource" { defaults = { @@ -17,7 +17,7 @@ mock_provider "test" { override_resource { target = test_resource.primary[1] - override_computed = false // this should take precedence over the provider-level override_computed + override_target = apply // this should take precedence over the provider-level override_target values = { id = "bbbb" } @@ -27,7 +27,7 @@ mock_provider "test" { override_resource { target = test_resource.secondary[0] - override_computed = true + override_target = plan values = { id = "ssss" } @@ -44,12 +44,12 @@ run "test" { assert { condition = test_resource.primary[0].id == "bbbb" - error_message = "plan should override the value when override_computed is true" + error_message = "plan should override the value when override_target is plan" } assert { condition = test_resource.secondary[0].id == "ssss" - error_message = "plan should override the value when override_computed is true" + error_message = "plan should override the value when override_target is plan" } } diff --git a/internal/configs/mock_provider.go b/internal/configs/mock_provider.go index b54d9dc974d7..3cc288c52754 100644 --- a/internal/configs/mock_provider.go +++ b/internal/configs/mock_provider.go @@ -7,12 +7,18 @@ import ( "github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/zclconf/go-cty/cty" - "github.com/zclconf/go-cty/cty/gocty" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/tfdiags" ) +var ( + // When this attribute is set to plan, the values specified in the override + // block will be used for computed attributes even when planning. It defaults + // to apply, meaning that the values will only be used during apply. + overrideTargetCommand = "override_target" +) + func decodeMockProviderBlock(block *hcl.Block) (*Provider, hcl.Diagnostics) { var diags hcl.Diagnostics @@ -66,23 +72,20 @@ func decodeMockProviderBlock(block *hcl.Block) (*Provider, hcl.Diagnostics) { return provider, diags } -func extractOverrideComputed(content *hcl.BodyContent) (*bool, hcl.Diagnostics) { +func extractOverrideComputed(content *hcl.BodyContent) (*string, hcl.Diagnostics) { var diags hcl.Diagnostics - if attr, exists := content.Attributes[overrideComputed]; exists { - val, valueDiags := attr.Expr.Value(nil) - diags = append(diags, valueDiags...) - var overrideComputedBool bool - err := gocty.FromCtyValue(val, &overrideComputedBool) - if err != nil { + if attr, exists := content.Attributes[overrideTargetCommand]; exists { + overrideComputedStr := hcl.ExprAsKeyword(attr.Expr) + if overrideComputedStr != "plan" && overrideComputedStr != "apply" { diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, - Summary: fmt.Sprintf("Invalid %s value", overrideComputed), - Detail: fmt.Sprintf("The %s attribute must be a boolean.", overrideComputed), + Summary: fmt.Sprintf("Invalid %s value", overrideTargetCommand), + Detail: fmt.Sprintf("The %s attribute must be a value of plan or apply.", overrideTargetCommand), Subject: attr.Range.Ptr(), }) } - return &overrideComputedBool, diags + return &overrideComputedStr, diags } return nil, diags @@ -234,12 +237,12 @@ func decodeMockDataBody(body hcl.Body, source OverrideSource) (*MockData, hcl.Di // provider-level setting for overrideComputed providerOverrideComputed, valueDiags := extractOverrideComputed(content) diags = append(diags, valueDiags...) - + useForPlan := providerOverrideComputed != nil && *providerOverrideComputed == "plan" data := &MockData{ MockResources: make(map[string]*MockResource), MockDataSources: make(map[string]*MockResource), Overrides: addrs.MakeMap[addrs.Targetable, *Override](), - useForPlan: providerOverrideComputed, + useForPlan: &useForPlan, } for _, block := range content.Blocks { @@ -313,8 +316,9 @@ func decodeMockDataBody(body hcl.Body, source OverrideSource) (*MockData, hcl.Di for _, elem := range data.Overrides.Elements() { // use the provider-level setting if there is none set for this override + useForPlan := providerOverrideComputed != nil && *providerOverrideComputed == "plan" if elem.Value.useForPlan == nil { - elem.Value.useForPlan = providerOverrideComputed + elem.Value.useForPlan = &useForPlan } data.Overrides.Put(elem.Key, elem.Value) } @@ -450,20 +454,13 @@ func decodeOverrideDataBlock(block *hcl.Block, source OverrideSource) (*Override return override, diags } -var ( - // When this attribute is set to true, the values specified in the override - // block will be used for computed attributes even when planning. Otherwise, - // the computed values will be set to unknown, just like in a real plan. - overrideComputed = "override_computed" -) - func decodeOverrideBlock(block *hcl.Block, attributeName string, blockName string, source OverrideSource) (*Override, hcl.Diagnostics) { var diags hcl.Diagnostics content, contentDiags := block.Body.Content(&hcl.BodySchema{ Attributes: []hcl.AttributeSchema{ {Name: "target"}, - {Name: overrideComputed}, + {Name: overrideTargetCommand}, {Name: attributeName}, }, }) @@ -505,10 +502,13 @@ func decodeOverrideBlock(block *hcl.Block, attributeName string, blockName strin override.Values = cty.EmptyObjectVal } - // Override computed values during planning if override_computed is true. - overrideComputedBool, valueDiags := extractOverrideComputed(content) + // Override computed values during planning if override_target is plan. + overrideComputedStr, valueDiags := extractOverrideComputed(content) diags = append(diags, valueDiags...) - override.useForPlan = overrideComputedBool + if overrideComputedStr != nil { + useForPlan := *overrideComputedStr == "plan" + override.useForPlan = &useForPlan + } if !override.Values.Type().IsObjectType() { @@ -544,7 +544,7 @@ var mockProviderSchema = &hcl.BodySchema{ var mockDataSchema = &hcl.BodySchema{ Attributes: []hcl.AttributeSchema{ - {Name: overrideComputed}, + {Name: overrideTargetCommand}, }, Blocks: []hcl.BlockHeaderSchema{ {Type: "mock_resource", LabelNames: []string{"type"}}, diff --git a/internal/moduletest/eval_context.go b/internal/moduletest/eval_context.go index 623d71f4fb4a..7a7b8a3fea12 100644 --- a/internal/moduletest/eval_context.go +++ b/internal/moduletest/eval_context.go @@ -141,7 +141,7 @@ func (ec *EvalContext) Evaluate() (Status, cty.Value, tfdiags.Diagnostics) { diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, Summary: "Unknown condition value", - Detail: "Condition expression could not be evaluated at this time. This means you have executed a `run` block with `command = plan` and one of the values your condition depended on is not known until after the plan has been applied. Either remove this value from your condition, or execute an `apply` command from this `run` block. Alternatively, if there is an override for this value, you can make it available during the plan phase by setting `override_computed = true` in the `override_` block.", + Detail: "Condition expression could not be evaluated at this time. This means you have executed a `run` block with `command = plan` and one of the values your condition depended on is not known until after the plan has been applied. Either remove this value from your condition, or execute an `apply` command from this `run` block. Alternatively, if there is an override for this value, you can make it available during the plan phase by setting `override_target = plan` in the `override_` block.", Subject: rule.Condition.Range().Ptr(), Expression: rule.Condition, EvalContext: hclCtx, diff --git a/internal/moduletest/mocking/values.go b/internal/moduletest/mocking/values.go index 5b09fe9cbc9a..f06e2e34fb87 100644 --- a/internal/moduletest/mocking/values.go +++ b/internal/moduletest/mocking/values.go @@ -192,11 +192,11 @@ type MockedData struct { } // NewMockedData creates a new MockedData struct with the given value and range. -func NewMockedData(value cty.Value, computedAsUnknown bool, range_ hcl.Range) MockedData { +func NewMockedData(value cty.Value, computedAsUnknown bool, rng hcl.Range) MockedData { return MockedData{ Value: value, ComputedAsUnknown: computedAsUnknown, - Range: range_, + Range: rng, } }