diff --git a/.golangci.yml b/.golangci.yml index 80d2f5be2d35..c790472ca5c5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -238,7 +238,7 @@ linters: # should be removed as the referenced deprecated item is removed from the project. - linters: - staticcheck - text: 'SA1019: (bootstrapv1.ClusterStatus|KubeadmConfigSpec.UseExperimentalRetryJoin|scope.Config.Spec.UseExperimentalRetryJoin|DockerMachine.Spec.Bootstrapped|machineStatus.Bootstrapped|dockerMachine.Spec.Backend.Docker.Bootstrapped|dockerMachine.Spec.Bootstrapped|devMachine.Spec.Backend.Docker.Bootstrapped|c.TopologyPlan|clusterv1.ClusterClassVariableMetadata|clusterv1beta1.ClusterClassVariableMetadata|(variable|currentDefinition|specVar|newVariableDefinition|statusVarDefinition).Metadata) is deprecated' + text: 'SA1019: (bootstrapv1.ClusterStatus|DockerMachine.Spec.Bootstrapped|machineStatus.Bootstrapped|dockerMachine.Spec.Backend.Docker.Bootstrapped|dockerMachine.Spec.Bootstrapped|devMachine.Spec.Backend.Docker.Bootstrapped|c.TopologyPlan|clusterv1.ClusterClassVariableMetadata|clusterv1beta1.ClusterClassVariableMetadata|(variable|currentDefinition|specVar|newVariableDefinition|statusVarDefinition).Metadata) is deprecated' # Deprecations for MD revision management - linters: - staticcheck diff --git a/bootstrap/kubeadm/api/v1beta1/conversion.go b/bootstrap/kubeadm/api/v1beta1/conversion.go index 6e8833cb15e2..6d090edbbe92 100644 --- a/bootstrap/kubeadm/api/v1beta1/conversion.go +++ b/bootstrap/kubeadm/api/v1beta1/conversion.go @@ -82,6 +82,11 @@ func Convert_v1beta2_KubeadmConfigStatus_To_v1beta1_KubeadmConfigStatus(in *boot return nil } +func Convert_v1beta1_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *KubeadmConfigSpec, out *bootstrapv1.KubeadmConfigSpec, s apimachineryconversion.Scope) error { + // NOTE: v1beta2 KubeadmConfigSpec does not have UseExperimentalRetryJoin anymore, so it's fine to just lose this field. + return autoConvert_v1beta1_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in, out, s) +} + func Convert_v1beta1_KubeadmConfigStatus_To_v1beta2_KubeadmConfigStatus(in *KubeadmConfigStatus, out *bootstrapv1.KubeadmConfigStatus, s apimachineryconversion.Scope) error { if err := autoConvert_v1beta1_KubeadmConfigStatus_To_v1beta2_KubeadmConfigStatus(in, out, s); err != nil { return err diff --git a/bootstrap/kubeadm/api/v1beta1/conversion_test.go b/bootstrap/kubeadm/api/v1beta1/conversion_test.go index dac8067ddda3..5a619bd6ad06 100644 --- a/bootstrap/kubeadm/api/v1beta1/conversion_test.go +++ b/bootstrap/kubeadm/api/v1beta1/conversion_test.go @@ -39,14 +39,16 @@ func TestFuzzyConversion(t *testing.T) { FuzzerFuncs: []fuzzer.FuzzerFuncs{KubeadmConfigFuzzFuncs}, })) t.Run("for KubeadmConfigTemplate", utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ - Hub: &bootstrapv1.KubeadmConfigTemplate{}, - Spoke: &KubeadmConfigTemplate{}, + Hub: &bootstrapv1.KubeadmConfigTemplate{}, + Spoke: &KubeadmConfigTemplate{}, + FuzzerFuncs: []fuzzer.FuzzerFuncs{KubeadmConfigTemplateFuzzFuncs}, })) } func KubeadmConfigFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ hubKubeadmConfigStatus, + spokeKubeadmConfigSpec, spokeKubeadmConfigStatus, } } @@ -69,6 +71,13 @@ func hubKubeadmConfigStatus(in *bootstrapv1.KubeadmConfigStatus, c fuzz.Continue } } +func spokeKubeadmConfigSpec(in *KubeadmConfigSpec, c fuzz.Continue) { + c.FuzzNoCustom(in) + + // Drop UseExperimentalRetryJoin as we intentionally don't preserve it. + in.UseExperimentalRetryJoin = false +} + func spokeKubeadmConfigStatus(in *KubeadmConfigStatus, c fuzz.Continue) { c.FuzzNoCustom(in) // Drop empty structs with only omit empty fields. @@ -78,3 +87,9 @@ func spokeKubeadmConfigStatus(in *KubeadmConfigStatus, c fuzz.Continue) { } } } + +func KubeadmConfigTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { + return []interface{}{ + spokeKubeadmConfigSpec, + } +} diff --git a/bootstrap/kubeadm/api/v1beta1/zz_generated.conversion.go b/bootstrap/kubeadm/api/v1beta1/zz_generated.conversion.go index 8cfc53559f65..ea0c4588a8c0 100644 --- a/bootstrap/kubeadm/api/v1beta1/zz_generated.conversion.go +++ b/bootstrap/kubeadm/api/v1beta1/zz_generated.conversion.go @@ -370,11 +370,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*KubeadmConfigSpec)(nil), (*v1beta2.KubeadmConfigSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1beta1_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(a.(*KubeadmConfigSpec), b.(*v1beta2.KubeadmConfigSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*v1beta2.KubeadmConfigSpec)(nil), (*KubeadmConfigSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta2_KubeadmConfigSpec_To_v1beta1_KubeadmConfigSpec(a.(*v1beta2.KubeadmConfigSpec), b.(*KubeadmConfigSpec), scope) }); err != nil { @@ -530,6 +525,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*KubeadmConfigSpec)(nil), (*v1beta2.KubeadmConfigSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1beta1_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(a.(*KubeadmConfigSpec), b.(*v1beta2.KubeadmConfigSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*KubeadmConfigStatus)(nil), (*v1beta2.KubeadmConfigStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1beta1_KubeadmConfigStatus_To_v1beta2_KubeadmConfigStatus(a.(*KubeadmConfigStatus), b.(*v1beta2.KubeadmConfigStatus), scope) }); err != nil { @@ -1467,16 +1467,11 @@ func autoConvert_v1beta1_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *Kube out.NTP = (*v1beta2.NTP)(unsafe.Pointer(in.NTP)) out.Format = v1beta2.Format(in.Format) out.Verbosity = (*int32)(unsafe.Pointer(in.Verbosity)) - out.UseExperimentalRetryJoin = in.UseExperimentalRetryJoin + // WARNING: in.UseExperimentalRetryJoin requires manual conversion: does not exist in peer-type out.Ignition = (*v1beta2.IgnitionSpec)(unsafe.Pointer(in.Ignition)) return nil } -// Convert_v1beta1_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec is an autogenerated conversion function. -func Convert_v1beta1_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *KubeadmConfigSpec, out *v1beta2.KubeadmConfigSpec, s conversion.Scope) error { - return autoConvert_v1beta1_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in, out, s) -} - func autoConvert_v1beta2_KubeadmConfigSpec_To_v1beta1_KubeadmConfigSpec(in *v1beta2.KubeadmConfigSpec, out *KubeadmConfigSpec, s conversion.Scope) error { out.ClusterConfiguration = (*ClusterConfiguration)(unsafe.Pointer(in.ClusterConfiguration)) out.InitConfiguration = (*InitConfiguration)(unsafe.Pointer(in.InitConfiguration)) @@ -1491,7 +1486,6 @@ func autoConvert_v1beta2_KubeadmConfigSpec_To_v1beta1_KubeadmConfigSpec(in *v1be out.NTP = (*NTP)(unsafe.Pointer(in.NTP)) out.Format = Format(in.Format) out.Verbosity = (*int32)(unsafe.Pointer(in.Verbosity)) - out.UseExperimentalRetryJoin = in.UseExperimentalRetryJoin out.Ignition = (*IgnitionSpec)(unsafe.Pointer(in.Ignition)) return nil } diff --git a/bootstrap/kubeadm/api/v1beta2/kubeadmconfig_types.go b/bootstrap/kubeadm/api/v1beta2/kubeadmconfig_types.go index 1ba4cb6e87cb..3098df818a9a 100644 --- a/bootstrap/kubeadm/api/v1beta2/kubeadmconfig_types.go +++ b/bootstrap/kubeadm/api/v1beta2/kubeadmconfig_types.go @@ -122,22 +122,6 @@ type KubeadmConfigSpec struct { // +optional Verbosity *int32 `json:"verbosity,omitempty"` - // useExperimentalRetryJoin replaces a basic kubeadm command with a shell - // script with retries for joins. - // - // This is meant to be an experimental temporary workaround on some environments - // where joins fail due to timing (and other issues). The long term goal is to add retries to - // kubeadm proper and use that functionality. - // - // This will add about 40KB to userdata - // - // For more information, refer to https://github.com/kubernetes-sigs/cluster-api/pull/2763#discussion_r397306055. - // +optional - // - // Deprecated: This experimental fix is no longer needed and this field will be removed in a future release. - // When removing also remove from staticcheck exclude-rules for SA1019 in golangci.yml - UseExperimentalRetryJoin bool `json:"useExperimentalRetryJoin,omitempty"` - // ignition contains Ignition specific configuration. // +optional Ignition *IgnitionSpec `json:"ignition,omitempty"` @@ -347,16 +331,6 @@ func (c *KubeadmConfigSpec) validateIgnition(pathPrefix *field.Path) field.Error } } - if c.UseExperimentalRetryJoin { - allErrs = append( - allErrs, - field.Forbidden( - pathPrefix.Child("useExperimentalRetryJoin"), - cannotUseWithIgnition, - ), - ) - } - for i, file := range c.Files { if file.Encoding == Gzip || file.Encoding == GzipBase64 { allErrs = append( 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 74d8ffd82d47..58f9ef1d93b2 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 @@ -5881,22 +5881,6 @@ spec: type: string maxItems: 1000 type: array - useExperimentalRetryJoin: - description: |- - useExperimentalRetryJoin replaces a basic kubeadm command with a shell - script with retries for joins. - - This is meant to be an experimental temporary workaround on some environments - where joins fail due to timing (and other issues). The long term goal is to add retries to - kubeadm proper and use that functionality. - - This will add about 40KB to userdata - - For more information, refer to https://github.com/kubernetes-sigs/cluster-api/pull/2763#discussion_r397306055. - - Deprecated: This experimental fix is no longer needed and this field will be removed in a future release. - When removing also remove from staticcheck exclude-rules for SA1019 in golangci.yml - type: boolean users: description: users specifies extra users to add items: 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 39d620d2b81c..dad9be2a1307 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 @@ -5793,22 +5793,6 @@ spec: type: string maxItems: 1000 type: array - useExperimentalRetryJoin: - description: |- - useExperimentalRetryJoin replaces a basic kubeadm command with a shell - script with retries for joins. - - This is meant to be an experimental temporary workaround on some environments - where joins fail due to timing (and other issues). The long term goal is to add retries to - kubeadm proper and use that functionality. - - This will add about 40KB to userdata - - For more information, refer to https://github.com/kubernetes-sigs/cluster-api/pull/2763#discussion_r397306055. - - Deprecated: This experimental fix is no longer needed and this field will be removed in a future release. - When removing also remove from staticcheck exclude-rules for SA1019 in golangci.yml - type: boolean users: description: users specifies extra users to add items: diff --git a/bootstrap/kubeadm/internal/cloudinit/cloudinit.go b/bootstrap/kubeadm/internal/cloudinit/cloudinit.go index aaf9d7a0951d..6d78f5c363f3 100644 --- a/bootstrap/kubeadm/internal/cloudinit/cloudinit.go +++ b/bootstrap/kubeadm/internal/cloudinit/cloudinit.go @@ -18,7 +18,6 @@ package cloudinit import ( "bytes" - _ "embed" "fmt" "text/template" @@ -26,56 +25,42 @@ import ( "github.com/pkg/errors" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta2" - "sigs.k8s.io/cluster-api/util/version" ) const ( standardJoinCommand = "kubeadm join --config /run/kubeadm/kubeadm-join-config.yaml %s" // sentinelFileCommand writes a file to /run/cluster-api to signal successful Kubernetes bootstrapping in a way that // works both for Linux and Windows OS. - sentinelFileCommand = "echo success > /run/cluster-api/bootstrap-success.complete" - retriableJoinScriptName = "/usr/local/bin/kubeadm-bootstrap-script" - retriableJoinScriptOwner = "root" - retriableJoinScriptPermissions = "0755" - cloudConfigHeader = `## template: jinja + sentinelFileCommand = "echo success > /run/cluster-api/bootstrap-success.complete" + cloudConfigHeader = `## template: jinja #cloud-config ` ) // BaseUserData is shared across all the various types of files written to disk. type BaseUserData struct { - Header string - BootCommands []string - PreKubeadmCommands []string - PostKubeadmCommands []string - AdditionalFiles []bootstrapv1.File - WriteFiles []bootstrapv1.File - Users []bootstrapv1.User - NTP *bootstrapv1.NTP - DiskSetup *bootstrapv1.DiskSetup - Mounts []bootstrapv1.MountPoints - ControlPlane bool - UseExperimentalRetry bool - KubeadmCommand string - KubeadmVerbosity string - SentinelFileCommand string - KubernetesVersion semver.Version + Header string + BootCommands []string + PreKubeadmCommands []string + PostKubeadmCommands []string + AdditionalFiles []bootstrapv1.File + WriteFiles []bootstrapv1.File + Users []bootstrapv1.User + NTP *bootstrapv1.NTP + DiskSetup *bootstrapv1.DiskSetup + Mounts []bootstrapv1.MountPoints + ControlPlane bool + KubeadmCommand string + KubeadmVerbosity string + SentinelFileCommand string + KubernetesVersion semver.Version } -func (input *BaseUserData) prepare() error { +func (input *BaseUserData) prepare() { input.Header = cloudConfigHeader input.WriteFiles = append(input.WriteFiles, input.AdditionalFiles...) input.KubeadmCommand = fmt.Sprintf(standardJoinCommand, input.KubeadmVerbosity) - if input.UseExperimentalRetry { - input.KubeadmCommand = retriableJoinScriptName - joinScriptFile, err := generateBootstrapScript(input, input.KubernetesVersion) - if err != nil { - return errors.Wrap(err, "failed to generate user data for machine joining control plane") - } - input.WriteFiles = append(input.WriteFiles, *joinScriptFile) - } input.SentinelFileCommand = sentinelFileCommand - return nil } func generate(kind string, tpl string, data interface{}) ([]byte, error) { @@ -124,36 +109,3 @@ func generate(kind string, tpl string, data interface{}) ([]byte, error) { return out.Bytes(), nil } - -var ( - //go:embed kubeadm-bootstrap-script-pre-k8s-1-31.sh - kubeadmBootstrapScriptPre1_31 string - //go:embed kubeadm-bootstrap-script.sh - kubeadmBootstrapScript string - - // kubernetesVersion1_31 is the version where kubeadm removed the update-status phase - // and introduced new phases with the ControlPlaneKubeletLocalMode feature gate. - kubernetesVersion1_31 = semver.MustParse("1.31.0") -) - -func generateBootstrapScript(input interface{}, parsedversion semver.Version) (*bootstrapv1.File, error) { - bootstrapScript := kubeadmBootstrapScript - if useKubeadmBootstrapScriptPre1_31(parsedversion) { - bootstrapScript = kubeadmBootstrapScriptPre1_31 - } - - joinScript, err := generate("JoinScript", bootstrapScript, input) - if err != nil { - return nil, errors.Wrap(err, "failed to bootstrap script for machine joins") - } - return &bootstrapv1.File{ - Path: retriableJoinScriptName, - Owner: retriableJoinScriptOwner, - Permissions: retriableJoinScriptPermissions, - Content: string(joinScript), - }, nil -} - -func useKubeadmBootstrapScriptPre1_31(parsedversion semver.Version) bool { - return version.Compare(parsedversion, kubernetesVersion1_31, version.WithoutPreReleases()) < 0 -} diff --git a/bootstrap/kubeadm/internal/cloudinit/cloudinit_test.go b/bootstrap/kubeadm/internal/cloudinit/cloudinit_test.go index 21431804b39a..99b38d9423ea 100644 --- a/bootstrap/kubeadm/internal/cloudinit/cloudinit_test.go +++ b/bootstrap/kubeadm/internal/cloudinit/cloudinit_test.go @@ -19,7 +19,6 @@ package cloudinit import ( "testing" - "github.com/blang/semver/v4" . "github.com/onsi/gomega" "k8s.io/utils/ptr" @@ -250,82 +249,6 @@ func TestNewJoinControlPlaneAdditionalFileEncodings(t *testing.T) { } } -func TestNewJoinControlPlaneExperimentalRetry(t *testing.T) { - g := NewWithT(t) - - cpinput := &ControlPlaneJoinInput{ - BaseUserData: BaseUserData{ - Header: "test", - BootCommands: nil, - PreKubeadmCommands: nil, - PostKubeadmCommands: nil, - UseExperimentalRetry: true, - WriteFiles: nil, - Users: nil, - NTP: nil, - }, - Certificates: secret.Certificates{}, - BootstrapToken: "my-bootstrap-token", - JoinConfiguration: "my-join-config", - } - - for _, certificate := range cpinput.Certificates { - certificate.KeyPair = &certs.KeyPair{ - Cert: []byte("some certificate"), - Key: []byte("some key"), - } - } - - out, err := NewJoinControlPlane(cpinput) - g.Expect(err).ToNot(HaveOccurred()) - - expectedFiles := []string{ - `- path: ` + retriableJoinScriptName + ` - owner: ` + retriableJoinScriptOwner + ` - permissions: '` + retriableJoinScriptPermissions + `' - `, - } - for _, f := range expectedFiles { - g.Expect(out).To(ContainSubstring(f)) - } -} - -func Test_useKubeadmBootstrapScriptPre1_31(t *testing.T) { - tests := []struct { - name string - parsedversion semver.Version - want bool - }{ - { - name: "true for version for v1.30", - parsedversion: semver.MustParse("1.30.99"), - want: true, - }, - { - name: "true for version for v1.28", - parsedversion: semver.MustParse("1.28.0"), - want: true, - }, - { - name: "false for v1.31.0", - parsedversion: semver.MustParse("1.31.0"), - want: false, - }, - { - name: "false for v1.31.0-beta.0", - parsedversion: semver.MustParse("1.31.0-beta.0"), - want: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := useKubeadmBootstrapScriptPre1_31(tt.parsedversion); got != tt.want { - t.Errorf("useKubeadmBootstrapScriptPre1_31() = %v, want %v", got, tt.want) - } - }) - } -} - func TestNewJoinControlPlaneCommands(t *testing.T) { g := NewWithT(t) diff --git a/bootstrap/kubeadm/internal/cloudinit/controlplane_join.go b/bootstrap/kubeadm/internal/cloudinit/controlplane_join.go index 127a9047f1b3..df6b4fb2752a 100644 --- a/bootstrap/kubeadm/internal/cloudinit/controlplane_join.go +++ b/bootstrap/kubeadm/internal/cloudinit/controlplane_join.go @@ -60,9 +60,8 @@ func NewJoinControlPlane(input *ControlPlaneJoinInput) ([]byte, error) { // TODO: Consider validating that the correct certificates exist. It is different for external/stacked etcd input.WriteFiles = input.AsFiles() input.ControlPlane = true - if err := input.prepare(); err != nil { - return nil, err - } + input.prepare() + userData, err := generate("JoinControlplane", controlPlaneJoinCloudInit, input) if err != nil { return nil, errors.Wrapf(err, "failed to generate user data for machine joining control plane") diff --git a/bootstrap/kubeadm/internal/cloudinit/kubeadm-bootstrap-script-pre-k8s-1-31.sh b/bootstrap/kubeadm/internal/cloudinit/kubeadm-bootstrap-script-pre-k8s-1-31.sh deleted file mode 100644 index 5c78238ce0ac..000000000000 --- a/bootstrap/kubeadm/internal/cloudinit/kubeadm-bootstrap-script-pre-k8s-1-31.sh +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/bash -# Copyright 2020 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. - -# Log an error and exit. -# Args: -# $1 Message to log with the error -# $2 The error code to return -log::error_exit() { - local message="${1}" - local code="${2}" - - log::error "${message}" - # {{ if .ControlPlane }} - log::info "Removing member from cluster status" - kubeadm reset -f update-cluster-status || true - log::info "Removing etcd member" - kubeadm reset -f remove-etcd-member || true - # {{ end }} - log::info "Resetting kubeadm" - kubeadm reset -f || true - log::error "cluster.x-k8s.io kubeadm bootstrap script $0 exiting with status ${code}" - exit "${code}" -} - -log::success_exit() { - log::info "cluster.x-k8s.io kubeadm bootstrap script $0 finished" - exit 0 -} - -# Log an error but keep going. -log::error() { - local message="${1}" - timestamp=$(date --iso-8601=seconds) - echo "!!! [${timestamp}] ${1}" >&2 - shift - for message; do - echo " ${message}" >&2 - done -} - -# Print a status line. Formatted to show up in a stream of output. -log::info() { - timestamp=$(date --iso-8601=seconds) - echo "+++ [${timestamp}] ${1}" - shift - for message; do - echo " ${message}" - done -} - -check_kubeadm_command() { - local command="${1}" - local code="${2}" - case ${code} in - "0") - log::info "kubeadm reported successful execution for ${command}" - ;; - "1") - log::error "kubeadm reported failed action(s) for ${command}" - ;; - "2") - log::error "kubeadm reported preflight check error during ${command}" - ;; - "3") - log::error_exit "kubeadm reported validation error for ${command}" "${code}" - ;; - *) - log::error "kubeadm reported unknown error ${code} for ${command}" - ;; - esac -} - -function retry-command() { - n=0 - local kubeadm_return - until [ $n -ge 5 ]; do - log::info "running '$*'" - # shellcheck disable=SC1083 - "$@" --config=/run/kubeadm/kubeadm-join-config.yaml {{.KubeadmVerbosity}} - kubeadm_return=$? - check_kubeadm_command "'$*'" "${kubeadm_return}" - if [ ${kubeadm_return} -eq 0 ]; then - break - fi - # We allow preflight errors to pass - if [ ${kubeadm_return} -eq 2 ]; then - break - fi - n=$((n + 1)) - sleep 15 - done - if [ ${kubeadm_return} -ne 0 ]; then - log::error_exit "too many errors, exiting" "${kubeadm_return}" - fi -} - -# {{ if .ControlPlane }} -function try-or-die-command() { - local kubeadm_return - log::info "running '$*'" - # shellcheck disable=SC1083 - "$@" --config=/run/kubeadm/kubeadm-join-config.yaml {{.KubeadmVerbosity}} - kubeadm_return=$? - check_kubeadm_command "'$*'" "${kubeadm_return}" - if [ ${kubeadm_return} -ne 0 ]; then - log::error_exit "fatal error, exiting" "${kubeadm_return}" - fi -} -# {{ end }} - -retry-command kubeadm join phase preflight --ignore-preflight-errors=DirAvailable--etc-kubernetes-manifests -# {{ if .ControlPlane }} -retry-command kubeadm join phase control-plane-prepare download-certs -retry-command kubeadm join phase control-plane-prepare certs -retry-command kubeadm join phase control-plane-prepare kubeconfig -retry-command kubeadm join phase control-plane-prepare control-plane -# {{ end }} -retry-command kubeadm join phase kubelet-start -# {{ if .ControlPlane }} -try-or-die-command kubeadm join phase control-plane-join etcd -retry-command kubeadm join phase control-plane-join update-status -retry-command kubeadm join phase control-plane-join mark-control-plane -# {{ end }} - -log::success_exit diff --git a/bootstrap/kubeadm/internal/cloudinit/kubeadm-bootstrap-script.sh b/bootstrap/kubeadm/internal/cloudinit/kubeadm-bootstrap-script.sh deleted file mode 100644 index 4a3aa5d0d860..000000000000 --- a/bootstrap/kubeadm/internal/cloudinit/kubeadm-bootstrap-script.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/bash -# Copyright 2024 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. - -# Log an error and exit. -# Args: -# $1 Message to log with the error -# $2 The error code to return -log::error_exit() { - local message="${1}" - local code="${2}" - - log::error "${message}" - # {{ if .ControlPlane }} - log::info "Removing member from cluster status" - kubeadm reset -f update-cluster-status || true - log::info "Removing etcd member" - kubeadm reset -f remove-etcd-member || true - # {{ end }} - log::info "Resetting kubeadm" - kubeadm reset -f || true - log::error "cluster.x-k8s.io kubeadm bootstrap script $0 exiting with status ${code}" - exit "${code}" -} - -log::success_exit() { - log::info "cluster.x-k8s.io kubeadm bootstrap script $0 finished" - exit 0 -} - -# Log an error but keep going. -log::error() { - local message="${1}" - timestamp=$(date --iso-8601=seconds) - echo "!!! [${timestamp}] ${1}" >&2 - shift - for message; do - echo " ${message}" >&2 - done -} - -# Print a status line. Formatted to show up in a stream of output. -log::info() { - timestamp=$(date --iso-8601=seconds) - echo "+++ [${timestamp}] ${1}" - shift - for message; do - echo " ${message}" - done -} - -check_kubeadm_command() { - local command="${1}" - local code="${2}" - case ${code} in - "0") - log::info "kubeadm reported successful execution for ${command}" - ;; - "1") - log::error "kubeadm reported failed action(s) for ${command}" - ;; - "2") - log::error "kubeadm reported preflight check error during ${command}" - ;; - "3") - log::error_exit "kubeadm reported validation error for ${command}" "${code}" - ;; - *) - log::error "kubeadm reported unknown error ${code} for ${command}" - ;; - esac -} - -function retry-command() { - n=0 - local kubeadm_return - until [ $n -ge 5 ]; do - log::info "running '$*'" - # shellcheck disable=SC1083 - "$@" --config=/run/kubeadm/kubeadm-join-config.yaml {{.KubeadmVerbosity}} - kubeadm_return=$? - check_kubeadm_command "'$*'" "${kubeadm_return}" - if [ ${kubeadm_return} -eq 0 ]; then - break - fi - # We allow preflight errors to pass - if [ ${kubeadm_return} -eq 2 ]; then - break - fi - n=$((n + 1)) - sleep 15 - done - if [ ${kubeadm_return} -ne 0 ]; then - log::error_exit "too many errors, exiting" "${kubeadm_return}" - fi -} - -function try-or-die-command() { - local kubeadm_return - log::info "running '$*'" - # shellcheck disable=SC1083 - "$@" --config=/run/kubeadm/kubeadm-join-config.yaml {{.KubeadmVerbosity}} - kubeadm_return=$? - check_kubeadm_command "'$*'" "${kubeadm_return}" - if [ ${kubeadm_return} -ne 0 ]; then - log::error_exit "fatal error, exiting" "${kubeadm_return}" - fi -} - -retry-command kubeadm join phase preflight --ignore-preflight-errors=DirAvailable--etc-kubernetes-manifests -# {{ if .ControlPlane }} -retry-command kubeadm join phase control-plane-prepare download-certs -retry-command kubeadm join phase control-plane-prepare certs -retry-command kubeadm join phase control-plane-prepare kubeconfig -retry-command kubeadm join phase control-plane-prepare control-plane -# {{ end }} -retry-command kubeadm join phase kubelet-start - -# Run kubeadm join and skip all already executed phases. -try-or-die-command kubeadm join --skip-phases preflight,control-plane-prepare,kubelet-start - -log::success_exit diff --git a/bootstrap/kubeadm/internal/cloudinit/node.go b/bootstrap/kubeadm/internal/cloudinit/node.go index 81a9e0a4966d..474b3d08b93e 100644 --- a/bootstrap/kubeadm/internal/cloudinit/node.go +++ b/bootstrap/kubeadm/internal/cloudinit/node.go @@ -50,9 +50,7 @@ type NodeInput struct { // NewNode returns the user data string to be used on a node instance. func NewNode(input *NodeInput) ([]byte, error) { - if err := input.prepare(); err != nil { - return nil, err - } + input.prepare() input.Header = cloudConfigHeader return generate("Node", nodeCloudInit, input) } diff --git a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go index 2b9f98ba862f..bd49ddb0b614 100644 --- a/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go +++ b/bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go @@ -797,17 +797,16 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope) nodeInput := &cloudinit.NodeInput{ BaseUserData: cloudinit.BaseUserData{ - AdditionalFiles: files, - NTP: scope.Config.Spec.NTP, - BootCommands: scope.Config.Spec.BootCommands, - PreKubeadmCommands: scope.Config.Spec.PreKubeadmCommands, - PostKubeadmCommands: scope.Config.Spec.PostKubeadmCommands, - Users: users, - Mounts: scope.Config.Spec.Mounts, - DiskSetup: scope.Config.Spec.DiskSetup, - KubeadmVerbosity: verbosityFlag, - UseExperimentalRetry: scope.Config.Spec.UseExperimentalRetryJoin, - KubernetesVersion: parsedVersion, + AdditionalFiles: files, + NTP: scope.Config.Spec.NTP, + BootCommands: scope.Config.Spec.BootCommands, + PreKubeadmCommands: scope.Config.Spec.PreKubeadmCommands, + PostKubeadmCommands: scope.Config.Spec.PostKubeadmCommands, + Users: users, + Mounts: scope.Config.Spec.Mounts, + DiskSetup: scope.Config.Spec.DiskSetup, + KubeadmVerbosity: verbosityFlag, + KubernetesVersion: parsedVersion, }, JoinConfiguration: joinData, } @@ -952,17 +951,16 @@ func (r *KubeadmConfigReconciler) joinControlplane(ctx context.Context, scope *S JoinConfiguration: joinData, Certificates: certificates, BaseUserData: cloudinit.BaseUserData{ - AdditionalFiles: files, - NTP: scope.Config.Spec.NTP, - BootCommands: scope.Config.Spec.BootCommands, - PreKubeadmCommands: scope.Config.Spec.PreKubeadmCommands, - PostKubeadmCommands: scope.Config.Spec.PostKubeadmCommands, - Users: users, - Mounts: scope.Config.Spec.Mounts, - DiskSetup: scope.Config.Spec.DiskSetup, - KubeadmVerbosity: verbosityFlag, - UseExperimentalRetry: scope.Config.Spec.UseExperimentalRetryJoin, - KubernetesVersion: parsedVersion, + AdditionalFiles: files, + NTP: scope.Config.Spec.NTP, + BootCommands: scope.Config.Spec.BootCommands, + PreKubeadmCommands: scope.Config.Spec.PreKubeadmCommands, + PostKubeadmCommands: scope.Config.Spec.PostKubeadmCommands, + Users: users, + Mounts: scope.Config.Spec.Mounts, + DiskSetup: scope.Config.Spec.DiskSetup, + KubeadmVerbosity: verbosityFlag, + KubernetesVersion: parsedVersion, }, } diff --git a/bootstrap/kubeadm/internal/webhooks/kubeadmconfig_test.go b/bootstrap/kubeadm/internal/webhooks/kubeadmconfig_test.go index 00e3c6a5d960..ce9098254516 100644 --- a/bootstrap/kubeadm/internal/webhooks/kubeadmconfig_test.go +++ b/bootstrap/kubeadm/internal/webhooks/kubeadmconfig_test.go @@ -340,20 +340,6 @@ func TestKubeadmConfigValidate(t *testing.T) { }, expectErr: true, }, - "format is Ignition, experimental retry join is set": { - enableIgnitionFeature: true, - in: &bootstrapv1.KubeadmConfig{ - ObjectMeta: metav1.ObjectMeta{ - Name: "baz", - Namespace: "default", - }, - Spec: bootstrapv1.KubeadmConfigSpec{ - Format: bootstrapv1.Ignition, - UseExperimentalRetryJoin: true, - }, - }, - expectErr: true, - }, "feature gate disabled, format is Ignition": { in: &bootstrapv1.KubeadmConfig{ ObjectMeta: metav1.ObjectMeta{ diff --git a/controlplane/kubeadm/api/v1beta1/conversion_test.go b/controlplane/kubeadm/api/v1beta1/conversion_test.go index 658489540372..728f79b86951 100644 --- a/controlplane/kubeadm/api/v1beta1/conversion_test.go +++ b/controlplane/kubeadm/api/v1beta1/conversion_test.go @@ -26,6 +26,7 @@ import ( "k8s.io/apimachinery/pkg/api/apitesting/fuzzer" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" + bootstrapv1beta1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta2" utilconversion "sigs.k8s.io/cluster-api/util/conversion" ) @@ -39,8 +40,9 @@ func TestFuzzyConversion(t *testing.T) { FuzzerFuncs: []fuzzer.FuzzerFuncs{KubeadmControlPlaneFuzzFuncs}, })) t.Run("for KubeadmControlPlaneTemplate", utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ - Hub: &controlplanev1.KubeadmControlPlaneTemplate{}, - Spoke: &KubeadmControlPlaneTemplate{}, + Hub: &controlplanev1.KubeadmControlPlaneTemplate{}, + Spoke: &KubeadmControlPlaneTemplate{}, + FuzzerFuncs: []fuzzer.FuzzerFuncs{KubeadmControlPlaneTemplateFuzzFuncs}, })) } @@ -48,6 +50,7 @@ func KubeadmControlPlaneFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{ return []interface{}{ hubKubeadmControlPlaneStatus, spokeKubeadmControlPlaneStatus, + spokeKubeadmConfigSpec, } } @@ -81,3 +84,16 @@ func spokeKubeadmControlPlaneStatus(in *KubeadmControlPlaneStatus, c fuzz.Contin // Make sure ready is consistent with ready replicas, so we can rebuild the info after the round trip. in.Ready = in.ReadyReplicas > 0 } + +func KubeadmControlPlaneTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { + return []interface{}{ + spokeKubeadmConfigSpec, + } +} + +func spokeKubeadmConfigSpec(in *bootstrapv1beta1.KubeadmConfigSpec, c fuzz.Continue) { + c.FuzzNoCustom(in) + + // Drop UseExperimentalRetryJoin as we intentionally don't preserve it. + in.UseExperimentalRetryJoin = false +} 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 e4004d0e2337..944daf2902ce 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 @@ -6823,22 +6823,6 @@ spec: type: string maxItems: 1000 type: array - useExperimentalRetryJoin: - description: |- - useExperimentalRetryJoin replaces a basic kubeadm command with a shell - script with retries for joins. - - This is meant to be an experimental temporary workaround on some environments - where joins fail due to timing (and other issues). The long term goal is to add retries to - kubeadm proper and use that functionality. - - This will add about 40KB to userdata - - For more information, refer to https://github.com/kubernetes-sigs/cluster-api/pull/2763#discussion_r397306055. - - Deprecated: This experimental fix is no longer needed and this field will be removed in a future release. - When removing also remove from staticcheck exclude-rules for SA1019 in golangci.yml - type: boolean users: description: users specifies extra users to add items: 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 3702715a4817..7dffdf3a4d17 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 @@ -5226,22 +5226,6 @@ spec: type: string maxItems: 1000 type: array - useExperimentalRetryJoin: - description: |- - useExperimentalRetryJoin replaces a basic kubeadm command with a shell - script with retries for joins. - - This is meant to be an experimental temporary workaround on some environments - where joins fail due to timing (and other issues). The long term goal is to add retries to - kubeadm proper and use that functionality. - - This will add about 40KB to userdata - - For more information, refer to https://github.com/kubernetes-sigs/cluster-api/pull/2763#discussion_r397306055. - - Deprecated: This experimental fix is no longer needed and this field will be removed in a future release. - When removing also remove from staticcheck exclude-rules for SA1019 in golangci.yml - type: boolean users: description: users specifies extra users to add items: diff --git a/controlplane/kubeadm/internal/filters_test.go b/controlplane/kubeadm/internal/filters_test.go index 90c74c0b8df1..7174bb1f93b5 100644 --- a/controlplane/kubeadm/internal/filters_test.go +++ b/controlplane/kubeadm/internal/filters_test.go @@ -550,7 +550,7 @@ func TestMatchInitOrJoinConfiguration(t *testing.T) { }, JoinConfiguration: nil, Files: nil, - ... // 11 identical fields + ... // 10 identical fields }`)) }) t.Run("returns true if JoinConfiguration is equal", func(t *testing.T) { @@ -675,7 +675,7 @@ func TestMatchInitOrJoinConfiguration(t *testing.T) { }, Files: nil, DiskSetup: nil, - ... // 10 identical fields + ... // 9 identical fields }`)) }) t.Run("returns false if some other configurations are not equal", func(t *testing.T) { @@ -736,7 +736,7 @@ func TestMatchInitOrJoinConfiguration(t *testing.T) { + Files: []v1beta2.File{}, DiskSetup: nil, Mounts: nil, - ... // 9 identical fields + ... // 8 identical fields }`)) }) } @@ -922,7 +922,7 @@ func TestMatchesKubeadmBootstrapConfig(t *testing.T) { }, JoinConfiguration: nil, Files: nil, - ... // 11 identical fields + ... // 10 identical fields }`)) }) t.Run("returns true if JoinConfiguration is equal", func(t *testing.T) { @@ -1047,7 +1047,7 @@ func TestMatchesKubeadmBootstrapConfig(t *testing.T) { }, Files: nil, DiskSetup: nil, - ... // 10 identical fields + ... // 9 identical fields }`)) }) t.Run("returns false if some other configurations are not equal", func(t *testing.T) { @@ -1108,7 +1108,7 @@ func TestMatchesKubeadmBootstrapConfig(t *testing.T) { + Files: []v1beta2.File{}, DiskSetup: nil, Mounts: nil, - ... // 9 identical fields + ... // 8 identical fields }`)) }) t.Run("should match on labels and annotations", func(t *testing.T) { diff --git a/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane.go b/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane.go index 69fec95b7334..e58ac5b1a8bd 100644 --- a/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane.go +++ b/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane.go @@ -216,7 +216,6 @@ func (webhook *KubeadmControlPlane) ValidateUpdate(_ context.Context, oldObj, ne {spec, kubeadmConfigSpec, diskSetup, "*"}, {spec, kubeadmConfigSpec, "format"}, {spec, kubeadmConfigSpec, "mounts"}, - {spec, kubeadmConfigSpec, "useExperimentalRetryJoin"}, // spec.machineTemplate {spec, "machineTemplate", "metadata"}, {spec, "machineTemplate", "metadata", "*"}, diff --git a/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane_test.go b/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane_test.go index ba974ef0ec1c..a65421eed6fe 100644 --- a/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane_test.go +++ b/controlplane/kubeadm/internal/webhooks/kubeadm_control_plane_test.go @@ -718,11 +718,6 @@ func TestKubeadmControlPlaneValidateUpdate(t *testing.T) { "/invalid-key": "foo", } - beforeUseExperimentalRetryJoin := before.DeepCopy() - beforeUseExperimentalRetryJoin.Spec.KubeadmConfigSpec.UseExperimentalRetryJoin = true //nolint:staticcheck - updateUseExperimentalRetryJoin := before.DeepCopy() - updateUseExperimentalRetryJoin.Spec.KubeadmConfigSpec.UseExperimentalRetryJoin = false //nolint:staticcheck - tests := []struct { name string enableIgnitionFeature bool @@ -1086,12 +1081,6 @@ func TestKubeadmControlPlaneValidateUpdate(t *testing.T) { before: before, kcp: invalidMetadata, }, - { - name: "should allow changes to useExperimentalRetryJoin", - expectErr: false, - before: beforeUseExperimentalRetryJoin, - kcp: updateUseExperimentalRetryJoin, - }, } for _, tt := range tests { diff --git a/docs/book/src/tasks/bootstrap/kubeadm-bootstrap/index.md b/docs/book/src/tasks/bootstrap/kubeadm-bootstrap/index.md index cdf3074d6379..9df31fae5d38 100644 --- a/docs/book/src/tasks/bootstrap/kubeadm-bootstrap/index.md +++ b/docs/book/src/tasks/bootstrap/kubeadm-bootstrap/index.md @@ -259,10 +259,4 @@ The `KubeadmConfig` object supports customizing the content of the config-data. verbosity: 10 ``` -- `KubeadmConfig.UseExperimentalRetryJoin` replaces a basic kubeadm command with a shell script with retries for joins. This will add about 40KB to userdata. - - ```yaml - useExperimentalRetryJoin: true - ``` - For more information on cloud-init options, see [cloud config examples](https://cloudinit.readthedocs.io/en/latest/topics/examples.html). diff --git a/internal/apis/bootstrap/kubeadm/v1alpha3/conversion.go b/internal/apis/bootstrap/kubeadm/v1alpha3/conversion.go index d7e6d5dbe956..c27b092ecf55 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha3/conversion.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha3/conversion.go @@ -205,6 +205,11 @@ func (dst *KubeadmConfigTemplate) ConvertFrom(srcRaw conversion.Hub) error { return nil } +func Convert_v1alpha3_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *KubeadmConfigSpec, out *bootstrapv1.KubeadmConfigSpec, s apimachineryconversion.Scope) error { + // NOTE: v1beta2 KubeadmConfigSpec does not have UseExperimentalRetryJoin anymore, so it's fine to just lose this field. + return autoConvert_v1alpha3_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in, out, s) +} + func Convert_v1alpha3_KubeadmConfigStatus_To_v1beta2_KubeadmConfigStatus(in *KubeadmConfigStatus, out *bootstrapv1.KubeadmConfigStatus, s apimachineryconversion.Scope) error { // KubeadmConfigStatus.BootstrapData has been removed in v1alpha4 because its content has been moved to the bootstrap data secret, value will be lost during conversion. return autoConvert_v1alpha3_KubeadmConfigStatus_To_v1beta2_KubeadmConfigStatus(in, out, s) diff --git a/internal/apis/bootstrap/kubeadm/v1alpha3/conversion_test.go b/internal/apis/bootstrap/kubeadm/v1alpha3/conversion_test.go index fcf550548702..d46e5fd451bb 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha3/conversion_test.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha3/conversion_test.go @@ -48,6 +48,7 @@ func TestFuzzyConversion(t *testing.T) { func KubeadmConfigFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ + spokeKubeadmConfigSpec, spokeKubeadmConfigStatus, spokeDNS, spokeClusterConfiguration, @@ -87,6 +88,7 @@ func hubKubeadmConfigStatus(in *bootstrapv1.KubeadmConfigStatus, c fuzz.Continue func KubeadmConfigTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ + spokeKubeadmConfigSpec, spokeKubeadmConfigStatus, spokeDNS, spokeClusterConfiguration, @@ -105,6 +107,13 @@ func KubeadmConfigTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []interfac } } +func spokeKubeadmConfigSpec(in *KubeadmConfigSpec, c fuzz.Continue) { + c.FuzzNoCustom(in) + + // Drop UseExperimentalRetryJoin as we intentionally don't preserve it. + in.UseExperimentalRetryJoin = false +} + func spokeKubeadmConfigStatus(obj *KubeadmConfigStatus, c fuzz.Continue) { c.FuzzNoCustom(obj) diff --git a/internal/apis/bootstrap/kubeadm/v1alpha3/zz_generated.conversion.go b/internal/apis/bootstrap/kubeadm/v1alpha3/zz_generated.conversion.go index 5d56177d30b2..ec8fcf4434d1 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha3/zz_generated.conversion.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha3/zz_generated.conversion.go @@ -94,11 +94,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*KubeadmConfigSpec)(nil), (*v1beta2.KubeadmConfigSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha3_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(a.(*KubeadmConfigSpec), b.(*v1beta2.KubeadmConfigSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*KubeadmConfigTemplate)(nil), (*v1beta2.KubeadmConfigTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha3_KubeadmConfigTemplate_To_v1beta2_KubeadmConfigTemplate(a.(*KubeadmConfigTemplate), b.(*v1beta2.KubeadmConfigTemplate), scope) }); err != nil { @@ -194,6 +189,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*KubeadmConfigSpec)(nil), (*v1beta2.KubeadmConfigSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha3_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(a.(*KubeadmConfigSpec), b.(*v1beta2.KubeadmConfigSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*KubeadmConfigStatus)(nil), (*v1beta2.KubeadmConfigStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha3_KubeadmConfigStatus_To_v1beta2_KubeadmConfigStatus(a.(*KubeadmConfigStatus), b.(*v1beta2.KubeadmConfigStatus), scope) }); err != nil { @@ -477,15 +477,10 @@ func autoConvert_v1alpha3_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *Kub out.NTP = (*v1beta2.NTP)(unsafe.Pointer(in.NTP)) out.Format = v1beta2.Format(in.Format) out.Verbosity = (*int32)(unsafe.Pointer(in.Verbosity)) - out.UseExperimentalRetryJoin = in.UseExperimentalRetryJoin + // WARNING: in.UseExperimentalRetryJoin requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha3_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec is an autogenerated conversion function. -func Convert_v1alpha3_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *KubeadmConfigSpec, out *v1beta2.KubeadmConfigSpec, s conversion.Scope) error { - return autoConvert_v1alpha3_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in, out, s) -} - func autoConvert_v1beta2_KubeadmConfigSpec_To_v1alpha3_KubeadmConfigSpec(in *v1beta2.KubeadmConfigSpec, out *KubeadmConfigSpec, s conversion.Scope) error { if in.ClusterConfiguration != nil { in, out := &in.ClusterConfiguration, &out.ClusterConfiguration @@ -544,7 +539,6 @@ func autoConvert_v1beta2_KubeadmConfigSpec_To_v1alpha3_KubeadmConfigSpec(in *v1b out.NTP = (*NTP)(unsafe.Pointer(in.NTP)) out.Format = Format(in.Format) out.Verbosity = (*int32)(unsafe.Pointer(in.Verbosity)) - out.UseExperimentalRetryJoin = in.UseExperimentalRetryJoin // WARNING: in.Ignition requires manual conversion: does not exist in peer-type return nil } diff --git a/internal/apis/bootstrap/kubeadm/v1alpha4/conversion.go b/internal/apis/bootstrap/kubeadm/v1alpha4/conversion.go index 86511b4c9f91..2fe01b17013c 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha4/conversion.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha4/conversion.go @@ -193,6 +193,11 @@ func (dst *KubeadmConfigTemplate) ConvertFrom(srcRaw conversion.Hub) error { return utilconversion.MarshalData(src, dst) } +func Convert_v1alpha4_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *KubeadmConfigSpec, out *bootstrapv1.KubeadmConfigSpec, s apimachineryconversion.Scope) error { + // NOTE: v1beta2 KubeadmConfigSpec does not have UseExperimentalRetryJoin anymore, so it's fine to just lose this field. + return autoConvert_v1alpha4_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in, out, s) +} + // Convert_v1beta2_KubeadmConfigSpec_To_v1alpha4_KubeadmConfigSpec is an autogenerated conversion function. func Convert_v1beta2_KubeadmConfigSpec_To_v1alpha4_KubeadmConfigSpec(in *bootstrapv1.KubeadmConfigSpec, out *KubeadmConfigSpec, s apimachineryconversion.Scope) error { // KubeadmConfigSpec.Ignition does not exist in kubeadm v1alpha4 API. diff --git a/internal/apis/bootstrap/kubeadm/v1alpha4/conversion_test.go b/internal/apis/bootstrap/kubeadm/v1alpha4/conversion_test.go index c5f81a176627..a81927f15730 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha4/conversion_test.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha4/conversion_test.go @@ -46,13 +46,14 @@ func TestFuzzyConversion(t *testing.T) { t.Run("for KubeadmConfigTemplate", utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{ Hub: &bootstrapv1.KubeadmConfigTemplate{}, Spoke: &KubeadmConfigTemplate{}, - FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzFuncs}, + FuzzerFuncs: []fuzzer.FuzzerFuncs{KubeadmConfigTemplateFuzzFuncs, fuzzFuncs}, })) } func KubeadmConfigFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ hubKubeadmConfigStatus, + spokeKubeadmConfigSpec, } } @@ -74,6 +75,13 @@ func hubKubeadmConfigStatus(in *bootstrapv1.KubeadmConfigStatus, c fuzz.Continue } } +func spokeKubeadmConfigSpec(in *KubeadmConfigSpec, c fuzz.Continue) { + c.FuzzNoCustom(in) + + // Drop UseExperimentalRetryJoin as we intentionally don't preserve it. + in.UseExperimentalRetryJoin = false +} + func fuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { return []interface{}{ // This custom functions are needed when ConvertTo/ConvertFrom functions @@ -100,3 +108,9 @@ func kubeadmBootstrapTokenStringFuzzerV1Alpha4(in *BootstrapTokenString, _ fuzz. in.ID = fakeID in.Secret = fakeSecret } + +func KubeadmConfigTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{} { + return []interface{}{ + spokeKubeadmConfigSpec, + } +} diff --git a/internal/apis/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go b/internal/apis/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go index 76a793714fad..7a0a443c8511 100644 --- a/internal/apis/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go +++ b/internal/apis/bootstrap/kubeadm/v1alpha4/zz_generated.conversion.go @@ -254,11 +254,6 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } - if err := s.AddGeneratedConversionFunc((*KubeadmConfigSpec)(nil), (*v1beta2.KubeadmConfigSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { - return Convert_v1alpha4_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(a.(*KubeadmConfigSpec), b.(*v1beta2.KubeadmConfigSpec), scope) - }); err != nil { - return err - } if err := s.AddGeneratedConversionFunc((*KubeadmConfigTemplate)(nil), (*v1beta2.KubeadmConfigTemplate)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha4_KubeadmConfigTemplate_To_v1beta2_KubeadmConfigTemplate(a.(*KubeadmConfigTemplate), b.(*v1beta2.KubeadmConfigTemplate), scope) }); err != nil { @@ -359,6 +354,11 @@ func RegisterConversions(s *runtime.Scheme) error { }); err != nil { return err } + if err := s.AddConversionFunc((*KubeadmConfigSpec)(nil), (*v1beta2.KubeadmConfigSpec)(nil), func(a, b interface{}, scope conversion.Scope) error { + return Convert_v1alpha4_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(a.(*KubeadmConfigSpec), b.(*v1beta2.KubeadmConfigSpec), scope) + }); err != nil { + return err + } if err := s.AddConversionFunc((*KubeadmConfigStatus)(nil), (*v1beta2.KubeadmConfigStatus)(nil), func(a, b interface{}, scope conversion.Scope) error { return Convert_v1alpha4_KubeadmConfigStatus_To_v1beta2_KubeadmConfigStatus(a.(*KubeadmConfigStatus), b.(*v1beta2.KubeadmConfigStatus), scope) }); err != nil { @@ -1169,15 +1169,10 @@ func autoConvert_v1alpha4_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *Kub out.NTP = (*v1beta2.NTP)(unsafe.Pointer(in.NTP)) out.Format = v1beta2.Format(in.Format) out.Verbosity = (*int32)(unsafe.Pointer(in.Verbosity)) - out.UseExperimentalRetryJoin = in.UseExperimentalRetryJoin + // WARNING: in.UseExperimentalRetryJoin requires manual conversion: does not exist in peer-type return nil } -// Convert_v1alpha4_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec is an autogenerated conversion function. -func Convert_v1alpha4_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in *KubeadmConfigSpec, out *v1beta2.KubeadmConfigSpec, s conversion.Scope) error { - return autoConvert_v1alpha4_KubeadmConfigSpec_To_v1beta2_KubeadmConfigSpec(in, out, s) -} - func autoConvert_v1beta2_KubeadmConfigSpec_To_v1alpha4_KubeadmConfigSpec(in *v1beta2.KubeadmConfigSpec, out *KubeadmConfigSpec, s conversion.Scope) error { if in.ClusterConfiguration != nil { in, out := &in.ClusterConfiguration, &out.ClusterConfiguration @@ -1236,7 +1231,6 @@ func autoConvert_v1beta2_KubeadmConfigSpec_To_v1alpha4_KubeadmConfigSpec(in *v1b out.NTP = (*NTP)(unsafe.Pointer(in.NTP)) out.Format = Format(in.Format) out.Verbosity = (*int32)(unsafe.Pointer(in.Verbosity)) - out.UseExperimentalRetryJoin = in.UseExperimentalRetryJoin // WARNING: in.Ignition requires manual conversion: does not exist in peer-type return nil } diff --git a/internal/apis/controlplane/kubeadm/v1alpha3/conversion_test.go b/internal/apis/controlplane/kubeadm/v1alpha3/conversion_test.go index 3689f4d892ee..56e32cc045be 100644 --- a/internal/apis/controlplane/kubeadm/v1alpha3/conversion_test.go +++ b/internal/apis/controlplane/kubeadm/v1alpha3/conversion_test.go @@ -29,6 +29,7 @@ import ( bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta2" "sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/upstreamv1beta1" controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta2" + bootstrapv1alpha3 "sigs.k8s.io/cluster-api/internal/apis/bootstrap/kubeadm/v1alpha3" utilconversion "sigs.k8s.io/cluster-api/util/conversion" ) @@ -60,6 +61,7 @@ func KubeadmControlPlaneFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{ // the values for ID and Secret to working alphanumeric values. hubBootstrapTokenString, spokeKubeadmBootstrapTokenString, + spokeKubeadmConfigSpec, } } @@ -111,3 +113,10 @@ func spokeKubeadmClusterConfiguration(obj *upstreamv1beta1.ClusterConfiguration, // ClusterConfiguration.UseHyperKubeImage has been removed in v1alpha4, so setting it to false in order to avoid v1alpha3 --> v1alpha4 --> v1alpha3 round trip errors. obj.UseHyperKubeImage = false } + +func spokeKubeadmConfigSpec(in *bootstrapv1alpha3.KubeadmConfigSpec, c fuzz.Continue) { + c.FuzzNoCustom(in) + + // Drop UseExperimentalRetryJoin as we intentionally don't preserve it. + in.UseExperimentalRetryJoin = false +} diff --git a/internal/apis/controlplane/kubeadm/v1alpha4/conversion_test.go b/internal/apis/controlplane/kubeadm/v1alpha4/conversion_test.go index bb6285e7be3e..67f771955c16 100644 --- a/internal/apis/controlplane/kubeadm/v1alpha4/conversion_test.go +++ b/internal/apis/controlplane/kubeadm/v1alpha4/conversion_test.go @@ -72,6 +72,7 @@ func KubeadmControlPlaneFuzzFuncs(_ runtimeserializer.CodecFactory) []interface{ // the values for ID and Secret to working alphanumeric values. hubBootstrapTokenString, spokeBootstrapTokenString, + spokeKubeadmConfigSpec, } } @@ -115,6 +116,7 @@ func KubeadmControlPlaneTemplateFuzzFuncs(_ runtimeserializer.CodecFactory) []in // the values for ID and Secret to working alphanumeric values. hubBootstrapTokenString, spokeBootstrapTokenString, + spokeKubeadmConfigSpec, } } @@ -137,3 +139,10 @@ func spokeKubeadmControlPlaneTemplateResource(in *KubeadmControlPlaneTemplateRes in.Spec.MachineTemplate.ObjectMeta = clusterv1alpha4.ObjectMeta{} in.Spec.MachineTemplate.InfrastructureRef = corev1.ObjectReference{} } + +func spokeKubeadmConfigSpec(in *bootstrapv1alpha4.KubeadmConfigSpec, c fuzz.Continue) { + c.FuzzNoCustom(in) + + // Drop UseExperimentalRetryJoin as we intentionally don't preserve it. + in.UseExperimentalRetryJoin = false +}