Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

terraform plan -generate-config-out fails for map nested objects with keys with spaces #35752

Closed
henryrecker-pingidentity opened this issue Sep 19, 2024 · 3 comments · Fixed by #35754 or #35837
Assignees
Labels
bug confirmed a Terraform Core team member has reproduced this issue new new issue not yet triaged

Comments

@henryrecker-pingidentity

Terraform Version

Terraform v1.9.5
on darwin_amd64

Terraform Configuration Files

provider "example" {
}

import {
  to = example_example.myExample
  id = "str"
}

Debug Output

https://gist.github.com/henryrecker-pingidentity/ae09eb59b71a2d0c02526018760dd254

Expected Behavior

HCL should be generated with the expected values

Actual Behavior

Error, no HCL is generated:

Planning failed. Terraform encountered an error while generating this plan.

╷
│ Error: Missing key/value separator
│
│   on generated_resources.tf line 2:
│   (source code not available)
│
│ Expected an equals sign ("=") to mark the beginning of the attribute value. If you intended to given an
│ attribute name containing periods or spaces, write the name in quotes to create a string literal.
╵

Steps to Reproduce

terraform plan -generate-config-out=generated_resources.tf with a provider schema that has a MapNestedAttribute with a key that includes spaces.

A simple provider that reproduces this issue can be found here: https://github.com/henryrecker-pingidentity/terraform-provider-example/tree/GenerateConfigBug

Relevant provider code, note the "Use Case" name with the space.

func (r *exampleResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
	resp.Schema = schema.Schema{
		Description: "Example resource.",
		Attributes: map[string]schema.Attribute{
			"string_val": schema.StringAttribute{
				Description: "Optional string attribute",
				Optional:    true,
			},
			"map_val": schema.MapNestedAttribute{
				NestedObject: schema.NestedAttributeObject{
					Attributes: map[string]schema.Attribute{
						"values": schema.SetAttribute{
							ElementType: types.StringType,
							Optional:    true,
							Description: "A Set of values",
						},
					},
				},
				Optional:    true,
				Description: "Extended Properties allows to store additional information for IdP/SP Connections. The names of these extended properties should be defined in /extendedProperties.",
			},
		},
	}
}

// Metadata returns the resource type name.
func (r *exampleResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
	resp.TypeName = req.ProviderTypeName + "_example"
}

func (r *exampleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
	plan := exampleResourceModel{
		StringVal: types.StringValue("str"),
		MapVal: types.MapValueMust(types.ObjectType{
			AttrTypes: map[string]attr.Type{
				"values": types.SetType{
					ElemType: types.StringType,
				},
			}}, map[string]attr.Value{
			"Use Case": types.ObjectValueMust(map[string]attr.Type{
				"values": types.SetType{
					ElemType: types.StringType,
				},
			}, map[string]attr.Value{
				"values": types.SetValueMust(types.StringType, []attr.Value{
					types.StringValue("CIAM"),
				}),
			}),
		}),
	}
	diags := resp.State.Set(ctx, plan)
	resp.Diagnostics.Append(diags...)
}

func (r *exampleResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
	plan := exampleResourceModel{
		StringVal: types.StringValue("str"),
		MapVal: types.MapValueMust(types.ObjectType{
			AttrTypes: map[string]attr.Type{
				"values": types.SetType{
					ElemType: types.StringType,
				},
			}}, map[string]attr.Value{
			"Use Case": types.ObjectValueMust(map[string]attr.Type{
				"values": types.SetType{
					ElemType: types.StringType,
				},
			}, map[string]attr.Value{
				"values": types.SetValueMust(types.StringType, []attr.Value{
					types.StringValue("CIAM"),
				}),
			}),
		}),
	}
	diags := resp.State.Set(ctx, plan)
	resp.Diagnostics.Append(diags...)
}

// Update updates the resource and sets the updated Terraform state on success.
func (r *exampleResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
	plan := exampleResourceModel{
		StringVal: types.StringValue("str"),
		MapVal: types.MapValueMust(types.ObjectType{
			AttrTypes: map[string]attr.Type{
				"values": types.SetType{
					ElemType: types.StringType,
				},
			}}, map[string]attr.Value{
			"Use Case": types.ObjectValueMust(map[string]attr.Type{
				"values": types.SetType{
					ElemType: types.StringType,
				},
			}, map[string]attr.Value{
				"values": types.SetValueMust(types.StringType, []attr.Value{
					types.StringValue("CIAM"),
				}),
			}),
		}),
	}
	diags := resp.State.Set(ctx, plan)
	resp.Diagnostics.Append(diags...)
}

// No backend so no logic needed
func (r *exampleResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}

func (r *exampleResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
	resource.ImportStatePassthroughID(ctx, path.Root("string_val"), req, resp)
}

Additional Context

No response

References

No response

@henryrecker-pingidentity henryrecker-pingidentity added bug new new issue not yet triaged labels Sep 19, 2024
@liamcervante liamcervante added the confirmed a Terraform Core team member has reproduced this issue label Sep 20, 2024
@liamcervante liamcervante self-assigned this Sep 20, 2024
@henryrecker-pingidentity
Copy link
Author

It looks like this may be a problem with periods in map keys as well - in the case of periods the HCL can be generated, but there ends up being an error about an undeclared resource:

│ Error: Reference to undeclared resource
│
│   on generated_resources.tf line 34:
│   (source code not available)
│
│ A managed resource "policy" "action" has not been declared in the root module.

With generated HCL that looks like this:

attribute_contract_fulfillment = {
      policy.action = {
        source = {
          id   = null
          type = "ADAPTER"
        }
        value = "policy.action"
      }
}

It looks like the "policy.action" value ought to be in quotes.

@henryrecker-pingidentity
Copy link
Author

@DanielMSchmidt It doesn't look to me like that merge request fixes the problem I added in a comment yesterday for when map keys have periods.

@DanielMSchmidt
Copy link
Collaborator

Yeah, I agree, let me re-open this again 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug confirmed a Terraform Core team member has reproduced this issue new new issue not yet triaged
Projects
None yet
3 participants