diff --git a/cli/azd/pkg/azure/arm_template.go b/cli/azd/pkg/azure/arm_template.go index 006fcde4848..8890fe73b0f 100644 --- a/cli/azd/pkg/azure/arm_template.go +++ b/cli/azd/pkg/azure/arm_template.go @@ -57,7 +57,7 @@ type ArmTemplateParameterDefinitions map[string]ArmTemplateParameterDefinition type ArmTemplateOutputs map[string]ArmTemplateOutput -type ArmTemplateParameterAdditionalProperties struct { +type ArmTemplateParameterAdditionalPropertiesProperties struct { Type string `json:"type"` MinValue *int `json:"minValue,omitempty"` MaxValue *int `json:"maxValue,omitempty"` @@ -66,18 +66,52 @@ type ArmTemplateParameterAdditionalProperties struct { Metadata map[string]json.RawMessage `json:"metadata"` } +type ArmTemplateParameterAdditionalPropertiesValue struct { + props *ArmTemplateParameterAdditionalPropertiesProperties +} + +func (v ArmTemplateParameterAdditionalPropertiesValue) HasAdditionalProperties() bool { + return v.props != nil +} + +func (v ArmTemplateParameterAdditionalPropertiesValue) Properties() ArmTemplateParameterAdditionalPropertiesProperties { + return *v.props +} + +func (v *ArmTemplateParameterAdditionalPropertiesValue) UnmarshalJSON(data []byte) error { + if string(data) == "false" { + return nil + } + + var props ArmTemplateParameterAdditionalPropertiesProperties + if err := json.Unmarshal(data, &props); err != nil { + return err + } + + v.props = &props + return nil +} + +func (v *ArmTemplateParameterAdditionalPropertiesValue) MarshalJSON() ([]byte, error) { + if v.props == nil { + return []byte("false"), nil + } + + return json.Marshal(v.props) +} + type ArmTemplateParameterDefinition struct { - Type string `json:"type"` - DefaultValue any `json:"defaultValue"` - AllowedValues *[]any `json:"allowedValues,omitempty"` - MinValue *int `json:"minValue,omitempty"` - MaxValue *int `json:"maxValue,omitempty"` - MinLength *int `json:"minLength,omitempty"` - MaxLength *int `json:"maxLength,omitempty"` - Metadata map[string]json.RawMessage `json:"metadata"` - Ref string `json:"$ref"` - Properties ArmTemplateParameterDefinitions `json:"properties,omitempty"` - AdditionalProperties ArmTemplateParameterAdditionalProperties `json:"additionalProperties,omitempty"` + Type string `json:"type"` + DefaultValue any `json:"defaultValue"` + AllowedValues *[]any `json:"allowedValues,omitempty"` + MinValue *int `json:"minValue,omitempty"` + MaxValue *int `json:"maxValue,omitempty"` + MinLength *int `json:"minLength,omitempty"` + MaxLength *int `json:"maxLength,omitempty"` + Metadata map[string]json.RawMessage `json:"metadata"` + Ref string `json:"$ref"` + Properties ArmTemplateParameterDefinitions `json:"properties,omitempty"` + AdditionalProperties *ArmTemplateParameterAdditionalPropertiesValue `json:"additionalProperties,omitempty"` } func (d *ArmTemplateParameterDefinition) Secure() bool { diff --git a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider_test.go b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider_test.go index 0c0d4cff1f6..08928cf3fdb 100644 --- a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider_test.go +++ b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider_test.go @@ -1032,9 +1032,10 @@ func TestUserDefinedTypes(t *testing.T) { }, objectParam.Properties) require.NotNil(t, objectParam.AdditionalProperties) + require.True(t, objectParam.AdditionalProperties.HasAdditionalProperties()) require.Equal( t, - azure.ArmTemplateParameterAdditionalProperties{ + azure.ArmTemplateParameterAdditionalPropertiesProperties{ Type: "string", MinLength: to.Ptr(10), Metadata: map[string]json.RawMessage{ @@ -1042,7 +1043,7 @@ func TestUserDefinedTypes(t *testing.T) { "fromDefinitionBar": []byte(`"bar"`), }, }, - objectParam.AdditionalProperties) + objectParam.AdditionalProperties.Properties()) require.NotNil(t, objectParam.Metadata) require.Equal( t, @@ -1056,6 +1057,21 @@ func TestUserDefinedTypes(t *testing.T) { }, objectParam.Metadata) + sealedObjectParam, exists := template.Parameters["sealedObjectParam"] + require.True(t, exists) + require.Equal(t, "object", sealedObjectParam.Type) + require.Nil(t, sealedObjectParam.AllowedValues) + require.NotNil(t, sealedObjectParam.Properties) + require.Equal( + t, + azure.ArmTemplateParameterDefinitions{ + "name": {Type: "string"}, + "sku": {Type: "string"}, + }, + sealedObjectParam.Properties) + require.NotNil(t, sealedObjectParam.AdditionalProperties) + require.False(t, sealedObjectParam.AdditionalProperties.HasAdditionalProperties()) + // output resolves just the type. Value and Metadata should persist customOutput, exists := template.Outputs["customOutput"] require.True(t, exists) @@ -1211,6 +1227,18 @@ const userDefinedParamsSample = `{ "fromDefinitionFoo": "foo", "fromDefinitionBar": "bar" } + }, + "sealedObjectType": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "sku": { + "type": "string" + } + }, + "additionalProperties": false } }, "parameters": { @@ -1242,6 +1270,9 @@ const userDefinedParamsSample = `{ "fromDefinitionBar": "override", "fromParameter": "parameter" } + }, + "sealedObjectParam": { + "$ref": "#/definitions/sealedObjectType" } }, "resources": {},