diff --git a/common/pkg/capi/clustertopology/variables/fromcrdyaml.go b/common/pkg/capi/clustertopology/variables/fromcrdyaml.go index 79ae62d62..9a28c37e0 100644 --- a/common/pkg/capi/clustertopology/variables/fromcrdyaml.go +++ b/common/pkg/capi/clustertopology/variables/fromcrdyaml.go @@ -5,6 +5,7 @@ package variables import ( "fmt" + "math" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" @@ -71,6 +72,39 @@ func ConvertAPIExtensionsToJSONSchemaProps( ) (*clusterv1.JSONSchemaProps, field.ErrorList) { var allErrs field.ErrorList + // Check if minimum/maximum is a whole number that we can convert to int64 without loss of precision. + var maximumAsInt64Ptr, minimumAsInt64Ptr *int64 + if schema.Maximum != nil { + maximumAsFloat64 := ptr.Deref(schema.Maximum, 0.0) + if math.Ceil(maximumAsFloat64) == maximumAsFloat64 { + maximumAsInt64Ptr = ptr.To(int64(maximumAsFloat64)) + } else { + allErrs = append( + allErrs, + field.Invalid( + fldPath.Child("maximum"), + maximumAsFloat64, + "ClusterClass variables only support a whole number for maximum", + ), + ) + } + } + if schema.Minimum != nil { + minimumAsFloat64 := ptr.Deref(schema.Minimum, 0.0) + if math.Ceil(minimumAsFloat64) == minimumAsFloat64 { + minimumAsInt64Ptr = ptr.To(int64(minimumAsFloat64)) + } else { + allErrs = append( + allErrs, + field.Invalid( + fldPath.Child("minimum"), + minimumAsFloat64, + "ClusterClass variables only support a whole number for minimum", + ), + ) + } + } + props := &clusterv1.JSONSchemaProps{ Type: schema.Type, Required: schema.Required, @@ -81,20 +115,17 @@ func ConvertAPIExtensionsToJSONSchemaProps( MaxLength: schema.MaxLength, MinLength: schema.MinLength, Pattern: schema.Pattern, + Maximum: maximumAsInt64Ptr, + Minimum: minimumAsInt64Ptr, ExclusiveMaximum: schema.ExclusiveMaximum, ExclusiveMinimum: schema.ExclusiveMinimum, XPreserveUnknownFields: ptr.Deref(schema.XPreserveUnknownFields, false), Default: schema.Default, Enum: schema.Enum, Example: schema.Example, - } - - if schema.Maximum != nil { - props.Maximum = ptr.To(int64(*schema.Maximum)) - } - - if schema.Minimum != nil { - props.Minimum = ptr.To(int64(*schema.Minimum)) + Description: schema.Description, + MaxProperties: schema.MaxProperties, + MinProperties: schema.MinProperties, } if schema.AdditionalProperties != nil && schema.AdditionalProperties.Schema != nil { @@ -157,5 +188,22 @@ func ConvertAPIExtensionsToJSONSchemaProps( } } + if schema.XValidations != nil { + props.XValidations = make([]clusterv1.ValidationRule, 0, len(schema.XValidations)) + for _, v := range schema.XValidations { + reason := "" + if v.Reason != nil { + reason = string(*v.Reason) + } + props.XValidations = append(props.XValidations, clusterv1.ValidationRule{ + Rule: v.Rule, + Message: v.Message, + MessageExpression: v.MessageExpression, + Reason: clusterv1.FieldValueErrorReason(reason), + FieldPath: v.FieldPath, + }) + } + } + return props, allErrs }