diff --git a/.golangci-kal.yml b/.golangci-kal.yml index e6e1ef85b4dc..624c0fd849bb 100644 --- a/.golangci-kal.yml +++ b/.golangci-kal.yml @@ -23,6 +23,8 @@ linters: - "nobools" # Bools do not evolve over time, should use enums instead. - "nofloats" # Ensure floats are not used. - "nomaps" # Ensure maps are not used. + - "optionalfields" # Ensure that all fields marked as optional adhere to being pointers and + # having the `omitempty` value in their `json` tag where appropriate. - "optionalorrequired" # Every field should be marked as `+optional` or `+required`. - "requiredfields" # Required fields should not be pointers, and should not have `omitempty`. - "statusoptional" # Ensure all first children within status should be optional. @@ -42,6 +44,12 @@ linters: isFirstField: Warn # Require conditions to be the first field in the status struct. usePatchStrategy: Forbid # Require conditions to be the first field in the status struct. useProtobuf: Forbid # We don't use protobuf, so protobuf tags are not required. + optionalFields: + pointers: + preference: WhenRequired # Always | WhenRequired # Whether to always require pointers, or only when required. Defaults to `Always`. + policy: SuggestFix # SuggestFix | Warn # The policy for pointers in optional fields. Defaults to `SuggestFix`. + omitempty: + policy: SuggestFix # SuggestFix | Warn | Ignore # The policy for omitempty in optional fields. Defaults to `SuggestFix`. # jsonTags: # jsonTagRegex: "^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$" # The default regex is appropriate for our use case. # optionalOrRequired: @@ -96,6 +104,14 @@ linters: text: "nomaps: FailureDomains should not use a map type, use a list type with a unique name/identifier instead" linters: - kubeapilinter + - path: "api/addons/v1beta1/*|api/bootstrap/kubeadm/v1beta1/*|api/controlplane/kubeadm/v1beta1/*|api/core/v1beta1/*|api/ipam/v1beta1/*|api/ipam/v1alpha1/*|api/runtime/v1alpha1/*|cmd/clusterctl/api/v1alpha3/*" + text: "optionalfields" + linters: + - kubeapilinter + - path: "api/core/v1beta1/clusterclass_types.go" + text: "field Ref is marked as required, should not be a pointer" + linters: + - kubeapilinter ## Excludes for clusterctl and Runtime Hooks (can be fixed once we bump their apiVersion) - path: "cmd/clusterctl/api/v1alpha3|api/runtime/hooks/v1alpha1" @@ -134,14 +150,60 @@ linters: linters: - kubeapilinter + ## Excludes for optionalfields + # Empty Bootstrap object is blocked via validating webhooks. This cannot be detected by KAL (same if we move the validation to CEL). + - path: "api/core/v1beta2/machine_types.go" + text: "optionalfields: field (Bootstrap) is optional and (should be a pointer|should have the omitempty tag|has a valid zero value)" + linters: + - kubeapilinter + # KAL incorrectly reports that the Taints field doesn't have to be a pointer (it has to be to preserve []). + - path: "api/bootstrap/kubeadm/v1beta2/kubeadm_types.go" + text: "optionalfields: field Taints is optional but the underlying type does not need to be a pointer. The pointer should be removed." + linters: + - kubeapilinter + ## TODO: The following rules are disabled until we migrate to the new API. # Note: Maybe this has to stay a pointer for marshalling reasons. - path: "api/bootstrap/kubeadm/v1beta2/kubeadm_types.go|api/bootstrap/kubeadm/v1beta1/kubeadm_types.go" text: "field Token is marked as required, should not be a pointer" linters: - kubeapilinter - - path: "api/core/v1beta2/clusterclass_types.go|api/core/v1beta1/clusterclass_types.go" - text: "field Ref is marked as required, should not be a pointer" + + # Audit the entire hook types + builtins from a serialization point of view when bumping the API (this is not a CRD) + - path: "api/runtime/hooks/v1alpha1/*" + text: "optionalfields" + linters: + - kubeapilinter + + # KAL does not handle omitzero correctly yet: https://github.com/kubernetes-sigs/kube-api-linter/pull/115 + - path: "api/.*" + text: "optionalfields: field Status is optional and should (be a pointer|have the omitempty tag)" + linters: + - kubeapilinter + - path: "api/bootstrap/kubeadm/v1beta2/*" + text: "optionalfields: field (Spec|NodeRegistration|LocalAPIEndpoint|Etcd|APIServer|ControllerManager|Scheduler|DNS|Discovery|ObjectMeta) is optional and should (be a pointer|have the omitempty tag)" + linters: + - kubeapilinter + - path: "api/controlplane/kubeadm/v1beta2/*" + text: "optionalfields: field (Spec|ObjectMeta|KubeadmConfigSpec) is optional and should (be a pointer|have the omitempty tag)" + linters: + - kubeapilinter + - path: "api/core/v1beta2/cluster_types.go" + text: "optionalfields: field (ControlPlaneEndpoint|ControlPlane|Metadata) is optional and should (be a pointer|have the omitempty tag)" + linters: + - kubeapilinter + - path: "api/core/v1beta2/clusterclass_types.go" + text: "optionalfields: field (Workers|Metadata|ControlPlane|Infrastructure|DeprecatedV1Beta1Metadata) is optional and should (be a pointer|have the omitempty tag)" + linters: + - kubeapilinter + - path: "api/ipam/v1beta2/ipaddressclaim_types.go" + text: "optionalfields: field AddressRef is optional and should (be a pointer|have the omitempty tag)" + linters: + - kubeapilinter + + # KAL does not handle enum markers on enum types yet: https://github.com/kubernetes-sigs/kube-api-linter/issues/113 + - path: ".*" + text: "optionalfields: field (Format|Encoding|Type|DeletePolicy) is optional and (should be a pointer|has a valid zero value)" linters: - kubeapilinter issues: diff --git a/api/bootstrap/kubeadm/v1beta1/conversion.go b/api/bootstrap/kubeadm/v1beta1/conversion.go index 6641118f2e89..4b05c76c658e 100644 --- a/api/bootstrap/kubeadm/v1beta1/conversion.go +++ b/api/bootstrap/kubeadm/v1beta1/conversion.go @@ -375,6 +375,14 @@ func Convert_v1beta2_KubeadmConfigStatus_To_v1beta1_KubeadmConfigStatus(in *boot return nil } +func Convert_v1beta2_ControllerManager_To_v1beta1_ControlPlaneComponent(in *bootstrapv1.ControllerManager, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + return Convert_v1beta2_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + +func Convert_v1beta2_Scheduler_To_v1beta1_ControlPlaneComponent(in *bootstrapv1.Scheduler, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + return Convert_v1beta2_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + func Convert_v1beta2_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in *bootstrapv1.ControlPlaneComponent, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { // Following fields require a custom conversions. out.ExtraArgs = bootstrapv1.ConvertFromArgs(in.ExtraArgs) @@ -390,6 +398,11 @@ func Convert_v1beta2_LocalEtcd_To_v1beta1_LocalEtcd(in *bootstrapv1.LocalEtcd, o func Convert_v1beta2_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, out *NodeRegistrationOptions, s apimachineryconversion.Scope) error { // Following fields require a custom conversions. out.KubeletExtraArgs = bootstrapv1.ConvertFromArgs(in.KubeletExtraArgs) + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = *in.Taints + } return autoConvert_v1beta2_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in, out, s) } @@ -406,6 +419,14 @@ func Convert_v1beta1_APIServer_To_v1beta2_APIServer(in *APIServer, out *bootstra return autoConvert_v1beta1_APIServer_To_v1beta2_APIServer(in, out, s) } +func Convert_v1beta1_ControlPlaneComponent_To_v1beta2_ControllerManager(in *ControlPlaneComponent, out *bootstrapv1.ControllerManager, s apimachineryconversion.Scope) error { + return Convert_v1beta1_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + +func Convert_v1beta1_ControlPlaneComponent_To_v1beta2_Scheduler(in *ControlPlaneComponent, out *bootstrapv1.Scheduler, s apimachineryconversion.Scope) error { + return Convert_v1beta1_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + func Convert_v1beta1_Discovery_To_v1beta2_Discovery(in *Discovery, out *bootstrapv1.Discovery, s apimachineryconversion.Scope) error { // Timeout has been removed in v1beta2 return autoConvert_v1beta1_Discovery_To_v1beta2_Discovery(in, out, s) @@ -432,6 +453,11 @@ func Convert_v1beta1_LocalEtcd_To_v1beta2_LocalEtcd(in *LocalEtcd, out *bootstra func Convert_v1beta1_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *bootstrapv1.NodeRegistrationOptions, s apimachineryconversion.Scope) error { out.KubeletExtraArgs = bootstrapv1.ConvertToArgs(in.KubeletExtraArgs) + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = ptr.To(in.Taints) + } return autoConvert_v1beta1_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in, out, s) } diff --git a/api/bootstrap/kubeadm/v1beta1/conversion_test.go b/api/bootstrap/kubeadm/v1beta1/conversion_test.go index 5ce4917ca713..c043b8d2e5e3 100644 --- a/api/bootstrap/kubeadm/v1beta1/conversion_test.go +++ b/api/bootstrap/kubeadm/v1beta1/conversion_test.go @@ -65,6 +65,7 @@ func KubeadmConfigFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { spokeBootstrapTokenString, spokeBootstrapToken, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, } } @@ -78,6 +79,7 @@ func KubeadmConfigTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []interfac hubBootstrapTokenString, spokeBootstrapToken, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, } } @@ -128,6 +130,14 @@ func hubKubeadmConfigSpec(in *bootstrapv1.KubeadmConfigSpec, c randfill.Continue } } +func hubNodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, c randfill.Continue) { + c.FillNoCustom(in) + + if in.Taints != nil && *in.Taints == nil { + in.Taints = nil + } +} + func spokeKubeadmConfigSpec(in *KubeadmConfigSpec, c randfill.Continue) { c.FillNoCustom(in) diff --git a/api/bootstrap/kubeadm/v1beta1/zz_generated.conversion.go b/api/bootstrap/kubeadm/v1beta1/zz_generated.conversion.go index 17a8d2f0e8b7..c0d6e9ae4e2a 100644 --- a/api/bootstrap/kubeadm/v1beta1/zz_generated.conversion.go +++ b/api/bootstrap/kubeadm/v1beta1/zz_generated.conversion.go @@ -450,6 +450,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.ControllerManager)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ControlPlaneComponent_To_v1beta2_ControllerManager(a.(*ControlPlaneComponent), b.(*v1beta2.ControllerManager), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.Scheduler)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_ControlPlaneComponent_To_v1beta2_Scheduler(a.(*ControlPlaneComponent), b.(*v1beta2.Scheduler), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*Discovery)(nil), (*v1beta2.Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_Discovery_To_v1beta2_Discovery(a.(*Discovery), b.(*v1beta2.Discovery), scope) }); err != nil { @@ -500,6 +510,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.ControllerManager)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ControllerManager_To_v1beta1_ControlPlaneComponent(a.(*v1beta2.ControllerManager), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.InitConfiguration)(nil), (*InitConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_InitConfiguration_To_v1beta1_InitConfiguration(a.(*v1beta2.InitConfiguration), b.(*InitConfiguration), scope) }); err != nil { @@ -530,6 +545,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.Scheduler)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Scheduler_To_v1beta1_ControlPlaneComponent(a.(*v1beta2.Scheduler), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } return nil } @@ -660,10 +680,10 @@ func autoConvert_v1beta1_ClusterConfiguration_To_v1beta2_ClusterConfiguration(in if err := Convert_v1beta1_APIServer_To_v1beta2_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_v1beta1_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_v1beta1_ControlPlaneComponent_To_v1beta2_ControllerManager(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_v1beta1_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_v1beta1_ControlPlaneComponent_To_v1beta2_Scheduler(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_v1beta1_DNS_To_v1beta2_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -684,10 +704,10 @@ func autoConvert_v1beta2_ClusterConfiguration_To_v1beta1_ClusterConfiguration(in if err := Convert_v1beta2_APIServer_To_v1beta1_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_v1beta2_ControllerManager_To_v1beta1_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_v1beta2_Scheduler_To_v1beta1_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_v1beta2_DNS_To_v1beta1_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -1955,7 +1975,7 @@ func Convert_v1beta2_NTP_To_v1beta1_NTP(in *v1beta2.NTP, out *NTP, s conversion. func autoConvert_v1beta1_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *v1beta2.NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types ([]k8s.io/api/core/v1.Taint vs *[]k8s.io/api/core/v1.Taint) // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2.Arg) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy) @@ -1966,7 +1986,7 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOpti func autoConvert_v1beta2_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in *v1beta2.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types (*[]k8s.io/api/core/v1.Taint vs []k8s.io/api/core/v1.Taint) // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2.Arg vs map[string]string) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = string(in.ImagePullPolicy) diff --git a/api/bootstrap/kubeadm/v1beta2/kubeadm_types.go b/api/bootstrap/kubeadm/v1beta2/kubeadm_types.go index cc3151181c91..3fc0ee91b0fb 100644 --- a/api/bootstrap/kubeadm/v1beta2/kubeadm_types.go +++ b/api/bootstrap/kubeadm/v1beta2/kubeadm_types.go @@ -17,7 +17,6 @@ limitations under the License. package v1beta2 import ( - "encoding/json" "fmt" "strings" @@ -85,7 +84,7 @@ type InitConfiguration struct { // When used in the context of control plane nodes, NodeRegistration should remain consistent // across both InitConfiguration and JoinConfiguration // +optional - NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"` + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty,omitzero"` // localAPIEndpoint represents the endpoint of the API server instance that's deployed on this control plane node // In HA setups, this differs from ClusterConfiguration.ControlPlaneEndpoint in the sense that ControlPlaneEndpoint @@ -94,7 +93,7 @@ type InitConfiguration struct { // on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process // fails you may set the desired value here. // +optional - LocalAPIEndpoint APIEndpoint `json:"localAPIEndpoint,omitempty"` + LocalAPIEndpoint APIEndpoint `json:"localAPIEndpoint,omitempty,omitzero"` // skipPhases is a list of phases to skip during command execution. // The list of phases can be obtained with the "kubeadm init --help" command. @@ -120,7 +119,7 @@ type ClusterConfiguration struct { // etcd holds configuration for etcd. // NB: This value defaults to a Local (stacked) etcd // +optional - Etcd Etcd `json:"etcd,omitempty"` + Etcd Etcd `json:"etcd,omitempty,omitzero"` // controlPlaneEndpoint sets a stable IP address or DNS name for the control plane; it // can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port. @@ -141,19 +140,19 @@ type ClusterConfiguration struct { // apiServer contains extra settings for the API server control plane component // +optional - APIServer APIServer `json:"apiServer,omitempty"` + APIServer APIServer `json:"apiServer,omitempty,omitzero"` // controllerManager contains extra settings for the controller manager control plane component // +optional - ControllerManager ControlPlaneComponent `json:"controllerManager,omitempty"` + ControllerManager ControllerManager `json:"controllerManager,omitempty,omitzero"` // scheduler contains extra settings for the scheduler control plane component // +optional - Scheduler ControlPlaneComponent `json:"scheduler,omitempty"` + Scheduler Scheduler `json:"scheduler,omitempty,omitzero"` // dns defines the options for the DNS add-on installed in the cluster. // +optional - DNS DNS `json:"dns,omitempty"` + DNS DNS `json:"dns,omitempty,omitzero"` // certificatesDir specifies where to store or look for all required certificates. // NB: if not provided, this will default to `/etc/kubernetes/pki` @@ -211,6 +210,7 @@ type ControlPlaneComponent struct { } // APIServer holds settings necessary for API server deployments in the cluster. +// +kubebuilder:validation:MinProperties=1 type APIServer struct { ControlPlaneComponent `json:",inline"` @@ -222,7 +222,20 @@ type APIServer struct { CertSANs []string `json:"certSANs,omitempty"` } +// ControllerManager holds settings necessary for controller-manager deployments in the cluster. +// +kubebuilder:validation:MinProperties=1 +type ControllerManager struct { + ControlPlaneComponent `json:",inline"` +} + +// Scheduler holds settings necessary for scheduler deployments in the cluster. +// +kubebuilder:validation:MinProperties=1 +type Scheduler struct { + ControlPlaneComponent `json:",inline"` +} + // DNS defines the DNS addon that should be used in the cluster. +// +kubebuilder:validation:MinProperties=1 type DNS struct { // ImageMeta allows to customize the image used for the DNS component ImageMeta `json:",inline"` @@ -249,6 +262,7 @@ type ImageMeta struct { } // APIEndpoint struct contains elements of API server instance deployed on a node. +// +kubebuilder:validation:MinProperties=1 type APIEndpoint struct { // advertiseAddress sets the IP address for the API server to advertise. // +optional @@ -265,8 +279,8 @@ type APIEndpoint struct { // NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via "kubeadm init" or "kubeadm join". // Note: The NodeRegistrationOptions struct has to be kept in sync with the structs in MarshalJSON. +// +kubebuilder:validation:MinProperties=1 type NodeRegistrationOptions struct { - // name is the `.Metadata.Name` field of the Node API object that will be created in this `kubeadm init` or `kubeadm join` operation. // This field is also used in the CommonName field of the kubelet's client certificate to the API server. // Defaults to the hostname of the node if not provided. @@ -285,8 +299,9 @@ type NodeRegistrationOptions struct { // it will be defaulted to []v1.Taint{'node-role.kubernetes.io/master=""'}. If you don't want to taint your control-plane node, set this field to an // empty slice, i.e. `taints: []` in the YAML file. This field is solely used for Node registration. // +optional + // +kubebuilder:validation:MinItems=0 // +kubebuilder:validation:MaxItems=100 - Taints []corev1.Taint `json:"taints,omitempty"` + Taints *[]corev1.Taint `json:"taints,omitempty"` // kubeletExtraArgs is a list of args to pass to kubelet. // The arg name must match the command line flag name except without leading dash(es). @@ -311,8 +326,7 @@ type NodeRegistrationOptions struct { // imagePullPolicy specifies the policy for image pulling // during kubeadm "init" and "join" operations. The value of // this field must be one of "Always", "IfNotPresent" or - // "Never". Defaults to "IfNotPresent". This can be used only - // with Kubernetes version equal to 1.22 and later. + // "Never". Defaults to "IfNotPresent". // +kubebuilder:validation:Enum=Always;IfNotPresent;Never // +optional ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` @@ -324,57 +338,6 @@ type NodeRegistrationOptions struct { ImagePullSerial *bool `json:"imagePullSerial,omitempty"` } -// MarshalJSON marshals NodeRegistrationOptions in a way that an empty slice in Taints is preserved. -// Taints are then rendered as: -// * nil => omitted from the marshalled JSON -// * [] => rendered as empty array (`[]`) -// * [regular-array] => rendered as usual -// We have to do this as the regular Golang JSON marshalling would just omit -// the empty slice (xref: https://github.com/golang/go/issues/22480). -// Note: We can't re-use the original struct as that would lead to an infinite recursion. -// Note: The structs in this func have to be kept in sync with the NodeRegistrationOptions struct. -func (n *NodeRegistrationOptions) MarshalJSON() ([]byte, error) { - // Marshal an empty Taints slice array without omitempty so it's preserved. - if n.Taints != nil && len(n.Taints) == 0 { - return json.Marshal(struct { - Name string `json:"name,omitempty"` - CRISocket string `json:"criSocket,omitempty"` - Taints []corev1.Taint `json:"taints"` - KubeletExtraArgs []Arg `json:"kubeletExtraArgs,omitempty"` - IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"` - ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` - ImagePullSerial *bool `json:"imagePullSerial,omitempty"` - }{ - Name: n.Name, - CRISocket: n.CRISocket, - Taints: n.Taints, - KubeletExtraArgs: n.KubeletExtraArgs, - IgnorePreflightErrors: n.IgnorePreflightErrors, - ImagePullPolicy: n.ImagePullPolicy, - ImagePullSerial: n.ImagePullSerial, - }) - } - - // If Taints is nil or not empty we can use omitempty. - return json.Marshal(struct { - Name string `json:"name,omitempty"` - CRISocket string `json:"criSocket,omitempty"` - Taints []corev1.Taint `json:"taints,omitempty"` - KubeletExtraArgs []Arg `json:"kubeletExtraArgs,omitempty"` - IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"` - ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` - ImagePullSerial *bool `json:"imagePullSerial,omitempty"` - }{ - Name: n.Name, - CRISocket: n.CRISocket, - Taints: n.Taints, - KubeletExtraArgs: n.KubeletExtraArgs, - IgnorePreflightErrors: n.IgnorePreflightErrors, - ImagePullPolicy: n.ImagePullPolicy, - ImagePullSerial: n.ImagePullSerial, - }) -} - // BootstrapToken describes one bootstrap token, stored as a Secret in the cluster. type BootstrapToken struct { // token is used for establishing bidirectional trust between nodes and control-planes. @@ -413,8 +376,8 @@ type BootstrapToken struct { } // Etcd contains elements describing Etcd configuration. +// +kubebuilder:validation:MinProperties=1 type Etcd struct { - // local provides configuration knobs for configuring the local etcd instance // Local and External are mutually exclusive // +optional @@ -511,7 +474,7 @@ type JoinConfiguration struct { // When used in the context of control plane nodes, NodeRegistration should remain consistent // across both InitConfiguration and JoinConfiguration // +optional - NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty"` + NodeRegistration NodeRegistrationOptions `json:"nodeRegistration,omitempty,omitzero"` // caCertPath is the path to the SSL certificate authority used to // secure communications between node and control-plane. @@ -525,7 +488,7 @@ type JoinConfiguration struct { // discovery specifies the options for the kubelet to use during the TLS Bootstrap process // +optional // TODO: revisit when there is defaulting from k/k - Discovery Discovery `json:"discovery,omitempty"` + Discovery Discovery `json:"discovery,omitempty,omitzero"` // controlPlane defines the additional control plane instance to be deployed on the joining node. // If nil, no additional control plane instance will be deployed. @@ -555,10 +518,11 @@ type JoinConfiguration struct { type JoinControlPlane struct { // localAPIEndpoint represents the endpoint of the API server instance to be deployed on this node. // +optional - LocalAPIEndpoint APIEndpoint `json:"localAPIEndpoint,omitempty"` + LocalAPIEndpoint APIEndpoint `json:"localAPIEndpoint,omitempty,omitzero"` } // Discovery specifies the options for the kubelet to use during the TLS Bootstrap process. +// +kubebuilder:validation:MinProperties=1 type Discovery struct { // bootstrapToken is used to set the options for bootstrap token based discovery // BootstrapToken and File are mutually exclusive diff --git a/api/bootstrap/kubeadm/v1beta2/kubeadm_types_test.go b/api/bootstrap/kubeadm/v1beta2/kubeadm_types_test.go index f41a87dcf0b3..f1cd03453448 100644 --- a/api/bootstrap/kubeadm/v1beta2/kubeadm_types_test.go +++ b/api/bootstrap/kubeadm/v1beta2/kubeadm_types_test.go @@ -23,66 +23,8 @@ import ( "github.com/google/go-cmp/cmp" . "github.com/onsi/gomega" "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" ) -func TestNodeRegistrationOptionsMarshalJSON(t *testing.T) { - var tests = []struct { - name string - opts NodeRegistrationOptions - expected string - }{ - { - name: "marshal nil taints", - opts: NodeRegistrationOptions{ - Name: "node-1", - CRISocket: "unix:///var/run/containerd/containerd.sock", - Taints: nil, - KubeletExtraArgs: []Arg{{Name: "abc", Value: "def"}}, - IgnorePreflightErrors: []string{"ignore-1"}, - }, - expected: `{"name":"node-1","criSocket":"unix:///var/run/containerd/containerd.sock","kubeletExtraArgs":[{"name":"abc","value":"def"}],"ignorePreflightErrors":["ignore-1"]}`, - }, - { - name: "marshal empty taints", - opts: NodeRegistrationOptions{ - Name: "node-1", - CRISocket: "unix:///var/run/containerd/containerd.sock", - Taints: []corev1.Taint{}, - KubeletExtraArgs: []Arg{{Name: "abc", Value: "def"}}, - IgnorePreflightErrors: []string{"ignore-1"}, - }, - expected: `{"name":"node-1","criSocket":"unix:///var/run/containerd/containerd.sock","taints":[],"kubeletExtraArgs":[{"name":"abc","value":"def"}],"ignorePreflightErrors":["ignore-1"]}`, - }, - { - name: "marshal regular taints", - opts: NodeRegistrationOptions{ - Name: "node-1", - CRISocket: "unix:///var/run/containerd/containerd.sock", - Taints: []corev1.Taint{ - { - Key: "key", - Value: "value", - Effect: "effect", - }, - }, - KubeletExtraArgs: []Arg{{Name: "abc", Value: "def"}}, - IgnorePreflightErrors: []string{"ignore-1"}, - }, - expected: `{"name":"node-1","criSocket":"unix:///var/run/containerd/containerd.sock","taints":[{"key":"key","value":"value","effect":"effect"}],"kubeletExtraArgs":[{"name":"abc","value":"def"}],"ignorePreflightErrors":["ignore-1"]}`, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - g := NewWithT(t) - - b, err := tt.opts.MarshalJSON() - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(string(b)).To(Equal(tt.expected)) - }) - } -} - func TestBootstrapTokenStringMarshalJSON(t *testing.T) { var tests = []struct { bts BootstrapTokenString diff --git a/api/bootstrap/kubeadm/v1beta2/kubeadmconfigtemplate_types.go b/api/bootstrap/kubeadm/v1beta2/kubeadmconfigtemplate_types.go index d29848acb81a..7b62cfd65eeb 100644 --- a/api/bootstrap/kubeadm/v1beta2/kubeadmconfigtemplate_types.go +++ b/api/bootstrap/kubeadm/v1beta2/kubeadmconfigtemplate_types.go @@ -35,7 +35,7 @@ type KubeadmConfigTemplateResource struct { // metadata is the standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // spec is the desired state of KubeadmConfig. // +optional diff --git a/api/bootstrap/kubeadm/v1beta2/zz_generated.deepcopy.go b/api/bootstrap/kubeadm/v1beta2/zz_generated.deepcopy.go index d9f391299523..083339f15efe 100644 --- a/api/bootstrap/kubeadm/v1beta2/zz_generated.deepcopy.go +++ b/api/bootstrap/kubeadm/v1beta2/zz_generated.deepcopy.go @@ -238,6 +238,22 @@ func (in *ControlPlaneComponent) DeepCopy() *ControlPlaneComponent { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControllerManager) DeepCopyInto(out *ControllerManager) { + *out = *in + in.ControlPlaneComponent.DeepCopyInto(&out.ControlPlaneComponent) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControllerManager. +func (in *ControllerManager) DeepCopy() *ControllerManager { + if in == nil { + return nil + } + out := new(ControllerManager) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DNS) DeepCopyInto(out *DNS) { *out = *in @@ -1161,9 +1177,13 @@ func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) { *out = *in if in.Taints != nil { in, out := &in.Taints, &out.Taints - *out = make([]v1.Taint, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) + *out = new([]v1.Taint) + if **in != nil { + in, out := *in, *out + *out = make([]v1.Taint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } } if in.KubeletExtraArgs != nil { @@ -1244,6 +1264,22 @@ func (in *Patches) DeepCopy() *Patches { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Scheduler) DeepCopyInto(out *Scheduler) { + *out = *in + in.ControlPlaneComponent.DeepCopyInto(&out.ControlPlaneComponent) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Scheduler. +func (in *Scheduler) DeepCopy() *Scheduler { + if in == nil { + return nil + } + out := new(Scheduler) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SecretFileSource) DeepCopyInto(out *SecretFileSource) { *out = *in diff --git a/api/controlplane/kubeadm/v1beta1/conversion_test.go b/api/controlplane/kubeadm/v1beta1/conversion_test.go index 3252c3118d64..51efa3bb15b0 100644 --- a/api/controlplane/kubeadm/v1beta1/conversion_test.go +++ b/api/controlplane/kubeadm/v1beta1/conversion_test.go @@ -82,6 +82,7 @@ func KubeadmControlPlaneFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{ spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeRemediationStrategy, spokeKubeadmControlPlaneMachineTemplate, spokeBootstrapToken, @@ -97,6 +98,7 @@ func KubeadmControlPlaneTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []in spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeRemediationStrategy, spokeKubeadmControlPlaneTemplateMachineTemplate, spokeBootstrapToken, @@ -122,6 +124,14 @@ func hubKubeadmConfigSpec(in *bootstrapv1.KubeadmConfigSpec, c randfill.Continue } } +func hubNodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, c randfill.Continue) { + c.FillNoCustom(in) + + if in.Taints != nil && *in.Taints == nil { + in.Taints = nil + } +} + func hubBootstrapTokenString(in *bootstrapv1.BootstrapTokenString, _ randfill.Continue) { in.ID = fakeID in.Secret = fakeSecret diff --git a/api/controlplane/kubeadm/v1beta2/kubeadm_control_plane_types.go b/api/controlplane/kubeadm/v1beta2/kubeadm_control_plane_types.go index 763b8e82b4a2..6aef3141385a 100644 --- a/api/controlplane/kubeadm/v1beta2/kubeadm_control_plane_types.go +++ b/api/controlplane/kubeadm/v1beta2/kubeadm_control_plane_types.go @@ -480,7 +480,7 @@ type KubeadmControlPlaneMachineTemplate struct { // metadata is the standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // infrastructureRef is a required reference to a custom resource // offered by an infrastructure provider. diff --git a/api/controlplane/kubeadm/v1beta2/kubeadmcontrolplanetemplate_types.go b/api/controlplane/kubeadm/v1beta2/kubeadmcontrolplanetemplate_types.go index b75667e38b07..dc5c4219e404 100644 --- a/api/controlplane/kubeadm/v1beta2/kubeadmcontrolplanetemplate_types.go +++ b/api/controlplane/kubeadm/v1beta2/kubeadmcontrolplanetemplate_types.go @@ -72,7 +72,7 @@ type KubeadmControlPlaneTemplateResource struct { // metadata is the standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // spec is the desired state of KubeadmControlPlaneTemplateResource. // +optional @@ -134,7 +134,7 @@ type KubeadmControlPlaneTemplateMachineTemplate struct { // metadata is the standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // nodeDrainTimeoutSeconds is the total amount of time that the controller will spend on draining a controlplane node // The default value is 0, meaning that the node can be drained without any time limitations. diff --git a/api/core/v1beta1/conversion.go b/api/core/v1beta1/conversion.go index 08be7578904e..cb05e1f055a2 100644 --- a/api/core/v1beta1/conversion.go +++ b/api/core/v1beta1/conversion.go @@ -650,7 +650,8 @@ func Convert_v1beta2_InfrastructureClass_To_v1beta1_LocalObjectTemplate(in *clus return nil } - return Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(&in.ClusterClassTemplate, out, s) + Convert_v1beta2_ClusterClassTemplateReference_To_v1beta1_LocalObjectTemplate(&in.TemplateRef, out, s) + return nil } func Convert_v1beta1_ClusterClassSpec_To_v1beta2_ClusterClassSpec(in *ClusterClassSpec, out *clusterv1.ClusterClassSpec, s apimachineryconversion.Scope) error { @@ -705,7 +706,8 @@ func Convert_v1beta1_LocalObjectTemplate_To_v1beta2_InfrastructureClass(in *Loca return nil } - return Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(in, &out.ClusterClassTemplate, s) + convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil } func Convert_v1beta1_ControlPlaneClass_To_v1beta2_ControlPlaneClass(in *ControlPlaneClass, out *clusterv1.ControlPlaneClass, s apimachineryconversion.Scope) error { @@ -715,7 +717,8 @@ func Convert_v1beta1_ControlPlaneClass_To_v1beta2_ControlPlaneClass(in *ControlP out.NodeDrainTimeoutSeconds = clusterv1.ConvertToSeconds(in.NodeDrainTimeout) out.NodeVolumeDetachTimeoutSeconds = clusterv1.ConvertToSeconds(in.NodeVolumeDetachTimeout) out.NodeDeletionTimeoutSeconds = clusterv1.ConvertToSeconds(in.NodeDeletionTimeout) - return Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(&in.LocalObjectTemplate, &out.ClusterClassTemplate, s) + convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(&in.LocalObjectTemplate, &out.TemplateRef, s) + return nil } func Convert_v1beta2_ControlPlaneClass_To_v1beta1_ControlPlaneClass(in *clusterv1.ControlPlaneClass, out *ControlPlaneClass, s apimachineryconversion.Scope) error { @@ -725,7 +728,8 @@ func Convert_v1beta2_ControlPlaneClass_To_v1beta1_ControlPlaneClass(in *clusterv out.NodeDrainTimeout = clusterv1.ConvertFromSeconds(in.NodeDrainTimeoutSeconds) out.NodeVolumeDetachTimeout = clusterv1.ConvertFromSeconds(in.NodeVolumeDetachTimeoutSeconds) out.NodeDeletionTimeout = clusterv1.ConvertFromSeconds(in.NodeDeletionTimeoutSeconds) - return Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(&in.ClusterClassTemplate, &out.LocalObjectTemplate, s) + Convert_v1beta2_ClusterClassTemplateReference_To_v1beta1_LocalObjectTemplate(&in.TemplateRef, &out.LocalObjectTemplate, s) + return nil } func Convert_v1beta1_ControlPlaneTopology_To_v1beta2_ControlPlaneTopology(in *ControlPlaneTopology, out *clusterv1.ControlPlaneTopology, s apimachineryconversion.Scope) error { @@ -1583,30 +1587,78 @@ func Convert_v1beta2_MachineNodeReference_To_v1_ObjectReference(in *clusterv1.Ma return nil } -func Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(in *LocalObjectTemplate, out *clusterv1.ClusterClassTemplate, _ apimachineryconversion.Scope) error { - if in.Ref == nil { - return nil +func Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ControlPlaneClassMachineInfrastructureTemplate(in *LocalObjectTemplate, out *clusterv1.ControlPlaneClassMachineInfrastructureTemplate, s apimachineryconversion.Scope) error { + convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil +} + +func Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassBootstrapTemplate(in *LocalObjectTemplate, out *clusterv1.MachineDeploymentClassBootstrapTemplate, s apimachineryconversion.Scope) error { + convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil +} + +func Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassInfrastructureTemplate(in *LocalObjectTemplate, out *clusterv1.MachineDeploymentClassInfrastructureTemplate, s apimachineryconversion.Scope) error { + convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil +} + +func Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachinePoolClassBootstrapTemplate(in *LocalObjectTemplate, out *clusterv1.MachinePoolClassBootstrapTemplate, s apimachineryconversion.Scope) error { + convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil +} + +func Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachinePoolClassInfrastructureTemplate(in *LocalObjectTemplate, out *clusterv1.MachinePoolClassInfrastructureTemplate, s apimachineryconversion.Scope) error { + convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil +} + +func convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in *LocalObjectTemplate, out *clusterv1.ClusterClassTemplateReference, _ apimachineryconversion.Scope) { + if in == nil || in.Ref == nil { + return } - out.Ref = &clusterv1.ClusterClassTemplateReference{ + *out = clusterv1.ClusterClassTemplateReference{ Kind: in.Ref.Kind, Name: in.Ref.Name, APIVersion: in.Ref.APIVersion, } +} + +func Convert_v1beta2_ControlPlaneClassMachineInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(in *clusterv1.ControlPlaneClassMachineInfrastructureTemplate, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { + Convert_v1beta2_ClusterClassTemplateReference_To_v1beta1_LocalObjectTemplate(&in.TemplateRef, out, s) return nil } -func Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(in *clusterv1.ClusterClassTemplate, out *LocalObjectTemplate, _ apimachineryconversion.Scope) error { - if in.Ref == nil { - return nil +func Convert_v1beta2_MachineDeploymentClassBootstrapTemplate_To_v1beta1_LocalObjectTemplate(in *clusterv1.MachineDeploymentClassBootstrapTemplate, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { + Convert_v1beta2_ClusterClassTemplateReference_To_v1beta1_LocalObjectTemplate(&in.TemplateRef, out, s) + return nil +} + +func Convert_v1beta2_MachineDeploymentClassInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(in *clusterv1.MachineDeploymentClassInfrastructureTemplate, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { + Convert_v1beta2_ClusterClassTemplateReference_To_v1beta1_LocalObjectTemplate(&in.TemplateRef, out, s) + return nil +} + +func Convert_v1beta2_MachinePoolClassBootstrapTemplate_To_v1beta1_LocalObjectTemplate(in *clusterv1.MachinePoolClassBootstrapTemplate, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { + Convert_v1beta2_ClusterClassTemplateReference_To_v1beta1_LocalObjectTemplate(&in.TemplateRef, out, s) + return nil +} + +func Convert_v1beta2_MachinePoolClassInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(in *clusterv1.MachinePoolClassInfrastructureTemplate, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { + Convert_v1beta2_ClusterClassTemplateReference_To_v1beta1_LocalObjectTemplate(&in.TemplateRef, out, s) + return nil +} + +func Convert_v1beta2_ClusterClassTemplateReference_To_v1beta1_LocalObjectTemplate(in *clusterv1.ClusterClassTemplateReference, out *LocalObjectTemplate, _ apimachineryconversion.Scope) { + if in == nil { + return } out.Ref = &corev1.ObjectReference{ - Kind: in.Ref.Kind, - Name: in.Ref.Name, - APIVersion: in.Ref.APIVersion, + Kind: in.Kind, + Name: in.Name, + APIVersion: in.APIVersion, } - return nil } func convertMachineSpecToContractVersionedObjectReference(src *MachineSpec, dst *clusterv1.MachineSpec) error { diff --git a/api/core/v1beta1/zz_generated.conversion.go b/api/core/v1beta1/zz_generated.conversion.go index 70152d972759..892c173da694 100644 --- a/api/core/v1beta1/zz_generated.conversion.go +++ b/api/core/v1beta1/zz_generated.conversion.go @@ -755,8 +755,8 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.ClusterClassTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.ClusterClassTemplate), scope) + if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.ControlPlaneClassMachineInfrastructureTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ControlPlaneClassMachineInfrastructureTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.ControlPlaneClassMachineInfrastructureTemplate), scope) }); err != nil { return err } @@ -765,6 +765,26 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.MachineDeploymentClassBootstrapTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassBootstrapTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.MachineDeploymentClassBootstrapTemplate), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.MachineDeploymentClassInfrastructureTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassInfrastructureTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.MachineDeploymentClassInfrastructureTemplate), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.MachinePoolClassBootstrapTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachinePoolClassBootstrapTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.MachinePoolClassBootstrapTemplate), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.MachinePoolClassInfrastructureTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachinePoolClassInfrastructureTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.MachinePoolClassInfrastructureTemplate), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*MachineDeploymentClass)(nil), (*v1beta2.MachineDeploymentClass)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_MachineDeploymentClass_To_v1beta2_MachineDeploymentClass(a.(*MachineDeploymentClass), b.(*v1beta2.MachineDeploymentClass), scope) }); err != nil { @@ -860,11 +880,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddConversionFunc((*v1beta2.ClusterClassTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(a.(*v1beta2.ClusterClassTemplate), b.(*LocalObjectTemplate), scope) - }); err != nil { - return err - } if err := s.AddConversionFunc((*v1beta2.ClusterClassVariable)(nil), (*ClusterClassVariable)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_ClusterClassVariable_To_v1beta1_ClusterClassVariable(a.(*v1beta2.ClusterClassVariable), b.(*ClusterClassVariable), scope) }); err != nil { @@ -885,6 +900,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.ControlPlaneClassMachineInfrastructureTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ControlPlaneClassMachineInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(a.(*v1beta2.ControlPlaneClassMachineInfrastructureTemplate), b.(*LocalObjectTemplate), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.ControlPlaneClass)(nil), (*ControlPlaneClass)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_ControlPlaneClass_To_v1beta1_ControlPlaneClass(a.(*v1beta2.ControlPlaneClass), b.(*ControlPlaneClass), scope) }); err != nil { @@ -905,6 +925,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.MachineDeploymentClassBootstrapTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_MachineDeploymentClassBootstrapTemplate_To_v1beta1_LocalObjectTemplate(a.(*v1beta2.MachineDeploymentClassBootstrapTemplate), b.(*LocalObjectTemplate), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta2.MachineDeploymentClassInfrastructureTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_MachineDeploymentClassInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(a.(*v1beta2.MachineDeploymentClassInfrastructureTemplate), b.(*LocalObjectTemplate), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.MachineDeploymentClass)(nil), (*MachineDeploymentClass)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_MachineDeploymentClass_To_v1beta1_MachineDeploymentClass(a.(*v1beta2.MachineDeploymentClass), b.(*MachineDeploymentClass), scope) }); err != nil { @@ -945,6 +975,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.MachinePoolClassBootstrapTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_MachinePoolClassBootstrapTemplate_To_v1beta1_LocalObjectTemplate(a.(*v1beta2.MachinePoolClassBootstrapTemplate), b.(*LocalObjectTemplate), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta2.MachinePoolClassInfrastructureTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_MachinePoolClassInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(a.(*v1beta2.MachinePoolClassInfrastructureTemplate), b.(*LocalObjectTemplate), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.MachinePoolClass)(nil), (*MachinePoolClass)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_MachinePoolClass_To_v1beta1_MachinePoolClass(a.(*v1beta2.MachinePoolClass), b.(*MachinePoolClass), scope) }); err != nil { @@ -1757,8 +1797,8 @@ func autoConvert_v1beta1_ControlPlaneClass_To_v1beta2_ControlPlaneClass(in *Cont // WARNING: in.LocalObjectTemplate requires manual conversion: does not exist in peer-type if in.MachineInfrastructure != nil { in, out := &in.MachineInfrastructure, &out.MachineInfrastructure - *out = new(v1beta2.ClusterClassTemplate) - if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(*in, *out, s); err != nil { + *out = new(v1beta2.ControlPlaneClassMachineInfrastructureTemplate) + if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ControlPlaneClassMachineInfrastructureTemplate(*in, *out, s); err != nil { return err } } else { @@ -1793,11 +1833,11 @@ func autoConvert_v1beta2_ControlPlaneClass_To_v1beta1_ControlPlaneClass(in *v1be if err := Convert_v1beta2_ObjectMeta_To_v1beta1_ObjectMeta(&in.Metadata, &out.Metadata, s); err != nil { return err } - // WARNING: in.ClusterClassTemplate requires manual conversion: does not exist in peer-type + // WARNING: in.TemplateRef requires manual conversion: does not exist in peer-type if in.MachineInfrastructure != nil { in, out := &in.MachineInfrastructure, &out.MachineInfrastructure *out = new(LocalObjectTemplate) - if err := Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(*in, *out, s); err != nil { + if err := Convert_v1beta2_ControlPlaneClassMachineInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(*in, *out, s); err != nil { return err } } else { @@ -2475,10 +2515,10 @@ func autoConvert_v1beta1_MachineDeploymentClassTemplate_To_v1beta2_MachineDeploy if err := Convert_v1beta1_ObjectMeta_To_v1beta2_ObjectMeta(&in.Metadata, &out.Metadata, s); err != nil { return err } - if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { + if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassBootstrapTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { return err } - if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { + if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassInfrastructureTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { return err } return nil @@ -2493,10 +2533,10 @@ func autoConvert_v1beta2_MachineDeploymentClassTemplate_To_v1beta1_MachineDeploy if err := Convert_v1beta2_ObjectMeta_To_v1beta1_ObjectMeta(&in.Metadata, &out.Metadata, s); err != nil { return err } - if err := Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { + if err := Convert_v1beta2_MachineDeploymentClassBootstrapTemplate_To_v1beta1_LocalObjectTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { return err } - if err := Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { + if err := Convert_v1beta2_MachineDeploymentClassInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { return err } return nil @@ -3328,10 +3368,10 @@ func autoConvert_v1beta1_MachinePoolClassTemplate_To_v1beta2_MachinePoolClassTem if err := Convert_v1beta1_ObjectMeta_To_v1beta2_ObjectMeta(&in.Metadata, &out.Metadata, s); err != nil { return err } - if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { + if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachinePoolClassBootstrapTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { return err } - if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { + if err := Convert_v1beta1_LocalObjectTemplate_To_v1beta2_MachinePoolClassInfrastructureTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { return err } return nil @@ -3346,10 +3386,10 @@ func autoConvert_v1beta2_MachinePoolClassTemplate_To_v1beta1_MachinePoolClassTem if err := Convert_v1beta2_ObjectMeta_To_v1beta1_ObjectMeta(&in.Metadata, &out.Metadata, s); err != nil { return err } - if err := Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { + if err := Convert_v1beta2_MachinePoolClassBootstrapTemplate_To_v1beta1_LocalObjectTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { return err } - if err := Convert_v1beta2_ClusterClassTemplate_To_v1beta1_LocalObjectTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { + if err := Convert_v1beta2_MachinePoolClassInfrastructureTemplate_To_v1beta1_LocalObjectTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { return err } return nil diff --git a/api/core/v1beta2/cluster_types.go b/api/core/v1beta2/cluster_types.go index f1eac38559a0..f9049e9873be 100644 --- a/api/core/v1beta2/cluster_types.go +++ b/api/core/v1beta2/cluster_types.go @@ -470,7 +470,7 @@ type ClusterSpec struct { // controlPlaneEndpoint represents the endpoint used to communicate with the control plane. // +optional - ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint,omitempty"` + ControlPlaneEndpoint APIEndpoint `json:"controlPlaneEndpoint,omitempty,omitzero"` // controlPlaneRef is an optional reference to a provider-specific resource that holds // the details for provisioning the Control Plane for a Cluster. @@ -549,7 +549,7 @@ type Topology struct { // controlPlane describes the cluster control plane. // +optional - ControlPlane ControlPlaneTopology `json:"controlPlane,omitempty"` + ControlPlane ControlPlaneTopology `json:"controlPlane,omitempty,omitzero"` // workers encapsulates the different constructs that form the worker nodes // for the cluster. @@ -591,13 +591,14 @@ type ClusterClassRef struct { } // ControlPlaneTopology specifies the parameters for the control plane nodes in the cluster. +// +kubebuilder:validation:MinProperties=1 type ControlPlaneTopology struct { // metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane // if the ControlPlaneTemplate referenced by the ClusterClass is machine based. If not, it // is applied only to the ControlPlane. // At runtime this metadata is merged with the corresponding metadata from the ClusterClass. // +optional - Metadata ObjectMeta `json:"metadata,omitempty"` + Metadata ObjectMeta `json:"metadata,omitempty,omitzero"` // replicas is the number of control plane nodes. // If the value is nil, the ControlPlane object is created without the number of Replicas @@ -675,7 +676,7 @@ type MachineDeploymentTopology struct { // metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment. // At runtime this metadata is merged with the corresponding metadata from the ClusterClass. // +optional - Metadata ObjectMeta `json:"metadata,omitempty"` + Metadata ObjectMeta `json:"metadata,omitempty,omitzero"` // class is the name of the MachineDeploymentClass used to create the set of worker nodes. // This should match one of the deployment classes defined in the ClusterClass object @@ -789,7 +790,7 @@ type MachinePoolTopology struct { // metadata is the metadata applied to the MachinePool. // At runtime this metadata is merged with the corresponding metadata from the ClusterClass. // +optional - Metadata ObjectMeta `json:"metadata,omitempty"` + Metadata ObjectMeta `json:"metadata,omitempty,omitzero"` // class is the name of the MachinePoolClass used to create the pool of worker nodes. // This should match one of the deployment classes defined in the ClusterClass object @@ -1139,16 +1140,19 @@ func (c *ClusterStatus) GetTypedPhase() ClusterPhase { // ANCHOR: APIEndpoint // APIEndpoint represents a reachable Kubernetes API endpoint. +// +kubebuilder:validation:MinProperties=1 type APIEndpoint struct { // host is the hostname on which the API server is serving. - // TODO: Can't set MinLength=1 for now, because this struct is not always used in pointer fields so today we have cases where host is set to an empty string. - // +required + // +optional + // +kubebuilder:validation:MinLength=1 // +kubebuilder:validation:MaxLength=512 - Host string `json:"host"` + Host string `json:"host,omitempty"` // port is the port on which the API server is serving. - // +required - Port int32 `json:"port"` + // +optional + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=65535 + Port int32 `json:"port,omitempty"` } // IsZero returns true if both host and port are zero values. @@ -1172,7 +1176,7 @@ func (v APIEndpoint) String() string { // +kubebuilder:resource:path=clusters,shortName=cl,scope=Namespaced,categories=cluster-api // +kubebuilder:storageversion // +kubebuilder:subresource:status -// +kubebuilder:printcolumn:name="ClusterClass",type="string",JSONPath=".spec.topology.class",description="ClusterClass of this Cluster, empty if the Cluster is not using a ClusterClass" +// +kubebuilder:printcolumn:name="ClusterClass",type="string",JSONPath=".spec.topology.classRef.name",description="ClusterClass of this Cluster, empty if the Cluster is not using a ClusterClass" // +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="Cluster status such as Pending/Provisioning/Provisioned/Deleting/Failed" // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of Cluster" // +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".spec.topology.version",description="Kubernetes version associated with this Cluster" diff --git a/api/core/v1beta2/clusterclass_types.go b/api/core/v1beta2/clusterclass_types.go index 33b0942730f0..efb6ce5d9a3d 100644 --- a/api/core/v1beta2/clusterclass_types.go +++ b/api/core/v1beta2/clusterclass_types.go @@ -104,18 +104,18 @@ type ClusterClassSpec struct { // infrastructure is a reference to a local struct that holds the details // for provisioning the infrastructure cluster for the Cluster. // +optional - Infrastructure InfrastructureClass `json:"infrastructure,omitempty"` + Infrastructure InfrastructureClass `json:"infrastructure,omitempty,omitzero"` // controlPlane is a reference to a local struct that holds the details // for provisioning the Control Plane for the Cluster. // +optional - ControlPlane ControlPlaneClass `json:"controlPlane,omitempty"` + ControlPlane ControlPlaneClass `json:"controlPlane,omitempty,omitzero"` // workers describes the worker nodes for the cluster. // It is a collection of node types which can be used to create // the worker nodes of the cluster. // +optional - Workers WorkersClass `json:"workers,omitempty"` + Workers WorkersClass `json:"workers,omitempty,omitzero"` // variables defines the variables which can be configured // in the Cluster topology and are then used in patches. @@ -133,8 +133,9 @@ type ClusterClassSpec struct { // InfrastructureClass defines the class for the infrastructure cluster. type InfrastructureClass struct { - // LocalObjectTemplate contains the reference to a provider-specific infrastructure cluster template. - ClusterClassTemplate `json:",inline"` + // templateRef contains the reference to a provider-specific infrastructure cluster template. + // +required + TemplateRef ClusterClassTemplateReference `json:"templateRef,omitempty,omitzero"` // namingStrategy allows changing the naming pattern used when creating the infrastructure cluster object. // +optional @@ -151,10 +152,11 @@ type ControlPlaneClass struct { // This field is supported if and only if the control plane provider template // referenced is Machine based. // +optional - Metadata ObjectMeta `json:"metadata,omitempty"` + Metadata ObjectMeta `json:"metadata,omitempty,omitzero"` - // LocalObjectTemplate contains the reference to a provider-specific control plane template. - ClusterClassTemplate `json:",inline"` + // templateRef contains the reference to a provider-specific control plane template. + // +required + TemplateRef ClusterClassTemplateReference `json:"templateRef,omitempty,omitzero"` // machineInfrastructure defines the metadata and infrastructure information // for control plane machines. @@ -163,7 +165,7 @@ type ControlPlaneClass struct { // referenced above is Machine based and supports setting replicas. // // +optional - MachineInfrastructure *ClusterClassTemplate `json:"machineInfrastructure,omitempty"` + MachineInfrastructure *ControlPlaneClassMachineInfrastructureTemplate `json:"machineInfrastructure,omitempty"` // machineHealthCheck defines a MachineHealthCheck for this ControlPlaneClass. // This field is supported if and only if the ControlPlane provider template @@ -246,6 +248,7 @@ type InfrastructureClassNamingStrategy struct { } // WorkersClass is a collection of deployment classes. +// +kubebuilder:validation:MinProperties=1 type WorkersClass struct { // machineDeployments is a list of machine deployment classes that can be used to create // a set of worker nodes. @@ -354,17 +357,17 @@ type MachineDeploymentClassTemplate struct { // metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment. // At runtime this metadata is merged with the corresponding metadata from the topology. // +optional - Metadata ObjectMeta `json:"metadata,omitempty"` + Metadata ObjectMeta `json:"metadata,omitempty,omitzero"` // bootstrap contains the bootstrap template reference to be used // for the creation of worker Machines. // +required - Bootstrap ClusterClassTemplate `json:"bootstrap"` + Bootstrap MachineDeploymentClassBootstrapTemplate `json:"bootstrap"` // infrastructure contains the infrastructure template reference to be used // for the creation of worker Machines. // +required - Infrastructure ClusterClassTemplate `json:"infrastructure"` + Infrastructure MachineDeploymentClassInfrastructureTemplate `json:"infrastructure"` } // MachineDeploymentClassNamingStrategy defines the naming strategy for machine deployment objects. @@ -504,17 +507,17 @@ type MachinePoolClassTemplate struct { // metadata is the metadata applied to the MachinePool. // At runtime this metadata is merged with the corresponding metadata from the topology. // +optional - Metadata ObjectMeta `json:"metadata,omitempty"` + Metadata ObjectMeta `json:"metadata,omitempty,omitzero"` // bootstrap contains the bootstrap template reference to be used // for the creation of the Machines in the MachinePool. // +required - Bootstrap ClusterClassTemplate `json:"bootstrap"` + Bootstrap MachinePoolClassBootstrapTemplate `json:"bootstrap"` // infrastructure contains the infrastructure template reference to be used // for the creation of the MachinePool. // +required - Infrastructure ClusterClassTemplate `json:"infrastructure"` + Infrastructure MachinePoolClassInfrastructureTemplate `json:"infrastructure"` } // MachinePoolClassNamingStrategy defines the naming strategy for machine pool objects. @@ -561,7 +564,7 @@ type ClusterClassVariable struct { // Deprecated: This field is deprecated and will be removed when support for v1beta1 will be dropped. Please use XMetadata in JSONSchemaProps instead. // // +optional - DeprecatedV1Beta1Metadata ClusterClassVariableMetadata `json:"deprecatedV1Beta1Metadata,omitempty"` + DeprecatedV1Beta1Metadata ClusterClassVariableMetadata `json:"deprecatedV1Beta1Metadata,omitempty,omitzero"` // schema defines the schema of the variable. // +required @@ -573,6 +576,7 @@ type ClusterClassVariable struct { // a ClusterClassVariable. // // Deprecated: This struct is deprecated and is going to be removed in the next apiVersion. +// +kubebuilder:validation:MinProperties=1 type ClusterClassVariableMetadata struct { // labels is a map of string keys and values that can be used to organize and categorize // (scope and select) variables. @@ -1147,12 +1151,39 @@ type ExternalPatchDefinition struct { Settings map[string]string `json:"settings,omitempty"` } -// ClusterClassTemplate defines a template referenced by a ClusterClass. -type ClusterClassTemplate struct { - // ref is a required reference to a custom resource - // offered by a provider. +// ControlPlaneClassMachineInfrastructureTemplate defines the template for a MachineInfrastructure of a ControlPlane. +type ControlPlaneClassMachineInfrastructureTemplate struct { + // templateRef is a required reference to the template for a MachineInfrastructure of a ControlPlane. + // +required + TemplateRef ClusterClassTemplateReference `json:"templateRef,omitempty,omitzero"` +} + +// MachineDeploymentClassBootstrapTemplate defines the BootstrapTemplate for a MachineDeployment. +type MachineDeploymentClassBootstrapTemplate struct { + // templateRef is a required reference to the BootstrapTemplate for a MachineDeployment. + // +required + TemplateRef ClusterClassTemplateReference `json:"templateRef,omitempty,omitzero"` +} + +// MachineDeploymentClassInfrastructureTemplate defines the InfrastructureTemplate for a MachineDeployment. +type MachineDeploymentClassInfrastructureTemplate struct { + // templateRef is a required reference to the InfrastructureTemplate for a MachineDeployment. + // +required + TemplateRef ClusterClassTemplateReference `json:"templateRef,omitempty,omitzero"` +} + +// MachinePoolClassBootstrapTemplate defines the BootstrapTemplate for a MachinePool. +type MachinePoolClassBootstrapTemplate struct { + // templateRef is a required reference to the BootstrapTemplate for a MachinePool. + // +required + TemplateRef ClusterClassTemplateReference `json:"templateRef,omitempty,omitzero"` +} + +// MachinePoolClassInfrastructureTemplate defines the InfrastructureTemplate for a MachinePool. +type MachinePoolClassInfrastructureTemplate struct { + // templateRef is a required reference to the InfrastructureTemplate for a MachinePool. // +required - Ref *ClusterClassTemplateReference `json:"ref"` + TemplateRef ClusterClassTemplateReference `json:"templateRef,omitempty,omitzero"` } // ClusterClassTemplateReference is a reference to a ClusterClass template. @@ -1289,7 +1320,7 @@ type ClusterClassStatusVariableDefinition struct { // Deprecated: This field is deprecated and will be removed when support for v1beta1 will be dropped. Please use XMetadata in JSONSchemaProps instead. // // +optional - DeprecatedV1Beta1Metadata ClusterClassVariableMetadata `json:"deprecatedV1Beta1Metadata,omitempty"` + DeprecatedV1Beta1Metadata ClusterClassVariableMetadata `json:"deprecatedV1Beta1Metadata,omitempty,omitzero"` // schema defines the schema of the variable. // +required diff --git a/api/core/v1beta2/common_types.go b/api/core/v1beta2/common_types.go index cc4ddf6de2c2..0d46d4853879 100644 --- a/api/core/v1beta2/common_types.go +++ b/api/core/v1beta2/common_types.go @@ -326,6 +326,7 @@ type MachineAddresses []MachineAddress // // In future versions, controller-tools@v2 might allow overriding the type and validation for embedded // types. When that happens, this hack should be revisited. +// +kubebuilder:validation:MinProperties=1 type ObjectMeta struct { // labels is a map of string keys and values that can be used to organize and categorize // (scope and select) objects. May match selectors of replication controllers diff --git a/api/core/v1beta2/condition_types.go b/api/core/v1beta2/condition_types.go index 5cb55f25fc1d..adf11891efa6 100644 --- a/api/core/v1beta2/condition_types.go +++ b/api/core/v1beta2/condition_types.go @@ -70,7 +70,7 @@ type Condition struct { // understand the current situation and act accordingly. // The Severity field MUST be set only when Status=False. // +optional - Severity ConditionSeverity `json:"severity,omitempty"` + Severity ConditionSeverity `json:"severity,omitempty"` //nolint:kubeapilinter // the Condition type will be removed when v1beta1 is removed // lastTransitionTime is the last time the condition transitioned from one status to another. // This should be when the underlying condition changed. If that is not known, then using the time when diff --git a/api/core/v1beta2/machine_types.go b/api/core/v1beta2/machine_types.go index 92960ab4c1dd..4a33dedceae3 100644 --- a/api/core/v1beta2/machine_types.go +++ b/api/core/v1beta2/machine_types.go @@ -388,7 +388,7 @@ type MachineSpec struct { // bootstrap is a reference to a local struct which encapsulates // fields to configure the Machine’s bootstrapping mechanism. // +required - Bootstrap Bootstrap `json:"bootstrap"` + Bootstrap Bootstrap `json:"bootstrap,omitempty,omitzero"` // infrastructureRef is a required reference to a custom resource // offered by an infrastructure provider. diff --git a/api/core/v1beta2/machineset_types.go b/api/core/v1beta2/machineset_types.go index 0fe0395ad16d..4493edb937c6 100644 --- a/api/core/v1beta2/machineset_types.go +++ b/api/core/v1beta2/machineset_types.go @@ -236,7 +236,7 @@ type MachineTemplateSpec struct { // metadata is the standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta `json:"metadata,omitempty"` + ObjectMeta `json:"metadata,omitempty,omitzero"` // spec is the specification of the desired behavior of the machine. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status diff --git a/api/core/v1beta2/zz_generated.deepcopy.go b/api/core/v1beta2/zz_generated.deepcopy.go index d394cd728795..e856541a6e65 100644 --- a/api/core/v1beta2/zz_generated.deepcopy.go +++ b/api/core/v1beta2/zz_generated.deepcopy.go @@ -347,26 +347,6 @@ func (in *ClusterClassStatusVariableDefinition) DeepCopy() *ClusterClassStatusVa return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterClassTemplate) DeepCopyInto(out *ClusterClassTemplate) { - *out = *in - if in.Ref != nil { - in, out := &in.Ref, &out.Ref - *out = new(ClusterClassTemplateReference) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterClassTemplate. -func (in *ClusterClassTemplate) DeepCopy() *ClusterClassTemplate { - if in == nil { - return nil - } - out := new(ClusterClassTemplate) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterClassTemplateReference) DeepCopyInto(out *ClusterClassTemplateReference) { *out = *in @@ -796,11 +776,11 @@ func (in *ContractVersionedObjectReference) DeepCopy() *ContractVersionedObjectR func (in *ControlPlaneClass) DeepCopyInto(out *ControlPlaneClass) { *out = *in in.Metadata.DeepCopyInto(&out.Metadata) - in.ClusterClassTemplate.DeepCopyInto(&out.ClusterClassTemplate) + out.TemplateRef = in.TemplateRef if in.MachineInfrastructure != nil { in, out := &in.MachineInfrastructure, &out.MachineInfrastructure - *out = new(ClusterClassTemplate) - (*in).DeepCopyInto(*out) + *out = new(ControlPlaneClassMachineInfrastructureTemplate) + **out = **in } if in.MachineHealthCheck != nil { in, out := &in.MachineHealthCheck, &out.MachineHealthCheck @@ -844,6 +824,22 @@ func (in *ControlPlaneClass) DeepCopy() *ControlPlaneClass { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneClassMachineInfrastructureTemplate) DeepCopyInto(out *ControlPlaneClassMachineInfrastructureTemplate) { + *out = *in + out.TemplateRef = in.TemplateRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneClassMachineInfrastructureTemplate. +func (in *ControlPlaneClassMachineInfrastructureTemplate) DeepCopy() *ControlPlaneClassMachineInfrastructureTemplate { + if in == nil { + return nil + } + out := new(ControlPlaneClassMachineInfrastructureTemplate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ControlPlaneClassNamingStrategy) DeepCopyInto(out *ControlPlaneClassNamingStrategy) { *out = *in @@ -984,7 +980,7 @@ func (in *FailureDomain) DeepCopy() *FailureDomain { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *InfrastructureClass) DeepCopyInto(out *InfrastructureClass) { *out = *in - in.ClusterClassTemplate.DeepCopyInto(&out.ClusterClassTemplate) + out.TemplateRef = in.TemplateRef if in.NamingStrategy != nil { in, out := &in.NamingStrategy, &out.NamingStrategy *out = new(InfrastructureClassNamingStrategy) @@ -1379,6 +1375,38 @@ func (in *MachineDeploymentClass) DeepCopy() *MachineDeploymentClass { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentClassBootstrapTemplate) DeepCopyInto(out *MachineDeploymentClassBootstrapTemplate) { + *out = *in + out.TemplateRef = in.TemplateRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentClassBootstrapTemplate. +func (in *MachineDeploymentClassBootstrapTemplate) DeepCopy() *MachineDeploymentClassBootstrapTemplate { + if in == nil { + return nil + } + out := new(MachineDeploymentClassBootstrapTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineDeploymentClassInfrastructureTemplate) DeepCopyInto(out *MachineDeploymentClassInfrastructureTemplate) { + *out = *in + out.TemplateRef = in.TemplateRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentClassInfrastructureTemplate. +func (in *MachineDeploymentClassInfrastructureTemplate) DeepCopy() *MachineDeploymentClassInfrastructureTemplate { + if in == nil { + return nil + } + out := new(MachineDeploymentClassInfrastructureTemplate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachineDeploymentClassNamingStrategy) DeepCopyInto(out *MachineDeploymentClassNamingStrategy) { *out = *in @@ -1398,8 +1426,8 @@ func (in *MachineDeploymentClassNamingStrategy) DeepCopy() *MachineDeploymentCla func (in *MachineDeploymentClassTemplate) DeepCopyInto(out *MachineDeploymentClassTemplate) { *out = *in in.Metadata.DeepCopyInto(&out.Metadata) - in.Bootstrap.DeepCopyInto(&out.Bootstrap) - in.Infrastructure.DeepCopyInto(&out.Infrastructure) + out.Bootstrap = in.Bootstrap + out.Infrastructure = in.Infrastructure } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineDeploymentClassTemplate. @@ -2275,6 +2303,38 @@ func (in *MachinePoolClass) DeepCopy() *MachinePoolClass { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachinePoolClassBootstrapTemplate) DeepCopyInto(out *MachinePoolClassBootstrapTemplate) { + *out = *in + out.TemplateRef = in.TemplateRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachinePoolClassBootstrapTemplate. +func (in *MachinePoolClassBootstrapTemplate) DeepCopy() *MachinePoolClassBootstrapTemplate { + if in == nil { + return nil + } + out := new(MachinePoolClassBootstrapTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachinePoolClassInfrastructureTemplate) DeepCopyInto(out *MachinePoolClassInfrastructureTemplate) { + *out = *in + out.TemplateRef = in.TemplateRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachinePoolClassInfrastructureTemplate. +func (in *MachinePoolClassInfrastructureTemplate) DeepCopy() *MachinePoolClassInfrastructureTemplate { + if in == nil { + return nil + } + out := new(MachinePoolClassInfrastructureTemplate) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MachinePoolClassNamingStrategy) DeepCopyInto(out *MachinePoolClassNamingStrategy) { *out = *in @@ -2294,8 +2354,8 @@ func (in *MachinePoolClassNamingStrategy) DeepCopy() *MachinePoolClassNamingStra func (in *MachinePoolClassTemplate) DeepCopyInto(out *MachinePoolClassTemplate) { *out = *in in.Metadata.DeepCopyInto(&out.Metadata) - in.Bootstrap.DeepCopyInto(&out.Bootstrap) - in.Infrastructure.DeepCopyInto(&out.Infrastructure) + out.Bootstrap = in.Bootstrap + out.Infrastructure = in.Infrastructure } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachinePoolClassTemplate. diff --git a/api/core/v1beta2/zz_generated.openapi.go b/api/core/v1beta2/zz_generated.openapi.go index d9c6c8a35d88..e2f5ebb6dc97 100644 --- a/api/core/v1beta2/zz_generated.openapi.go +++ b/api/core/v1beta2/zz_generated.openapi.go @@ -41,7 +41,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassStatus": schema_cluster_api_api_core_v1beta2_ClusterClassStatus(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassStatusVariable": schema_cluster_api_api_core_v1beta2_ClusterClassStatusVariable(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassStatusVariableDefinition": schema_cluster_api_api_core_v1beta2_ClusterClassStatusVariableDefinition(ref), - "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate": schema_cluster_api_api_core_v1beta2_ClusterClassTemplate(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference": schema_cluster_api_api_core_v1beta2_ClusterClassTemplateReference(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassV1Beta1DeprecatedStatus": schema_cluster_api_api_core_v1beta2_ClusterClassV1Beta1DeprecatedStatus(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassVariable": schema_cluster_api_api_core_v1beta2_ClusterClassVariable(ref), @@ -58,6 +57,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api/api/core/v1beta2.Condition": schema_cluster_api_api_core_v1beta2_Condition(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ContractVersionedObjectReference": schema_cluster_api_api_core_v1beta2_ContractVersionedObjectReference(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClass": schema_cluster_api_api_core_v1beta2_ControlPlaneClass(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClassMachineInfrastructureTemplate": schema_cluster_api_api_core_v1beta2_ControlPlaneClassMachineInfrastructureTemplate(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClassNamingStrategy": schema_cluster_api_api_core_v1beta2_ControlPlaneClassNamingStrategy(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneTopology": schema_cluster_api_api_core_v1beta2_ControlPlaneTopology(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneVariables": schema_cluster_api_api_core_v1beta2_ControlPlaneVariables(ref), @@ -73,6 +73,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeletionStatus": schema_cluster_api_api_core_v1beta2_MachineDeletionStatus(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeployment": schema_cluster_api_api_core_v1beta2_MachineDeployment(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClass": schema_cluster_api_api_core_v1beta2_MachineDeploymentClass(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClassBootstrapTemplate": schema_cluster_api_api_core_v1beta2_MachineDeploymentClassBootstrapTemplate(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClassInfrastructureTemplate": schema_cluster_api_api_core_v1beta2_MachineDeploymentClassInfrastructureTemplate(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClassNamingStrategy": schema_cluster_api_api_core_v1beta2_MachineDeploymentClassNamingStrategy(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClassTemplate": schema_cluster_api_api_core_v1beta2_MachineDeploymentClassTemplate(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentDeprecatedStatus": schema_cluster_api_api_core_v1beta2_MachineDeploymentDeprecatedStatus(ref), @@ -105,6 +107,8 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineNodeReference": schema_cluster_api_api_core_v1beta2_MachineNodeReference(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePool": schema_cluster_api_api_core_v1beta2_MachinePool(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClass": schema_cluster_api_api_core_v1beta2_MachinePoolClass(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClassBootstrapTemplate": schema_cluster_api_api_core_v1beta2_MachinePoolClassBootstrapTemplate(ref), + "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClassInfrastructureTemplate": schema_cluster_api_api_core_v1beta2_MachinePoolClassInfrastructureTemplate(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClassNamingStrategy": schema_cluster_api_api_core_v1beta2_MachinePoolClassNamingStrategy(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClassTemplate": schema_cluster_api_api_core_v1beta2_MachinePoolClassTemplate(ref), "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolDeprecatedStatus": schema_cluster_api_api_core_v1beta2_MachinePoolDeprecatedStatus(ref), @@ -156,7 +160,6 @@ func schema_cluster_api_api_core_v1beta2_APIEndpoint(ref common.ReferenceCallbac "host": { SchemaProps: spec.SchemaProps{ Description: "host is the hostname on which the API server is serving.", - Default: "", Type: []string{"string"}, Format: "", }, @@ -164,13 +167,11 @@ func schema_cluster_api_api_core_v1beta2_APIEndpoint(ref common.ReferenceCallbac "port": { SchemaProps: spec.SchemaProps{ Description: "port is the port on which the API server is serving.", - Default: 0, Type: []string{"integer"}, Format: "int32", }, }, }, - Required: []string{"host", "port"}, }, }, } @@ -735,28 +736,6 @@ func schema_cluster_api_api_core_v1beta2_ClusterClassStatusVariableDefinition(re } } -func schema_cluster_api_api_core_v1beta2_ClusterClassTemplate(ref common.ReferenceCallback) common.OpenAPIDefinition { - return common.OpenAPIDefinition{ - Schema: spec.Schema{ - SchemaProps: spec.SchemaProps{ - Description: "ClusterClassTemplate defines a template referenced by a ClusterClass.", - Type: []string{"object"}, - Properties: map[string]spec.Schema{ - "ref": { - SchemaProps: spec.SchemaProps{ - Description: "ref is a required reference to a custom resource offered by a provider.", - Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"), - }, - }, - }, - Required: []string{"ref"}, - }, - }, - Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"}, - } -} - func schema_cluster_api_api_core_v1beta2_ClusterClassTemplateReference(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -1459,16 +1438,17 @@ func schema_cluster_api_api_core_v1beta2_ControlPlaneClass(ref common.ReferenceC Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ObjectMeta"), }, }, - "ref": { + "templateRef": { SchemaProps: spec.SchemaProps{ - Description: "ref is a required reference to a custom resource offered by a provider.", + Description: "templateRef contains the reference to a provider-specific control plane template.", + Default: map[string]interface{}{}, Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"), }, }, "machineInfrastructure": { SchemaProps: spec.SchemaProps{ Description: "machineInfrastructure defines the metadata and infrastructure information for control plane machines.\n\nThis field is supported if and only if the control plane provider template referenced above is Machine based and supports setting replicas.", - Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate"), + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClassMachineInfrastructureTemplate"), }, }, "machineHealthCheck": { @@ -1527,11 +1507,34 @@ func schema_cluster_api_api_core_v1beta2_ControlPlaneClass(ref common.ReferenceC }, }, }, - Required: []string{"ref"}, + Required: []string{"templateRef"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference", "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClassMachineInfrastructureTemplate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClassNamingStrategy", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineHealthCheckClass", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineReadinessGate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ObjectMeta"}, + } +} + +func schema_cluster_api_api_core_v1beta2_ControlPlaneClassMachineInfrastructureTemplate(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "ControlPlaneClassMachineInfrastructureTemplate defines the template for a MachineInfrastructure of a ControlPlane.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "templateRef": { + SchemaProps: spec.SchemaProps{ + Description: "templateRef is a required reference to the template for a MachineInfrastructure of a ControlPlane.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"), + }, + }, + }, + Required: []string{"templateRef"}, }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference", "sigs.k8s.io/cluster-api/api/core/v1beta2.ControlPlaneClassNamingStrategy", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineHealthCheckClass", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineReadinessGate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ObjectMeta"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"}, } } @@ -1778,9 +1781,10 @@ func schema_cluster_api_api_core_v1beta2_InfrastructureClass(ref common.Referenc Description: "InfrastructureClass defines the class for the infrastructure cluster.", Type: []string{"object"}, Properties: map[string]spec.Schema{ - "ref": { + "templateRef": { SchemaProps: spec.SchemaProps{ - Description: "ref is a required reference to a custom resource offered by a provider.", + Description: "templateRef contains the reference to a provider-specific infrastructure cluster template.", + Default: map[string]interface{}{}, Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"), }, }, @@ -1791,7 +1795,7 @@ func schema_cluster_api_api_core_v1beta2_InfrastructureClass(ref common.Referenc }, }, }, - Required: []string{"ref"}, + Required: []string{"templateRef"}, }, }, Dependencies: []string{ @@ -2432,6 +2436,52 @@ func schema_cluster_api_api_core_v1beta2_MachineDeploymentClass(ref common.Refer } } +func schema_cluster_api_api_core_v1beta2_MachineDeploymentClassBootstrapTemplate(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MachineDeploymentClassBootstrapTemplate defines the BootstrapTemplate for a MachineDeployment.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "templateRef": { + SchemaProps: spec.SchemaProps{ + Description: "templateRef is a required reference to the BootstrapTemplate for a MachineDeployment.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"), + }, + }, + }, + Required: []string{"templateRef"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"}, + } +} + +func schema_cluster_api_api_core_v1beta2_MachineDeploymentClassInfrastructureTemplate(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MachineDeploymentClassInfrastructureTemplate defines the InfrastructureTemplate for a MachineDeployment.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "templateRef": { + SchemaProps: spec.SchemaProps{ + Description: "templateRef is a required reference to the InfrastructureTemplate for a MachineDeployment.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"), + }, + }, + }, + Required: []string{"templateRef"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"}, + } +} + func schema_cluster_api_api_core_v1beta2_MachineDeploymentClassNamingStrategy(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -2470,14 +2520,14 @@ func schema_cluster_api_api_core_v1beta2_MachineDeploymentClassTemplate(ref comm SchemaProps: spec.SchemaProps{ Description: "bootstrap contains the bootstrap template reference to be used for the creation of worker Machines.", Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate"), + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClassBootstrapTemplate"), }, }, "infrastructure": { SchemaProps: spec.SchemaProps{ Description: "infrastructure contains the infrastructure template reference to be used for the creation of worker Machines.", Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate"), + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClassInfrastructureTemplate"), }, }, }, @@ -2485,7 +2535,7 @@ func schema_cluster_api_api_core_v1beta2_MachineDeploymentClassTemplate(ref comm }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ObjectMeta"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClassBootstrapTemplate", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachineDeploymentClassInfrastructureTemplate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ObjectMeta"}, } } @@ -3951,6 +4001,52 @@ func schema_cluster_api_api_core_v1beta2_MachinePoolClass(ref common.ReferenceCa } } +func schema_cluster_api_api_core_v1beta2_MachinePoolClassBootstrapTemplate(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MachinePoolClassBootstrapTemplate defines the BootstrapTemplate for a MachinePool.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "templateRef": { + SchemaProps: spec.SchemaProps{ + Description: "templateRef is a required reference to the BootstrapTemplate for a MachinePool.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"), + }, + }, + }, + Required: []string{"templateRef"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"}, + } +} + +func schema_cluster_api_api_core_v1beta2_MachinePoolClassInfrastructureTemplate(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "MachinePoolClassInfrastructureTemplate defines the InfrastructureTemplate for a MachinePool.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "templateRef": { + SchemaProps: spec.SchemaProps{ + Description: "templateRef is a required reference to the InfrastructureTemplate for a MachinePool.", + Default: map[string]interface{}{}, + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"), + }, + }, + }, + Required: []string{"templateRef"}, + }, + }, + Dependencies: []string{ + "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplateReference"}, + } +} + func schema_cluster_api_api_core_v1beta2_MachinePoolClassNamingStrategy(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -3989,14 +4085,14 @@ func schema_cluster_api_api_core_v1beta2_MachinePoolClassTemplate(ref common.Ref SchemaProps: spec.SchemaProps{ Description: "bootstrap contains the bootstrap template reference to be used for the creation of the Machines in the MachinePool.", Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate"), + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClassBootstrapTemplate"), }, }, "infrastructure": { SchemaProps: spec.SchemaProps{ Description: "infrastructure contains the infrastructure template reference to be used for the creation of the MachinePool.", Default: map[string]interface{}{}, - Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate"), + Ref: ref("sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClassInfrastructureTemplate"), }, }, }, @@ -4004,7 +4100,7 @@ func schema_cluster_api_api_core_v1beta2_MachinePoolClassTemplate(ref common.Ref }, }, Dependencies: []string{ - "sigs.k8s.io/cluster-api/api/core/v1beta2.ClusterClassTemplate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ObjectMeta"}, + "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClassBootstrapTemplate", "sigs.k8s.io/cluster-api/api/core/v1beta2.MachinePoolClassInfrastructureTemplate", "sigs.k8s.io/cluster-api/api/core/v1beta2.ObjectMeta"}, } } diff --git a/api/ipam/v1beta2/ipaddressclaim_types.go b/api/ipam/v1beta2/ipaddressclaim_types.go index 2e0097f679fc..b09b1bb2f53e 100644 --- a/api/ipam/v1beta2/ipaddressclaim_types.go +++ b/api/ipam/v1beta2/ipaddressclaim_types.go @@ -66,7 +66,7 @@ type IPAddressClaimStatus struct { // addressRef is a reference to the address that was created for this claim. // +optional - AddressRef IPAddressReference `json:"addressRef,omitempty"` + AddressRef IPAddressReference `json:"addressRef,omitempty,omitzero"` // deprecated groups all the status fields that are deprecated and will be removed when all the nested field are removed. // +optional diff --git a/api/runtime/v1beta2/extensionconfig_types.go b/api/runtime/v1beta2/extensionconfig_types.go index 902413ba4ab9..0f316087d8aa 100644 --- a/api/runtime/v1beta2/extensionconfig_types.go +++ b/api/runtime/v1beta2/extensionconfig_types.go @@ -179,7 +179,6 @@ type ExtensionHandler struct { // failurePolicy defines how failures in calls to the ExtensionHandler should be handled by a client. // Defaults to Fail if not set. // +optional - // +kubebuilder:validation:Enum=Ignore;Fail FailurePolicy *FailurePolicy `json:"failurePolicy,omitempty"` } @@ -203,6 +202,7 @@ type GroupVersionHook struct { // The following type of errors are never ignored by FailurePolicy Ignore: // - Misconfigurations (e.g. incompatible types) // - Extension explicitly returns a Status Failure. +// +kubebuilder:validation:Enum=Ignore;Fail type FailurePolicy string const ( diff --git a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml index 0a96195321b6..4cb961786deb 100644 --- a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml +++ b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigs.yaml @@ -4137,6 +4137,7 @@ spec: apiServer: description: apiServer contains extra settings for the API server control plane component + minProperties: 1 properties: certSANs: description: certSANs sets extra Subject Alternative Names @@ -4371,6 +4372,7 @@ spec: controllerManager: description: controllerManager contains extra settings for the controller manager control plane component + minProperties: 1 properties: extraArgs: description: |- @@ -4572,6 +4574,7 @@ spec: dns: description: dns defines the options for the DNS add-on installed in the cluster. + minProperties: 1 properties: imageRepository: description: |- @@ -4592,6 +4595,7 @@ spec: description: |- etcd holds configuration for etcd. NB: This value defaults to a Local (stacked) etcd + minProperties: 1 properties: external: description: |- @@ -4862,6 +4866,7 @@ spec: scheduler: description: scheduler contains extra settings for the scheduler control plane component + minProperties: 1 properties: extraArgs: description: |- @@ -5329,6 +5334,7 @@ spec: configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process fails you may set the desired value here. + minProperties: 1 properties: advertiseAddress: description: advertiseAddress sets the IP address for the @@ -5349,6 +5355,7 @@ spec: nodeRegistration holds fields that relate to registering the new control-plane node to the cluster. When used in the context of control plane nodes, NodeRegistration should remain consistent across both InitConfiguration and JoinConfiguration + minProperties: 1 properties: criSocket: description: criSocket is used to retrieve container runtime @@ -5372,8 +5379,7 @@ spec: imagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations. The value of this field must be one of "Always", "IfNotPresent" or - "Never". Defaults to "IfNotPresent". This can be used only - with Kubernetes version equal to 1.22 and later. + "Never". Defaults to "IfNotPresent". enum: - Always - IfNotPresent @@ -5461,6 +5467,7 @@ spec: - key type: object maxItems: 100 + minItems: 0 type: array type: object patches: @@ -5569,6 +5576,7 @@ spec: localAPIEndpoint: description: localAPIEndpoint represents the endpoint of the API server instance to be deployed on this node. + minProperties: 1 properties: advertiseAddress: description: advertiseAddress sets the IP address for @@ -5588,6 +5596,7 @@ spec: discovery: description: discovery specifies the options for the kubelet to use during the TLS Bootstrap process + minProperties: 1 properties: bootstrapToken: description: |- @@ -5812,6 +5821,7 @@ spec: nodeRegistration holds fields that relate to registering the new control-plane node to the cluster. When used in the context of control plane nodes, NodeRegistration should remain consistent across both InitConfiguration and JoinConfiguration + minProperties: 1 properties: criSocket: description: criSocket is used to retrieve container runtime @@ -5835,8 +5845,7 @@ spec: imagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations. The value of this field must be one of "Always", "IfNotPresent" or - "Never". Defaults to "IfNotPresent". This can be used only - with Kubernetes version equal to 1.22 and later. + "Never". Defaults to "IfNotPresent". enum: - Always - IfNotPresent @@ -5924,6 +5933,7 @@ spec: - key type: object maxItems: 100 + minItems: 0 type: array type: object patches: diff --git a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml index 22535b1c6cc5..3875eed81115 100644 --- a/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml +++ b/bootstrap/kubeadm/config/crd/bases/bootstrap.cluster.x-k8s.io_kubeadmconfigtemplates.yaml @@ -3964,6 +3964,7 @@ spec: description: |- metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: @@ -4006,6 +4007,7 @@ spec: apiServer: description: apiServer contains extra settings for the API server control plane component + minProperties: 1 properties: certSANs: description: certSANs sets extra Subject Alternative @@ -4246,6 +4248,7 @@ spec: controllerManager: description: controllerManager contains extra settings for the controller manager control plane component + minProperties: 1 properties: extraArgs: description: |- @@ -4453,6 +4456,7 @@ spec: dns: description: dns defines the options for the DNS add-on installed in the cluster. + minProperties: 1 properties: imageRepository: description: |- @@ -4473,6 +4477,7 @@ spec: description: |- etcd holds configuration for etcd. NB: This value defaults to a Local (stacked) etcd + minProperties: 1 properties: external: description: |- @@ -4751,6 +4756,7 @@ spec: scheduler: description: scheduler contains extra settings for the scheduler control plane component + minProperties: 1 properties: extraArgs: description: |- @@ -5232,6 +5238,7 @@ spec: configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process fails you may set the desired value here. + minProperties: 1 properties: advertiseAddress: description: advertiseAddress sets the IP address @@ -5252,6 +5259,7 @@ spec: nodeRegistration holds fields that relate to registering the new control-plane node to the cluster. When used in the context of control plane nodes, NodeRegistration should remain consistent across both InitConfiguration and JoinConfiguration + minProperties: 1 properties: criSocket: description: criSocket is used to retrieve container @@ -5275,8 +5283,7 @@ spec: imagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations. The value of this field must be one of "Always", "IfNotPresent" or - "Never". Defaults to "IfNotPresent". This can be used only - with Kubernetes version equal to 1.22 and later. + "Never". Defaults to "IfNotPresent". enum: - Always - IfNotPresent @@ -5364,6 +5371,7 @@ spec: - key type: object maxItems: 100 + minItems: 0 type: array type: object patches: @@ -5473,6 +5481,7 @@ spec: description: localAPIEndpoint represents the endpoint of the API server instance to be deployed on this node. + minProperties: 1 properties: advertiseAddress: description: advertiseAddress sets the IP address @@ -5492,6 +5501,7 @@ spec: discovery: description: discovery specifies the options for the kubelet to use during the TLS Bootstrap process + minProperties: 1 properties: bootstrapToken: description: |- @@ -5722,6 +5732,7 @@ spec: nodeRegistration holds fields that relate to registering the new control-plane node to the cluster. When used in the context of control plane nodes, NodeRegistration should remain consistent across both InitConfiguration and JoinConfiguration + minProperties: 1 properties: criSocket: description: criSocket is used to retrieve container @@ -5745,8 +5756,7 @@ spec: imagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations. The value of this field must be one of "Always", "IfNotPresent" or - "Never". Defaults to "IfNotPresent". This can be used only - with Kubernetes version equal to 1.22 and later. + "Never". Defaults to "IfNotPresent". enum: - Always - IfNotPresent @@ -5834,6 +5844,7 @@ spec: - key type: object maxItems: 100 + minItems: 0 type: array type: object patches: diff --git a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go index f244be696968..724fc3ccd293 100644 --- a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go +++ b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go @@ -722,8 +722,8 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope) // Do not modify the KubeadmConfig in etcd as this is a temporary taint that will be dropped after the node // is initialized by ClusterAPI. joinConfiguration := scope.Config.Spec.JoinConfiguration.DeepCopy() - if !taints.HasTaint(joinConfiguration.NodeRegistration.Taints, clusterv1.NodeUninitializedTaint) { - joinConfiguration.NodeRegistration.Taints = append(joinConfiguration.NodeRegistration.Taints, clusterv1.NodeUninitializedTaint) + if !taints.HasTaint(ptr.Deref(joinConfiguration.NodeRegistration.Taints, []corev1.Taint{}), clusterv1.NodeUninitializedTaint) { + joinConfiguration.NodeRegistration.Taints = ptr.To(append(ptr.Deref(joinConfiguration.NodeRegistration.Taints, []corev1.Taint{}), clusterv1.NodeUninitializedTaint)) } // NOTE: It is not required to provide in input ClusterConfiguration because only clusterConfiguration.APIServer.TimeoutForControlPlane diff --git a/bootstrap/kubeadm/types/upstreamv1beta3/conversion.go b/bootstrap/kubeadm/types/upstreamv1beta3/conversion.go index 9c0765cb881d..ba43c94bfc42 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta3/conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta3/conversion.go @@ -91,6 +91,14 @@ func Convert_upstreamv1beta3_APIServer_To_v1beta2_APIServer(in *APIServer, out * return autoConvert_upstreamv1beta3_APIServer_To_v1beta2_APIServer(in, out, s) } +func Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_ControllerManager(in *ControlPlaneComponent, out *bootstrapv1.ControllerManager, s apimachineryconversion.Scope) error { + return Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + +func Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_Scheduler(in *ControlPlaneComponent, out *bootstrapv1.Scheduler, s apimachineryconversion.Scope) error { + return Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + func Convert_upstreamv1beta3_Discovery_To_v1beta2_Discovery(in *Discovery, out *bootstrapv1.Discovery, s apimachineryconversion.Scope) error { // Discovery.Timeout does not exist in CABPK, because CABPK aligns to upstreamV1Beta4. return autoConvert_upstreamv1beta3_Discovery_To_v1beta2_Discovery(in, out, s) @@ -108,6 +116,11 @@ func Convert_upstreamv1beta3_LocalEtcd_To_v1beta2_LocalEtcd(in *LocalEtcd, out * func Convert_upstreamv1beta3_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *bootstrapv1.NodeRegistrationOptions, s apimachineryconversion.Scope) error { out.KubeletExtraArgs = bootstrapv1.ConvertToArgs(in.KubeletExtraArgs) + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = ptr.To(in.Taints) + } return autoConvert_upstreamv1beta3_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in, out, s) } @@ -143,6 +156,14 @@ func Convert_v1beta2_FileDiscovery_To_upstreamv1beta3_FileDiscovery(in *bootstra return autoConvert_v1beta2_FileDiscovery_To_upstreamv1beta3_FileDiscovery(in, out, s) } +func Convert_v1beta2_ControllerManager_To_upstreamv1beta3_ControlPlaneComponent(in *bootstrapv1.ControllerManager, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + return Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + +func Convert_v1beta2_Scheduler_To_upstreamv1beta3_ControlPlaneComponent(in *bootstrapv1.Scheduler, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + return Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + func Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(in *bootstrapv1.ControlPlaneComponent, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { // ControlPlaneComponent.ExtraEnvs does not exist in kubeadm v1beta3, dropping this info. @@ -167,6 +188,11 @@ func Convert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistration // Following fields require a custom conversions. // Note: there is a potential info loss when there are two values for the same arg but this is accepted because the kubeadm v1beta3 API does not allow this use case. out.KubeletExtraArgs = bootstrapv1.ConvertFromArgs(in.KubeletExtraArgs) + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = *in.Taints + } return autoConvert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistrationOptions(in, out, s) } diff --git a/bootstrap/kubeadm/types/upstreamv1beta3/conversion_test.go b/bootstrap/kubeadm/types/upstreamv1beta3/conversion_test.go index 83404d76dc98..0cb9f908ccf2 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta3/conversion_test.go +++ b/bootstrap/kubeadm/types/upstreamv1beta3/conversion_test.go @@ -186,6 +186,10 @@ func hubNodeRegistrationOptionsFuzzer(obj *bootstrapv1.NodeRegistrationOptions, c.FillNoCustom(obj) obj.ImagePullSerial = nil + + if obj.Taints != nil && *obj.Taints == nil { + obj.Taints = nil + } } func hubInitConfigurationFuzzer(obj *bootstrapv1.InitConfiguration, c randfill.Continue) { diff --git a/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go index a5b6bb53d23c..287dbd63112f 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go @@ -173,6 +173,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.ControllerManager)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_ControllerManager(a.(*ControlPlaneComponent), b.(*v1beta2.ControllerManager), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.Scheduler)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_Scheduler(a.(*ControlPlaneComponent), b.(*v1beta2.Scheduler), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*Discovery)(nil), (*v1beta2.Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_upstreamv1beta3_Discovery_To_v1beta2_Discovery(a.(*Discovery), b.(*v1beta2.Discovery), scope) }); err != nil { @@ -213,6 +223,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.ControllerManager)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ControllerManager_To_upstreamv1beta3_ControlPlaneComponent(a.(*v1beta2.ControllerManager), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.FileDiscovery)(nil), (*FileDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_FileDiscovery_To_upstreamv1beta3_FileDiscovery(a.(*v1beta2.FileDiscovery), b.(*FileDiscovery), scope) }); err != nil { @@ -238,6 +253,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.Scheduler)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Scheduler_To_upstreamv1beta3_ControlPlaneComponent(a.(*v1beta2.Scheduler), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } return nil } @@ -368,10 +388,10 @@ func autoConvert_upstreamv1beta3_ClusterConfiguration_To_v1beta2_ClusterConfigur if err := Convert_upstreamv1beta3_APIServer_To_v1beta2_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_ControllerManager(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta2_Scheduler(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_upstreamv1beta3_DNS_To_v1beta2_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -392,10 +412,10 @@ func autoConvert_v1beta2_ClusterConfiguration_To_upstreamv1beta3_ClusterConfigur if err := Convert_v1beta2_APIServer_To_upstreamv1beta3_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_v1beta2_ControllerManager_To_upstreamv1beta3_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_v1beta2_Scheduler_To_upstreamv1beta3_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_v1beta2_DNS_To_upstreamv1beta3_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -796,7 +816,7 @@ func autoConvert_v1beta2_LocalEtcd_To_upstreamv1beta3_LocalEtcd(in *v1beta2.Loca func autoConvert_upstreamv1beta3_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *v1beta2.NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types ([]k8s.io/api/core/v1.Taint vs *[]k8s.io/api/core/v1.Taint) // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2.Arg) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy) @@ -806,7 +826,7 @@ func autoConvert_upstreamv1beta3_NodeRegistrationOptions_To_v1beta2_NodeRegistra func autoConvert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistrationOptions(in *v1beta2.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types (*[]k8s.io/api/core/v1.Taint vs []k8s.io/api/core/v1.Taint) // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2.Arg vs map[string]string) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = string(in.ImagePullPolicy) diff --git a/bootstrap/kubeadm/types/upstreamv1beta4/conversion.go b/bootstrap/kubeadm/types/upstreamv1beta4/conversion.go index 4060161930e6..f3fbc1c1fe71 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta4/conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta4/conversion.go @@ -108,6 +108,15 @@ func Convert_upstreamv1beta4_Timeouts_To_v1beta2_Timeouts(in *Timeouts, out *boo return nil } +func Convert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *bootstrapv1.NodeRegistrationOptions, s apimachineryconversion.Scope) error { + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = ptr.To(in.Taints) + } + return autoConvert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in, out, s) +} + func Convert_upstreamv1beta4_BootstrapToken_To_v1beta2_BootstrapToken(in *BootstrapToken, out *bootstrapv1.BootstrapToken, s apimachineryconversion.Scope) error { if err := autoConvert_upstreamv1beta4_BootstrapToken_To_v1beta2_BootstrapToken(in, out, s); err != nil { return err @@ -116,6 +125,14 @@ func Convert_upstreamv1beta4_BootstrapToken_To_v1beta2_BootstrapToken(in *Bootst return nil } +func Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_ControllerManager(in *ControlPlaneComponent, out *bootstrapv1.ControllerManager, s apimachineryconversion.Scope) error { + return Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + +func Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_Scheduler(in *ControlPlaneComponent, out *bootstrapv1.Scheduler, s apimachineryconversion.Scope) error { + return Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + // Custom conversion from the hub version, CABPK v1beta1, to this API, kubeadm v1beta4. func Convert_v1beta2_APIServer_To_upstreamv1beta4_APIServer(in *bootstrapv1.APIServer, out *APIServer, s apimachineryconversion.Scope) error { @@ -124,6 +141,14 @@ func Convert_v1beta2_APIServer_To_upstreamv1beta4_APIServer(in *bootstrapv1.APIS return autoConvert_v1beta2_APIServer_To_upstreamv1beta4_APIServer(in, out, s) } +func Convert_v1beta2_ControllerManager_To_upstreamv1beta4_ControlPlaneComponent(in *bootstrapv1.ControllerManager, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + return Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta4_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + +func Convert_v1beta2_Scheduler_To_upstreamv1beta4_ControlPlaneComponent(in *bootstrapv1.Scheduler, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + return Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta4_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + func Convert_v1beta2_Discovery_To_upstreamv1beta4_Discovery(in *bootstrapv1.Discovery, out *Discovery, s apimachineryconversion.Scope) error { // Following fields do not exist in kubeadm v1beta4 version: // - Timeout (this field has been migrated to JoinConfiguration.Timeouts.TLSBootstrap, the conversion is handled in Convert_v1beta2_JoinConfiguration_To_upstreamv1beta4_JoinConfiguration) @@ -149,6 +174,15 @@ func Convert_v1beta2_Timeouts_To_upstreamv1beta4_Timeouts(in *bootstrapv1.Timeou return nil } +func Convert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, out *NodeRegistrationOptions, s apimachineryconversion.Scope) error { + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = *in.Taints + } + return autoConvert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistrationOptions(in, out, s) +} + func Convert_v1beta2_BootstrapToken_To_upstreamv1beta4_BootstrapToken(in *bootstrapv1.BootstrapToken, out *BootstrapToken, s apimachineryconversion.Scope) error { if err := autoConvert_v1beta2_BootstrapToken_To_upstreamv1beta4_BootstrapToken(in, out, s); err != nil { return err diff --git a/bootstrap/kubeadm/types/upstreamv1beta4/conversion_test.go b/bootstrap/kubeadm/types/upstreamv1beta4/conversion_test.go index 38739e128d86..9f33d72f1beb 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta4/conversion_test.go +++ b/bootstrap/kubeadm/types/upstreamv1beta4/conversion_test.go @@ -80,6 +80,7 @@ func fuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { hubJoinConfigurationFuzzer, hubHostPathMountFuzzer, hubBootstrapTokenDiscoveryFuzzer, + hubNodeRegistrationOptionsFuzzer, } } @@ -200,3 +201,11 @@ func hubBootstrapTokenDiscoveryFuzzer(obj *bootstrapv1.BootstrapTokenDiscovery, obj.UnsafeSkipCAVerification = ptr.To(false) } } + +func hubNodeRegistrationOptionsFuzzer(obj *bootstrapv1.NodeRegistrationOptions, c randfill.Continue) { + c.FillNoCustom(obj) + + if obj.Taints != nil && *obj.Taints == nil { + obj.Taints = nil + } +} diff --git a/bootstrap/kubeadm/types/upstreamv1beta4/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta4/zz_generated.conversion.go index e6bf72b529e9..56eaa6a17315 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta4/zz_generated.conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta4/zz_generated.conversion.go @@ -188,16 +188,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*NodeRegistrationOptions)(nil), (*v1beta2.NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(a.(*NodeRegistrationOptions), b.(*v1beta2.NodeRegistrationOptions), scope) - }); err != nil { - return err - } - if err := s.AddGeneratedConversionFunc((*v1beta2.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistrationOptions(a.(*v1beta2.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*Patches)(nil), (*v1beta2.Patches)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_upstreamv1beta4_Patches_To_v1beta2_Patches(a.(*Patches), b.(*v1beta2.Patches), scope) }); err != nil { @@ -218,6 +208,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.ControllerManager)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_ControllerManager(a.(*ControlPlaneComponent), b.(*v1beta2.ControllerManager), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.Scheduler)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_Scheduler(a.(*ControlPlaneComponent), b.(*v1beta2.Scheduler), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*DNS)(nil), (*v1beta2.DNS)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_upstreamv1beta4_DNS_To_v1beta2_DNS(a.(*DNS), b.(*v1beta2.DNS), scope) }); err != nil { @@ -238,6 +238,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*NodeRegistrationOptions)(nil), (*v1beta2.NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(a.(*NodeRegistrationOptions), b.(*v1beta2.NodeRegistrationOptions), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*Timeouts)(nil), (*v1beta2.Timeouts)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_upstreamv1beta4_Timeouts_To_v1beta2_Timeouts(a.(*Timeouts), b.(*v1beta2.Timeouts), scope) }); err != nil { @@ -253,6 +258,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.ControllerManager)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ControllerManager_To_upstreamv1beta4_ControlPlaneComponent(a.(*v1beta2.ControllerManager), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.Discovery)(nil), (*Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_Discovery_To_upstreamv1beta4_Discovery(a.(*v1beta2.Discovery), b.(*Discovery), scope) }); err != nil { @@ -263,6 +273,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.NodeRegistrationOptions)(nil), (*NodeRegistrationOptions)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistrationOptions(a.(*v1beta2.NodeRegistrationOptions), b.(*NodeRegistrationOptions), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta2.Scheduler)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Scheduler_To_upstreamv1beta4_ControlPlaneComponent(a.(*v1beta2.Scheduler), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.Timeouts)(nil), (*Timeouts)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_Timeouts_To_upstreamv1beta4_Timeouts(a.(*v1beta2.Timeouts), b.(*Timeouts), scope) }); err != nil { @@ -419,10 +439,10 @@ func autoConvert_upstreamv1beta4_ClusterConfiguration_To_v1beta2_ClusterConfigur if err := Convert_upstreamv1beta4_APIServer_To_v1beta2_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_ControllerManager(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta2_Scheduler(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_upstreamv1beta4_DNS_To_v1beta2_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -447,10 +467,10 @@ func autoConvert_v1beta2_ClusterConfiguration_To_upstreamv1beta4_ClusterConfigur if err := Convert_v1beta2_APIServer_To_upstreamv1beta4_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta4_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_v1beta2_ControllerManager_To_upstreamv1beta4_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_upstreamv1beta4_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_v1beta2_Scheduler_To_upstreamv1beta4_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_v1beta2_DNS_To_upstreamv1beta4_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -918,7 +938,7 @@ func Convert_v1beta2_LocalEtcd_To_upstreamv1beta4_LocalEtcd(in *v1beta2.LocalEtc func autoConvert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *v1beta2.NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types ([]k8s.io/api/core/v1.Taint vs *[]k8s.io/api/core/v1.Taint) out.KubeletExtraArgs = *(*[]v1beta2.Arg)(unsafe.Pointer(&in.KubeletExtraArgs)) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy) @@ -926,15 +946,10 @@ func autoConvert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistra return nil } -// Convert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions is an autogenerated conversion function. -func Convert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *v1beta2.NodeRegistrationOptions, s conversion.Scope) error { - return autoConvert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in, out, s) -} - func autoConvert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistrationOptions(in *v1beta2.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types (*[]k8s.io/api/core/v1.Taint vs []k8s.io/api/core/v1.Taint) out.KubeletExtraArgs = *(*[]Arg)(unsafe.Pointer(&in.KubeletExtraArgs)) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy) @@ -942,11 +957,6 @@ func autoConvert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistra return nil } -// Convert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistrationOptions is an autogenerated conversion function. -func Convert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistrationOptions(in *v1beta2.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { - return autoConvert_v1beta2_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistrationOptions(in, out, s) -} - func autoConvert_upstreamv1beta4_Patches_To_v1beta2_Patches(in *Patches, out *v1beta2.Patches, s conversion.Scope) error { out.Directory = in.Directory return nil diff --git a/cmd/clusterctl/client/cluster/mover_test.go b/cmd/clusterctl/client/cluster/mover_test.go index 35088119c5c6..5d4e2dc33431 100644 --- a/cmd/clusterctl/client/cluster/mover_test.go +++ b/cmd/clusterctl/client/cluster/mover_test.go @@ -693,7 +693,7 @@ var backupRestoreTests = []struct { objs: test.NewFakeCluster("ns1", "foo").Objs(), }, files: map[string]string{ - "Cluster_ns1_foo.yaml": `{"apiVersion":"$CAPI","kind":"Cluster","metadata":{"creationTimestamp":null,"name":"foo","namespace":"ns1","resourceVersion":"999","uid":"$CAPI, Kind=Cluster, ns1/foo"},"spec":{"controlPlaneEndpoint":{"host":"","port":0},"infrastructureRef":{"apiGroup":"$INFRA_GROUP","kind":"GenericInfrastructureCluster","name":"foo"}}}` + "\n", + "Cluster_ns1_foo.yaml": `{"apiVersion":"$CAPI","kind":"Cluster","metadata":{"creationTimestamp":null,"name":"foo","namespace":"ns1","resourceVersion":"999","uid":"$CAPI, Kind=Cluster, ns1/foo"},"spec":{"infrastructureRef":{"apiGroup":"$INFRA_GROUP","kind":"GenericInfrastructureCluster","name":"foo"}}}` + "\n", "Secret_ns1_foo-kubeconfig.yaml": `{"apiVersion":"v1","kind":"Secret","metadata":{"creationTimestamp":null,"name":"foo-kubeconfig","namespace":"ns1","ownerReferences":[{"apiVersion":"$CAPI","kind":"Cluster","name":"foo","uid":"$CAPI, Kind=Cluster, ns1/foo"}],"resourceVersion":"999","uid":"/v1, Kind=Secret, ns1/foo-kubeconfig"}}` + "\n", "Secret_ns1_foo-ca.yaml": `{"apiVersion":"v1","kind":"Secret","metadata":{"creationTimestamp":null,"name":"foo-ca","namespace":"ns1","resourceVersion":"999","uid":"/v1, Kind=Secret, ns1/foo-ca"}}` + "\n", "GenericInfrastructureCluster_ns1_foo.yaml": `{"apiVersion":"$INFRA","kind":"GenericInfrastructureCluster","metadata":{"creationTimestamp":null,"labels":{"cluster.x-k8s.io/cluster-name":"foo"},"name":"foo","namespace":"ns1","ownerReferences":[{"apiVersion":"$CAPI","kind":"Cluster","name":"foo","uid":"$CAPI, Kind=Cluster, ns1/foo"}],"resourceVersion":"999","uid":"$INFRA, Kind=GenericInfrastructureCluster, ns1/foo"}}` + "\n", @@ -711,11 +711,11 @@ var backupRestoreTests = []struct { }(), }, files: map[string]string{ - "Cluster_ns1_foo.yaml": `{"apiVersion":"$CAPI","kind":"Cluster","metadata":{"creationTimestamp":null,"name":"foo","namespace":"ns1","resourceVersion":"999","uid":"$CAPI, Kind=Cluster, ns1/foo"},"spec":{"controlPlaneEndpoint":{"host":"","port":0},"infrastructureRef":{"apiGroup":"$INFRA_GROUP","kind":"GenericInfrastructureCluster","name":"foo"}}}` + "\n", + "Cluster_ns1_foo.yaml": `{"apiVersion":"$CAPI","kind":"Cluster","metadata":{"creationTimestamp":null,"name":"foo","namespace":"ns1","resourceVersion":"999","uid":"$CAPI, Kind=Cluster, ns1/foo"},"spec":{"infrastructureRef":{"apiGroup":"$INFRA_GROUP","kind":"GenericInfrastructureCluster","name":"foo"}}}` + "\n", "Secret_ns1_foo-kubeconfig.yaml": `{"apiVersion":"v1","kind":"Secret","metadata":{"creationTimestamp":null,"name":"foo-kubeconfig","namespace":"ns1","ownerReferences":[{"apiVersion":"$CAPI","kind":"Cluster","name":"foo","uid":"$CAPI, Kind=Cluster, ns1/foo"}],"resourceVersion":"999","uid":"/v1, Kind=Secret, ns1/foo-kubeconfig"}}` + "\n", "Secret_ns1_foo-ca.yaml": `{"apiVersion":"v1","kind":"Secret","metadata":{"creationTimestamp":null,"name":"foo-ca","namespace":"ns1","resourceVersion":"999","uid":"/v1, Kind=Secret, ns1/foo-ca"}}` + "\n", "GenericInfrastructureCluster_ns1_foo.yaml": `{"apiVersion":"$INFRA","kind":"GenericInfrastructureCluster","metadata":{"creationTimestamp":null,"labels":{"cluster.x-k8s.io/cluster-name":"foo"},"name":"foo","namespace":"ns1","ownerReferences":[{"apiVersion":"$CAPI","kind":"Cluster","name":"foo","uid":"$CAPI, Kind=Cluster, ns1/foo"}],"resourceVersion":"999","uid":"$INFRA, Kind=GenericInfrastructureCluster, ns1/foo"}}` + "\n", - "Cluster_ns2_bar.yaml": `{"apiVersion":"$CAPI","kind":"Cluster","metadata":{"creationTimestamp":null,"name":"bar","namespace":"ns2","resourceVersion":"999","uid":"$CAPI, Kind=Cluster, ns2/bar"},"spec":{"controlPlaneEndpoint":{"host":"","port":0},"infrastructureRef":{"apiGroup":"$INFRA_GROUP","kind":"GenericInfrastructureCluster","name":"bar"}}}` + "\n", + "Cluster_ns2_bar.yaml": `{"apiVersion":"$CAPI","kind":"Cluster","metadata":{"creationTimestamp":null,"name":"bar","namespace":"ns2","resourceVersion":"999","uid":"$CAPI, Kind=Cluster, ns2/bar"},"spec":{"infrastructureRef":{"apiGroup":"$INFRA_GROUP","kind":"GenericInfrastructureCluster","name":"bar"}}}` + "\n", "Secret_ns2_bar-kubeconfig.yaml": `{"apiVersion":"v1","kind":"Secret","metadata":{"creationTimestamp":null,"name":"bar-kubeconfig","namespace":"ns2","ownerReferences":[{"apiVersion":"$CAPI","kind":"Cluster","name":"bar","uid":"$CAPI, Kind=Cluster, ns2/bar"}],"resourceVersion":"999","uid":"/v1, Kind=Secret, ns2/bar-kubeconfig"}}` + "\n", "Secret_ns2_bar-ca.yaml": `{"apiVersion":"v1","kind":"Secret","metadata":{"creationTimestamp":null,"name":"bar-ca","namespace":"ns2","resourceVersion":"999","uid":"/v1, Kind=Secret, ns2/bar-ca"}}` + "\n", "GenericInfrastructureCluster_ns2_bar.yaml": `{"apiVersion":"$INFRA","kind":"GenericInfrastructureCluster","metadata":{"creationTimestamp":null,"labels":{"cluster.x-k8s.io/cluster-name":"bar"},"name":"bar","namespace":"ns2","ownerReferences":[{"apiVersion":"$CAPI","kind":"Cluster","name":"bar","uid":"$CAPI, Kind=Cluster, ns2/bar"}],"resourceVersion":"999","uid":"$INFRA, Kind=GenericInfrastructureCluster, ns2/bar"}}` + "\n", diff --git a/cmd/clusterctl/client/cluster/objectgraph.go b/cmd/clusterctl/client/cluster/objectgraph.go index 2408805fb7bb..0113eba5ff9c 100644 --- a/cmd/clusterctl/client/cluster/objectgraph.go +++ b/cmd/clusterctl/client/cluster/objectgraph.go @@ -521,27 +521,27 @@ func (o *objectGraph) Discovery(ctx context.Context, namespace string) error { } errs := []error{} - _, err = o.fetchRef(ctx, discoveryBackoff, cc.Spec.Infrastructure.Ref.ToObjectReference(cc.Namespace)) + _, err = o.fetchRef(ctx, discoveryBackoff, cc.Spec.Infrastructure.TemplateRef.ToObjectReference(cc.Namespace)) errs = append(errs, err) - _, err = o.fetchRef(ctx, discoveryBackoff, cc.Spec.ControlPlane.Ref.ToObjectReference(cc.Namespace)) + _, err = o.fetchRef(ctx, discoveryBackoff, cc.Spec.ControlPlane.TemplateRef.ToObjectReference(cc.Namespace)) errs = append(errs, err) if cc.Spec.ControlPlane.MachineInfrastructure != nil { - _, err = o.fetchRef(ctx, discoveryBackoff, cc.Spec.ControlPlane.MachineInfrastructure.Ref.ToObjectReference(cc.Namespace)) + _, err = o.fetchRef(ctx, discoveryBackoff, cc.Spec.ControlPlane.MachineInfrastructure.TemplateRef.ToObjectReference(cc.Namespace)) errs = append(errs, err) } for _, mdClass := range cc.Spec.Workers.MachineDeployments { - _, err = o.fetchRef(ctx, discoveryBackoff, mdClass.Template.Infrastructure.Ref.ToObjectReference(cc.Namespace)) + _, err = o.fetchRef(ctx, discoveryBackoff, mdClass.Template.Infrastructure.TemplateRef.ToObjectReference(cc.Namespace)) errs = append(errs, err) - _, err = o.fetchRef(ctx, discoveryBackoff, mdClass.Template.Bootstrap.Ref.ToObjectReference(cc.Namespace)) + _, err = o.fetchRef(ctx, discoveryBackoff, mdClass.Template.Bootstrap.TemplateRef.ToObjectReference(cc.Namespace)) errs = append(errs, err) } for _, mpClass := range cc.Spec.Workers.MachinePools { - _, err = o.fetchRef(ctx, discoveryBackoff, mpClass.Template.Infrastructure.Ref.ToObjectReference(cc.Namespace)) + _, err = o.fetchRef(ctx, discoveryBackoff, mpClass.Template.Infrastructure.TemplateRef.ToObjectReference(cc.Namespace)) errs = append(errs, err) - _, err = o.fetchRef(ctx, discoveryBackoff, mpClass.Template.Bootstrap.Ref.ToObjectReference(cc.Namespace)) + _, err = o.fetchRef(ctx, discoveryBackoff, mpClass.Template.Bootstrap.TemplateRef.ToObjectReference(cc.Namespace)) errs = append(errs, err) } diff --git a/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml b/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml index 0eb8e6981e73..2dde73afafcb 100644 --- a/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml +++ b/config/crd/bases/cluster.x-k8s.io_clusterclasses.yaml @@ -3020,10 +3020,9 @@ spec: This field is supported if and only if the control plane provider template referenced above is Machine based and supports setting replicas. properties: - ref: - description: |- - ref is a required reference to a custom resource - offered by a provider. + templateRef: + description: templateRef is a required reference to the template + for a MachineInfrastructure of a ControlPlane. properties: apiVersion: description: |- @@ -3055,7 +3054,7 @@ spec: - name type: object required: - - ref + - templateRef type: object metadata: description: |- @@ -3066,6 +3065,7 @@ spec: This field is supported if and only if the control plane provider template referenced is Machine based. + minProperties: 1 properties: annotations: additionalProperties: @@ -3173,10 +3173,9 @@ spec: x-kubernetes-list-map-keys: - conditionType x-kubernetes-list-type: map - ref: - description: |- - ref is a required reference to a custom resource - offered by a provider. + templateRef: + description: templateRef contains the reference to a provider-specific + control plane template. properties: apiVersion: description: |- @@ -3208,7 +3207,7 @@ spec: - name type: object required: - - ref + - templateRef type: object infrastructure: description: |- @@ -3232,10 +3231,9 @@ spec: minLength: 1 type: string type: object - ref: - description: |- - ref is a required reference to a custom resource - offered by a provider. + templateRef: + description: templateRef contains the reference to a provider-specific + infrastructure cluster template. properties: apiVersion: description: |- @@ -3267,7 +3265,7 @@ spec: - name type: object required: - - ref + - templateRef type: object patches: description: |- @@ -3502,6 +3500,7 @@ spec: a ClusterClassVariable. Deprecated: This field is deprecated and will be removed when support for v1beta1 will be dropped. Please use XMetadata in JSONSchemaProps instead. + minProperties: 1 properties: annotations: additionalProperties: @@ -3903,6 +3902,7 @@ spec: workers describes the worker nodes for the cluster. It is a collection of node types which can be used to create the worker nodes of the cluster. + minProperties: 1 properties: machineDeployments: description: |- @@ -4246,10 +4246,9 @@ spec: bootstrap contains the bootstrap template reference to be used for the creation of worker Machines. properties: - ref: - description: |- - ref is a required reference to a custom resource - offered by a provider. + templateRef: + description: templateRef is a required reference + to the BootstrapTemplate for a MachineDeployment. properties: apiVersion: description: |- @@ -4281,17 +4280,16 @@ spec: - name type: object required: - - ref + - templateRef type: object infrastructure: description: |- infrastructure contains the infrastructure template reference to be used for the creation of worker Machines. properties: - ref: - description: |- - ref is a required reference to a custom resource - offered by a provider. + templateRef: + description: templateRef is a required reference + to the InfrastructureTemplate for a MachineDeployment. properties: apiVersion: description: |- @@ -4323,12 +4321,13 @@ spec: - name type: object required: - - ref + - templateRef type: object metadata: description: |- metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment. At runtime this metadata is merged with the corresponding metadata from the topology. + minProperties: 1 properties: annotations: additionalProperties: @@ -4453,10 +4452,9 @@ spec: bootstrap contains the bootstrap template reference to be used for the creation of the Machines in the MachinePool. properties: - ref: - description: |- - ref is a required reference to a custom resource - offered by a provider. + templateRef: + description: templateRef is a required reference + to the BootstrapTemplate for a MachinePool. properties: apiVersion: description: |- @@ -4488,17 +4486,16 @@ spec: - name type: object required: - - ref + - templateRef type: object infrastructure: description: |- infrastructure contains the infrastructure template reference to be used for the creation of the MachinePool. properties: - ref: - description: |- - ref is a required reference to a custom resource - offered by a provider. + templateRef: + description: templateRef is a required reference + to the InfrastructureTemplate for a MachinePool. properties: apiVersion: description: |- @@ -4530,12 +4527,13 @@ spec: - name type: object required: - - ref + - templateRef type: object metadata: description: |- metadata is the metadata applied to the MachinePool. At runtime this metadata is merged with the corresponding metadata from the topology. + minProperties: 1 properties: annotations: additionalProperties: @@ -4730,6 +4728,7 @@ spec: a ClusterClassVariable. Deprecated: This field is deprecated and will be removed when support for v1beta1 will be dropped. Please use XMetadata in JSONSchemaProps instead. + minProperties: 1 properties: annotations: additionalProperties: diff --git a/config/crd/bases/cluster.x-k8s.io_clusters.yaml b/config/crd/bases/cluster.x-k8s.io_clusters.yaml index b814f9d7a4f0..412b0f6631e9 100644 --- a/config/crd/bases/cluster.x-k8s.io_clusters.yaml +++ b/config/crd/bases/cluster.x-k8s.io_clusters.yaml @@ -2149,7 +2149,7 @@ spec: - additionalPrinterColumns: - description: ClusterClass of this Cluster, empty if the Cluster is not using a ClusterClass - jsonPath: .spec.topology.class + jsonPath: .spec.topology.classRef.name name: ClusterClass type: string - description: Cluster status such as Pending/Provisioning/Provisioned/Deleting/Failed @@ -2276,18 +2276,19 @@ spec: controlPlaneEndpoint: description: controlPlaneEndpoint represents the endpoint used to communicate with the control plane. + minProperties: 1 properties: host: description: host is the hostname on which the API server is serving. maxLength: 512 + minLength: 1 type: string port: description: port is the port on which the API server is serving. format: int32 + maximum: 65535 + minimum: 1 type: integer - required: - - host - - port type: object controlPlaneRef: description: |- @@ -2402,6 +2403,7 @@ spec: type: object controlPlane: description: controlPlane describes the cluster control plane. + minProperties: 1 properties: machineHealthCheck: description: |- @@ -2540,6 +2542,7 @@ spec: if the ControlPlaneTemplate referenced by the ClusterClass is machine based. If not, it is applied only to the ControlPlane. At runtime this metadata is merged with the corresponding metadata from the ClusterClass. + minProperties: 1 properties: annotations: additionalProperties: @@ -2875,6 +2878,7 @@ spec: description: |- metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment. At runtime this metadata is merged with the corresponding metadata from the ClusterClass. + minProperties: 1 properties: annotations: additionalProperties: @@ -3155,6 +3159,7 @@ spec: description: |- metadata is the metadata applied to the MachinePool. At runtime this metadata is merged with the corresponding metadata from the ClusterClass. + minProperties: 1 properties: annotations: additionalProperties: diff --git a/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml b/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml index 7e10f55733a0..c35829fd4fea 100644 --- a/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml +++ b/config/crd/bases/cluster.x-k8s.io_machinedeployments.yaml @@ -2092,6 +2092,7 @@ spec: description: |- metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/config/crd/bases/cluster.x-k8s.io_machinepools.yaml b/config/crd/bases/cluster.x-k8s.io_machinepools.yaml index df0b55d8f939..374b2f816e28 100644 --- a/config/crd/bases/cluster.x-k8s.io_machinepools.yaml +++ b/config/crd/bases/cluster.x-k8s.io_machinepools.yaml @@ -1701,6 +1701,7 @@ spec: description: |- metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/config/crd/bases/cluster.x-k8s.io_machinesets.yaml b/config/crd/bases/cluster.x-k8s.io_machinesets.yaml index a8aecbc63c54..89447e686572 100644 --- a/config/crd/bases/cluster.x-k8s.io_machinesets.yaml +++ b/config/crd/bases/cluster.x-k8s.io_machinesets.yaml @@ -1756,6 +1756,7 @@ spec: description: |- metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml index 72c58c493eb4..33c860c5c264 100644 --- a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml +++ b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanes.yaml @@ -5059,6 +5059,7 @@ spec: apiServer: description: apiServer contains extra settings for the API server control plane component + minProperties: 1 properties: certSANs: description: certSANs sets extra Subject Alternative Names @@ -5295,6 +5296,7 @@ spec: controllerManager: description: controllerManager contains extra settings for the controller manager control plane component + minProperties: 1 properties: extraArgs: description: |- @@ -5498,6 +5500,7 @@ spec: dns: description: dns defines the options for the DNS add-on installed in the cluster. + minProperties: 1 properties: imageRepository: description: |- @@ -5518,6 +5521,7 @@ spec: description: |- etcd holds configuration for etcd. NB: This value defaults to a Local (stacked) etcd + minProperties: 1 properties: external: description: |- @@ -5792,6 +5796,7 @@ spec: scheduler: description: scheduler contains extra settings for the scheduler control plane component + minProperties: 1 properties: extraArgs: description: |- @@ -6265,6 +6270,7 @@ spec: configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process fails you may set the desired value here. + minProperties: 1 properties: advertiseAddress: description: advertiseAddress sets the IP address for @@ -6285,6 +6291,7 @@ spec: nodeRegistration holds fields that relate to registering the new control-plane node to the cluster. When used in the context of control plane nodes, NodeRegistration should remain consistent across both InitConfiguration and JoinConfiguration + minProperties: 1 properties: criSocket: description: criSocket is used to retrieve container runtime @@ -6308,8 +6315,7 @@ spec: imagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations. The value of this field must be one of "Always", "IfNotPresent" or - "Never". Defaults to "IfNotPresent". This can be used only - with Kubernetes version equal to 1.22 and later. + "Never". Defaults to "IfNotPresent". enum: - Always - IfNotPresent @@ -6397,6 +6403,7 @@ spec: - key type: object maxItems: 100 + minItems: 0 type: array type: object patches: @@ -6505,6 +6512,7 @@ spec: localAPIEndpoint: description: localAPIEndpoint represents the endpoint of the API server instance to be deployed on this node. + minProperties: 1 properties: advertiseAddress: description: advertiseAddress sets the IP address @@ -6524,6 +6532,7 @@ spec: discovery: description: discovery specifies the options for the kubelet to use during the TLS Bootstrap process + minProperties: 1 properties: bootstrapToken: description: |- @@ -6751,6 +6760,7 @@ spec: nodeRegistration holds fields that relate to registering the new control-plane node to the cluster. When used in the context of control plane nodes, NodeRegistration should remain consistent across both InitConfiguration and JoinConfiguration + minProperties: 1 properties: criSocket: description: criSocket is used to retrieve container runtime @@ -6774,8 +6784,7 @@ spec: imagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations. The value of this field must be one of "Always", "IfNotPresent" or - "Never". Defaults to "IfNotPresent". This can be used only - with Kubernetes version equal to 1.22 and later. + "Never". Defaults to "IfNotPresent". enum: - Always - IfNotPresent @@ -6863,6 +6872,7 @@ spec: - key type: object maxItems: 100 + minItems: 0 type: array type: object patches: @@ -7172,6 +7182,7 @@ spec: description: |- metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml index 76a3bdbc2c4c..1b2b5d1147ef 100644 --- a/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml +++ b/controlplane/kubeadm/config/crd/bases/controlplane.cluster.x-k8s.io_kubeadmcontrolplanetemplates.yaml @@ -3373,6 +3373,7 @@ spec: description: |- metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: @@ -3420,6 +3421,7 @@ spec: apiServer: description: apiServer contains extra settings for the API server control plane component + minProperties: 1 properties: certSANs: description: certSANs sets extra Subject Alternative @@ -3664,6 +3666,7 @@ spec: controllerManager: description: controllerManager contains extra settings for the controller manager control plane component + minProperties: 1 properties: extraArgs: description: |- @@ -3875,6 +3878,7 @@ spec: dns: description: dns defines the options for the DNS add-on installed in the cluster. + minProperties: 1 properties: imageRepository: description: |- @@ -3895,6 +3899,7 @@ spec: description: |- etcd holds configuration for etcd. NB: This value defaults to a Local (stacked) etcd + minProperties: 1 properties: external: description: |- @@ -4180,6 +4185,7 @@ spec: scheduler: description: scheduler contains extra settings for the scheduler control plane component + minProperties: 1 properties: extraArgs: description: |- @@ -4668,6 +4674,7 @@ spec: configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible on. By default, kubeadm tries to auto-detect the IP of the default interface and use that, but in case that process fails you may set the desired value here. + minProperties: 1 properties: advertiseAddress: description: advertiseAddress sets the IP address @@ -4688,6 +4695,7 @@ spec: nodeRegistration holds fields that relate to registering the new control-plane node to the cluster. When used in the context of control plane nodes, NodeRegistration should remain consistent across both InitConfiguration and JoinConfiguration + minProperties: 1 properties: criSocket: description: criSocket is used to retrieve container @@ -4711,8 +4719,7 @@ spec: imagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations. The value of this field must be one of "Always", "IfNotPresent" or - "Never". Defaults to "IfNotPresent". This can be used only - with Kubernetes version equal to 1.22 and later. + "Never". Defaults to "IfNotPresent". enum: - Always - IfNotPresent @@ -4801,6 +4808,7 @@ spec: - key type: object maxItems: 100 + minItems: 0 type: array type: object patches: @@ -4910,6 +4918,7 @@ spec: description: localAPIEndpoint represents the endpoint of the API server instance to be deployed on this node. + minProperties: 1 properties: advertiseAddress: description: advertiseAddress sets the IP @@ -4929,6 +4938,7 @@ spec: discovery: description: discovery specifies the options for the kubelet to use during the TLS Bootstrap process + minProperties: 1 properties: bootstrapToken: description: |- @@ -5160,6 +5170,7 @@ spec: nodeRegistration holds fields that relate to registering the new control-plane node to the cluster. When used in the context of control plane nodes, NodeRegistration should remain consistent across both InitConfiguration and JoinConfiguration + minProperties: 1 properties: criSocket: description: criSocket is used to retrieve container @@ -5183,8 +5194,7 @@ spec: imagePullPolicy specifies the policy for image pulling during kubeadm "init" and "join" operations. The value of this field must be one of "Always", "IfNotPresent" or - "Never". Defaults to "IfNotPresent". This can be used only - with Kubernetes version equal to 1.22 and later. + "Never". Defaults to "IfNotPresent". enum: - Always - IfNotPresent @@ -5273,6 +5283,7 @@ spec: - key type: object maxItems: 100 + minItems: 0 type: array type: object patches: @@ -5551,6 +5562,7 @@ spec: description: |- metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/controlplane/kubeadm/internal/controllers/helpers_test.go b/controlplane/kubeadm/internal/controllers/helpers_test.go index f06c6d64fbca..69a688fa7344 100644 --- a/controlplane/kubeadm/internal/controllers/helpers_test.go +++ b/controlplane/kubeadm/internal/controllers/helpers_test.go @@ -547,7 +547,7 @@ func TestKubeadmControlPlaneReconciler_computeDesiredMachine(t *testing.T) { HavePrefix(kcpName + namingTemplateKey), Not(HaveSuffix("00000")), }, - wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"etcd\":{},\"apiServer\":{},\"controllerManager\":{},\"scheduler\":{},\"dns\":{},\"certificatesDir\":\"foo\"}", + wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"certificatesDir\":\"foo\"}", wantErr: false, }, { @@ -608,7 +608,7 @@ func TestKubeadmControlPlaneReconciler_computeDesiredMachine(t *testing.T) { ContainSubstring(fmt.Sprintf("%053d", 0)), Not(HaveSuffix("00000")), }, - wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"etcd\":{},\"apiServer\":{},\"controllerManager\":{},\"scheduler\":{},\"dns\":{},\"certificatesDir\":\"foo\"}", + wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"certificatesDir\":\"foo\"}", wantErr: false, }, { @@ -667,7 +667,7 @@ func TestKubeadmControlPlaneReconciler_computeDesiredMachine(t *testing.T) { HavePrefix(kcpName), Not(HaveSuffix("00000")), }, - wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"etcd\":{},\"apiServer\":{},\"controllerManager\":{},\"scheduler\":{},\"dns\":{},\"certificatesDir\":\"foo\"}", + wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"certificatesDir\":\"foo\"}", }, { name: "should return the correct Machine object when creating a new Machine with additional kcp readinessGates", @@ -693,7 +693,7 @@ func TestKubeadmControlPlaneReconciler_computeDesiredMachine(t *testing.T) { }, }, isUpdatingExistingMachine: false, - wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"etcd\":{},\"apiServer\":{},\"controllerManager\":{},\"scheduler\":{},\"dns\":{},\"certificatesDir\":\"foo\"}", + wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"certificatesDir\":\"foo\"}", wantErr: false, }, { @@ -759,8 +759,8 @@ func TestKubeadmControlPlaneReconciler_computeDesiredMachine(t *testing.T) { }, isUpdatingExistingMachine: true, - existingClusterConfigurationAnnotation: "{\"etcd\":{},\"apiServer\":{\"extraArgs\":{\"foo\":\"bar\"}},\"controllerManager\":{},\"scheduler\":{},\"dns\":{},\"certificatesDir\":\"foo\"}", - wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"etcd\":{},\"apiServer\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"controllerManager\":{},\"scheduler\":{},\"dns\":{},\"certificatesDir\":\"foo\"}", + existingClusterConfigurationAnnotation: "{\"etcd\":{},\"apiServer\":{\"extraArgs\":{\"foo\":\"bar\"}},\"certificatesDir\":\"foo\"}", + wantClusterConfigurationAnnotation: "{\"marshalVersion\":\"v1beta2\",\"apiServer\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"certificatesDir\":\"foo\"}", wantErr: false, }, { diff --git a/controlplane/kubeadm/internal/filters_test.go b/controlplane/kubeadm/internal/filters_test.go index 585fa4602a4c..16c93ac6296f 100644 --- a/controlplane/kubeadm/internal/filters_test.go +++ b/controlplane/kubeadm/internal/filters_test.go @@ -61,7 +61,7 @@ func TestClusterConfigurationAnnotation(t *testing.T) { annotations, err := ClusterConfigurationToMachineAnnotationValue(kcp.Spec.KubeadmConfigSpec.ClusterConfiguration) g.Expect(err).NotTo(HaveOccurred()) - g.Expect(annotations).To(Equal("{\"marshalVersion\":\"v1beta2\",\"etcd\":{},\"apiServer\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"controllerManager\":{},\"scheduler\":{},\"dns\":{},\"certificatesDir\":\"foo\"}")) + g.Expect(annotations).To(Equal("{\"marshalVersion\":\"v1beta2\",\"apiServer\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"certificatesDir\":\"foo\"}")) }) t.Run("ClusterConfigurationFromMachineIsOutdated", func(t *testing.T) { g := NewWithT(t) @@ -294,19 +294,23 @@ func TestMatchClusterConfiguration(t *testing.T) { }, }, }, - ControllerManager: bootstrapv1.ControlPlaneComponent{ - ExtraArgs: []bootstrapv1.Arg{ - { - Name: "foo", - Value: "bar", + ControllerManager: bootstrapv1.ControllerManager{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: []bootstrapv1.Arg{ + { + Name: "foo", + Value: "bar", + }, }, }, }, - Scheduler: bootstrapv1.ControlPlaneComponent{ - ExtraArgs: []bootstrapv1.Arg{ - { - Name: "foo", - Value: "bar", + Scheduler: bootstrapv1.Scheduler{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: []bootstrapv1.Arg{ + { + Name: "foo", + Value: "bar", + }, }, }, }, @@ -324,7 +328,7 @@ func TestMatchClusterConfiguration(t *testing.T) { // This is a point in time snapshot of how a serialized ClusterConfiguration looks like; // we are hardcoding this in the test so we can detect if a change in the API impacts serialization. // NOTE: changes in the json representation do not always trigger a rollout in KCP, but they are an heads up that should be investigated. - annotationsCheckPoint := "{\"marshalVersion\":\"v1beta2\",\"etcd\":{},\"apiServer\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"controllerManager\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"scheduler\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"dns\":{\"imageRepository\":\"gcr.io/capi-test\",\"imageTag\":\"v1.10.1\"}}" + annotationsCheckPoint := "{\"marshalVersion\":\"v1beta2\",\"apiServer\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"controllerManager\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"scheduler\":{\"extraArgs\":[{\"name\":\"foo\",\"value\":\"bar\"}]},\"dns\":{\"imageRepository\":\"gcr.io/capi-test\",\"imageTag\":\"v1.10.1\"}}" // compute how a serialized ClusterConfiguration looks like now annotations, err := ClusterConfigurationToMachineAnnotationValue(kcp.Spec.KubeadmConfigSpec.ClusterConfiguration) @@ -1875,15 +1879,19 @@ func TestOmittableFieldsClusterConfiguration(t *testing.T) { }, CertSANs: []string{}, }, - ControllerManager: bootstrapv1.ControlPlaneComponent{ - ExtraArgs: []bootstrapv1.Arg{}, - ExtraVolumes: []bootstrapv1.HostPathMount{}, - ExtraEnvs: []bootstrapv1.EnvVar{}, + ControllerManager: bootstrapv1.ControllerManager{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: []bootstrapv1.Arg{}, + ExtraVolumes: []bootstrapv1.HostPathMount{}, + ExtraEnvs: []bootstrapv1.EnvVar{}, + }, }, - Scheduler: bootstrapv1.ControlPlaneComponent{ - ExtraArgs: []bootstrapv1.Arg{}, - ExtraVolumes: []bootstrapv1.HostPathMount{}, - ExtraEnvs: []bootstrapv1.EnvVar{}, + Scheduler: bootstrapv1.Scheduler{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: []bootstrapv1.Arg{}, + ExtraVolumes: []bootstrapv1.HostPathMount{}, + ExtraEnvs: []bootstrapv1.EnvVar{}, + }, }, FeatureGates: map[string]bool{}, }, @@ -1909,15 +1917,19 @@ func TestOmittableFieldsClusterConfiguration(t *testing.T) { }, CertSANs: nil, }, - ControllerManager: bootstrapv1.ControlPlaneComponent{ - ExtraArgs: nil, - ExtraVolumes: nil, - ExtraEnvs: nil, + ControllerManager: bootstrapv1.ControllerManager{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: nil, + ExtraVolumes: nil, + ExtraEnvs: nil, + }, }, - Scheduler: bootstrapv1.ControlPlaneComponent{ - ExtraArgs: nil, - ExtraVolumes: nil, - ExtraEnvs: nil, + Scheduler: bootstrapv1.Scheduler{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: nil, + ExtraVolumes: nil, + ExtraEnvs: nil, + }, }, FeatureGates: nil, }, @@ -1953,7 +1965,7 @@ func TestOmittableFieldsInitConfiguration(t *testing.T) { A: &bootstrapv1.InitConfiguration{ BootstrapTokens: []bootstrapv1.BootstrapToken{}, NodeRegistration: bootstrapv1.NodeRegistrationOptions{ - Taints: []corev1.Taint{}, + Taints: ptr.To([]corev1.Taint{}), KubeletExtraArgs: []bootstrapv1.Arg{}, IgnorePreflightErrors: []string{}, }, @@ -1962,7 +1974,7 @@ func TestOmittableFieldsInitConfiguration(t *testing.T) { B: &bootstrapv1.InitConfiguration{ BootstrapTokens: nil, NodeRegistration: bootstrapv1.NodeRegistrationOptions{ - Taints: []corev1.Taint{}, // Special serialization + Taints: ptr.To([]corev1.Taint{}), // Special serialization, i.e. intentionally a pointer to a slice to preserve [] KubeletExtraArgs: nil, IgnorePreflightErrors: nil, }, @@ -2018,7 +2030,7 @@ func TestOmittableFieldsJoinConfiguration(t *testing.T) { name: "Test omittable fields", A: &bootstrapv1.JoinConfiguration{ NodeRegistration: bootstrapv1.NodeRegistrationOptions{ - Taints: []corev1.Taint{}, + Taints: ptr.To([]corev1.Taint{}), KubeletExtraArgs: []bootstrapv1.Arg{}, IgnorePreflightErrors: []string{}, }, @@ -2047,7 +2059,7 @@ func TestOmittableFieldsJoinConfiguration(t *testing.T) { }, B: &bootstrapv1.JoinConfiguration{ NodeRegistration: bootstrapv1.NodeRegistrationOptions{ - Taints: []corev1.Taint{}, + Taints: ptr.To([]corev1.Taint{}), // Special serialization, i.e. intentionally a pointer to a slice to preserve [] KubeletExtraArgs: nil, IgnorePreflightErrors: nil, }, diff --git a/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane.go b/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane.go index fa04e04627e1..0a8d9352715e 100644 --- a/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane.go +++ b/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane.go @@ -163,6 +163,8 @@ func (webhook *KubeadmControlPlane) ValidateUpdate(_ context.Context, oldObj, ne // metadata {"metadata", "*"}, // spec.kubeadmConfigSpec.clusterConfiguration + {spec, kubeadmConfigSpec, clusterConfiguration, "etcd"}, + {spec, kubeadmConfigSpec, clusterConfiguration, "etcd", "*"}, {spec, kubeadmConfigSpec, clusterConfiguration, "etcd", "local"}, {spec, kubeadmConfigSpec, clusterConfiguration, "etcd", "local", "*"}, {spec, kubeadmConfigSpec, clusterConfiguration, "etcd", "external", "*"}, diff --git a/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane_test.go b/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane_test.go index e248b6847fdb..a65cf8ccaa90 100644 --- a/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane_test.go +++ b/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane_test.go @@ -501,25 +501,29 @@ func TestKubeadmControlPlaneValidateUpdate(t *testing.T) { } controllerManager := before.DeepCopy() - controllerManager.Spec.KubeadmConfigSpec.ClusterConfiguration.ControllerManager = bootstrapv1.ControlPlaneComponent{ - ExtraArgs: []bootstrapv1.Arg{ - { - Name: "controller manager field", - Value: "controller manager value", + controllerManager.Spec.KubeadmConfigSpec.ClusterConfiguration.ControllerManager = bootstrapv1.ControllerManager{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: []bootstrapv1.Arg{ + { + Name: "controller manager field", + Value: "controller manager value", + }, }, + ExtraVolumes: []bootstrapv1.HostPathMount{{Name: "mount", HostPath: "/foo", MountPath: "bar", ReadOnly: ptr.To(true), PathType: "File"}}, }, - ExtraVolumes: []bootstrapv1.HostPathMount{{Name: "mount", HostPath: "/foo", MountPath: "bar", ReadOnly: ptr.To(true), PathType: "File"}}, } scheduler := before.DeepCopy() - scheduler.Spec.KubeadmConfigSpec.ClusterConfiguration.Scheduler = bootstrapv1.ControlPlaneComponent{ - ExtraArgs: []bootstrapv1.Arg{ - { - Name: "scheduler field", - Value: "scheduler value", + scheduler.Spec.KubeadmConfigSpec.ClusterConfiguration.Scheduler = bootstrapv1.Scheduler{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: []bootstrapv1.Arg{ + { + Name: "scheduler field", + Value: "scheduler value", + }, }, + ExtraVolumes: []bootstrapv1.HostPathMount{{Name: "mount", HostPath: "/foo", MountPath: "bar", ReadOnly: ptr.To(true), PathType: "File"}}, }, - ExtraVolumes: []bootstrapv1.HostPathMount{{Name: "mount", HostPath: "/foo", MountPath: "bar", ReadOnly: ptr.To(true), PathType: "File"}}, } dns := before.DeepCopy() diff --git a/controlplane/kubeadm/internal/workload_cluster.go b/controlplane/kubeadm/internal/workload_cluster.go index 00c52fee903e..41c408d2d0d2 100644 --- a/controlplane/kubeadm/internal/workload_cluster.go +++ b/controlplane/kubeadm/internal/workload_cluster.go @@ -92,8 +92,8 @@ type WorkloadCluster interface { UpdateEtcdLocalInKubeadmConfigMap(localEtcd *bootstrapv1.LocalEtcd) func(*bootstrapv1.ClusterConfiguration) UpdateEtcdExternalInKubeadmConfigMap(externalEtcd *bootstrapv1.ExternalEtcd) func(*bootstrapv1.ClusterConfiguration) UpdateAPIServerInKubeadmConfigMap(apiServer bootstrapv1.APIServer) func(*bootstrapv1.ClusterConfiguration) - UpdateControllerManagerInKubeadmConfigMap(controllerManager bootstrapv1.ControlPlaneComponent) func(*bootstrapv1.ClusterConfiguration) - UpdateSchedulerInKubeadmConfigMap(scheduler bootstrapv1.ControlPlaneComponent) func(*bootstrapv1.ClusterConfiguration) + UpdateControllerManagerInKubeadmConfigMap(controllerManager bootstrapv1.ControllerManager) func(*bootstrapv1.ClusterConfiguration) + UpdateSchedulerInKubeadmConfigMap(scheduler bootstrapv1.Scheduler) func(*bootstrapv1.ClusterConfiguration) UpdateKubeProxyImageInfo(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane) error UpdateCoreDNS(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane) error RemoveEtcdMemberForMachine(ctx context.Context, machine *clusterv1.Machine) error @@ -206,14 +206,14 @@ func (w *Workload) UpdateAPIServerInKubeadmConfigMap(apiServer bootstrapv1.APISe } // UpdateControllerManagerInKubeadmConfigMap updates controller manager configuration in kubeadm config map. -func (w *Workload) UpdateControllerManagerInKubeadmConfigMap(controllerManager bootstrapv1.ControlPlaneComponent) func(*bootstrapv1.ClusterConfiguration) { +func (w *Workload) UpdateControllerManagerInKubeadmConfigMap(controllerManager bootstrapv1.ControllerManager) func(*bootstrapv1.ClusterConfiguration) { return func(c *bootstrapv1.ClusterConfiguration) { c.ControllerManager = controllerManager } } // UpdateSchedulerInKubeadmConfigMap updates scheduler configuration in kubeadm config map. -func (w *Workload) UpdateSchedulerInKubeadmConfigMap(scheduler bootstrapv1.ControlPlaneComponent) func(*bootstrapv1.ClusterConfiguration) { +func (w *Workload) UpdateSchedulerInKubeadmConfigMap(scheduler bootstrapv1.Scheduler) func(*bootstrapv1.ClusterConfiguration) { return func(c *bootstrapv1.ClusterConfiguration) { c.Scheduler = scheduler } diff --git a/controlplane/kubeadm/internal/workload_cluster_test.go b/controlplane/kubeadm/internal/workload_cluster_test.go index 1f6248cb71dc..d833523586b3 100644 --- a/controlplane/kubeadm/internal/workload_cluster_test.go +++ b/controlplane/kubeadm/internal/workload_cluster_test.go @@ -645,7 +645,7 @@ func TestUpdateControllerManagerInKubeadmConfigMap(t *testing.T) { tests := []struct { name string clusterConfigurationData string - newControllerManager bootstrapv1.ControlPlaneComponent + newControllerManager bootstrapv1.ControllerManager wantClusterConfiguration string }{ { @@ -654,22 +654,24 @@ func TestUpdateControllerManagerInKubeadmConfigMap(t *testing.T) { apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration `), - newControllerManager: bootstrapv1.ControlPlaneComponent{ - ExtraArgs: []bootstrapv1.Arg{ - { - Name: "bar", - Value: "baz", - }, - { - Name: "someKey", - Value: "someVal", + newControllerManager: bootstrapv1.ControllerManager{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: []bootstrapv1.Arg{ + { + Name: "bar", + Value: "baz", + }, + { + Name: "someKey", + Value: "someVal", + }, }, - }, - ExtraVolumes: []bootstrapv1.HostPathMount{ - { - Name: "mount2", - HostPath: "/bar/baz", - MountPath: "/foo/bar", + ExtraVolumes: []bootstrapv1.HostPathMount{ + { + Name: "mount2", + HostPath: "/bar/baz", + MountPath: "/foo/bar", + }, }, }, }, @@ -728,7 +730,7 @@ func TestUpdateSchedulerInKubeadmConfigMap(t *testing.T) { tests := []struct { name string clusterConfigurationData string - newScheduler bootstrapv1.ControlPlaneComponent + newScheduler bootstrapv1.Scheduler wantClusterConfiguration string }{ { @@ -737,22 +739,24 @@ func TestUpdateSchedulerInKubeadmConfigMap(t *testing.T) { apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration `), - newScheduler: bootstrapv1.ControlPlaneComponent{ - ExtraArgs: []bootstrapv1.Arg{ - { - Name: "bar", - Value: "baz", - }, - { - Name: "someKey", - Value: "someVal", + newScheduler: bootstrapv1.Scheduler{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: []bootstrapv1.Arg{ + { + Name: "bar", + Value: "baz", + }, + { + Name: "someKey", + Value: "someVal", + }, }, - }, - ExtraVolumes: []bootstrapv1.HostPathMount{ - { - Name: "mount2", - HostPath: "/bar/baz", - MountPath: "/foo/bar", + ExtraVolumes: []bootstrapv1.HostPathMount{ + { + Name: "mount2", + HostPath: "/bar/baz", + MountPath: "/foo/bar", + }, }, }, }, diff --git a/docs/book/src/developer/providers/contracts/bootstrap-config.md b/docs/book/src/developer/providers/contracts/bootstrap-config.md index 268ec253da60..5eb11085a79d 100644 --- a/docs/book/src/developer/providers/contracts/bootstrap-config.md +++ b/docs/book/src/developer/providers/contracts/bootstrap-config.md @@ -373,7 +373,7 @@ type FooConfigTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` Spec FooConfigSpec `json:"spec"` } ``` diff --git a/docs/book/src/developer/providers/contracts/control-plane.md b/docs/book/src/developer/providers/contracts/control-plane.md index 1f80894053ba..c9c503344116 100644 --- a/docs/book/src/developer/providers/contracts/control-plane.md +++ b/docs/book/src/developer/providers/contracts/control-plane.md @@ -402,7 +402,7 @@ type FooControlPlaneMachineTemplate struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // infrastructureRef is a required reference to a custom infra machine template resource // offered by an infrastructure provider. @@ -663,7 +663,7 @@ type FooControlPlaneTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` Spec FooControlPlaneSpec `json:"spec"` } ``` diff --git a/docs/book/src/developer/providers/contracts/infra-cluster.md b/docs/book/src/developer/providers/contracts/infra-cluster.md index c16eee228a32..1d30c8b97a32 100644 --- a/docs/book/src/developer/providers/contracts/infra-cluster.md +++ b/docs/book/src/developer/providers/contracts/infra-cluster.md @@ -427,7 +427,7 @@ type FooClusterTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` Spec FooClusterSpec `json:"spec"` } ``` diff --git a/docs/book/src/developer/providers/contracts/infra-machine.md b/docs/book/src/developer/providers/contracts/infra-machine.md index 10fe71a6e6e0..6479900e53af 100644 --- a/docs/book/src/developer/providers/contracts/infra-machine.md +++ b/docs/book/src/developer/providers/contracts/infra-machine.md @@ -432,7 +432,7 @@ type FooMachineTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` Spec FooMachineSpec `json:"spec"` } ``` diff --git a/exp/internal/webhooks/machinepool.go b/exp/internal/webhooks/machinepool.go index a335cf6a91ee..824b943dd1ad 100644 --- a/exp/internal/webhooks/machinepool.go +++ b/exp/internal/webhooks/machinepool.go @@ -159,8 +159,8 @@ func (webhook *MachinePool) validate(oldObj, newObj *clusterv1.MachinePool) erro allErrs = append( allErrs, field.Required( - specPath.Child("template", "spec", "bootstrap", "data"), - "expected either spec.bootstrap.dataSecretName or spec.bootstrap.configRef to be populated", + specPath.Child("template", "spec", "bootstrap"), + "expected either spec.template.spec.bootstrap.dataSecretName or spec.template.spec.bootstrap.configRef to be populated", ), ) } diff --git a/exp/topology/desiredstate/desired_state.go b/exp/topology/desiredstate/desired_state.go index 1d0f34af4399..2a5eae7556ce 100644 --- a/exp/topology/desiredstate/desired_state.go +++ b/exp/topology/desiredstate/desired_state.go @@ -189,7 +189,7 @@ func (g *generator) Generate(ctx context.Context, s *scope.Scope) (*scope.Cluste // corresponding template defined in the blueprint. func computeInfrastructureCluster(_ context.Context, s *scope.Scope) (*unstructured.Unstructured, error) { template := s.Blueprint.InfrastructureClusterTemplate - templateClonedFromRef := s.Blueprint.ClusterClass.Spec.Infrastructure.Ref.ToObjectReference(s.Blueprint.ClusterClass.Namespace) + templateClonedFromRef := s.Blueprint.ClusterClass.Spec.Infrastructure.TemplateRef.ToObjectReference(s.Blueprint.ClusterClass.Namespace) cluster := s.Current.Cluster currentRef := cluster.Spec.InfrastructureRef @@ -227,7 +227,7 @@ func computeInfrastructureCluster(_ context.Context, s *scope.Scope) (*unstructu // that should be referenced by the ControlPlane object. func (g *generator) computeControlPlaneInfrastructureMachineTemplate(ctx context.Context, s *scope.Scope) (*unstructured.Unstructured, error) { template := s.Blueprint.ControlPlane.InfrastructureMachineTemplate - templateClonedFromRef := s.Blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref.ToObjectReference(s.Blueprint.ClusterClass.Namespace) + templateClonedFromRef := s.Blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef.ToObjectReference(s.Blueprint.ClusterClass.Namespace) cluster := s.Current.Cluster // Check if the current control plane object has a machineTemplate.infrastructureRef already defined. @@ -272,7 +272,7 @@ func (g *generator) computeControlPlaneInfrastructureMachineTemplate(ctx context // corresponding template defined in the blueprint. func (g *generator) computeControlPlane(ctx context.Context, s *scope.Scope, infrastructureMachineTemplate *unstructured.Unstructured) (*unstructured.Unstructured, error) { template := s.Blueprint.ControlPlane.Template - templateClonedFromRef := s.Blueprint.ClusterClass.Spec.ControlPlane.Ref.ToObjectReference(s.Blueprint.ClusterClass.Namespace) + templateClonedFromRef := s.Blueprint.ClusterClass.Spec.ControlPlane.TemplateRef.ToObjectReference(s.Blueprint.ClusterClass.Namespace) cluster := s.Current.Cluster currentRef := cluster.Spec.ControlPlaneRef diff --git a/exp/topology/desiredstate/desired_state_test.go b/exp/topology/desiredstate/desired_state_test.go index 7c051aef007d..b3c9269ff074 100644 --- a/exp/topology/desiredstate/desired_state_test.go +++ b/exp/topology/desiredstate/desired_state_test.go @@ -122,7 +122,7 @@ func TestComputeInfrastructureCluster(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: scope.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.Infrastructure.Ref, + templateRef: blueprint.ClusterClass.Spec.Infrastructure.TemplateRef, template: blueprint.InfrastructureClusterTemplate, labels: nil, annotations: nil, @@ -150,7 +150,7 @@ func TestComputeInfrastructureCluster(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: scope.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.Infrastructure.Ref, + templateRef: blueprint.ClusterClass.Spec.Infrastructure.TemplateRef, template: blueprint.InfrastructureClusterTemplate, labels: nil, annotations: nil, @@ -230,7 +230,7 @@ func TestComputeControlPlaneInfrastructureMachineTemplate(t *testing.T) { assertTemplateToTemplate(g, assertTemplateInput{ cluster: scope.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef, template: blueprint.ControlPlane.InfrastructureMachineTemplate, currentObjectName: "", obj: obj, @@ -256,7 +256,7 @@ func TestComputeControlPlaneInfrastructureMachineTemplate(t *testing.T) { assertTemplateToTemplate(g, assertTemplateInput{ cluster: scope.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef, template: blueprint.ControlPlane.InfrastructureMachineTemplate, currentObjectName: "", obj: obj, @@ -301,7 +301,7 @@ func TestComputeControlPlaneInfrastructureMachineTemplate(t *testing.T) { assertTemplateToTemplate(g, assertTemplateInput{ cluster: s.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef, template: blueprint.ControlPlane.InfrastructureMachineTemplate, currentObjectName: contract.ObjToRef(currentInfrastructureMachineTemplate).Name, obj: obj, @@ -342,7 +342,7 @@ func TestComputeControlPlaneInfrastructureMachineTemplate(t *testing.T) { assertTemplateToTemplate(g, assertTemplateInput{ cluster: s.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef, template: blueprint.ControlPlane.InfrastructureMachineTemplate, currentObjectName: contract.ObjToRef(currentInfrastructureMachineTemplate).Name, obj: obj, @@ -462,7 +462,7 @@ func TestComputeControlPlane(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: scope.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.TemplateRef, template: blueprint.ControlPlane.Template, currentObjectName: "", obj: obj, @@ -502,7 +502,7 @@ func TestComputeControlPlane(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: scope.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.TemplateRef, template: blueprint.ControlPlane.Template, currentObjectName: "", obj: obj, @@ -636,7 +636,7 @@ func TestComputeControlPlane(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: scope.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.TemplateRef, template: blueprint.ControlPlane.Template, currentObjectName: "", obj: obj, @@ -713,7 +713,7 @@ func TestComputeControlPlane(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: s.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.TemplateRef, template: controlPlaneTemplateWithoutMachineTemplate, currentObjectName: "", obj: obj, @@ -797,7 +797,7 @@ func TestComputeControlPlane(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: s.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.TemplateRef, template: controlPlaneTemplateWithoutMachineTemplate, currentObjectName: "", obj: obj, @@ -848,7 +848,7 @@ func TestComputeControlPlane(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: scope.Current.Cluster, - templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref, + templateRef: blueprint.ClusterClass.Spec.ControlPlane.TemplateRef, template: blueprint.ControlPlane.Template, currentObjectName: scope.Current.Cluster.Spec.ControlPlaneRef.Name, obj: obj, @@ -3054,7 +3054,7 @@ func TestTemplateToObject(t *testing.T) { assertTemplateToObject(g, assertTemplateInput{ cluster: cluster, - templateRef: &clusterv1.ClusterClassTemplateReference{ + templateRef: clusterv1.ClusterClassTemplateReference{ Kind: fakeRef1.Kind, Name: fakeRef1.Name, APIVersion: fakeRef1.APIVersion, @@ -3079,7 +3079,7 @@ func TestTemplateToObject(t *testing.T) { // ObjectMeta assertTemplateToObject(g, assertTemplateInput{ cluster: cluster, - templateRef: &clusterv1.ClusterClassTemplateReference{ + templateRef: clusterv1.ClusterClassTemplateReference{ Kind: fakeRef1.Kind, Name: fakeRef1.Name, APIVersion: fakeRef1.APIVersion, @@ -3122,7 +3122,7 @@ func TestTemplateToTemplate(t *testing.T) { g.Expect(obj).ToNot(BeNil()) assertTemplateToTemplate(g, assertTemplateInput{ cluster: cluster, - templateRef: &clusterv1.ClusterClassTemplateReference{ + templateRef: clusterv1.ClusterClassTemplateReference{ Kind: fakeRef1.Kind, Name: fakeRef1.Name, APIVersion: fakeRef1.APIVersion, @@ -3145,7 +3145,7 @@ func TestTemplateToTemplate(t *testing.T) { g.Expect(obj).ToNot(BeNil()) assertTemplateToTemplate(g, assertTemplateInput{ cluster: cluster, - templateRef: &clusterv1.ClusterClassTemplateReference{ + templateRef: clusterv1.ClusterClassTemplateReference{ Kind: fakeRef1.Kind, Name: fakeRef1.Name, APIVersion: fakeRef1.APIVersion, @@ -3159,7 +3159,7 @@ func TestTemplateToTemplate(t *testing.T) { type assertTemplateInput struct { cluster *clusterv1.Cluster - templateRef *clusterv1.ClusterClassTemplateReference + templateRef clusterv1.ClusterClassTemplateReference template *unstructured.Unstructured labels, annotations map[string]string currentObjectName string diff --git a/exp/topology/scope/blueprint.go b/exp/topology/scope/blueprint.go index 68d5e6fc9c9d..f8e01566ea3e 100644 --- a/exp/topology/scope/blueprint.go +++ b/exp/topology/scope/blueprint.go @@ -93,7 +93,7 @@ type MachinePoolBlueprint struct { // HasControlPlaneInfrastructureMachine checks whether the clusterClass mandates the controlPlane has infrastructureMachines. func (b *ClusterBlueprint) HasControlPlaneInfrastructureMachine() bool { - return b.ClusterClass.Spec.ControlPlane.MachineInfrastructure != nil && b.ClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref != nil + return b.ClusterClass.Spec.ControlPlane.MachineInfrastructure != nil } // IsControlPlaneMachineHealthCheckEnabled returns true if a MachineHealthCheck should be created for the control plane. diff --git a/internal/api/bootstrap/kubeadm/v1alpha3/conversion.go b/internal/api/bootstrap/kubeadm/v1alpha3/conversion.go index 4e070ad74f53..efb691aea7ff 100644 --- a/internal/api/bootstrap/kubeadm/v1alpha3/conversion.go +++ b/internal/api/bootstrap/kubeadm/v1alpha3/conversion.go @@ -399,11 +399,28 @@ func Convert_v1alpha3_BootstrapToken_To_v1beta2_BootstrapToken(in *BootstrapToke return nil } +func Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_ControllerManager(in *ControlPlaneComponent, out *bootstrapv1.ControllerManager, s apimachineryconversion.Scope) error { + return Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + +func Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_Scheduler(in *ControlPlaneComponent, out *bootstrapv1.Scheduler, s apimachineryconversion.Scope) error { + return Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + func Convert_v1beta2_KubeadmConfigSpec_To_v1alpha3_KubeadmConfigSpec(in *bootstrapv1.KubeadmConfigSpec, out *KubeadmConfigSpec, s apimachineryconversion.Scope) error { // KubeadmConfigSpec.Ignition does not exist in kubeadm v1alpha3 API. return autoConvert_v1beta2_KubeadmConfigSpec_To_v1alpha3_KubeadmConfigSpec(in, out, s) } +func Convert_v1beta2_ControllerManager_To_v1alpha3_ControlPlaneComponent(in *bootstrapv1.ControllerManager, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + + return Convert_v1beta2_ControlPlaneComponent_To_v1alpha3_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + +func Convert_v1beta2_Scheduler_To_v1alpha3_ControlPlaneComponent(in *bootstrapv1.Scheduler, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + return Convert_v1beta2_ControlPlaneComponent_To_v1alpha3_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + func Convert_v1beta2_File_To_v1alpha3_File(in *bootstrapv1.File, out *File, s apimachineryconversion.Scope) error { // File.Append does not exist in kubeadm v1alpha3 API. return autoConvert_v1beta2_File_To_v1alpha3_File(in, out, s) diff --git a/internal/api/bootstrap/kubeadm/v1alpha3/conversion_test.go b/internal/api/bootstrap/kubeadm/v1alpha3/conversion_test.go index 923217e9a6ef..3f15ad321325 100644 --- a/internal/api/bootstrap/kubeadm/v1alpha3/conversion_test.go +++ b/internal/api/bootstrap/kubeadm/v1alpha3/conversion_test.go @@ -65,6 +65,7 @@ func KubeadmConfigFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeBootstrapToken, } } @@ -79,6 +80,7 @@ func KubeadmConfigTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []interfac spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeBootstrapToken, } } @@ -102,6 +104,14 @@ func hubKubeadmConfigSpec(in *bootstrapv1.KubeadmConfigSpec, c randfill.Continue } } +func hubNodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, c randfill.Continue) { + c.FillNoCustom(in) + + if in.Taints != nil && *in.Taints == nil { + in.Taints = nil + } +} + func hubKubeadmConfigStatus(in *bootstrapv1.KubeadmConfigStatus, c randfill.Continue) { c.FillNoCustom(in) // Always create struct with at least one mandatory fields. diff --git a/internal/api/bootstrap/kubeadm/v1alpha3/upstream_conversion.go b/internal/api/bootstrap/kubeadm/v1alpha3/upstream_conversion.go index 744397e883dd..9e5553c8beff 100644 --- a/internal/api/bootstrap/kubeadm/v1alpha3/upstream_conversion.go +++ b/internal/api/bootstrap/kubeadm/v1alpha3/upstream_conversion.go @@ -18,6 +18,7 @@ package v1alpha3 import ( apimachineryconversion "k8s.io/apimachinery/pkg/conversion" + "k8s.io/utils/ptr" bootstrapv1 "sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2" clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2" @@ -70,6 +71,11 @@ func Convert_v1alpha3_LocalEtcd_To_v1beta2_LocalEtcd(in *LocalEtcd, out *bootstr func Convert_v1alpha3_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *bootstrapv1.NodeRegistrationOptions, s apimachineryconversion.Scope) error { out.KubeletExtraArgs = bootstrapv1.ConvertToArgs(in.KubeletExtraArgs) + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = ptr.To(in.Taints) + } return autoConvert_v1alpha3_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in, out, s) } @@ -116,6 +122,11 @@ func Convert_v1beta2_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions // Following fields require a custom conversions. // Note: there is a potential info loss when there are two values for the same arg but this is accepted because the kubeadm v1beta1 API does not allow this use case. out.KubeletExtraArgs = bootstrapv1.ConvertFromArgs(in.KubeletExtraArgs) + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = *in.Taints + } return autoConvert_v1beta2_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(in, out, s) } diff --git a/internal/api/bootstrap/kubeadm/v1alpha3/zz_generated.conversion.go b/internal/api/bootstrap/kubeadm/v1alpha3/zz_generated.conversion.go index 3cd96dbc6eca..a9d474f6ed58 100644 --- a/internal/api/bootstrap/kubeadm/v1alpha3/zz_generated.conversion.go +++ b/internal/api/bootstrap/kubeadm/v1alpha3/zz_generated.conversion.go @@ -299,6 +299,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.ControllerManager)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_ControllerManager(a.(*ControlPlaneComponent), b.(*v1beta2.ControllerManager), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.Scheduler)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_Scheduler(a.(*ControlPlaneComponent), b.(*v1beta2.Scheduler), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*DNS)(nil), (*v1beta2.DNS)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha3_DNS_To_v1beta2_DNS(a.(*DNS), b.(*v1beta2.DNS), scope) }); err != nil { @@ -349,6 +359,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.ControllerManager)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ControllerManager_To_v1alpha3_ControlPlaneComponent(a.(*v1beta2.ControllerManager), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.FileDiscovery)(nil), (*FileDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_FileDiscovery_To_v1alpha3_FileDiscovery(a.(*v1beta2.FileDiscovery), b.(*FileDiscovery), scope) }); err != nil { @@ -394,6 +409,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.Scheduler)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Scheduler_To_v1alpha3_ControlPlaneComponent(a.(*v1beta2.Scheduler), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.User)(nil), (*User)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_User_To_v1alpha3_User(a.(*v1beta2.User), b.(*User), scope) }); err != nil { @@ -529,10 +549,10 @@ func autoConvert_v1alpha3_ClusterConfiguration_To_v1beta2_ClusterConfiguration(i if err := Convert_v1alpha3_APIServer_To_v1beta2_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_ControllerManager(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_v1alpha3_ControlPlaneComponent_To_v1beta2_Scheduler(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_v1alpha3_DNS_To_v1beta2_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -554,10 +574,10 @@ func autoConvert_v1beta2_ClusterConfiguration_To_v1alpha3_ClusterConfiguration(i if err := Convert_v1beta2_APIServer_To_v1alpha3_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_v1alpha3_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_v1beta2_ControllerManager_To_v1alpha3_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_v1alpha3_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_v1beta2_Scheduler_To_v1alpha3_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_v1beta2_DNS_To_v1alpha3_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -1480,7 +1500,7 @@ func Convert_v1beta2_NTP_To_v1alpha3_NTP(in *v1beta2.NTP, out *NTP, s conversion func autoConvert_v1alpha3_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *v1beta2.NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types ([]k8s.io/api/core/v1.Taint vs *[]k8s.io/api/core/v1.Taint) // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2.Arg) return nil } @@ -1488,7 +1508,7 @@ func autoConvert_v1alpha3_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOpt func autoConvert_v1beta2_NodeRegistrationOptions_To_v1alpha3_NodeRegistrationOptions(in *v1beta2.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types (*[]k8s.io/api/core/v1.Taint vs []k8s.io/api/core/v1.Taint) // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2.Arg vs map[string]string) // WARNING: in.IgnorePreflightErrors requires manual conversion: does not exist in peer-type // WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type diff --git a/internal/api/bootstrap/kubeadm/v1alpha4/conversion.go b/internal/api/bootstrap/kubeadm/v1alpha4/conversion.go index ae2e3f1223fe..817a91e08e91 100644 --- a/internal/api/bootstrap/kubeadm/v1alpha4/conversion.go +++ b/internal/api/bootstrap/kubeadm/v1alpha4/conversion.go @@ -418,6 +418,11 @@ func Convert_v1beta2_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions // NodeRegistrationOptions.ImagePullPolicy does not exit in kubeadm v1alpha4 API. // Following fields require a custom conversions. out.KubeletExtraArgs = bootstrapv1.ConvertFromArgs(in.KubeletExtraArgs) + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = *in.Taints + } return autoConvert_v1beta2_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions(in, out, s) } @@ -431,6 +436,15 @@ func Convert_v1beta2_FileDiscovery_To_v1alpha4_FileDiscovery(in *bootstrapv1.Fil return autoConvert_v1beta2_FileDiscovery_To_v1alpha4_FileDiscovery(in, out, s) } +func Convert_v1beta2_ControllerManager_To_v1alpha4_ControlPlaneComponent(in *bootstrapv1.ControllerManager, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + + return Convert_v1beta2_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + +func Convert_v1beta2_Scheduler_To_v1alpha4_ControlPlaneComponent(in *bootstrapv1.Scheduler, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + return Convert_v1beta2_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(&in.ControlPlaneComponent, out, s) +} + func Convert_v1beta2_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(in *bootstrapv1.ControlPlaneComponent, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { // ControlPlaneComponent.ExtraEnvs does not exist in v1alpha4 APIs. // Following fields require a custom conversions. @@ -474,6 +488,11 @@ func Convert_v1alpha4_LocalEtcd_To_v1beta2_LocalEtcd(in *LocalEtcd, out *bootstr func Convert_v1alpha4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *bootstrapv1.NodeRegistrationOptions, s apimachineryconversion.Scope) error { out.KubeletExtraArgs = bootstrapv1.ConvertToArgs(in.KubeletExtraArgs) + if in.Taints == nil { + out.Taints = nil + } else { + out.Taints = ptr.To(in.Taints) + } return autoConvert_v1alpha4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in, out, s) } @@ -482,6 +501,14 @@ func Convert_v1alpha4_APIServer_To_v1beta2_APIServer(in *APIServer, out *bootstr return autoConvert_v1alpha4_APIServer_To_v1beta2_APIServer(in, out, s) } +func Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_ControllerManager(in *ControlPlaneComponent, out *bootstrapv1.ControllerManager, s apimachineryconversion.Scope) error { + return Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + +func Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_Scheduler(in *ControlPlaneComponent, out *bootstrapv1.Scheduler, s apimachineryconversion.Scope) error { + return Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(in, &out.ControlPlaneComponent, s) +} + func Convert_v1alpha4_Discovery_To_v1beta2_Discovery(in *Discovery, out *bootstrapv1.Discovery, s apimachineryconversion.Scope) error { // Timeout has been removed in v1beta2 return autoConvert_v1alpha4_Discovery_To_v1beta2_Discovery(in, out, s) diff --git a/internal/api/bootstrap/kubeadm/v1alpha4/conversion_test.go b/internal/api/bootstrap/kubeadm/v1alpha4/conversion_test.go index 6943587c2cdf..db03ea55391b 100644 --- a/internal/api/bootstrap/kubeadm/v1alpha4/conversion_test.go +++ b/internal/api/bootstrap/kubeadm/v1alpha4/conversion_test.go @@ -64,6 +64,7 @@ func KubeadmConfigFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeBootstrapToken, } } @@ -77,6 +78,7 @@ func KubeadmConfigTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []interfac spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeBootstrapToken, } } @@ -100,6 +102,14 @@ func hubKubeadmConfigSpec(in *bootstrapv1.KubeadmConfigSpec, c randfill.Continue } } +func hubNodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, c randfill.Continue) { + c.FillNoCustom(in) + + if in.Taints != nil && *in.Taints == nil { + in.Taints = nil + } +} + func hubKubeadmConfigStatus(in *bootstrapv1.KubeadmConfigStatus, c randfill.Continue) { c.FillNoCustom(in) // Always create struct with at least one mandatory fields. diff --git a/internal/api/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go b/internal/api/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go index b86f42c35ab1..7bf2b602d341 100644 --- a/internal/api/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go +++ b/internal/api/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go @@ -304,6 +304,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.ControllerManager)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_ControllerManager(a.(*ControlPlaneComponent), b.(*v1beta2.ControllerManager), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*ControlPlaneComponent)(nil), (*v1beta2.Scheduler)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_Scheduler(a.(*ControlPlaneComponent), b.(*v1beta2.Scheduler), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*Discovery)(nil), (*v1beta2.Discovery)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha4_Discovery_To_v1beta2_Discovery(a.(*Discovery), b.(*v1beta2.Discovery), scope) }); err != nil { @@ -349,6 +359,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.ControllerManager)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ControllerManager_To_v1alpha4_ControlPlaneComponent(a.(*v1beta2.ControllerManager), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.FileDiscovery)(nil), (*FileDiscovery)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_FileDiscovery_To_v1alpha4_FileDiscovery(a.(*v1beta2.FileDiscovery), b.(*FileDiscovery), scope) }); err != nil { @@ -394,6 +409,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.Scheduler)(nil), (*ControlPlaneComponent)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_Scheduler_To_v1alpha4_ControlPlaneComponent(a.(*v1beta2.Scheduler), b.(*ControlPlaneComponent), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.User)(nil), (*User)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_User_To_v1alpha4_User(a.(*v1beta2.User), b.(*User), scope) }); err != nil { @@ -529,10 +549,10 @@ func autoConvert_v1alpha4_ClusterConfiguration_To_v1beta2_ClusterConfiguration(i if err := Convert_v1alpha4_APIServer_To_v1beta2_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_ControllerManager(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_v1alpha4_ControlPlaneComponent_To_v1beta2_Scheduler(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_v1alpha4_DNS_To_v1beta2_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -553,10 +573,10 @@ func autoConvert_v1beta2_ClusterConfiguration_To_v1alpha4_ClusterConfiguration(i if err := Convert_v1beta2_APIServer_To_v1alpha4_APIServer(&in.APIServer, &out.APIServer, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { + if err := Convert_v1beta2_ControllerManager_To_v1alpha4_ControlPlaneComponent(&in.ControllerManager, &out.ControllerManager, s); err != nil { return err } - if err := Convert_v1beta2_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { + if err := Convert_v1beta2_Scheduler_To_v1alpha4_ControlPlaneComponent(&in.Scheduler, &out.Scheduler, s); err != nil { return err } if err := Convert_v1beta2_DNS_To_v1alpha4_DNS(&in.DNS, &out.DNS, s); err != nil { @@ -1482,7 +1502,7 @@ func Convert_v1beta2_NTP_To_v1alpha4_NTP(in *v1beta2.NTP, out *NTP, s conversion func autoConvert_v1alpha4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOptions(in *NodeRegistrationOptions, out *v1beta2.NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types ([]k8s.io/api/core/v1.Taint vs *[]k8s.io/api/core/v1.Taint) // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2.Arg) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) return nil @@ -1491,7 +1511,7 @@ func autoConvert_v1alpha4_NodeRegistrationOptions_To_v1beta2_NodeRegistrationOpt func autoConvert_v1beta2_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOptions(in *v1beta2.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { out.Name = in.Name out.CRISocket = in.CRISocket - out.Taints = *(*[]corev1.Taint)(unsafe.Pointer(&in.Taints)) + // WARNING: in.Taints requires manual conversion: inconvertible types (*[]k8s.io/api/core/v1.Taint vs []k8s.io/api/core/v1.Taint) // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api/api/bootstrap/kubeadm/v1beta2.Arg vs map[string]string) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) // WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type diff --git a/internal/api/controlplane/kubeadm/v1alpha3/conversion_test.go b/internal/api/controlplane/kubeadm/v1alpha3/conversion_test.go index 79edf651014d..d61fbb232d2d 100644 --- a/internal/api/controlplane/kubeadm/v1alpha3/conversion_test.go +++ b/internal/api/controlplane/kubeadm/v1alpha3/conversion_test.go @@ -78,6 +78,7 @@ func KubeadmControlPlaneFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{ spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeBootstrapToken, } } @@ -101,6 +102,14 @@ func hubKubeadmConfigSpec(in *bootstrapv1.KubeadmConfigSpec, c randfill.Continue } } +func hubNodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, c randfill.Continue) { + c.FillNoCustom(in) + + if in.Taints != nil && *in.Taints == nil { + in.Taints = nil + } +} + func hubKubeadmControlPlaneStatus(in *controlplanev1.KubeadmControlPlaneStatus, c randfill.Continue) { c.FillNoCustom(in) // Always create struct with at least one mandatory fields. diff --git a/internal/api/controlplane/kubeadm/v1alpha4/conversion_test.go b/internal/api/controlplane/kubeadm/v1alpha4/conversion_test.go index 20ae6cbab84d..62f58230ae7c 100644 --- a/internal/api/controlplane/kubeadm/v1alpha4/conversion_test.go +++ b/internal/api/controlplane/kubeadm/v1alpha4/conversion_test.go @@ -87,6 +87,7 @@ func KubeadmControlPlaneFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{ spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeBootstrapToken, } } @@ -102,6 +103,7 @@ func KubeadmControlPlaneTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []in spokeAPIServer, spokeDiscovery, hubKubeadmConfigSpec, + hubNodeRegistrationOptions, spokeBootstrapToken, } } @@ -125,6 +127,14 @@ func hubKubeadmConfigSpec(in *bootstrapv1.KubeadmConfigSpec, c randfill.Continue } } +func hubNodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, c randfill.Continue) { + c.FillNoCustom(in) + + if in.Taints != nil && *in.Taints == nil { + in.Taints = nil + } +} + func hubKubeadmControlPlaneStatus(in *controlplanev1.KubeadmControlPlaneStatus, c randfill.Continue) { c.FillNoCustom(in) // Always create struct with at least one mandatory fields. diff --git a/internal/api/core/v1alpha4/conversion.go b/internal/api/core/v1alpha4/conversion.go index 340890a558ea..8b4623b1b9db 100644 --- a/internal/api/core/v1alpha4/conversion.go +++ b/internal/api/core/v1alpha4/conversion.go @@ -785,7 +785,8 @@ func Convert_v1alpha4_ControlPlaneClass_To_v1beta2_ControlPlaneClass(in *Control return err } - return Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(&in.LocalObjectTemplate, &out.ClusterClassTemplate, s) + convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(&in.LocalObjectTemplate, &out.TemplateRef, s) + return nil } func Convert_v1beta2_InfrastructureClass_To_v1alpha4_LocalObjectTemplate(in *clusterv1.InfrastructureClass, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { @@ -793,7 +794,8 @@ func Convert_v1beta2_InfrastructureClass_To_v1alpha4_LocalObjectTemplate(in *clu return nil } - return Convert_v1beta2_ClusterClassTemplate_To_v1alpha4_LocalObjectTemplate(&in.ClusterClassTemplate, out, s) + Convert_v1beta2_ClusterClassTemplateReference_To_v1alpha4_LocalObjectTemplate(&in.TemplateRef, out, s) + return nil } func Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_InfrastructureClass(in *LocalObjectTemplate, out *clusterv1.InfrastructureClass, s apimachineryconversion.Scope) error { @@ -801,7 +803,8 @@ func Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_InfrastructureClass(in *Loc return nil } - return Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(in, &out.ClusterClassTemplate, s) + convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil } func Convert_v1beta2_MachineSpec_To_v1alpha4_MachineSpec(in *clusterv1.MachineSpec, out *MachineSpec, s apimachineryconversion.Scope) error { @@ -869,7 +872,8 @@ func Convert_v1beta2_ControlPlaneClass_To_v1alpha4_ControlPlaneClass(in *cluster return err } - return Convert_v1beta2_ClusterClassTemplate_To_v1alpha4_LocalObjectTemplate(&in.ClusterClassTemplate, &out.LocalObjectTemplate, s) + Convert_v1beta2_ClusterClassTemplateReference_To_v1alpha4_LocalObjectTemplate(&in.TemplateRef, &out.LocalObjectTemplate, s) + return nil } func Convert_v1alpha4_Topology_To_v1beta2_Topology(in *Topology, out *clusterv1.Topology, s apimachineryconversion.Scope) error { @@ -1065,30 +1069,58 @@ func Convert_v1alpha4_MachineSpec_To_v1beta2_MachineSpec(in *MachineSpec, out *c return nil } -func Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(in *LocalObjectTemplate, out *clusterv1.ClusterClassTemplate, _ apimachineryconversion.Scope) error { - if in.Ref == nil { - return nil +func Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ControlPlaneClassMachineInfrastructureTemplate(in *LocalObjectTemplate, out *clusterv1.ControlPlaneClassMachineInfrastructureTemplate, s apimachineryconversion.Scope) error { + convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil +} + +func Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassBootstrapTemplate(in *LocalObjectTemplate, out *clusterv1.MachineDeploymentClassBootstrapTemplate, s apimachineryconversion.Scope) error { + convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil +} + +func Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassInfrastructureTemplate(in *LocalObjectTemplate, out *clusterv1.MachineDeploymentClassInfrastructureTemplate, s apimachineryconversion.Scope) error { + convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in, &out.TemplateRef, s) + return nil +} + +func convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplateReference(in *LocalObjectTemplate, out *clusterv1.ClusterClassTemplateReference, _ apimachineryconversion.Scope) { + if in == nil || in.Ref == nil { + return } - out.Ref = &clusterv1.ClusterClassTemplateReference{ + *out = clusterv1.ClusterClassTemplateReference{ Kind: in.Ref.Kind, Name: in.Ref.Name, APIVersion: in.Ref.APIVersion, } +} + +func Convert_v1beta2_ControlPlaneClassMachineInfrastructureTemplate_To_v1alpha4_LocalObjectTemplate(in *clusterv1.ControlPlaneClassMachineInfrastructureTemplate, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { + Convert_v1beta2_ClusterClassTemplateReference_To_v1alpha4_LocalObjectTemplate(&in.TemplateRef, out, s) return nil } -func Convert_v1beta2_ClusterClassTemplate_To_v1alpha4_LocalObjectTemplate(in *clusterv1.ClusterClassTemplate, out *LocalObjectTemplate, _ apimachineryconversion.Scope) error { - if in.Ref == nil { - return nil +func Convert_v1beta2_MachineDeploymentClassBootstrapTemplate_To_v1alpha4_LocalObjectTemplate(in *clusterv1.MachineDeploymentClassBootstrapTemplate, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { + Convert_v1beta2_ClusterClassTemplateReference_To_v1alpha4_LocalObjectTemplate(&in.TemplateRef, out, s) + return nil +} + +func Convert_v1beta2_MachineDeploymentClassInfrastructureTemplate_To_v1alpha4_LocalObjectTemplate(in *clusterv1.MachineDeploymentClassInfrastructureTemplate, out *LocalObjectTemplate, s apimachineryconversion.Scope) error { + Convert_v1beta2_ClusterClassTemplateReference_To_v1alpha4_LocalObjectTemplate(&in.TemplateRef, out, s) + return nil +} + +func Convert_v1beta2_ClusterClassTemplateReference_To_v1alpha4_LocalObjectTemplate(in *clusterv1.ClusterClassTemplateReference, out *LocalObjectTemplate, _ apimachineryconversion.Scope) { + if in == nil { + return } out.Ref = &corev1.ObjectReference{ - Kind: in.Ref.Kind, - Name: in.Ref.Name, - APIVersion: in.Ref.APIVersion, + Kind: in.Kind, + Name: in.Name, + APIVersion: in.APIVersion, } - return nil } // Implement local conversion func because conversion-gen is not aware of conversion func in other packages (see https://github.com/kubernetes/code-generator/issues/94) diff --git a/internal/api/core/v1alpha4/conversion_test.go b/internal/api/core/v1alpha4/conversion_test.go index 2d2dba931f5c..8b43e68c5744 100644 --- a/internal/api/core/v1alpha4/conversion_test.go +++ b/internal/api/core/v1alpha4/conversion_test.go @@ -365,6 +365,12 @@ func spokeLocalObjectTemplate(in *LocalObjectTemplate, c randfill.Continue) { c.FillNoCustom(in) if in.Ref == nil { + in.Ref = &corev1.ObjectReference{ + APIVersion: "fooAPIVersion", + Kind: "fooKind", + Name: "fooName", + Namespace: "foo", + } return } diff --git a/internal/api/core/v1alpha4/zz_generated.conversion.go b/internal/api/core/v1alpha4/zz_generated.conversion.go index 087edcd7fedd..284f5befdec1 100644 --- a/internal/api/core/v1alpha4/zz_generated.conversion.go +++ b/internal/api/core/v1alpha4/zz_generated.conversion.go @@ -345,8 +345,8 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.ClusterClassTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.ClusterClassTemplate), scope) + if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.ControlPlaneClassMachineInfrastructureTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ControlPlaneClassMachineInfrastructureTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.ControlPlaneClassMachineInfrastructureTemplate), scope) }); err != nil { return err } @@ -355,6 +355,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.MachineDeploymentClassBootstrapTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassBootstrapTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.MachineDeploymentClassBootstrapTemplate), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*LocalObjectTemplate)(nil), (*v1beta2.MachineDeploymentClassInfrastructureTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassInfrastructureTemplate(a.(*LocalObjectTemplate), b.(*v1beta2.MachineDeploymentClassInfrastructureTemplate), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*MachineDeploymentSpec)(nil), (*v1beta2.MachineDeploymentSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha4_MachineDeploymentSpec_To_v1beta2_MachineDeploymentSpec(a.(*MachineDeploymentSpec), b.(*v1beta2.MachineDeploymentSpec), scope) }); err != nil { @@ -410,11 +420,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddConversionFunc((*v1beta2.ClusterClassTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta2_ClusterClassTemplate_To_v1alpha4_LocalObjectTemplate(a.(*v1beta2.ClusterClassTemplate), b.(*LocalObjectTemplate), scope) - }); err != nil { - return err - } if err := s.AddConversionFunc((*v1beta2.ClusterClass)(nil), (*ClusterClass)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_ClusterClass_To_v1alpha4_ClusterClass(a.(*v1beta2.ClusterClass), b.(*ClusterClass), scope) }); err != nil { @@ -430,6 +435,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.ControlPlaneClassMachineInfrastructureTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_ControlPlaneClassMachineInfrastructureTemplate_To_v1alpha4_LocalObjectTemplate(a.(*v1beta2.ControlPlaneClassMachineInfrastructureTemplate), b.(*LocalObjectTemplate), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.ControlPlaneClass)(nil), (*ControlPlaneClass)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_ControlPlaneClass_To_v1alpha4_ControlPlaneClass(a.(*v1beta2.ControlPlaneClass), b.(*ControlPlaneClass), scope) }); err != nil { @@ -445,6 +455,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*v1beta2.MachineDeploymentClassBootstrapTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_MachineDeploymentClassBootstrapTemplate_To_v1alpha4_LocalObjectTemplate(a.(*v1beta2.MachineDeploymentClassBootstrapTemplate), b.(*LocalObjectTemplate), scope) + }); err != nil { + return err + } + if err := s.AddConversionFunc((*v1beta2.MachineDeploymentClassInfrastructureTemplate)(nil), (*LocalObjectTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta2_MachineDeploymentClassInfrastructureTemplate_To_v1alpha4_LocalObjectTemplate(a.(*v1beta2.MachineDeploymentClassInfrastructureTemplate), b.(*LocalObjectTemplate), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*v1beta2.MachineDeploymentClass)(nil), (*MachineDeploymentClass)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_MachineDeploymentClass_To_v1alpha4_MachineDeploymentClass(a.(*v1beta2.MachineDeploymentClass), b.(*MachineDeploymentClass), scope) }); err != nil { @@ -944,8 +964,8 @@ func autoConvert_v1alpha4_ControlPlaneClass_To_v1beta2_ControlPlaneClass(in *Con // WARNING: in.LocalObjectTemplate requires manual conversion: does not exist in peer-type if in.MachineInfrastructure != nil { in, out := &in.MachineInfrastructure, &out.MachineInfrastructure - *out = new(v1beta2.ClusterClassTemplate) - if err := Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(*in, *out, s); err != nil { + *out = new(v1beta2.ControlPlaneClassMachineInfrastructureTemplate) + if err := Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ControlPlaneClassMachineInfrastructureTemplate(*in, *out, s); err != nil { return err } } else { @@ -958,11 +978,11 @@ func autoConvert_v1beta2_ControlPlaneClass_To_v1alpha4_ControlPlaneClass(in *v1b if err := Convert_v1beta2_ObjectMeta_To_v1alpha4_ObjectMeta(&in.Metadata, &out.Metadata, s); err != nil { return err } - // WARNING: in.ClusterClassTemplate requires manual conversion: does not exist in peer-type + // WARNING: in.TemplateRef requires manual conversion: does not exist in peer-type if in.MachineInfrastructure != nil { in, out := &in.MachineInfrastructure, &out.MachineInfrastructure *out = new(LocalObjectTemplate) - if err := Convert_v1beta2_ClusterClassTemplate_To_v1alpha4_LocalObjectTemplate(*in, *out, s); err != nil { + if err := Convert_v1beta2_ControlPlaneClassMachineInfrastructureTemplate_To_v1alpha4_LocalObjectTemplate(*in, *out, s); err != nil { return err } } else { @@ -1124,10 +1144,10 @@ func autoConvert_v1alpha4_MachineDeploymentClassTemplate_To_v1beta2_MachineDeplo if err := Convert_v1alpha4_ObjectMeta_To_v1beta2_ObjectMeta(&in.Metadata, &out.Metadata, s); err != nil { return err } - if err := Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { + if err := Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassBootstrapTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { return err } - if err := Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_ClusterClassTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { + if err := Convert_v1alpha4_LocalObjectTemplate_To_v1beta2_MachineDeploymentClassInfrastructureTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { return err } return nil @@ -1142,10 +1162,10 @@ func autoConvert_v1beta2_MachineDeploymentClassTemplate_To_v1alpha4_MachineDeplo if err := Convert_v1beta2_ObjectMeta_To_v1alpha4_ObjectMeta(&in.Metadata, &out.Metadata, s); err != nil { return err } - if err := Convert_v1beta2_ClusterClassTemplate_To_v1alpha4_LocalObjectTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { + if err := Convert_v1beta2_MachineDeploymentClassBootstrapTemplate_To_v1alpha4_LocalObjectTemplate(&in.Bootstrap, &out.Bootstrap, s); err != nil { return err } - if err := Convert_v1beta2_ClusterClassTemplate_To_v1alpha4_LocalObjectTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { + if err := Convert_v1beta2_MachineDeploymentClassInfrastructureTemplate_To_v1alpha4_LocalObjectTemplate(&in.Infrastructure, &out.Infrastructure, s); err != nil { return err } return nil diff --git a/internal/controllers/clusterclass/clusterclass_controller.go b/internal/controllers/clusterclass/clusterclass_controller.go index 4e39fd9cba94..058932e025e2 100644 --- a/internal/controllers/clusterclass/clusterclass_controller.go +++ b/internal/controllers/clusterclass/clusterclass_controller.go @@ -214,35 +214,18 @@ func (r *Reconciler) reconcileExternalReferences(ctx context.Context, s *scope) clusterClass := s.clusterClass // Collect all the reference from the ClusterClass to templates. - refs := []*clusterv1.ClusterClassTemplateReference{} - - if clusterClass.Spec.Infrastructure.Ref != nil { - refs = append(refs, clusterClass.Spec.Infrastructure.Ref) - } - - if clusterClass.Spec.ControlPlane.Ref != nil { - refs = append(refs, clusterClass.Spec.ControlPlane.Ref) + refs := []clusterv1.ClusterClassTemplateReference{ + clusterClass.Spec.Infrastructure.TemplateRef, + clusterClass.Spec.ControlPlane.TemplateRef, } - if clusterClass.Spec.ControlPlane.MachineInfrastructure != nil && clusterClass.Spec.ControlPlane.MachineInfrastructure.Ref != nil { - refs = append(refs, clusterClass.Spec.ControlPlane.MachineInfrastructure.Ref) + if clusterClass.Spec.ControlPlane.MachineInfrastructure != nil { + refs = append(refs, clusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef) } - for _, mdClass := range clusterClass.Spec.Workers.MachineDeployments { - if mdClass.Template.Bootstrap.Ref != nil { - refs = append(refs, mdClass.Template.Bootstrap.Ref) - } - if mdClass.Template.Infrastructure.Ref != nil { - refs = append(refs, mdClass.Template.Infrastructure.Ref) - } + refs = append(refs, mdClass.Template.Bootstrap.TemplateRef, mdClass.Template.Infrastructure.TemplateRef) } - for _, mpClass := range clusterClass.Spec.Workers.MachinePools { - if mpClass.Template.Bootstrap.Ref != nil { - refs = append(refs, mpClass.Template.Bootstrap.Ref) - } - if mpClass.Template.Infrastructure.Ref != nil { - refs = append(refs, mpClass.Template.Infrastructure.Ref) - } + refs = append(refs, mpClass.Template.Bootstrap.TemplateRef, mpClass.Template.Infrastructure.TemplateRef) } // Ensure all referenced objects are owned by the ClusterClass. @@ -254,6 +237,11 @@ func (r *Reconciler) reconcileExternalReferences(ctx context.Context, s *scope) reconciledRefs := sets.Set[string]{} outdatedRefs := []outdatedRef{} for i := range refs { + // Skip empty refs. + if reflect.DeepEqual(refs[i], clusterv1.ClusterClassTemplateReference{}) { + continue + } + ref := refs[i].ToObjectReference(s.clusterClass.Namespace) uniqueKey := uniqueObjectRefKey(ref) diff --git a/internal/controllers/clusterclass/clusterclass_controller_status.go b/internal/controllers/clusterclass/clusterclass_controller_status.go index 3436b3dd723a..212ea101a095 100644 --- a/internal/controllers/clusterclass/clusterclass_controller_status.go +++ b/internal/controllers/clusterclass/clusterclass_controller_status.go @@ -52,7 +52,7 @@ func setRefVersionsUpToDateCondition(_ context.Context, clusterClass *clusterv1. if len(outdatedRefs) > 0 { var msg []string for _, outdatedRef := range outdatedRefs { - msg = append(msg, fmt.Sprintf("* Ref %q should be %q", refString(outdatedRef.Outdated), refString(outdatedRef.UpToDate))) + msg = append(msg, fmt.Sprintf("* templateRef %q should be %q", refString(outdatedRef.Outdated), refString(outdatedRef.UpToDate))) } v1beta1conditions.Set(clusterClass, v1beta1conditions.FalseCondition( diff --git a/internal/controllers/clusterclass/clusterclass_controller_status_test.go b/internal/controllers/clusterclass/clusterclass_controller_status_test.go index 7ca6a3a2c908..98a34ca1d4ef 100644 --- a/internal/controllers/clusterclass/clusterclass_controller_status_test.go +++ b/internal/controllers/clusterclass/clusterclass_controller_status_test.go @@ -81,9 +81,9 @@ func TestSetRefVersionsUpToDateCondition(t *testing.T) { Type: clusterv1.ClusterClassRefVersionsUpToDateCondition, Status: metav1.ConditionFalse, Reason: clusterv1.ClusterClassRefVersionsNotUpToDateReason, - Message: "* Ref \"controlplane.cluster.x-k8s.io/v1beta2, Kind=KubeadmControlPlaneTemplate default/test-kcp\" should be " + + Message: "* templateRef \"controlplane.cluster.x-k8s.io/v1beta2, Kind=KubeadmControlPlaneTemplate default/test-kcp\" should be " + "\"controlplane.cluster.x-k8s.io/v99, Kind=KubeadmControlPlaneTemplate default/test-kcp\"\n" + - "* Ref \"infrastructure.cluster.x-k8s.io/v1beta2, Kind=DockerMachineTemplate default/test-dmt\" should be " + + "* templateRef \"infrastructure.cluster.x-k8s.io/v1beta2, Kind=DockerMachineTemplate default/test-dmt\" should be " + "\"infrastructure.cluster.x-k8s.io/v99, Kind=DockerMachineTemplate default/test-dmt\"", }, }, diff --git a/internal/controllers/clusterclass/clusterclass_controller_test.go b/internal/controllers/clusterclass/clusterclass_controller_test.go index bda9c261491a..ddc904ec03e1 100644 --- a/internal/controllers/clusterclass/clusterclass_controller_test.go +++ b/internal/controllers/clusterclass/clusterclass_controller_test.go @@ -220,7 +220,7 @@ func assertInfrastructureClusterTemplate(ctx context.Context, actualClusterClass actualInfraClusterTemplate := builder.InfrastructureClusterTemplate("", "").Build() actualInfraClusterTemplateKey := client.ObjectKey{ Namespace: ns.Name, - Name: actualClusterClass.Spec.Infrastructure.Ref.Name, + Name: actualClusterClass.Spec.Infrastructure.TemplateRef.Name, } if err := env.Get(ctx, actualInfraClusterTemplateKey, actualInfraClusterTemplate); err != nil { return err @@ -230,7 +230,7 @@ func assertInfrastructureClusterTemplate(ctx context.Context, actualClusterClass } // Assert the ClusterClass has the expected APIVersion and Kind of to the infrastructure cluster template - return referenceExistsWithCorrectKindAndAPIVersion(actualClusterClass.Spec.Infrastructure.Ref, + return referenceExistsWithCorrectKindAndAPIVersion(actualClusterClass.Spec.Infrastructure.TemplateRef, builder.GenericInfrastructureClusterTemplateKind, builder.InfrastructureGroupVersion) } @@ -240,7 +240,7 @@ func assertControlPlaneTemplate(ctx context.Context, actualClusterClass *cluster actualControlPlaneTemplate := builder.ControlPlaneTemplate("", "").Build() actualControlPlaneTemplateKey := client.ObjectKey{ Namespace: ns.Name, - Name: actualClusterClass.Spec.ControlPlane.Ref.Name, + Name: actualClusterClass.Spec.ControlPlane.TemplateRef.Name, } if err := env.Get(ctx, actualControlPlaneTemplateKey, actualControlPlaneTemplate); err != nil { return err @@ -250,18 +250,18 @@ func assertControlPlaneTemplate(ctx context.Context, actualClusterClass *cluster } // Assert the ClusterClass has the expected APIVersion and Kind to the control plane template - if err := referenceExistsWithCorrectKindAndAPIVersion(actualClusterClass.Spec.ControlPlane.Ref, + if err := referenceExistsWithCorrectKindAndAPIVersion(actualClusterClass.Spec.ControlPlane.TemplateRef, builder.GenericControlPlaneTemplateKind, builder.ControlPlaneGroupVersion); err != nil { return err } // If the control plane has machine infra assert that the infra machine template has the correct owner reference. - if actualClusterClass.Spec.ControlPlane.MachineInfrastructure != nil && actualClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref != nil { + if actualClusterClass.Spec.ControlPlane.MachineInfrastructure != nil { actualInfrastructureMachineTemplate := builder.InfrastructureMachineTemplate("", "").Build() actualInfrastructureMachineTemplateKey := client.ObjectKey{ Namespace: ns.Name, - Name: actualClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref.Name, + Name: actualClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef.Name, } if err := env.Get(ctx, actualInfrastructureMachineTemplateKey, actualInfrastructureMachineTemplate); err != nil { return err @@ -271,7 +271,7 @@ func assertControlPlaneTemplate(ctx context.Context, actualClusterClass *cluster } // Assert the ClusterClass has the expected APIVersion and Kind to the infrastructure machine template - if err := referenceExistsWithCorrectKindAndAPIVersion(actualClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref, + if err := referenceExistsWithCorrectKindAndAPIVersion(actualClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef, builder.GenericInfrastructureMachineTemplateKind, builder.InfrastructureGroupVersion); err != nil { return err @@ -295,7 +295,7 @@ func assertMachineDeploymentClass(ctx context.Context, actualClusterClass *clust actualInfrastructureMachineTemplate := builder.InfrastructureMachineTemplate("", "").Build() actualInfrastructureMachineTemplateKey := client.ObjectKey{ Namespace: ns.Name, - Name: mdClass.Template.Infrastructure.Ref.Name, + Name: mdClass.Template.Infrastructure.TemplateRef.Name, } if err := env.Get(ctx, actualInfrastructureMachineTemplateKey, actualInfrastructureMachineTemplate); err != nil { return err @@ -305,7 +305,7 @@ func assertMachineDeploymentClass(ctx context.Context, actualClusterClass *clust } // Assert the MachineDeploymentClass has the expected APIVersion and Kind to the infrastructure machine template - if err := referenceExistsWithCorrectKindAndAPIVersion(mdClass.Template.Infrastructure.Ref, + if err := referenceExistsWithCorrectKindAndAPIVersion(mdClass.Template.Infrastructure.TemplateRef, builder.GenericInfrastructureMachineTemplateKind, builder.InfrastructureGroupVersion); err != nil { return err @@ -315,7 +315,7 @@ func assertMachineDeploymentClass(ctx context.Context, actualClusterClass *clust actualBootstrapTemplate := builder.BootstrapTemplate("", "").Build() actualBootstrapTemplateKey := client.ObjectKey{ Namespace: ns.Name, - Name: mdClass.Template.Bootstrap.Ref.Name, + Name: mdClass.Template.Bootstrap.TemplateRef.Name, } if err := env.Get(ctx, actualBootstrapTemplateKey, actualBootstrapTemplate); err != nil { return err @@ -325,7 +325,7 @@ func assertMachineDeploymentClass(ctx context.Context, actualClusterClass *clust } // Assert the MachineDeploymentClass has the expected APIVersion and Kind to the bootstrap template - return referenceExistsWithCorrectKindAndAPIVersion(mdClass.Template.Bootstrap.Ref, + return referenceExistsWithCorrectKindAndAPIVersion(mdClass.Template.Bootstrap.TemplateRef, builder.GenericBootstrapConfigTemplateKind, builder.BootstrapGroupVersion) } @@ -344,7 +344,7 @@ func assertMachinePoolClass(ctx context.Context, actualClusterClass *clusterv1.C actualInfrastructureMachinePoolTemplate := builder.InfrastructureMachinePoolTemplate("", "").Build() actualInfrastructureMachinePoolTemplateKey := client.ObjectKey{ Namespace: ns.Name, - Name: mpClass.Template.Infrastructure.Ref.Name, + Name: mpClass.Template.Infrastructure.TemplateRef.Name, } if err := env.Get(ctx, actualInfrastructureMachinePoolTemplateKey, actualInfrastructureMachinePoolTemplate); err != nil { return err @@ -354,7 +354,7 @@ func assertMachinePoolClass(ctx context.Context, actualClusterClass *clusterv1.C } // Assert the MachinePoolClass has the expected APIVersion and Kind to the infrastructure machinepool template - if err := referenceExistsWithCorrectKindAndAPIVersion(mpClass.Template.Infrastructure.Ref, + if err := referenceExistsWithCorrectKindAndAPIVersion(mpClass.Template.Infrastructure.TemplateRef, builder.GenericInfrastructureMachinePoolTemplateKind, builder.InfrastructureGroupVersion); err != nil { return err @@ -364,7 +364,7 @@ func assertMachinePoolClass(ctx context.Context, actualClusterClass *clusterv1.C actualBootstrapTemplate := builder.BootstrapTemplate("", "").Build() actualBootstrapTemplateKey := client.ObjectKey{ Namespace: ns.Name, - Name: mpClass.Template.Bootstrap.Ref.Name, + Name: mpClass.Template.Bootstrap.TemplateRef.Name, } if err := env.Get(ctx, actualBootstrapTemplateKey, actualBootstrapTemplate); err != nil { return err @@ -374,7 +374,7 @@ func assertMachinePoolClass(ctx context.Context, actualClusterClass *clusterv1.C } // Assert the MachinePoolClass has the expected APIVersion and Kind to the bootstrap template - return referenceExistsWithCorrectKindAndAPIVersion(mpClass.Template.Bootstrap.Ref, + return referenceExistsWithCorrectKindAndAPIVersion(mpClass.Template.Bootstrap.TemplateRef, builder.GenericBootstrapConfigTemplateKind, builder.BootstrapGroupVersion) } diff --git a/internal/controllers/clusterclass/suite_test.go b/internal/controllers/clusterclass/suite_test.go index 54045a52ac02..d01f4f7a58f6 100644 --- a/internal/controllers/clusterclass/suite_test.go +++ b/internal/controllers/clusterclass/suite_test.go @@ -113,10 +113,7 @@ func ownerReferenceTo(obj client.Object, gvk schema.GroupVersionKind) *metav1.Ow } // referenceExistsWithCorrectKindAndAPIVersion asserts that the passed ClusterClassTemplateReference is not nil and that it has the correct kind and apiVersion. -func referenceExistsWithCorrectKindAndAPIVersion(reference *clusterv1.ClusterClassTemplateReference, kind string, apiVersion schema.GroupVersion) error { - if reference == nil { - return fmt.Errorf("object reference passed was nil") - } +func referenceExistsWithCorrectKindAndAPIVersion(reference clusterv1.ClusterClassTemplateReference, kind string, apiVersion schema.GroupVersion) error { if reference.Kind != kind { return fmt.Errorf("object reference kind %v does not match expected %v", reference.Kind, kind) } diff --git a/internal/controllers/topology/cluster/blueprint.go b/internal/controllers/topology/cluster/blueprint.go index 83ffad12a214..14fbc9c32728 100644 --- a/internal/controllers/topology/cluster/blueprint.go +++ b/internal/controllers/topology/cluster/blueprint.go @@ -39,21 +39,21 @@ func (r *Reconciler) getBlueprint(ctx context.Context, cluster *clusterv1.Cluste var err error // Get ClusterClass.spec.infrastructure. - blueprint.InfrastructureClusterTemplate, err = r.getReference(ctx, blueprint.ClusterClass.Spec.Infrastructure.Ref.ToObjectReference(clusterClass.Namespace)) + blueprint.InfrastructureClusterTemplate, err = r.getReference(ctx, blueprint.ClusterClass.Spec.Infrastructure.TemplateRef.ToObjectReference(clusterClass.Namespace)) if err != nil { return nil, errors.Wrapf(err, "failed to get infrastructure cluster template for ClusterClass %s", klog.KObj(blueprint.ClusterClass)) } // Get ClusterClass.spec.controlPlane. blueprint.ControlPlane = &scope.ControlPlaneBlueprint{} - blueprint.ControlPlane.Template, err = r.getReference(ctx, blueprint.ClusterClass.Spec.ControlPlane.Ref.ToObjectReference(clusterClass.Namespace)) + blueprint.ControlPlane.Template, err = r.getReference(ctx, blueprint.ClusterClass.Spec.ControlPlane.TemplateRef.ToObjectReference(clusterClass.Namespace)) if err != nil { return nil, errors.Wrapf(err, "failed to get control plane template for ClusterClass %s", klog.KObj(blueprint.ClusterClass)) } // If the clusterClass mandates the controlPlane has infrastructureMachines, read it. if blueprint.HasControlPlaneInfrastructureMachine() { - blueprint.ControlPlane.InfrastructureMachineTemplate, err = r.getReference(ctx, blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref.ToObjectReference(clusterClass.Namespace)) + blueprint.ControlPlane.InfrastructureMachineTemplate, err = r.getReference(ctx, blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef.ToObjectReference(clusterClass.Namespace)) if err != nil { return nil, errors.Wrapf(err, "failed to get control plane's machine template for ClusterClass %s", klog.KObj(blueprint.ClusterClass)) } @@ -75,13 +75,13 @@ func (r *Reconciler) getBlueprint(ctx context.Context, cluster *clusterv1.Cluste machineDeploymentClass.Template.Metadata.DeepCopyInto(&machineDeploymentBlueprint.Metadata) // Get the infrastructure machine template. - machineDeploymentBlueprint.InfrastructureMachineTemplate, err = r.getReference(ctx, machineDeploymentClass.Template.Infrastructure.Ref.ToObjectReference(clusterClass.Namespace)) + machineDeploymentBlueprint.InfrastructureMachineTemplate, err = r.getReference(ctx, machineDeploymentClass.Template.Infrastructure.TemplateRef.ToObjectReference(clusterClass.Namespace)) if err != nil { return nil, errors.Wrapf(err, "failed to get infrastructure machine template for ClusterClass %s, MachineDeployment class %q", klog.KObj(blueprint.ClusterClass), machineDeploymentClass.Class) } // Get the bootstrap config template. - machineDeploymentBlueprint.BootstrapTemplate, err = r.getReference(ctx, machineDeploymentClass.Template.Bootstrap.Ref.ToObjectReference(clusterClass.Namespace)) + machineDeploymentBlueprint.BootstrapTemplate, err = r.getReference(ctx, machineDeploymentClass.Template.Bootstrap.TemplateRef.ToObjectReference(clusterClass.Namespace)) if err != nil { return nil, errors.Wrapf(err, "failed to get bootstrap config template for ClusterClass %s, MachineDeployment class %q", klog.KObj(blueprint.ClusterClass), machineDeploymentClass.Class) } @@ -104,13 +104,13 @@ func (r *Reconciler) getBlueprint(ctx context.Context, cluster *clusterv1.Cluste machinePoolClass.Template.Metadata.DeepCopyInto(&machinePoolBlueprint.Metadata) // Get the InfrastructureMachinePoolTemplate. - machinePoolBlueprint.InfrastructureMachinePoolTemplate, err = r.getReference(ctx, machinePoolClass.Template.Infrastructure.Ref.ToObjectReference(clusterClass.Namespace)) + machinePoolBlueprint.InfrastructureMachinePoolTemplate, err = r.getReference(ctx, machinePoolClass.Template.Infrastructure.TemplateRef.ToObjectReference(clusterClass.Namespace)) if err != nil { return nil, errors.Wrapf(err, "failed to get InfrastructureMachinePoolTemplate for ClusterClass %s, MachinePool class %q", klog.KObj(blueprint.ClusterClass), machinePoolClass.Class) } // Get the bootstrap config template. - machinePoolBlueprint.BootstrapTemplate, err = r.getReference(ctx, machinePoolClass.Template.Bootstrap.Ref.ToObjectReference(clusterClass.Namespace)) + machinePoolBlueprint.BootstrapTemplate, err = r.getReference(ctx, machinePoolClass.Template.Bootstrap.TemplateRef.ToObjectReference(clusterClass.Namespace)) if err != nil { return nil, errors.Wrapf(err, "failed to get bootstrap config for ClusterClass %s, MachinePool class %q", klog.KObj(blueprint.ClusterClass), machinePoolClass.Class) } diff --git a/internal/controllers/topology/cluster/cluster_controller_test.go b/internal/controllers/topology/cluster/cluster_controller_test.go index bcf0d0f1170e..32e87745b368 100644 --- a/internal/controllers/topology/cluster/cluster_controller_test.go +++ b/internal/controllers/topology/cluster/cluster_controller_test.go @@ -309,9 +309,9 @@ func TestClusterReconciler_reconcileUpdatesOnClusterClass(t *testing.T) { patchHelper, err := patch.NewHelper(clusterClass, env.Client) g.Expect(err).ToNot(HaveOccurred()) // Change the infrastructureMachineTemplateName for the first of our MachineDeployments and update in the API. - clusterClass.Spec.Workers.MachineDeployments[0].Template.Infrastructure.Ref.Name = infrastructureMachineTemplateName2 + clusterClass.Spec.Workers.MachineDeployments[0].Template.Infrastructure.TemplateRef.Name = infrastructureMachineTemplateName2 // Change the infrastructureMachinePoolTemplateName for the first of our MachinePools and update in the API. - clusterClass.Spec.Workers.MachinePools[0].Template.Infrastructure.Ref.Name = infrastructureMachinePoolTemplateName2 + clusterClass.Spec.Workers.MachinePools[0].Template.Infrastructure.TemplateRef.Name = infrastructureMachinePoolTemplateName2 g.Expect(patchHelper.Patch(ctx, clusterClass)).To(Succeed()) g.Eventually(func(g Gomega) error { @@ -319,8 +319,8 @@ func TestClusterReconciler_reconcileUpdatesOnClusterClass(t *testing.T) { // This is necessary as sometimes the cache can take a little time to update. class := &clusterv1.ClusterClass{} g.Expect(env.Get(ctx, actualCluster.GetClassKey(), class)).To(Succeed()) - g.Expect(class.Spec.Workers.MachineDeployments[0].Template.Infrastructure.Ref.Name).To(Equal(infrastructureMachineTemplateName2)) - g.Expect(class.Spec.Workers.MachinePools[0].Template.Infrastructure.Ref.Name).To(Equal(infrastructureMachinePoolTemplateName2)) + g.Expect(class.Spec.Workers.MachineDeployments[0].Template.Infrastructure.TemplateRef.Name).To(Equal(infrastructureMachineTemplateName2)) + g.Expect(class.Spec.Workers.MachinePools[0].Template.Infrastructure.TemplateRef.Name).To(Equal(infrastructureMachinePoolTemplateName2)) // For each cluster check that the clusterClass changes have been correctly reconciled. for _, name := range []string{clusterName1, clusterName2} { @@ -1003,7 +1003,7 @@ func assertControlPlaneReconcile(cluster *clusterv1.Cluster) error { return err } // Check for the ControlPlaneInfrastructure if it's referenced in the clusterClass. - if clusterClass.Spec.ControlPlane.MachineInfrastructure != nil && clusterClass.Spec.ControlPlane.MachineInfrastructure.Ref != nil { + if clusterClass.Spec.ControlPlane.MachineInfrastructure != nil { cpInfra, err := contract.ControlPlane().MachineTemplate().InfrastructureRef().Get(cp) if err != nil { return err diff --git a/internal/controllers/topology/cluster/reconcile_state_test.go b/internal/controllers/topology/cluster/reconcile_state_test.go index a793ca943c94..c9db533f6f8c 100644 --- a/internal/controllers/topology/cluster/reconcile_state_test.go +++ b/internal/controllers/topology/cluster/reconcile_state_test.go @@ -1543,8 +1543,8 @@ func testReconcileControlPlane(t *testing.T, controlPlaneContractVersion string) ClusterClass: &clusterv1.ClusterClass{}, } if tt.class.InfrastructureMachineTemplate != nil { - s.Blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure = &clusterv1.ClusterClassTemplate{ - Ref: objToClusterClassTemplateRef(tt.class.InfrastructureMachineTemplate), + s.Blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure = &clusterv1.ControlPlaneClassMachineInfrastructureTemplate{ + TemplateRef: objToClusterClassTemplateRef(tt.class.InfrastructureMachineTemplate), } } if tt.upgradeTracker != nil { @@ -1736,8 +1736,8 @@ func TestReconcileControlPlaneCleanup(t *testing.T) { ClusterClass: &clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - MachineInfrastructure: &clusterv1.ClusterClassTemplate{ - Ref: objToClusterClassTemplateRef(infrastructureMachineTemplate), + MachineInfrastructure: &clusterv1.ControlPlaneClassMachineInfrastructureTemplate{ + TemplateRef: objToClusterClassTemplateRef(infrastructureMachineTemplate), }, }, }, @@ -1892,8 +1892,8 @@ func TestReconcileControlPlaneMachineHealthCheck(t *testing.T) { ClusterClass: &clusterv1.ClusterClass{}, } if tt.class.InfrastructureMachineTemplate != nil { - s.Blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure = &clusterv1.ClusterClassTemplate{ - Ref: objToClusterClassTemplateRef(tt.class.InfrastructureMachineTemplate), + s.Blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure = &clusterv1.ControlPlaneClassMachineInfrastructureTemplate{ + TemplateRef: objToClusterClassTemplateRef(tt.class.InfrastructureMachineTemplate), } } @@ -4075,9 +4075,9 @@ func Test_createErrorWithoutObjectName(t *testing.T) { } } -func objToClusterClassTemplateRef(obj *unstructured.Unstructured) *clusterv1.ClusterClassTemplateReference { +func objToClusterClassTemplateRef(obj *unstructured.Unstructured) clusterv1.ClusterClassTemplateReference { gvk := obj.GetObjectKind().GroupVersionKind() - return &clusterv1.ClusterClassTemplateReference{ + return clusterv1.ClusterClassTemplateReference{ Kind: gvk.Kind, APIVersion: gvk.GroupVersion().String(), Name: obj.GetName(), diff --git a/internal/controllers/topology/cluster/structuredmerge/serversidepathhelper.go b/internal/controllers/topology/cluster/structuredmerge/serversidepathhelper.go index e4b6ecd6ec94..5a8b04c67f3c 100644 --- a/internal/controllers/topology/cluster/structuredmerge/serversidepathhelper.go +++ b/internal/controllers/topology/cluster/structuredmerge/serversidepathhelper.go @@ -70,7 +70,7 @@ func NewServerSidePatchHelper(ctx context.Context, original, modified client.Obj } } - // Filter the modifiedUnstructured object to only contain changes intendet to be done. + // Filter the modifiedUnstructured object to only contain changes intended to be done. // The originalUnstructured object will be filtered in dryRunSSAPatch using other options. ssa.FilterObject(modifiedUnstructured, &helperOptions.FilterObjectInput) diff --git a/internal/topology/check/compatibility.go b/internal/topology/check/compatibility.go index f910810e3b7b..4a093e58d249 100644 --- a/internal/topology/check/compatibility.go +++ b/internal/topology/check/compatibility.go @@ -87,11 +87,11 @@ func ObjectsAreInTheSameNamespace(current, desired client.Object) field.ErrorLis // ClusterClassTemplateAreCompatible checks if two referenced objects are compatible, meaning that // they are of the same GroupKind. -func ClusterClassTemplateAreCompatible(current, desired clusterv1.ClusterClassTemplate, pathPrefix *field.Path) field.ErrorList { +func ClusterClassTemplateAreCompatible(current, desired clusterv1.ClusterClassTemplateReference, pathPrefix *field.Path) field.ErrorList { var allErrs field.ErrorList - currentGK := current.Ref.GroupVersionKind().GroupKind() - desiredGK := desired.Ref.GroupVersionKind().GroupKind() + currentGK := current.GroupVersionKind().GroupKind() + desiredGK := desired.GroupVersionKind().GroupKind() if currentGK.Group != desiredGK.Group { allErrs = append(allErrs, field.Forbidden( @@ -111,19 +111,11 @@ func ClusterClassTemplateAreCompatible(current, desired clusterv1.ClusterClassTe } // ClusterClassTemplateIsValid ensures the template has no nil references, and has a valid Kind and GroupVersion. -func ClusterClassTemplateIsValid(template *clusterv1.ClusterClassTemplate, pathPrefix *field.Path) field.ErrorList { +func ClusterClassTemplateIsValid(templateRef clusterv1.ClusterClassTemplateReference, pathPrefix *field.Path) field.ErrorList { var allErrs field.ErrorList - // check if ref is not nil. - if template.Ref == nil { - return field.ErrorList{field.Required( - pathPrefix.Child("ref"), - "template reference must be defined", - )} - } - // check if a name is provided - if template.Ref.Name == "" { + if templateRef.Name == "" { allErrs = append(allErrs, field.Required( pathPrefix.Child("ref", "name"), @@ -133,23 +125,23 @@ func ClusterClassTemplateIsValid(template *clusterv1.ClusterClassTemplate, pathP } // check if kind is a template - if len(template.Ref.Kind) <= len(clusterv1.TemplateSuffix) || !strings.HasSuffix(template.Ref.Kind, clusterv1.TemplateSuffix) { + if len(templateRef.Kind) <= len(clusterv1.TemplateSuffix) || !strings.HasSuffix(templateRef.Kind, clusterv1.TemplateSuffix) { allErrs = append(allErrs, field.Invalid( pathPrefix.Child("ref", "kind"), - template.Ref.Kind, + templateRef.Kind, fmt.Sprintf("template kind must be of form \"%s\"", clusterv1.TemplateSuffix), ), ) } // check if apiVersion is valid - gv, err := schema.ParseGroupVersion(template.Ref.APIVersion) + gv, err := schema.ParseGroupVersion(templateRef.APIVersion) if err != nil { allErrs = append(allErrs, field.Invalid( pathPrefix.Child("ref", "apiVersion"), - template.Ref.APIVersion, + templateRef.APIVersion, fmt.Sprintf("template apiVersion must be a valid Kubernetes apiVersion: %v", err), ), ) @@ -182,14 +174,14 @@ func ClusterClassesAreCompatible(current, desired *clusterv1.ClusterClass) field } // Validate InfrastructureClusterTemplate changes desired a compatible way. - allErrs = append(allErrs, ClusterClassTemplateAreCompatible(current.Spec.Infrastructure.ClusterClassTemplate, desired.Spec.Infrastructure.ClusterClassTemplate, + allErrs = append(allErrs, ClusterClassTemplateAreCompatible(current.Spec.Infrastructure.TemplateRef, desired.Spec.Infrastructure.TemplateRef, field.NewPath("spec", "infrastructure"))...) // Validate control plane changes desired a compatible way. - allErrs = append(allErrs, ClusterClassTemplateAreCompatible(current.Spec.ControlPlane.ClusterClassTemplate, desired.Spec.ControlPlane.ClusterClassTemplate, + allErrs = append(allErrs, ClusterClassTemplateAreCompatible(current.Spec.ControlPlane.TemplateRef, desired.Spec.ControlPlane.TemplateRef, field.NewPath("spec", "controlPlane"))...) if desired.Spec.ControlPlane.MachineInfrastructure != nil && current.Spec.ControlPlane.MachineInfrastructure != nil { - allErrs = append(allErrs, ClusterClassTemplateAreCompatible(*current.Spec.ControlPlane.MachineInfrastructure, *desired.Spec.ControlPlane.MachineInfrastructure, + allErrs = append(allErrs, ClusterClassTemplateAreCompatible(current.Spec.ControlPlane.MachineInfrastructure.TemplateRef, desired.Spec.ControlPlane.MachineInfrastructure.TemplateRef, field.NewPath("spec", "controlPlane", "machineInfrastructure"))...) } @@ -216,7 +208,7 @@ func MachineDeploymentClassesAreCompatible(current, desired *clusterv1.ClusterCl // class.Template.Bootstrap is ensured syntactically correct by LocalObjectTemplateIsValid. // Validates class.Template.Infrastructure template changes in a compatible way - allErrs = append(allErrs, ClusterClassTemplateAreCompatible(oldClass.Template.Infrastructure, class.Template.Infrastructure, + allErrs = append(allErrs, ClusterClassTemplateAreCompatible(oldClass.Template.Infrastructure.TemplateRef, class.Template.Infrastructure.TemplateRef, field.NewPath("spec", "workers", "machineDeployments").Index(i))...) } } @@ -257,7 +249,7 @@ func MachinePoolClassesAreCompatible(current, desired *clusterv1.ClusterClass) f // class.Template.Bootstrap is ensured syntactically correct by LocalObjectTemplateIsValid. // Validates class.Template.Infrastructure template changes in a compatible way - allErrs = append(allErrs, ClusterClassTemplateAreCompatible(oldClass.Template.Infrastructure, class.Template.Infrastructure, + allErrs = append(allErrs, ClusterClassTemplateAreCompatible(oldClass.Template.Infrastructure.TemplateRef, class.Template.Infrastructure.TemplateRef, field.NewPath("spec", "workers", "machinePools").Index(i))...) } } @@ -416,22 +408,22 @@ func MachinePoolTopologiesAreValidAndDefinedInClusterClass(desired *clusterv1.Cl func ClusterClassTemplatesAreValid(clusterClass *clusterv1.ClusterClass) field.ErrorList { var allErrs field.ErrorList - allErrs = append(allErrs, ClusterClassTemplateIsValid(&clusterClass.Spec.Infrastructure.ClusterClassTemplate, field.NewPath("spec", "infrastructure"))...) - allErrs = append(allErrs, ClusterClassTemplateIsValid(&clusterClass.Spec.ControlPlane.ClusterClassTemplate, field.NewPath("spec", "controlPlane"))...) + allErrs = append(allErrs, ClusterClassTemplateIsValid(clusterClass.Spec.Infrastructure.TemplateRef, field.NewPath("spec", "infrastructure"))...) + allErrs = append(allErrs, ClusterClassTemplateIsValid(clusterClass.Spec.ControlPlane.TemplateRef, field.NewPath("spec", "controlPlane"))...) if clusterClass.Spec.ControlPlane.MachineInfrastructure != nil { - allErrs = append(allErrs, ClusterClassTemplateIsValid(clusterClass.Spec.ControlPlane.MachineInfrastructure, field.NewPath("spec", "controlPlane", "machineInfrastructure"))...) + allErrs = append(allErrs, ClusterClassTemplateIsValid(clusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef, field.NewPath("spec", "controlPlane", "machineInfrastructure"))...) } for i := range clusterClass.Spec.Workers.MachineDeployments { mdc := clusterClass.Spec.Workers.MachineDeployments[i] - allErrs = append(allErrs, ClusterClassTemplateIsValid(&mdc.Template.Bootstrap, field.NewPath("spec", "workers", "machineDeployments").Index(i).Child("template", "bootstrap"))...) - allErrs = append(allErrs, ClusterClassTemplateIsValid(&mdc.Template.Infrastructure, field.NewPath("spec", "workers", "machineDeployments").Index(i).Child("template", "infrastructure"))...) + allErrs = append(allErrs, ClusterClassTemplateIsValid(mdc.Template.Bootstrap.TemplateRef, field.NewPath("spec", "workers", "machineDeployments").Index(i).Child("template", "bootstrap"))...) + allErrs = append(allErrs, ClusterClassTemplateIsValid(mdc.Template.Infrastructure.TemplateRef, field.NewPath("spec", "workers", "machineDeployments").Index(i).Child("template", "infrastructure"))...) } for i := range clusterClass.Spec.Workers.MachinePools { mpc := clusterClass.Spec.Workers.MachinePools[i] - allErrs = append(allErrs, ClusterClassTemplateIsValid(&mpc.Template.Bootstrap, field.NewPath("spec", "workers", "machinePools").Index(i).Child("template", "bootstrap"))...) - allErrs = append(allErrs, ClusterClassTemplateIsValid(&mpc.Template.Infrastructure, field.NewPath("spec", "workers", "machinePools").Index(i).Child("template", "infrastructure"))...) + allErrs = append(allErrs, ClusterClassTemplateIsValid(mpc.Template.Bootstrap.TemplateRef, field.NewPath("spec", "workers", "machinePools").Index(i).Child("template", "bootstrap"))...) + allErrs = append(allErrs, ClusterClassTemplateIsValid(mpc.Template.Infrastructure.TemplateRef, field.NewPath("spec", "workers", "machinePools").Index(i).Child("template", "infrastructure"))...) } return allErrs diff --git a/internal/topology/check/compatibility_test.go b/internal/topology/check/compatibility_test.go index 6b4626891830..bc4e6de32086 100644 --- a/internal/topology/check/compatibility_test.go +++ b/internal/topology/check/compatibility_test.go @@ -185,69 +185,59 @@ func TestObjectsAreStrictlyCompatible(t *testing.T) { } func TestClusterClassTemplateAreCompatible(t *testing.T) { - template := clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "foo", - Kind: "bar", - APIVersion: "test.group.io/versionone", - }, + templateRef := clusterv1.ClusterClassTemplateReference{ + Name: "foo", + Kind: "bar", + APIVersion: "test.group.io/versionone", } - compatibleNameChangeTemplate := clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "newFoo", - Kind: "bar", - APIVersion: "test.group.io/versionone", - }, + compatibleNameChangeTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "newFoo", + Kind: "bar", + APIVersion: "test.group.io/versionone", } - compatibleAPIVersionChangeTemplate := clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "foo", - Kind: "bar", - APIVersion: "test.group.io/versiontwo", - }, + compatibleAPIVersionChangeTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "foo", + Kind: "bar", + APIVersion: "test.group.io/versiontwo", } - incompatibleAPIGroupChangeTemplate := clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "foo", - Kind: "bar", - APIVersion: "production.group.io/versionone", - }, + incompatibleAPIGroupChangeTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "foo", + Kind: "bar", + APIVersion: "production.group.io/versionone", } - incompatibleAPIKindChangeTemplate := clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "foo", - Kind: "notabar", - APIVersion: "test.group.io/versionone", - }, + incompatibleAPIKindChangeTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "foo", + Kind: "notabar", + APIVersion: "test.group.io/versionone", } tests := []struct { name string - current clusterv1.ClusterClassTemplate - desired clusterv1.ClusterClassTemplate + current clusterv1.ClusterClassTemplateReference + desired clusterv1.ClusterClassTemplateReference wantErr bool }{ { name: "Allow change to template name", - current: template, - desired: compatibleNameChangeTemplate, + current: templateRef, + desired: compatibleNameChangeTemplateRef, wantErr: false, }, { name: "Allow change to template APIVersion", - current: template, - desired: compatibleAPIVersionChangeTemplate, + current: templateRef, + desired: compatibleAPIVersionChangeTemplateRef, wantErr: false, }, { name: "Block change to template API Group", - current: template, - desired: incompatibleAPIGroupChangeTemplate, + current: templateRef, + desired: incompatibleAPIGroupChangeTemplateRef, wantErr: true, }, { name: "Block change to template API Kind", - current: template, - desired: incompatibleAPIKindChangeTemplate, + current: templateRef, + desired: incompatibleAPIKindChangeTemplateRef, wantErr: true, }, } @@ -267,87 +257,76 @@ func TestClusterClassTemplateAreCompatible(t *testing.T) { func TestClusterClassTemplateIsValid(t *testing.T) { pathPrefix := field.NewPath("this", "is", "a", "prefix") - validTemplate := &clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "valid", - Kind: "barTemplate", - APIVersion: "test.group.io/versionone", - }, + validTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "valid", + Kind: "barTemplate", + APIVersion: "test.group.io/versionone", } - nilTemplate := &clusterv1.ClusterClassTemplate{ - Ref: nil, - } - emptyNameTemplate := &clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "", - Kind: "barTemplate", - APIVersion: "test.group.io/versionone", - }, + emptyTemplateRef := clusterv1.ClusterClassTemplateReference{} + + emptyNameTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "", + Kind: "barTemplate", + APIVersion: "test.group.io/versionone", } - notTemplateKindTemplate := &clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "foo", - Kind: "bar", - APIVersion: "test.group.io/versionone", - }, + notTemplateKindTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "foo", + Kind: "bar", + APIVersion: "test.group.io/versionone", } - invalidAPIVersionTemplate := &clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "foo", - Kind: "barTemplate", - APIVersion: "this/has/too/many/slashes", - }, + invalidAPIVersionTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "foo", + Kind: "barTemplate", + APIVersion: "this/has/too/many/slashes", } - emptyAPIVersionTemplate := &clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Name: "foo", - Kind: "barTemplate", - APIVersion: "", - }, + emptyAPIVersionTemplateRef := clusterv1.ClusterClassTemplateReference{ + Name: "foo", + Kind: "barTemplate", + APIVersion: "", } tests := []struct { - template *clusterv1.ClusterClassTemplate - name string - wantErr bool + templateRef clusterv1.ClusterClassTemplateReference + name string + wantErr bool }{ { - name: "No error with valid Template", - template: validTemplate, - wantErr: false, + name: "No error with valid Template", + templateRef: validTemplateRef, + wantErr: false, }, { - name: "Invalid if ref is nil", - template: nilTemplate, - wantErr: true, + name: "Invalid if ref is nil", + templateRef: emptyTemplateRef, + wantErr: true, }, { - name: "Invalid if name is empty", - template: emptyNameTemplate, - wantErr: true, + name: "Invalid if name is empty", + templateRef: emptyNameTemplateRef, + wantErr: true, }, { - name: "Invalid if Kind doesn't have Template suffix", - template: notTemplateKindTemplate, - wantErr: true, + name: "Invalid if Kind doesn't have Template suffix", + templateRef: notTemplateKindTemplateRef, + wantErr: true, }, { - name: "Invalid if apiVersion is not valid", - template: invalidAPIVersionTemplate, - wantErr: true, + name: "Invalid if apiVersion is not valid", + templateRef: invalidAPIVersionTemplateRef, + wantErr: true, }, { - name: "Empty apiVersion is not valid", - template: emptyAPIVersionTemplate, - wantErr: true, + name: "Empty apiVersion is not valid", + templateRef: emptyAPIVersionTemplateRef, + wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) - allErrs := ClusterClassTemplateIsValid(tt.template, pathPrefix) + allErrs := ClusterClassTemplateIsValid(tt.templateRef, pathPrefix) if tt.wantErr { g.Expect(allErrs).ToNot(BeEmpty()) return diff --git a/internal/topology/upgrade/clusterctl_upgrade_test.go b/internal/topology/upgrade/clusterctl_upgrade_test.go index bd454f3f20bc..2c2c3ff4e6a0 100644 --- a/internal/topology/upgrade/clusterctl_upgrade_test.go +++ b/internal/topology/upgrade/clusterctl_upgrade_test.go @@ -347,15 +347,15 @@ func createT1ClusterClass(g *WithT, ns *corev1.Namespace, ct1 client.Client) *cl machineDeploymentClass1 := clusterv1.MachineDeploymentClass{ Class: "md-class1", Template: clusterv1.MachineDeploymentClassTemplate{ - Infrastructure: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ + Infrastructure: clusterv1.MachineDeploymentClassInfrastructureTemplate{ + TemplateRef: clusterv1.ClusterClassTemplateReference{ Kind: "TestResourceTemplate", Name: infrastructureMachineTemplate1.Name, APIVersion: testt1v1beta1.GroupVersion.String(), }, }, - Bootstrap: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ + Bootstrap: clusterv1.MachineDeploymentClassBootstrapTemplate{ + TemplateRef: clusterv1.ClusterClassTemplateReference{ Kind: "TestResourceTemplate", Name: bootstrapTemplate.Name, APIVersion: testt1v1beta1.GroupVersion.String(), @@ -371,24 +371,20 @@ func createT1ClusterClass(g *WithT, ns *corev1.Namespace, ct1 client.Client) *cl }, Spec: clusterv1.ClusterClassSpec{ Infrastructure: clusterv1.InfrastructureClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Kind: "TestResourceTemplate", - Name: infrastructureClusterTemplate1.Name, - APIVersion: testt1v1beta1.GroupVersion.String(), - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + Kind: "TestResourceTemplate", + Name: infrastructureClusterTemplate1.Name, + APIVersion: testt1v1beta1.GroupVersion.String(), }, }, ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Kind: "TestResourceTemplate", - Name: controlPlaneTemplate.Name, - APIVersion: testt1v1beta1.GroupVersion.String(), - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + Kind: "TestResourceTemplate", + Name: controlPlaneTemplate.Name, + APIVersion: testt1v1beta1.GroupVersion.String(), }, - MachineInfrastructure: &clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ + MachineInfrastructure: &clusterv1.ControlPlaneClassMachineInfrastructureTemplate{ + TemplateRef: clusterv1.ClusterClassTemplateReference{ Kind: "TestResourceTemplate", Name: infrastructureMachineTemplate1.Name, APIVersion: testt1v1beta1.GroupVersion.String(), @@ -546,15 +542,15 @@ func createT2ClusterClass(g *WithT, ns *corev1.Namespace, ct2 client.Client) *cl machineDeploymentClass1 := clusterv1.MachineDeploymentClass{ Class: "md-class1", Template: clusterv1.MachineDeploymentClassTemplate{ - Infrastructure: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ + Infrastructure: clusterv1.MachineDeploymentClassInfrastructureTemplate{ + TemplateRef: clusterv1.ClusterClassTemplateReference{ Kind: "TestResourceTemplate", Name: infrastructureMachineTemplate1.Name, APIVersion: testt2v1beta2.GroupVersion.String(), }, }, - Bootstrap: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ + Bootstrap: clusterv1.MachineDeploymentClassBootstrapTemplate{ + TemplateRef: clusterv1.ClusterClassTemplateReference{ Kind: "TestResourceTemplate", Name: bootstrapTemplate.Name, APIVersion: testt2v1beta2.GroupVersion.String(), @@ -570,24 +566,20 @@ func createT2ClusterClass(g *WithT, ns *corev1.Namespace, ct2 client.Client) *cl }, Spec: clusterv1.ClusterClassSpec{ Infrastructure: clusterv1.InfrastructureClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Kind: "TestResourceTemplate", - Name: infrastructureClusterTemplate1.Name, - APIVersion: testt2v1beta2.GroupVersion.String(), - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + Kind: "TestResourceTemplate", + Name: infrastructureClusterTemplate1.Name, + APIVersion: testt2v1beta2.GroupVersion.String(), }, }, ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - Kind: "TestResourceTemplate", - Name: controlPlaneTemplate.Name, - APIVersion: testt2v1beta2.GroupVersion.String(), - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + Kind: "TestResourceTemplate", + Name: controlPlaneTemplate.Name, + APIVersion: testt2v1beta2.GroupVersion.String(), }, - MachineInfrastructure: &clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ + MachineInfrastructure: &clusterv1.ControlPlaneClassMachineInfrastructureTemplate{ + TemplateRef: clusterv1.ClusterClassTemplateReference{ Kind: "TestResourceTemplate", Name: infrastructureMachineTemplate1.Name, APIVersion: testt2v1beta2.GroupVersion.String(), diff --git a/internal/topology/upgrade/test/t1/crd/test.cluster.x-k8s.io_testresources.yaml b/internal/topology/upgrade/test/t1/crd/test.cluster.x-k8s.io_testresources.yaml index c988945557b2..0fbb871a30c7 100644 --- a/internal/topology/upgrade/test/t1/crd/test.cluster.x-k8s.io_testresources.yaml +++ b/internal/topology/upgrade/test/t1/crd/test.cluster.x-k8s.io_testresources.yaml @@ -87,6 +87,7 @@ spec: In future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited. + minProperties: 1 properties: annotations: additionalProperties: diff --git a/internal/topology/upgrade/test/t1/crd/test.cluster.x-k8s.io_testresourcetemplates.yaml b/internal/topology/upgrade/test/t1/crd/test.cluster.x-k8s.io_testresourcetemplates.yaml index 7a1d74b6f0af..92d4d36d12ce 100644 --- a/internal/topology/upgrade/test/t1/crd/test.cluster.x-k8s.io_testresourcetemplates.yaml +++ b/internal/topology/upgrade/test/t1/crd/test.cluster.x-k8s.io_testresourcetemplates.yaml @@ -94,6 +94,7 @@ spec: In future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited. + minProperties: 1 properties: annotations: additionalProperties: diff --git a/internal/topology/upgrade/test/t1/v1beta1/types.go b/internal/topology/upgrade/test/t1/v1beta1/types.go index 6d7d1795cec3..75f0fca3e2b8 100644 --- a/internal/topology/upgrade/test/t1/v1beta1/types.go +++ b/internal/topology/upgrade/test/t1/v1beta1/types.go @@ -129,7 +129,7 @@ type StructWithOnlyOptionalFields struct { // Note: infrastructureRef field is not required because this CRD is also used for non - control plane cases. type TestResourceMachineTemplateSpec struct { // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // +optional InfrastructureRef TestContractVersionedObjectReference `json:"infrastructureRef"` diff --git a/internal/topology/upgrade/test/t2/crd/test.cluster.x-k8s.io_testresources.yaml b/internal/topology/upgrade/test/t2/crd/test.cluster.x-k8s.io_testresources.yaml index 170427c2ae70..619d93dab3d7 100644 --- a/internal/topology/upgrade/test/t2/crd/test.cluster.x-k8s.io_testresources.yaml +++ b/internal/topology/upgrade/test/t2/crd/test.cluster.x-k8s.io_testresources.yaml @@ -87,6 +87,7 @@ spec: In future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited. + minProperties: 1 properties: annotations: additionalProperties: @@ -213,6 +214,7 @@ spec: In future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited. + minProperties: 1 properties: annotations: additionalProperties: diff --git a/internal/topology/upgrade/test/t2/crd/test.cluster.x-k8s.io_testresourcetemplates.yaml b/internal/topology/upgrade/test/t2/crd/test.cluster.x-k8s.io_testresourcetemplates.yaml index 62251e455d7b..70fabe2ee4d1 100644 --- a/internal/topology/upgrade/test/t2/crd/test.cluster.x-k8s.io_testresourcetemplates.yaml +++ b/internal/topology/upgrade/test/t2/crd/test.cluster.x-k8s.io_testresourcetemplates.yaml @@ -94,6 +94,7 @@ spec: In future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited. + minProperties: 1 properties: annotations: additionalProperties: @@ -234,6 +235,7 @@ spec: In future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited. + minProperties: 1 properties: annotations: additionalProperties: diff --git a/internal/topology/upgrade/test/t2/v1beta1/types.go b/internal/topology/upgrade/test/t2/v1beta1/types.go index 9b6a354d6746..b36b327ab0ad 100644 --- a/internal/topology/upgrade/test/t2/v1beta1/types.go +++ b/internal/topology/upgrade/test/t2/v1beta1/types.go @@ -124,7 +124,7 @@ type StructWithOnlyOptionalFields struct { // Note: infrastructureRef field is not required because this CRD is also used for non - control plane cases. type TestResourceMachineTemplateSpec struct { // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // +optional InfrastructureRef TestContractVersionedObjectReference `json:"infrastructureRef"` diff --git a/internal/topology/upgrade/test/t2/v1beta2/types.go b/internal/topology/upgrade/test/t2/v1beta2/types.go index 9a5f97cc6a05..8c756191560e 100644 --- a/internal/topology/upgrade/test/t2/v1beta2/types.go +++ b/internal/topology/upgrade/test/t2/v1beta2/types.go @@ -131,7 +131,7 @@ type StructWithOnlyOptionalFields struct { // Note: infrastructureRef field is not required because this CRD is also used for non - control plane cases. type TestResourceMachineTemplateSpec struct { // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // +optional InfrastructureRef TestContractVersionedObjectReference `json:"infrastructureRef"` diff --git a/internal/webhooks/machine.go b/internal/webhooks/machine.go index 38f51e51617c..a80d9005a134 100644 --- a/internal/webhooks/machine.go +++ b/internal/webhooks/machine.go @@ -116,7 +116,7 @@ func (webhook *Machine) validate(oldM, newM *clusterv1.Machine) error { allErrs = append( allErrs, field.Required( - specPath.Child("bootstrap", "data"), + specPath.Child("bootstrap"), "expected either spec.bootstrap.dataSecretName or spec.bootstrap.configRef to be populated", ), ) diff --git a/internal/webhooks/machinedeployment.go b/internal/webhooks/machinedeployment.go index 0b50dad33932..eadd737b0662 100644 --- a/internal/webhooks/machinedeployment.go +++ b/internal/webhooks/machinedeployment.go @@ -196,6 +196,17 @@ func (webhook *MachineDeployment) validate(oldMD, newMD *clusterv1.MachineDeploy } } specPath := field.NewPath("spec") + + if newMD.Spec.Template.Spec.Bootstrap.ConfigRef == nil && newMD.Spec.Template.Spec.Bootstrap.DataSecretName == nil { + allErrs = append( + allErrs, + field.Required( + specPath.Child("template", "spec", "bootstrap"), + "expected either spec.template.spec.bootstrap.dataSecretName or spec.template.spec.bootstrap.configRef to be populated", + ), + ) + } + selector, err := metav1.LabelSelectorAsSelector(&newMD.Spec.Selector) if err != nil { allErrs = append( diff --git a/internal/webhooks/machinedeployment_test.go b/internal/webhooks/machinedeployment_test.go index 8b714d74827a..79851e7e44a6 100644 --- a/internal/webhooks/machinedeployment_test.go +++ b/internal/webhooks/machinedeployment_test.go @@ -44,6 +44,9 @@ func TestMachineDeploymentDefault(t *testing.T) { Template: clusterv1.MachineTemplateSpec{ Spec: clusterv1.MachineSpec{ Version: "1.19.10", + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, }, }, }, @@ -82,6 +85,65 @@ func TestMachineDeploymentDefault(t *testing.T) { g.Expect(md.Spec.Template.Spec.Version).To(Equal("v1.19.10")) } +func TestMachineDeploymentBootstrapValidation(t *testing.T) { + tests := []struct { + name string + bootstrap clusterv1.Bootstrap + expectErr bool + }{ + { + name: "should return error if configref and data are nil", + bootstrap: clusterv1.Bootstrap{ConfigRef: nil, DataSecretName: nil}, + expectErr: true, + }, + { + name: "should not return error if dataSecretName is set", + bootstrap: clusterv1.Bootstrap{ConfigRef: nil, DataSecretName: ptr.To("test")}, + expectErr: false, + }, + { + name: "should not return error if dataSecretName is set", + bootstrap: clusterv1.Bootstrap{ConfigRef: nil, DataSecretName: ptr.To("")}, + expectErr: false, + }, + { + name: "should not return error if config ref is set", + bootstrap: clusterv1.Bootstrap{ConfigRef: &clusterv1.ContractVersionedObjectReference{}, DataSecretName: nil}, + expectErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + m := &clusterv1.MachineDeployment{ + Spec: clusterv1.MachineDeploymentSpec{ + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{Bootstrap: tt.bootstrap}, + }, + }, + } + webhook := &MachineDeployment{} + + if tt.expectErr { + warnings, err := webhook.ValidateCreate(ctx, m) + g.Expect(err).To(HaveOccurred()) + g.Expect(warnings).To(BeEmpty()) + warnings, err = webhook.ValidateUpdate(ctx, m, m) + g.Expect(err).To(HaveOccurred()) + g.Expect(warnings).To(BeEmpty()) + } else { + warnings, err := webhook.ValidateCreate(ctx, m) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(warnings).To(BeEmpty()) + warnings, err = webhook.ValidateUpdate(ctx, m, m) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(warnings).To(BeEmpty()) + } + }) + } +} + func TestMachineDeploymentReferenceDefault(t *testing.T) { g := NewWithT(t) md := &clusterv1.MachineDeployment{ @@ -488,6 +550,11 @@ func TestMachineDeploymentValidation(t *testing.T) { ObjectMeta: clusterv1.ObjectMeta{ Labels: tt.labels, }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, + }, }, MachineNamingStrategy: &tt.machineNamingStrategy, }, @@ -560,6 +627,9 @@ func TestMachineDeploymentVersionValidation(t *testing.T) { Template: clusterv1.MachineTemplateSpec{ Spec: clusterv1.MachineSpec{ Version: tt.version, + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, }, }, }, @@ -618,12 +688,26 @@ func TestMachineDeploymentClusterNameImmutable(t *testing.T) { newMD := &clusterv1.MachineDeployment{ Spec: clusterv1.MachineDeploymentSpec{ ClusterName: tt.newClusterName, + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, + }, + }, }, } oldMD := &clusterv1.MachineDeployment{ Spec: clusterv1.MachineDeploymentSpec{ ClusterName: tt.oldClusterName, + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, + }, + }, }, } diff --git a/internal/webhooks/machineset.go b/internal/webhooks/machineset.go index 6352065922b4..6efbf6f6df84 100644 --- a/internal/webhooks/machineset.go +++ b/internal/webhooks/machineset.go @@ -161,6 +161,17 @@ func (webhook *MachineSet) ValidateDelete(_ context.Context, _ runtime.Object) ( func (webhook *MachineSet) validate(oldMS, newMS *clusterv1.MachineSet) error { var allErrs field.ErrorList specPath := field.NewPath("spec") + + if newMS.Spec.Template.Spec.Bootstrap.ConfigRef == nil && newMS.Spec.Template.Spec.Bootstrap.DataSecretName == nil { + allErrs = append( + allErrs, + field.Required( + specPath.Child("template", "spec", "bootstrap"), + "expected either spec.template.spec.bootstrap.dataSecretName or spec.template.spec.bootstrap.configRef to be populated", + ), + ) + } + selector, err := metav1.LabelSelectorAsSelector(&newMS.Spec.Selector) if err != nil { allErrs = append( diff --git a/internal/webhooks/machineset_test.go b/internal/webhooks/machineset_test.go index 388648940636..17c2d76763c7 100644 --- a/internal/webhooks/machineset_test.go +++ b/internal/webhooks/machineset_test.go @@ -41,6 +41,9 @@ func TestMachineSetDefault(t *testing.T) { Template: clusterv1.MachineTemplateSpec{ Spec: clusterv1.MachineSpec{ Version: "1.19.10", + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, }, }, }, @@ -63,6 +66,65 @@ func TestMachineSetDefault(t *testing.T) { g.Expect(ms.Spec.Template.Spec.Version).To(Equal("v1.19.10")) } +func TestMachineSetBootstrapValidation(t *testing.T) { + tests := []struct { + name string + bootstrap clusterv1.Bootstrap + expectErr bool + }{ + { + name: "should return error if configref and data are nil", + bootstrap: clusterv1.Bootstrap{ConfigRef: nil, DataSecretName: nil}, + expectErr: true, + }, + { + name: "should not return error if dataSecretName is set", + bootstrap: clusterv1.Bootstrap{ConfigRef: nil, DataSecretName: ptr.To("test")}, + expectErr: false, + }, + { + name: "should not return error if dataSecretName is set", + bootstrap: clusterv1.Bootstrap{ConfigRef: nil, DataSecretName: ptr.To("")}, + expectErr: false, + }, + { + name: "should not return error if config ref is set", + bootstrap: clusterv1.Bootstrap{ConfigRef: &clusterv1.ContractVersionedObjectReference{}, DataSecretName: nil}, + expectErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + m := &clusterv1.MachineSet{ + Spec: clusterv1.MachineSetSpec{ + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{Bootstrap: tt.bootstrap}, + }, + }, + } + webhook := &MachineSet{} + + if tt.expectErr { + warnings, err := webhook.ValidateCreate(ctx, m) + g.Expect(err).To(HaveOccurred()) + g.Expect(warnings).To(BeEmpty()) + warnings, err = webhook.ValidateUpdate(ctx, m, m) + g.Expect(err).To(HaveOccurred()) + g.Expect(warnings).To(BeEmpty()) + } else { + warnings, err := webhook.ValidateCreate(ctx, m) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(warnings).To(BeEmpty()) + warnings, err = webhook.ValidateUpdate(ctx, m, m) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(warnings).To(BeEmpty()) + } + }) + } +} + func TestCalculateMachineSetReplicas(t *testing.T) { tests := []struct { name string @@ -277,6 +339,11 @@ func TestMachineSetLabelSelectorMatchValidation(t *testing.T) { ObjectMeta: clusterv1.ObjectMeta{ Labels: tt.labels, }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, + }, }, }, } @@ -329,12 +396,26 @@ func TestMachineSetClusterNameImmutable(t *testing.T) { newMS := &clusterv1.MachineSet{ Spec: clusterv1.MachineSetSpec{ ClusterName: tt.newClusterName, + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, + }, + }, }, } oldMS := &clusterv1.MachineSet{ Spec: clusterv1.MachineSetSpec{ ClusterName: tt.oldClusterName, + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, + }, + }, }, } @@ -391,6 +472,9 @@ func TestMachineSetVersionValidation(t *testing.T) { Template: clusterv1.MachineTemplateSpec{ Spec: clusterv1.MachineSpec{ Version: tt.version, + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, }, }, }, @@ -577,6 +661,13 @@ func TestMachineSetMachineNamingStrategyValidation(t *testing.T) { ms := &clusterv1.MachineSet{ Spec: clusterv1.MachineSetSpec{ MachineNamingStrategy: &tt.machineNamingStrategy, + Template: clusterv1.MachineTemplateSpec{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, + }, + }, }, } diff --git a/internal/webhooks/patch_validation.go b/internal/webhooks/patch_validation.go index 97a9c109cb05..10773fcaf05f 100644 --- a/internal/webhooks/patch_validation.go +++ b/internal/webhooks/patch_validation.go @@ -178,7 +178,7 @@ func validateSelectors(selector clusterv1.PatchSelector, class *clusterv1.Cluste } if ptr.Deref(selector.MatchResources.InfrastructureCluster, false) { - if !selectorMatchTemplate(selector, class.Spec.Infrastructure.Ref) { + if !selectorMatchTemplate(selector, class.Spec.Infrastructure.TemplateRef) { allErrs = append(allErrs, field.Invalid( path.Child("matchResources", "infrastructureCluster"), selector.MatchResources.InfrastructureCluster, @@ -189,11 +189,11 @@ func validateSelectors(selector clusterv1.PatchSelector, class *clusterv1.Cluste if ptr.Deref(selector.MatchResources.ControlPlane, false) { match := false - if selectorMatchTemplate(selector, class.Spec.ControlPlane.Ref) { + if selectorMatchTemplate(selector, class.Spec.ControlPlane.TemplateRef) { match = true } if class.Spec.ControlPlane.MachineInfrastructure != nil && - selectorMatchTemplate(selector, class.Spec.ControlPlane.MachineInfrastructure.Ref) { + selectorMatchTemplate(selector, class.Spec.ControlPlane.MachineInfrastructure.TemplateRef) { match = true } if !match { @@ -224,8 +224,8 @@ func validateSelectors(selector clusterv1.PatchSelector, class *clusterv1.Cluste } if matches { - if selectorMatchTemplate(selector, md.Template.Infrastructure.Ref) || - selectorMatchTemplate(selector, md.Template.Bootstrap.Ref) { + if selectorMatchTemplate(selector, md.Template.Infrastructure.TemplateRef) || + selectorMatchTemplate(selector, md.Template.Bootstrap.TemplateRef) { match = true break } @@ -260,8 +260,8 @@ func validateSelectors(selector clusterv1.PatchSelector, class *clusterv1.Cluste } if matches { - if selectorMatchTemplate(selector, mp.Template.Infrastructure.Ref) || - selectorMatchTemplate(selector, mp.Template.Bootstrap.Ref) { + if selectorMatchTemplate(selector, mp.Template.Infrastructure.TemplateRef) || + selectorMatchTemplate(selector, mp.Template.Bootstrap.TemplateRef) { match = true break } @@ -311,10 +311,7 @@ func validateSelectorName(name string, path *field.Path, resourceName string, in } // selectorMatchTemplate returns true if APIVersion and Kind for the given selector match the reference. -func selectorMatchTemplate(selector clusterv1.PatchSelector, reference *clusterv1.ClusterClassTemplateReference) bool { - if reference == nil { - return false - } +func selectorMatchTemplate(selector clusterv1.PatchSelector, reference clusterv1.ClusterClassTemplateReference) bool { return selector.Kind == reference.Kind && selector.APIVersion == reference.APIVersion } diff --git a/internal/webhooks/patch_validation_test.go b/internal/webhooks/patch_validation_test.go index 9209c030f932..c1a3804c51e3 100644 --- a/internal/webhooks/patch_validation_test.go +++ b/internal/webhooks/patch_validation_test.go @@ -43,11 +43,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -130,11 +128,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -183,11 +179,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -270,11 +264,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -293,11 +285,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -316,11 +306,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -358,11 +346,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -398,11 +384,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -450,11 +434,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -503,11 +485,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -556,11 +536,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -609,11 +587,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -664,11 +640,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -704,11 +678,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -759,11 +731,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -798,11 +768,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -840,11 +808,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -881,11 +847,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -926,11 +890,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -965,11 +927,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -1020,11 +980,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -1072,11 +1030,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -1127,11 +1083,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -1179,11 +1133,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -1231,11 +1183,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -1288,11 +1238,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, Patches: []clusterv1.ClusterClassPatch{ @@ -1329,11 +1277,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -1373,11 +1319,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -1400,11 +1344,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -1427,11 +1369,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -1451,11 +1391,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, @@ -1479,11 +1417,9 @@ func TestValidatePatches(t *testing.T) { clusterClass: clusterv1.ClusterClass{ Spec: clusterv1.ClusterClassSpec{ ControlPlane: clusterv1.ControlPlaneClass{ - ClusterClassTemplate: clusterv1.ClusterClassTemplate{ - Ref: &clusterv1.ClusterClassTemplateReference{ - APIVersion: clusterv1.GroupVersionControlPlane.String(), - Kind: "ControlPlaneTemplate", - }, + TemplateRef: clusterv1.ClusterClassTemplateReference{ + APIVersion: clusterv1.GroupVersionControlPlane.String(), + Kind: "ControlPlaneTemplate", }, }, diff --git a/internal/webhooks/test/clusterclass_test.go b/internal/webhooks/test/clusterclass_test.go index c6ff45d127d0..beb9304ba3d9 100644 --- a/internal/webhooks/test/clusterclass_test.go +++ b/internal/webhooks/test/clusterclass_test.go @@ -212,7 +212,7 @@ func TestClusterWebhook_Succeed_Update(t *testing.T) { actualClusterClass.Spec.Workers.MachineDeployments[1], } // Change the template used in the ClusterClass to a compatible alternative (Only name is changed). - actualClusterClass.Spec.Infrastructure.Ref.Name = infrastructureClusterTemplateName2 + actualClusterClass.Spec.Infrastructure.TemplateRef.Name = infrastructureClusterTemplateName2 // Attempt to update the ClusterClass with the above changes. // Expect no error here as the updates are compatible with the current Clusters using the ClusterClass. diff --git a/test/e2e/clusterclass_changes.go b/test/e2e/clusterclass_changes.go index ceea31cfcb2e..a4d095dd7d94 100644 --- a/test/e2e/clusterclass_changes.go +++ b/test/e2e/clusterclass_changes.go @@ -317,7 +317,7 @@ func modifyControlPlaneViaClusterClassAndWait(ctx context.Context, input modifyC log.Logf("Modifying the ControlPlaneTemplate of ClusterClass %s", klog.KObj(input.ClusterClass)) // Get ControlPlaneTemplate object. - controlPlaneTemplateRef := input.ClusterClass.Spec.ControlPlane.Ref + controlPlaneTemplateRef := &input.ClusterClass.Spec.ControlPlane.TemplateRef controlPlaneTemplate, err := external.Get(ctx, mgmtClient, controlPlaneTemplateRef.ToObjectReference(input.ClusterClass.Namespace)) Expect(err).ToNot(HaveOccurred()) @@ -448,31 +448,29 @@ func modifyMachineDeploymentViaClusterClassAndWait(ctx context.Context, input mo mgmtClient := input.ClusterProxy.GetClient() - for _, mdClass := range input.ClusterClass.Spec.Workers.MachineDeployments { + for i, mdClass := range input.ClusterClass.Spec.Workers.MachineDeployments { // Only try to modify the BootstrapConfigTemplate if the MachineDeploymentClass is using a BootstrapConfigTemplate. var newBootstrapConfigTemplateName string - if mdClass.Template.Bootstrap.Ref != nil { - log.Logf("Modifying the BootstrapConfigTemplate of MachineDeploymentClass %q of ClusterClass %s", mdClass.Class, klog.KObj(input.ClusterClass)) - - // Retrieve BootstrapConfigTemplate object. - bootstrapConfigTemplateRef := mdClass.Template.Bootstrap.Ref.ToObjectReference(input.ClusterClass.Namespace) - bootstrapConfigTemplate, err := external.Get(ctx, mgmtClient, bootstrapConfigTemplateRef) - Expect(err).ToNot(HaveOccurred()) - // Create a new BootstrapConfigTemplate object with a new name and ModifyBootstrapConfigTemplateFields set. - newBootstrapConfigTemplate := bootstrapConfigTemplate.DeepCopy() - newBootstrapConfigTemplateName = fmt.Sprintf("%s-%s", bootstrapConfigTemplateRef.Name, util.RandomString(6)) - newBootstrapConfigTemplate.SetName(newBootstrapConfigTemplateName) - newBootstrapConfigTemplate.SetResourceVersion("") - for fieldPath, value := range input.ModifyBootstrapConfigTemplateFields { - Expect(unstructured.SetNestedField(newBootstrapConfigTemplate.Object, value, strings.Split(fieldPath, ".")...)).To(Succeed()) - } - Expect(mgmtClient.Create(ctx, newBootstrapConfigTemplate)).To(Succeed()) + log.Logf("Modifying the BootstrapConfigTemplate of MachineDeploymentClass %q of ClusterClass %s", mdClass.Class, klog.KObj(input.ClusterClass)) + + // Retrieve BootstrapConfigTemplate object. + bootstrapConfigTemplateRef := mdClass.Template.Bootstrap.TemplateRef.ToObjectReference(input.ClusterClass.Namespace) + bootstrapConfigTemplate, err := external.Get(ctx, mgmtClient, bootstrapConfigTemplateRef) + Expect(err).ToNot(HaveOccurred()) + // Create a new BootstrapConfigTemplate object with a new name and ModifyBootstrapConfigTemplateFields set. + newBootstrapConfigTemplate := bootstrapConfigTemplate.DeepCopy() + newBootstrapConfigTemplateName = fmt.Sprintf("%s-%s", bootstrapConfigTemplateRef.Name, util.RandomString(6)) + newBootstrapConfigTemplate.SetName(newBootstrapConfigTemplateName) + newBootstrapConfigTemplate.SetResourceVersion("") + for fieldPath, value := range input.ModifyBootstrapConfigTemplateFields { + Expect(unstructured.SetNestedField(newBootstrapConfigTemplate.Object, value, strings.Split(fieldPath, ".")...)).To(Succeed()) } + Expect(mgmtClient.Create(ctx, newBootstrapConfigTemplate)).To(Succeed()) log.Logf("Modifying the InfrastructureMachineTemplate of MachineDeploymentClass %q of ClusterClass %s", mdClass.Class, klog.KObj(input.ClusterClass)) // Retrieve InfrastructureMachineTemplate object. - infrastructureMachineTemplateRef := mdClass.Template.Infrastructure.Ref.ToObjectReference(input.ClusterClass.Namespace) + infrastructureMachineTemplateRef := mdClass.Template.Infrastructure.TemplateRef.ToObjectReference(input.ClusterClass.Namespace) infrastructureMachineTemplate, err := external.Get(ctx, mgmtClient, infrastructureMachineTemplateRef) Expect(err).ToNot(HaveOccurred()) // Create a new InfrastructureMachineTemplate object with a new name and ModifyInfrastructureMachineTemplateFields set. @@ -488,10 +486,8 @@ func modifyMachineDeploymentViaClusterClassAndWait(ctx context.Context, input mo // Patch the refs of the MachineDeploymentClass to reference the new templates. patchHelper, err := patch.NewHelper(input.ClusterClass, mgmtClient) Expect(err).ToNot(HaveOccurred()) - if mdClass.Template.Bootstrap.Ref != nil { - mdClass.Template.Bootstrap.Ref.Name = newBootstrapConfigTemplateName - } - mdClass.Template.Infrastructure.Ref.Name = newInfrastructureMachineTemplateName + input.ClusterClass.Spec.Workers.MachineDeployments[i].Template.Bootstrap.TemplateRef.Name = newBootstrapConfigTemplateName + input.ClusterClass.Spec.Workers.MachineDeployments[i].Template.Infrastructure.TemplateRef.Name = newInfrastructureMachineTemplateName Expect(patchHelper.Patch(ctx, input.ClusterClass)).To(Succeed()) log.Logf("Waiting for MachineDeployment rollout for MachineDeploymentClass %q to complete.", mdClass.Class) @@ -516,19 +512,17 @@ func modifyMachineDeploymentViaClusterClassAndWait(ctx context.Context, input mo // Verify that the fields from Cluster topology are set on the MachineDeployment. assertMachineDeploymentTopologyFields(g, md, mdTopology) - if mdClass.Template.Bootstrap.Ref != nil { - // Get the corresponding BootstrapConfigTemplate. - bootstrapConfigTemplateRef := md.Spec.Template.Spec.Bootstrap.ConfigRef - bootstrapConfigTemplate, err := external.GetObjectFromContractVersionedRef(ctx, mgmtClient, bootstrapConfigTemplateRef, md.Namespace) - g.Expect(err).ToNot(HaveOccurred()) - - // Verify that ModifyBootstrapConfigTemplateFields have been set. - for fieldPath, expectedValue := range input.ModifyBootstrapConfigTemplateFields { - currentValue, ok, err := unstructured.NestedFieldNoCopy(bootstrapConfigTemplate.Object, strings.Split(fieldPath, ".")...) - g.Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to get field %q", fieldPath)) - g.Expect(ok).To(BeTrue(), fmt.Sprintf("failed to get field %q", fieldPath)) - g.Expect(currentValue).To(Equal(expectedValue), fmt.Sprintf("field %q should be equal", fieldPath)) - } + // Get the corresponding BootstrapConfigTemplate. + bootstrapConfigTemplateRef := md.Spec.Template.Spec.Bootstrap.ConfigRef + bootstrapConfigTemplate, err := external.GetObjectFromContractVersionedRef(ctx, mgmtClient, bootstrapConfigTemplateRef, md.Namespace) + g.Expect(err).ToNot(HaveOccurred()) + + // Verify that ModifyBootstrapConfigTemplateFields have been set. + for fieldPath, expectedValue := range input.ModifyBootstrapConfigTemplateFields { + currentValue, ok, err := unstructured.NestedFieldNoCopy(bootstrapConfigTemplate.Object, strings.Split(fieldPath, ".")...) + g.Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to get field %q", fieldPath)) + g.Expect(ok).To(BeTrue(), fmt.Sprintf("failed to get field %q", fieldPath)) + g.Expect(currentValue).To(Equal(expectedValue), fmt.Sprintf("field %q should be equal", fieldPath)) } // Get the corresponding InfrastructureMachineTemplate. @@ -570,31 +564,29 @@ func modifyMachinePoolViaClusterClassAndWait(ctx context.Context, input modifyMa mgmtClient := input.ClusterProxy.GetClient() - for _, mpClass := range input.ClusterClass.Spec.Workers.MachinePools { + for i, mpClass := range input.ClusterClass.Spec.Workers.MachinePools { // Only try to modify the BootstrapConfigTemplate if the MachinePoolClass is using a BootstrapConfigTemplate. var newBootstrapConfigTemplateName string - if mpClass.Template.Bootstrap.Ref != nil { - log.Logf("Modifying the BootstrapConfigTemplate of MachinePoolClass %q of ClusterClass %s", mpClass.Class, klog.KObj(input.ClusterClass)) - - // Retrieve BootstrapConfigTemplate object. - bootstrapConfigTemplateRef := mpClass.Template.Bootstrap.Ref.ToObjectReference(input.ClusterClass.Namespace) - bootstrapConfigTemplate, err := external.Get(ctx, mgmtClient, bootstrapConfigTemplateRef) - Expect(err).ToNot(HaveOccurred()) - // Create a new BootstrapConfigTemplate object with a new name and ModifyBootstrapConfigTemplateFields set. - newBootstrapConfigTemplate := bootstrapConfigTemplate.DeepCopy() - newBootstrapConfigTemplateName = fmt.Sprintf("%s-%s", bootstrapConfigTemplateRef.Name, util.RandomString(6)) - newBootstrapConfigTemplate.SetName(newBootstrapConfigTemplateName) - newBootstrapConfigTemplate.SetResourceVersion("") - for fieldPath, value := range input.ModifyBootstrapConfigTemplateFields { - Expect(unstructured.SetNestedField(newBootstrapConfigTemplate.Object, value, strings.Split(fieldPath, ".")...)).To(Succeed()) - } - Expect(mgmtClient.Create(ctx, newBootstrapConfigTemplate)).To(Succeed()) + log.Logf("Modifying the BootstrapConfigTemplate of MachinePoolClass %q of ClusterClass %s", mpClass.Class, klog.KObj(input.ClusterClass)) + + // Retrieve BootstrapConfigTemplate object. + bootstrapConfigTemplateRef := mpClass.Template.Bootstrap.TemplateRef.ToObjectReference(input.ClusterClass.Namespace) + bootstrapConfigTemplate, err := external.Get(ctx, mgmtClient, bootstrapConfigTemplateRef) + Expect(err).ToNot(HaveOccurred()) + // Create a new BootstrapConfigTemplate object with a new name and ModifyBootstrapConfigTemplateFields set. + newBootstrapConfigTemplate := bootstrapConfigTemplate.DeepCopy() + newBootstrapConfigTemplateName = fmt.Sprintf("%s-%s", bootstrapConfigTemplateRef.Name, util.RandomString(6)) + newBootstrapConfigTemplate.SetName(newBootstrapConfigTemplateName) + newBootstrapConfigTemplate.SetResourceVersion("") + for fieldPath, value := range input.ModifyBootstrapConfigTemplateFields { + Expect(unstructured.SetNestedField(newBootstrapConfigTemplate.Object, value, strings.Split(fieldPath, ".")...)).To(Succeed()) } + Expect(mgmtClient.Create(ctx, newBootstrapConfigTemplate)).To(Succeed()) log.Logf("Modifying the InfrastructureMachinePoolTemplate of MachinePoolClass %q of ClusterClass %s", mpClass.Class, klog.KObj(input.ClusterClass)) // Retrieve InfrastructureMachineTemplate object. - infrastructureMachinePoolTemplateRef := mpClass.Template.Infrastructure.Ref.ToObjectReference(input.ClusterClass.Namespace) + infrastructureMachinePoolTemplateRef := mpClass.Template.Infrastructure.TemplateRef.ToObjectReference(input.ClusterClass.Namespace) infrastructureMachinePoolTemplate, err := external.Get(ctx, mgmtClient, infrastructureMachinePoolTemplateRef) Expect(err).ToNot(HaveOccurred()) // Create a new InfrastructureMachinePoolTemplate object with a new name and ModifyInfrastructureMachinePoolTemplateFields set. @@ -610,10 +602,8 @@ func modifyMachinePoolViaClusterClassAndWait(ctx context.Context, input modifyMa // Patch the refs of the MachinePoolClass to reference the new templates. patchHelper, err := patch.NewHelper(input.ClusterClass, mgmtClient) Expect(err).ToNot(HaveOccurred()) - if mpClass.Template.Bootstrap.Ref != nil { - mpClass.Template.Bootstrap.Ref.Name = newBootstrapConfigTemplateName - } - mpClass.Template.Infrastructure.Ref.Name = newInfrastructureMachinePoolTemplateName + input.ClusterClass.Spec.Workers.MachinePools[i].Template.Bootstrap.TemplateRef.Name = newBootstrapConfigTemplateName + input.ClusterClass.Spec.Workers.MachinePools[i].Template.Infrastructure.TemplateRef.Name = newInfrastructureMachinePoolTemplateName Expect(patchHelper.Patch(ctx, input.ClusterClass)).To(Succeed()) log.Logf("Waiting for MachinePool rollout for MachinePoolClass %q to complete.", mpClass.Class) @@ -638,21 +628,19 @@ func modifyMachinePoolViaClusterClassAndWait(ctx context.Context, input modifyMa // Verify that the fields from Cluster topology are set on the MachinePool. assertMachinePoolTopologyFields(g, mp, mpTopology) - if mpClass.Template.Bootstrap.Ref != nil { - // Get the corresponding BootstrapConfig object. - bootstrapConfigObjectRef := mp.Spec.Template.Spec.Bootstrap.ConfigRef - bootstrapConfigObject, err := external.GetObjectFromContractVersionedRef(ctx, mgmtClient, bootstrapConfigObjectRef, mp.Namespace) - g.Expect(err).ToNot(HaveOccurred()) - - // Verify that ModifyBootstrapConfigTemplateFields have been set and propagates to the BootstrapConfig. - for fieldPath, expectedValue := range input.ModifyBootstrapConfigTemplateFields { - // MachinePools have a BootstrapConfig, not a BootstrapConfigTemplate, so we need to convert the fieldPath so it can find it on the object. - fieldPath = strings.TrimPrefix(fieldPath, "spec.template.") - currentValue, ok, err := unstructured.NestedFieldNoCopy(bootstrapConfigObject.Object, strings.Split(fieldPath, ".")...) - g.Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to get field %q", fieldPath)) - g.Expect(ok).To(BeTrue(), fmt.Sprintf("failed to get field %q", fieldPath)) - g.Expect(currentValue).To(Equal(expectedValue), fmt.Sprintf("field %q should be equal", fieldPath)) - } + // Get the corresponding BootstrapConfig object. + bootstrapConfigObjectRef := mp.Spec.Template.Spec.Bootstrap.ConfigRef + bootstrapConfigObject, err := external.GetObjectFromContractVersionedRef(ctx, mgmtClient, bootstrapConfigObjectRef, mp.Namespace) + g.Expect(err).ToNot(HaveOccurred()) + + // Verify that ModifyBootstrapConfigTemplateFields have been set and propagates to the BootstrapConfig. + for fieldPath, expectedValue := range input.ModifyBootstrapConfigTemplateFields { + // MachinePools have a BootstrapConfig, not a BootstrapConfigTemplate, so we need to convert the fieldPath so it can find it on the object. + fieldPath = strings.TrimPrefix(fieldPath, "spec.template.") + currentValue, ok, err := unstructured.NestedFieldNoCopy(bootstrapConfigObject.Object, strings.Split(fieldPath, ".")...) + g.Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to get field %q", fieldPath)) + g.Expect(ok).To(BeTrue(), fmt.Sprintf("failed to get field %q", fieldPath)) + g.Expect(currentValue).To(Equal(expectedValue), fmt.Sprintf("field %q should be equal", fieldPath)) } // Get the corresponding InfrastructureMachinePoolTemplate. @@ -793,20 +781,20 @@ func rebaseClusterClassAndWait(ctx context.Context, input rebaseClusterClassAndW // Copy ClusterClass templates to the new namespace for i, mdClass := range newClusterClass.Spec.Workers.MachineDeployments { - cloneTemplateAndUpdateRef(ctx, mgmtClient, &mdClass.Template.Infrastructure, input.ClusterClass.Namespace, input.ClusterClassNamespace) - cloneTemplateAndUpdateRef(ctx, mgmtClient, &mdClass.Template.Bootstrap, input.ClusterClass.Namespace, input.ClusterClassNamespace) + cloneTemplateAndUpdateRef(ctx, mgmtClient, &mdClass.Template.Infrastructure.TemplateRef, input.ClusterClass.Namespace, input.ClusterClassNamespace) + cloneTemplateAndUpdateRef(ctx, mgmtClient, &mdClass.Template.Bootstrap.TemplateRef, input.ClusterClass.Namespace, input.ClusterClassNamespace) newClusterClass.Spec.Workers.MachineDeployments[i] = mdClass } for i, mpClass := range newClusterClass.Spec.Workers.MachinePools { - cloneTemplateAndUpdateRef(ctx, mgmtClient, &mpClass.Template.Infrastructure, input.ClusterClass.Namespace, input.ClusterClassNamespace) - cloneTemplateAndUpdateRef(ctx, mgmtClient, &mpClass.Template.Bootstrap, input.ClusterClass.Namespace, input.ClusterClassNamespace) + cloneTemplateAndUpdateRef(ctx, mgmtClient, &mpClass.Template.Infrastructure.TemplateRef, input.ClusterClass.Namespace, input.ClusterClassNamespace) + cloneTemplateAndUpdateRef(ctx, mgmtClient, &mpClass.Template.Bootstrap.TemplateRef, input.ClusterClass.Namespace, input.ClusterClassNamespace) newClusterClass.Spec.Workers.MachinePools[i] = mpClass } - cloneTemplateAndUpdateRef(ctx, mgmtClient, newClusterClass.Spec.ControlPlane.MachineInfrastructure, input.ClusterClass.Namespace, input.ClusterClassNamespace) - cloneTemplateAndUpdateRef(ctx, mgmtClient, &newClusterClass.Spec.ControlPlane.ClusterClassTemplate, input.ClusterClass.Namespace, input.ClusterClassNamespace) - cloneTemplateAndUpdateRef(ctx, mgmtClient, &newClusterClass.Spec.Infrastructure.ClusterClassTemplate, input.ClusterClass.Namespace, input.ClusterClassNamespace) + cloneTemplateAndUpdateRef(ctx, mgmtClient, &newClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef, input.ClusterClass.Namespace, input.ClusterClassNamespace) + cloneTemplateAndUpdateRef(ctx, mgmtClient, &newClusterClass.Spec.ControlPlane.TemplateRef, input.ClusterClass.Namespace, input.ClusterClassNamespace) + cloneTemplateAndUpdateRef(ctx, mgmtClient, &newClusterClass.Spec.Infrastructure.TemplateRef, input.ClusterClass.Namespace, input.ClusterClassNamespace) Expect(mgmtClient.Create(ctx, newClusterClass)).To(Succeed()) @@ -894,12 +882,8 @@ func rebaseClusterClassAndWait(ctx context.Context, input rebaseClusterClassAndW } // cloneTemplateAndUpdateRef performs required modifications to avoid conflict, and create a copy of the referenced object, updating the ref in-place. -func cloneTemplateAndUpdateRef(ctx context.Context, cl client.Client, template *clusterv1.ClusterClassTemplate, currentNamespace, targetNamespace string) { - if template == nil || template.Ref == nil { - return - } - - templateObject, err := external.Get(ctx, cl, template.Ref.ToObjectReference(currentNamespace)) +func cloneTemplateAndUpdateRef(ctx context.Context, cl client.Client, templateRef *clusterv1.ClusterClassTemplateReference, currentNamespace, targetNamespace string) { + templateObject, err := external.Get(ctx, cl, templateRef.ToObjectReference(currentNamespace)) Expect(err).ToNot(HaveOccurred()) if targetNamespace != "" { templateObject.SetNamespace(targetNamespace) @@ -911,7 +895,7 @@ func cloneTemplateAndUpdateRef(ctx context.Context, cl client.Client, template * templateObject.SetOwnerReferences(nil) Expect(cl.Create(ctx, templateObject)).To(Succeed()) - template.Ref = &clusterv1.ClusterClassTemplateReference{ + *templateRef = clusterv1.ClusterClassTemplateReference{ Kind: templateObject.GetKind(), Name: templateObject.GetName(), APIVersion: templateObject.GetAPIVersion(), diff --git a/test/e2e/clusterclass_rollout.go b/test/e2e/clusterclass_rollout.go index cd6f5c101bd7..d64fd480aff7 100644 --- a/test/e2e/clusterclass_rollout.go +++ b/test/e2e/clusterclass_rollout.go @@ -357,8 +357,8 @@ func assertInfrastructureCluster(g Gomega, clusterClassObjects clusterClassObjec expectMapsToBeEquivalent(g, clusterObjects.InfrastructureCluster.GetAnnotations(), union( map[string]string{ - clusterv1.TemplateClonedFromGroupKindAnnotation: clusterClass.Spec.Infrastructure.Ref.GroupVersionKind().GroupKind().String(), - clusterv1.TemplateClonedFromNameAnnotation: clusterClass.Spec.Infrastructure.Ref.Name, + clusterv1.TemplateClonedFromGroupKindAnnotation: clusterClass.Spec.Infrastructure.TemplateRef.GroupVersionKind().GroupKind().String(), + clusterv1.TemplateClonedFromNameAnnotation: clusterClass.Spec.Infrastructure.TemplateRef.Name, }, ccInfrastructureClusterTemplateTemplateMetadata.Annotations, ), @@ -387,8 +387,8 @@ func assertControlPlane(g Gomega, clusterClassObjects clusterClassObjects, clust expectMapsToBeEquivalent(g, clusterObjects.ControlPlane.GetAnnotations(), union( map[string]string{ - clusterv1.TemplateClonedFromGroupKindAnnotation: clusterClass.Spec.ControlPlane.Ref.GroupVersionKind().GroupKind().String(), - clusterv1.TemplateClonedFromNameAnnotation: clusterClass.Spec.ControlPlane.Ref.Name, + clusterv1.TemplateClonedFromGroupKindAnnotation: clusterClass.Spec.ControlPlane.TemplateRef.GroupVersionKind().GroupKind().String(), + clusterv1.TemplateClonedFromNameAnnotation: clusterClass.Spec.ControlPlane.TemplateRef.Name, }, cluster.Spec.Topology.ControlPlane.Metadata.Annotations, clusterClass.Spec.ControlPlane.Metadata.Annotations, @@ -432,8 +432,8 @@ func assertControlPlane(g Gomega, clusterClassObjects clusterClassObjects, clust expectMapsToBeEquivalent(g, clusterObjects.ControlPlaneInfrastructureMachineTemplate.GetAnnotations(), union( map[string]string{ - clusterv1.TemplateClonedFromGroupKindAnnotation: clusterClass.Spec.ControlPlane.MachineInfrastructure.Ref.GroupVersionKind().GroupKind().String(), - clusterv1.TemplateClonedFromNameAnnotation: clusterClass.Spec.ControlPlane.MachineInfrastructure.Ref.Name, + clusterv1.TemplateClonedFromGroupKindAnnotation: clusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef.GroupVersionKind().GroupKind().String(), + clusterv1.TemplateClonedFromNameAnnotation: clusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef.Name, }, clusterClassObjects.ControlPlaneInfrastructureMachineTemplate.GetAnnotations(), ), @@ -623,8 +623,8 @@ func assertMachineDeployments(g Gomega, clusterClassObjects clusterClassObjects, expectMapsToBeEquivalent(g, infrastructureMachineTemplate.GetAnnotations(), union( map[string]string{ - clusterv1.TemplateClonedFromGroupKindAnnotation: mdClass.Template.Infrastructure.Ref.GroupVersionKind().GroupKind().String(), - clusterv1.TemplateClonedFromNameAnnotation: mdClass.Template.Infrastructure.Ref.Name, + clusterv1.TemplateClonedFromGroupKindAnnotation: mdClass.Template.Infrastructure.TemplateRef.GroupVersionKind().GroupKind().String(), + clusterv1.TemplateClonedFromNameAnnotation: mdClass.Template.Infrastructure.TemplateRef.Name, }, ccInfrastructureMachineTemplate.GetAnnotations(), ), @@ -655,8 +655,8 @@ func assertMachineDeployments(g Gomega, clusterClassObjects clusterClassObjects, expectMapsToBeEquivalent(g, bootstrapConfigTemplate.GetAnnotations(), union( map[string]string{ - clusterv1.TemplateClonedFromGroupKindAnnotation: mdClass.Template.Bootstrap.Ref.GroupVersionKind().GroupKind().String(), - clusterv1.TemplateClonedFromNameAnnotation: mdClass.Template.Bootstrap.Ref.Name, + clusterv1.TemplateClonedFromGroupKindAnnotation: mdClass.Template.Bootstrap.TemplateRef.GroupVersionKind().GroupKind().String(), + clusterv1.TemplateClonedFromNameAnnotation: mdClass.Template.Bootstrap.TemplateRef.Name, }, ccBootstrapConfigTemplate.GetAnnotations(), ), @@ -734,8 +734,8 @@ func assertMachinePools(g Gomega, clusterClassObjects clusterClassObjects, clust expectMapsToBeEquivalent(g, infrastructureMachinePool.GetAnnotations(), union( map[string]string{ - clusterv1.TemplateClonedFromGroupKindAnnotation: mpClass.Template.Infrastructure.Ref.GroupVersionKind().GroupKind().String(), - clusterv1.TemplateClonedFromNameAnnotation: mpClass.Template.Infrastructure.Ref.Name, + clusterv1.TemplateClonedFromGroupKindAnnotation: mpClass.Template.Infrastructure.TemplateRef.GroupVersionKind().GroupKind().String(), + clusterv1.TemplateClonedFromNameAnnotation: mpClass.Template.Infrastructure.TemplateRef.Name, }, ccInfrastructureMachinePoolTemplateTemplateMetadata.Annotations, ), @@ -758,8 +758,8 @@ func assertMachinePools(g Gomega, clusterClassObjects clusterClassObjects, clust expectMapsToBeEquivalent(g, bootstrapConfig.GetAnnotations(), union( map[string]string{ - clusterv1.TemplateClonedFromGroupKindAnnotation: mpClass.Template.Bootstrap.Ref.GroupVersionKind().GroupKind().String(), - clusterv1.TemplateClonedFromNameAnnotation: mpClass.Template.Bootstrap.Ref.Name, + clusterv1.TemplateClonedFromGroupKindAnnotation: mpClass.Template.Bootstrap.TemplateRef.GroupVersionKind().GroupKind().String(), + clusterv1.TemplateClonedFromNameAnnotation: mpClass.Template.Bootstrap.TemplateRef.Name, }, ccBootstrapConfigTemplateTemplateMetadata.Annotations, ), @@ -1058,31 +1058,31 @@ func getClusterClassObjects(ctx context.Context, g Gomega, clusterProxy framewor } var err error - res.InfrastructureClusterTemplate, err = external.Get(ctx, mgmtClient, clusterClass.Spec.Infrastructure.Ref.ToObjectReference(clusterClass.Namespace)) + res.InfrastructureClusterTemplate, err = external.Get(ctx, mgmtClient, clusterClass.Spec.Infrastructure.TemplateRef.ToObjectReference(clusterClass.Namespace)) g.Expect(err).ToNot(HaveOccurred()) - res.ControlPlaneTemplate, err = external.Get(ctx, mgmtClient, clusterClass.Spec.ControlPlane.Ref.ToObjectReference(clusterClass.Namespace)) + res.ControlPlaneTemplate, err = external.Get(ctx, mgmtClient, clusterClass.Spec.ControlPlane.TemplateRef.ToObjectReference(clusterClass.Namespace)) g.Expect(err).ToNot(HaveOccurred()) - res.ControlPlaneInfrastructureMachineTemplate, err = external.Get(ctx, mgmtClient, clusterClass.Spec.ControlPlane.MachineInfrastructure.Ref.ToObjectReference(clusterClass.Namespace)) + res.ControlPlaneInfrastructureMachineTemplate, err = external.Get(ctx, mgmtClient, clusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef.ToObjectReference(clusterClass.Namespace)) g.Expect(err).ToNot(HaveOccurred()) for _, mdClass := range clusterClass.Spec.Workers.MachineDeployments { - infrastructureMachineTemplate, err := external.Get(ctx, mgmtClient, mdClass.Template.Infrastructure.Ref.ToObjectReference(clusterClass.Namespace)) + infrastructureMachineTemplate, err := external.Get(ctx, mgmtClient, mdClass.Template.Infrastructure.TemplateRef.ToObjectReference(clusterClass.Namespace)) g.Expect(err).ToNot(HaveOccurred()) res.InfrastructureMachineTemplateByMachineDeploymentClass[mdClass.Class] = infrastructureMachineTemplate - bootstrapConfigTemplate, err := external.Get(ctx, mgmtClient, mdClass.Template.Bootstrap.Ref.ToObjectReference(clusterClass.Namespace)) + bootstrapConfigTemplate, err := external.Get(ctx, mgmtClient, mdClass.Template.Bootstrap.TemplateRef.ToObjectReference(clusterClass.Namespace)) g.Expect(err).ToNot(HaveOccurred()) res.BootstrapConfigTemplateByMachineDeploymentClass[mdClass.Class] = bootstrapConfigTemplate } for _, mpClass := range clusterClass.Spec.Workers.MachinePools { - infrastructureMachinePoolTemplate, err := external.Get(ctx, mgmtClient, mpClass.Template.Infrastructure.Ref.ToObjectReference(clusterClass.Namespace)) + infrastructureMachinePoolTemplate, err := external.Get(ctx, mgmtClient, mpClass.Template.Infrastructure.TemplateRef.ToObjectReference(clusterClass.Namespace)) g.Expect(err).ToNot(HaveOccurred()) res.InfrastructureMachinePoolTemplateByMachinePoolClass[mpClass.Class] = infrastructureMachinePoolTemplate - bootstrapConfigTemplate, err := external.Get(ctx, mgmtClient, mpClass.Template.Bootstrap.Ref.ToObjectReference(clusterClass.Namespace)) + bootstrapConfigTemplate, err := external.Get(ctx, mgmtClient, mpClass.Template.Bootstrap.TemplateRef.ToObjectReference(clusterClass.Namespace)) g.Expect(err).ToNot(HaveOccurred()) res.BootstrapConfigTemplateByMachinePoolClass[mpClass.Class] = bootstrapConfigTemplate } diff --git a/test/e2e/scale.go b/test/e2e/scale.go index 8f25acb0d454..f298d2e3be18 100644 --- a/test/e2e/scale.go +++ b/test/e2e/scale.go @@ -41,6 +41,8 @@ import ( "k8s.io/klog/v2" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/apiutil" + "sigs.k8s.io/yaml" controlplanev1 "sigs.k8s.io/cluster-api/api/controlplane/kubeadm/v1beta2" clusterv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" @@ -48,7 +50,7 @@ import ( "sigs.k8s.io/cluster-api/test/e2e/internal/log" "sigs.k8s.io/cluster-api/test/framework" "sigs.k8s.io/cluster-api/test/framework/clusterctl" - "sigs.k8s.io/cluster-api/util/yaml" + utilyaml "sigs.k8s.io/cluster-api/util/yaml" ) const ( @@ -524,7 +526,7 @@ func ScaleSpec(ctx context.Context, inputGetter func() ScaleSpecInput) { } func extractClusterClassAndClusterFromTemplate(rawYAML []byte) ([]byte, []byte) { - objs, err := yaml.ToUnstructured(rawYAML) + objs, err := utilyaml.ToUnstructured(rawYAML) Expect(err).ToNot(HaveOccurred()) clusterObj := unstructured.Unstructured{} clusterClassAndTemplates := []unstructured.Unstructured{} @@ -535,9 +537,9 @@ func extractClusterClassAndClusterFromTemplate(rawYAML []byte) ([]byte, []byte) clusterClassAndTemplates = append(clusterClassAndTemplates, obj) } } - clusterYAML, err := yaml.FromUnstructured([]unstructured.Unstructured{clusterObj}) + clusterYAML, err := utilyaml.FromUnstructured([]unstructured.Unstructured{clusterObj}) Expect(err).ToNot(HaveOccurred()) - clusterClassYAML, err := yaml.FromUnstructured(clusterClassAndTemplates) + clusterClassYAML, err := utilyaml.FromUnstructured(clusterClassAndTemplates) Expect(err).ToNot(HaveOccurred()) return clusterClassYAML, clusterYAML } @@ -940,7 +942,7 @@ func modifyMachineDeployments(baseClusterTemplateYAML []byte, count int64) []byt Expect(baseClusterTemplateYAML).NotTo(BeEmpty(), "Invalid argument. baseClusterTemplateYAML cannot be empty when calling modifyMachineDeployments") Expect(count).To(BeNumerically(">=", 0), "Invalid argument. count cannot be less than 0 when calling modifyMachineDeployments") - objs, err := yaml.ToUnstructured(baseClusterTemplateYAML) + objs, err := utilyaml.ToUnstructured(baseClusterTemplateYAML) Expect(err).ToNot(HaveOccurred()) Expect(objs).To(HaveLen(1), "Unexpected number of objects found in baseClusterTemplateYAML") @@ -970,9 +972,11 @@ func modifyMachineDeployments(baseClusterTemplateYAML []byte, count int64) []byt allMDs[i-1] = *md } cluster.Spec.Topology.Workers.MachineDeployments = allMDs - u := &unstructured.Unstructured{} - Expect(scheme.Convert(cluster, u, nil)).To(Succeed()) - modifiedClusterYAML, err := yaml.FromUnstructured([]unstructured.Unstructured{*u}) + // Note: We have to set GVK here explicitly otherwise apiVersion + kind won't be set in the YAML. + gvk, err := apiutil.GVKForObject(cluster, scheme) + Expect(err).ToNot(HaveOccurred()) + cluster.SetGroupVersionKind(gvk) + modifiedClusterYAML, err := yaml.Marshal(cluster) Expect(err).ToNot(HaveOccurred()) return modifiedClusterYAML diff --git a/test/extension/handlers/topologymutation/handler_integration_test.go b/test/extension/handlers/topologymutation/handler_integration_test.go index 80a42e43a188..c95a91b0b930 100644 --- a/test/extension/handlers/topologymutation/handler_integration_test.go +++ b/test/extension/handlers/topologymutation/handler_integration_test.go @@ -263,7 +263,7 @@ func getScope(cluster *clusterv1.Cluster, clusterClassFile string) (*scope.Scope // Get ClusterClass and referenced templates. // ClusterClass - s.Blueprint.ClusterClass = mustFind(findObject[*clusterv1.ClusterClass](parsedObjects, &clusterv1.ClusterClassTemplateReference{ + s.Blueprint.ClusterClass = mustFind(findObject[*clusterv1.ClusterClass](parsedObjects, clusterv1.ClusterClassTemplateReference{ Kind: "ClusterClass", })) // Set paused condition for ClusterClass @@ -274,12 +274,12 @@ func getScope(cluster *clusterv1.Cluster, clusterClassFile string) (*scope.Scope ObservedGeneration: s.Blueprint.ClusterClass.GetGeneration(), }) // InfrastructureClusterTemplate - s.Blueprint.InfrastructureClusterTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, s.Blueprint.ClusterClass.Spec.Infrastructure.Ref)) + s.Blueprint.InfrastructureClusterTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, s.Blueprint.ClusterClass.Spec.Infrastructure.TemplateRef)) // ControlPlane - s.Blueprint.ControlPlane.Template = mustFind(findObject[*unstructured.Unstructured](parsedObjects, s.Blueprint.ClusterClass.Spec.ControlPlane.Ref)) + s.Blueprint.ControlPlane.Template = mustFind(findObject[*unstructured.Unstructured](parsedObjects, s.Blueprint.ClusterClass.Spec.ControlPlane.TemplateRef)) if s.Blueprint.HasControlPlaneInfrastructureMachine() { - s.Blueprint.ControlPlane.InfrastructureMachineTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, s.Blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.Ref)) + s.Blueprint.ControlPlane.InfrastructureMachineTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, s.Blueprint.ClusterClass.Spec.ControlPlane.MachineInfrastructure.TemplateRef)) } if s.Blueprint.HasControlPlaneMachineHealthCheck() { s.Blueprint.ControlPlane.MachineHealthCheck = s.Blueprint.ClusterClass.Spec.ControlPlane.MachineHealthCheck @@ -289,8 +289,8 @@ func getScope(cluster *clusterv1.Cluster, clusterClassFile string) (*scope.Scope for _, machineDeploymentClass := range s.Blueprint.ClusterClass.Spec.Workers.MachineDeployments { machineDeploymentBlueprint := &scope.MachineDeploymentBlueprint{} machineDeploymentClass.Template.Metadata.DeepCopyInto(&machineDeploymentBlueprint.Metadata) - machineDeploymentBlueprint.InfrastructureMachineTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, machineDeploymentClass.Template.Infrastructure.Ref)) - machineDeploymentBlueprint.BootstrapTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, machineDeploymentClass.Template.Bootstrap.Ref)) + machineDeploymentBlueprint.InfrastructureMachineTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, machineDeploymentClass.Template.Infrastructure.TemplateRef)) + machineDeploymentBlueprint.BootstrapTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, machineDeploymentClass.Template.Bootstrap.TemplateRef)) if machineDeploymentClass.MachineHealthCheck != nil { machineDeploymentBlueprint.MachineHealthCheck = machineDeploymentClass.MachineHealthCheck } @@ -301,8 +301,8 @@ func getScope(cluster *clusterv1.Cluster, clusterClassFile string) (*scope.Scope for _, machinePoolClass := range s.Blueprint.ClusterClass.Spec.Workers.MachinePools { machinePoolBlueprint := &scope.MachinePoolBlueprint{} machinePoolClass.Template.Metadata.DeepCopyInto(&machinePoolBlueprint.Metadata) - machinePoolBlueprint.InfrastructureMachinePoolTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, machinePoolClass.Template.Infrastructure.Ref)) - machinePoolBlueprint.BootstrapTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, machinePoolClass.Template.Bootstrap.Ref)) + machinePoolBlueprint.InfrastructureMachinePoolTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, machinePoolClass.Template.Infrastructure.TemplateRef)) + machinePoolBlueprint.BootstrapTemplate = mustFind(findObject[*unstructured.Unstructured](parsedObjects, machinePoolClass.Template.Bootstrap.TemplateRef)) s.Blueprint.MachinePools[machinePoolClass.Class] = machinePoolBlueprint } @@ -374,7 +374,7 @@ func mustFind[K runtime.Object](obj K, err error) K { } // findObject looks up an object with the given groupVersionKindName in the given objects map. -func findObject[K runtime.Object](objects map[clusterv1.ClusterClassTemplateReference]runtime.Object, groupVersionKindName *clusterv1.ClusterClassTemplateReference) (K, error) { +func findObject[K runtime.Object](objects map[clusterv1.ClusterClassTemplateReference]runtime.Object, groupVersionKindName clusterv1.ClusterClassTemplateReference) (K, error) { var res K var alreadyFound bool for gvkn, obj := range objects { diff --git a/test/extension/handlers/topologymutation/testdata/clusterclass-quick-start-runtimesdk.yaml b/test/extension/handlers/topologymutation/testdata/clusterclass-quick-start-runtimesdk.yaml index 967fd8c61682..114a3c3a895f 100644 --- a/test/extension/handlers/topologymutation/testdata/clusterclass-quick-start-runtimesdk.yaml +++ b/test/extension/handlers/topologymutation/testdata/clusterclass-quick-start-runtimesdk.yaml @@ -4,19 +4,19 @@ metadata: name: quick-start-runtimesdk spec: controlPlane: - ref: + templateRef: apiVersion: controlplane.cluster.x-k8s.io/v1beta1 kind: KubeadmControlPlaneTemplate name: quick-start-control-plane machineInfrastructure: - ref: + templateRef: kind: DockerMachineTemplate apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 name: quick-start-control-plane namingStrategy: template: "{{ .cluster.name }}-cp-{{ .random }}" infrastructure: - ref: + templateRef: apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 kind: DockerClusterTemplate name: quick-start-cluster @@ -27,12 +27,12 @@ spec: template: "{{ .cluster.name }}-md-{{ .machineDeployment.topologyName }}-{{ .random }}" template: bootstrap: - ref: + templateRef: apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 kind: KubeadmConfigTemplate name: quick-start-default-worker-bootstraptemplate infrastructure: - ref: + templateRef: apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 kind: DockerMachineTemplate name: quick-start-default-worker-machinetemplate @@ -42,12 +42,12 @@ spec: template: "{{ .cluster.name }}-mp-{{ .machinePool.topologyName }}-{{ .random }}" template: bootstrap: - ref: + templateRef: apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 kind: KubeadmConfigTemplate name: quick-start-default-worker-bootstraptemplate infrastructure: - ref: + templateRef: apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 kind: DockerMachinePoolTemplate name: quick-start-default-worker-machinepooltemplate diff --git a/test/infrastructure/docker/api/v1beta2/devclustertemplate_types.go b/test/infrastructure/docker/api/v1beta2/devclustertemplate_types.go index 14b829e677fa..4593d26b0dbb 100644 --- a/test/infrastructure/docker/api/v1beta2/devclustertemplate_types.go +++ b/test/infrastructure/docker/api/v1beta2/devclustertemplate_types.go @@ -58,6 +58,6 @@ type DevClusterTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` Spec DevClusterSpec `json:"spec"` } diff --git a/test/infrastructure/docker/api/v1beta2/devmachinetemplate_types.go b/test/infrastructure/docker/api/v1beta2/devmachinetemplate_types.go index 67612fbc1e9e..41a9a68d98eb 100644 --- a/test/infrastructure/docker/api/v1beta2/devmachinetemplate_types.go +++ b/test/infrastructure/docker/api/v1beta2/devmachinetemplate_types.go @@ -58,7 +58,7 @@ type DevMachineTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // Spec is the specification of the desired behavior of the machine. Spec DevMachineSpec `json:"spec"` diff --git a/test/infrastructure/docker/api/v1beta2/dockerclustertemplate_types.go b/test/infrastructure/docker/api/v1beta2/dockerclustertemplate_types.go index 06d678f6c028..2381870717d3 100644 --- a/test/infrastructure/docker/api/v1beta2/dockerclustertemplate_types.go +++ b/test/infrastructure/docker/api/v1beta2/dockerclustertemplate_types.go @@ -58,6 +58,6 @@ type DockerClusterTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` Spec DockerClusterSpec `json:"spec"` } diff --git a/test/infrastructure/docker/api/v1beta2/dockermachinetemplate_types.go b/test/infrastructure/docker/api/v1beta2/dockermachinetemplate_types.go index 51077e462a75..78142a6ec0d4 100644 --- a/test/infrastructure/docker/api/v1beta2/dockermachinetemplate_types.go +++ b/test/infrastructure/docker/api/v1beta2/dockermachinetemplate_types.go @@ -58,7 +58,7 @@ type DockerMachineTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` // Spec is the specification of the desired behavior of the machine. Spec DockerMachineSpec `json:"spec"` } diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_devclustertemplates.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_devclustertemplates.yaml index cc4eaf02295d..0a15f1e9c3c0 100644 --- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_devclustertemplates.yaml +++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_devclustertemplates.yaml @@ -222,6 +222,7 @@ spec: description: |- Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_devmachinetemplates.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_devmachinetemplates.yaml index 7146ecde6e64..8729ca7fe695 100644 --- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_devmachinetemplates.yaml +++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_devmachinetemplates.yaml @@ -290,6 +290,7 @@ spec: description: |- Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml index e9eb27d6c5e5..4507e72ec59f 100644 --- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml +++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockerclustertemplates.yaml @@ -312,6 +312,7 @@ spec: description: |- Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepooltemplates.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepooltemplates.yaml index 35aecb27d688..dad1e20a6489 100644 --- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepooltemplates.yaml +++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinepooltemplates.yaml @@ -182,6 +182,7 @@ spec: description: |- Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinetemplates.yaml b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinetemplates.yaml index 2f636ec7eaaa..4adb7d83d384 100644 --- a/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinetemplates.yaml +++ b/test/infrastructure/docker/config/crd/bases/infrastructure.cluster.x-k8s.io_dockermachinetemplates.yaml @@ -370,6 +370,7 @@ spec: description: |- Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + minProperties: 1 properties: annotations: additionalProperties: diff --git a/test/infrastructure/docker/exp/api/v1beta2/dockermachinepooltemplate_types.go b/test/infrastructure/docker/exp/api/v1beta2/dockermachinepooltemplate_types.go index cee6e037c14e..160f0230b976 100644 --- a/test/infrastructure/docker/exp/api/v1beta2/dockermachinepooltemplate_types.go +++ b/test/infrastructure/docker/exp/api/v1beta2/dockermachinepooltemplate_types.go @@ -58,7 +58,7 @@ type DockerMachinePoolTemplateResource struct { // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional - ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty"` + ObjectMeta clusterv1.ObjectMeta `json:"metadata,omitempty,omitzero"` Spec DockerMachinePoolSpec `json:"spec"` } diff --git a/util/patch/patch_test.go b/util/patch/patch_test.go index dffbd138301f..611f0d69259b 100644 --- a/util/patch/patch_test.go +++ b/util/patch/patch_test.go @@ -813,6 +813,9 @@ func TestPatchHelper(t *testing.T) { Template: clusterv1.MachineTemplateSpec{ Spec: clusterv1.MachineSpec{ ClusterName: "test1", + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, InfrastructureRef: clusterv1.ContractVersionedObjectReference{ APIGroup: builder.InfrastructureGroupVersion.Group, Kind: builder.TestInfrastructureMachineTemplateKind, @@ -978,6 +981,9 @@ func TestPatchHelper(t *testing.T) { Template: clusterv1.MachineTemplateSpec{ Spec: clusterv1.MachineSpec{ ClusterName: "test1", + Bootstrap: clusterv1.Bootstrap{ + DataSecretName: ptr.To("data-secret"), + }, InfrastructureRef: clusterv1.ContractVersionedObjectReference{ APIGroup: builder.InfrastructureGroupVersion.Group, Kind: builder.TestInfrastructureMachineTemplateKind, diff --git a/util/test/builder/builders.go b/util/test/builder/builders.go index e56bcdc2c7b1..12af33744627 100644 --- a/util/test/builder/builders.go +++ b/util/test/builder/builders.go @@ -501,9 +501,7 @@ func (c *ClusterClassBuilder) Build() *clusterv1.ClusterClass { obj.Status.Conditions = c.conditions } if c.infrastructureClusterTemplate != nil { - obj.Spec.Infrastructure.ClusterClassTemplate = clusterv1.ClusterClassTemplate{ - Ref: objToClusterClassTemplateRef(c.infrastructureClusterTemplate), - } + obj.Spec.Infrastructure.TemplateRef = objToClusterClassTemplateRef(c.infrastructureClusterTemplate) } if c.controlPlaneMetadata != nil { obj.Spec.ControlPlane.Metadata = *c.controlPlaneMetadata @@ -512,9 +510,7 @@ func (c *ClusterClassBuilder) Build() *clusterv1.ClusterClass { obj.Spec.ControlPlane.ReadinessGates = c.controlPlaneReadinessGates } if c.controlPlaneTemplate != nil { - obj.Spec.ControlPlane.ClusterClassTemplate = clusterv1.ClusterClassTemplate{ - Ref: objToClusterClassTemplateRef(c.controlPlaneTemplate), - } + obj.Spec.ControlPlane.TemplateRef = objToClusterClassTemplateRef(c.controlPlaneTemplate) } if c.controlPlaneMHC != nil { obj.Spec.ControlPlane.MachineHealthCheck = c.controlPlaneMHC @@ -529,8 +525,8 @@ func (c *ClusterClassBuilder) Build() *clusterv1.ClusterClass { obj.Spec.ControlPlane.NodeDeletionTimeoutSeconds = c.controlPlaneNodeDeletionTimeout } if c.controlPlaneInfrastructureMachineTemplate != nil { - obj.Spec.ControlPlane.MachineInfrastructure = &clusterv1.ClusterClassTemplate{ - Ref: objToClusterClassTemplateRef(c.controlPlaneInfrastructureMachineTemplate), + obj.Spec.ControlPlane.MachineInfrastructure = &clusterv1.ControlPlaneClassMachineInfrastructureTemplate{ + TemplateRef: objToClusterClassTemplateRef(c.controlPlaneInfrastructureMachineTemplate), } } if c.controlPlaneNamingStrategy != nil { @@ -660,10 +656,10 @@ func (m *MachineDeploymentClassBuilder) Build() *clusterv1.MachineDeploymentClas }, } if m.bootstrapTemplate != nil { - obj.Template.Bootstrap.Ref = objToClusterClassTemplateRef(m.bootstrapTemplate) + obj.Template.Bootstrap.TemplateRef = objToClusterClassTemplateRef(m.bootstrapTemplate) } if m.infrastructureMachineTemplate != nil { - obj.Template.Infrastructure.Ref = objToClusterClassTemplateRef(m.infrastructureMachineTemplate) + obj.Template.Infrastructure.TemplateRef = objToClusterClassTemplateRef(m.infrastructureMachineTemplate) } if m.machineHealthCheckClass != nil { obj.MachineHealthCheck = m.machineHealthCheckClass @@ -789,10 +785,10 @@ func (m *MachinePoolClassBuilder) Build() *clusterv1.MachinePoolClass { }, } if m.bootstrapTemplate != nil { - obj.Template.Bootstrap.Ref = objToClusterClassTemplateRef(m.bootstrapTemplate) + obj.Template.Bootstrap.TemplateRef = objToClusterClassTemplateRef(m.bootstrapTemplate) } if m.infrastructureMachinePoolTemplate != nil { - obj.Template.Infrastructure.Ref = objToClusterClassTemplateRef(m.infrastructureMachinePoolTemplate) + obj.Template.Infrastructure.TemplateRef = objToClusterClassTemplateRef(m.infrastructureMachinePoolTemplate) } if m.failureDomains != nil { obj.FailureDomains = m.failureDomains @@ -2048,9 +2044,9 @@ func (m *MachineBuilder) Build() *clusterv1.Machine { return machine } -func objToClusterClassTemplateRef(obj *unstructured.Unstructured) *clusterv1.ClusterClassTemplateReference { +func objToClusterClassTemplateRef(obj *unstructured.Unstructured) clusterv1.ClusterClassTemplateReference { gvk := obj.GetObjectKind().GroupVersionKind() - return &clusterv1.ClusterClassTemplateReference{ + return clusterv1.ClusterClassTemplateReference{ Kind: gvk.Kind, APIVersion: gvk.GroupVersion().String(), Name: obj.GetName(),