diff --git a/pkg/reconciler/tenancy/workspace/README.md b/pkg/reconciler/tenancy/workspace/README.md new file mode 100644 index 00000000000..edff9d7eead --- /dev/null +++ b/pkg/reconciler/tenancy/workspace/README.md @@ -0,0 +1,9 @@ +# Workspace Controller + +The workspace controller is root controller for the workspace. +It is responsible for (in calling order): + +- `Metadata` - updates workspace metadata in annotations. +- `Delete` the workspace if it is in the `Deleting` phase and LogicalCluster finalizer is removed. +- `Scheduling` - picks the shard and schedules the workspace on the shard. Creates logical cluster for it. +- `Phase` - updates workspace phase based on the conditions of the workspace and LogicalCluster. diff --git a/pkg/reconciler/tenancy/workspace/workspace_reconcile_phase.go b/pkg/reconciler/tenancy/workspace/workspace_reconcile_phase.go index 99648ff7974..8696731877d 100644 --- a/pkg/reconciler/tenancy/workspace/workspace_reconcile_phase.go +++ b/pkg/reconciler/tenancy/workspace/workspace_reconcile_phase.go @@ -22,6 +22,7 @@ import ( "github.com/kcp-dev/logicalcluster/v3" + v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/klog/v2" @@ -74,7 +75,13 @@ func (r *phaseReconciler) reconcile(ctx context.Context, workspace *tenancyv1alp workspace.Status.Phase = corev1alpha1.LogicalClusterPhaseReady conditions.MarkTrue(workspace, tenancyv1alpha1.WorkspaceInitialized) + case corev1alpha1.LogicalClusterPhaseNotReady: + checkConditionAndSetPhase(workspace) + return reconcileStatusContinue, nil + case corev1alpha1.LogicalClusterPhaseReady: + // On delete we need to wait for the logical cluster to be deleted + // before we can mark the workspace as deleted. if !workspace.DeletionTimestamp.IsZero() { logger = logger.WithValues("cluster", workspace.Spec.Cluster) @@ -106,7 +113,22 @@ func (r *phaseReconciler) reconcile(ctx context.Context, workspace *tenancyv1alp logger.Info("workspace content is deleted") return reconcileStatusContinue, nil } + // if workspace is ready, we check if it suppose to be ready by checking conditions. + checkConditionAndSetPhase(workspace) + return reconcileStatusContinue, nil } return reconcileStatusContinue, nil } + +func checkConditionAndSetPhase(workspace *tenancyv1alpha1.Workspace) { + // if workspace is ready, we check if it suppose to be ready by checking conditions. + // Conditions can be added by other reconcilers, so we need to check them. + for _, c := range workspace.Status.Conditions { + if c.Status != v1.ConditionTrue { + workspace.Status.Phase = corev1alpha1.LogicalClusterPhaseNotReady + return + } + } + workspace.Status.Phase = corev1alpha1.LogicalClusterPhaseReady +} diff --git a/pkg/reconciler/tenancy/workspace/workspace_reconcile_phase_test.go b/pkg/reconciler/tenancy/workspace/workspace_reconcile_phase_test.go new file mode 100644 index 00000000000..1683ed3cc7b --- /dev/null +++ b/pkg/reconciler/tenancy/workspace/workspace_reconcile_phase_test.go @@ -0,0 +1,230 @@ +/* +Copyright 2024 The KCP 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 workspace + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + + corev1alpha1 "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1" + tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" + conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1" + "github.com/kcp-dev/logicalcluster/v3" +) + +func TestReconcilePhase(t *testing.T) { + //date, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") + //require.NoError(t, err) + + for _, testCase := range []struct { + name string + input *tenancyv1alpha1.Workspace + getLogicalCluster func(ctx context.Context, cluster logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) + + wantPhase corev1alpha1.LogicalClusterPhaseType + wantStatus reconcileStatus + wantCondition conditionsv1alpha1.Condition + }{ + { + name: "workspace is scheduling but not yet initialized", + input: &tenancyv1alpha1.Workspace{ + Status: tenancyv1alpha1.WorkspaceStatus{ + Phase: corev1alpha1.LogicalClusterPhaseScheduling, + }, + }, + wantPhase: corev1alpha1.LogicalClusterPhaseScheduling, + wantStatus: reconcileStatusContinue, + wantCondition: conditionsv1alpha1.Condition{ + Type: tenancyv1alpha1.WorkspaceInitialized, + Status: corev1.ConditionFalse, + }, + }, + { + name: "workspace is scheduled and moved to initializing", + input: &tenancyv1alpha1.Workspace{ + Spec: tenancyv1alpha1.WorkspaceSpec{ + URL: "http://example.com", + Cluster: "cluster-1", + }, + Status: tenancyv1alpha1.WorkspaceStatus{ + Phase: corev1alpha1.LogicalClusterPhaseScheduling, + }, + }, + wantPhase: corev1alpha1.LogicalClusterPhaseInitializing, + wantStatus: reconcileStatusContinue, + }, + { + name: "workspace is initializing and logical cluster is not found", + input: &tenancyv1alpha1.Workspace{ + Spec: tenancyv1alpha1.WorkspaceSpec{ + URL: "http://example.com", + Cluster: "cluster-1", + }, + Status: tenancyv1alpha1.WorkspaceStatus{ + Phase: corev1alpha1.LogicalClusterPhaseInitializing, + }, + }, + getLogicalCluster: func(ctx context.Context, cluster logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) { + return nil, apierrors.NewNotFound(corev1alpha1.Resource("logicalcluster"), "cluster-1") + }, + wantPhase: corev1alpha1.LogicalClusterPhaseInitializing, + wantStatus: reconcileStatusContinue, + }, + { + name: "workspace is initializing and logicalCluster not yet initialized", + input: &tenancyv1alpha1.Workspace{ + Spec: tenancyv1alpha1.WorkspaceSpec{ + URL: "http://example.com", + Cluster: "cluster-1", + }, + Status: tenancyv1alpha1.WorkspaceStatus{ + Phase: corev1alpha1.LogicalClusterPhaseInitializing, + }, + }, + getLogicalCluster: func(ctx context.Context, cluster logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) { + return &corev1alpha1.LogicalCluster{ + Status: corev1alpha1.LogicalClusterStatus{ + Initializers: []corev1alpha1.LogicalClusterInitializer{ + "initializer-1", + }, + }, + }, nil + }, + wantPhase: corev1alpha1.LogicalClusterPhaseInitializing, + wantStatus: reconcileStatusContinue, + }, + { + name: "workspace is initializing and logicalCluster initialized", + input: &tenancyv1alpha1.Workspace{ + Spec: tenancyv1alpha1.WorkspaceSpec{ + URL: "http://example.com", + Cluster: "cluster-1", + }, + Status: tenancyv1alpha1.WorkspaceStatus{ + Phase: corev1alpha1.LogicalClusterPhaseInitializing, + }, + }, + getLogicalCluster: func(ctx context.Context, cluster logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) { + return &corev1alpha1.LogicalCluster{ + Status: corev1alpha1.LogicalClusterStatus{ + Initializers: []corev1alpha1.LogicalClusterInitializer{}, + }, + }, nil + }, + wantPhase: corev1alpha1.LogicalClusterPhaseReady, + wantStatus: reconcileStatusContinue, + }, + { + name: "workspace is ready - no-op", + input: &tenancyv1alpha1.Workspace{ + Spec: tenancyv1alpha1.WorkspaceSpec{ + URL: "http://example.com", + Cluster: "cluster-1", + }, + Status: tenancyv1alpha1.WorkspaceStatus{ + Phase: corev1alpha1.LogicalClusterPhaseReady, + }, + }, + getLogicalCluster: func(ctx context.Context, cluster logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) { + return &corev1alpha1.LogicalCluster{ + Status: corev1alpha1.LogicalClusterStatus{ + Initializers: []corev1alpha1.LogicalClusterInitializer{}, + }, + }, nil + }, + wantPhase: corev1alpha1.LogicalClusterPhaseReady, + wantStatus: reconcileStatusContinue, + }, + { + name: "workspace is ready - but condition is not ready", + input: &tenancyv1alpha1.Workspace{ + Spec: tenancyv1alpha1.WorkspaceSpec{ + URL: "http://example.com", + Cluster: "cluster-1", + }, + Status: tenancyv1alpha1.WorkspaceStatus{ + Phase: corev1alpha1.LogicalClusterPhaseReady, + Conditions: []conditionsv1alpha1.Condition{ + { + Type: tenancyv1alpha1.MountConditionReady, + Status: corev1.ConditionFalse, + }, + }, + }, + }, + getLogicalCluster: func(ctx context.Context, cluster logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) { + return &corev1alpha1.LogicalCluster{ + Status: corev1alpha1.LogicalClusterStatus{ + Initializers: []corev1alpha1.LogicalClusterInitializer{}, + }, + }, nil + }, + wantPhase: corev1alpha1.LogicalClusterPhaseNotReady, + wantStatus: reconcileStatusContinue, + }, + { + name: "workspace is no ready - but condition is ready", + input: &tenancyv1alpha1.Workspace{ + Spec: tenancyv1alpha1.WorkspaceSpec{ + URL: "http://example.com", + Cluster: "cluster-1", + }, + Status: tenancyv1alpha1.WorkspaceStatus{ + Phase: corev1alpha1.LogicalClusterPhaseNotReady, + Conditions: []conditionsv1alpha1.Condition{ + { + Type: tenancyv1alpha1.MountConditionReady, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + getLogicalCluster: func(ctx context.Context, cluster logicalcluster.Path) (*corev1alpha1.LogicalCluster, error) { + return &corev1alpha1.LogicalCluster{ + Status: corev1alpha1.LogicalClusterStatus{ + Initializers: []corev1alpha1.LogicalClusterInitializer{}, + }, + }, nil + }, + wantPhase: corev1alpha1.LogicalClusterPhaseReady, + wantStatus: reconcileStatusContinue, + }, + } { + t.Run(testCase.name, func(t *testing.T) { + reconciler := phaseReconciler{ + getLogicalCluster: testCase.getLogicalCluster, + requeueAfter: func(workspace *tenancyv1alpha1.Workspace, after time.Duration) {}, + } + status, err := reconciler.reconcile(context.Background(), testCase.input) + + require.NoError(t, err) + require.Equal(t, testCase.wantStatus, status) + require.Equal(t, testCase.wantPhase, testCase.input.Status.Phase) + + for _, condition := range testCase.input.Status.Conditions { + if condition.Type == testCase.wantCondition.Type { + require.Equal(t, testCase.wantCondition, condition) + } + } + }) + } +} diff --git a/pkg/reconciler/tenancy/workspacestatuses/README.md b/pkg/reconciler/tenancy/workspacestatuses/README.md deleted file mode 100644 index e7d5a76e9a3..00000000000 --- a/pkg/reconciler/tenancy/workspacestatuses/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Workspace statuses controller - -The controller has a single purpose - to update the workspace phase based on -the conditions of the workspace. This way if we have an external process that -updates the workspace, we can reflect the status of the workspace in the workspace -object. diff --git a/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_controller.go b/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_controller.go deleted file mode 100644 index 940e45ad49b..00000000000 --- a/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_controller.go +++ /dev/null @@ -1,193 +0,0 @@ -/* -Copyright 2024 The KCP 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 workspacestatuses - -import ( - "context" - "fmt" - "time" - - kcpcache "github.com/kcp-dev/apimachinery/v2/pkg/cache" - kcpdynamic "github.com/kcp-dev/client-go/dynamic" - - kerrors "k8s.io/apimachinery/pkg/api/errors" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/runtime" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/workqueue" - "k8s.io/klog/v2" - - "github.com/kcp-dev/kcp/pkg/logging" - "github.com/kcp-dev/kcp/pkg/reconciler/committer" - tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" - kcpclientset "github.com/kcp-dev/kcp/sdk/client/clientset/versioned/cluster" - tenancyv1alpha1client "github.com/kcp-dev/kcp/sdk/client/clientset/versioned/typed/tenancy/v1alpha1" - tenancyv1alpha1informers "github.com/kcp-dev/kcp/sdk/client/informers/externalversions/tenancy/v1alpha1" - tenancyv1alpha1listers "github.com/kcp-dev/kcp/sdk/client/listers/tenancy/v1alpha1" -) - -const ( - // ControllerName is the name of this controller. - ControllerName = "kcp-workspace-statuses" -) - -// NewController creates a new controller for generic mounts. -func NewController( - kcpClusterClient kcpclientset.ClusterInterface, - dynamicClusterClient kcpdynamic.ClusterInterface, - workspaceInformer tenancyv1alpha1informers.WorkspaceClusterInformer, -) (*Controller, error) { - c := &Controller{ - queue: workqueue.NewTypedRateLimitingQueueWithConfig( - workqueue.DefaultTypedControllerRateLimiter[string](), - workqueue.TypedRateLimitingQueueConfig[string]{ - Name: ControllerName, - }, - ), - - dynamicClusterClient: dynamicClusterClient, - - workspaceIndexer: workspaceInformer.Informer().GetIndexer(), - workspaceLister: workspaceInformer.Lister(), - - commit: committer.NewCommitter[*tenancyv1alpha1.Workspace, tenancyv1alpha1client.WorkspaceInterface, *tenancyv1alpha1.WorkspaceSpec, *tenancyv1alpha1.WorkspaceStatus](kcpClusterClient.TenancyV1alpha1().Workspaces()), - } - - _, _ = workspaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { c.enqueueWorkspace(obj) }, - UpdateFunc: func(old, obj interface{}) { c.enqueueWorkspace(obj) }, - }) - - return c, nil -} - -type workspaceResource = committer.Resource[*tenancyv1alpha1.WorkspaceSpec, *tenancyv1alpha1.WorkspaceStatus] - -// Controller watches Workspaces and checks conditions. If a condition is not ready, -// it will flip workspace status to "NotReady". If all conditions are ready, it will -// flip workspace status to "Ready". -type Controller struct { - // queue is the work-queue used by the controller - queue workqueue.TypedRateLimitingInterface[string] - - dynamicClusterClient kcpdynamic.ClusterInterface - - workspaceIndexer cache.Indexer - workspaceLister tenancyv1alpha1listers.WorkspaceClusterLister - - // commit creates a patch and submits it, if needed. - commit func(ctx context.Context, new, old *workspaceResource) error -} - -// enqueueWorkspace adds the object to the work queue. -func (c *Controller) enqueueWorkspace(obj interface{}) { - key, err := kcpcache.MetaClusterNamespaceKeyFunc(obj) - if err != nil { - runtime.HandleError(err) - return - } - logger := logging.WithQueueKey(logging.WithReconciler(klog.Background(), ControllerName), key) - logger.V(4).Info("queueing Workspace") - c.queue.Add(key) -} - -func (c *Controller) Start(ctx context.Context, numThreads int) { - defer runtime.HandleCrash() - defer c.queue.ShutDown() - - logger := logging.WithReconciler(klog.FromContext(ctx), ControllerName) - ctx = klog.NewContext(ctx, logger) - logger.Info("Starting controller") - defer logger.Info("Shutting down controller") - - for i := 0; i < numThreads; i++ { - go wait.Until(func() { c.startWorker(ctx) }, time.Second, ctx.Done()) - } - - <-ctx.Done() -} - -func (c *Controller) startWorker(ctx context.Context) { - for c.processNextWorkItem(ctx) { - } -} - -func (c *Controller) processNextWorkItem(ctx context.Context) bool { - // Wait until there is a new item in the working queue - k, quit := c.queue.Get() - if quit { - return false - } - key := k - - logger := logging.WithQueueKey(klog.FromContext(ctx), key) - ctx = klog.NewContext(ctx, logger) - logger.V(4).Info("processing key") - - // No matter what, tell the queue we're done with this key, to unblock - // other workers. - defer c.queue.Done(key) - - if requeue, err := c.process(ctx, key); err != nil { - runtime.HandleError(fmt.Errorf("%q controller failed to sync %q, err: %w", ControllerName, key, err)) - c.queue.AddRateLimited(key) - return true - } else if requeue { - // only requeue if we didn't error, but we still want to requeue - c.queue.Add(key) - return true - } - c.queue.Forget(key) - return true -} - -func (c *Controller) process(ctx context.Context, key string) (bool, error) { - parent, _, name, err := kcpcache.SplitMetaClusterNamespaceKey(key) - if err != nil { - return false, err - } - - workspace, err := c.workspaceLister.Cluster(parent).Get(name) - if err != nil { - if kerrors.IsNotFound(err) { - return false, nil // object deleted before we handled it - } - return false, err - } - - old := workspace - workspace = workspace.DeepCopy() - - logger := logging.WithObject(klog.FromContext(ctx), workspace) - ctx = klog.NewContext(ctx, logger) - - var errs []error - requeue, err := c.reconcile(ctx, workspace) - if err != nil { - errs = append(errs, err) - } - - // If the object being reconciled changed as a result, update it. - oldResource := &workspaceResource{ObjectMeta: old.ObjectMeta, Spec: &old.Spec, Status: &old.Status} - newResource := &workspaceResource{ObjectMeta: workspace.ObjectMeta, Spec: &workspace.Spec, Status: &workspace.Status} - if err := c.commit(ctx, oldResource, newResource); err != nil { - errs = append(errs, err) - } - - return requeue, utilerrors.NewAggregate(errs) -} diff --git a/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_reconciler.go b/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_reconciler.go deleted file mode 100644 index 72fc1a9824f..00000000000 --- a/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_reconciler.go +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2024 The KCP 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 workspacestatuses - -import ( - "context" - - utilserrors "k8s.io/apimachinery/pkg/util/errors" - - tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" -) - -type reconcileStatus int - -const ( - reconcileStatusStopAndRequeue reconcileStatus = iota - reconcileStatusContinue -) - -type reconciler interface { - reconcile(ctx context.Context, workspace *tenancyv1alpha1.Workspace) (reconcileStatus, error) -} - -// reconcile reconciles the workspace objects and controls the phase of the workspace. -func (c *Controller) reconcile(ctx context.Context, ws *tenancyv1alpha1.Workspace) (bool, error) { - reconcilers := []reconciler{ - &workspacePhaseUpdater{}, - } - - var errs []error - - requeue := false - for _, r := range reconcilers { - var err error - var status reconcileStatus - status, err = r.reconcile(ctx, ws) - if err != nil { - errs = append(errs, err) - } - if status == reconcileStatusStopAndRequeue { - requeue = true - break - } - } - - return requeue, utilserrors.NewAggregate(errs) -} diff --git a/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_reconciler_updater.go b/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_reconciler_updater.go deleted file mode 100644 index a88d2a7fa63..00000000000 --- a/pkg/reconciler/tenancy/workspacestatuses/workspacestatuses_reconciler_updater.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2024 The KCP 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 workspacestatuses - -import ( - "context" - - v1 "k8s.io/api/core/v1" - - corev1alpha1 "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1" - tenancyv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/tenancy/v1alpha1" -) - -// workspaceStatusUpdater updates the status of the workspace based on the conditions. -type workspacePhaseUpdater struct{} - -func (r *workspacePhaseUpdater) reconcile(ctx context.Context, workspace *tenancyv1alpha1.Workspace) (reconcileStatus, error) { - for _, c := range workspace.Status.Conditions { - if c.Status != v1.ConditionTrue { - workspace.Status.Phase = corev1alpha1.LogicalClusterPhaseNotReady - return reconcileStatusContinue, nil - } - } - - workspace.Status.Phase = corev1alpha1.LogicalClusterPhaseReady - return reconcileStatusContinue, nil -} diff --git a/pkg/server/controllers.go b/pkg/server/controllers.go index d0ccd24e624..d1c9bf34492 100644 --- a/pkg/server/controllers.go +++ b/pkg/server/controllers.go @@ -88,7 +88,6 @@ import ( tenancyreplicatelogicalcluster "github.com/kcp-dev/kcp/pkg/reconciler/tenancy/replicatelogicalcluster" "github.com/kcp-dev/kcp/pkg/reconciler/tenancy/workspace" "github.com/kcp-dev/kcp/pkg/reconciler/tenancy/workspacemounts" - "github.com/kcp-dev/kcp/pkg/reconciler/tenancy/workspacestatuses" "github.com/kcp-dev/kcp/pkg/reconciler/tenancy/workspacetype" "github.com/kcp-dev/kcp/pkg/reconciler/topology/partitionset" initializingworkspacesbuilder "github.com/kcp-dev/kcp/pkg/virtual/initializingworkspaces/builder" @@ -697,41 +696,6 @@ func (s *Server) installWorkspaceMountsScheduler(ctx context.Context, config *re }) } -func (s *Server) installWorkspaceStatusesScheduler(ctx context.Context, config *rest.Config) error { - // TODO(mjudeikis): Remove this and move to batteries. - if !kcpfeatures.DefaultFeatureGate.Enabled(kcpfeatures.WorkspaceMounts) { - return nil - } - // NOTE: keep `config` unaltered so there isn't cross-use between controllers installed here. - workspaceConfig := rest.CopyConfig(config) - workspaceConfig = rest.AddUserAgent(workspaceConfig, workspacestatuses.ControllerName) - kcpClusterClient, err := kcpclientset.NewForConfig(workspaceConfig) - if err != nil { - return err - } - - dynamicClusterClient, err := kcpdynamic.NewForConfig(workspaceConfig) - if err != nil { - return err - } - - workspaceStatusesController, err := workspacestatuses.NewController( - kcpClusterClient, - dynamicClusterClient, - s.KcpSharedInformerFactory.Tenancy().V1alpha1().Workspaces(), - ) - if err != nil { - return err - } - - return s.registerController(&controllerWrapper{ - Name: workspacestatuses.ControllerName, - Runner: func(ctx context.Context) { - workspaceStatusesController.Start(ctx, 2) - }, - }) -} - func (s *Server) installLogicalCluster(ctx context.Context, config *rest.Config) error { logicalClusterConfig := rest.CopyConfig(config) logicalClusterConfig = rest.AddUserAgent(logicalClusterConfig, logicalclusterctrl.ControllerName) diff --git a/pkg/server/server.go b/pkg/server/server.go index 8cf90428936..dfff534a93e 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -234,9 +234,6 @@ func (s *Server) installControllers(ctx context.Context, controllerConfig *rest. if err := s.installWorkspaceMountsScheduler(ctx, controllerConfig); err != nil { return err } - if err := s.installWorkspaceStatusesScheduler(ctx, controllerConfig); err != nil { - return err - } if err := s.installTenancyLogicalClusterController(ctx, controllerConfig); err != nil { return err }