diff --git a/bootstrap/kubeadm/config/manager/manager.yaml b/bootstrap/kubeadm/config/manager/manager.yaml index dae2a9b6c615..b06c177c478f 100644 --- a/bootstrap/kubeadm/config/manager/manager.yaml +++ b/bootstrap/kubeadm/config/manager/manager.yaml @@ -22,7 +22,7 @@ spec: - "--leader-elect" - "--diagnostics-address=${CAPI_DIAGNOSTICS_ADDRESS:=:8443}" - "--insecure-diagnostics=${CAPI_INSECURE_DIAGNOSTICS:=false}" - - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=false},KubeadmBootstrapFormatIgnition=${EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION:=false}" + - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=true},KubeadmBootstrapFormatIgnition=${EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION:=false}" - "--bootstrap-token-ttl=${KUBEADM_BOOTSTRAP_TOKEN_TTL:=15m}" image: controller:latest name: manager diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 37c4ae3cbc1b..292272b0b034 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -23,7 +23,7 @@ spec: - "--leader-elect" - "--diagnostics-address=${CAPI_DIAGNOSTICS_ADDRESS:=:8443}" - "--insecure-diagnostics=${CAPI_INSECURE_DIAGNOSTICS:=false}" - - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=false},ClusterResourceSet=${EXP_CLUSTER_RESOURCE_SET:=false},ClusterTopology=${CLUSTER_TOPOLOGY:=false},RuntimeSDK=${EXP_RUNTIME_SDK:=false},MachineSetPreflightChecks=${EXP_MACHINE_SET_PREFLIGHT_CHECKS:=false}" + - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=true},ClusterResourceSet=${EXP_CLUSTER_RESOURCE_SET:=false},ClusterTopology=${CLUSTER_TOPOLOGY:=false},RuntimeSDK=${EXP_RUNTIME_SDK:=false},MachineSetPreflightChecks=${EXP_MACHINE_SET_PREFLIGHT_CHECKS:=false}" image: controller:latest name: manager env: diff --git a/controlplane/kubeadm/config/manager/manager.yaml b/controlplane/kubeadm/config/manager/manager.yaml index d79579b40b5f..314d8c395742 100644 --- a/controlplane/kubeadm/config/manager/manager.yaml +++ b/controlplane/kubeadm/config/manager/manager.yaml @@ -22,7 +22,7 @@ spec: - "--leader-elect" - "--diagnostics-address=${CAPI_DIAGNOSTICS_ADDRESS:=:8443}" - "--insecure-diagnostics=${CAPI_INSECURE_DIAGNOSTICS:=false}" - - "--feature-gates=ClusterTopology=${CLUSTER_TOPOLOGY:=false},KubeadmBootstrapFormatIgnition=${EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION:=false}" + - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=true},ClusterTopology=${CLUSTER_TOPOLOGY:=false},KubeadmBootstrapFormatIgnition=${EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION:=false}" image: controller:latest name: manager env: diff --git a/controlplane/kubeadm/config/rbac/role.yaml b/controlplane/kubeadm/config/rbac/role.yaml index 8bae8c0a19f5..c79787ee7d5e 100644 --- a/controlplane/kubeadm/config/rbac/role.yaml +++ b/controlplane/kubeadm/config/rbac/role.yaml @@ -47,6 +47,12 @@ rules: - get - list - watch +- apiGroups: + - cluster.x-k8s.io + resources: + - machinepools + verbs: + - list - apiGroups: - cluster.x-k8s.io resources: diff --git a/controlplane/kubeadm/internal/controllers/controller.go b/controlplane/kubeadm/internal/controllers/controller.go index d58125fc9972..22ba4f0ae2a1 100644 --- a/controlplane/kubeadm/internal/controllers/controller.go +++ b/controlplane/kubeadm/internal/controllers/controller.go @@ -67,6 +67,7 @@ const ( // +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io;bootstrap.cluster.x-k8s.io;controlplane.cluster.x-k8s.io,resources=*,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters;clusters/status,verbs=get;list;watch // +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machinepools,verbs=list // +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch // KubeadmControlPlaneReconciler reconciles a KubeadmControlPlane object. diff --git a/controlplane/kubeadm/main.go b/controlplane/kubeadm/main.go index 8e8646b5c297..cbb91cd1364d 100644 --- a/controlplane/kubeadm/main.go +++ b/controlplane/kubeadm/main.go @@ -52,6 +52,7 @@ import ( kubeadmcontrolplanecontrollers "sigs.k8s.io/cluster-api/controlplane/kubeadm/controllers" "sigs.k8s.io/cluster-api/controlplane/kubeadm/internal/etcd" kcpwebhooks "sigs.k8s.io/cluster-api/controlplane/kubeadm/webhooks" + expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" "sigs.k8s.io/cluster-api/feature" controlplanev1alpha3 "sigs.k8s.io/cluster-api/internal/apis/controlplane/kubeadm/v1alpha3" controlplanev1alpha4 "sigs.k8s.io/cluster-api/internal/apis/controlplane/kubeadm/v1alpha4" @@ -92,6 +93,7 @@ var ( func init() { _ = clientgoscheme.AddToScheme(scheme) _ = clusterv1.AddToScheme(scheme) + _ = expv1.AddToScheme(scheme) _ = controlplanev1alpha3.AddToScheme(scheme) _ = controlplanev1alpha4.AddToScheme(scheme) _ = controlplanev1.AddToScheme(scheme) diff --git a/docs/book/src/developer/testing.md b/docs/book/src/developer/testing.md index 961a9ec18fef..85f5f9945904 100644 --- a/docs/book/src/developer/testing.md +++ b/docs/book/src/developer/testing.md @@ -263,7 +263,6 @@ via [Create the local repository](http://localhost:3000/clusterctl/developers.ht ```yaml kustomize_substitutions: CLUSTER_TOPOLOGY: "true" - EXP_MACHINE_POOL: "true" EXP_CLUSTER_RESOURCE_SET: "true" EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true" EXP_RUNTIME_SDK: "true" diff --git a/docs/book/src/developer/tilt.md b/docs/book/src/developer/tilt.md index 3dec91b63380..1596e89828a7 100644 --- a/docs/book/src/developer/tilt.md +++ b/docs/book/src/developer/tilt.md @@ -108,7 +108,6 @@ provider's yaml. These substitutions are also used when deploying cluster templa ```yaml kustomize_substitutions: CLUSTER_TOPOLOGY: "true" - EXP_MACHINE_POOL: "true" EXP_CLUSTER_RESOURCE_SET: "true" EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION: "true" EXP_RUNTIME_SDK: "true" diff --git a/docs/book/src/tasks/experimental-features/experimental-features.md b/docs/book/src/tasks/experimental-features/experimental-features.md index 6144eced25c9..987d604acd7c 100644 --- a/docs/book/src/tasks/experimental-features/experimental-features.md +++ b/docs/book/src/tasks/experimental-features/experimental-features.md @@ -31,7 +31,6 @@ One way is to set experimental variables on the clusterctl config file. For CAPI ```yaml variables: EXP_CLUSTER_RESOURCE_SET: "true" - EXP_MACHINE_POOL: "true" CLUSTER_TOPOLOGY: "true" EXP_RUNTIME_SDK: "true" EXP_MACHINE_SET_PREFLIGHT_CHECKS: "true" @@ -46,7 +45,6 @@ On development environments started with `Tilt`, features can be enabled by sett ```yaml kustomize_substitutions: EXP_CLUSTER_RESOURCE_SET: 'true' - EXP_MACHINE_POOL: 'true' CLUSTER_TOPOLOGY: 'true' EXP_RUNTIME_SDK: 'true' EXP_MACHINE_SET_PREFLIGHT_CHECKS: 'true' diff --git a/docs/book/src/tasks/experimental-features/machine-pools.md b/docs/book/src/tasks/experimental-features/machine-pools.md index 521550e2922b..84c15bfc21ec 100644 --- a/docs/book/src/tasks/experimental-features/machine-pools.md +++ b/docs/book/src/tasks/experimental-features/machine-pools.md @@ -1,4 +1,4 @@ -# Experimental Feature: MachinePool (alpha) +# Experimental Feature: MachinePool (beta) The `MachinePool` feature provides a way to manage a set of machines by defining a common configuration, number of desired machine replicas etc. similar to `MachineDeployment`, except `MachineSet` controllers are responsible for the lifecycle management of the machines for `MachineDeployment`, whereas in `MachinePools`, diff --git a/docs/book/src/user/quick-start.md b/docs/book/src/user/quick-start.md index 075dda19eccc..90576bb94b93 100644 --- a/docs/book/src/user/quick-start.md +++ b/docs/book/src/user/quick-start.md @@ -539,9 +539,6 @@ for the upgrade from v1.23 to v1.24 as we have to use different cgroupDrivers de # Enable the experimental Cluster topology feature. export CLUSTER_TOPOLOGY=true -# Enable the experimental Machine Pool feature -export EXP_MACHINE_POOL=true - # Initialize the management cluster clusterctl init --infrastructure docker ``` diff --git a/exp/internal/controllers/machinepool_controller_phases_test.go b/exp/internal/controllers/machinepool_controller_phases_test.go index c9f0eaafee18..19b98c7f75b6 100644 --- a/exp/internal/controllers/machinepool_controller_phases_test.go +++ b/exp/internal/controllers/machinepool_controller_phases_test.go @@ -29,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" - utilfeature "k8s.io/component-base/featuregate/testing" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -40,7 +39,6 @@ import ( "sigs.k8s.io/cluster-api/controllers/external" "sigs.k8s.io/cluster-api/controllers/remote" expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" - "sigs.k8s.io/cluster-api/feature" "sigs.k8s.io/cluster-api/internal/test/builder" "sigs.k8s.io/cluster-api/internal/util/ssa" "sigs.k8s.io/cluster-api/util/kubeconfig" @@ -1236,10 +1234,6 @@ func TestReconcileMachinePoolInfrastructure(t *testing.T) { func TestReconcileMachinePoolMachines(t *testing.T) { t.Run("Reconcile MachinePool Machines", func(t *testing.T) { - // NOTE: MachinePool feature flag is disabled by default, thus preventing to create or update MachinePool. - // Enabling the feature flag temporarily for this test. - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() - g := NewWithT(t) ns, err := env.CreateNamespace(ctx, "test-machinepool-machines") diff --git a/exp/internal/webhooks/machinepool_test.go b/exp/internal/webhooks/machinepool_test.go index ecda5dadcd42..583b069383c3 100644 --- a/exp/internal/webhooks/machinepool_test.go +++ b/exp/internal/webhooks/machinepool_test.go @@ -23,23 +23,17 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utilfeature "k8s.io/component-base/featuregate/testing" "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" - "sigs.k8s.io/cluster-api/feature" "sigs.k8s.io/cluster-api/internal/webhooks/util" ) var ctx = ctrl.SetupSignalHandler() func TestMachinePoolDefault(t *testing.T) { - // NOTE: MachinePool feature flag is disabled by default, thus preventing to create or update MachinePool. - // Enabling the feature flag temporarily for this test. - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() - g := NewWithT(t) mp := &expv1.MachinePool{ @@ -68,9 +62,6 @@ func TestMachinePoolDefault(t *testing.T) { } func TestMachinePoolBootstrapValidation(t *testing.T) { - // NOTE: MachinePool feature flag is disabled by default, thus preventing to create or update MachinePool. - // Enabling the feature flag temporarily for this test. - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() tests := []struct { name string bootstrap clusterv1.Bootstrap @@ -127,9 +118,6 @@ func TestMachinePoolBootstrapValidation(t *testing.T) { } func TestMachinePoolNamespaceValidation(t *testing.T) { - // NOTE: MachinePool feature flag is disabled by default, thus preventing to create or update MachinePool. - // Enabling the feature flag temporarily for this test. - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() tests := []struct { name string expectErr bool @@ -204,9 +192,6 @@ func TestMachinePoolNamespaceValidation(t *testing.T) { } func TestMachinePoolClusterNameImmutable(t *testing.T) { - // NOTE: MachinePool feature flag is disabled by default, thus preventing to create or update MachinePool. - // Enabling the feature flag temporarily for this test. - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() tests := []struct { name string oldClusterName string @@ -266,9 +251,6 @@ func TestMachinePoolClusterNameImmutable(t *testing.T) { } func TestMachinePoolVersionValidation(t *testing.T) { - // NOTE: MachinePool feature flag is disabled by default, thus preventing to create or update MachinePool. - // Enabling the feature flag temporarily for this test. - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() tests := []struct { name string expectErr bool diff --git a/feature/feature.go b/feature/feature.go index ff2bb33dc4bf..cec880672656 100644 --- a/feature/feature.go +++ b/feature/feature.go @@ -32,6 +32,7 @@ const ( // MachinePool is a feature gate for MachinePool functionality. // // alpha: v0.3 + // beta: v1.7 MachinePool featuregate.Feature = "MachinePool" // ClusterResourceSet is a feature gate for the ClusterResourceSet functionality. @@ -70,7 +71,7 @@ func init() { // To add a new feature, define a key for it above and add it here. var defaultClusterAPIFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ // Every feature should be initiated here: - MachinePool: {Default: false, PreRelease: featuregate.Alpha}, + MachinePool: {Default: true, PreRelease: featuregate.Beta}, ClusterResourceSet: {Default: true, PreRelease: featuregate.Beta}, ClusterTopology: {Default: false, PreRelease: featuregate.Alpha}, KubeadmBootstrapFormatIgnition: {Default: false, PreRelease: featuregate.Alpha}, diff --git a/internal/controllers/topology/cluster/cluster_controller_test.go b/internal/controllers/topology/cluster/cluster_controller_test.go index 3f2013b810f3..b1be769fa553 100644 --- a/internal/controllers/topology/cluster/cluster_controller_test.go +++ b/internal/controllers/topology/cluster/cluster_controller_test.go @@ -64,7 +64,6 @@ var ( func TestClusterReconciler_reconcileNewlyCreatedCluster(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.ClusterTopology, true)() - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() g := NewWithT(t) timeout := 5 * time.Second @@ -113,7 +112,6 @@ func TestClusterReconciler_reconcileNewlyCreatedCluster(t *testing.T) { func TestClusterReconciler_reconcileMultipleClustersFromOneClass(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.ClusterTopology, true)() - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() g := NewWithT(t) timeout := 5 * time.Second @@ -166,7 +164,6 @@ func TestClusterReconciler_reconcileMultipleClustersFromOneClass(t *testing.T) { func TestClusterReconciler_reconcileUpdateOnClusterTopology(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.ClusterTopology, true)() - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() g := NewWithT(t) timeout := 300 * time.Second @@ -258,7 +255,6 @@ func TestClusterReconciler_reconcileUpdateOnClusterTopology(t *testing.T) { func TestClusterReconciler_reconcileUpdatesOnClusterClass(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.ClusterTopology, true)() - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() g := NewWithT(t) timeout := 5 * time.Second @@ -359,7 +355,6 @@ func TestClusterReconciler_reconcileUpdatesOnClusterClass(t *testing.T) { func TestClusterReconciler_reconcileClusterClassRebase(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.ClusterTopology, true)() - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() g := NewWithT(t) timeout := 30 * time.Second @@ -441,7 +436,6 @@ func TestClusterReconciler_reconcileClusterClassRebase(t *testing.T) { func TestClusterReconciler_reconcileDelete(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.RuntimeSDK, true)() - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() catalog := runtimecatalog.New() _ = runtimehooksv1.AddToCatalog(catalog) @@ -595,7 +589,6 @@ func TestClusterReconciler_reconcileDelete(t *testing.T) { // In this case deletion of the ClusterClass should be blocked by the webhook. func TestClusterReconciler_deleteClusterClass(t *testing.T) { defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.ClusterTopology, true)() - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() g := NewWithT(t) timeout := 5 * time.Second diff --git a/internal/controllers/topology/cluster/reconcile_state_test.go b/internal/controllers/topology/cluster/reconcile_state_test.go index dff252506a98..bec5c2ca62f0 100644 --- a/internal/controllers/topology/cluster/reconcile_state_test.go +++ b/internal/controllers/topology/cluster/reconcile_state_test.go @@ -33,7 +33,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" - utilfeature "k8s.io/component-base/featuregate/testing" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" @@ -45,7 +44,6 @@ import ( runtimev1 "sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1" runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog" runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" - "sigs.k8s.io/cluster-api/feature" "sigs.k8s.io/cluster-api/internal/contract" "sigs.k8s.io/cluster-api/internal/controllers/topology/cluster/scope" "sigs.k8s.io/cluster-api/internal/controllers/topology/cluster/structuredmerge" @@ -2196,8 +2194,6 @@ func TestReconcileMachineDeployments(t *testing.T) { } func TestReconcileMachinePools(t *testing.T) { - defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)() - g := NewWithT(t) infrastructureMachinePool1 := builder.TestInfrastructureMachinePool(metav1.NamespaceDefault, "infrastructure-machinepool-1").Build() diff --git a/test/infrastructure/docker/config/manager/manager.yaml b/test/infrastructure/docker/config/manager/manager.yaml index 56fc71bb9239..29c2661bbca9 100644 --- a/test/infrastructure/docker/config/manager/manager.yaml +++ b/test/infrastructure/docker/config/manager/manager.yaml @@ -20,7 +20,7 @@ spec: - "--leader-elect" - "--diagnostics-address=${CAPI_DIAGNOSTICS_ADDRESS:=:8443}" - "--insecure-diagnostics=${CAPI_INSECURE_DIAGNOSTICS:=false}" - - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=false},ClusterTopology=${CLUSTER_TOPOLOGY:=false}" + - "--feature-gates=MachinePool=${EXP_MACHINE_POOL:=true},ClusterTopology=${CLUSTER_TOPOLOGY:=false}" image: controller:latest name: manager env: