fix(terraform): apply path parameter schema defaults in ImportState - #19
AshGodfrey wants to merge 2 commits into
Conversation
When a read operation's path parameter has a schema default, the resource schema already applies it, but the generated ImportState treated the field as mandatory in the JSON import ID and returned a "Missing required field" error when it was omitted. Defaulted fields are now decoded as pointers so absence is distinguishable from a zero value, and a missing field is filled with the schema default before being written to state. Global fields keep their provider-level fallback first. Fields without a default behave as before. Adds an ImportDefaultedId review resource and an acceptance test that imports with only the id field and verifies the default lands in state.
|
Running ultrareview automatically — This modifies the core generator template that controls ImportState output, a cross-cutting logic change where a subtle bug in default handling could silently misapply defaults across all generated providers and imported resources.. I'll post findings when complete. |
There was a problem hiding this comment.
Ultrareview completed in 11m 19s
2 issues found across 26 files
Confidence score: 3/5
zSDKs/terraform-provider-testing/internal/provider/importdefaultedid_resource_sdk.gocan replace the imported/schema default forworkspacewith null when the API omits it, causing later requests to send an empty path segment; preserve the existingr.Workspaceunlessresp.Workspaceis non-null.zSDKs/terraform-provider-testing/examples/resources/testing_import_defaulted_id/import.shstill passesworkspace, so the example does not exercise the new omitted-default behavior and may imply the field is required; remove it from the example command.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="zSDKs/terraform-provider-testing/examples/resources/testing_import_defaulted_id/import.sh">
<violation number="1" location="zSDKs/terraform-provider-testing/examples/resources/testing_import_defaulted_id/import.sh:1">
P2: This example still supplies `workspace`, so it does not demonstrate the new omitted-default behavior and makes the optional import field look necessary. Remove `workspace` from the example command.</violation>
</file>
<file name="zSDKs/terraform-provider-testing/internal/provider/importdefaultedid_resource_sdk.go">
<violation number="1" location="zSDKs/terraform-provider-testing/internal/provider/importdefaultedid_resource_sdk.go:19">
P1: When the API omits optional `workspace`, this assignment overwrites the imported/schema default with null. The next request sends an empty path segment; preserve the existing `r.Workspace` unless `resp.Workspace` is non-nil.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
| if resp != nil { | ||
| r.ID = types.StringPointerValue(resp.ID) | ||
| r.RequestBodyProperty = types.StringPointerValue(resp.RequestBodyProperty) | ||
| r.Workspace = types.StringPointerValue(resp.Workspace) |
There was a problem hiding this comment.
P1: When the API omits optional workspace, this assignment overwrites the imported/schema default with null. The next request sends an empty path segment; preserve the existing r.Workspace unless resp.Workspace is non-nil.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At zSDKs/terraform-provider-testing/internal/provider/importdefaultedid_resource_sdk.go, line 19:
<comment>When the API omits optional `workspace`, this assignment overwrites the imported/schema default with null. The next request sends an empty path segment; preserve the existing `r.Workspace` unless `resp.Workspace` is non-nil.</comment>
<file context>
@@ -0,0 +1,94 @@
+ if resp != nil {
+ r.ID = types.StringPointerValue(resp.ID)
+ r.RequestBodyProperty = types.StringPointerValue(resp.RequestBodyProperty)
+ r.Workspace = types.StringPointerValue(resp.Workspace)
+ }
+
</file context>
| r.Workspace = types.StringPointerValue(resp.Workspace) | |
| if resp.Workspace != nil { | |
| r.Workspace = types.StringPointerValue(resp.Workspace) | |
| } |
| @@ -0,0 +1 @@ | |||
| terraform import testing_import_defaulted_id.my_testing_import_defaulted_id '{"id": "...", "workspace": "..."}' | |||
There was a problem hiding this comment.
P2: This example still supplies workspace, so it does not demonstrate the new omitted-default behavior and makes the optional import field look necessary. Remove workspace from the example command.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At zSDKs/terraform-provider-testing/examples/resources/testing_import_defaulted_id/import.sh, line 1:
<comment>This example still supplies `workspace`, so it does not demonstrate the new omitted-default behavior and makes the optional import field look necessary. Remove `workspace` from the example command.</comment>
<file context>
@@ -0,0 +1 @@
+terraform import testing_import_defaulted_id.my_testing_import_defaulted_id '{"id": "...", "workspace": "..."}'
</file context>
| terraform import testing_import_defaulted_id.my_testing_import_defaulted_id '{"id": "...", "workspace": "..."}' | |
| terraform import testing_import_defaulted_id.my_testing_import_defaulted_id '{"id": "..."}' |
Defaulted enum fields fell through the import default literal switch as undefined, so an enum path parameter with a schema default stayed mandatory in the JSON import ID and importing without it failed. The literal now resolves through the enum's underlying type, matching how resource schema defaults are dispatched. The review ImportDefaultedId resource gains a defaulted enum path parameter and the acceptance test verifies both defaults land in state when omitted from the import ID.
Generator Snapshot Testing
Snapshot results: https://github.com/speakeasy-api/openapi-generation-snapshots/issues/94#issuecomment-5715556185 Snapshot results are summarized above. Additional run context is linked for maintainers with access. |
Why
When a resource's read operation has a path parameter with a schema
default, the generated resource schema applies it (Computed+Optional+ a static default), and refresh works with it unset. The generatedImportStatedid not: the field was still mandatory in the JSON import ID and importing without it failed with:This forces users to know and pass a value that every other code path already defaults, and blocks adding a defaulted path parameter to an existing resource without breaking established import workflows.
What changed
templates/templates/terraform/includes/generateImportState.ts:ImportStateassigns the schema default and continues instead of returning an error. Global fields still try the provider-level value first, then the default.Generated output for a defaulted string path parameter:
Review spec and provider:
ImportDefaultedIdresource totests/specs/review-terraform.yamlwhose read path has a defaultedworkspaceparameter.zSDKs/terraform-provider-testing. The existingXGlobalsresource picks up the same behaviour for its defaulted global fields.Not a breaking change: imports that include the field produce identical code and state; imports that omit it go from a hard error to the schema default, matching Create and refresh.
Testing
./scripts/build-review-terraform.sh: full regeneration and acceptance suite pass.TestImportDefaultedIDResourceLifecyclecreates the resource with the parameter unset, then imports with only{"id": "..."}and verifies viaImportStateVerifythat the default lands in state.make lint,make check-template-terraform,npm run format.Public-safety check
.claude/skills/public-repo-communication/SKILL.md).git diff --check.Summary by cubic
Fixes generated Terraform
ImportStateso path parameters with a schemadefaultare optional in the JSON import ID, including enum path parameters whose defaults resolve through the enum's underlying type. Importing without a defaulted field now applies the default instead of failing withMissing required field, matching Create and refresh.ImportDefaultedIdreview resource with string and enum defaults and an acceptance test that imports with only{"id": "..."}and verifies both defaults land in state.Written for commit 5dc956d. Summary will update on new commits.