Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/unreleased/NOTES-20260304-134617.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: NOTES
body: 'This release moves the [resource configuration generation](https://developer.hashicorp.com/terraform/language/import/generating-configuration) logic for the `-generate-config-out` flag from
Terraform Core to the SDKv2. There should be no functionality changes for resource configuration generation in this release.'
time: 2026-03-04T13:46:17.250227-05:00
custom:
Issue: "1559"
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/hashicorp/logutils v1.0.0
github.com/hashicorp/terraform-exec v0.25.0
github.com/hashicorp/terraform-json v0.27.2
github.com/hashicorp/terraform-plugin-go v0.30.0
github.com/hashicorp/terraform-plugin-go v0.30.1-0.20260224203057-7d789423e31f
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to us to update this before merging/releasing

github.com/hashicorp/terraform-plugin-log v0.10.0
github.com/mitchellh/copystructure v1.2.0
github.com/mitchellh/go-testing-interface v1.14.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ github.com/hashicorp/terraform-json v0.27.2 h1:BwGuzM6iUPqf9JYM/Z4AF1OJ5VVJEEzoK
github.com/hashicorp/terraform-json v0.27.2/go.mod h1:GzPLJ1PLdUG5xL6xn1OXWIjteQRT2CNT9o/6A9mi9hE=
github.com/hashicorp/terraform-plugin-go v0.30.0 h1:VmEiD0n/ewxbvV5VI/bYwNtlSEAXtHaZlSnyUUuQK6k=
github.com/hashicorp/terraform-plugin-go v0.30.0/go.mod h1:8d523ORAW8OHgA9e8JKg0ezL3XUO84H0A25o4NY/jRo=
github.com/hashicorp/terraform-plugin-go v0.30.1-0.20260224203057-7d789423e31f h1:Gn9urczv0KsRi0YrjI7kdzHNUT2zQ/HLi5lfiLY6oxY=
github.com/hashicorp/terraform-plugin-go v0.30.1-0.20260224203057-7d789423e31f/go.mod h1:8d523ORAW8OHgA9e8JKg0ezL3XUO84H0A25o4NY/jRo=
github.com/hashicorp/terraform-plugin-log v0.10.0 h1:eu2kW6/QBVdN4P3Ju2WiB2W3ObjkAsyfBsL3Wh1fj3g=
github.com/hashicorp/terraform-plugin-log v0.10.0/go.mod h1:/9RR5Cv2aAbrqcTSdNmY1NRHP4E3ekrXRGjqORpXyB0=
github.com/hashicorp/terraform-registry-address v0.4.0 h1:S1yCGomj30Sao4l5BMPjTGZmCNzuv7/GDTDX99E9gTk=
Expand Down
104 changes: 104 additions & 0 deletions helper/schema/grpc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func (s *GRPCProviderServer) StopContext(ctx context.Context) context.Context {
func (s *GRPCProviderServer) serverCapabilities() *tfprotov5.ServerCapabilities {
return &tfprotov5.ServerCapabilities{
GetProviderSchemaOptional: true,
GenerateResourceConfig: true,
}
}

Expand Down Expand Up @@ -1785,6 +1786,109 @@ func (s *GRPCProviderServer) ImportResourceState(ctx context.Context, req *tfpro
return resp, nil
}

func (s *GRPCProviderServer) GenerateResourceConfig(ctx context.Context, req *tfprotov5.GenerateResourceConfigRequest) (*tfprotov5.GenerateResourceConfigResponse, error) {
ctx = logging.InitContext(ctx)

resp := &tfprotov5.GenerateResourceConfigResponse{}

schemaBlock := s.getResourceSchemaBlock(req.TypeName)

stateVal, err := msgpack.Unmarshal(req.State.MsgPack, schemaBlock.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(ctx, resp.Diagnostics, err)
return resp, nil
}

if stateVal.IsNull() {
resp.Diagnostics = []*tfprotov5.Diagnostic{
{
Severity: tfprotov5.DiagnosticSeverityError,
Summary: "Unexpected Generate Config Request",
Detail: "An unexpected error was encountered when generating resource configuration. The current state was missing.\n\n" +
"This is always a problem with Terraform or terraform-plugin-sdk. Please report this to the provider developer.",
},
}

}

newConfigVal := stateVal

// Handle top level attributes and defaults
newConfigVal, err = cty.Transform(newConfigVal, func(path cty.Path, val cty.Value) (cty.Value, error) {
if val.IsNull() {
return val, nil
}

if len(path) == 0 {
return val, nil
}

ty := val.Type()
null := cty.NullVal(ty)

// find the attribute or block schema representing the value
attr := schemaBlock.AttributeByPath(path)
block := schemaBlock.BlockByPath(path)
switch {
case attr != nil:
// deprecated attributes
if attr.Deprecated {
return null, nil
}

// read-only attributes are not written in the configuration
if attr.Computed && !attr.Optional {
return null, nil
}

// The legacy SDK adds an Optional+Computed "id" attribute to the
// resource schema even if not defined in provider code.
// During validation, however, the presence of an extraneous "id"
// attribute in config will cause an error.
// Remove this attribute so we do not generate an "id" attribute
// where there is a risk that it is not in the real resource schema.
if path.Equals(cty.GetAttrPath("id")) && attr.Computed && attr.Optional {
return null, nil
}

// If we have "" for an optional value, assume it is actually null
// due to the legacy SDK.
if ty == cty.String {
if !val.IsNull() && attr.Optional && len(val.AsString()) == 0 {
return null, nil
}
}
return val, nil

case block != nil:
if block.Deprecated {
return null, nil
}
}

return val, nil
})
if err != nil {
configErr := fmt.Errorf("An unexpected error occurred while trying to generate resource configuration. "+
"This is an error in terraform-plugin-sdk used by the provider. "+
"Please report the following to the provider developers.\n\n"+
"Original Error: %s", err.Error())
resp.Diagnostics = convert.AppendProtoDiag(ctx, resp.Diagnostics, configErr)
return resp, nil
}

newConfigMP, err := msgpack.Marshal(newConfigVal, schemaBlock.ImpliedType())
if err != nil {
resp.Diagnostics = convert.AppendProtoDiag(ctx, resp.Diagnostics, err)
return resp, nil
}
resp.Config = &tfprotov5.DynamicValue{
MsgPack: newConfigMP,
}

return resp, nil
}

func (s *GRPCProviderServer) MoveResourceState(ctx context.Context, req *tfprotov5.MoveResourceStateRequest) (*tfprotov5.MoveResourceStateResponse, error) {
if req == nil {
return nil, fmt.Errorf("MoveResourceState request is nil")
Expand Down
Loading
Loading