Skip to content

Commit 1947cf2

Browse files
committed
Implement map nested attribute logic
1 parent 1eb0679 commit 1947cf2

File tree

2 files changed

+145
-120
lines changed

2 files changed

+145
-120
lines changed

internal/fwserver/schema_propose_new_plan.go

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,6 @@ func SchemaProposeNewState(ctx context.Context, s fwschema.Schema, req ProposeNe
4848
}
4949

5050
func proposedNew(ctx context.Context, s fwschema.Schema, path *tftypes.AttributePath, prior, config tftypes.Value) tftypes.Value {
51-
// TODO: This is in core's logic, but I'm not sure what how this scenario would be triggered
52-
// Need to verify if it's relevant...
53-
//if config.IsNull() || !config.IsKnown() {
54-
// return prior
55-
//}
56-
57-
// TODO: double check this logic
5851
if config.IsNull() {
5952
return config
6053
}
@@ -70,7 +63,6 @@ func proposedNew(ctx context.Context, s fwschema.Schema, path *tftypes.Attribute
7063

7164
newAttrs := proposedNewAttributes(ctx, s, s.GetAttributes(), path, prior, config)
7265

73-
// TODO: add block logic
7466
for name, blockType := range s.GetBlocks() {
7567
attrVal, _ := prior.ApplyTerraform5AttributePathStep(tftypes.AttributeName(name))
7668
priorVal := attrVal.(tftypes.Value)
@@ -224,7 +216,7 @@ func proposeNewNestedAttribute(ctx context.Context, s fwschema.Schema, attr fwsc
224216
case fwschema.NestingModeList:
225217
newVal = proposedNewListNested(ctx, s, attr, path, prior, config)
226218
case fwschema.NestingModeMap:
227-
219+
newVal = proposedNewMapNested(ctx, s, attr, path, prior, config)
228220
case fwschema.NestingModeSet:
229221
newVal = proposedNewSetNested(ctx, s, attr, path, prior, config)
230222
default:
@@ -235,6 +227,53 @@ func proposeNewNestedAttribute(ctx context.Context, s fwschema.Schema, attr fwsc
235227
return newVal
236228
}
237229

230+
func proposedNewMapNested(ctx context.Context, s fwschema.Schema, attr fwschema.NestedAttribute, path *tftypes.AttributePath, prior, config tftypes.Value) tftypes.Value {
231+
newVal := config
232+
233+
configMap := make(map[string]tftypes.Value)
234+
priorMap := make(map[string]tftypes.Value)
235+
236+
configValLen := 0
237+
if !config.IsNull() {
238+
err := config.As(&priorMap)
239+
// TODO: handle err
240+
if err != nil {
241+
panic(err)
242+
}
243+
configValLen = len(configMap)
244+
}
245+
246+
if !prior.IsNull() {
247+
err := prior.As(&priorMap)
248+
// TODO: handle err
249+
if err != nil {
250+
panic(err)
251+
}
252+
}
253+
254+
if configValLen > 0 {
255+
newVals := make(map[string]tftypes.Value, configValLen)
256+
for name, configEV := range configMap {
257+
priorEV, inPrior := priorMap[name]
258+
if !inPrior {
259+
// if the prior value was unknown the map won't have any
260+
// keys, so generate an unknown value.
261+
if !prior.IsKnown() {
262+
priorEV = tftypes.NewValue(configEV.Type(), tftypes.UnknownValue)
263+
} else {
264+
priorEV = tftypes.NewValue(configEV.Type(), nil)
265+
266+
}
267+
}
268+
269+
newVals[name] = proposedNewObjectAttributes(ctx, s, attr, path.WithElementKeyString(name), priorEV, configEV)
270+
}
271+
newVal = tftypes.NewValue(config.Type(), newVals)
272+
}
273+
274+
return newVal
275+
}
276+
238277
func proposedNewBlockListNested(ctx context.Context, s fwschema.Schema, block fwschema.Block, path *tftypes.AttributePath, prior, config tftypes.Value) tftypes.Value {
239278
newVal := config
240279

@@ -272,7 +311,6 @@ func proposedNewBlockListNested(ctx context.Context, s fwschema.Schema, block fw
272311
newVals = append(newVals, proposedNewBlockObjectAttributes(ctx, s, block, path.WithElementKeyInt(idx), priorEV, configEV))
273312
}
274313

275-
// TODO: should work for tuples + lists
276314
newVal = tftypes.NewValue(config.Type(), newVals)
277315
}
278316

@@ -330,15 +368,10 @@ func proposedNewBlockSetNested(ctx context.Context, s fwschema.Schema, block fws
330368
}
331369

332370
if priorEV.IsNull() {
333-
// TODO might have to come back to figure out how to get elem type
334371
priorEV = tftypes.NewValue(block.GetNestedObject().Type().TerraformType(ctx), nil)
335372
}
336-
//block.GetNestedObject().GetAttributes()
337-
// TODO create proposed new nested block object
338373
newVals = append(newVals, proposeNewNestedBlockObject(ctx, s, block.GetNestedObject(), path.WithElementKeyValue(priorEV), priorEV, configEV))
339374
}
340-
341-
// TODO: should work for tuples + lists
342375
newVal = tftypes.NewValue(config.Type(), newVals)
343376
}
344377

@@ -381,8 +414,6 @@ func proposedNewListNested(ctx context.Context, s fwschema.Schema, attr fwschema
381414
priorEV := priorVals[idx]
382415
newVals = append(newVals, proposedNewObjectAttributes(ctx, s, attr, path.WithElementKeyInt(idx), priorEV, configEV))
383416
}
384-
385-
// TODO: should work for tuples + lists
386417
newVal = tftypes.NewValue(config.Type(), newVals)
387418
}
388419

@@ -440,15 +471,10 @@ func proposedNewSetNested(ctx context.Context, s fwschema.Schema, attr fwschema.
440471
}
441472

442473
if priorEV.IsNull() {
443-
// TODO might have to come back to figure out how to get elem type
444474
priorEV = tftypes.NewValue(attr.GetNestedObject().Type().TerraformType(ctx), nil)
445475
}
446-
//block.GetNestedObject().GetAttributes()
447-
// TODO create proposed new nested block object
448476
newVals = append(newVals, proposedNewObjectAttributes(ctx, s, attr, path.WithElementKeyValue(priorEV), priorEV, configEV))
449477
}
450-
451-
// TODO: should work for tuples + lists
452478
newVal = tftypes.NewValue(config.Type(), newVals)
453479
}
454480

