mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
Fixed the mismatch between arguments sent to the for_each evaluator (#3564)
Signed-off-by: Andrei Ciobanu <andrei.ciobanu@opentofu.org> Signed-off-by: Diogenes Fernandes <diofeher@gmail.com> Co-authored-by: Diogenes Fernandes <diofeher@gmail.com>
This commit is contained in:
@@ -121,11 +121,11 @@ func (ri *ImportResolver) ValidateImportIDs(ctx context.Context, importTarget *I
|
|||||||
rootCtx := evalCtx.WithPath(addrs.RootModuleInstance)
|
rootCtx := evalCtx.WithPath(addrs.RootModuleInstance)
|
||||||
|
|
||||||
if importTarget.Config.ForEach != nil {
|
if importTarget.Config.ForEach != nil {
|
||||||
const unknownsNotAllowed = false
|
const unknownsAllowed = true
|
||||||
const tupleAllowed = true
|
const tupleAllowed = true
|
||||||
|
|
||||||
// The import target has a for_each attribute, so we need to expand it
|
// The import target has a for_each attribute, so we need to expand it
|
||||||
forEachVal, evalDiags := evaluateForEachExpressionValue(ctx, importTarget.Config.ForEach, rootCtx, unknownsNotAllowed, tupleAllowed, nil)
|
forEachVal, evalDiags := evaluateForEachExpressionValue(ctx, importTarget.Config.ForEach, rootCtx, unknownsAllowed, tupleAllowed, nil)
|
||||||
diags = diags.Append(evalDiags)
|
diags = diags.Append(evalDiags)
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
return diags
|
return diags
|
||||||
@@ -134,6 +134,9 @@ func (ri *ImportResolver) ValidateImportIDs(ctx context.Context, importTarget *I
|
|||||||
// We are building an instances.RepetitionData based on each for_each key and val combination
|
// We are building an instances.RepetitionData based on each for_each key and val combination
|
||||||
var repetitions []instances.RepetitionData
|
var repetitions []instances.RepetitionData
|
||||||
|
|
||||||
|
if !forEachVal.IsKnown() {
|
||||||
|
return diags
|
||||||
|
}
|
||||||
it := forEachVal.ElementIterator()
|
it := forEachVal.ElementIterator()
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
k, v := it.Element()
|
k, v := it.Element()
|
||||||
|
|||||||
@@ -2576,3 +2576,68 @@ resource "test_object" "t" {
|
|||||||
t.Fatalf("expected error, got: %q\n", diags.Err().Error())
|
t.Fatalf("expected error, got: %q\n", diags.Err().Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContext2Validate_importWithForEachOnUnknown(t *testing.T) {
|
||||||
|
// This tests checks that a validate run works correctly when the import block is configured with a
|
||||||
|
// for_each statement on unknown values.
|
||||||
|
// In this case, the validation is skipped since the expansion cannot be performed.
|
||||||
|
// Related to https://github.com/opentofu/opentofu/issues/3563
|
||||||
|
m := testModuleInline(t, map[string]string{
|
||||||
|
"main.tf": `
|
||||||
|
variable "server_ids" {
|
||||||
|
type = list(string)
|
||||||
|
default = ["one", "two"]
|
||||||
|
}
|
||||||
|
resource "test_object" "a" {
|
||||||
|
test_string = "foo"
|
||||||
|
count = 2
|
||||||
|
}
|
||||||
|
import {
|
||||||
|
to = test_object.a[tonumber(each.key)]
|
||||||
|
id = each.value
|
||||||
|
for_each = {
|
||||||
|
for idx, item in var.server_ids: idx => item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
p := simpleMockProvider()
|
||||||
|
hook := new(MockHook)
|
||||||
|
ctx := testContext2(t, &ContextOpts{
|
||||||
|
Hooks: []Hook{hook},
|
||||||
|
Providers: map[addrs.Provider]providers.Factory{
|
||||||
|
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
p.ReadResourceFn = func(request providers.ReadResourceRequest) providers.ReadResourceResponse {
|
||||||
|
return providers.ReadResourceResponse{
|
||||||
|
NewState: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"test_string": cty.StringVal("foo"),
|
||||||
|
"test_number": cty.NullVal(cty.Number),
|
||||||
|
"test_bool": cty.NullVal(cty.Bool),
|
||||||
|
"test_list": cty.NullVal(cty.List(cty.String)),
|
||||||
|
"test_map": cty.NullVal(cty.Map(cty.String)),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.ImportResourceStateFn = func(request providers.ImportResourceStateRequest) providers.ImportResourceStateResponse {
|
||||||
|
return providers.ImportResourceStateResponse{
|
||||||
|
ImportedResources: []providers.ImportedResource{
|
||||||
|
{
|
||||||
|
TypeName: "test_object",
|
||||||
|
State: cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"test_string": cty.StringVal("foo"),
|
||||||
|
"test_number": cty.NullVal(cty.Number),
|
||||||
|
"test_bool": cty.NullVal(cty.Bool),
|
||||||
|
"test_list": cty.NullVal(cty.List(cty.String)),
|
||||||
|
"test_map": cty.NullVal(cty.Map(cty.String)),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diags := ctx.Validate(context.Background(), m)
|
||||||
|
if diags.HasErrors() {
|
||||||
|
t.Fatalf("unexpected errors\n%s", diags.Err().Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user