一键导入
tgc-fix-handwritten-resources-tests-skill
Fix integration tests for handwritten resources in TGC. Use when you need to fix integration tests for TGC.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Fix integration tests for handwritten resources in TGC. Use when you need to fix integration tests for TGC.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Skill for reviewing Magic Modules schemas. Currently covers the Enum vs. String decision via the knowledge base.
Opt resource into MMv1 list-resource generation by setting `generate_list_resource: true`, validate it locally, and open a one-resource PR against GoogleCloudPlatform/magic-modules. Invoke when the user asks to add list-resource support for a specific MMv1 resource or to enable `generate_list_resource` for an eligible resource.
Fallback workflow for general implementation and debugging tasks that do not involve creating a new resource.
Workflow specifically for creating a new resource, supporting both autogen and manual generation.
Create a Pull Request (PR) against GoogleCloudPlatform/magic-modules following repository standards, including branch management, commit formatting, mandatory release notes, pre-PR verification checks, and gh CLI commands.
Validate that changes to the generated providers don't introduce breaking changes or fields with missing tests or missing documentation. Use this skill when the user wants to check for breaking changes, missing tests, or missing documentation, or other problems in the downstream providers.
| name | tgc-fix-handwritten-resources-tests-skill |
| description | Fix integration tests for handwritten resources in TGC. Use when you need to fix integration tests for TGC. |
When you need to fix integration tests for handwritten resources in TGC, use this skill.
When troubleshooting and resolving test failures, adhere to these constraints:
mmv1/api/resource.go to hardcode or manually append ignored fields for tests. If there is a field path mapping mismatch (e.g., due to singular/plural name differences), rename the property name in the resource YAML configuration (e.g., Instance.yaml) and use api_name to map it to the API field name.mmv1/third_party/terraform. All changes must be localized to TGC Next code under mmv1/third_party/tgc_next/.mmv1/third_party/cai2hcl or mmv1/third_party/tgc. All changes must be made to TGC Next code in mmv1/third_party/tgc_next/.When adding or fixing tests for a resource, ensure that the handwritten test files in mmv1/third_party/terraform/services/<product>/ follow the expected naming convention: resource_<product>_<resource_name>_test.go.
If the file name does not match (e.g., it uses a legacy name or has extra suffixes), the generator function addTestsFromHandwrittenTests will fail to find it and will log a message like no handwritten test file found for <resource>.
Solution: Rename the file to match the expected convention so the generator can discover it and include its tests in the generated TGC test suite.
Failing Test: TestAccContainerCluster_auto_ipam_config_enabled_step3_roundtrip.tf
The test might fail during the evaluation of the terraform plan phase with an error indicating a missing argument inside a generated block, such as:
Error: Missing required argument
The argument "enabled" is required, but no definition was found in auto_ipam_config.
If a boolean or zero-value field (e.g., enabled = false) is silently omitted during the API export process, it can cause Terraform to fail with missing required fields (e.g., returning an empty block auto_ipam_config {} instead of auto_ipam_config { enabled = false }).
Solution: To fix issues where zero-value boolean fields are omitted:
ForceSendFields is explicitly specified in the expander function (e.g., expandAutoIpamConfig), so that the converted CAI asset in roundtrip.json includes the zero value (e.g., enabled: false). For example, add ForceSendFields: []string{"Enabled"} to ensure the 0-value is not dropped by the Go omitempty JSON struct tag.After adding these, rebuild TGC and run the respective integration test to verify the fix.
TestAccContainerCluster_withLoggingConfig.tf
The test might fail during the evaluation of terraform plan phase with the following error:
expected pod_autoscaling.0.hpa_profile to be one of ["NONE" "PERFORMANCE"], got HPA_PROFILE_UNSPECIFIED
The underlying issue is that the CAI export contains a default/unspecified enumeration value (HPA_PROFILE_UNSPECIFIED) that Terraform's internal schema explicitly forbids.
Solution: To fix issues where an unspecified enum fails Terraform validation:
cai2hcl.go flattener (e.g., flattenPodAutoscaling). When the underlying map value matches an unspecified enum value (or is an empty string), discard the block entirely by returning nil. This correctly implies the default absent state back into the HCL config block mapping.When user provides no terraform configuration or supplies a completely empty block for a struct that expects a CAI enum (like HpaProfile expecting HPA_PROFILE_UNSPECIFIED rather than nil), it may produce missing field differences in the asset verification checks.
Solution:
nil or empty. If so, return a new struct with the correct default CAI enum explicitly assigned (e.g. &container.PodAutoscaling{HpaProfile: "HPA_PROFILE_UNSPECIFIED"}) rather than directly returning nil. This forces the proper default to be populated into the CAI export payload generated by TGC.TestAccContainerCluster_withCostManagementConfig.tf
The test might fail during the evaluation of terraform plan phase with the following error:
Error: Missing required argument "enabled" in cost_management_config
The underlying issue is that the CAI-to-HCL flattener was generating an empty block (e.g., cost_management_config {}) instead of properly defaulting the required fields or omitting the block. Since enabled is a required attribute within cost_management_config in the Terraform schema, generating an empty block triggers schema validation errors.
Solution: To fix issues where a nested block requires a specific field value to pass validation when generated without explicit data:
cai2hcl.go flattener (e.g., flattenManagementConfig). Instead of returning an empty map when the CAI asset lacks the fields, explicitly default the required attributes to their default values (e.g., set enabled to false). This ensures the emitted HCL block meets schema requirements natively.costManagementConfig: {}) instead of omitting the field entirely. The expander (e.g., expandCostManagementConfig) must return a pointer to an empty struct (&container.CostManagementConfig{}) rather than nil when the user configuration block is absent or disabled. This ensures structural equality in roundtrip.json tests.Failing Test: TestAccContainerCluster_withAuthenticatorGroupsConfig.tf
The test might fail during the evaluation of terraform plan phase with the following error:
Error: Missing required argument
The argument "security_group" is required, but no definition was found.
The underlying issue is that the user specified an empty string for a required field (e.g. security_group = "") in a nested block. During the CAI export, this empty string may be dropped by the omitempty JSON tag, causing the flattener to interpret the field as missing completely rather than as an empty string. This generates an empty block {} which fails schema validation for the required field.
Solution: To fix issues where required fields are dropped because they are empty strings:
cai2hcl.go flattener (e.g., flattenAuthenticatorGroupsConfig). Check if the payload contains the field; if not, explicitly fall back to an empty string "" instead of returning a missing value map. This correctly satisfies the Required: true HCL schema.Failing Test: TestAccContainerCluster_withAddons
The test might fail during the test framework's asset assertions with an error:
error when converting the export assets into export config: &errors.errorString{s:"error unmarshaling JSON as cty.Value: unsupported attribute \"slice_controller_config\""}
This error occurs when the CAI-to-HCL flattener correctly exports a nested field (e.g., slice_controller_config), but the associated exact Terraform schema block is missing from the downstream terraform-google-conversion generated codebase. When the framework attempts to decode the output JSON into a cty.Value to verify matches against the TF plan, it fails to recognize the exported attribute because the schema is stale or incomplete.
Solution:
To fix unsupported attribute unmarshaling errors for newly mapped CAI fields:
mmv1/third_party/tgc_next/pkg/services/container/resource_container_cluster.go or mmv1/products/...) and ensure the new attribute block is declared structurally within its parent schema type definition map.mmv1 directory!
make tgc OUTPUT_PATH="/path/to/downstream/terraform-google-conversion"
make mod-clean && make build) and re-run the integration test.Failing Test: TestAccContainerCluster_withReleaseChannelEnabled.tf
The test might fail during the evaluation phase with the following error:
TestAccContainerCluster_withReleaseChannelEnabled_step3: missing fields in resource google_container_cluster.with_release_channel after cai2hcl conversion:
[release_channel.channel]
The underlying issue is that the GKE API considers UNSPECIFIED as the zero state for releaseChannel.channel and omits it entirely from the JSON response. When the field is omitted, the CAI asset contains an empty map {}. If the flattener checks if c, ok := v.(map[string]interface{}); ok && c["channel"] != "", the missing key evaluates to nil. In Go, interface{}(nil) != interface{}("") evaluates to true. This incorrectly maps a nil back into the HCL configuration, which eventually drops during map serialization, causing a missing field discrepancy.
Solution:
To fix missing fields errors caused by nil map values bypassing string interface comparisons:
cai2hcl.go flattener (e.g., flattenReleaseChannel) to explicitly perform a string type assertion (if ch, ok := c["channel"].(string); ok && ch != "") before assignment. This forces missing or non-string configurations to properly fallback to the default HCL value (e.g., "UNSPECIFIED").{}) for the zero-state (like releaseChannel: {} when "UNSPECIFIED"), ensure the expander matches this behavior. Configure the expander (e.g., expandReleaseChannel) to return an empty struct pointer (&container.ReleaseChannel{}) when the zero-state is detected. Because internal fields like Channel use the omitempty JSON tag, the empty struct will correctly serialize into an empty JSON object ({}), ensuring the tfplan2cai roundtrip payload perfectly matches the upstream cai2hcl conversion output.Failing Test: TestAccContainerCluster_deleteExclusionWindow.tf
The test might fail during the evaluation of the terraform plan phase against the generated output with an error indicating an attribute cannot be explicitly set:
Error: Value for unconfigurable attribute
Can't configure a value for "maintenance_policy.0.daily_maintenance_window.0.duration": its value will be decided automatically based on the result of applying this configuration.
The underlying issue is that the Terraform schema defines the attribute (e.g. duration) strictly as Computed: true (read-only output from the API). Because it is generated dynamically by the upstream API, Terraform forbids explicitly defining or configuring it within .tf blocks. However, during the cai2hcl conversion mapping process, the flattener unconditionally exported the duration value from the CAI asset into the generated struct, populating an unconfigurable field and triggering schema validation rejection.
Solution: To fix validation errors caused by unconfigurable computed attributes being populated in HCL maps:
flattenMaintenancePolicy). Find where the nested properties are assigned from the API map into the transformed JSON equivalent. Surgically omit mapping the offending Computed attribute (e.g. duration). By mapping only the configurable fields (e.g., start_time), Terraform gracefully allows the implicitly computed value to pass without complaining about manually configured read-only attributes.Failing Test: Multiple generated resources mapping to the same API endpoints
The TGC code generation loops through all known CAI endpoints to match a converted asset back to a single unique HCL block name. Previously, it searched for a single strictly unique IdentityParam string segment (e.g. "global" or "projects"). When multiple resources within a group (e.g. compute.googleapis.com/FirewallPolicy) shared these single unique segments (_region_network_firewall_policy has "projects", and _firewall_policy has "global"), the deterministic identifier fallback misclassified the asset resource type.
Solution: To fix CAI mapping collisions between similar resources:
IdentityParams slice. Instead of identifying a single unique segment, removeSharedElements strips common URL components across a product, leaving all remaining distinct parameters. The generator natively evaluates all segments concurrently (e.g. contains(projects) && contains(global)), resulting in perfect multi-parameter exact-path checking for highly nested collision-prone resources.When a field is reported as missing or failing in a handwritten resource's integration test, you must follow this strict logical order of operations rather than immediately marking it as ignored:
tgc_next handwritten Go files (e.g., node_config.go) to see if the schema, flattener, and expander for the missing field are already implemented.
d.GetOk("field")).
is_missing_in_cai: true to the MM YAML (e.g., NodePool.yaml) to gracefully bypass validation.is_missing_in_cai: true.
This ensures that the validation framework gracefully ignores the CAI-level API omission during testing, while still allowing your Go-level conversion code (schema, flattener, and expander) to execute normally when properties are converted.[!TIP] GKE CAI Parity Warning: When dealing with nested configuration blocks shared between parent resources (like GKE Cluster) and standalone child resources (like GKE NodePool), do not assume their API CAI exporters share the same level of parity. For example, while GKE Clusters return
crashLoopBackOffin CAI, the standalone GKE NodePool CAI asset (container.googleapis.com/NodePool) has a permanent omission and never returnscrashLoopBackOff. Always verify target CAI asset types specifically.
Failing Test: TestAccComputeInstance_schedulingTerminationTime
The test fails during the CAI-to-HCL validation check because of a missing field:
TestAccComputeInstance_schedulingTerminationTime_step1: Failed after 5 attempts. First real error: retryable: missing fields: [scheduling.termination_time]
Analysis:
TestAccComputeInstance_schedulingTerminationTime_step1.json). If the property (terminationTime) is present in the CAI payload, it is NOT missing from CAI. Thus, is_missing_in_cai: true must NOT be used.google_compute_instance), look at the custom conversion files (e.g., compute_instance_cai2hcl.go). If the property flattener is missing the mapping code, the property won't be written to the exported HCL.Solution:
flattenSchedulingTgcNext). Add Go code to extract the value from the CAI response map and write it to the HCL schema map:
if tt, ok := resp["terminationTime"].(string); ok && tt != "" {
schedulingMap["termination_time"] = tt
}