From fccad65573ef61ec785eb0210e604049f3bb8b05 Mon Sep 17 00:00:00 2001 From: fabriziopandini Date: Mon, 8 Jul 2024 20:47:36 +0200 Subject: [PATCH] Add ExtraEnvs and ImagePullSerial to KubeadmConfig --- .../kubeadm/api/v1beta1/kubeadm_types.go | 29 +- .../api/v1beta1/zz_generated.deepcopy.go | 35 ++ ...strap.cluster.x-k8s.io_kubeadmconfigs.yaml | 521 +++++++++++++++++ ...uster.x-k8s.io_kubeadmconfigtemplates.yaml | 538 +++++++++++++++++ .../types/upstreamv1beta1/conversion.go | 16 +- .../types/upstreamv1beta1/conversion_test.go | 21 +- .../zz_generated.conversion.go | 33 +- .../types/upstreamv1beta2/conversion.go | 16 +- .../types/upstreamv1beta2/conversion_test.go | 15 + .../zz_generated.conversion.go | 33 +- .../types/upstreamv1beta3/conversion.go | 17 + .../types/upstreamv1beta3/conversion_test.go | 25 + .../zz_generated.conversion.go | 38 +- .../types/upstreamv1beta4/conversion.go | 9 - .../types/upstreamv1beta4/conversion_test.go | 21 - .../zz_generated.conversion.go | 39 +- ...cluster.x-k8s.io_kubeadmcontrolplanes.yaml | 527 +++++++++++++++++ ...x-k8s.io_kubeadmcontrolplanetemplates.yaml | 548 ++++++++++++++++++ controlplane/kubeadm/internal/filters_test.go | 49 ++ .../bootstrap/kubeadm/v1alpha3/conversion.go | 157 ++--- .../bootstrap/kubeadm/v1alpha3/suite_test.go | 43 -- .../bootstrap/kubeadm/v1alpha4/conversion.go | 143 ++--- .../v1alpha4/zz_generated.conversion.go | 53 +- .../kubeadm/v1alpha3/conversion.go | 67 +-- .../kubeadm/v1alpha3/suite_test.go | 43 -- .../kubeadm/v1alpha4/conversion.go | 104 +--- 26 files changed, 2606 insertions(+), 534 deletions(-) delete mode 100644 internal/apis/bootstrap/kubeadm/v1alpha3/suite_test.go delete mode 100644 internal/apis/controlplane/kubeadm/v1alpha3/suite_test.go diff --git a/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go b/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go index 5d8812b9b0fe..8bed14f6a5f0 100644 --- a/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go +++ b/bootstrap/kubeadm/api/v1beta1/kubeadm_types.go @@ -158,6 +158,12 @@ type ControlPlaneComponent struct { // ExtraVolumes is an extra set of host volumes, mounted to the control plane component. // +optional ExtraVolumes []HostPathMount `json:"extraVolumes,omitempty"` + + // ExtraEnvs is an extra set of environment variables to pass to the control plane component. + // Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + // This option takes effect only on Kubernetes >=1.31.0. + // +optional + ExtraEnvs []EnvVar `json:"extraEnvs,omitempty"` } // APIServer holds settings necessary for API server deployments in the cluster. @@ -192,7 +198,7 @@ type ImageMeta struct { // +optional ImageTag string `json:"imageTag,omitempty"` - //TODO: evaluate if we need also a ImageName based on user feedbacks + // TODO: evaluate if we need also a ImageName based on user feedbacks } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -260,6 +266,12 @@ type NodeRegistrationOptions struct { // +kubebuilder:validation:Enum=Always;IfNotPresent;Never // +optional ImagePullPolicy string `json:"imagePullPolicy,omitempty"` + + // ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + // This option takes effect only on Kubernetes >=1.31.0. + // Default: true (defaulted in kubeadm) + // +optional + ImagePullSerial *bool `json:"imagePullSerial,omitempty"` } // MarshalJSON marshals NodeRegistrationOptions in a way that an empty slice in Taints is preserved. @@ -281,6 +293,7 @@ func (n *NodeRegistrationOptions) MarshalJSON() ([]byte, error) { KubeletExtraArgs map[string]string `json:"kubeletExtraArgs,omitempty"` IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"` ImagePullPolicy string `json:"imagePullPolicy,omitempty"` + ImagePullSerial *bool `json:"imagePullSerial,omitempty"` }{ Name: n.Name, CRISocket: n.CRISocket, @@ -288,6 +301,7 @@ func (n *NodeRegistrationOptions) MarshalJSON() ([]byte, error) { KubeletExtraArgs: n.KubeletExtraArgs, IgnorePreflightErrors: n.IgnorePreflightErrors, ImagePullPolicy: n.ImagePullPolicy, + ImagePullSerial: n.ImagePullSerial, }) } @@ -299,6 +313,7 @@ func (n *NodeRegistrationOptions) MarshalJSON() ([]byte, error) { KubeletExtraArgs map[string]string `json:"kubeletExtraArgs,omitempty"` IgnorePreflightErrors []string `json:"ignorePreflightErrors,omitempty"` ImagePullPolicy string `json:"imagePullPolicy,omitempty"` + ImagePullSerial *bool `json:"imagePullSerial,omitempty"` }{ Name: n.Name, CRISocket: n.CRISocket, @@ -306,6 +321,7 @@ func (n *NodeRegistrationOptions) MarshalJSON() ([]byte, error) { KubeletExtraArgs: n.KubeletExtraArgs, IgnorePreflightErrors: n.IgnorePreflightErrors, ImagePullPolicy: n.ImagePullPolicy, + ImagePullSerial: n.ImagePullSerial, }) } @@ -382,6 +398,12 @@ type LocalEtcd struct { // +optional ExtraArgs map[string]string `json:"extraArgs,omitempty"` + // ExtraEnvs is an extra set of environment variables to pass to the control plane component. + // Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + // This option takes effect only on Kubernetes >=1.31.0. + // +optional + ExtraEnvs []EnvVar `json:"extraEnvs,omitempty"` + // ServerCertSANs sets extra Subject Alternative Names for the etcd server signing cert. // +optional ServerCertSANs []string `json:"serverCertSANs,omitempty"` @@ -735,3 +757,8 @@ type Patches struct { // +optional Directory string `json:"directory,omitempty"` } + +// EnvVar represents an environment variable present in a Container. +type EnvVar struct { + corev1.EnvVar `json:",inline"` +} diff --git a/bootstrap/kubeadm/api/v1beta1/zz_generated.deepcopy.go b/bootstrap/kubeadm/api/v1beta1/zz_generated.deepcopy.go index dcd587f5d772..0c4becdd21a0 100644 --- a/bootstrap/kubeadm/api/v1beta1/zz_generated.deepcopy.go +++ b/bootstrap/kubeadm/api/v1beta1/zz_generated.deepcopy.go @@ -240,6 +240,13 @@ func (in *ControlPlaneComponent) DeepCopyInto(out *ControlPlaneComponent) { *out = make([]HostPathMount, len(*in)) copy(*out, *in) } + if in.ExtraEnvs != nil { + in, out := &in.ExtraEnvs, &out.ExtraEnvs + *out = make([]EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneComponent. @@ -327,6 +334,22 @@ func (in *DiskSetup) DeepCopy() *DiskSetup { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvVar) DeepCopyInto(out *EnvVar) { + *out = *in + in.EnvVar.DeepCopyInto(&out.EnvVar) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvVar. +func (in *EnvVar) DeepCopy() *EnvVar { + if in == nil { + return nil + } + out := new(EnvVar) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Etcd) DeepCopyInto(out *Etcd) { *out = *in @@ -1014,6 +1037,13 @@ func (in *LocalEtcd) DeepCopyInto(out *LocalEtcd) { (*out)[key] = val } } + if in.ExtraEnvs != nil { + in, out := &in.ExtraEnvs, &out.ExtraEnvs + *out = make([]EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.ServerCertSANs != nil { in, out := &in.ServerCertSANs, &out.ServerCertSANs *out = make([]string, len(*in)) @@ -1117,6 +1147,11 @@ func (in *NodeRegistrationOptions) DeepCopyInto(out *NodeRegistrationOptions) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.ImagePullSerial != nil { + in, out := &in.ImagePullSerial, &out.ImagePullSerial + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeRegistrationOptions. 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 a03150ab7b8e..2208256ad706 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 @@ -2093,6 +2093,133 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -2172,6 +2299,133 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -2273,6 +2527,134 @@ spec: ExtraArgs are extra arguments provided to the etcd binary when run inside a static pod. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array imageRepository: description: |- ImageRepository sets the container registry to pull images from. @@ -2363,6 +2745,133 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -2677,6 +3186,12 @@ spec: - IfNotPresent - Never type: string + imagePullSerial: + description: |- + ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + This option takes effect only on Kubernetes >=1.31.0. + Default: true (defaulted in kubeadm) + type: boolean kubeletExtraArgs: additionalProperties: type: string @@ -3027,6 +3542,12 @@ spec: - IfNotPresent - Never type: string + imagePullSerial: + description: |- + ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + This option takes effect only on Kubernetes >=1.31.0. + Default: true (defaulted in kubeadm) + type: boolean kubeletExtraArgs: additionalProperties: type: string 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 e5be84ccb435..9b6b709cc183 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 @@ -2039,6 +2039,137 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -2120,6 +2251,137 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -2224,6 +2486,139 @@ spec: ExtraArgs are extra arguments provided to the etcd binary when run inside a static pod. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array imageRepository: description: |- ImageRepository sets the container registry to pull images from. @@ -2315,6 +2710,137 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -2640,6 +3166,12 @@ spec: - IfNotPresent - Never type: string + imagePullSerial: + description: |- + ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + This option takes effect only on Kubernetes >=1.31.0. + Default: true (defaulted in kubeadm) + type: boolean kubeletExtraArgs: additionalProperties: type: string @@ -2997,6 +3529,12 @@ spec: - IfNotPresent - Never type: string + imagePullSerial: + description: |- + ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + This option takes effect only on Kubernetes >=1.31.0. + Default: true (defaulted in kubeadm) + type: boolean kubeletExtraArgs: additionalProperties: type: string diff --git a/bootstrap/kubeadm/types/upstreamv1beta1/conversion.go b/bootstrap/kubeadm/types/upstreamv1beta1/conversion.go index 5944965f69f0..1607d50f620e 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta1/conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta1/conversion.go @@ -77,18 +77,28 @@ func Convert_upstreamv1beta1_DNS_To_v1beta1_DNS(in *DNS, out *bootstrapv1.DNS, s // Custom conversion from the hub version, CABPK v1beta1, to this API, kubeadm v1beta1. +func Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta1_ControlPlaneComponent(in *bootstrapv1.ControlPlaneComponent, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + // ControlPlaneComponent.ExtraEnvs does not exist in kubeadm v1beta1, dropping this info. + return autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta1_ControlPlaneComponent(in, out, s) +} + +func Convert_v1beta1_LocalEtcd_To_upstreamv1beta1_LocalEtcd(in *bootstrapv1.LocalEtcd, out *LocalEtcd, s apimachineryconversion.Scope) error { + // LocalEtcd.ExtraEnvs does not exist in kubeadm v1beta1, dropping this info. + return autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta1_LocalEtcd(in, out, s) +} + func Convert_v1beta1_InitConfiguration_To_upstreamv1beta1_InitConfiguration(in *bootstrapv1.InitConfiguration, out *InitConfiguration, s apimachineryconversion.Scope) error { - // InitConfiguration.SkipPhases and Patches does not exist in kubeadm v1beta1, dropping those info. + // InitConfiguration.SkipPhases and Patches do not exist in kubeadm v1beta1, dropping those info. return autoConvert_v1beta1_InitConfiguration_To_upstreamv1beta1_InitConfiguration(in, out, s) } func Convert_v1beta1_JoinConfiguration_To_upstreamv1beta1_JoinConfiguration(in *bootstrapv1.JoinConfiguration, out *JoinConfiguration, s apimachineryconversion.Scope) error { - // JoinConfiguration.SkipPhases and Patches does not exist in kubeadm v1beta1, dropping those info. + // JoinConfiguration.SkipPhases and Patches do not exist in kubeadm v1beta1, dropping those info. return autoConvert_v1beta1_JoinConfiguration_To_upstreamv1beta1_JoinConfiguration(in, out, s) } func Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta1_NodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, out *NodeRegistrationOptions, s apimachineryconversion.Scope) error { - // NodeRegistrationOptions.IgnorePreflightErrors and ImagePullPolicy does not exist in kubeadm v1beta1, dropping those info. + // NodeRegistrationOptions.IgnorePreflightErrors, ImagePullPolicy and ImagePullSerial do not exist in kubeadm v1beta1, dropping those info. return autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta1_NodeRegistrationOptions(in, out, s) } diff --git a/bootstrap/kubeadm/types/upstreamv1beta1/conversion_test.go b/bootstrap/kubeadm/types/upstreamv1beta1/conversion_test.go index da1dd63bf54f..1e12a1986600 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta1/conversion_test.go +++ b/bootstrap/kubeadm/types/upstreamv1beta1/conversion_test.go @@ -62,6 +62,8 @@ func fuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ clusterConfigurationFuzzer, dnsFuzzer, + bootstrapv1ControlPlaneComponentFuzzer, + bootstrapv1LocalEtcdFuzzer, bootstrapv1InitConfigurationFuzzer, bootstrapv1JoinConfigurationFuzzer, bootstrapv1NodeRegistrationOptionsFuzzer, @@ -88,6 +90,18 @@ func dnsFuzzer(obj *DNS, c fuzz.Continue) { // NOTES: // - When fields do not exist in kubeadm v1beta1 types, pinning it to avoid cabpk v1beta1 --> kubeadm v1beta1 --> cabpk v1beta1 round trip errors. +func bootstrapv1ControlPlaneComponentFuzzer(obj *bootstrapv1.ControlPlaneComponent, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + obj.ExtraEnvs = nil +} + +func bootstrapv1LocalEtcdFuzzer(obj *bootstrapv1.LocalEtcd, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + obj.ExtraEnvs = nil +} + func bootstrapv1InitConfigurationFuzzer(obj *bootstrapv1.InitConfiguration, c fuzz.Continue) { c.FuzzNoCustom(obj) @@ -98,10 +112,7 @@ func bootstrapv1InitConfigurationFuzzer(obj *bootstrapv1.InitConfiguration, c fu func bootstrapv1JoinConfigurationFuzzer(obj *bootstrapv1.JoinConfiguration, c fuzz.Continue) { c.FuzzNoCustom(obj) - // JoinConfiguration.Patches does not exist in kubeadm v1beta1 types, pinning it to avoid cabpk v1beta1 --> kubeadm v1beta1 --> cabpk v1beta1 round trip errors. obj.Patches = nil - - // JoinConfiguration.SkipPhases does not exist in kubeadm v1beta1 types, pinning it to avoid cabpk v1beta1 --> kubeadm v1beta1 --> cabpk v1beta1 round trip errors. obj.SkipPhases = nil if obj.Discovery.File != nil { @@ -112,9 +123,7 @@ func bootstrapv1JoinConfigurationFuzzer(obj *bootstrapv1.JoinConfiguration, c fu func bootstrapv1NodeRegistrationOptionsFuzzer(obj *bootstrapv1.NodeRegistrationOptions, c fuzz.Continue) { c.FuzzNoCustom(obj) - // NodeRegistrationOptions.IgnorePreflightErrors does not exist in kubeadm v1beta1 types, pinning it to avoid cabpk v1beta1 --> kubeadm v1beta1 --> cabpk v1beta1 round trip errors. obj.IgnorePreflightErrors = nil - - // NodeRegistrationOptions.ImagePullPolicy does not exist in kubeadm v1beta1 types, pinning it to avoid cabpk v1beta1 --> kubeadm v1beta1 --> cabpk v1beta1 round trip errors. obj.ImagePullPolicy = "" + obj.ImagePullSerial = nil } diff --git a/bootstrap/kubeadm/types/upstreamv1beta1/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta1/zz_generated.conversion.go index 3a35e2f91972..d47e95881100 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta1/zz_generated.conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta1/zz_generated.conversion.go @@ -475,14 +475,10 @@ func Convert_upstreamv1beta1_ControlPlaneComponent_To_v1beta1_ControlPlaneCompon func autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta1_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) out.ExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ExtraVolumes)) + // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type return nil } -// Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta1_ControlPlaneComponent is an autogenerated conversion function. -func Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta1_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { - return autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta1_ControlPlaneComponent(in, out, s) -} - func autoConvert_upstreamv1beta1_DNS_To_v1beta1_DNS(in *DNS, out *v1beta1.DNS, s conversion.Scope) error { // WARNING: in.Type requires manual conversion: does not exist in peer-type if err := Convert_upstreamv1beta1_ImageMeta_To_v1beta1_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil { @@ -546,7 +542,15 @@ func Convert_v1beta1_Discovery_To_upstreamv1beta1_Discovery(in *v1beta1.Discover } func autoConvert_upstreamv1beta1_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s conversion.Scope) error { - out.Local = (*v1beta1.LocalEtcd)(unsafe.Pointer(in.Local)) + if in.Local != nil { + in, out := &in.Local, &out.Local + *out = new(v1beta1.LocalEtcd) + if err := Convert_upstreamv1beta1_LocalEtcd_To_v1beta1_LocalEtcd(*in, *out, s); err != nil { + return err + } + } else { + out.Local = nil + } out.External = (*v1beta1.ExternalEtcd)(unsafe.Pointer(in.External)) return nil } @@ -557,7 +561,15 @@ func Convert_upstreamv1beta1_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s } func autoConvert_v1beta1_Etcd_To_upstreamv1beta1_Etcd(in *v1beta1.Etcd, out *Etcd, s conversion.Scope) error { - out.Local = (*LocalEtcd)(unsafe.Pointer(in.Local)) + if in.Local != nil { + in, out := &in.Local, &out.Local + *out = new(LocalEtcd) + if err := Convert_v1beta1_LocalEtcd_To_upstreamv1beta1_LocalEtcd(*in, *out, s); err != nil { + return err + } + } else { + out.Local = nil + } out.External = (*ExternalEtcd)(unsafe.Pointer(in.External)) return nil } @@ -765,16 +777,12 @@ func autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta1_LocalEtcd(in *v1beta1.Loca } out.DataDir = in.DataDir out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) + // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) return nil } -// Convert_v1beta1_LocalEtcd_To_upstreamv1beta1_LocalEtcd is an autogenerated conversion function. -func Convert_v1beta1_LocalEtcd_To_upstreamv1beta1_LocalEtcd(in *v1beta1.LocalEtcd, out *LocalEtcd, s conversion.Scope) error { - return autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta1_LocalEtcd(in, out, s) -} - func autoConvert_upstreamv1beta1_Networking_To_v1beta1_Networking(in *Networking, out *v1beta1.Networking, s conversion.Scope) error { out.ServiceSubnet = in.ServiceSubnet out.PodSubnet = in.PodSubnet @@ -819,5 +827,6 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta1_NodeRegistra out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) // WARNING: in.IgnorePreflightErrors requires manual conversion: does not exist in peer-type // WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type + // WARNING: in.ImagePullSerial requires manual conversion: does not exist in peer-type return nil } diff --git a/bootstrap/kubeadm/types/upstreamv1beta2/conversion.go b/bootstrap/kubeadm/types/upstreamv1beta2/conversion.go index f40ac2ab3cdc..d1ec1fa25a6b 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta2/conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta2/conversion.go @@ -88,20 +88,30 @@ func Convert_upstreamv1beta2_JoinControlPlane_To_v1beta1_JoinControlPlane(in *Jo // Custom conversion from the hub version, CABPK v1beta1, to this API, kubeadm v1beta2. func Convert_v1beta1_InitConfiguration_To_upstreamv1beta2_InitConfiguration(in *bootstrapv1.InitConfiguration, out *InitConfiguration, s apimachineryconversion.Scope) error { - // InitConfiguration.SkipPhases and Patches does not exist in kubeadm v1beta2, dropping those info. + // InitConfiguration.SkipPhases and Patches do not exist in kubeadm v1beta2, dropping those info. return autoConvert_v1beta1_InitConfiguration_To_upstreamv1beta2_InitConfiguration(in, out, s) } func Convert_v1beta1_JoinConfiguration_To_upstreamv1beta2_JoinConfiguration(in *bootstrapv1.JoinConfiguration, out *JoinConfiguration, s apimachineryconversion.Scope) error { - // JoinConfiguration.SkipPhases and Patches does not exist in kubeadm v1beta2, dropping those info. + // JoinConfiguration.SkipPhases and Patches do not exist in kubeadm v1beta2, dropping those info. return autoConvert_v1beta1_JoinConfiguration_To_upstreamv1beta2_JoinConfiguration(in, out, s) } func Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, out *NodeRegistrationOptions, s apimachineryconversion.Scope) error { - // NodeRegistrationOptions.IgnorePreflightErrors and ImagePullPolicy does not exist in kubeadm v1beta2, dropping those info. + // NodeRegistrationOptions.ImagePullPolicy and ImagePullSerial do not exist in kubeadm v1beta2, dropping those info. return autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistrationOptions(in, out, s) } +func Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta2_ControlPlaneComponent(in *bootstrapv1.ControlPlaneComponent, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + // ControlPlaneComponent.ExtraEnvs does not exist in kubeadm v1beta2, dropping this info. + return autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta2_ControlPlaneComponent(in, out, s) +} + +func Convert_v1beta1_LocalEtcd_To_upstreamv1beta2_LocalEtcd(in *bootstrapv1.LocalEtcd, out *LocalEtcd, s apimachineryconversion.Scope) error { + // LocalEtcd.ExtraEnvs does not exist in kubeadm v1beta2, dropping this info. + return autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta2_LocalEtcd(in, out, s) +} + func Convert_v1beta1_FileDiscovery_To_upstreamv1beta2_FileDiscovery(in *bootstrapv1.FileDiscovery, out *FileDiscovery, s apimachineryconversion.Scope) error { // JoinConfiguration.Discovery.File.KubeConfig does not exist in kubeadm because it's internal to Cluster API, dropping those info. return autoConvert_v1beta1_FileDiscovery_To_upstreamv1beta2_FileDiscovery(in, out, s) diff --git a/bootstrap/kubeadm/types/upstreamv1beta2/conversion_test.go b/bootstrap/kubeadm/types/upstreamv1beta2/conversion_test.go index 166272e3fcb3..0e0371e20087 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta2/conversion_test.go +++ b/bootstrap/kubeadm/types/upstreamv1beta2/conversion_test.go @@ -64,6 +64,8 @@ func fuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { dnsFuzzer, initConfigurationFuzzer, joinControlPlanesFuzzer, + bootstrapv1ControlPlaneComponentFuzzer, + bootstrapv1LocalEtcdFuzzer, bootstrapv1InitConfigurationFuzzer, bootstrapv1JoinConfigurationFuzzer, bootstrapv1NodeRegistrationOptionsFuzzer, @@ -102,6 +104,18 @@ func joinControlPlanesFuzzer(obj *JoinControlPlane, c fuzz.Continue) { // NOTES: // - When fields do not exist in kubeadm v1beta2 types, pinning it to avoid cabpk v1beta1 --> kubeadm v1beta2 --> cabpk v1beta1 round trip errors. +func bootstrapv1ControlPlaneComponentFuzzer(obj *bootstrapv1.ControlPlaneComponent, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + obj.ExtraEnvs = nil +} + +func bootstrapv1LocalEtcdFuzzer(obj *bootstrapv1.LocalEtcd, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + obj.ExtraEnvs = nil +} + func bootstrapv1InitConfigurationFuzzer(obj *bootstrapv1.InitConfiguration, c fuzz.Continue) { c.FuzzNoCustom(obj) @@ -124,4 +138,5 @@ func bootstrapv1NodeRegistrationOptionsFuzzer(obj *bootstrapv1.NodeRegistrationO c.FuzzNoCustom(obj) obj.ImagePullPolicy = "" + obj.ImagePullSerial = nil } diff --git a/bootstrap/kubeadm/types/upstreamv1beta2/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta2/zz_generated.conversion.go index c9d29c1d2ba2..b82b1d088ceb 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta2/zz_generated.conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta2/zz_generated.conversion.go @@ -475,14 +475,10 @@ func Convert_upstreamv1beta2_ControlPlaneComponent_To_v1beta1_ControlPlaneCompon func autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta2_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) out.ExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ExtraVolumes)) + // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type return nil } -// Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta2_ControlPlaneComponent is an autogenerated conversion function. -func Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta2_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { - return autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta2_ControlPlaneComponent(in, out, s) -} - func autoConvert_upstreamv1beta2_DNS_To_v1beta1_DNS(in *DNS, out *v1beta1.DNS, s conversion.Scope) error { // WARNING: in.Type requires manual conversion: does not exist in peer-type if err := Convert_upstreamv1beta2_ImageMeta_To_v1beta1_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil { @@ -546,7 +542,15 @@ func Convert_v1beta1_Discovery_To_upstreamv1beta2_Discovery(in *v1beta1.Discover } func autoConvert_upstreamv1beta2_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s conversion.Scope) error { - out.Local = (*v1beta1.LocalEtcd)(unsafe.Pointer(in.Local)) + if in.Local != nil { + in, out := &in.Local, &out.Local + *out = new(v1beta1.LocalEtcd) + if err := Convert_upstreamv1beta2_LocalEtcd_To_v1beta1_LocalEtcd(*in, *out, s); err != nil { + return err + } + } else { + out.Local = nil + } out.External = (*v1beta1.ExternalEtcd)(unsafe.Pointer(in.External)) return nil } @@ -557,7 +561,15 @@ func Convert_upstreamv1beta2_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s } func autoConvert_v1beta1_Etcd_To_upstreamv1beta2_Etcd(in *v1beta1.Etcd, out *Etcd, s conversion.Scope) error { - out.Local = (*LocalEtcd)(unsafe.Pointer(in.Local)) + if in.Local != nil { + in, out := &in.Local, &out.Local + *out = new(LocalEtcd) + if err := Convert_v1beta1_LocalEtcd_To_upstreamv1beta2_LocalEtcd(*in, *out, s); err != nil { + return err + } + } else { + out.Local = nil + } out.External = (*ExternalEtcd)(unsafe.Pointer(in.External)) return nil } @@ -773,16 +785,12 @@ func autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta2_LocalEtcd(in *v1beta1.Loca } out.DataDir = in.DataDir out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) + // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) return nil } -// Convert_v1beta1_LocalEtcd_To_upstreamv1beta2_LocalEtcd is an autogenerated conversion function. -func Convert_v1beta1_LocalEtcd_To_upstreamv1beta2_LocalEtcd(in *v1beta1.LocalEtcd, out *LocalEtcd, s conversion.Scope) error { - return autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta2_LocalEtcd(in, out, s) -} - func autoConvert_upstreamv1beta2_Networking_To_v1beta1_Networking(in *Networking, out *v1beta1.Networking, s conversion.Scope) error { out.ServiceSubnet = in.ServiceSubnet out.PodSubnet = in.PodSubnet @@ -828,5 +836,6 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta2_NodeRegistra out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) // WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type + // WARNING: in.ImagePullSerial requires manual conversion: does not exist in peer-type return nil } diff --git a/bootstrap/kubeadm/types/upstreamv1beta3/conversion.go b/bootstrap/kubeadm/types/upstreamv1beta3/conversion.go index b6ff0ac5bdb3..9003aeb32d91 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta3/conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta3/conversion.go @@ -65,7 +65,24 @@ func Convert_upstreamv1beta3_JoinControlPlane_To_v1beta1_JoinControlPlane(in *Jo return autoConvert_upstreamv1beta3_JoinControlPlane_To_v1beta1_JoinControlPlane(in, out, s) } +// Custom conversion from the hub version, CABPK v1beta1, to this API, kubeadm v1beta3. + func Convert_v1beta1_FileDiscovery_To_upstreamv1beta3_FileDiscovery(in *bootstrapv1.FileDiscovery, out *FileDiscovery, s apimachineryconversion.Scope) error { // JoinConfiguration.Discovery.File.KubeConfig does not exist in kubeadm because it's internal to Cluster API, dropping those info. return autoConvert_v1beta1_FileDiscovery_To_upstreamv1beta3_FileDiscovery(in, out, s) } + +func Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(in *bootstrapv1.ControlPlaneComponent, out *ControlPlaneComponent, s apimachineryconversion.Scope) error { + // ControlPlaneComponent.ExtraEnvs does not exist in kubeadm v1beta3, dropping this info. + return autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(in, out, s) +} + +func Convert_v1beta1_LocalEtcd_To_upstreamv1beta3_LocalEtcd(in *bootstrapv1.LocalEtcd, out *LocalEtcd, s apimachineryconversion.Scope) error { + // LocalEtcd.ExtraEnvs does not exist in kubeadm v1beta3, dropping this info. + return autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta3_LocalEtcd(in, out, s) +} + +func Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistrationOptions(in *bootstrapv1.NodeRegistrationOptions, out *NodeRegistrationOptions, s apimachineryconversion.Scope) error { + // NodeRegistrationOptions.ImagePullSerial does not exist in kubeadm v1beta3, dropping this info. + return autoConvert_v1beta1_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 f91ff18955b2..8a0c710eb377 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta3/conversion_test.go +++ b/bootstrap/kubeadm/types/upstreamv1beta3/conversion_test.go @@ -68,6 +68,9 @@ func fuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { bootstrapv1JoinConfigurationFuzzer, nodeRegistrationOptionsFuzzer, joinControlPlanesFuzzer, + bootstrapv1ControlPlaneComponentFuzzer, + bootstrapv1LocalEtcdFuzzer, + bootstrapv1NodeRegistrationOptionsFuzzer, } } @@ -107,3 +110,25 @@ func joinControlPlanesFuzzer(obj *JoinControlPlane, c fuzz.Continue) { obj.CertificateKey = "" } + +// Custom fuzzers for CABPK v1beta1 types. +// NOTES: +// - When fields do not exist in kubeadm v1beta4 types, pinning them to avoid cabpk v1beta1 --> kubeadm v1beta4 --> cabpk v1beta1 round trip errors. + +func bootstrapv1ControlPlaneComponentFuzzer(obj *bootstrapv1.ControlPlaneComponent, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + obj.ExtraEnvs = nil +} + +func bootstrapv1LocalEtcdFuzzer(obj *bootstrapv1.LocalEtcd, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + obj.ExtraEnvs = nil +} + +func bootstrapv1NodeRegistrationOptionsFuzzer(obj *bootstrapv1.NodeRegistrationOptions, c fuzz.Continue) { + c.FuzzNoCustom(obj) + + obj.ImagePullSerial = nil +} diff --git a/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go index cfd45bf23834..4db985df8a59 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta3/zz_generated.conversion.go @@ -459,14 +459,10 @@ func Convert_upstreamv1beta3_ControlPlaneComponent_To_v1beta1_ControlPlaneCompon func autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) out.ExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ExtraVolumes)) + // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type return nil } -// Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent is an autogenerated conversion function. -func Convert_v1beta1_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { - return autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta3_ControlPlaneComponent(in, out, s) -} - func autoConvert_upstreamv1beta3_DNS_To_v1beta1_DNS(in *DNS, out *v1beta1.DNS, s conversion.Scope) error { if err := Convert_upstreamv1beta3_ImageMeta_To_v1beta1_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil { return err @@ -534,7 +530,15 @@ func Convert_v1beta1_Discovery_To_upstreamv1beta3_Discovery(in *v1beta1.Discover } func autoConvert_upstreamv1beta3_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s conversion.Scope) error { - out.Local = (*v1beta1.LocalEtcd)(unsafe.Pointer(in.Local)) + if in.Local != nil { + in, out := &in.Local, &out.Local + *out = new(v1beta1.LocalEtcd) + if err := Convert_upstreamv1beta3_LocalEtcd_To_v1beta1_LocalEtcd(*in, *out, s); err != nil { + return err + } + } else { + out.Local = nil + } out.External = (*v1beta1.ExternalEtcd)(unsafe.Pointer(in.External)) return nil } @@ -545,7 +549,15 @@ func Convert_upstreamv1beta3_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s } func autoConvert_v1beta1_Etcd_To_upstreamv1beta3_Etcd(in *v1beta1.Etcd, out *Etcd, s conversion.Scope) error { - out.Local = (*LocalEtcd)(unsafe.Pointer(in.Local)) + if in.Local != nil { + in, out := &in.Local, &out.Local + *out = new(LocalEtcd) + if err := Convert_v1beta1_LocalEtcd_To_upstreamv1beta3_LocalEtcd(*in, *out, s); err != nil { + return err + } + } else { + out.Local = nil + } out.External = (*ExternalEtcd)(unsafe.Pointer(in.External)) return nil } @@ -775,16 +787,12 @@ func autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta3_LocalEtcd(in *v1beta1.Loca } out.DataDir = in.DataDir out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) + // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) return nil } -// Convert_v1beta1_LocalEtcd_To_upstreamv1beta3_LocalEtcd is an autogenerated conversion function. -func Convert_v1beta1_LocalEtcd_To_upstreamv1beta3_LocalEtcd(in *v1beta1.LocalEtcd, out *LocalEtcd, s conversion.Scope) error { - return autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta3_LocalEtcd(in, out, s) -} - func autoConvert_upstreamv1beta3_Networking_To_v1beta1_Networking(in *Networking, out *v1beta1.Networking, s conversion.Scope) error { out.ServiceSubnet = in.ServiceSubnet out.PodSubnet = in.PodSubnet @@ -831,14 +839,10 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistra out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = in.ImagePullPolicy + // WARNING: in.ImagePullSerial requires manual conversion: does not exist in peer-type return nil } -// Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistrationOptions is an autogenerated conversion function. -func Convert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistrationOptions(in *v1beta1.NodeRegistrationOptions, out *NodeRegistrationOptions, s conversion.Scope) error { - return autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta3_NodeRegistrationOptions(in, out, s) -} - func autoConvert_upstreamv1beta3_Patches_To_v1beta1_Patches(in *Patches, out *v1beta1.Patches, s conversion.Scope) error { out.Directory = in.Directory return nil diff --git a/bootstrap/kubeadm/types/upstreamv1beta4/conversion.go b/bootstrap/kubeadm/types/upstreamv1beta4/conversion.go index b8b8987ae000..807571b5ed37 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta4/conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta4/conversion.go @@ -68,9 +68,6 @@ func Convert_upstreamv1beta4_ClusterConfiguration_To_v1beta1_ClusterConfiguratio } func Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in *ControlPlaneComponent, out *bootstrapv1.ControlPlaneComponent, s apimachineryconversion.Scope) error { - // Following fields do not exist in CABPK v1beta1 version: - // - ExtraEnvs (Not supported yet) - // Following fields exists in CABPK v1beta1 but they need a custom conversions. // Note: there is a potential info loss when there are two values for the same arg but this is not an issue because the CAPBK v1beta1 does not allow this use case. out.ExtraArgs = convertFromArgs(in.ExtraArgs) @@ -78,9 +75,6 @@ func Convert_upstreamv1beta4_ControlPlaneComponent_To_v1beta1_ControlPlaneCompon } func Convert_upstreamv1beta4_LocalEtcd_To_v1beta1_LocalEtcd(in *LocalEtcd, out *bootstrapv1.LocalEtcd, s apimachineryconversion.Scope) error { - // Following fields do not exist in CABPK v1beta1 version: - // - ExtraEnvs (Not supported yet) - // 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 not an issue because the CAPBK v1beta1 does not allow this use case. out.ExtraArgs = convertFromArgs(in.ExtraArgs) @@ -116,9 +110,6 @@ func Convert_upstreamv1beta4_JoinConfiguration_To_v1beta1_JoinConfiguration(in * } func Convert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta1_NodeRegistrationOptions(in *NodeRegistrationOptions, out *bootstrapv1.NodeRegistrationOptions, s apimachineryconversion.Scope) error { - // Following fields do not exist in CABPK v1beta1 version: - // - ImagePullSerial (Not supported yet) - // 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 not an issue because the CAPBK v1beta1 does not allow this use case. out.KubeletExtraArgs = convertFromArgs(in.KubeletExtraArgs) diff --git a/bootstrap/kubeadm/types/upstreamv1beta4/conversion_test.go b/bootstrap/kubeadm/types/upstreamv1beta4/conversion_test.go index add903176413..ada2c6415016 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta4/conversion_test.go +++ b/bootstrap/kubeadm/types/upstreamv1beta4/conversion_test.go @@ -66,12 +66,9 @@ func TestFuzzyConversion(t *testing.T) { func fuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ clusterConfigurationFuzzer, - controlPlaneComponentFuzzer, dnsFuzzer, - localEtcdFuzzer, initConfigurationFuzzer, joinConfigurationFuzzer, - nodeRegistrationOptionsFuzzer, joinControlPlaneFuzzer, bootstrapv1APIServerFuzzer, bootstrapv1JoinConfigurationFuzzer, @@ -91,24 +88,12 @@ func clusterConfigurationFuzzer(obj *ClusterConfiguration, c fuzz.Continue) { obj.CertificateValidityPeriod = nil } -func controlPlaneComponentFuzzer(obj *ControlPlaneComponent, c fuzz.Continue) { - c.FuzzNoCustom(obj) - - obj.ExtraEnvs = nil -} - func dnsFuzzer(obj *DNS, c fuzz.Continue) { c.FuzzNoCustom(obj) obj.Disabled = false } -func localEtcdFuzzer(obj *LocalEtcd, c fuzz.Continue) { - c.FuzzNoCustom(obj) - - obj.ExtraEnvs = nil -} - func initConfigurationFuzzer(obj *InitConfiguration, c fuzz.Continue) { c.FuzzNoCustom(obj) @@ -136,12 +121,6 @@ func joinConfigurationFuzzer(obj *JoinConfiguration, c fuzz.Continue) { obj.Timeouts = supportedTimeouts } -func nodeRegistrationOptionsFuzzer(obj *NodeRegistrationOptions, c fuzz.Continue) { - c.FuzzNoCustom(obj) - - obj.ImagePullSerial = nil -} - func joinControlPlaneFuzzer(obj *JoinControlPlane, c fuzz.Continue) { c.FuzzNoCustom(obj) diff --git a/bootstrap/kubeadm/types/upstreamv1beta4/zz_generated.conversion.go b/bootstrap/kubeadm/types/upstreamv1beta4/zz_generated.conversion.go index fd2350a66e96..8b04bef1affa 100644 --- a/bootstrap/kubeadm/types/upstreamv1beta4/zz_generated.conversion.go +++ b/bootstrap/kubeadm/types/upstreamv1beta4/zz_generated.conversion.go @@ -98,6 +98,16 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddGeneratedConversionFunc((*EnvVar)(nil), (*v1beta1.EnvVar)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_upstreamv1beta4_EnvVar_To_v1beta1_EnvVar(a.(*EnvVar), b.(*v1beta1.EnvVar), scope) + }); err != nil { + return err + } + if err := s.AddGeneratedConversionFunc((*v1beta1.EnvVar)(nil), (*EnvVar)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_EnvVar_To_upstreamv1beta4_EnvVar(a.(*v1beta1.EnvVar), b.(*EnvVar), scope) + }); err != nil { + return err + } if err := s.AddGeneratedConversionFunc((*Etcd)(nil), (*v1beta1.Etcd)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_upstreamv1beta4_Etcd_To_v1beta1_Etcd(a.(*Etcd), b.(*v1beta1.Etcd), scope) }); err != nil { @@ -441,13 +451,14 @@ func Convert_v1beta1_ClusterConfiguration_To_upstreamv1beta4_ClusterConfiguratio func autoConvert_upstreamv1beta4_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in *ControlPlaneComponent, out *v1beta1.ControlPlaneComponent, s conversion.Scope) error { // WARNING: in.ExtraArgs requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/upstreamv1beta4.Arg vs map[string]string) out.ExtraVolumes = *(*[]v1beta1.HostPathMount)(unsafe.Pointer(&in.ExtraVolumes)) - // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type + out.ExtraEnvs = *(*[]v1beta1.EnvVar)(unsafe.Pointer(&in.ExtraEnvs)) return nil } func autoConvert_v1beta1_ControlPlaneComponent_To_upstreamv1beta4_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { // WARNING: in.ExtraArgs requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/upstreamv1beta4.Arg) out.ExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ExtraVolumes)) + out.ExtraEnvs = *(*[]EnvVar)(unsafe.Pointer(&in.ExtraEnvs)) return nil } @@ -507,6 +518,26 @@ func autoConvert_v1beta1_Discovery_To_upstreamv1beta4_Discovery(in *v1beta1.Disc return nil } +func autoConvert_upstreamv1beta4_EnvVar_To_v1beta1_EnvVar(in *EnvVar, out *v1beta1.EnvVar, s conversion.Scope) error { + out.EnvVar = in.EnvVar + return nil +} + +// Convert_upstreamv1beta4_EnvVar_To_v1beta1_EnvVar is an autogenerated conversion function. +func Convert_upstreamv1beta4_EnvVar_To_v1beta1_EnvVar(in *EnvVar, out *v1beta1.EnvVar, s conversion.Scope) error { + return autoConvert_upstreamv1beta4_EnvVar_To_v1beta1_EnvVar(in, out, s) +} + +func autoConvert_v1beta1_EnvVar_To_upstreamv1beta4_EnvVar(in *v1beta1.EnvVar, out *EnvVar, s conversion.Scope) error { + out.EnvVar = in.EnvVar + return nil +} + +// Convert_v1beta1_EnvVar_To_upstreamv1beta4_EnvVar is an autogenerated conversion function. +func Convert_v1beta1_EnvVar_To_upstreamv1beta4_EnvVar(in *v1beta1.EnvVar, out *EnvVar, s conversion.Scope) error { + return autoConvert_v1beta1_EnvVar_To_upstreamv1beta4_EnvVar(in, out, s) +} + func autoConvert_upstreamv1beta4_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s conversion.Scope) error { if in.Local != nil { in, out := &in.Local, &out.Local @@ -743,7 +774,7 @@ func autoConvert_upstreamv1beta4_LocalEtcd_To_v1beta1_LocalEtcd(in *LocalEtcd, o } out.DataDir = in.DataDir // WARNING: in.ExtraArgs requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/upstreamv1beta4.Arg vs map[string]string) - // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type + out.ExtraEnvs = *(*[]v1beta1.EnvVar)(unsafe.Pointer(&in.ExtraEnvs)) out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) return nil @@ -755,6 +786,7 @@ func autoConvert_v1beta1_LocalEtcd_To_upstreamv1beta4_LocalEtcd(in *v1beta1.Loca } out.DataDir = in.DataDir // WARNING: in.ExtraArgs requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/upstreamv1beta4.Arg) + out.ExtraEnvs = *(*[]EnvVar)(unsafe.Pointer(&in.ExtraEnvs)) out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) return nil @@ -791,7 +823,7 @@ func autoConvert_upstreamv1beta4_NodeRegistrationOptions_To_v1beta1_NodeRegistra // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types ([]sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/upstreamv1beta4.Arg vs map[string]string) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = string(in.ImagePullPolicy) - // WARNING: in.ImagePullSerial requires manual conversion: does not exist in peer-type + out.ImagePullSerial = (*bool)(unsafe.Pointer(in.ImagePullSerial)) return nil } @@ -802,6 +834,7 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_upstreamv1beta4_NodeRegistra // WARNING: in.KubeletExtraArgs requires manual conversion: inconvertible types (map[string]string vs []sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/upstreamv1beta4.Arg) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) out.ImagePullPolicy = corev1.PullPolicy(in.ImagePullPolicy) + out.ImagePullSerial = (*bool)(unsafe.Pointer(in.ImagePullSerial)) return nil } 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 4cb0d481c492..27ad7e0d8d91 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 @@ -2559,6 +2559,134 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -2639,6 +2767,134 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -2742,6 +2998,137 @@ spec: ExtraArgs are extra arguments provided to the etcd binary when run inside a static pod. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the + FieldPath is written in terms of, + defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults + to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to + select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in + the pod's namespace + properties: + key: + description: The key of the secret to + select from. Must be a valid secret + key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array imageRepository: description: |- ImageRepository sets the container registry to pull images from. @@ -2832,6 +3219,134 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select + in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format + of the exposed resources, defaults to + "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the Secret + or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -3152,6 +3667,12 @@ spec: - IfNotPresent - Never type: string + imagePullSerial: + description: |- + ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + This option takes effect only on Kubernetes >=1.31.0. + Default: true (defaulted in kubeadm) + type: boolean kubeletExtraArgs: additionalProperties: type: string @@ -3506,6 +4027,12 @@ spec: - IfNotPresent - Never type: string + imagePullSerial: + description: |- + ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + This option takes effect only on Kubernetes >=1.31.0. + Default: true (defaulted in kubeadm) + type: boolean kubeletExtraArgs: additionalProperties: type: string 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 c9c1215de395..f8eca78b06b0 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 @@ -1240,6 +1240,139 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -1322,6 +1455,139 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -1427,6 +1693,143 @@ spec: ExtraArgs are extra arguments provided to the etcd binary when run inside a static pod. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment + variable. Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if + value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a + ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether + the ConfigMap or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the + schema the FieldPath is written + in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field + to select in the specified + API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: + required for volumes, optional + for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a + secret in the pod's namespace + properties: + key: + description: The key of the + secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether + the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array imageRepository: description: |- ImageRepository sets the container registry to pull images from. @@ -1519,6 +1922,139 @@ spec: TODO: This is temporary and ideally we would like to switch all components to use ComponentConfig + ConfigMaps. type: object + extraEnvs: + description: |- + ExtraEnvs is an extra set of environment variables to pass to the control plane component. + Environment variables passed using ExtraEnvs will override any existing environment variables, or *_proxy environment variables that kubeadm adds by default. + This option takes effect only on Kubernetes >=1.31.0. + items: + description: EnvVar represents an environment + variable present in a Container. + properties: + name: + description: Name of the environment variable. + Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment + variable's value. Cannot be used if value + is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the + ConfigMap or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret + in the pod's namespace + properties: + key: + description: The key of the secret + to select from. Must be a valid + secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. + type: string + optional: + description: Specify whether the + Secret or its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array extraVolumes: description: ExtraVolumes is an extra set of host volumes, mounted to the control plane component. @@ -1848,6 +2384,12 @@ spec: - IfNotPresent - Never type: string + imagePullSerial: + description: |- + ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + This option takes effect only on Kubernetes >=1.31.0. + Default: true (defaulted in kubeadm) + type: boolean kubeletExtraArgs: additionalProperties: type: string @@ -2207,6 +2749,12 @@ spec: - IfNotPresent - Never type: string + imagePullSerial: + description: |- + ImagePullSerial specifies if image pulling performed by kubeadm must be done serially or in parallel. + This option takes effect only on Kubernetes >=1.31.0. + Default: true (defaulted in kubeadm) + type: boolean kubeletExtraArgs: additionalProperties: type: string diff --git a/controlplane/kubeadm/internal/filters_test.go b/controlplane/kubeadm/internal/filters_test.go index a496d5e1857f..fb124b195662 100644 --- a/controlplane/kubeadm/internal/filters_test.go +++ b/controlplane/kubeadm/internal/filters_test.go @@ -17,6 +17,7 @@ limitations under the License. package internal import ( + "encoding/json" "testing" . "github.com/onsi/gomega" @@ -153,6 +154,54 @@ func TestMatchClusterConfiguration(t *testing.T) { g.Expect(match).To(BeTrue()) g.Expect(diff).To(BeEmpty()) }) + t.Run("Check we are not introducing unexpected rollouts when changing the API", func(t *testing.T) { + g := NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &bootstrapv1.ClusterConfiguration{ + APIServer: bootstrapv1.APIServer{ + ControlPlaneComponent: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: map[string]string{"foo": "bar"}, + }, + }, + ControllerManager: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: map[string]string{"foo": "bar"}, + }, + Scheduler: bootstrapv1.ControlPlaneComponent{ + ExtraArgs: map[string]string{"foo": "bar"}, + }, + DNS: bootstrapv1.DNS{ + ImageMeta: bootstrapv1.ImageMeta{ + ImageTag: "v1.10.1", + ImageRepository: "gcr.io/capi-test", + }, + }, + }, + }, + }, + } + + // 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. + clusterConfigCheckPoint := []byte("{\"etcd\":{},\"networking\":{},\"apiServer\":{\"extraArgs\":{\"foo\":\"bar\"}},\"controllerManager\":{\"extraArgs\":{\"foo\":\"bar\"}},\"scheduler\":{\"extraArgs\":{\"foo\":\"bar\"}},\"dns\":{\"imageRepository\":\"gcr.io/capi-test\",\"imageTag\":\"v1.10.1\"}}") + + // compute how a serialized ClusterConfiguration looks like now + clusterConfig, err := json.Marshal(kcp.Spec.KubeadmConfigSpec.ClusterConfiguration) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(clusterConfig).To(Equal(clusterConfigCheckPoint)) + + // check the match function detects if a Machine with the annotation string above matches the object it originates from (round trip). + m := &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + controlplanev1.KubeadmClusterConfigurationAnnotation: string(clusterConfig), + }, + }, + } + g.Expect(matchClusterConfiguration(kcp, m)).To(BeTrue()) + }) } func TestGetAdjustedKcpConfig(t *testing.T) { diff --git a/internal/apis/bootstrap/kubeadm/v1alpha3/conversion.go b/internal/apis/bootstrap/kubeadm/v1alpha3/conversion.go index e36b0f3203cb..091bca63d2de 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha3/conversion.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha3/conversion.go @@ -37,70 +37,77 @@ func (src *KubeadmConfig) ConvertTo(dstRaw conversion.Hub) error { if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { return err } + MergeRestoredKubeadmConfigSpec(&dst.Spec, &restored.Spec) - dst.Spec.Files = restored.Spec.Files + return nil +} + +func MergeRestoredKubeadmConfigSpec(dst *bootstrapv1.KubeadmConfigSpec, restored *bootstrapv1.KubeadmConfigSpec) { + dst.Files = restored.Files - dst.Spec.Users = restored.Spec.Users - if restored.Spec.Users != nil { - for i := range restored.Spec.Users { - if restored.Spec.Users[i].PasswdFrom != nil { - dst.Spec.Users[i].PasswdFrom = restored.Spec.Users[i].PasswdFrom + dst.Users = restored.Users + if restored.Users != nil { + for i := range restored.Users { + if restored.Users[i].PasswdFrom != nil { + dst.Users[i].PasswdFrom = restored.Users[i].PasswdFrom } } } - if restored.Spec.JoinConfiguration != nil && restored.Spec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors != nil { - if dst.Spec.JoinConfiguration == nil { - dst.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} + dst.Ignition = restored.Ignition + + if restored.ClusterConfiguration != nil { + if dst.ClusterConfiguration == nil { + dst.ClusterConfiguration = &bootstrapv1.ClusterConfiguration{} } - dst.Spec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors = restored.Spec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors - } + dst.ClusterConfiguration.APIServer.ExtraEnvs = restored.ClusterConfiguration.APIServer.ExtraEnvs + dst.ClusterConfiguration.ControllerManager.ExtraEnvs = restored.ClusterConfiguration.ControllerManager.ExtraEnvs + dst.ClusterConfiguration.Scheduler.ExtraEnvs = restored.ClusterConfiguration.Scheduler.ExtraEnvs - if restored.Spec.InitConfiguration != nil && restored.Spec.InitConfiguration.NodeRegistration.IgnorePreflightErrors != nil { - if dst.Spec.InitConfiguration == nil { - dst.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} + if restored.ClusterConfiguration.Etcd.Local != nil { + if dst.ClusterConfiguration.Etcd.Local == nil { + dst.ClusterConfiguration.Etcd.Local = &bootstrapv1.LocalEtcd{} + } + dst.ClusterConfiguration.Etcd.Local.ExtraEnvs = restored.ClusterConfiguration.Etcd.Local.ExtraEnvs } - dst.Spec.InitConfiguration.NodeRegistration.IgnorePreflightErrors = restored.Spec.InitConfiguration.NodeRegistration.IgnorePreflightErrors } - dst.Spec.Ignition = restored.Spec.Ignition - if restored.Spec.InitConfiguration != nil { - if dst.Spec.InitConfiguration == nil { - dst.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} + if restored.InitConfiguration != nil { + if dst.InitConfiguration == nil { + dst.InitConfiguration = &bootstrapv1.InitConfiguration{} } - dst.Spec.InitConfiguration.Patches = restored.Spec.InitConfiguration.Patches - dst.Spec.InitConfiguration.SkipPhases = restored.Spec.InitConfiguration.SkipPhases + dst.InitConfiguration.Patches = restored.InitConfiguration.Patches + dst.InitConfiguration.SkipPhases = restored.InitConfiguration.SkipPhases + + // Important! whenever adding fields to NodeRegistration, same fields must be added to hub.NodeRegistration's custom serialization func + // otherwise those field won't exist in restored. + + dst.InitConfiguration.NodeRegistration.IgnorePreflightErrors = restored.InitConfiguration.NodeRegistration.IgnorePreflightErrors + dst.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.InitConfiguration.NodeRegistration.ImagePullPolicy + dst.InitConfiguration.NodeRegistration.ImagePullSerial = restored.InitConfiguration.NodeRegistration.ImagePullSerial } - if restored.Spec.JoinConfiguration != nil { - if dst.Spec.JoinConfiguration == nil { - dst.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} + + if restored.JoinConfiguration != nil { + if dst.JoinConfiguration == nil { + dst.JoinConfiguration = &bootstrapv1.JoinConfiguration{} } - dst.Spec.JoinConfiguration.Patches = restored.Spec.JoinConfiguration.Patches - dst.Spec.JoinConfiguration.SkipPhases = restored.Spec.JoinConfiguration.SkipPhases + dst.JoinConfiguration.Patches = restored.JoinConfiguration.Patches + dst.JoinConfiguration.SkipPhases = restored.JoinConfiguration.SkipPhases - if restored.Spec.JoinConfiguration.Discovery.File != nil && restored.Spec.JoinConfiguration.Discovery.File.KubeConfig != nil { - if dst.Spec.JoinConfiguration.Discovery.File == nil { - dst.Spec.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} + if restored.JoinConfiguration.Discovery.File != nil && restored.JoinConfiguration.Discovery.File.KubeConfig != nil { + if dst.JoinConfiguration.Discovery.File == nil { + dst.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} } - dst.Spec.JoinConfiguration.Discovery.File.KubeConfig = restored.Spec.JoinConfiguration.Discovery.File.KubeConfig + dst.JoinConfiguration.Discovery.File.KubeConfig = restored.JoinConfiguration.Discovery.File.KubeConfig } - } - if restored.Spec.JoinConfiguration != nil && restored.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.JoinConfiguration == nil { - dst.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy - } + // Important! whenever adding fields to NodeRegistration, same fields must be added to hub.NodeRegistration's custom serialization func + // otherwise those field won't exist in restored. - if restored.Spec.InitConfiguration != nil && restored.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.InitConfiguration == nil { - dst.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy + dst.JoinConfiguration.NodeRegistration.IgnorePreflightErrors = restored.JoinConfiguration.NodeRegistration.IgnorePreflightErrors + dst.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.JoinConfiguration.NodeRegistration.ImagePullPolicy + dst.JoinConfiguration.NodeRegistration.ImagePullSerial = restored.JoinConfiguration.NodeRegistration.ImagePullSerial } - - return nil } func (dst *KubeadmConfig) ConvertFrom(srcRaw conversion.Hub) error { @@ -143,69 +150,9 @@ func (src *KubeadmConfigTemplate) ConvertTo(dstRaw conversion.Hub) error { return err } - dst.Spec.Template.Spec.Files = restored.Spec.Template.Spec.Files - - dst.Spec.Template.Spec.Users = restored.Spec.Template.Spec.Users - if restored.Spec.Template.Spec.Users != nil { - for i := range restored.Spec.Template.Spec.Users { - if restored.Spec.Template.Spec.Users[i].PasswdFrom != nil { - dst.Spec.Template.Spec.Users[i].PasswdFrom = restored.Spec.Template.Spec.Users[i].PasswdFrom - } - } - } - dst.Spec.Template.ObjectMeta = restored.Spec.Template.ObjectMeta - if restored.Spec.Template.Spec.JoinConfiguration != nil && restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors != nil { - if dst.Spec.Template.Spec.JoinConfiguration == nil { - dst.Spec.Template.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.Template.Spec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors = restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors - } - - if restored.Spec.Template.Spec.InitConfiguration != nil && restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.IgnorePreflightErrors != nil { - if dst.Spec.Template.Spec.InitConfiguration == nil { - dst.Spec.Template.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.Template.Spec.InitConfiguration.NodeRegistration.IgnorePreflightErrors = restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.IgnorePreflightErrors - } - - dst.Spec.Template.Spec.Ignition = restored.Spec.Template.Spec.Ignition - if restored.Spec.Template.Spec.InitConfiguration != nil { - if dst.Spec.Template.Spec.InitConfiguration == nil { - dst.Spec.Template.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.Template.Spec.InitConfiguration.Patches = restored.Spec.Template.Spec.InitConfiguration.Patches - dst.Spec.Template.Spec.InitConfiguration.SkipPhases = restored.Spec.Template.Spec.InitConfiguration.SkipPhases - } - if restored.Spec.Template.Spec.JoinConfiguration != nil { - if dst.Spec.Template.Spec.JoinConfiguration == nil { - dst.Spec.Template.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.Template.Spec.JoinConfiguration.Patches = restored.Spec.Template.Spec.JoinConfiguration.Patches - dst.Spec.Template.Spec.JoinConfiguration.SkipPhases = restored.Spec.Template.Spec.JoinConfiguration.SkipPhases - - if restored.Spec.Template.Spec.JoinConfiguration.Discovery.File != nil && restored.Spec.Template.Spec.JoinConfiguration.Discovery.File.KubeConfig != nil { - if dst.Spec.Template.Spec.JoinConfiguration.Discovery.File == nil { - dst.Spec.Template.Spec.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} - } - dst.Spec.Template.Spec.JoinConfiguration.Discovery.File.KubeConfig = restored.Spec.Template.Spec.JoinConfiguration.Discovery.File.KubeConfig - } - } - - if restored.Spec.Template.Spec.JoinConfiguration != nil && restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.Template.Spec.JoinConfiguration == nil { - dst.Spec.Template.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy - } - - if restored.Spec.Template.Spec.InitConfiguration != nil && restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.Template.Spec.InitConfiguration == nil { - dst.Spec.Template.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy - } + MergeRestoredKubeadmConfigSpec(&dst.Spec.Template.Spec, &restored.Spec.Template.Spec) return nil } diff --git a/internal/apis/bootstrap/kubeadm/v1alpha3/suite_test.go b/internal/apis/bootstrap/kubeadm/v1alpha3/suite_test.go deleted file mode 100644 index 1bff9a48c8b3..000000000000 --- a/internal/apis/bootstrap/kubeadm/v1alpha3/suite_test.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha3 - -import ( - "os" - "testing" - - // +kubebuilder:scaffold:imports - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/kubernetes/scheme" - ctrl "sigs.k8s.io/controller-runtime" - - "sigs.k8s.io/cluster-api/internal/test/envtest" -) - -var ( - env *envtest.Environment - ctx = ctrl.SetupSignalHandler() -) - -func TestMain(m *testing.M) { - utilruntime.Must(AddToScheme(scheme.Scheme)) - - os.Exit(envtest.Run(ctx, envtest.RunInput{ - M: m, - SetupEnv: func(e *envtest.Environment) { env = e }, - })) -} diff --git a/internal/apis/bootstrap/kubeadm/v1alpha4/conversion.go b/internal/apis/bootstrap/kubeadm/v1alpha4/conversion.go index 8d367c8934a5..9544cb41df7b 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha4/conversion.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha4/conversion.go @@ -36,56 +36,75 @@ func (src *KubeadmConfig) ConvertTo(dstRaw conversion.Hub) error { if ok, err := utilconversion.UnmarshalData(src, restored); err != nil || !ok { return err } + MergeRestoredKubeadmConfigSpec(&dst.Spec, &restored.Spec) - dst.Spec.Files = restored.Spec.Files + return nil +} + +func MergeRestoredKubeadmConfigSpec(dst *bootstrapv1.KubeadmConfigSpec, restored *bootstrapv1.KubeadmConfigSpec) { + dst.Files = restored.Files - dst.Spec.Users = restored.Spec.Users - if restored.Spec.Users != nil { - for i := range restored.Spec.Users { - if restored.Spec.Users[i].PasswdFrom != nil { - dst.Spec.Users[i].PasswdFrom = restored.Spec.Users[i].PasswdFrom + dst.Users = restored.Users + if restored.Users != nil { + for i := range restored.Users { + if restored.Users[i].PasswdFrom != nil { + dst.Users[i].PasswdFrom = restored.Users[i].PasswdFrom } } } - dst.Spec.Ignition = restored.Spec.Ignition - if restored.Spec.InitConfiguration != nil { - if dst.Spec.InitConfiguration == nil { - dst.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.InitConfiguration.Patches = restored.Spec.InitConfiguration.Patches - dst.Spec.InitConfiguration.SkipPhases = restored.Spec.InitConfiguration.SkipPhases - } - if restored.Spec.JoinConfiguration != nil { - if dst.Spec.JoinConfiguration == nil { - dst.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} + dst.Ignition = restored.Ignition + + if restored.ClusterConfiguration != nil { + if dst.ClusterConfiguration == nil { + dst.ClusterConfiguration = &bootstrapv1.ClusterConfiguration{} } - dst.Spec.JoinConfiguration.Patches = restored.Spec.JoinConfiguration.Patches - dst.Spec.JoinConfiguration.SkipPhases = restored.Spec.JoinConfiguration.SkipPhases + dst.ClusterConfiguration.APIServer.ExtraEnvs = restored.ClusterConfiguration.APIServer.ExtraEnvs + dst.ClusterConfiguration.ControllerManager.ExtraEnvs = restored.ClusterConfiguration.ControllerManager.ExtraEnvs + dst.ClusterConfiguration.Scheduler.ExtraEnvs = restored.ClusterConfiguration.Scheduler.ExtraEnvs - if restored.Spec.JoinConfiguration.Discovery.File != nil && restored.Spec.JoinConfiguration.Discovery.File.KubeConfig != nil { - if dst.Spec.JoinConfiguration.Discovery.File == nil { - dst.Spec.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} + if restored.ClusterConfiguration.Etcd.Local != nil { + if dst.ClusterConfiguration.Etcd.Local == nil { + dst.ClusterConfiguration.Etcd.Local = &bootstrapv1.LocalEtcd{} } - dst.Spec.JoinConfiguration.Discovery.File.KubeConfig = restored.Spec.JoinConfiguration.Discovery.File.KubeConfig + dst.ClusterConfiguration.Etcd.Local.ExtraEnvs = restored.ClusterConfiguration.Etcd.Local.ExtraEnvs } } - if restored.Spec.JoinConfiguration != nil && restored.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.JoinConfiguration == nil { - dst.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} + if restored.InitConfiguration != nil { + if dst.InitConfiguration == nil { + dst.InitConfiguration = &bootstrapv1.InitConfiguration{} } - dst.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy + dst.InitConfiguration.Patches = restored.InitConfiguration.Patches + dst.InitConfiguration.SkipPhases = restored.InitConfiguration.SkipPhases + + // Important! whenever adding fields to NodeRegistration, same fields must be added to hub.NodeRegistration's custom serialization func + // otherwise those field won't exist in restored. + + dst.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.InitConfiguration.NodeRegistration.ImagePullPolicy + dst.InitConfiguration.NodeRegistration.ImagePullSerial = restored.InitConfiguration.NodeRegistration.ImagePullSerial } - if restored.Spec.InitConfiguration != nil && restored.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.InitConfiguration == nil { - dst.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} + if restored.JoinConfiguration != nil { + if dst.JoinConfiguration == nil { + dst.JoinConfiguration = &bootstrapv1.JoinConfiguration{} } - dst.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy - } + dst.JoinConfiguration.Patches = restored.JoinConfiguration.Patches + dst.JoinConfiguration.SkipPhases = restored.JoinConfiguration.SkipPhases - return nil + if restored.JoinConfiguration.Discovery.File != nil && restored.JoinConfiguration.Discovery.File.KubeConfig != nil { + if dst.JoinConfiguration.Discovery.File == nil { + dst.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} + } + dst.JoinConfiguration.Discovery.File.KubeConfig = restored.JoinConfiguration.Discovery.File.KubeConfig + } + + // Important! whenever adding fields to NodeRegistration, same fields must be added to hub.NodeRegistration's custom serialization func + // otherwise those field won't exist in restored. + + dst.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.JoinConfiguration.NodeRegistration.ImagePullPolicy + dst.JoinConfiguration.NodeRegistration.ImagePullSerial = restored.JoinConfiguration.NodeRegistration.ImagePullSerial + } } func (dst *KubeadmConfig) ConvertFrom(srcRaw conversion.Hub) error { @@ -123,55 +142,9 @@ func (src *KubeadmConfigTemplate) ConvertTo(dstRaw conversion.Hub) error { return err } - dst.Spec.Template.Spec.Files = restored.Spec.Template.Spec.Files - - dst.Spec.Template.Spec.Users = restored.Spec.Template.Spec.Users - if restored.Spec.Template.Spec.Users != nil { - for i := range restored.Spec.Template.Spec.Users { - if restored.Spec.Template.Spec.Users[i].PasswdFrom != nil { - dst.Spec.Template.Spec.Users[i].PasswdFrom = restored.Spec.Template.Spec.Users[i].PasswdFrom - } - } - } - dst.Spec.Template.ObjectMeta = restored.Spec.Template.ObjectMeta - dst.Spec.Template.Spec.Ignition = restored.Spec.Template.Spec.Ignition - if restored.Spec.Template.Spec.InitConfiguration != nil { - if dst.Spec.Template.Spec.InitConfiguration == nil { - dst.Spec.Template.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.Template.Spec.InitConfiguration.Patches = restored.Spec.Template.Spec.InitConfiguration.Patches - dst.Spec.Template.Spec.InitConfiguration.SkipPhases = restored.Spec.Template.Spec.InitConfiguration.SkipPhases - } - if restored.Spec.Template.Spec.JoinConfiguration != nil { - if dst.Spec.Template.Spec.JoinConfiguration == nil { - dst.Spec.Template.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.Template.Spec.JoinConfiguration.Patches = restored.Spec.Template.Spec.JoinConfiguration.Patches - dst.Spec.Template.Spec.JoinConfiguration.SkipPhases = restored.Spec.Template.Spec.JoinConfiguration.SkipPhases - - if restored.Spec.Template.Spec.JoinConfiguration.Discovery.File != nil && restored.Spec.Template.Spec.JoinConfiguration.Discovery.File.KubeConfig != nil { - if dst.Spec.Template.Spec.JoinConfiguration.Discovery.File == nil { - dst.Spec.Template.Spec.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} - } - dst.Spec.Template.Spec.JoinConfiguration.Discovery.File.KubeConfig = restored.Spec.Template.Spec.JoinConfiguration.Discovery.File.KubeConfig - } - } - - if restored.Spec.Template.Spec.JoinConfiguration != nil && restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.Template.Spec.JoinConfiguration == nil { - dst.Spec.Template.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.JoinConfiguration.NodeRegistration.ImagePullPolicy - } - - if restored.Spec.Template.Spec.InitConfiguration != nil && restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.Template.Spec.InitConfiguration == nil { - dst.Spec.Template.Spec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.InitConfiguration.NodeRegistration.ImagePullPolicy - } + MergeRestoredKubeadmConfigSpec(&dst.Spec.Template.Spec, &restored.Spec.Template.Spec) return nil } @@ -239,3 +212,13 @@ func Convert_v1beta1_FileDiscovery_To_v1alpha4_FileDiscovery(in *bootstrapv1.Fil // JoinConfiguration.Discovery.File.KubeConfig does not exist in v1alpha4 APIs. return autoConvert_v1beta1_FileDiscovery_To_v1alpha4_FileDiscovery(in, out, s) } + +func Convert_v1beta1_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(in *bootstrapv1.ControlPlaneComponent, out *ControlPlaneComponent, s apiconversion.Scope) error { + // ControlPlaneComponent.ExtraEnvs does not exist in v1alpha4 APIs. + return autoConvert_v1beta1_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(in, out, s) +} + +func Convert_v1beta1_LocalEtcd_To_v1alpha4_LocalEtcd(in *bootstrapv1.LocalEtcd, out *LocalEtcd, s apiconversion.Scope) error { + // LocalEtcd.ExtraEnvs does not exist in v1alpha4 APIs. + return autoConvert_v1beta1_LocalEtcd_To_v1alpha4_LocalEtcd(in, out, s) +} diff --git a/internal/apis/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go b/internal/apis/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go index 131202cc4238..a2e6ec96f77c 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go @@ -641,14 +641,10 @@ func Convert_v1alpha4_ControlPlaneComponent_To_v1beta1_ControlPlaneComponent(in func autoConvert_v1beta1_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) out.ExtraVolumes = *(*[]HostPathMount)(unsafe.Pointer(&in.ExtraVolumes)) + // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type return nil } -// Convert_v1beta1_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent is an autogenerated conversion function. -func Convert_v1beta1_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(in *v1beta1.ControlPlaneComponent, out *ControlPlaneComponent, s conversion.Scope) error { - return autoConvert_v1beta1_ControlPlaneComponent_To_v1alpha4_ControlPlaneComponent(in, out, s) -} - func autoConvert_v1alpha4_DNS_To_v1beta1_DNS(in *DNS, out *v1beta1.DNS, s conversion.Scope) error { if err := Convert_v1alpha4_ImageMeta_To_v1beta1_ImageMeta(&in.ImageMeta, &out.ImageMeta, s); err != nil { return err @@ -738,7 +734,15 @@ func Convert_v1beta1_DiskSetup_To_v1alpha4_DiskSetup(in *v1beta1.DiskSetup, out } func autoConvert_v1alpha4_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s conversion.Scope) error { - out.Local = (*v1beta1.LocalEtcd)(unsafe.Pointer(in.Local)) + if in.Local != nil { + in, out := &in.Local, &out.Local + *out = new(v1beta1.LocalEtcd) + if err := Convert_v1alpha4_LocalEtcd_To_v1beta1_LocalEtcd(*in, *out, s); err != nil { + return err + } + } else { + out.Local = nil + } out.External = (*v1beta1.ExternalEtcd)(unsafe.Pointer(in.External)) return nil } @@ -749,7 +753,15 @@ func Convert_v1alpha4_Etcd_To_v1beta1_Etcd(in *Etcd, out *v1beta1.Etcd, s conver } func autoConvert_v1beta1_Etcd_To_v1alpha4_Etcd(in *v1beta1.Etcd, out *Etcd, s conversion.Scope) error { - out.Local = (*LocalEtcd)(unsafe.Pointer(in.Local)) + if in.Local != nil { + in, out := &in.Local, &out.Local + *out = new(LocalEtcd) + if err := Convert_v1beta1_LocalEtcd_To_v1alpha4_LocalEtcd(*in, *out, s); err != nil { + return err + } + } else { + out.Local = nil + } out.External = (*ExternalEtcd)(unsafe.Pointer(in.External)) return nil } @@ -1092,7 +1104,15 @@ func Convert_v1beta1_KubeadmConfigList_To_v1alpha4_KubeadmConfigList(in *v1beta1 } func autoConvert_v1alpha4_KubeadmConfigSpec_To_v1beta1_KubeadmConfigSpec(in *KubeadmConfigSpec, out *v1beta1.KubeadmConfigSpec, s conversion.Scope) error { - out.ClusterConfiguration = (*v1beta1.ClusterConfiguration)(unsafe.Pointer(in.ClusterConfiguration)) + if in.ClusterConfiguration != nil { + in, out := &in.ClusterConfiguration, &out.ClusterConfiguration + *out = new(v1beta1.ClusterConfiguration) + if err := Convert_v1alpha4_ClusterConfiguration_To_v1beta1_ClusterConfiguration(*in, *out, s); err != nil { + return err + } + } else { + out.ClusterConfiguration = nil + } if in.InitConfiguration != nil { in, out := &in.InitConfiguration, &out.InitConfiguration *out = new(v1beta1.InitConfiguration) @@ -1150,7 +1170,15 @@ func Convert_v1alpha4_KubeadmConfigSpec_To_v1beta1_KubeadmConfigSpec(in *Kubeadm } func autoConvert_v1beta1_KubeadmConfigSpec_To_v1alpha4_KubeadmConfigSpec(in *v1beta1.KubeadmConfigSpec, out *KubeadmConfigSpec, s conversion.Scope) error { - out.ClusterConfiguration = (*ClusterConfiguration)(unsafe.Pointer(in.ClusterConfiguration)) + if in.ClusterConfiguration != nil { + in, out := &in.ClusterConfiguration, &out.ClusterConfiguration + *out = new(ClusterConfiguration) + if err := Convert_v1beta1_ClusterConfiguration_To_v1alpha4_ClusterConfiguration(*in, *out, s); err != nil { + return err + } + } else { + out.ClusterConfiguration = nil + } if in.InitConfiguration != nil { in, out := &in.InitConfiguration, &out.InitConfiguration *out = new(InitConfiguration) @@ -1367,16 +1395,12 @@ func autoConvert_v1beta1_LocalEtcd_To_v1alpha4_LocalEtcd(in *v1beta1.LocalEtcd, } out.DataDir = in.DataDir out.ExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.ExtraArgs)) + // WARNING: in.ExtraEnvs requires manual conversion: does not exist in peer-type out.ServerCertSANs = *(*[]string)(unsafe.Pointer(&in.ServerCertSANs)) out.PeerCertSANs = *(*[]string)(unsafe.Pointer(&in.PeerCertSANs)) return nil } -// Convert_v1beta1_LocalEtcd_To_v1alpha4_LocalEtcd is an autogenerated conversion function. -func Convert_v1beta1_LocalEtcd_To_v1alpha4_LocalEtcd(in *v1beta1.LocalEtcd, out *LocalEtcd, s conversion.Scope) error { - return autoConvert_v1beta1_LocalEtcd_To_v1alpha4_LocalEtcd(in, out, s) -} - func autoConvert_v1alpha4_NTP_To_v1beta1_NTP(in *NTP, out *v1beta1.NTP, s conversion.Scope) error { out.Servers = *(*[]string)(unsafe.Pointer(&in.Servers)) out.Enabled = (*bool)(unsafe.Pointer(in.Enabled)) @@ -1444,6 +1468,7 @@ func autoConvert_v1beta1_NodeRegistrationOptions_To_v1alpha4_NodeRegistrationOpt out.KubeletExtraArgs = *(*map[string]string)(unsafe.Pointer(&in.KubeletExtraArgs)) out.IgnorePreflightErrors = *(*[]string)(unsafe.Pointer(&in.IgnorePreflightErrors)) // WARNING: in.ImagePullPolicy requires manual conversion: does not exist in peer-type + // WARNING: in.ImagePullSerial requires manual conversion: does not exist in peer-type return nil } diff --git a/internal/apis/controlplane/kubeadm/v1alpha3/conversion.go b/internal/apis/controlplane/kubeadm/v1alpha3/conversion.go index b1fe7a67e3ad..67a884a4911d 100644 --- a/internal/apis/controlplane/kubeadm/v1alpha3/conversion.go +++ b/internal/apis/controlplane/kubeadm/v1alpha3/conversion.go @@ -41,72 +41,9 @@ func (src *KubeadmControlPlane) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.MachineTemplate.ObjectMeta = restored.Spec.MachineTemplate.ObjectMeta dst.Spec.MachineTemplate.NodeDeletionTimeout = restored.Spec.MachineTemplate.NodeDeletionTimeout - dst.Spec.KubeadmConfigSpec.Files = restored.Spec.KubeadmConfigSpec.Files - dst.Spec.KubeadmConfigSpec.Users = restored.Spec.KubeadmConfigSpec.Users dst.Spec.MachineTemplate.NodeVolumeDetachTimeout = restored.Spec.MachineTemplate.NodeVolumeDetachTimeout - dst.Status.Version = restored.Status.Version - - if restored.Spec.KubeadmConfigSpec.Users != nil { - for i := range restored.Spec.KubeadmConfigSpec.Users { - if restored.Spec.KubeadmConfigSpec.Users[i].PasswdFrom != nil { - dst.Spec.KubeadmConfigSpec.Users[i].PasswdFrom = restored.Spec.KubeadmConfigSpec.Users[i].PasswdFrom - } - } - } - - if restored.Spec.KubeadmConfigSpec.JoinConfiguration != nil && restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors != nil { - if dst.Spec.KubeadmConfigSpec.JoinConfiguration == nil { - dst.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors = restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.IgnorePreflightErrors - } - - if restored.Spec.KubeadmConfigSpec.InitConfiguration != nil && restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.IgnorePreflightErrors != nil { - if dst.Spec.KubeadmConfigSpec.InitConfiguration == nil { - dst.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.IgnorePreflightErrors = restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.IgnorePreflightErrors - } - - dst.Spec.KubeadmConfigSpec.Ignition = restored.Spec.KubeadmConfigSpec.Ignition - if restored.Spec.KubeadmConfigSpec.InitConfiguration != nil { - if dst.Spec.KubeadmConfigSpec.InitConfiguration == nil { - dst.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.KubeadmConfigSpec.InitConfiguration.Patches = restored.Spec.KubeadmConfigSpec.InitConfiguration.Patches - dst.Spec.KubeadmConfigSpec.InitConfiguration.SkipPhases = restored.Spec.KubeadmConfigSpec.InitConfiguration.SkipPhases - } - if restored.Spec.KubeadmConfigSpec.JoinConfiguration != nil { - if dst.Spec.KubeadmConfigSpec.JoinConfiguration == nil { - dst.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.KubeadmConfigSpec.JoinConfiguration.Patches = restored.Spec.KubeadmConfigSpec.JoinConfiguration.Patches - dst.Spec.KubeadmConfigSpec.JoinConfiguration.SkipPhases = restored.Spec.KubeadmConfigSpec.JoinConfiguration.SkipPhases - - if restored.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File != nil && restored.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig != nil { - if dst.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File == nil { - dst.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} - } - dst.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig = restored.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig - } - } - dst.Spec.RolloutBefore = restored.Spec.RolloutBefore - if restored.Spec.KubeadmConfigSpec.JoinConfiguration != nil && restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.KubeadmConfigSpec.JoinConfiguration == nil { - dst.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy - } - - if restored.Spec.KubeadmConfigSpec.InitConfiguration != nil && restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.KubeadmConfigSpec.InitConfiguration == nil { - dst.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy - } - if restored.Spec.RemediationStrategy != nil { dst.Spec.RemediationStrategy = restored.Spec.RemediationStrategy } @@ -114,6 +51,10 @@ func (src *KubeadmControlPlane) ConvertTo(dstRaw conversion.Hub) error { dst.Status.LastRemediation = restored.Status.LastRemediation } + bootstrapv1alpha3.MergeRestoredKubeadmConfigSpec(&dst.Spec.KubeadmConfigSpec, &restored.Spec.KubeadmConfigSpec) + + dst.Status.Version = restored.Status.Version + return nil } diff --git a/internal/apis/controlplane/kubeadm/v1alpha3/suite_test.go b/internal/apis/controlplane/kubeadm/v1alpha3/suite_test.go deleted file mode 100644 index 1bff9a48c8b3..000000000000 --- a/internal/apis/controlplane/kubeadm/v1alpha3/suite_test.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2021 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha3 - -import ( - "os" - "testing" - - // +kubebuilder:scaffold:imports - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/client-go/kubernetes/scheme" - ctrl "sigs.k8s.io/controller-runtime" - - "sigs.k8s.io/cluster-api/internal/test/envtest" -) - -var ( - env *envtest.Environment - ctx = ctrl.SetupSignalHandler() -) - -func TestMain(m *testing.M) { - utilruntime.Must(AddToScheme(scheme.Scheme)) - - os.Exit(envtest.Run(ctx, envtest.RunInput{ - M: m, - SetupEnv: func(e *envtest.Environment) { env = e }, - })) -} diff --git a/internal/apis/controlplane/kubeadm/v1alpha4/conversion.go b/internal/apis/controlplane/kubeadm/v1alpha4/conversion.go index 323cfbe81fb6..9c14902efa36 100644 --- a/internal/apis/controlplane/kubeadm/v1alpha4/conversion.go +++ b/internal/apis/controlplane/kubeadm/v1alpha4/conversion.go @@ -42,59 +42,9 @@ func (src *KubeadmControlPlane) ConvertTo(dstRaw conversion.Hub) error { return err } - dst.Spec.KubeadmConfigSpec.Files = restored.Spec.KubeadmConfigSpec.Files - - dst.Spec.KubeadmConfigSpec.Users = restored.Spec.KubeadmConfigSpec.Users - if restored.Spec.KubeadmConfigSpec.Users != nil { - for i := range restored.Spec.KubeadmConfigSpec.Users { - if restored.Spec.KubeadmConfigSpec.Users[i].PasswdFrom != nil { - dst.Spec.KubeadmConfigSpec.Users[i].PasswdFrom = restored.Spec.KubeadmConfigSpec.Users[i].PasswdFrom - } - } - } - - dst.Spec.KubeadmConfigSpec.Ignition = restored.Spec.KubeadmConfigSpec.Ignition - if restored.Spec.KubeadmConfigSpec.InitConfiguration != nil { - if dst.Spec.KubeadmConfigSpec.InitConfiguration == nil { - dst.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.KubeadmConfigSpec.InitConfiguration.Patches = restored.Spec.KubeadmConfigSpec.InitConfiguration.Patches - dst.Spec.KubeadmConfigSpec.InitConfiguration.SkipPhases = restored.Spec.KubeadmConfigSpec.InitConfiguration.SkipPhases - } - if restored.Spec.KubeadmConfigSpec.JoinConfiguration != nil { - if dst.Spec.KubeadmConfigSpec.JoinConfiguration == nil { - dst.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.KubeadmConfigSpec.JoinConfiguration.Patches = restored.Spec.KubeadmConfigSpec.JoinConfiguration.Patches - dst.Spec.KubeadmConfigSpec.JoinConfiguration.SkipPhases = restored.Spec.KubeadmConfigSpec.JoinConfiguration.SkipPhases - } - dst.Spec.MachineTemplate.NodeDeletionTimeout = restored.Spec.MachineTemplate.NodeDeletionTimeout - dst.Spec.RolloutBefore = restored.Spec.RolloutBefore dst.Spec.MachineTemplate.NodeVolumeDetachTimeout = restored.Spec.MachineTemplate.NodeVolumeDetachTimeout - - if restored.Spec.KubeadmConfigSpec.JoinConfiguration != nil { - if dst.Spec.KubeadmConfigSpec.JoinConfiguration == nil { - dst.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - if restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" { - dst.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy - } - - if restored.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File != nil && restored.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig != nil { - if dst.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File == nil { - dst.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} - } - dst.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig = restored.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig - } - } - - if restored.Spec.KubeadmConfigSpec.InitConfiguration != nil && restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.KubeadmConfigSpec.InitConfiguration == nil { - dst.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy - } + dst.Spec.RolloutBefore = restored.Spec.RolloutBefore if restored.Spec.RemediationStrategy != nil { dst.Spec.RemediationStrategy = restored.Spec.RemediationStrategy @@ -103,6 +53,8 @@ func (src *KubeadmControlPlane) ConvertTo(dstRaw conversion.Hub) error { dst.Status.LastRemediation = restored.Status.LastRemediation } + bootstrapv1alpha4.MergeRestoredKubeadmConfigSpec(&dst.Spec.KubeadmConfigSpec, &restored.Spec.KubeadmConfigSpec) + return nil } @@ -142,38 +94,13 @@ func (src *KubeadmControlPlaneTemplate) ConvertTo(dstRaw conversion.Hub) error { return err } - dst.Spec.Template.Spec.KubeadmConfigSpec.Files = restored.Spec.Template.Spec.KubeadmConfigSpec.Files - dst.Spec.Template.Spec.KubeadmConfigSpec.Users = restored.Spec.Template.Spec.KubeadmConfigSpec.Users - dst.Spec.Template.Spec.KubeadmConfigSpec.Ignition = restored.Spec.Template.Spec.KubeadmConfigSpec.Ignition dst.Spec.Template.Spec.MachineTemplate = restored.Spec.Template.Spec.MachineTemplate - if restored.Spec.Template.Spec.KubeadmConfigSpec.Users != nil { - for i := range restored.Spec.Template.Spec.KubeadmConfigSpec.Users { - if restored.Spec.Template.Spec.KubeadmConfigSpec.Users[i].PasswdFrom != nil { - dst.Spec.Template.Spec.KubeadmConfigSpec.Users[i].PasswdFrom = restored.Spec.Template.Spec.KubeadmConfigSpec.Users[i].PasswdFrom - } - } - } - dst.Spec.Template.ObjectMeta = restored.Spec.Template.ObjectMeta if restored.Spec.Template.Spec.MachineTemplate != nil { dst.Spec.Template.Spec.MachineTemplate.ObjectMeta = restored.Spec.Template.Spec.MachineTemplate.ObjectMeta } - if restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration != nil { - if dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration == nil { - dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.Patches = restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.Patches - dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.SkipPhases = restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.SkipPhases - } - if restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration != nil { - if dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration == nil { - dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.Patches = restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.Patches - dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.SkipPhases = restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.SkipPhases - } if dst.Spec.Template.Spec.MachineTemplate == nil { dst.Spec.Template.Spec.MachineTemplate = restored.Spec.Template.Spec.MachineTemplate } else if restored.Spec.Template.Spec.MachineTemplate != nil { @@ -183,33 +110,12 @@ func (src *KubeadmControlPlaneTemplate) ConvertTo(dstRaw conversion.Hub) error { dst.Spec.Template.Spec.RolloutBefore = restored.Spec.Template.Spec.RolloutBefore - if restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration != nil { - if dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration == nil { - dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration = &bootstrapv1.JoinConfiguration{} - } - if restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy != "" { - dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.NodeRegistration.ImagePullPolicy - } - - if restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File != nil && restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig != nil { - if dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File == nil { - dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File = &bootstrapv1.FileDiscovery{} - } - dst.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig = restored.Spec.Template.Spec.KubeadmConfigSpec.JoinConfiguration.Discovery.File.KubeConfig - } - } - - if restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration != nil && restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy != "" { - if dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration == nil { - dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration = &bootstrapv1.InitConfiguration{} - } - dst.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy = restored.Spec.Template.Spec.KubeadmConfigSpec.InitConfiguration.NodeRegistration.ImagePullPolicy - } - if restored.Spec.Template.Spec.RemediationStrategy != nil { dst.Spec.Template.Spec.RemediationStrategy = restored.Spec.Template.Spec.RemediationStrategy } + bootstrapv1alpha4.MergeRestoredKubeadmConfigSpec(&dst.Spec.Template.Spec.KubeadmConfigSpec, &restored.Spec.Template.Spec.KubeadmConfigSpec) + return nil }