diff --git a/pkg/api/v1alpha1/cluster.go b/pkg/api/v1alpha1/cluster.go index 551165bd4292..b88d275d6269 100644 --- a/pkg/api/v1alpha1/cluster.go +++ b/pkg/api/v1alpha1/cluster.go @@ -825,19 +825,20 @@ func validatePodIAMConfig(clusterConfig *Cluster) error { } func validateCPUpgradeRolloutStrategy(clusterConfig *Cluster) error { - if clusterConfig.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy == nil { + cpUpgradeRolloutStrategy := clusterConfig.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy + if cpUpgradeRolloutStrategy == nil { return nil } - if clusterConfig.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy.Type != "RollingUpdate" { - return fmt.Errorf("ControlPlaneConfiguration: only 'RollingUpdate' supported for upgrade rollout strategy type") + if cpUpgradeRolloutStrategy.Type != "RollingUpdate" && cpUpgradeRolloutStrategy.Type != "InPlace" { + return fmt.Errorf("ControlPlaneConfiguration: only 'RollingUpdate' and 'InPlace' are supported for upgrade rollout strategy type") } - if clusterConfig.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy.RollingUpdate.MaxSurge < 0 { + if cpUpgradeRolloutStrategy.RollingUpdate.MaxSurge < 0 { return fmt.Errorf("ControlPlaneConfiguration: maxSurge for control plane cannot be a negative value") } - if clusterConfig.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy.RollingUpdate.MaxSurge > 1 { + if cpUpgradeRolloutStrategy.RollingUpdate.MaxSurge > 1 { return fmt.Errorf("ControlPlaneConfiguration: maxSurge for control plane must be 0 or 1") } @@ -849,8 +850,8 @@ func validateMDUpgradeRolloutStrategy(w *WorkerNodeGroupConfiguration) error { return nil } - if w.UpgradeRolloutStrategy.Type != "RollingUpdate" { - return fmt.Errorf("WorkerNodeGroupConfiguration: only 'RollingUpdate' supported for upgrade rollout strategy type") + if w.UpgradeRolloutStrategy.Type != "RollingUpdate" && w.UpgradeRolloutStrategy.Type != "InPlace" { + return fmt.Errorf("WorkerNodeGroupConfiguration: only 'RollingUpdate' and 'InPlace' are supported for upgrade rollout strategy type") } if w.UpgradeRolloutStrategy.RollingUpdate.MaxSurge < 0 || w.UpgradeRolloutStrategy.RollingUpdate.MaxUnavailable < 0 { diff --git a/pkg/api/v1alpha1/cluster_test.go b/pkg/api/v1alpha1/cluster_test.go index 48080f0e878e..29bb9de20b82 100644 --- a/pkg/api/v1alpha1/cluster_test.go +++ b/pkg/api/v1alpha1/cluster_test.go @@ -3246,7 +3246,7 @@ func TestValidateCPUpgradeRolloutStrategy(t *testing.T) { }{ { name: "rolling upgrade strategy invalid", - wantErr: "ControlPlaneConfiguration: only 'RollingUpdate' supported for upgrade rollout strategy type", + wantErr: "ControlPlaneConfiguration: only 'RollingUpdate' and 'InPlace' are supported for upgrade rollout strategy type", cluster: &Cluster{ Spec: ClusterSpec{ ControlPlaneConfiguration: ControlPlaneConfiguration{ @@ -3332,7 +3332,7 @@ func TestValidateMDUpgradeRolloutStrategy(t *testing.T) { }{ { name: "rolling upgrade strategy invalid", - wantErr: "WorkerNodeGroupConfiguration: only 'RollingUpdate' supported for upgrade rollout strategy type", + wantErr: "WorkerNodeGroupConfiguration: only 'RollingUpdate' and 'InPlace' are supported for upgrade rollout strategy type", cluster: &Cluster{ Spec: ClusterSpec{ WorkerNodeGroupConfigurations: []WorkerNodeGroupConfiguration{{ diff --git a/pkg/providers/tinkerbell/assert.go b/pkg/providers/tinkerbell/assert.go index 9e02417a7ec2..ee7190ed123f 100644 --- a/pkg/providers/tinkerbell/assert.go +++ b/pkg/providers/tinkerbell/assert.go @@ -468,7 +468,8 @@ func ExtraHardwareAvailableAssertionForRollingUpgrade(catalogue *hardware.Catalo func ensureCPHardwareAvailability(spec *ClusterSpec, current ValidatableCluster, hwReq minimumHardwareRequirements) error { maxSurge := 1 - if spec.Cluster.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy != nil { + rolloutStrategy := spec.Cluster.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy + if rolloutStrategy != nil && rolloutStrategy.Type == "RollingUpdate" { maxSurge = spec.Cluster.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy.RollingUpdate.MaxSurge } err := hwReq.Add( @@ -489,7 +490,7 @@ func ensureWorkerHardwareAvailability(spec *ClusterSpec, current ValidatableClus // As rolling upgrades and scale up/down is not permitted in a single operation, its safe to access directly using the md name. mdName := fmt.Sprintf("%s-%s", spec.Cluster.Name, nodeGroup.Name) if currentWngK8sversion[mdName] != desiredWngK8sVersion[mdName] || eksaVersionUpgrade { - if nodeGroup.UpgradeRolloutStrategy != nil { + if nodeGroup.UpgradeRolloutStrategy != nil && nodeGroup.UpgradeRolloutStrategy.Type == "RollingUpdate" { maxSurge = nodeGroup.UpgradeRolloutStrategy.RollingUpdate.MaxSurge } err := hwReq.Add( diff --git a/pkg/providers/tinkerbell/tinkerbell_test.go b/pkg/providers/tinkerbell/tinkerbell_test.go index dbde03057081..a3e1b861446b 100644 --- a/pkg/providers/tinkerbell/tinkerbell_test.go +++ b/pkg/providers/tinkerbell/tinkerbell_test.go @@ -123,6 +123,31 @@ func TestTinkerbellProviderGenerateDeploymentFileWithExternalEtcd(t *testing.T) test.AssertContentToFile(t, string(md), "testdata/expected_results_cluster_tinkerbell_md.yaml") } +func TestTinkerbellProviderSetupAndValidateInPlaceBottlerocketNotSupported(t *testing.T) { + clusterSpecManifest := "cluster_tinkerbell_bottlerocket_minimal_registry_mirror.yaml" + mockCtrl := gomock.NewController(t) + docker := stackmocks.NewMockDocker(mockCtrl) + helm := stackmocks.NewMockHelm(mockCtrl) + kubectl := mocks.NewMockProviderKubectlClient(mockCtrl) + stackInstaller := stackmocks.NewMockStackInstaller(mockCtrl) + writer := filewritermocks.NewMockFileWriter(mockCtrl) + forceCleanup := false + + clusterSpec := givenClusterSpec(t, clusterSpecManifest) + clusterSpec.Cluster.Spec.ControlPlaneConfiguration.UpgradeRolloutStrategy.Type = "InPlace" + datacenterConfig := givenDatacenterConfig(t, clusterSpecManifest) + machineConfigs := givenMachineConfigs(t, clusterSpecManifest) + ctx := context.Background() + + provider := newProvider(datacenterConfig, machineConfigs, clusterSpec.Cluster, writer, docker, helm, kubectl, forceCleanup) + provider.stackInstaller = stackInstaller + + stackInstaller.EXPECT().CleanupLocalBoots(ctx, forceCleanup) + + err := provider.SetupAndValidateCreateCluster(ctx, clusterSpec) + assert.Error(t, err, "expect validation to fail because in place upgrades are only supported on Ubuntu OS family") +} + func TestGenerateDeploymentFileWithMachineConfigOSImageExternalEtcd(t *testing.T) { t.Skip("External etcd unsupported for GA") clusterSpecManifest := "cluster_osimage_machine_config_external_etcd.yaml" diff --git a/pkg/providers/tinkerbell/validate.go b/pkg/providers/tinkerbell/validate.go index 1922977a8564..2ca3276c56d6 100644 --- a/pkg/providers/tinkerbell/validate.go +++ b/pkg/providers/tinkerbell/validate.go @@ -27,11 +27,22 @@ func validateOsFamily(spec *ClusterSpec) error { if spec.MachineConfigs[groupRef.Name].OSFamily() != controlPlaneOsFamily { return fmt.Errorf("worker node group osFamily cannot be different from control plane osFamily") } + if group.UpgradeRolloutStrategy != nil { + if spec.MachineConfigs[groupRef.Name].OSFamily() != v1alpha1.DefaultOSFamily && group.UpgradeRolloutStrategy.Type == "InPlace" { + return fmt.Errorf("InPlace upgrades are only supported on the Ubuntu OS family") + } + } } if controlPlaneOsFamily != v1alpha1.Bottlerocket && spec.DatacenterConfig.Spec.OSImageURL == "" && spec.ControlPlaneMachineConfig().Spec.OSImageURL == "" { return fmt.Errorf("please use bottlerocket as osFamily for auto-importing or provide a valid osImageURL") } + + if spec.ControlPlaneConfiguration().UpgradeRolloutStrategy != nil { + if controlPlaneOsFamily != v1alpha1.DefaultOSFamily && spec.ControlPlaneConfiguration().UpgradeRolloutStrategy.Type == "InPlace" { + return fmt.Errorf("InPlace upgrades are only supported on the Ubuntu OS family") + } + } return nil }