microsoft/schema-model-generator
Given a Go SDK contract (DTOs), generate the corresponding Terraform schema attributes and model structs with high fidelity. USE FOR: creating schema_*.go and models.go files from SDK DTOs, mapping Go types to Terraform attribute types and custom types.
npx skills add https://github.com/microsoft/terraform-provider-fabric --skill schema-model-generator
Given a Go SDK contract (DTOs), generate the corresponding Terraform schema attributes and model structs with high fidelity.
#skill:sdk-contract-navigator)[]Type or *Typeset() methodsupertypes.ListNestedObjectValueOf (nested objects) vs supertypes.ListValueOf (scalars) vs supertypes.SingleNestedObjectValueOf (optional nested)For each field in the SDK DTO struct, determine its category using the "Attribute Behaviors" table in .github/instructions/schema-model-patterns.instructions.md.
Classification criteria:
| Category | Criterion |
| ------------------------- | -------------------------------------------------- |
| Read-only | Only appears in Get response Properties struct |
| Create-time-only | Appears in CreationPayload and cannot be updated |
| Updatable required | User must provide, can be changed after create |
| Updatable optional | User may provide, can be changed after create |
| Optional with default | Server sets a default if not provided |
Map each SDK field type to the corresponding Terraform model type using the "SDK Type → Model Type Mapping" table in .github/instructions/schema-model-patterns.instructions.md.
Every field must have a tfsdk:"<snake_case_name>" tag.
<item><purpose>Model — e.g. lakehousePropertiesModel, lakehouseConfigurationModel<item><nested>Model — e.g. lakehouseSQLEndpointPropertiesModeltfsdk:"snake_case" tagOneLakeFilesPath → onelake_files_pathtype lakehousePropertiesModel struct {
OneLakeFilesPath types.String `tfsdk:"onelake_files_path"`
OneLakeTablesPath types.String `tfsdk:"onelake_tables_path"`
SQLEndpointProperties supertypes.SingleNestedObjectValueOf[lakehouseSQLEndpointPropertiesModel] `tfsdk:"sql_endpoint_properties"`
DefaultSchema types.String `tfsdk:"default_schema"`
}
type lakehouseConfigurationModel struct {
EnableSchemas types.Bool `tfsdk:"enable_schemas"`
}
type lakehouseSQLEndpointPropertiesModel struct {
ID customtypes.UUID `tfsdk:"id"`
ConnectionString types.String `tfsdk:"connection_string"`
ProvisioningStatus types.String `tfsdk:"provisioning_status"`
}
Generate both directions of mapping: response set() (SDK → TF) and request builders (TF → SDK).
set() — SDK → TF (both Fabric Items and non-items)Every model struct needs a set() method that maps SDK response DTO → TF model.
Top-level set() (with nested objects):
Signature includes context.Context and returns diag.Diagnostics:
func (to *<item>PropertiesModel) set(ctx context.Context, from fab<package>.<DTO>) diag.Diagnostics {
to.SimpleField = types.StringPointerValue(from.SimpleField)
// ... other simple fields
// Handle nested struct
nestedValue := supertypes.NewSingleNestedObjectValueOfNull[<nestedModel>](ctx)
if from.NestedField != nil {
nestedModel := &<nestedModel>{}
nestedModel.set(*from.NestedField) // or with ctx if nested has its own nested
if diags := nestedValue.Set(ctx, nestedModel); diags.HasError() {
return diags
}
}
to.NestedField = nestedValue
return nil
}
Leaf set() (no nested objects):
Simpler signature without context.Context or diag.Diagnostics:
func (to *<nestedModel>) set(from fab<package>.<NestedDTO>) {
to.ID = customtypes.NewUUIDPointerValue(from.ID)
to.StringField = types.StringPointerValue(from.StringField)
to.EnumField = types.StringPointerValue((*string)(from.EnumField))
}
Setter patterns by type: Use the "Setter Pattern" column in the "SDK Type → Model Type Mapping" table in schema-model-patterns.instructions.md.
Both Fabric Items and non-items need TF→SDK mapping for writable fields. The pattern differs by category:
creationPayloadSetter closure (simple — typically 1-3 fields from configuration model). See fabric-item-patterns.instructions.md § "Closure Examples".set() method that builds the SDK request directly (complex — full request DTOs)Non-item request builder struct — embeds the SDK request type, set() populates it:
type requestCreate<Type> struct {
fabcore.Create<Type>Request // embedded SDK request type
}
func (to *requestCreate<Type>) set(ctx context.Context, from <type>ResourceModel) diag.Diagnostics {
to.DisplayName = from.DisplayName.ValueStringPointer()
to.Description = from.Description.ValueStringPointer()
// ... map each writable field into the embedded struct
return nil
}
Usage: r.client.Create<Type>(ctx, reqCreate.Create<Type>Request, nil)
Inverse mapping rules: Use the inverse of the "SDK Type → Model Type Mapping" table in schema-model-patterns.instructions.md. For each TF type, call its Value*Pointer() method (e.g., types.String → .ValueStringPointer(), types.Bool → .ValueBoolPointer()).
Non-obvious cases:
| TF Model Type | SDK Type | Pattern |
| ----------------------------------------- | ------------- | ------------------------------------------------------------------ |
| types.Int64 | *int32 | ptr.To(int32(from.Field.ValueInt64())) — type narrowing required |
| supertypes.SingleNestedObjectValueOf[M] | *NestedDTO | .Get(ctx) → construct nested DTO from sub-model |
| supertypes.ListNestedObjectValueOf[M] | []NestedDTO | .Get(ctx) → iterate slice, build each DTO |
Reference: internal/services/connection/models_resource_connection.go
For Fabric Item resources, schema attributes go in separate functions:
// schema_resource_<item>.go
func getResource<Item>PropertiesAttributes(ctx context.Context) map[string]schema.Attribute {
return map[string]schema.Attribute{
"<field_name>": schema.StringAttribute{
MarkdownDescription: "<description>.",
Computed: true,
},
// ... more attributes
}
}
func getResource<Item>ConfigurationAttributes() map[string]schema.Attribute {
return map[string]schema.Attribute{
"<field_name>": schema.BoolAttribute{
MarkdownDescription: "<description>.",
Required: true,
PlanModifiers: []planmodifier.Bool{
boolplanmodifier.RequiresReplace(),
},
},
}
}
Use the "SDK Type → Schema Mapping" table in .github/instructions/schema-model-patterns.instructions.md.
For attribute behavior flags, plan modifiers, and validators, refer to the "Attribute Behaviors", "Plan Modifiers", and "Validators" sections in .github/instructions/schema-model-patterns.instructions.md.
Additional rules:
MarkdownDescription (never Description)CustomType: supertypes.NewSingleNestedObjectTypeOf<model>CustomType: customtypes.UUIDType{}"sql_endpoint_properties": schema.SingleNestedAttribute{
MarkdownDescription: "An object containing the properties of the SQL endpoint.",
Computed: true,
CustomType: supertypes.NewSingleNestedObjectTypeOf[lakehouseSQLEndpointPropertiesModel](ctx),
Attributes: map[string]schema.Attribute{
"provisioning_status": schema.StringAttribute{
MarkdownDescription: "The SQL endpoint provisioning status.",
Computed: true,
},
"connection_string": schema.StringAttribute{
MarkdownDescription: "SQL endpoint connection string.",
Computed: true,
},
"id": schema.StringAttribute{
MarkdownDescription: "SQL endpoint ID.",
Computed: true,
CustomType: customtypes.UUIDType{},
},
},
},
internal/services/lakehouse/models.gointernal/services/lakehouse/schema_resource_lakehouse.gointernal/services/lakehouse/schema_data_lakehouse.gointernal/services/connection/schema.gointernal/services/connection/models_resource_connection.goTake microsoft/schema-model-generator from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.