diff --git a/pkg/kube_resource/generator/testdata/int_or_string_validation/models/crd_projectcalico_org_v1_global_network_policy.k b/pkg/kube_resource/generator/testdata/int_or_string_validation/models/crd_projectcalico_org_v1_global_network_policy.k index e1fb948..e204e90 100644 --- a/pkg/kube_resource/generator/testdata/int_or_string_validation/models/crd_projectcalico_org_v1_global_network_policy.k +++ b/pkg/kube_resource/generator/testdata/int_or_string_validation/models/crd_projectcalico_org_v1_global_network_policy.k @@ -15,6 +15,8 @@ schema GlobalNetworkPolicy: action apiVersion : str, default is "crd.projectcalico.org/v1", required APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + capacity : {str:int | str}, default is Undefined, optional + A description of the virtual volume's resources and capacity kind : str, default is "GlobalNetworkPolicy", required Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds destination : CrdProjectcalicoOrgV1GlobalNetworkPolicyDestination, default is Undefined, optional @@ -28,6 +30,8 @@ schema GlobalNetworkPolicy: apiVersion: "crd.projectcalico.org/v1" = "crd.projectcalico.org/v1" + capacity?: {str:int | str} + kind: "GlobalNetworkPolicy" = "GlobalNetworkPolicy" destination?: CrdProjectcalicoOrgV1GlobalNetworkPolicyDestination @@ -35,6 +39,10 @@ schema GlobalNetworkPolicy: metadata?: v1.ObjectMeta + check: + all _, n in capacity { regex.match(str(n), r"^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$") } if capacity + + schema CrdProjectcalicoOrgV1GlobalNetworkPolicyDestination: """ Destination contains the match criteria that apply to destination entity. @@ -89,6 +97,11 @@ schema CrdProjectcalicoOrgV1GlobalNetworkPolicyDestination: services?: CrdProjectcalicoOrgV1GlobalNetworkPolicyDestinationServices + check: + all n in notPorts { regex.match(str(n), r"^.*") } if notPorts + all n in ports { regex.match(str(n), r"^.*") } if ports + + schema CrdProjectcalicoOrgV1GlobalNetworkPolicyDestinationServiceAccounts: """ ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) a pod running as a matching service account. diff --git a/pkg/kube_resource/generator/testdata/int_or_string_validation/policy.golden.yaml b/pkg/kube_resource/generator/testdata/int_or_string_validation/policy.golden.yaml index 9c30b63..610762d 100644 --- a/pkg/kube_resource/generator/testdata/int_or_string_validation/policy.golden.yaml +++ b/pkg/kube_resource/generator/testdata/int_or_string_validation/policy.golden.yaml @@ -18,6 +18,16 @@ spec: properties: action: type: string + capacity: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: A description of the virtual volume's resources + and capacity + type: object destination: description: Destination contains the match criteria that apply to destination entity. diff --git a/pkg/swagger/generator/model.go b/pkg/swagger/generator/model.go index 613c0db..be97e69 100644 --- a/pkg/swagger/generator/model.go +++ b/pkg/swagger/generator/model.go @@ -487,10 +487,20 @@ func hasSliceValidations(model *spec.Schema) (hasSliceValidations bool) { return } +func hasItemAllPatternValidation(model *spec.Schema) (hasItemAllPatternValidation bool) { + if model.Items != nil && model.Items.Schema != nil && model.Items.Schema.Pattern != "" { + hasItemAllPatternValidation = true + } + if model.AdditionalProperties != nil && model.AdditionalProperties.Schema != nil && model.AdditionalProperties.Schema.Pattern != "" { + hasItemAllPatternValidation = true + } + return +} + func hasValidations(model *spec.Schema) (hasValidation bool) { hasNumberValidation := model.Maximum != nil || model.Minimum != nil || model.MultipleOf != nil hasStringValidation := model.MaxLength != nil || model.MinLength != nil || model.Pattern != "" - hasValidation = hasNumberValidation || hasStringValidation || hasSliceValidations(model) + hasValidation = hasNumberValidation || hasStringValidation || hasSliceValidations(model) || hasItemAllPatternValidation(model) return } diff --git a/pkg/swagger/generator/shared.go b/pkg/swagger/generator/shared.go index 18a8d76..9c96a37 100644 --- a/pkg/swagger/generator/shared.go +++ b/pkg/swagger/generator/shared.go @@ -377,6 +377,12 @@ func sharedValidationsFromSchema(v spec.Schema, sg schemaGenContext) (sh sharedV MultipleOf: v.MultipleOf, Enum: v.Enum, } + if v.Items != nil && v.Items.Schema != nil && v.Items.Schema.Pattern != "" { + sh.ItemPattern = v.Items.Schema.Pattern + } + if v.AdditionalProperties != nil && v.AdditionalProperties.Schema != nil && v.AdditionalProperties.Schema.Pattern != "" { + sh.AdditionalPropertiesPattern = v.AdditionalProperties.Schema.Pattern + } sh.pruneEnums(sg) return } diff --git a/pkg/swagger/generator/structs.go b/pkg/swagger/generator/structs.go index 773e64c..afbc9d1 100644 --- a/pkg/swagger/generator/structs.go +++ b/pkg/swagger/generator/structs.go @@ -155,6 +155,9 @@ type sharedValidations struct { NeedsSize bool // NOTE: "patternProperties" and "dependencies" not supported by Swagger 2.0 + + ItemPattern string + AdditionalPropertiesPattern string } // pruneEnums omit nil from enum values diff --git a/pkg/swagger/generator/templates/schemavalidator.gotmpl b/pkg/swagger/generator/templates/schemavalidator.gotmpl index 1bc1f2f..17911d1 100644 --- a/pkg/swagger/generator/templates/schemavalidator.gotmpl +++ b/pkg/swagger/generator/templates/schemavalidator.gotmpl @@ -1,6 +1,6 @@ {{- define "schemavalidator" -}} {{- range . -}} -{{- if or .Maximum .Minimum .MaxLength .MinLength .Pattern .UniqueItems .MinItems .MaxItems .MultipleOf }} +{{- if or .Maximum .Minimum .MaxLength .MinLength .Pattern .UniqueItems .MinItems .MaxItems .MultipleOf .ItemPattern .AdditionalPropertiesPattern }} {{- if .Maximum }} {{ if .ExclusiveMaximum }}{{ .EscapedName }} < {{.Maximum}}{{- else }}{{ .EscapedName }} <= {{.Maximum}}{{ end }} {{- end }} @@ -28,6 +28,12 @@ {{- if .MultipleOf }} multiplyof(int({{ .EscapedName }}), int({{ .MultipleOf }})) {{- end }} + {{- if and .ItemPattern }} + all n in {{ .EscapedName }} { regex.match(str(n), r"{{ .ItemPattern }}") }{{ if not .Required }} if {{ .EscapedName }}{{ end }} + {{- end }} + {{- if and .AdditionalPropertiesPattern }} + all _, n in {{ .EscapedName }} { regex.match(str(n), r"{{ .AdditionalPropertiesPattern }}") }{{ if not .Required }} if {{ .EscapedName }}{{ end }} + {{- end }} {{- end -}} {{- end -}} {{- end -}} diff --git a/pkg/swagger/generator/types.go b/pkg/swagger/generator/types.go index 44c166d..f5af367 100644 --- a/pkg/swagger/generator/types.go +++ b/pkg/swagger/generator/types.go @@ -274,10 +274,6 @@ func (t *typeResolver) resolveArray(schema *spec.Schema, isAnonymous, isRequired err = er return } - // walk around: [int | str] has no validations - if rt.KclType == typeMapping[intOrStr] { - schema.Items.Schema.Pattern = "" - } result.KclType = "[" + rt.KclType + "]" result.ElemType = &rt result.SwaggerType = array