Skip to content

fix(terraform): apply path parameter schema defaults in ImportState - #19

Open
AshGodfrey wants to merge 1 commit into
mainfrom
ash/terraform-import-state-path-param-defaults
Open

AshGodfrey wants to merge 1 commit into
mainfrom
ash/terraform-import-state-path-param-defaults

Conversation

@AshGodfrey

@AshGodfrey AshGodfrey commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

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 generated ImportState did not: the field was still mandatory in the JSON import ID and importing without it failed with:

Error: Missing required field
The field workspace is required but was not found in the json encoded ID.

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:

  • Fields with a schema default are decoded as pointers in the import JSON struct, so an omitted field is distinguishable from a zero value.
  • When such a field is omitted, ImportState assigns the schema default and continues instead of returning an error. Global fields still try the provider-level value first, then the default.
  • Fields without a default behave exactly as before.

Generated output for a defaulted string path parameter:

if data.Workspace == nil {
	var workspaceDefault string = `default-workspace`
	data.Workspace = &workspaceDefault
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("workspace"), data.Workspace)...)

Review spec and provider:

  • Adds an ImportDefaultedId resource to tests/specs/review-terraform.yaml whose read path has a defaulted workspace parameter.
  • Regenerates zSDKs/terraform-provider-testing. The existing XGlobals resource 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.
  • New TestImportDefaultedIDResourceLifecycle creates the resource with the parameter unset, then imports with only {"id": "..."} and verifies via ImportStateVerify that the default lands in state.
  • make lint, make check-template-terraform, npm run format.
  • Changeset added.

Public-safety check

  • This change contains no credentials, customer documents, private repository URLs, private filesystem paths, or unredacted private logs.
  • Title, body, comments, and commit messages name no customers or customer-derived identifiers, private paths or trackers, or workflow provenance, and are understandable without private context (.claude/skills/public-repo-communication/SKILL.md).
  • Generated fixtures and review SDK changes are public-safe.
  • I reviewed git diff --check.

Summary by cubic

Fixes generated Terraform ImportState so path parameters with a schema default are optional in the JSON import ID. Importing without a defaulted field now applies the default instead of failing with Missing required field, matching Create and refresh.

  • Defaulted fields are filled with the schema default before being written to state; global fields still use the provider-level value first.
  • Fields without a default keep the existing required behavior, and imports that include the defaulted field are unchanged, so this is not breaking.
  • Adds an ImportDefaultedId review 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.

Review in cubic

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.
@AshGodfrey
AshGodfrey requested a review from a team as a code owner September 15, 2026 10:22
@github-actions github-actions Bot added the terraform Trigger (12) snapshot tests for terraform label Sep 15, 2026
@linear-code

linear-code Bot commented Sep 15, 2026

Copy link
Copy Markdown

TFGEN-321

@cubic-dev-ai

cubic-dev-ai Bot commented Sep 15, 2026

Copy link
Copy Markdown

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.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 API workspace can overwrite the imported default with null, causing the next request to use an empty path segment; preserve r.Workspace unless the response provides a value.
  • In templates/templates/terraform/includes/generateImportState.ts, omitted enum, formatted-date, or collection import fields can become undefined instead 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, supplying workspace masks 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)

@cubic-dev-ai cubic-dev-ai Bot Sep 15, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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>
Suggested change
r.Workspace = types.StringPointerValue(resp.Workspace)
if resp.Workspace != nil {
r.Workspace = types.StringPointerValue(resp.Workspace)
}
Fix with cubic

return undefined;
}

switch (field.Type.Type.toString()) {

@cubic-dev-ai cubic-dev-ai Bot Sep 15, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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>
Fix with cubic

@@ -0,0 +1 @@
terraform import testing_import_defaulted_id.my_testing_import_defaulted_id '{"id": "...", "workspace": "..."}'

@cubic-dev-ai cubic-dev-ai Bot Sep 15, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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>
Suggested change
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": "..."}'
Fix with cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

terraform Trigger (12) snapshot tests for terraform

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant