with one click
modify-typed-resource
// [AzureRM-specific] Assist in adding a new property to an existing legacy resource (Typed SDK wrapper).
// [AzureRM-specific] Assist in adding a new property to an existing legacy resource (Typed SDK wrapper).
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | modify-typed-resource |
| description | [AzureRM-specific] Assist in adding a new property to an existing legacy resource (Typed SDK wrapper). |
| triggers | ["add property to typed resource","modify typed sdk resource","internal/sdk/resource.go modification"] |
This skill assists in adding a new property to an existing legacy resource that uses the "Typed" SDK wrapper (internal/sdk/resource.go).
A typed resource implements the sdk.Resource interface and typically has a companion *Model struct.
type ExampleResourceModel struct {
// ...
}
type ExampleResource struct{}
[!CAUTION] Remediate Combined Create/Update. If the existing Typed resource currently uses the same
Funcfor bothCreateandUpdate, or shares a helper function (likesubmitorcreateUpdate) between them, you MUST split the logic into discrete, independentCreateandUpdatemethods as part of your modification. Each CRUD method must manage its own client calls and payload construction independently. The Typed wrapper SDK automatically handlesread-after-createandread-after-update, so theFuncshould simply returnnilupon success rather than calling theReadfunction.
Add the field to the model struct with the tfschema tag.
type ExampleResourceModel struct {
// ...
NewProperty string `tfschema:"new_property"`
}
Add the field to either the Arguments() (if user-configurable) or Attributes() (if read-only) method.
func (r ExampleResource) Arguments() map[string]*pluginsdk.Schema {
return map[string]*pluginsdk.Schema{
// ...
"new_property": {
Type: pluginsdk.TypeString,
Optional: true,
},
}
}
Access the property directly from the model after decoding.
func (r ExampleResource) Create() sdk.ResourceFunc {
return sdk.ResourceFunc{
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
var model ExampleResourceModel
if err := metadata.Decode(&model); err != nil {
return err
}
// Use model.NewProperty
},
}
}
In the Update() method, check if the property has changed before including it in the update payload (especially for PATCH operations).
func (r ExampleResource) Update() sdk.ResourceFunc {
return sdk.ResourceFunc{
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
// ...
if metadata.ResourceData.HasChange("new_property") {
// include in patch/update payload
}
},
}
}
Set the property in the state model before encoding.
func (r ExampleResource) Read() sdk.ResourceFunc {
return sdk.ResourceFunc{
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
// ...
state.NewProperty = *apiResponse.NewProperty
return metadata.Encode(&state)
},
}
}
To implement CustomizeDiff on a Typed resource, the resource struct must implement the
sdk.ResourceWithCustomizeDiff interface. Add the compliance assertion and the method:
// Compile-time assertion — add alongside other interface assertions at the top of the file
var _ sdk.ResourceWithCustomizeDiff = ExampleResource{}
func (r ExampleResource) CustomizeDiff() sdk.ResourceFunc {
return sdk.ResourceFunc{
Timeout: 5 * time.Minute,
Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error {
if metadata.ResourceDiff == nil {
return nil
}
var model ExampleResourceModel
if err := metadata.DecodeDiff(&model); err != nil {
return err
}
// logic here
return nil
},
}
}
The SDK wrapper in sdk/wrapper_resource.go automatically detects the interface and wires
up CustomizeDiff — no changes to the resource registration function are needed.
tfschema tag matches the schema key.terraform plan to verify that the new property is correctly tracked in the state.