diff --git a/mmv1/api/type.go b/mmv1/api/type.go index df9ab2c3e161..b3923f1181fc 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -16,7 +16,6 @@ package api import ( "fmt" "log" - "reflect" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" @@ -135,9 +134,15 @@ type Type struct { EnumValues []string `yaml:"enum_values"` + // ==================== + // Array Fields + // ==================== ItemType *Type `yaml:"item_type"` + MinSize int `yaml:"min_size"` + MaxSize int `yaml:"max_size"` Resource string + Imports string // ==================== // Terraform Overrides @@ -190,6 +195,22 @@ type Type struct { // For a TypeMap, the DSF to apply to the key. KeyDiffSuppressFunc string `yaml:"key_diff_suppress_func"` + // ==================== + // Map Fields + // ==================== + // The type definition of the contents of the map. + ValueType *Type `yaml:"value_type"` + + // While the API doesn't give keys an explicit name, we specify one + // because in Terraform the key has to be a property of the object. + // + // The name of the key. Used in the Terraform schema as a field name. + KeyName string `yaml:"key_name` + + // A description of the key's format. Used in Terraform to describe + // the field in documentation. + KeyDescription string `yaml:"key_description` + // ==================== // Schema Modifications // ==================== @@ -313,7 +334,7 @@ const MAX_NAME = 20 // and at some points in the build this doesn't output a valid output. // def lineage -func (t *Type) Lineage() string { +func (t Type) Lineage() string { if t.ParentMetadata == nil { return google.Underscore(t.Name) } @@ -324,10 +345,13 @@ func (t *Type) Lineage() string { // Prints the access path of the field in the configration eg: metadata.0.labels // The only intended purpose is to get the value of the labes field by calling d.Get(). // func (t *Type) terraform_lineage() { -// return name&.underscore if __parent.nil? || __parent.flatten_object +func (t Type) TerraformLineage() string { + if t.ParentMetadata == nil || t.ParentMetadata.FlattenObject { + return google.Underscore(t.Name) + } -// "//{__parent.terraform_lineage}.0.//{name&.underscore}" -// } + return fmt.Sprintf("%s.0.%s", t.ParentMetadata.TerraformLineage(), google.Underscore(t.Name)) +} // func (t *Type) to_json(opts) { // ignore fields that will contain references to parent resources and @@ -394,10 +418,13 @@ func (t *Type) Lineage() string { // Returns list of properties that are in conflict with this property. // func (t *Type) conflicting() { -// return [] unless @__resource +func (t Type) Conflicting() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @conflicts -// } + return t.Conflicts +} // Checks that all properties that needs at least one of their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -410,10 +437,13 @@ func (t *Type) Lineage() string { // Returns list of properties that needs at least one of their fields set. // func (t *Type) at_least_one_of_list() { -// return [] unless @__resource +func (t Type) AtLeastOneOfList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @at_least_one_of -// } + return t.AtLeastOneOf +} // Checks that all properties that needs exactly one of their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -426,10 +456,13 @@ func (t *Type) Lineage() string { // Returns list of properties that needs exactly one of their fields set. // func (t *Type) exactly_one_of_list() { -// return [] unless @__resource +func (t Type) ExactlyOneOfList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @exactly_one_of -// } + return t.ExactlyOneOf +} // Checks that all properties that needs required with their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -442,21 +475,20 @@ func (t *Type) Lineage() string { // Returns list of properties that needs required with their fields set. // func (t *Type) required_with_list() { -// // return [] unless @__resource - -// // @required_with -// } +func (t Type) RequiredWithList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// func (t *Type) type() { -// // self.class.name.split('::').last -// } + return t.RequiredWith +} -// func (t *Type) parent() { -// // @__parent -// } +func (t Type) Parent() *Type { + return t.ParentMetadata +} // def min_version -func (t *Type) MinVersionObj() *product.Version { +func (t Type) MinVersionObj() *product.Version { if t.MinVersion != "" { return t.ResourceMetadata.ProductMetadata.versionObj(t.MinVersion) } else { @@ -484,6 +516,14 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { t.Exclude = version.CompareTo(t.MinVersionObj()) < 0 } } + + if t.IsA("NestedObject") { + for _, p := range t.Properties { + p.ExcludeIfNotInVersion(version) + } + } else if t.IsA("Array") && t.ItemType.IsA("NestedObject") { + t.ItemType.ExcludeIfNotInVersion(version) + } } // Overriding is_a? to enable class overrides. @@ -492,7 +532,7 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // TODO Q1: check the type of superclasses of property t // func (t *Type) is_a?(clazz) { -func (t *Type) IsA(clazz string) bool { +func (t Type) IsA(clazz string) bool { if clazz == "" { log.Fatalf("class cannot be empty") } @@ -501,7 +541,7 @@ func (t *Type) IsA(clazz string) bool { return t.NewType == clazz } - return reflect.TypeOf(t).Name() == fmt.Sprintf("main.%s", clazz) + return t.Type == clazz // super(clazz) } @@ -514,13 +554,38 @@ func (t *Type) IsA(clazz string) bool { // // super // } -// func (t *Type) removed() { -// // !(@removed_message.nil? || @removed_message == '') -// } +// Returns nested properties for this property. +// def nested_properties +func (t Type) NestedProperties() []*Type { + props := make([]*Type, 0) -// func (t *Type) deprecated() { -// // !(@deprecation_message.nil? || @deprecation_message == '') -// } + switch { + case t.IsA("Array"): + if t.ItemType.IsA("NestedObject") { + props = google.Reject(t.ItemType.NestedProperties(), func(p *Type) bool { + return t.Exclude + }) + } + case t.IsA("NestedObject"): + props = t.UserProperties() + case t.IsA("Map"): + props = google.Reject(t.ValueType.NestedProperties(), func(p *Type) bool { + return t.Exclude + }) + default: + } + return props +} + +// def removed? +func (t Type) Removed() bool { + return t.RemovedMessage != "" +} + +// def deprecated? +func (t Type) Deprecated() bool { + return t.DeprecationMessage != "" +} // // private @@ -632,20 +697,6 @@ func (t *Type) IsA(clazz string) bool { // check :max_size, type: ::Integer // end -// func (t *Type) property_class -// case @item_type -// when NestedObject, ResourceRef -// type = @item_type.property_class -// when Enum -// raise 'aaaa' -// else -// type = property_ns_prefix -// type << get_type(@item_type).new(@name).type -// end -// type[-1] = "//{type[-1].camelize(:upper)}Array" -// type -// end - // func (t *Type) exclude_if_not_in_version!(version) // super // @item_type.exclude_if_not_in_version!(version) \ @@ -659,13 +710,15 @@ func (t *Type) IsA(clazz string) bool { // super // end -// func (t *Type) item_type_class -// return @item_type \ -// if @item_type.instance_of?(Class) +// This function is for array field +// def item_type_class +func (t Type) ItemTypeClass() string { + if !t.IsA("Array") { + return "" + } -// Object.const_get(@item_type) -// end -// end + return t.ItemType.Type +} // // Represents an enum, and store is valid values // class Enum < Primitive @@ -738,14 +791,12 @@ func (t *Type) IsA(clazz string) bool { // check_resource_ref_property_exists // end -// func (t *Type) property -// props = resource_ref.all_user_properties -// .select { |prop| prop.name == @imports } -// return props.first unless props.empty? -// end - // func (t *Type) resource_ref -func (t *Type) ResourceRef() *Resource { +func (t Type) ResourceRef() *Resource { + if !t.IsA("ResourceRef") { + return nil + } + product := t.ResourceMetadata.ProductMetadata resources := google.Select(product.Objects, func(obj *Resource) bool { return obj.Name == t.Resource @@ -754,13 +805,6 @@ func (t *Type) ResourceRef() *Resource { return resources[0] } -// func (t *Type) property_class -// type = property_ns_prefix -// type << [@resource, @imports, 'Ref'] -// type[-1] = type[-1].join('_').camelize(:upper) -// type -// end - // private // func (t *Type) check_resource_ref_property_exists @@ -791,33 +835,25 @@ func (t *Type) ResourceRef() *Resource { // check :properties, type: ::Array, item_type: Api::Type, required: true // end -// func (t *Type) property_class -// type = property_ns_prefix -// type << [@__resource.name, @name] -// type[-1] = type[-1].join('_').camelize(:upper) -// type -// end - -// // Returns all properties including the ones that are excluded -// // This is used for PropertyOverride validation -// func (t *Type) all_properties -// @properties -// end +// Returns all properties including the ones that are excluded +// This is used for PropertyOverride validation +// def all_properties +func (t Type) AllProperties() []*Type { + return t.Properties +} // func (t *Type) properties -func (t *Type) UserProperties() []*Type { - if t.Properties == nil { - log.Fatalf("Field '{%s}' properties are nil!", t.Lineage()) - } - - return google.Reject(t.Properties, func(p *Type) bool { - return p.Exclude - }) -} +func (t Type) UserProperties() []*Type { + if t.IsA("NestedObject") { + if t.Properties == nil { + log.Fatalf("Field '{%s}' properties are nil!", t.Lineage()) + } -// func (t *Type) nested_properties -func (t *Type) NestedProperties() []*Type { - return t.UserProperties() + return google.Reject(t.Properties, func(p *Type) bool { + return p.Exclude + }) + } + return nil } // Returns the list of top-level properties once any nested objects with @@ -1010,11 +1046,11 @@ func (t *Type) RootProperties() []*Type { // Module.const_get(type) // end -// func (t *Type) property_ns_prefix -// [ -// 'Google', -// @__resource.__product.name.camelize(:upper), -// 'Property' -// ] -// end -// end +// def property_ns_prefix +func (t Type) PropertyNsPrefix() []string { + return []string{ + "Google", + google.Camelize(t.ResourceMetadata.ProductMetadata.Name, "upper"), + "Property", + } +} diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index 291c03053af0..9bac441c0cc5 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -566,20 +566,6 @@ def validate check :max_size, type: ::Integer end - def property_class - case @item_type - when NestedObject, ResourceRef - type = @item_type.property_class - when Enum - raise 'aaaa' - else - type = property_ns_prefix - type << get_type(@item_type).new(@name).type - end - type[-1] = "#{type[-1].camelize(:upper)}Array" - type - end - def exclude_if_not_in_version!(version) super @item_type.exclude_if_not_in_version!(version) \ @@ -657,12 +643,6 @@ def validate check_resource_ref_property_exists end - def property - props = resource_ref.all_user_properties - .select { |prop| prop.name == @imports } - return props.first unless props.empty? - end - def resource_ref product = @__resource.__product resources = product.objects.select { |obj| obj.name == @resource } @@ -670,13 +650,6 @@ def resource_ref resources[0] end - def property_class - type = property_ns_prefix - type << [@resource, @imports, 'Ref'] - type[-1] = type[-1].join('_').camelize(:upper) - type - end - private def check_resource_ref_property_exists @@ -708,13 +681,6 @@ def validate check :properties, type: ::Array, item_type: Api::Type, required: true end - def property_class - type = property_ns_prefix - type << [@__resource.name, @name] - type[-1] = type[-1].join('_').camelize(:upper) - type - end - # Returns all properties including the ones that are excluded # This is used for PropertyOverride validation def all_properties