internal/fwserver/schema_propose_new_plan_test.go

Lines changed: 97 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -917,104 +917,103 @@ func TestSchemaProposeNewState(t *testing.T) {
917917
),
918918
},
919919
},
920-
// TODO: uncomment after implementing map logic
921-
//"prior nested map": {
922-
// schema: schema.Schema{
923-
// Attributes: map[string]schema.Attribute{
924-
// "map_nested_attribute": schema.MapNestedAttribute{
925-
// Optional: true,
926-
// NestedObject: schema.NestedAttributeObject{
927-
// Attributes: map[string]schema.Attribute{
928-
// "required_nested_attribute": schema.StringAttribute{
929-
// Required: true,
930-
// },
931-
// },
932-
// },
933-
// },
934-
// },
935-
// },
936-
// priorVal: map[string]tftypes.Value{
937-
// "map_nested_attribute": tftypes.NewValue(
938-
// tftypes.Map{
939-
// ElementType: tftypes.Object{
940-
// AttributeTypes: map[string]tftypes.Type{
941-
// "required_nested_attribute": tftypes.String,
942-
// },
943-
// },
944-
// },
945-
// map[string]tftypes.Value{
946-
// "a": tftypes.NewValue(tftypes.Object{
947-
// AttributeTypes: map[string]tftypes.Type{
948-
// "required_nested_attribute": tftypes.String,
949-
// },
950-
// }, map[string]tftypes.Value{
951-
// "required_nested_attribute": tftypes.NewValue(tftypes.String, "glub"),
952-
// }),
953-
// "b": tftypes.NewValue(tftypes.Object{
954-
// AttributeTypes: map[string]tftypes.Type{
955-
// "required_nested_attribute": tftypes.String,
956-
// },
957-
// }, map[string]tftypes.Value{
958-
// "required_nested_attribute": tftypes.NewValue(tftypes.String, "blub"),
959-
// }),
960-
// },
961-
// ),
962-
// },
963-
// configVal: map[string]tftypes.Value{
964-
// "map_nested_attribute": tftypes.NewValue(
965-
// tftypes.Map{
966-
// ElementType: tftypes.Object{
967-
// AttributeTypes: map[string]tftypes.Type{
968-
// "required_nested_attribute": tftypes.String,
969-
// },
970-
// },
971-
// },
972-
// map[string]tftypes.Value{
973-
// "a": tftypes.NewValue(tftypes.Object{
974-
// AttributeTypes: map[string]tftypes.Type{
975-
// "required_nested_attribute": tftypes.String,
976-
// },
977-
// }, map[string]tftypes.Value{
978-
// "required_nested_attribute": tftypes.NewValue(tftypes.String, "glub"),
979-
// }),
980-
// "c": tftypes.NewValue(tftypes.Object{
981-
// AttributeTypes: map[string]tftypes.Type{
982-
// "required_nested_attribute": tftypes.String,
983-
// },
984-
// }, map[string]tftypes.Value{
985-
// "required_nested_attribute": tftypes.NewValue(tftypes.String, "blub"),
986-
// }),
987-
// },
988-
// ),
989-
// },
990-
// expectedVal: map[string]tftypes.Value{
991-
// "map_nested_attribute": tftypes.NewValue(
992-
// tftypes.Map{
993-
// ElementType: tftypes.Object{
994-
// AttributeTypes: map[string]tftypes.Type{
995-
// "required_nested_attribute": tftypes.String,
996-
// },
997-
// },
998-
// },
999-
// map[string]tftypes.Value{
1000-
// "a": tftypes.NewValue(tftypes.Object{
1001-
// AttributeTypes: map[string]tftypes.Type{
1002-
// "required_nested_attribute": tftypes.String,
1003-
// },
1004-
// }, map[string]tftypes.Value{
1005-
// "required_nested_attribute": tftypes.NewValue(tftypes.String, "glub"),
1006-
// }),
1007-
// "c": tftypes.NewValue(tftypes.Object{
1008-
// AttributeTypes: map[string]tftypes.Type{
1009-
// "required_nested_attribute": tftypes.String,
1010-
// },
1011-
// }, map[string]tftypes.Value{
1012-
// "required_nested_attribute": tftypes.NewValue(tftypes.String, "blub"),
1013-
// }),
1014-
// },
1015-
// ),
1016-
// },
1017-
//},
920+
"prior nested map": {
921+
schema: schema.Schema{
922+
Attributes: map[string]schema.Attribute{
923+
"map_nested_attribute": schema.MapNestedAttribute{
924+
Optional: true,
925+
NestedObject: schema.NestedAttributeObject{
926+
Attributes: map[string]schema.Attribute{
927+
"required_nested_attribute": schema.StringAttribute{
928+
Required: true,
929+
},
930+
},
931+
},
932+
},
933+
},
934+
},
935+
priorVal: map[string]tftypes.Value{
936+
"map_nested_attribute": tftypes.NewValue(
937+
tftypes.Map{
938+
ElementType: tftypes.Object{
939+
AttributeTypes: map[string]tftypes.Type{
940+
"required_nested_attribute": tftypes.String,
941+
},
942+
},
943+
},
944+
map[string]tftypes.Value{
945+
"a": tftypes.NewValue(tftypes.Object{
946+
AttributeTypes: map[string]tftypes.Type{
947+
"required_nested_attribute": tftypes.String,
948+
},
949+
}, map[string]tftypes.Value{
950+
"required_nested_attribute": tftypes.NewValue(tftypes.String, "glub"),
951+
}),
952+
"b": tftypes.NewValue(tftypes.Object{
953+
AttributeTypes: map[string]tftypes.Type{
954+
"required_nested_attribute": tftypes.String,
955+
},
956+
}, map[string]tftypes.Value{
957+
"required_nested_attribute": tftypes.NewValue(tftypes.String, "blub"),
958+
}),
959+
},
960+
),
961+
},
962+
configVal: map[string]tftypes.Value{
963+
"map_nested_attribute": tftypes.NewValue(
964+
tftypes.Map{
965+
ElementType: tftypes.Object{
966+
AttributeTypes: map[string]tftypes.Type{
967+
"required_nested_attribute": tftypes.String,
968+
},
969+
},
970+
},
971+
map[string]tftypes.Value{
972+
"a": tftypes.NewValue(tftypes.Object{
973+
AttributeTypes: map[string]tftypes.Type{
974+
"required_nested_attribute": tftypes.String,
975+
},
976+
}, map[string]tftypes.Value{
977+
"required_nested_attribute": tftypes.NewValue(tftypes.String, "glub"),
978+
}),
979+
"c": tftypes.NewValue(tftypes.Object{
980+
AttributeTypes: map[string]tftypes.Type{
981+
"required_nested_attribute": tftypes.String,
982+
},
983+
}, map[string]tftypes.Value{
984+
"required_nested_attribute": tftypes.NewValue(tftypes.String, "blub"),
985+
}),
986+
},
987+
),
988+
},
989+
expectedVal: map[string]tftypes.Value{
990+
"map_nested_attribute": tftypes.NewValue(
991+
tftypes.Map{
992+
ElementType: tftypes.Object{
993+
AttributeTypes: map[string]tftypes.Type{
994+
"required_nested_attribute": tftypes.String,
995+
},
996+
},
997+
},
998+
map[string]tftypes.Value{
999+
"a": tftypes.NewValue(tftypes.Object{
1000+
AttributeTypes: map[string]tftypes.Type{
1001+
"required_nested_attribute": tftypes.String,
1002+
},
1003+
}, map[string]tftypes.Value{
1004+
"required_nested_attribute": tftypes.NewValue(tftypes.String, "glub"),
1005+
}),
1006+
"c": tftypes.NewValue(tftypes.Object{
1007+
AttributeTypes: map[string]tftypes.Type{
1008+
"required_nested_attribute": tftypes.String,
1009+
},
1010+
}, map[string]tftypes.Value{
1011+
"required_nested_attribute": tftypes.NewValue(tftypes.String, "blub"),
1012+
}),
1013+
},
1014+
),
1015+
},
1016+
},
10181017
"prior optional computed nested map elem to null": {
10191018
schema: schema.Schema{
10201019
Attributes: map[string]schema.Attribute{

0 commit comments

Comments
 (0)