From 4d3cca420997254b559f71a241888f477ff70194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 22 Jan 2025 00:12:11 +0100 Subject: [PATCH] [node-labeler] Introduce workspace count controller (#20509) * [ws-daemon] Introduce pod count controller * remove unnecessary variable * move to `node-labeler` * act on ws crds * Fix runtime not filled in yet * Make tests pass! * Improve test file structure * Fix `node-labeler:lib` build * Remove unnecessary changes * Address some review comments (thanks, kyle!) * Try caching? * Queue deleted nodes and periodically reconcile it all * WCC cleanup function * Fix tests * Update name * Add metrics for controller * Add synchronization for node reconciliation to prevent race conditions * Address review comments * Remove superflous log * Remove unneeded metrics and add cool log line * big yellow warning for a thing that should not happen --- components/node-labeler/BUILD.yaml | 10 + components/node-labeler/cmd/root.go | 2 +- components/node-labeler/cmd/run.go | 246 +++++++++++++++- components/node-labeler/cmd/run_test.go | 266 ++++++++++++++++++ .../crd/workspace.gitpod.io_workspaces.yaml | 5 + components/node-labeler/go.mod | 27 +- components/node-labeler/go.sum | 34 ++- .../pkg/components/node-labeler/role.go | 13 + 8 files changed, 590 insertions(+), 13 deletions(-) create mode 100644 components/node-labeler/cmd/run_test.go create mode 100644 components/node-labeler/crd/workspace.gitpod.io_workspaces.yaml diff --git a/components/node-labeler/BUILD.yaml b/components/node-labeler/BUILD.yaml index e4143403474124..2a6e2f6477729b 100644 --- a/components/node-labeler/BUILD.yaml +++ b/components/node-labeler/BUILD.yaml @@ -5,11 +5,16 @@ packages: - "**/*.go" - "go.mod" - "go.sum" + - "crd/*.yaml" deps: - components/common-go:lib + - components/ws-manager-api/go:lib + - components/ws-manager-mk2:crd env: - CGO_ENABLED=0 - GOOS=linux + prep: + - ["mv", "_deps/components-ws-manager-mk2--crd/workspace.gitpod.io_workspaces.yaml", "crd/workspace.gitpod.io_workspaces.yaml"] config: packaging: app buildCommand: ["go", "build", "-trimpath", "-ldflags", "-buildid= -w -s -X 'github.com/gitpod-io/gitpod/node-labeler/cmd.Version=commit-${__git_commit}'"] @@ -34,5 +39,10 @@ packages: - "**/*.go" - "go.mod" - "go.sum" + - "crd/*.yaml" deps: - components/common-go:lib + - components/ws-manager-api/go:lib + - components/ws-manager-mk2:crd + prep: + - ["mv", "_deps/components-ws-manager-mk2--crd/workspace.gitpod.io_workspaces.yaml", "crd/workspace.gitpod.io_workspaces.yaml"] diff --git a/components/node-labeler/cmd/root.go b/components/node-labeler/cmd/root.go index a31580a5557bfa..ff940765c76f77 100644 --- a/components/node-labeler/cmd/root.go +++ b/components/node-labeler/cmd/root.go @@ -32,7 +32,7 @@ var ( // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: ServiceName, - Short: "node-labeler is in charge of maintining the node labels that workspaces require to run in a node", + Short: "node-labeler is in charge of maintaining the node labels that workspaces require to run in a node", PersistentPreRun: func(cmd *cobra.Command, args []string) { log.Init(ServiceName, Version, jsonLog, verbose) }, diff --git a/components/node-labeler/cmd/run.go b/components/node-labeler/cmd/run.go index 5f32978ddde651..f51b9f6bf3160e 100644 --- a/components/node-labeler/cmd/run.go +++ b/components/node-labeler/cmd/run.go @@ -15,6 +15,7 @@ import ( "time" "github.com/bombsimon/logrusr/v2" + workspacev1 "github.com/gitpod-io/gitpod/ws-manager/api/crd/v1" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -31,7 +32,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/metrics" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/predicate" @@ -78,16 +81,16 @@ var runCmd = &cobra.Command{ LeaderElectionID: "node-labeler.gitpod.io", }) if err != nil { - log.WithError(err).Fatal("unable to start node-labeber") + log.WithError(err).Fatal("unable to start node-labeler") } - client, err := client.New(ctrl.GetConfigOrDie(), client.Options{}) + kClient, err := client.New(ctrl.GetConfigOrDie(), client.Options{}) if err != nil { log.WithError(err).Fatal("unable to create client") } r := &PodReconciler{ - client, + kClient, } componentPredicate, err := predicate.LabelSelectorPredicate(metav1.LabelSelector{ @@ -110,6 +113,36 @@ var runCmd = &cobra.Command{ log.WithError(err).Fatal("unable to bind controller watch event handler") } + if err := mgr.GetFieldIndexer().IndexField(context.Background(), &workspacev1.Workspace{}, "status.runtime.nodeName", func(o client.Object) []string { + ws := o.(*workspacev1.Workspace) + if ws.Status.Runtime == nil { + return nil + } + return []string{ws.Status.Runtime.NodeName} + }); err != nil { + log.WithError(err).Fatal("unable to create workspace indexer") + return + } + + nsac, err := NewNodeScaledownAnnotationController(mgr.GetClient()) + if err != nil { + log.WithError(err).Fatal("unable to create node scaledown annotation controller") + } + err = nsac.SetupWithManager(mgr) + if err != nil { + log.WithError(err).Fatal("unable to bind node scaledown annotation controller") + } + + err = mgr.Add(manager.RunnableFunc(func(ctx context.Context) error { + <-ctx.Done() + log.Info("Received shutdown signal - stopping NodeScaledownAnnotationController") + nsac.Stop() + return nil + })) + if err != nil { + log.WithError(err).Fatal("couldn't properly clean up node scaledown annotation controller") + } + metrics.Registry.MustRegister(NodeLabelerCounterVec) metrics.Registry.MustRegister(NodeLabelerTimeHistVec) @@ -123,10 +156,10 @@ var runCmd = &cobra.Command{ log.WithError(err).Fatal("unable to set up ready check") } - log.Info("starting node-labeber") + log.Info("starting node-labeler") err = mgr.Start(ctrl.SetupSignalHandler()) if err != nil { - log.WithError(err).Fatal("problem running node-labeber") + log.WithError(err).Fatal("problem running node-labeler") } log.Info("Received SIGINT - shutting down") @@ -135,6 +168,8 @@ var runCmd = &cobra.Command{ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + utilruntime.Must(workspacev1.AddToScheme(scheme)) + rootCmd.AddCommand(runCmd) } @@ -249,6 +284,207 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req reconcile.Request) (r return reconcile.Result{}, nil } +type NodeScaledownAnnotationController struct { + client.Client + nodesToReconcile chan string + stopChan chan struct{} +} + +func NewNodeScaledownAnnotationController(client client.Client) (*NodeScaledownAnnotationController, error) { + controller := &NodeScaledownAnnotationController{ + Client: client, + nodesToReconcile: make(chan string, 1000), + stopChan: make(chan struct{}), + } + + return controller, nil +} + +func (c *NodeScaledownAnnotationController) SetupWithManager(mgr ctrl.Manager) error { + go c.reconciliationWorker() + go c.periodicReconciliation() + + return ctrl.NewControllerManagedBy(mgr). + Named("node-scaledown-annotation-controller"). + For(&workspacev1.Workspace{}). + WithEventFilter(c.workspaceFilter()). + Complete(c) +} + +// periodicReconciliation periodically reconciles all nodes in the cluster +func (c *NodeScaledownAnnotationController) periodicReconciliation() { + ticker := time.NewTicker(5 * time.Minute) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + log.Info("starting periodic full reconciliation") + ctx := context.Background() + if _, err := c.reconcileAllNodes(ctx); err != nil { + log.WithError(err).Error("periodic reconciliation failed") + } + case <-c.stopChan: + log.Info("stopping periodic full reconciliation") + return + } + } +} + +// reconciliationWorker consumes nodesToReconcile and reconciles each node +func (c *NodeScaledownAnnotationController) reconciliationWorker() { + log.Info("reconciliation worker started") + for { + select { + case nodeName := <-c.nodesToReconcile: + ctx := context.Background() + if err := c.reconcileNode(ctx, nodeName); err != nil { + log.WithError(err).WithField("node", nodeName).Error("failed to reconcile node from queue") + } + case <-c.stopChan: + log.Info("reconciliation worker stopping") + return + } + } +} + +func (c *NodeScaledownAnnotationController) workspaceFilter() predicate.Predicate { + return predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + ws := e.Object.(*workspacev1.Workspace) + if ws.Status.Runtime == nil { + log.WithField("workspace", ws.Name).Info("workspace not ready yet") + return false + } + + return ws.Status.Runtime != nil && ws.Status.Runtime.NodeName != "" + }, + UpdateFunc: func(e event.UpdateEvent) bool { + wsOld := e.ObjectOld.(*workspacev1.Workspace) + ws := e.ObjectNew.(*workspacev1.Workspace) + // if we haven't seen runtime info before and now it's there, let's reconcile. + // similarly, if the node name changed, we need to reconcile the old node as well. + if (wsOld.Status.Runtime == nil && ws.Status.Runtime != nil && ws.Status.Runtime.NodeName != "") || // we just got runtime info + (wsOld.Status.Runtime != nil && ws.Status.Runtime != nil && wsOld.Status.Runtime.NodeName != ws.Status.Runtime.NodeName) { // node name changed + if wsOld.Status.Runtime != nil && wsOld.Status.Runtime.NodeName != "" { + c.queueNodeForReconciliation(wsOld.Status.Runtime.NodeName) + } + return true + } + + return false + }, + DeleteFunc: func(e event.DeleteEvent) bool { + ws := e.Object.(*workspacev1.Workspace) + if ws.Status.Runtime != nil && ws.Status.Runtime.NodeName != "" { + c.queueNodeForReconciliation(ws.Status.Runtime.NodeName) + return true + } + return false + }, + } +} + +func (c *NodeScaledownAnnotationController) queueNodeForReconciliation(nodeName string) { + select { + case c.nodesToReconcile <- nodeName: + log.WithField("node", nodeName).Info("queued node for reconciliation") + default: + log.WithField("node", nodeName).Warn("reconciliation queue full") + } +} + +func (c *NodeScaledownAnnotationController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + log.WithField("request", req.NamespacedName.String()).Info("WorkspaceCountController reconciling") + + var ws workspacev1.Workspace + if err := c.Get(ctx, req.NamespacedName, &ws); err != nil { + if !errors.IsNotFound(err) { + log.WithError(err).WithField("workspace", req.NamespacedName).Error("unable to fetch Workspace") + return ctrl.Result{}, err + } + return ctrl.Result{}, nil + } + + if ws.Status.Runtime != nil && ws.Status.Runtime.NodeName != "" { + c.queueNodeForReconciliation(ws.Status.Runtime.NodeName) + } + + log.WithField("runtime", ws.Status.Runtime).Warn("reconciling object with no Runtime/NodeName, which wasn't filtered out by workspaceFilter") + return ctrl.Result{}, nil +} + +// Cleanup method to be called when shutting down the controller +func (wc *NodeScaledownAnnotationController) Stop() { + close(wc.stopChan) +} + +func (c *NodeScaledownAnnotationController) reconcileAllNodes(ctx context.Context) (ctrl.Result, error) { + var nodes corev1.NodeList + if err := c.List(ctx, &nodes); err != nil { + log.WithError(err).Error("failed to list nodes") + return ctrl.Result{}, err + } + + for _, node := range nodes.Items { + c.queueNodeForReconciliation(node.Name) + } + + return ctrl.Result{}, nil +} + +func (c *NodeScaledownAnnotationController) reconcileNode(ctx context.Context, nodeName string) error { + var workspaceList workspacev1.WorkspaceList + if err := c.List(ctx, &workspaceList, client.MatchingFields{ + "status.runtime.nodeName": nodeName, + }); err != nil { + return fmt.Errorf("failed to list workspaces: %w", err) + } + + log.WithField("node", nodeName).WithField("count", len(workspaceList.Items)).Info("acting on workspaces") + count := len(workspaceList.Items) + + return c.updateNodeAnnotation(ctx, nodeName, count) +} + +func (c *NodeScaledownAnnotationController) updateNodeAnnotation(ctx context.Context, nodeName string, count int) error { + return retry.RetryOnConflict(retry.DefaultBackoff, func() error { + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + var node corev1.Node + err := c.Get(ctx, types.NamespacedName{Name: nodeName}, &node) + if err != nil { + return fmt.Errorf("obtaining node %s: %w", nodeName, err) + } + + shouldDisableScaleDown := count > 0 + currentlyDisabled := false + if val, exists := node.Annotations["cluster-autoscaler.kubernetes.io/scale-down-disabled"]; exists { + currentlyDisabled = val == "true" + } + + // Only update if the state needs to change + if shouldDisableScaleDown != currentlyDisabled { + if node.Annotations == nil { + node.Annotations = make(map[string]string) + } + + if shouldDisableScaleDown { + node.Annotations["cluster-autoscaler.kubernetes.io/scale-down-disabled"] = "true" + log.WithField("nodeName", nodeName).Info("disabling scale-down for node") + } else { + delete(node.Annotations, "cluster-autoscaler.kubernetes.io/scale-down-disabled") + log.WithField("nodeName", nodeName).Info("enabling scale-down for node") + } + + return c.Update(ctx, &node) + } + + return nil + }) +} + func updateLabel(label string, add bool, nodeName string, client client.Client) error { return retry.RetryOnConflict(retry.DefaultBackoff, func() error { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) diff --git a/components/node-labeler/cmd/run_test.go b/components/node-labeler/cmd/run_test.go new file mode 100644 index 00000000000000..1e7cdcb08e6a11 --- /dev/null +++ b/components/node-labeler/cmd/run_test.go @@ -0,0 +1,266 @@ +// Copyright (c) 2025 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License.AGPL.txt in the project root for license information. + +package cmd + +import ( + "context" + "path/filepath" + "testing" + "time" + + "github.com/aws/smithy-go/ptr" + csapi "github.com/gitpod-io/gitpod/content-service/api" + workspacev1 "github.com/gitpod-io/gitpod/ws-manager/api/crd/v1" + "github.com/golang/mock/gomock" + "github.com/google/uuid" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "google.golang.org/protobuf/proto" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +const ( + timeout = time.Second * 10 + duration = time.Second * 2 + interval = time.Millisecond * 250 + workspaceNamespace = "default" + secretsNamespace = "workspace-secrets" +) + +var ( + k8sClient client.Client + testEnv *envtest.Environment + mock_ctrl *gomock.Controller + ctx context.Context + cancel context.CancelFunc + nodeScaledownCtrl *NodeScaledownAnnotationController + NodeName = "cool-ws-node" +) + +func TestAPIs(t *testing.T) { + mock_ctrl = gomock.NewController(t) + RegisterFailHandler(Fail) + RunSpecs(t, "Controller Suite") +} + +var _ = Describe("NodeScaledownAnnotationController", func() { + It("should remove scale-down-disabled when last workspace is removed", func() { + ws1 := newWorkspace(uuid.NewString(), workspaceNamespace, NodeName, workspacev1.WorkspacePhaseRunning) + ws2 := newWorkspace(uuid.NewString(), workspaceNamespace, NodeName, workspacev1.WorkspacePhaseRunning) + ws1.Status.Runtime = nil + ws2.Status.Runtime = nil + createWorkspace(ws1) + createWorkspace(ws2) + + By("Assigning nodes to workspaces") + updateObjWithRetries(k8sClient, ws1, true, func(ws *workspacev1.Workspace) { + ws.Status.Conditions = []metav1.Condition{} + ws.Status.Runtime = &workspacev1.WorkspaceRuntimeStatus{ + NodeName: NodeName, + } + }) + + updateObjWithRetries(k8sClient, ws2, true, func(ws *workspacev1.Workspace) { + ws.Status.Conditions = []metav1.Condition{} + ws.Status.Runtime = &workspacev1.WorkspaceRuntimeStatus{ + NodeName: NodeName, + } + }) + + By("Verifying node annotation") + Eventually(func(g Gomega) { + var node corev1.Node + g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: NodeName}, &node)).To(Succeed()) + g.Expect(node.Annotations).To(HaveKeyWithValue("cluster-autoscaler.kubernetes.io/scale-down-disabled", "true")) + }, timeout, interval).Should(Succeed()) + + By("Deleting workspaces") + Expect(k8sClient.Delete(ctx, ws1)).To(Succeed()) + Expect(k8sClient.Delete(ctx, ws2)).To(Succeed()) + + By("Verifying final state") + Eventually(func(g Gomega) { + var node corev1.Node + g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: NodeName}, &node)).To(Succeed()) + g.Expect(node.Annotations).ToNot(HaveKey("cluster-autoscaler.kubernetes.io/scale-down-disabled")) + }, timeout, interval).Should(Succeed()) + }) +}) + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + ControlPlaneStartTimeout: 1 * time.Minute, + ControlPlaneStopTimeout: 1 * time.Minute, + CRDDirectoryPaths: []string{filepath.Join("..", "crd")}, + ErrorIfCRDPathMissing: true, + } + + cfg, err := testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + err = workspacev1.AddToScheme(clientgoscheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: clientgoscheme.Scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + + k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: clientgoscheme.Scheme, + }) + Expect(err).ToNot(HaveOccurred()) + ctx, cancel = context.WithCancel(context.Background()) + + By("Creating default ws node") + node := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: NodeName, + }, + } + Expect(k8sClient.Create(ctx, node)).To(Succeed()) + + err = k8sManager.GetFieldIndexer().IndexField(context.Background(), + &workspacev1.Workspace{}, + "status.runtime.nodeName", + func(o client.Object) []string { + ws := o.(*workspacev1.Workspace) + if ws.Status.Runtime == nil { + return nil + } + return []string{ws.Status.Runtime.NodeName} + }) + Expect(err).ToNot(HaveOccurred()) + + By("Setting up controllers") + nodeScaledownCtrl, err = NewNodeScaledownAnnotationController(k8sManager.GetClient()) + Expect(err).NotTo(HaveOccurred()) + Expect(nodeScaledownCtrl.SetupWithManager(k8sManager)).To(Succeed()) + + _ = createNamespace(secretsNamespace) + + By("Starting the manager") + go func() { + defer GinkgoRecover() + err = k8sManager.Start(ctx) + Expect(err).ToNot(HaveOccurred(), "failed to run manager") + }() + + By("Waiting for controllers to be ready") + DeferCleanup(cancel) + + // Wait for controllers to be ready + Eventually(func() bool { + return k8sManager.GetCache().WaitForCacheSync(ctx) + }, time.Second*10, time.Millisecond*100).Should(BeTrue()) +}) + +var _ = AfterSuite(func() { + if cancel != nil { + cancel() + } + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) + +func newWorkspace(name, namespace, nodeName string, phase workspacev1.WorkspacePhase) *workspacev1.Workspace { + GinkgoHelper() + initializer := &csapi.WorkspaceInitializer{ + Spec: &csapi.WorkspaceInitializer_Empty{Empty: &csapi.EmptyInitializer{}}, + } + initializerBytes, err := proto.Marshal(initializer) + Expect(err).ToNot(HaveOccurred()) + + return &workspacev1.Workspace{ + Status: workspacev1.WorkspaceStatus{ + Phase: phase, + Runtime: &workspacev1.WorkspaceRuntimeStatus{ + NodeName: nodeName, + }, + Conditions: []metav1.Condition{}, + }, + TypeMeta: metav1.TypeMeta{ + APIVersion: "workspace.gitpod.io/v1", + Kind: "Workspace", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: workspacev1.WorkspaceSpec{ + Ownership: workspacev1.Ownership{ + Owner: "foobar", + WorkspaceID: "cool-workspace", + }, + Type: workspacev1.WorkspaceTypeRegular, + Class: "default", + Image: workspacev1.WorkspaceImages{ + Workspace: workspacev1.WorkspaceImage{ + Ref: ptr.String("alpine:latest"), + }, + IDE: workspacev1.IDEImages{ + Refs: []string{}, + }, + }, + Ports: []workspacev1.PortSpec{}, + Initializer: initializerBytes, + Admission: workspacev1.AdmissionSpec{ + Level: workspacev1.AdmissionLevelEveryone, + }, + }, + } +} + +func createWorkspace(ws *workspacev1.Workspace) { + GinkgoHelper() + By("creating workspace") + Expect(k8sClient.Create(ctx, ws)).To(Succeed()) +} + +func updateObjWithRetries[O client.Object](c client.Client, obj O, updateStatus bool, update func(obj O)) { + GinkgoHelper() + Eventually(func() error { + var err error + if err = c.Get(ctx, types.NamespacedName{Name: obj.GetName(), Namespace: obj.GetNamespace()}, obj); err != nil { + return err + } + // Apply update. + update(obj) + if updateStatus { + err = c.Status().Update(ctx, obj) + } else { + err = c.Update(ctx, obj) + } + return err + }, timeout, interval).Should(Succeed()) +} + +func createNamespace(name string) *corev1.Namespace { + GinkgoHelper() + + namespace := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } + + Expect(k8sClient.Create(ctx, namespace)).To(Succeed()) + return namespace +} diff --git a/components/node-labeler/crd/workspace.gitpod.io_workspaces.yaml b/components/node-labeler/crd/workspace.gitpod.io_workspaces.yaml new file mode 100644 index 00000000000000..bfcf2dac12b2e8 --- /dev/null +++ b/components/node-labeler/crd/workspace.gitpod.io_workspaces.yaml @@ -0,0 +1,5 @@ +# Copyright (c) 2025 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License.AGPL.txt in the project root for license information. + +THIS FILE IS REPLACED DURING LEEWAY BUILD diff --git a/components/node-labeler/go.mod b/components/node-labeler/go.mod index ae0fb577a58d13..d0c050433864c9 100644 --- a/components/node-labeler/go.mod +++ b/components/node-labeler/go.mod @@ -3,10 +3,18 @@ module github.com/gitpod-io/gitpod/node-labeler go 1.22 require ( + github.com/aws/smithy-go v1.22.1 github.com/bombsimon/logrusr/v2 v2.0.1 github.com/gitpod-io/gitpod/common-go v0.0.0-00010101000000-000000000000 + github.com/gitpod-io/gitpod/content-service/api v0.0.0-00010101000000-000000000000 + github.com/gitpod-io/gitpod/ws-manager/api v0.0.0-00010101000000-000000000000 + github.com/golang/mock v1.6.0 + github.com/google/uuid v1.3.0 + github.com/onsi/ginkgo/v2 v2.14.0 + github.com/onsi/gomega v1.30.0 github.com/prometheus/client_golang v1.19.0 github.com/spf13/cobra v1.7.0 + google.golang.org/protobuf v1.33.0 k8s.io/api v0.29.3 k8s.io/apimachinery v0.29.3 k8s.io/client-go v0.29.3 @@ -23,19 +31,21 @@ require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gitpod-io/gitpod/components/scrubber v0.0.0-00010101000000-000000000000 // indirect github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect - github.com/imdario/mergo v0.3.6 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -44,12 +54,16 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.5 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/net v0.20.0 // indirect golang.org/x/oauth2 v0.16.0 // indirect @@ -57,11 +71,12 @@ require ( golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.16.1 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/grpc v1.58.3 // indirect - google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -74,10 +89,16 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect ) +replace github.com/gitpod-io/gitpod/ws-manager/api => ../ws-manager-api/go // leeway + replace github.com/gitpod-io/gitpod/common-go => ../common-go // leeway replace github.com/gitpod-io/gitpod/components/scrubber => ../scrubber // leeway +replace github.com/gitpod-io/gitpod/content-service => ../content-service // leeway + +replace github.com/gitpod-io/gitpod/content-service/api => ../content-service-api/go // leeway + replace k8s.io/api => k8s.io/api v0.29.3 // leeway indirect from components/common-go:lib replace k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.29.3 // leeway indirect from components/common-go:lib diff --git a/components/node-labeler/go.sum b/components/node-labeler/go.sum index d5721da6995ac1..215259476cc033 100644 --- a/components/node-labeler/go.sum +++ b/components/node-labeler/go.sum @@ -1,5 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= +github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM= @@ -7,6 +9,9 @@ github.com/bombsimon/logrusr/v2 v2.0.1/go.mod h1:ByVAX+vHdLGAfdroiMg6q0zgq2FODY2 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -49,6 +54,8 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -72,8 +79,9 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaW github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -107,6 +115,10 @@ github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -122,8 +134,8 @@ github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSz github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -140,6 +152,7 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -148,6 +161,7 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -168,6 +182,7 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -177,6 +192,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -187,16 +203,22 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -214,12 +236,15 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -247,6 +272,7 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/install/installer/pkg/components/node-labeler/role.go b/install/installer/pkg/components/node-labeler/role.go index 8950c1c1e847f8..7f90099962fddd 100644 --- a/install/installer/pkg/components/node-labeler/role.go +++ b/install/installer/pkg/components/node-labeler/role.go @@ -31,7 +31,10 @@ func role(ctx *common.RenderContext) ([]runtime.Object, error) { }, Verbs: []string{ "get", + "list", + "watch", "update", + "patch", }, }, { @@ -45,6 +48,16 @@ func role(ctx *common.RenderContext) ([]runtime.Object, error) { "watch", }, }, + // permissions required for the WorkspaceCountController + { + APIGroups: []string{"workspace.gitpod.io"}, + Resources: []string{"workspaces"}, + Verbs: []string{ + "get", + "list", + "watch", + }, + }, // ConfigMap, Leases, and Events access is required for leader-election. { APIGroups: []string{""},