diff --git a/generate/generate.go b/generate/generate.go index ba43aa4711..a43af84eb3 100644 --- a/generate/generate.go +++ b/generate/generate.go @@ -556,7 +556,9 @@ func generatePolymorphicProperty(typename string, name string, property Property types := append([]string{}, property.PrimitiveTypes...) types = append(types, property.PrimitiveItemTypes...) + types = append(types, property.InclusivePrimitiveItemTypes...) types = append(types, property.ItemTypes...) + types = append(types, property.InclusiveItemTypes...) types = append(types, property.Types...) packageName, err := packageName(typename, true) diff --git a/generate/property.go b/generate/property.go index f5c06b49c3..74bb587f61 100644 --- a/generate/property.go +++ b/generate/property.go @@ -88,6 +88,24 @@ type Property struct { // resource type documentation. UpdateType string `json:"UpdateType"` + // InclusivePrimitiveItemTypes - items of an array that must be grouped together with other InclusivePrimitiveItemTypes + // and InclusiveItemTypes. If the value of the Type field is List or Map, indicates the type of list or map + // if they contain primitive types. Otherwise, this field is omitted. Valid types are the same as primitive item + // types String, Long, Integer, Double, Boolean, or Timestamp. + // + // This will allow a single array to contain multiple item types rather than one type per array instance + InclusivePrimitiveItemTypes []string `json:"InclusivePrimitiveItemTypes"` + + // InclusiveItemTypes - items of an array that must be grouped together with other InclusiveItemTypes + // and InclusivePrimitiveItemTypes. If the value of the Type field is List or Map, indicates the type of list or + // map if they contain non-primitive types. Otherwise, this field is omitted. + // + // A subproperty name is a valid item type. For example, if the type value is List and the item type + // value is PortMapping, you can specify a list of port mapping properties. + // + // This will allow a single array to contain multiple item types rather than one type per array instance + InclusiveItemTypes []string `json:"InclusiveItemTypes"` + // Types - if a property can be different types, they will be listed here PrimitiveTypes []string `json:"PrimitiveTypes"` PrimitiveItemTypes []string `json:"PrimitiveItemTypes"` @@ -185,7 +203,13 @@ func (p Property) HasValidType() bool { // IsPolymorphic checks whether a property can be multiple different types func (p Property) IsPolymorphic() bool { - return len(p.PrimitiveTypes) > 0 || len(p.PrimitiveItemTypes) > 0 || len(p.PrimitiveItemTypes) > 0 || len(p.ItemTypes) > 0 || len(p.Types) > 0 + return len(p.PrimitiveTypes) > 0 || + len(p.PrimitiveItemTypes) > 0 || + len(p.PrimitiveItemTypes) > 0 || + len(p.ItemTypes) > 0 || + len(p.Types) > 0 || + len(p.InclusivePrimitiveItemTypes) > 0 || + len(p.InclusiveItemTypes) > 0 } // IsPrimitive checks whether a property is a primitive type diff --git a/generate/sam-2016-10-31.json b/generate/sam-2016-10-31.json index a1bee8548e..26109ff54d 100644 --- a/generate/sam-2016-10-31.json +++ b/generate/sam-2016-10-31.json @@ -117,13 +117,13 @@ "PrimitiveTypes": [ "String" ], - "PrimitiveItemTypes": [ - "String" - ], "Types": [ "IAMPolicyDocument" ], - "ItemTypes": [ + "InclusivePrimitiveItemTypes": [ + "String" + ], + "InclusiveItemTypes": [ "IAMPolicyDocument", "SAMPolicyTemplate" ], @@ -705,13 +705,13 @@ "PrimitiveTypes": [ "String" ], - "PrimitiveItemTypes": [ - "String" - ], "Types": [ "IAMPolicyDocument" ], - "ItemTypes": [ + "InclusivePrimitiveItemTypes": [ + "String" + ], + "InclusiveItemTypes": [ "IAMPolicyDocument", "SAMPolicyTemplate" ], diff --git a/generate/templates/polymorphic-property.template b/generate/templates/polymorphic-property.template index c386f0023a..212e1601c5 100644 --- a/generate/templates/polymorphic-property.template +++ b/generate/templates/polymorphic-property.template @@ -19,11 +19,17 @@ type {{.Name}} struct { {{range $type := $.Property.PrimitiveItemTypes}} {{$type}}Array *[]{{convertToGoType $type}}{{end}} + {{range $type := $.Property.InclusivePrimitiveItemTypes}} + {{$type}}Array *[]{{convertToGoType $type}}{{end}} + {{range $type := $.Property.Types}} {{$type}} *{{$.Basename}}_{{$type}}{{end}} {{range $type := $.Property.ItemTypes}} {{$type}}Array *[]{{$.Basename}}_{{$type}}{{end}} + + {{range $type := $.Property.InclusiveItemTypes}} + {{$type}}Array *[]{{$.Basename}}_{{$type}}{{end}} } func (r {{.Name}}) value() interface{} { @@ -41,6 +47,12 @@ func (r {{.Name}}) value() interface{} { } {{end}} + {{range $type := $.Property.InclusivePrimitiveItemTypes}} + if r.{{$type}}Array != nil { + ret = append(ret, r.{{$type}}Array) + } + {{end}} + {{ if (.Property.Types) }} {{range $type := $.Property.Types}} if r.{{$type}} != nil { @@ -55,6 +67,12 @@ func (r {{.Name}}) value() interface{} { } {{end}} + {{range $type := $.Property.InclusiveItemTypes}} + if r.{{$type}}Array != nil { + ret = append(ret, r.{{$type}}Array) + } + {{end}} + sort.Sort(utils.ByJSONLength(ret)) // Heuristic to select best attribute if len(ret) > 0 { return ret[0] @@ -88,6 +106,11 @@ func (r *{{.Name}}) UnmarshalJSON(b []byte) error { r.{{$type}}Array = &val {{end}} + {{range $type := $.Property.InclusivePrimitiveItemTypes}} + case []{{convertToGoType $type}}: + r.{{$type}}Array = &val + {{end}} + case map[string]interface{}: val = val // This ensures val is used to stop an error @@ -107,9 +130,15 @@ func (r *{{.Name}}) UnmarshalJSON(b []byte) error { {{range $type := $.Property.PrimitiveItemTypes}} json.Unmarshal(b, &r.{{$type}}Array) {{end}} - {{range $type := $.Property.ItemTypes}} + {{range $type := $.Property.InclusivePrimitiveItemTypes}} json.Unmarshal(b, &r.{{$type}}Array) {{end}} + {{range $type := $.Property.ItemTypes}} + json.Unmarshal(b, &r.{{$type}}Array) + {{end}} + {{range $type := $.Property.InclusiveItemTypes}} + json.Unmarshal(b, &r.{{$type}}Array) + {{end}} } diff --git a/generate/templates/schema-property.template b/generate/templates/schema-property.template index ab2d4bec7d..8d8758943a 100644 --- a/generate/templates/schema-property.template +++ b/generate/templates/schema-property.template @@ -12,6 +12,26 @@ }{{if (or .Property.PrimitiveItemTypes (or .Property.Types .Property.ItemTypes))}},{{end}} {{end}} + {{if (or .Property.InclusivePrimitiveItemTypes .Property.InclusiveItemTypes)}} + { + "type": "array", + "items": { + "anyOf": [ + {{$length := len .Property.InclusivePrimitiveItemTypes}}{{$rc := counter $length}}{{range $index, $primitiveType := .Property.InclusivePrimitiveItemTypes}} + { + "type": "{{convertToJSONType $primitiveType}}"{{if call $rc}},{{end}} + }{{if $.Property.InclusiveItemTypes}},{{end}} + {{end}} + {{$length := len .Property.InclusiveItemTypes}}{{$rc := counter $length}}{{range $index, $itemType := .Property.InclusiveItemTypes}} + { + "$ref": "#/definitions/{{$.Parent}}.{{$itemType}}" + }{{if call $rc}},{{end}} + {{end}} + ] + } + }{{if (or $.Property.InclusivePrimitiveItemTypes $.Property.InclusiveItemTypes)}},{{end}} + {{end}} + {{if .Property.PrimitiveItemTypes}} {{$length := len .Property.PrimitiveItemTypes}}{{$rc := counter $length}}{{range $index, $primitiveItemType := .Property.PrimitiveItemTypes}} { diff --git a/schema/sam.go b/schema/sam.go index 3b68790922..b64b9791ad 100644 --- a/schema/sam.go +++ b/schema/sam.go @@ -124500,24 +124500,22 @@ var SamSchema = `{ }, { "items": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/AWS::Serverless::Function.IAMPolicyDocument" + }, + { + "$ref": "#/definitions/AWS::Serverless::Function.SAMPolicyTemplate" + } + ] }, "type": "array" }, { "$ref": "#/definitions/AWS::Serverless::Function.IAMPolicyDocument" - }, - { - "items": { - "$ref": "#/definitions/AWS::Serverless::Function.IAMPolicyDocument" - }, - "type": "array" - }, - { - "items": { - "$ref": "#/definitions/AWS::Serverless::Function.SAMPolicyTemplate" - }, - "type": "array" } ] }, @@ -126113,24 +126111,22 @@ var SamSchema = `{ }, { "items": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/AWS::Serverless::StateMachine.IAMPolicyDocument" + }, + { + "$ref": "#/definitions/AWS::Serverless::StateMachine.SAMPolicyTemplate" + } + ] }, "type": "array" }, { "$ref": "#/definitions/AWS::Serverless::StateMachine.IAMPolicyDocument" - }, - { - "items": { - "$ref": "#/definitions/AWS::Serverless::StateMachine.IAMPolicyDocument" - }, - "type": "array" - }, - { - "items": { - "$ref": "#/definitions/AWS::Serverless::StateMachine.SAMPolicyTemplate" - }, - "type": "array" } ] }, diff --git a/schema/sam.schema.json b/schema/sam.schema.json index 8630315e78..2f793f5908 100644 --- a/schema/sam.schema.json +++ b/schema/sam.schema.json @@ -124495,24 +124495,22 @@ }, { "items": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/AWS::Serverless::Function.IAMPolicyDocument" + }, + { + "$ref": "#/definitions/AWS::Serverless::Function.SAMPolicyTemplate" + } + ] }, "type": "array" }, { "$ref": "#/definitions/AWS::Serverless::Function.IAMPolicyDocument" - }, - { - "items": { - "$ref": "#/definitions/AWS::Serverless::Function.IAMPolicyDocument" - }, - "type": "array" - }, - { - "items": { - "$ref": "#/definitions/AWS::Serverless::Function.SAMPolicyTemplate" - }, - "type": "array" } ] }, @@ -126108,24 +126106,22 @@ }, { "items": { - "type": "string" + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/AWS::Serverless::StateMachine.IAMPolicyDocument" + }, + { + "$ref": "#/definitions/AWS::Serverless::StateMachine.SAMPolicyTemplate" + } + ] }, "type": "array" }, { "$ref": "#/definitions/AWS::Serverless::StateMachine.IAMPolicyDocument" - }, - { - "items": { - "$ref": "#/definitions/AWS::Serverless::StateMachine.IAMPolicyDocument" - }, - "type": "array" - }, - { - "items": { - "$ref": "#/definitions/AWS::Serverless::StateMachine.SAMPolicyTemplate" - }, - "type": "array" } ] },