fix: Improve handling of computed fields and attribute types in ResourceGenerator

This commit is contained in:
Simon Larsen
2025-06-26 20:12:10 +01:00
parent 46558d4a77
commit eed5ce6ec9
2 changed files with 24 additions and 19 deletions

View File

@@ -604,15 +604,16 @@ export class OpenAPIParser {
// If field already exists and we're adding computed fields, check if it should be both optional and computed
if (computed && schema[terraformName]) {
// Update description if it's better in the read schema
if (description && !schema[terraformName]?.description) {
schema[terraformName].description = description!;
const existingField = schema[terraformName];
if (existingField && description && !existingField.description) {
existingField.description = description;
}
// If the field exists from create/update and now appears in read,
// it should be marked as both optional and computed (server-managed field)
if (!schema[terraformName]?.required) {
if (existingField && !existingField.required) {
schema[terraformName] = {
...schema[terraformName],
...existingField,
computed: true,
optional: true, // Mark as explicitly optional and computed
};
@@ -624,15 +625,18 @@ export class OpenAPIParser {
if (
!computed &&
schema[terraformName] &&
schema[terraformName].computed
schema[terraformName]?.computed
) {
// Update the existing computed field to also be an input field
schema[terraformName] = {
...schema[terraformName],
required: openApiSchema.required?.includes(propName) || false,
computed: false, // This field can be both input and output
apiFieldName: propName, // Preserve original OpenAPI property name
};
const existingField = schema[terraformName];
if (existingField) {
schema[terraformName] = {
...existingField,
required: openApiSchema.required?.includes(propName) || false,
computed: false, // This field can be both input and output
apiFieldName: propName, // Preserve original OpenAPI property name
};
}
continue;
}

View File

@@ -979,7 +979,8 @@ func (r *${resourceTypeName}Resource) Delete(ctx context.Context, req resource.D
conditionalAssignments.push("");
for (const [name, attr] of Object.entries(updateSchema)) {
if (name === "id" || attr.computed) {
const terraformAttr = attr as TerraformAttribute;
if (name === "id" || terraformAttr.computed) {
continue;
}
@@ -990,25 +991,25 @@ func (r *${resourceTypeName}Resource) Delete(ctx context.Context, req resource.D
const sanitizedName: string = this.sanitizeAttributeName(name);
const fieldName: string = StringUtils.toPascalCase(sanitizedName);
const apiFieldName: string = attr.apiFieldName || name; // Use original OpenAPI field name
const apiFieldName: string = terraformAttr.apiFieldName || name; // Use original OpenAPI field name
// Handle different field types with conditional assignment
if (attr.type === "map") {
if (terraformAttr.type === "map") {
conditionalAssignments.push(
` if !data.${fieldName}.IsNull() {\n requestDataMap["${apiFieldName}"] = r.convertTerraformMapToInterface(data.${fieldName})\n }`,
);
} else if (attr.type === "list") {
} else if (terraformAttr.type === "list") {
conditionalAssignments.push(
` if !data.${fieldName}.IsNull() {\n requestDataMap["${apiFieldName}"] = r.convertTerraformListToInterface(data.${fieldName})\n }`,
);
} else {
const value: string = this.getGoValueForTerraformType(
attr.type,
terraformAttr.type,
`data.${fieldName}`,
);
if (attr.type === "string") {
if (attr.isComplexObject) {
if (terraformAttr.type === "string") {
if (terraformAttr.isComplexObject) {
// For complex object strings, parse JSON and convert to interface{}
conditionalAssignments.push(
` if !data.${fieldName}.IsNull() && data.${fieldName}.ValueString() != "" {\n var ${fieldName.toLowerCase()}Data interface{}\n if err := json.Unmarshal([]byte(data.${fieldName}.ValueString()), &${fieldName.toLowerCase()}Data); err == nil {\n requestDataMap["${apiFieldName}"] = ${fieldName.toLowerCase()}Data\n }\n }`,
@@ -1019,7 +1020,7 @@ func (r *${resourceTypeName}Resource) Delete(ctx context.Context, req resource.D
` if !data.${fieldName}.IsNull() && data.${fieldName}.ValueString() != "" {\n requestDataMap["${apiFieldName}"] = ${value}\n }`,
);
}
} else if (attr.type === "bool") {
} else if (terraformAttr.type === "bool") {
// For booleans, always include since they have meaningful defaults
conditionalAssignments.push(
` requestDataMap["${apiFieldName}"] = ${value}`,