diff --git a/internal/generate/responses.go b/internal/generate/responses.go index 8507fa1..a749e42 100644 --- a/internal/generate/responses.go +++ b/internal/generate/responses.go @@ -62,7 +62,7 @@ func populateResponseType(name string, r *openapi3.Response) ([]TypeTemplate, [] continue } - tt, et := populateTypeTemplates(respName, s.Value, "") + tt, et := populateTypeTemplates(respName, s.Value, "", "") types = append(types, tt...) enumTypes = append(enumTypes, et...) diff --git a/internal/generate/types.go b/internal/generate/types.go index 3b508b7..59d3e2b 100644 --- a/internal/generate/types.go +++ b/internal/generate/types.go @@ -34,6 +34,25 @@ type TypeTemplate struct { Type string // Fields holds the information for the field Fields []TypeFields + + // DiscriminatorKey is the name of the discriminator key used to determine the type of a complex oneOf field: commonly "type", "kind", etc. + DiscriminatorKey string + // DiscriminatorField + DiscriminatorField string + // DiscriminatorType is the generated type name of the discriminator field, and should be constructed as "{{.OneOfName}}Type": MetricType, ValueArrayType, etc. + DiscriminatorType string + // DiscriminatorMappings maps oneOf enum constant (e.g. DatumTypeBool) to their concrete types (e.g. DatumBool). + DiscriminatorMappings []DiscriminatorMapping + + VariantField string + VariantInterface string +} + +// DiscriminatorMapping maps a discriminator enum value to its concrete type +type DiscriminatorMapping struct { + EnumConstant string // The enum constant to match in switch (e.g., "DatumTypeBool") + ConcreteType string // The concrete type to unmarshal into (e.g., "DatumBool") + ObjectType string } // TypeFields holds the information for each type field @@ -256,7 +275,7 @@ func constructTypes(schemas openapi3.Schemas) ([]TypeTemplate, []EnumTemplate) { // Set name as a valid Go type name name = strcase.ToCamel(name) - typeTpl, enumTpl := populateTypeTemplates(name, s.Value, "") + typeTpl, enumTpl := populateTypeTemplates(name, s.Value, "", "") typeCollection = append(typeCollection, typeTpl...) enumCollection = append(enumCollection, enumTpl...) } @@ -326,7 +345,12 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect fmt.Fprintf(f, "%s\n", splitDocString(tt.Description)) fmt.Fprintf(f, "type %s %s", tt.Name, tt.Type) - if tt.Fields != nil { + + if tt.Type == "interface" { + fmt.Fprintf(f, " {\n") + fmt.Fprintf(f, "\tis%s()\n", tt.Name) + fmt.Fprint(f, "}\n") + } else if tt.Fields != nil { fmt.Fprint(f, " {\n") for _, ft := range tt.Fields { if ft.Description != "" { @@ -336,6 +360,51 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect } fmt.Fprint(f, "}\n") } + + // Write custom UnmarshalJSON method for oneOf types. + if tt.DiscriminatorKey != "" && tt.VariantField != "" { + fmt.Fprintf(f, "func (v *%s) UnmarshalJSON(data []byte) error {\n", tt.Name) + + // Check the discriminator to decide which type to unmarshal to. + fmt.Fprintf(f, "\tvar peek struct {\n") + fmt.Fprintf(f, "\t\tDiscriminator %s `json:\"%s\"`\n", tt.DiscriminatorType, tt.DiscriminatorKey) + fmt.Fprintf(f, "\t\tValue json.RawMessage `json:\"%s\"`\n", strings.ToLower(tt.VariantField)) + fmt.Fprintf(f, "\t}\n") + fmt.Fprintf(f, "\tif err := json.Unmarshal(data, &peek); err != nil {\n") + fmt.Fprintf(f, "\t\treturn err\n") + fmt.Fprintf(f, "\t}\n") + fmt.Fprintf(f, "\tswitch peek.Discriminator {\n") + + // Construct a case for each possible variant. + for _, mapping := range tt.DiscriminatorMappings { + fmt.Fprintf(f, "\tcase %s:\n", mapping.EnumConstant) + + // For objects, unmarshal into the corresponding struct. For simple types, unmarshal into a temporary struct, then grab the value from it. + if isSimpleType(mapping.ObjectType) { + fmt.Fprintf(f, "\t\tvar val %s\n", mapping.ConcreteType) + fmt.Fprintf(f, "\t\tif err := json.Unmarshal(peek.Value, &val); err != nil {\n") + fmt.Fprintf(f, "\t\t\treturn err\n") + fmt.Fprintf(f, "\t\t}\n") + fmt.Fprintf(f, "\tv.%s = val\n", tt.VariantField) + } else { + fmt.Fprintf(f, "\t\tvar val %s\n", mapping.ConcreteType) + fmt.Fprintf(f, "\t\tif err := json.Unmarshal(peek.Value, &val); err != nil {\n") + fmt.Fprintf(f, "\t\t\treturn err\n") + fmt.Fprintf(f, "\t\t}\n") + fmt.Fprintf(f, "\tv.%s = val\n", tt.VariantField) + } + } + fmt.Fprintf(f, "\tdefault:\n") + fmt.Fprintf(f, "\t\treturn fmt.Errorf(\"unknown %s discriminator value for %s: %%v\", peek.Discriminator)\n", tt.Name, tt.DiscriminatorKey) + fmt.Fprintf(f, "\t}\n") + fmt.Fprintf(f, "\tv.%s = peek.Discriminator\n", tt.DiscriminatorField) + fmt.Fprintf(f, "\treturn nil\n") + fmt.Fprint(f, "}\n") + } + if tt.VariantInterface != "" { + fmt.Fprintf(f, "\n") + fmt.Fprintf(f, "func (%s) is%s() {}\n", tt.Name, tt.VariantInterface) + } fmt.Fprint(f, "\n") } @@ -381,7 +450,7 @@ func writeTypes(f *os.File, typeCollection []TypeTemplate, typeValidationCollect // populateTypeTemplates populates the template of a type definition for the given schema. // The additional parameter is only used as a suffix for the type name. // This is mostly for oneOf types. -func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string) ([]TypeTemplate, []EnumTemplate) { +func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string, variantInterface string) ([]TypeTemplate, []EnumTemplate) { typeName := name // Type name will change for each enum type @@ -402,6 +471,8 @@ func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string s.Type = &openapi3.Types{"string"} } + typeTpl.VariantInterface = variantInterface + switch ot := getObjectType(s); ot { case "string_enum": enums, tt, et := createStringEnum(s, collectEnumStringTypes, name, typeName) @@ -411,7 +482,7 @@ func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string case "string", "*bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64": typeTpl.Description = formatTypeDescription(typeName, s) - typeTpl.Type = ot + typeTpl.Type = strings.TrimPrefix(ot, "*") typeTpl.Name = typeName case "array": typeTpl.Description = formatTypeDescription(typeName, s) @@ -419,20 +490,21 @@ func populateTypeTemplates(name string, s *openapi3.Schema, enumFieldName string typeTpl.Name = typeName case "object": typeTpl = createTypeObject(s, name, typeName, formatTypeDescription(typeName, s)) + typeTpl.VariantInterface = variantInterface // Iterate over the properties and append the types, if we need to. properties := sortedKeys(s.Properties) for _, k := range properties { v := s.Properties[k] if isLocalEnum(v) { - tt, et := populateTypeTemplates(fmt.Sprintf("%s%s", name, strcase.ToCamel(k)), v.Value, "") + tt, et := populateTypeTemplates(fmt.Sprintf("%s%s", name, strcase.ToCamel(k)), v.Value, "", "") types = append(types, tt...) enumTypes = append(enumTypes, et...) } // TODO: So far this code is never hit with the current openapi spec if isLocalObject(v) { - tt, et := populateTypeTemplates(fmt.Sprintf("%s%s", name, strcase.ToCamel(k)), v.Value, "") + tt, et := populateTypeTemplates(fmt.Sprintf("%s%s", name, strcase.ToCamel(k)), v.Value, "", "") types = append(types, tt...) enumTypes = append(enumTypes, et...) } @@ -624,6 +696,10 @@ func createStringEnum(s *openapi3.Schema, stringEnums map[string][]string, name, // Probably not the best approach, but will leave them this way until I come up with // a more idiomatic solution. Keep an eye out on this one to refine. func createAllOf(s *openapi3.Schema, stringEnums map[string][]string, name, typeName string) []TypeTemplate { + + // if typeName == "VpcFirewallRuleTarget" { + // panic("sad") + // } typeTpls := make([]TypeTemplate, 0) // Make sure we don't redeclare the enum type. @@ -650,54 +726,49 @@ func createAllOf(s *openapi3.Schema, stringEnums map[string][]string, name, type func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []EnumTemplate) { var parsedProperties []string - var properties []string - var genericTypes []string enumTpls := make([]EnumTemplate, 0) typeTpls := make([]TypeTemplate, 0) fields := make([]TypeFields, 0) - for _, v := range s.OneOf { - // Iterate over all the schema components in the spec and write the types. - keys := sortedKeys(v.Value.Properties) - for _, prop := range keys { - p := v.Value.Properties[prop] - // We want to collect all the unique properties to create our global oneOf type. - propertyType := convertToValidGoType(prop, typeName, p) - properties = append(properties, prop+"="+propertyType) + discriminator := "" + propertyToVariants := map[string]map[string]struct{}{} + propertyToObjectTypes := map[string]string{} + for _, v := range s.OneOf { + for propName, prop := range v.Value.Properties { + if len(prop.Value.Enum) == 1 { + discriminator = propName + } + if _, ok := propertyToVariants[propName]; !ok { + propertyToVariants[propName] = map[string]struct{}{} + } + goType := convertToValidGoType(propName, typeName, prop) + propertyToVariants[propName][goType] = struct{}{} + propertyToObjectTypes[propName] = getObjectType(prop.Value) } } - - // When dealing with oneOf sometimes property types will not be the same, we want to - // catch these to set them as "any" when we generate the type. - typeKeys := []string{} - // First we gather all unique properties - for _, v := range properties { - parts := strings.Split(v, "=") - key := parts[0] - if !slices.Contains(typeKeys, key) { - typeKeys = append(typeKeys, key) + variantField := "" + variantFields := []string{} + variantTypes := []string{} + for propName, variants := range propertyToVariants { + if len(variants) > 1 { + variantFields = append(variantFields, propName) + variantTypes = append(variantTypes, propName) } } - - // For each of the properties above we gather all possible types - // and gather all of those that are not. We will be setting those - // as a generic type - for _, k := range typeKeys { - values := []string{} - for _, v := range properties { - parts := strings.Split(v, "=") - key := parts[0] - value := parts[1] - if key == k { - values = append(values, value) - } - } - - if !allItemsAreSame(values) { - genericTypes = append(genericTypes, k) - } + variantInterface := "" + if len(variantFields) == 1 && len(variantTypes) == 1 { + variantField = strcase.ToCamel(variantFields[0]) + // Note: the variant interface is only used to define the tagged enum, and not of interest to users, so we make it private. + variantInterface = fmt.Sprintf("%s%s", strcase.ToLowerCamel(typeName), strcase.ToCamel(variantTypes[0])) + typeTpls = append(typeTpls, TypeTemplate{ + Name: variantInterface, + Type: "interface", + }) } + discriminatorMappings := []DiscriminatorMapping{} + discriminatorToDiscriminatorType := map[string]string{} + for _, v := range s.OneOf { // We want to iterate over the properties of the embedded object // and find the type that is a string. @@ -707,16 +778,33 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E keys := sortedKeys(v.Value.Properties) for _, prop := range keys { p := v.Value.Properties[prop] + propertyName := strcase.ToCamel(prop) // We want to collect all the unique properties to create our global oneOf type. propertyType := convertToValidGoType(prop, typeName, p) + if propertyType == "string" && len(p.Value.Enum) == 1 { + discriminatorToDiscriminatorType[prop] = typeName + strcase.ToCamel(prop) + discriminatorMappings = append(discriminatorMappings, DiscriminatorMapping{ + EnumConstant: fmt.Sprintf("%s%s%s", typeName, propertyName, strcase.ToCamel(p.Value.Enum[0].(string))), + ConcreteType: fmt.Sprintf("%s%s", typeName, strcase.ToCamel(p.Value.Enum[0].(string))), + // ObjectType: propertyToObjectTypes[variantTypes[0]], + }) + if len(variantFields) > 0 { + vp := v.Value.Properties[strings.ToLower(variantField)] + if vp != nil { + discriminatorMappings[len(discriminatorMappings)-1].ObjectType = propertyToObjectTypes[variantFields[0]] + + } + } + } + // Check if we have an enum in order to use the corresponding type instead of // "string" if propertyType == "string" && len(p.Value.Enum) != 0 { propertyType = typeName + strcase.ToCamel(prop) } - propertyName := strcase.ToCamel(prop) + propertyName = strcase.ToCamel(prop) // Avoids duplication for every enum if !containsMatchFirstWord(parsedProperties, propertyName) { @@ -728,8 +816,8 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E } // We set the type of a field as "any" if every element of the oneOf property isn't the same - if slices.Contains(genericTypes, prop) { - field.Type = "any" + if slices.Contains(variantTypes, prop) { + field.Type = variantInterface } // Check if the field is nullable and use omitzero instead of omitempty. @@ -765,7 +853,28 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E // TODO: This is the only place that has an "additional name" at the end // TODO: This is where the "allOf" is being detected - tt, et := populateTypeTemplates(name, v.Value, enumFieldName) + if len(variantFields) == 1 && v.Value.Properties[variantFields[0]] != nil { + variantField := variantFields[0] + variantType := getObjectType(v.Value.Properties[variantField].Value) + if isSimpleType(variantType) { + // Special case: process the variant field property separately + tt, _ := populateTypeTemplates(name, v.Value.Properties[variantField].Value, enumFieldName, variantInterface) + typeTpls = append(typeTpls, tt...) + parentTT, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) + enumTpls = append(enumTpls, et...) + + // Only include parent types with Type suffix + for _, tt := range parentTT { + if strings.HasSuffix(tt.Name, strcase.ToCamel(discriminator)) { + typeTpls = append(typeTpls, tt) + } + } + continue + } + } + + // Normal case: process the parent schema + tt, et := populateTypeTemplates(name, v.Value, enumFieldName, variantInterface) typeTpls = append(typeTpls, tt...) enumTpls = append(enumTpls, et...) } @@ -782,10 +891,15 @@ func createOneOf(s *openapi3.Schema, name, typeName string) ([]TypeTemplate, []E // Make sure to only create structs if the oneOf is not a replacement for enums on the API spec if len(fields) > 0 { typeTpl := TypeTemplate{ - Description: formatTypeDescription(typeName, s), - Name: typeName, - Type: "struct", - Fields: fields, + Description: formatTypeDescription(typeName, s), + Name: typeName, + Type: "struct", + Fields: fields, + DiscriminatorKey: discriminator, + DiscriminatorField: strcase.ToCamel(discriminator), + DiscriminatorType: discriminatorToDiscriminatorType[discriminator], + DiscriminatorMappings: discriminatorMappings, + VariantField: variantField, } typeTpls = append(typeTpls, typeTpl) } @@ -844,3 +958,9 @@ func formatTypeDescription(name string, s *openapi3.Schema) string { } return fmt.Sprintf("// %s is the type definition for a %s.", name, name) } + +func isSimpleType(t string) bool { + simpleTypes := []string{"string", "*bool", "int", "int8", "int16", "int32", "int64", "uint", "uint8", + "uint16", "uint32", "uint64", "uintptr", "float32", "float64"} + return slices.Contains(simpleTypes, t) +} diff --git a/internal/generate/types_test.go b/internal/generate/types_test.go index 8059762..7b2b30f 100644 --- a/internal/generate/types_test.go +++ b/internal/generate/types_test.go @@ -273,7 +273,10 @@ func Test_createOneOf(t *testing.T) { }, }, { - Description: "// ImageSource is the source of the underlying image.", Name: "ImageSource", Type: "struct", Fields: []TypeFields{ + Description: "// ImageSource is the source of the underlying image.", + Name: "ImageSource", + Type: "struct", + Fields: []TypeFields{ { Description: "// Type is the type definition for a Type.", Name: "Type", Type: "ImageSourceType", SerializationInfo: "`json:\"type,omitempty\" yaml:\"type,omitempty\"`", }, @@ -284,6 +287,22 @@ func Test_createOneOf(t *testing.T) { Description: "// Id is the type definition for a Id.", Name: "Id", Type: "string", SerializationInfo: "`json:\"id,omitempty\" yaml:\"id,omitempty\"`", }, }, + DiscriminatorKey: "type", + DiscriminatorField: "Type", + DiscriminatorType: "ImageSourceType", + DiscriminatorMappings: []DiscriminatorMapping{ + { + EnumConstant: "ImageSourceTypeUrl", + ConcreteType: "ImageSourceUrl", + ObjectType: "", + }, + { + EnumConstant: "ImageSourceTypeSnapshot", + ConcreteType: "ImageSourceSnapshot", + ObjectType: "", + }, + }, + VariantField: "", }, }, want1: []EnumTemplate{ diff --git a/internal/generate/utils.go b/internal/generate/utils.go index 8285fa8..4801f0d 100644 --- a/internal/generate/utils.go +++ b/internal/generate/utils.go @@ -255,15 +255,6 @@ func isNumericType(str string) bool { return slices.Contains(numTypes, str) } -func allItemsAreSame[T comparable](a []T) bool { - for _, v := range a { - if v != a[0] { - return false - } - } - return true -} - // sortedKeys returns a []string of sorted keys from a map. Used to ensure // deterministic ordering of generated code. func sortedKeys[T any](m map[string]T) []string { diff --git a/oxide/types.go b/oxide/types.go index 4bc1a62..2630389 100644 --- a/oxide/types.go +++ b/oxide/types.go @@ -7,6 +7,7 @@ package oxide import ( + "encoding/json" "fmt" "io" "time" @@ -1923,128 +1924,72 @@ type CurrentUser struct { SiloName Name `json:"silo_name" yaml:"silo_name"` } -// DatumType is the type definition for a DatumType. -type DatumType string +type datumDatum interface { + isdatumDatum() +} // DatumBool is the type definition for a DatumBool. -// -// Required fields: -// - Datum -// - Type -type DatumBool struct { - Datum *bool `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumBool bool + +func (DatumBool) isdatumDatum() {} + +// DatumType is the type definition for a DatumType. +type DatumType string // DatumI8 is the type definition for a DatumI8. -// -// Required fields: -// - Datum -// - Type -type DatumI8 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumI8 int8 + +func (DatumI8) isdatumDatum() {} // DatumU8 is the type definition for a DatumU8. -// -// Required fields: -// - Datum -// - Type -type DatumU8 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumU8 uint8 + +func (DatumU8) isdatumDatum() {} // DatumI16 is the type definition for a DatumI16. -// -// Required fields: -// - Datum -// - Type -type DatumI16 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumI16 int16 + +func (DatumI16) isdatumDatum() {} // DatumU16 is the type definition for a DatumU16. -// -// Required fields: -// - Datum -// - Type -type DatumU16 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumU16 uint16 + +func (DatumU16) isdatumDatum() {} // DatumI32 is the type definition for a DatumI32. -// -// Required fields: -// - Datum -// - Type -type DatumI32 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumI32 int32 + +func (DatumI32) isdatumDatum() {} // DatumU32 is the type definition for a DatumU32. -// -// Required fields: -// - Datum -// - Type -type DatumU32 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumU32 uint32 + +func (DatumU32) isdatumDatum() {} // DatumI64 is the type definition for a DatumI64. -// -// Required fields: -// - Datum -// - Type -type DatumI64 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumI64 int64 + +func (DatumI64) isdatumDatum() {} // DatumU64 is the type definition for a DatumU64. -// -// Required fields: -// - Datum -// - Type -type DatumU64 struct { - Datum *int `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumU64 uint64 + +func (DatumU64) isdatumDatum() {} // DatumF32 is the type definition for a DatumF32. -// -// Required fields: -// - Datum -// - Type -type DatumF32 struct { - Datum float64 `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumF32 float64 + +func (DatumF32) isdatumDatum() {} // DatumF64 is the type definition for a DatumF64. -// -// Required fields: -// - Datum -// - Type -type DatumF64 struct { - Datum float64 `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumF64 float64 + +func (DatumF64) isdatumDatum() {} // DatumString is the type definition for a DatumString. -// -// Required fields: -// - Datum -// - Type -type DatumString struct { - Datum string `json:"datum" yaml:"datum"` - Type DatumType `json:"type" yaml:"type"` -} +type DatumString string + +func (DatumString) isdatumDatum() {} // DatumBytes is the type definition for a DatumBytes. // @@ -2056,6 +2001,8 @@ type DatumBytes struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumBytes) isdatumDatum() {} + // DatumCumulativeI64 is the type definition for a DatumCumulativeI64. // // Required fields: @@ -2067,6 +2014,8 @@ type DatumCumulativeI64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumCumulativeI64) isdatumDatum() {} + // DatumCumulativeU64 is the type definition for a DatumCumulativeU64. // // Required fields: @@ -2078,6 +2027,8 @@ type DatumCumulativeU64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumCumulativeU64) isdatumDatum() {} + // DatumCumulativeF32 is the type definition for a DatumCumulativeF32. // // Required fields: @@ -2089,6 +2040,8 @@ type DatumCumulativeF32 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumCumulativeF32) isdatumDatum() {} + // DatumCumulativeF64 is the type definition for a DatumCumulativeF64. // // Required fields: @@ -2100,6 +2053,8 @@ type DatumCumulativeF64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumCumulativeF64) isdatumDatum() {} + // DatumHistogramI8 is the type definition for a DatumHistogramI8. // // Required fields: @@ -2117,6 +2072,8 @@ type DatumHistogramI8 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramI8) isdatumDatum() {} + // DatumHistogramU8 is the type definition for a DatumHistogramU8. // // Required fields: @@ -2134,6 +2091,8 @@ type DatumHistogramU8 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramU8) isdatumDatum() {} + // DatumHistogramI16 is the type definition for a DatumHistogramI16. // // Required fields: @@ -2151,6 +2110,8 @@ type DatumHistogramI16 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramI16) isdatumDatum() {} + // DatumHistogramU16 is the type definition for a DatumHistogramU16. // // Required fields: @@ -2168,6 +2129,8 @@ type DatumHistogramU16 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramU16) isdatumDatum() {} + // DatumHistogramI32 is the type definition for a DatumHistogramI32. // // Required fields: @@ -2185,6 +2148,8 @@ type DatumHistogramI32 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramI32) isdatumDatum() {} + // DatumHistogramU32 is the type definition for a DatumHistogramU32. // // Required fields: @@ -2202,6 +2167,8 @@ type DatumHistogramU32 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramU32) isdatumDatum() {} + // DatumHistogramI64 is the type definition for a DatumHistogramI64. // // Required fields: @@ -2219,6 +2186,8 @@ type DatumHistogramI64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramI64) isdatumDatum() {} + // DatumHistogramU64 is the type definition for a DatumHistogramU64. // // Required fields: @@ -2236,6 +2205,8 @@ type DatumHistogramU64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramU64) isdatumDatum() {} + // DatumHistogramF32 is the type definition for a DatumHistogramF32. // // Required fields: @@ -2253,6 +2224,8 @@ type DatumHistogramF32 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramF32) isdatumDatum() {} + // DatumHistogramF64 is the type definition for a DatumHistogramF64. // // Required fields: @@ -2270,6 +2243,8 @@ type DatumHistogramF64 struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumHistogramF64) isdatumDatum() {} + // DatumMissing is the type definition for a DatumMissing. // // Required fields: @@ -2280,14 +2255,200 @@ type DatumMissing struct { Type DatumType `json:"type" yaml:"type"` } +func (DatumMissing) isdatumDatum() {} + // Datum is a `Datum` is a single sampled data point from a metric. type Datum struct { // Datum is the type definition for a Datum. - Datum any `json:"datum,omitempty" yaml:"datum,omitempty"` + Datum datumDatum `json:"datum,omitempty" yaml:"datum,omitempty"` // Type is the type definition for a Type. Type DatumType `json:"type,omitempty" yaml:"type,omitempty"` } +func (v *Datum) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator DatumType `json:"type"` + Value json.RawMessage `json:"datum"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case DatumTypeBool: + var val DatumBool + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeI8: + var val DatumI8 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeU8: + var val DatumU8 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeI16: + var val DatumI16 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeU16: + var val DatumU16 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeI32: + var val DatumI32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeU32: + var val DatumU32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeI64: + var val DatumI64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeU64: + var val DatumU64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeF32: + var val DatumF32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeF64: + var val DatumF64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeString: + var val DatumString + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeBytes: + var val DatumBytes + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeCumulativeI64: + var val DatumCumulativeI64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeCumulativeU64: + var val DatumCumulativeU64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeCumulativeF32: + var val DatumCumulativeF32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeCumulativeF64: + var val DatumCumulativeF64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramI8: + var val DatumHistogramI8 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramU8: + var val DatumHistogramU8 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramI16: + var val DatumHistogramI16 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramU16: + var val DatumHistogramU16 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramI32: + var val DatumHistogramI32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramU32: + var val DatumHistogramU32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramI64: + var val DatumHistogramI64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramU64: + var val DatumHistogramU64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramF32: + var val DatumHistogramF32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeHistogramF64: + var val DatumHistogramF64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + case DatumTypeMissing: + var val DatumMissing + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Datum = val + default: + return fmt.Errorf("unknown Datum discriminator value for type: %v", peek.Discriminator) + } + v.Type = peek.Discriminator + return nil +} + // DerEncodedKeyPair is the type definition for a DerEncodedKeyPair. // // Required fields: @@ -2860,135 +3021,167 @@ type FieldSource string // FieldType is the `FieldType` identifies the data type of a target or metric field. type FieldType string -// FieldValueType is the type definition for a FieldValueType. -type FieldValueType string +type fieldValueValue interface { + isfieldValueValue() +} // FieldValueString is the type definition for a FieldValueString. -// -// Required fields: -// - Type -// - Value -type FieldValueString struct { - Type FieldValueType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +type FieldValueString string + +func (FieldValueString) isfieldValueValue() {} + +// FieldValueType is the type definition for a FieldValueType. +type FieldValueType string // FieldValueI8 is the type definition for a FieldValueI8. -// -// Required fields: -// - Type -// - Value -type FieldValueI8 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueI8 int8 + +func (FieldValueI8) isfieldValueValue() {} // FieldValueU8 is the type definition for a FieldValueU8. -// -// Required fields: -// - Type -// - Value -type FieldValueU8 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueU8 uint8 + +func (FieldValueU8) isfieldValueValue() {} // FieldValueI16 is the type definition for a FieldValueI16. -// -// Required fields: -// - Type -// - Value -type FieldValueI16 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueI16 int16 + +func (FieldValueI16) isfieldValueValue() {} // FieldValueU16 is the type definition for a FieldValueU16. -// -// Required fields: -// - Type -// - Value -type FieldValueU16 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueU16 uint16 + +func (FieldValueU16) isfieldValueValue() {} // FieldValueI32 is the type definition for a FieldValueI32. -// -// Required fields: -// - Type -// - Value -type FieldValueI32 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueI32 int32 + +func (FieldValueI32) isfieldValueValue() {} // FieldValueU32 is the type definition for a FieldValueU32. -// -// Required fields: -// - Type -// - Value -type FieldValueU32 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueU32 uint32 + +func (FieldValueU32) isfieldValueValue() {} // FieldValueI64 is the type definition for a FieldValueI64. -// -// Required fields: -// - Type -// - Value -type FieldValueI64 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueI64 int64 + +func (FieldValueI64) isfieldValueValue() {} // FieldValueU64 is the type definition for a FieldValueU64. -// -// Required fields: -// - Type -// - Value -type FieldValueU64 struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *int `json:"value" yaml:"value"` -} +type FieldValueU64 uint64 + +func (FieldValueU64) isfieldValueValue() {} // FieldValueIpAddr is the type definition for a FieldValueIpAddr. -// -// Required fields: -// - Type -// - Value -type FieldValueIpAddr struct { - Type FieldValueType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +type FieldValueIpAddr string + +func (FieldValueIpAddr) isfieldValueValue() {} // FieldValueUuid is the type definition for a FieldValueUuid. -// -// Required fields: -// - Type -// - Value -type FieldValueUuid struct { - Type FieldValueType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +type FieldValueUuid string + +func (FieldValueUuid) isfieldValueValue() {} // FieldValueBool is the type definition for a FieldValueBool. -// -// Required fields: -// - Type -// - Value -type FieldValueBool struct { - Type FieldValueType `json:"type" yaml:"type"` - Value *bool `json:"value" yaml:"value"` -} +type FieldValueBool bool + +func (FieldValueBool) isfieldValueValue() {} // FieldValue is the `FieldValue` contains the value of a target or metric field. type FieldValue struct { // Type is the type definition for a Type. Type FieldValueType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value any `json:"value,omitempty" yaml:"value,omitempty"` + Value fieldValueValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *FieldValue) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator FieldValueType `json:"type"` + Value json.RawMessage `json:"value"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case FieldValueTypeString: + var val FieldValueString + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeI8: + var val FieldValueI8 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeU8: + var val FieldValueU8 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeI16: + var val FieldValueI16 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeU16: + var val FieldValueU16 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeI32: + var val FieldValueI32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeU32: + var val FieldValueU32 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeI64: + var val FieldValueI64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeU64: + var val FieldValueU64 + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeIpAddr: + var val FieldValueIpAddr + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeUuid: + var val FieldValueUuid + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case FieldValueTypeBool: + var val FieldValueBool + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + default: + return fmt.Errorf("unknown FieldValue discriminator value for type: %v", peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // FinalizeDisk is parameters for finalizing a disk @@ -5343,19 +5536,18 @@ type RouteConfig struct { Routes []Route `json:"routes" yaml:"routes"` } +type routeDestinationValue interface { + isrouteDestinationValue() +} + +// RouteDestinationIp is the type definition for a RouteDestinationIp. +type RouteDestinationIp string + +func (RouteDestinationIp) isrouteDestinationValue() {} + // RouteDestinationType is the type definition for a RouteDestinationType. type RouteDestinationType string -// RouteDestinationIp is route applies to traffic destined for the specified IP address -// -// Required fields: -// - Type -// - Value -type RouteDestinationIp struct { - Type RouteDestinationType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} - // RouteDestinationIpNet is route applies to traffic destined for the specified IP subnet // // Required fields: @@ -5366,31 +5558,21 @@ type RouteDestinationIpNet struct { Value IpNet `json:"value" yaml:"value"` } -// RouteDestinationVpc is route applies to traffic destined for the specified VPC -// -// Required fields: -// - Type -// - Value -type RouteDestinationVpc struct { - Type RouteDestinationType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (RouteDestinationIpNet) isrouteDestinationValue() {} -// RouteDestinationSubnet is route applies to traffic destined for the specified VPC subnet -// -// Required fields: -// - Type -// - Value -type RouteDestinationSubnet struct { - Type RouteDestinationType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// RouteDestinationVpc is names must begin with a lower case ASCII letter, be composed exclusively of lowercase +// ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may +// contain a UUID. They can be at most 63 characters long. +type RouteDestinationVpc string + +func (RouteDestinationVpc) isrouteDestinationValue() {} + +// RouteDestinationSubnet is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type RouteDestinationSubnet string + +func (RouteDestinationSubnet) isrouteDestinationValue() {} // RouteDestination is a `RouteDestination` is used to match traffic with a routing rule based on the destination // of that traffic. @@ -5401,73 +5583,88 @@ type RouteDestination struct { // Type is the type definition for a Type. Type RouteDestinationType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value any `json:"value,omitempty" yaml:"value,omitempty"` -} + Value routeDestinationValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *RouteDestination) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator RouteDestinationType `json:"type"` + Value json.RawMessage `json:"value"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case RouteDestinationTypeIp: + var val RouteDestinationIp + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case RouteDestinationTypeIpNet: + var val RouteDestinationIpNet + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case RouteDestinationTypeVpc: + var val RouteDestinationVpc + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case RouteDestinationTypeSubnet: + var val RouteDestinationSubnet + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + default: + return fmt.Errorf("unknown RouteDestination discriminator value for type: %v", peek.Discriminator) + } + v.Type = peek.Discriminator + return nil +} + +type routeTargetValue interface { + isrouteTargetValue() +} + +// RouteTargetIp is the type definition for a RouteTargetIp. +type RouteTargetIp string + +func (RouteTargetIp) isrouteTargetValue() {} // RouteTargetType is the type definition for a RouteTargetType. type RouteTargetType string -// RouteTargetIp is forward traffic to a particular IP address. -// -// Required fields: -// - Type -// - Value -type RouteTargetIp struct { - Type RouteTargetType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +// RouteTargetVpc is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, +// uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a +// UUID. They can be at most 63 characters long. +type RouteTargetVpc string -// RouteTargetVpc is forward traffic to a VPC -// -// Required fields: -// - Type -// - Value -type RouteTargetVpc struct { - Type RouteTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (RouteTargetVpc) isrouteTargetValue() {} -// RouteTargetSubnet is forward traffic to a VPC Subnet -// -// Required fields: -// - Type -// - Value -type RouteTargetSubnet struct { - Type RouteTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// RouteTargetSubnet is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, +// uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a +// UUID. They can be at most 63 characters long. +type RouteTargetSubnet string -// RouteTargetInstance is forward traffic to a specific instance -// -// Required fields: -// - Type -// - Value -type RouteTargetInstance struct { - Type RouteTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (RouteTargetSubnet) isrouteTargetValue() {} -// RouteTargetInternetGateway is forward traffic to an internet gateway -// -// Required fields: -// - Type -// - Value -type RouteTargetInternetGateway struct { - Type RouteTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// RouteTargetInstance is names must begin with a lower case ASCII letter, be composed exclusively of lowercase +// ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may +// contain a UUID. They can be at most 63 characters long. +type RouteTargetInstance string + +func (RouteTargetInstance) isrouteTargetValue() {} + +// RouteTargetInternetGateway is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type RouteTargetInternetGateway string + +func (RouteTargetInternetGateway) isrouteTargetValue() {} // RouteTargetDrop is drop matching traffic // @@ -5477,13 +5674,67 @@ type RouteTargetDrop struct { Type RouteTargetType `json:"type" yaml:"type"` } +func (RouteTargetDrop) isrouteTargetValue() {} + // RouteTarget is a `RouteTarget` describes the possible locations that traffic matching a route destination can // be sent. type RouteTarget struct { // Type is the type definition for a Type. Type RouteTargetType `json:"type,omitempty" yaml:"type,omitempty"` // Value is the type definition for a Value. - Value any `json:"value,omitempty" yaml:"value,omitempty"` + Value routeTargetValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *RouteTarget) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator RouteTargetType `json:"type"` + Value json.RawMessage `json:"value"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case RouteTargetTypeIp: + var val RouteTargetIp + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case RouteTargetTypeVpc: + var val RouteTargetVpc + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case RouteTargetTypeSubnet: + var val RouteTargetSubnet + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case RouteTargetTypeInstance: + var val RouteTargetInstance + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case RouteTargetTypeInternetGateway: + var val RouteTargetInternetGateway + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case RouteTargetTypeDrop: + var val RouteTargetDrop + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + default: + return fmt.Errorf("unknown RouteTarget discriminator value for type: %v", peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // RouterRoute is a route defines a rule that governs where traffic should be sent based on its destination. @@ -7126,6 +7377,10 @@ type Utilization struct { Provisioned VirtualResourceCounts `json:"provisioned" yaml:"provisioned"` } +type valueArrayValues interface { + isvalueArrayValues() +} + // ValueArrayType is the type definition for a ValueArrayType. type ValueArrayType string @@ -7139,6 +7394,8 @@ type ValueArrayInteger struct { Values []int `json:"values" yaml:"values"` } +func (ValueArrayInteger) isvalueArrayValues() {} + // ValueArrayDouble is the type definition for a ValueArrayDouble. // // Required fields: @@ -7149,6 +7406,8 @@ type ValueArrayDouble struct { Values []float64 `json:"values" yaml:"values"` } +func (ValueArrayDouble) isvalueArrayValues() {} + // ValueArrayBoolean is the type definition for a ValueArrayBoolean. // // Required fields: @@ -7159,6 +7418,8 @@ type ValueArrayBoolean struct { Values []bool `json:"values" yaml:"values"` } +func (ValueArrayBoolean) isvalueArrayValues() {} + // ValueArrayString is the type definition for a ValueArrayString. // // Required fields: @@ -7169,6 +7430,8 @@ type ValueArrayString struct { Values []string `json:"values" yaml:"values"` } +func (ValueArrayString) isvalueArrayValues() {} + // ValueArrayIntegerDistribution is the type definition for a ValueArrayIntegerDistribution. // // Required fields: @@ -7179,6 +7442,8 @@ type ValueArrayIntegerDistribution struct { Values []Distributionint64 `json:"values" yaml:"values"` } +func (ValueArrayIntegerDistribution) isvalueArrayValues() {} + // ValueArrayDoubleDistribution is the type definition for a ValueArrayDoubleDistribution. // // Required fields: @@ -7189,6 +7454,8 @@ type ValueArrayDoubleDistribution struct { Values []Distributiondouble `json:"values" yaml:"values"` } +func (ValueArrayDoubleDistribution) isvalueArrayValues() {} + // ValueArray is list of data values for one timeseries. // // Each element is an option, where `None` represents a missing sample. @@ -7196,7 +7463,59 @@ type ValueArray struct { // Type is the type definition for a Type. Type ValueArrayType `json:"type,omitempty" yaml:"type,omitempty"` // Values is the type definition for a Values. - Values any `json:"values,omitempty" yaml:"values,omitempty"` + Values valueArrayValues `json:"values,omitempty" yaml:"values,omitempty"` +} + +func (v *ValueArray) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator ValueArrayType `json:"type"` + Value json.RawMessage `json:"values"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case ValueArrayTypeInteger: + var val ValueArrayInteger + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeDouble: + var val ValueArrayDouble + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeBoolean: + var val ValueArrayBoolean + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeString: + var val ValueArrayString + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeIntegerDistribution: + var val ValueArrayIntegerDistribution + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Values = val + case ValueArrayTypeDoubleDistribution: + var val ValueArrayDoubleDistribution + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Values = val + default: + return fmt.Errorf("unknown ValueArray discriminator value for type: %v", peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // Values is a single list of values, for one dimension of a timeseries. @@ -7358,57 +7677,38 @@ type VpcFirewallRuleFilter struct { Protocols []VpcFirewallRuleProtocol `json:"protocols" yaml:"protocols"` } +type vpcFirewallRuleHostFilterValue interface { + isvpcFirewallRuleHostFilterValue() +} + +// VpcFirewallRuleHostFilterVpc is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleHostFilterVpc string + +func (VpcFirewallRuleHostFilterVpc) isvpcFirewallRuleHostFilterValue() {} + // VpcFirewallRuleHostFilterType is the type definition for a VpcFirewallRuleHostFilterType. type VpcFirewallRuleHostFilterType string -// VpcFirewallRuleHostFilterVpc is the rule applies to traffic from/to all instances in the VPC -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleHostFilterVpc struct { - Type VpcFirewallRuleHostFilterType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// VpcFirewallRuleHostFilterSubnet is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleHostFilterSubnet string -// VpcFirewallRuleHostFilterSubnet is the rule applies to traffic from/to all instances in the VPC Subnet -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleHostFilterSubnet struct { - Type VpcFirewallRuleHostFilterType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (VpcFirewallRuleHostFilterSubnet) isvpcFirewallRuleHostFilterValue() {} -// VpcFirewallRuleHostFilterInstance is the rule applies to traffic from/to this specific instance -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleHostFilterInstance struct { - Type VpcFirewallRuleHostFilterType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// VpcFirewallRuleHostFilterInstance is names must begin with a lower case ASCII letter, be composed exclusively +// of lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, +// but they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleHostFilterInstance string -// VpcFirewallRuleHostFilterIp is the rule applies to traffic from/to a specific IP address -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleHostFilterIp struct { - Type VpcFirewallRuleHostFilterType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +func (VpcFirewallRuleHostFilterInstance) isvpcFirewallRuleHostFilterValue() {} + +// VpcFirewallRuleHostFilterIp is the type definition for a VpcFirewallRuleHostFilterIp. +type VpcFirewallRuleHostFilterIp string + +func (VpcFirewallRuleHostFilterIp) isvpcFirewallRuleHostFilterValue() {} // VpcFirewallRuleHostFilterIpNet is the rule applies to traffic from/to a specific IP subnet // @@ -7420,6 +7720,8 @@ type VpcFirewallRuleHostFilterIpNet struct { Value IpNet `json:"value" yaml:"value"` } +func (VpcFirewallRuleHostFilterIpNet) isvpcFirewallRuleHostFilterValue() {} + // VpcFirewallRuleHostFilter is the `VpcFirewallRuleHostFilter` is used to filter traffic on the basis of // its source or destination host. type VpcFirewallRuleHostFilter struct { @@ -7428,7 +7730,53 @@ type VpcFirewallRuleHostFilter struct { // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They // can be at most 63 characters long. - Value any `json:"value,omitempty" yaml:"value,omitempty"` + Value vpcFirewallRuleHostFilterValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *VpcFirewallRuleHostFilter) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator VpcFirewallRuleHostFilterType `json:"type"` + Value json.RawMessage `json:"value"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case VpcFirewallRuleHostFilterTypeVpc: + var val VpcFirewallRuleHostFilterVpc + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleHostFilterTypeSubnet: + var val VpcFirewallRuleHostFilterSubnet + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleHostFilterTypeInstance: + var val VpcFirewallRuleHostFilterInstance + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleHostFilterTypeIp: + var val VpcFirewallRuleHostFilterIp + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleHostFilterTypeIpNet: + var val VpcFirewallRuleHostFilterIpNet + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + default: + return fmt.Errorf("unknown VpcFirewallRuleHostFilter discriminator value for type: %v", peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // VpcFirewallRuleProtocolType is the type definition for a VpcFirewallRuleProtocolType. @@ -7471,57 +7819,38 @@ type VpcFirewallRuleProtocol struct { // VpcFirewallRuleStatus is the type definition for a VpcFirewallRuleStatus. type VpcFirewallRuleStatus string +type vpcFirewallRuleTargetValue interface { + isvpcFirewallRuleTargetValue() +} + +// VpcFirewallRuleTargetVpc is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleTargetVpc string + +func (VpcFirewallRuleTargetVpc) isvpcFirewallRuleTargetValue() {} + // VpcFirewallRuleTargetType is the type definition for a VpcFirewallRuleTargetType. type VpcFirewallRuleTargetType string -// VpcFirewallRuleTargetVpc is the rule applies to all instances in the VPC -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleTargetVpc struct { - Type VpcFirewallRuleTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// VpcFirewallRuleTargetSubnet is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleTargetSubnet string -// VpcFirewallRuleTargetSubnet is the rule applies to all instances in the VPC Subnet -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleTargetSubnet struct { - Type VpcFirewallRuleTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +func (VpcFirewallRuleTargetSubnet) isvpcFirewallRuleTargetValue() {} -// VpcFirewallRuleTargetInstance is the rule applies to this specific instance -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleTargetInstance struct { - Type VpcFirewallRuleTargetType `json:"type" yaml:"type"` - // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase - // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They - // can be at most 63 characters long. - Value Name `json:"value" yaml:"value"` -} +// VpcFirewallRuleTargetInstance is names must begin with a lower case ASCII letter, be composed exclusively of +// lowercase ASCII, uppercase ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but +// they may contain a UUID. They can be at most 63 characters long. +type VpcFirewallRuleTargetInstance string -// VpcFirewallRuleTargetIp is the rule applies to a specific IP address -// -// Required fields: -// - Type -// - Value -type VpcFirewallRuleTargetIp struct { - Type VpcFirewallRuleTargetType `json:"type" yaml:"type"` - Value string `json:"value" yaml:"value"` -} +func (VpcFirewallRuleTargetInstance) isvpcFirewallRuleTargetValue() {} + +// VpcFirewallRuleTargetIp is the type definition for a VpcFirewallRuleTargetIp. +type VpcFirewallRuleTargetIp string + +func (VpcFirewallRuleTargetIp) isvpcFirewallRuleTargetValue() {} // VpcFirewallRuleTargetIpNet is the rule applies to a specific IP subnet // @@ -7533,6 +7862,8 @@ type VpcFirewallRuleTargetIpNet struct { Value IpNet `json:"value" yaml:"value"` } +func (VpcFirewallRuleTargetIpNet) isvpcFirewallRuleTargetValue() {} + // VpcFirewallRuleTarget is a `VpcFirewallRuleTarget` is used to specify the set of instances to which a // firewall rule applies. You can target instances directly by name, or specify a VPC, VPC subnet, IP, or IP // subnet, which will apply the rule to traffic going to all matching instances. Targets are additive: the rule @@ -7543,7 +7874,53 @@ type VpcFirewallRuleTarget struct { // Value is names must begin with a lower case ASCII letter, be composed exclusively of lowercase ASCII, uppercase // ASCII, numbers, and '-', and may not end with a '-'. Names cannot be a UUID, but they may contain a UUID. They // can be at most 63 characters long. - Value any `json:"value,omitempty" yaml:"value,omitempty"` + Value vpcFirewallRuleTargetValue `json:"value,omitempty" yaml:"value,omitempty"` +} + +func (v *VpcFirewallRuleTarget) UnmarshalJSON(data []byte) error { + var peek struct { + Discriminator VpcFirewallRuleTargetType `json:"type"` + Value json.RawMessage `json:"value"` + } + if err := json.Unmarshal(data, &peek); err != nil { + return err + } + switch peek.Discriminator { + case VpcFirewallRuleTargetTypeVpc: + var val VpcFirewallRuleTargetVpc + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleTargetTypeSubnet: + var val VpcFirewallRuleTargetSubnet + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleTargetTypeInstance: + var val VpcFirewallRuleTargetInstance + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleTargetTypeIp: + var val VpcFirewallRuleTargetIp + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + case VpcFirewallRuleTargetTypeIpNet: + var val VpcFirewallRuleTargetIpNet + if err := json.Unmarshal(peek.Value, &val); err != nil { + return err + } + v.Value = val + default: + return fmt.Errorf("unknown VpcFirewallRuleTarget discriminator value for type: %v", peek.Discriminator) + } + v.Type = peek.Discriminator + return nil } // VpcFirewallRuleUpdate is a single rule in a VPC firewall