fix(terraform): apply path parameter schema defaults in ImportState - #19
AshGodfrey wants to merge 1 commit 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
3 issues found across 26 files
Confidence score: 2/5
- In
zSDKs/terraform-provider-testing/internal/provider/importdefaultedid_resource_sdk.go, an omitted APIworkspacecan overwrite the imported default with null, causing the next request to use an empty path segment; preserver.Workspaceunless the response provides a value. - In
templates/templates/terraform/includes/generateImportState.ts, omitted enum, formatted-date, or collection import fields can becomeundefinedinstead of receiving schema defaults, causing incorrect imported resource state; reuse the schema-default type dispatch. - In
zSDKs/terraform-provider-testing/examples/resources/testing_import_defaulted_id/import.sh, supplyingworkspacemasks the omitted-default scenario and suggests 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/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>
<file name="templates/templates/terraform/includes/generateImportState.ts">
<violation number="1" location="templates/templates/terraform/includes/generateImportState.ts:231">
P1: When an import ID omits an enum, formatted date, or collection field with a schema default, this switch returns `undefined`, so ImportState does not apply the resource's default. Reuse the schema-default type dispatch, including enum underlying types and supported formatted or collection defaults, before deciding pointer-ness.</violation>
</file>
<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>
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) | |
| } |
| return undefined; | ||
| } | ||
|
|
||
| switch (field.Type.Type.toString()) { |
There was a problem hiding this comment.
P1: When an import ID omits an enum, formatted date, or collection field with a schema default, this switch returns undefined, so ImportState does not apply the resource's default. Reuse the schema-default type dispatch, including enum underlying types and supported formatted or collection defaults, before deciding pointer-ness.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At templates/templates/terraform/includes/generateImportState.ts, line 231:
<comment>When an import ID omits an enum, formatted date, or collection field with a schema default, this switch returns `undefined`, so ImportState does not apply the resource's default. Reuse the schema-default type dispatch, including enum underlying types and supported formatted or collection defaults, before deciding pointer-ness.</comment>
<file context>
@@ -221,6 +221,41 @@ function genIsZeroValue(
+ return undefined;
+ }
+
+ switch (field.Type.Type.toString()) {
+ case "string":
+ return typeof value === "string"
</file context>
| @@ -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": "..."}' |
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. Importing without a defaulted field now applies the default instead of failing withMissing required field, matching Create and refresh.ImportDefaultedIdreview resource and an acceptance test that imports with only{"id": "..."}and verifies the default lands in state.Written for commit 8c8f44f. Summary will update on new commits.