mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
genconfig: do not generate null NestingSingle blocks (#33213)
* genconfig: fix nil nested block panic * always InternalValidate test schemas * genconfig: null NestingSingle blocks should be absent A NestingSingle block that is null in state should be completely absent from config.
This commit is contained in:
parent
048cc65787
commit
4015f1aa30
@ -17,7 +17,7 @@ import (
|
||||
// GenerateResourceContents generates HCL configuration code for the provided
|
||||
// resource and state value.
|
||||
//
|
||||
// If you want tot generate actual valid Terraform code you should follow this
|
||||
// If you want to generate actual valid Terraform code you should follow this
|
||||
// call up with a call to WrapResourceContents, which will place a Terraform
|
||||
// resource header around the attributes and blocks returned by this function.
|
||||
func GenerateResourceContents(addr addrs.AbsResourceInstance,
|
||||
@ -140,7 +140,7 @@ func writeConfigAttributesFromExisting(addr addrs.AbsResourceInstance, buf *stri
|
||||
buf.WriteString(fmt.Sprintf("%s = ", name))
|
||||
|
||||
var val cty.Value
|
||||
if stateVal.Type().HasAttribute(name) {
|
||||
if !stateVal.IsNull() && stateVal.Type().HasAttribute(name) {
|
||||
val = stateVal.GetAttr(name)
|
||||
} else {
|
||||
val = attrS.EmptyValue()
|
||||
@ -422,6 +422,9 @@ func writeConfigNestedBlockFromExisting(addr addrs.AbsResourceInstance, buf *str
|
||||
|
||||
switch schema.Nesting {
|
||||
case configschema.NestingSingle, configschema.NestingGroup:
|
||||
if stateVal.IsNull() {
|
||||
return diags
|
||||
}
|
||||
buf.WriteString(strings.Repeat(" ", indent))
|
||||
buf.WriteString(fmt.Sprintf("%s {", name))
|
||||
|
||||
|
@ -302,6 +302,7 @@ resource "tfcoremock_simple_resource" "empty" {
|
||||
Attributes: map[string]*configschema.Attribute{},
|
||||
Nesting: configschema.NestingSingle,
|
||||
},
|
||||
Required: true,
|
||||
},
|
||||
"list": {
|
||||
NestedType: &configschema.Object{
|
||||
@ -313,6 +314,7 @@ resource "tfcoremock_simple_resource" "empty" {
|
||||
},
|
||||
Nesting: configschema.NestingList,
|
||||
},
|
||||
Required: true,
|
||||
},
|
||||
"map": {
|
||||
NestedType: &configschema.Object{
|
||||
@ -324,6 +326,54 @@ resource "tfcoremock_simple_resource" "empty" {
|
||||
},
|
||||
Nesting: configschema.NestingMap,
|
||||
},
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
BlockTypes: map[string]*configschema.NestedBlock{
|
||||
"nested_single": {
|
||||
Nesting: configschema.NestingSingle,
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"nested_id": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// No configschema.NestingGroup example for this test, because this block type can never be null in state.
|
||||
"nested_list": {
|
||||
Nesting: configschema.NestingList,
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"nested_id": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"nested_set": {
|
||||
Nesting: configschema.NestingSet,
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"nested_id": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"nested_map": {
|
||||
Nesting: configschema.NestingMap,
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"nested_id": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -350,6 +400,18 @@ resource "tfcoremock_simple_resource" "empty" {
|
||||
"map": cty.NullVal(cty.Map(cty.Object(map[string]cty.Type{
|
||||
"nested_id": cty.String,
|
||||
}))),
|
||||
"nested_single": cty.NullVal(cty.Object(map[string]cty.Type{
|
||||
"nested_id": cty.String,
|
||||
})),
|
||||
"nested_list": cty.ListValEmpty(cty.Object(map[string]cty.Type{
|
||||
"nested_id": cty.String,
|
||||
})),
|
||||
"nested_set": cty.SetValEmpty(cty.Object(map[string]cty.Type{
|
||||
"nested_id": cty.String,
|
||||
})),
|
||||
"nested_map": cty.MapValEmpty(cty.Object(map[string]cty.Type{
|
||||
"nested_id": cty.String,
|
||||
})),
|
||||
}),
|
||||
expected: `
|
||||
resource "tfcoremock_simple_resource" "empty" {
|
||||
@ -361,6 +423,10 @@ resource "tfcoremock_simple_resource" "empty" {
|
||||
}
|
||||
for name, tc := range tcs {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
err := tc.schema.InternalValidate()
|
||||
if err != nil {
|
||||
t.Fatalf("schema failed InternalValidate: %s", err)
|
||||
}
|
||||
contents, diags := GenerateResourceContents(tc.addr, tc.schema, tc.provider, tc.value)
|
||||
if len(diags) > 0 {
|
||||
t.Errorf("expected no diagnostics but found %s", diags)
|
||||
|
Loading…
Reference in New Issue
Block a user