From b23e2da3fc95960bec86617bd70df23892dd5b27 Mon Sep 17 00:00:00 2001 From: mgianluc Date: Fri, 12 Apr 2024 10:27:17 +0200 Subject: [PATCH] Renew TokenRequest --- .github/workflows/main.yaml | 17 +- Dockerfile | 2 +- Makefile | 93 ++++- config/default/manager_image_patch.yaml | 2 +- config/rbac/role.yaml | 1 + controllers/controllers_suite_test.go | 4 + controllers/export_test.go | 21 ++ controllers/sveltoscluster_controller.go | 164 ++++++++- controllers/sveltoscluster_controller_test.go | 59 +++ go.mod | 43 +-- go.sum | 98 ++--- hack/tools/go.mod | 15 +- hack/tools/go.sum | 25 +- manifest/deployment-shard.yaml | 2 +- manifest/manifest.yaml | 3 +- test/clusterapi-workload.yaml | 312 ++++++++++++++++ test/fv/fv_suite_test.go | 335 ++++++++++++++++++ test/fv/renew_toke_request_test.go | 108 ++++++ test/kind-cluster.yaml | 33 ++ test/kind-workload-cluster.yaml | 0 20 files changed, 1235 insertions(+), 102 deletions(-) create mode 100644 controllers/export_test.go create mode 100644 test/clusterapi-workload.yaml create mode 100644 test/fv/fv_suite_test.go create mode 100644 test/fv/renew_toke_request_test.go create mode 100644 test/kind-cluster.yaml create mode 100644 test/kind-workload-cluster.yaml diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index c24085e..a286f52 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -18,7 +18,7 @@ jobs: - name: Set up Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # tag=v5.0.0 with: - go-version: 1.21.5 + go-version: 1.22.0 - name: Build run: make build - name: FMT @@ -37,8 +37,21 @@ jobs: - name: Set up Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # tag=v5.0.0 with: - go-version: 1.21.5 + go-version: 1.22.0 - name: ut run: make test env: UT: true + FV: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Set up Go + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # tag=v5.0.0 + with: + go-version: 1.22.0 + - name: fv + run: make create-cluster fv + env: + FV: true diff --git a/Dockerfile b/Dockerfile index 155b850..6439439 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILDOS ARG TARGETARCH diff --git a/Makefile b/Makefile index 55fc4d1..30d7fdd 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ ARCH ?= amd64 OS ?= $(shell uname -s | tr A-Z a-z) K8S_LATEST_VER ?= $(shell curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) export CONTROLLER_IMG ?= $(REGISTRY)/$(IMAGE_NAME) -TAG ?= main +TAG ?= dev .PHONY: all all: build @@ -64,10 +64,12 @@ GOIMPORTS := $(TOOLS_BIN_DIR)/goimports GOLANGCI_LINT := $(TOOLS_BIN_DIR)/golangci-lint GINKGO := $(TOOLS_BIN_DIR)/ginkgo SETUP_ENVTEST := $(TOOLS_BIN_DIR)/setup_envs +CLUSTERCTL := $(TOOLS_BIN_DIR)/clusterctl KIND := $(TOOLS_BIN_DIR)/kind KUBECTL := $(TOOLS_BIN_DIR)/kubectl GOLANGCI_LINT_VERSION := "v1.55.2" +CLUSTERCTL_VERSION := "v1.7.0" KUSTOMIZE_VER := v4.5.2 KUSTOMIZE_BIN := kustomize @@ -106,6 +108,10 @@ $(GINKGO): $(TOOLS_DIR)/go.mod $(KIND): $(TOOLS_DIR)/go.mod cd $(TOOLS_DIR) && $(GOBUILD) -tags tools -o $(subst $(TOOLS_DIR)/hack/tools/,,$@) sigs.k8s.io/kind +$(CLUSTERCTL): $(TOOLS_DIR)/go.mod ## Build clusterctl binary + curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/$(CLUSTERCTL_VERSION)/clusterctl-$(OS)-$(ARCH) -o $@ + chmod +x $@ + $(KUBECTL): curl -L https://storage.googleapis.com/kubernetes-release/release/$(K8S_LATEST_VER)/bin/$(OS)/$(ARCH)/kubectl -o $@ chmod +x $@ @@ -191,7 +197,7 @@ run: manifests generate fmt vet ## Run a controller from your host. .PHONY: docker-build docker-build: ## Build docker image with the manager. go generate - docker build --build-arg BUILDOS=linux --build-arg TARGETARCH=amd64 -t $(CONTROLLER_IMG):$(TAG) . + docker build --load --build-arg BUILDOS=linux --build-arg TARGETARCH=amd64 -t $(CONTROLLER_IMG):$(TAG) . MANIFEST_IMG=$(CONTROLLER_IMG) MANIFEST_TAG=$(TAG) $(MAKE) set-manifest-image $(MAKE) set-manifest-pull-policy @@ -230,3 +236,86 @@ deploy: manifests $(KUSTOMIZE) $(KUBECTL) ## Deploy controller to the K8s cluste .PHONY: undeploy undeploy: s $(KUSTOMIZE) ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. $(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f - + + +## fv +KIND_CONFIG ?= kind-cluster.yaml +CONTROL_CLUSTER_NAME ?= sveltos-management +WORKLOAD_CLUSTER_NAME ?= clusterapi-workload +TIMEOUT ?= 10m +KIND_CLUSTER_YAML ?= test/$(WORKLOAD_CLUSTER_NAME).yaml +NUM_NODES ?= 1 + +.PHONY: kind-test +kind-test: test create-cluster fv ## Build docker image; start kind cluster; load docker image; install all cluster api components and run fv + +.PHONY: fv +fv: $(KUBECTL) $(GINKGO) ## Run Sveltos Controller tests using existing cluster + cd test/fv; $(GINKGO) -nodes $(NUM_NODES) --label-filter='FV' --v --trace --randomize-all + + +.PHONY: create-cluster +create-cluster: $(KIND) $(CLUSTERCTL) $(KUBECTL) $(ENVSUBST) ## Create a new kind cluster designed for development + $(MAKE) create-control-cluster + + @echo "Start projectsveltos" + $(MAKE) deploy-projectsveltos + + $(MAKE) create-workload-cluster + +.PHONY: delete-cluster +delete-cluster: $(KIND) ## Deletes the kind clusters + $(KIND) delete cluster --name $(CONTROL_CLUSTER_NAME) + $(KIND) delete cluster --name $(WORKLOAD_CLUSTER_NAME) + + +create-control-cluster: $(KIND) $(CLUSTERCTL) $(KUBECTL) + sed -e "s/K8S_VERSION/$(K8S_VERSION)/g" test/$(KIND_CONFIG) > test/$(KIND_CONFIG).tmp + $(KIND) create cluster --name=$(CONTROL_CLUSTER_NAME) --config test/$(KIND_CONFIG).tmp + @echo "Create control cluster with docker as infrastructure provider" + CLUSTER_TOPOLOGY=true $(CLUSTERCTL) init --core cluster-api --bootstrap kubeadm --control-plane kubeadm --infrastructure docker + + @echo wait for capd-system pod + $(KUBECTL) wait --for=condition=Available deployment/capd-controller-manager -n capd-system --timeout=$(TIMEOUT) + $(KUBECTL) wait --for=condition=Available deployment/capi-kubeadm-control-plane-controller-manager -n capi-kubeadm-control-plane-system --timeout=$(TIMEOUT) + $(KUBECTL) wait --for=condition=Available deployment/capi-kubeadm-bootstrap-controller-manager -n capi-kubeadm-bootstrap-system --timeout=$(TIMEOUT) + + @echo "sleep allowing webhook to be ready" + sleep 10 + +create-workload-cluster: $(KIND) $(KUBECTL) + @echo "Create a workload cluster" + $(KUBECTL) apply -f $(KIND_CLUSTER_YAML) + + @echo "wait for cluster to be provisioned" + $(KUBECTL) wait cluster $(WORKLOAD_CLUSTER_NAME) -n default --for=jsonpath='{.status.phase}'=Provisioned --timeout=$(TIMEOUT) + + @echo "sleep allowing control plane to be ready" + sleep 100 + + @echo "get kubeconfig to access workload cluster" + $(KIND) get kubeconfig --name $(WORKLOAD_CLUSTER_NAME) > test/fv/workload_kubeconfig + + @echo "install calico on workload cluster" + $(KUBECTL) --kubeconfig=./test/fv/workload_kubeconfig apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/calico.yaml + + @echo wait for calico pod + $(KUBECTL) --kubeconfig=./test/fv/workload_kubeconfig wait --for=condition=Available deployment/calico-kube-controllers -n kube-system --timeout=$(TIMEOUT) + + +deploy-projectsveltos: $(KUSTOMIZE) + # Load projectsveltos image into cluster + @echo 'Load projectsveltos image into cluster' + $(MAKE) load-image + + @echo 'Install libsveltos CRDs' + $(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/config/crd/bases/lib.projectsveltos.io_debuggingconfigurations.yaml + $(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/config/crd/bases/lib.projectsveltos.io_sveltosclusters.yaml + + # Install projectsveltos sveltoscluster-manager components + @echo 'Install projectsveltos sveltoscluster-manager components' + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/default | $(ENVSUBST) | $(KUBECTL) apply -f- + + @echo "Waiting for projectsveltos sveltoscluster-manager to be available..." + $(KUBECTL) wait --for=condition=Available deployment/sc-manager -n projectsveltos --timeout=$(TIMEOUT) \ No newline at end of file diff --git a/config/default/manager_image_patch.yaml b/config/default/manager_image_patch.yaml index bba12dc..46ae11e 100644 --- a/config/default/manager_image_patch.yaml +++ b/config/default/manager_image_patch.yaml @@ -8,5 +8,5 @@ spec: spec: containers: # Change the value of image field below to your controller image URL - - image: projectsveltos/sveltoscluster-manager:main + - image: projectsveltos/sveltoscluster-manager:dev name: manager diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 2c7e480..7d68f82 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -11,6 +11,7 @@ rules: verbs: - get - list + - update - watch - apiGroups: - authentication.k8s.io diff --git a/controllers/controllers_suite_test.go b/controllers/controllers_suite_test.go index f75f2f4..c2f6483 100644 --- a/controllers/controllers_suite_test.go +++ b/controllers/controllers_suite_test.go @@ -31,7 +31,9 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/klog/v2" "sigs.k8s.io/cluster-api/util" + ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" libsveltosv1alpha1 "github.com/projectsveltos/libsveltos/api/v1alpha1" @@ -70,6 +72,8 @@ func TestControllers(t *testing.T) { var _ = BeforeSuite(func() { By("bootstrapping test environment") + ctrl.SetLogger(klog.Background()) + ctx, cancel = context.WithCancel(context.TODO()) var err error diff --git a/controllers/export_test.go b/controllers/export_test.go new file mode 100644 index 0000000..f7c5189 --- /dev/null +++ b/controllers/export_test.go @@ -0,0 +1,21 @@ +/* +Copyright 2024. projectsveltos.io. All rights reserved. + +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 controllers + +var ( + ShouldRenewTokenRequest = (*SveltosClusterReconciler).shouldRenewTokenRequest +) diff --git a/controllers/sveltoscluster_controller.go b/controllers/sveltoscluster_controller.go index 64958dd..f0cd37d 100644 --- a/controllers/sveltoscluster_controller.go +++ b/controllers/sveltoscluster_controller.go @@ -18,17 +18,23 @@ package controllers import ( "context" + "encoding/base64" "fmt" "time" "github.com/go-logr/logr" "github.com/pkg/errors" + authenticationv1 "k8s.io/api/authentication/v1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" clientgoscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" + apiv1 "k8s.io/client-go/tools/clientcmd/api/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -60,7 +66,7 @@ type SveltosClusterReconciler struct { //+kubebuilder:rbac:groups=lib.projectsveltos.io,resources=sveltosclusters,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=lib.projectsveltos.io,resources=sveltosclusters/status,verbs=get;update;patch //+kubebuilder:rbac:groups=lib.projectsveltos.io,resources=sveltosclusters/finalizers,verbs=update -//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch +//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;update //+kubebuilder:rbac:groups=lib.projectsveltos.io,resources=debuggingconfigurations,verbs=get;list;watch func (r *SveltosClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctrl.Result, reterr error) { @@ -183,6 +189,13 @@ func (r *SveltosClusterReconciler) reconcileNormal( } else { sveltosClusterScope.SveltosCluster.Status.Version = currentVersion logger.V(logs.LogDebug).Info(fmt.Sprintf("cluster version %s", currentVersion)) + if r.shouldRenewTokenRequest(sveltosClusterScope, logger) { + err = r.handleTokenRequestRenewal(ctx, sveltosClusterScope, config) + if err != nil { + errorMessage := err.Error() + sveltosClusterScope.SveltosCluster.Status.FailureMessage = &errorMessage + } + } } } } @@ -221,3 +234,152 @@ func (r *SveltosClusterReconciler) isClusterAShardMatch(ctx context.Context, return true, nil } + +func (r *SveltosClusterReconciler) shouldRenewTokenRequest(sveltosClusterScope *scope.SveltosClusterScope, + logger logr.Logger) bool { + + sveltosCluster := sveltosClusterScope.SveltosCluster + if sveltosCluster.Spec.TokenRequestRenewalOption == nil { + return false + } + + currentTime := time.Now() + lastRenewal := sveltosCluster.CreationTimestamp + if sveltosCluster.Status.LastReconciledTokenRequestAt != "" { + parsedTime, err := time.Parse(time.RFC3339, sveltosCluster.Status.LastReconciledTokenRequestAt) + if err != nil { + logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to parse LastReconciledTokenRequestAt: %v. Using CreationTimestamep", err)) + } else { + lastRenewal = metav1.Time{Time: parsedTime} + } + } + + // Calculate how much time has passed since lastRenewal + elapsed := currentTime.Sub(lastRenewal.Time) + return elapsed.Seconds() > sveltosCluster.Spec.TokenRequestRenewalOption.RenewTokenRequestInterval.Seconds() +} + +func (r *SveltosClusterReconciler) handleTokenRequestRenewal(ctx context.Context, + sveltosClusterScope *scope.SveltosClusterScope, remoteConfig *rest.Config) error { + + sveltosCluster := sveltosClusterScope.SveltosCluster + + if sveltosCluster.Spec.TokenRequestRenewalOption != nil { + logger := sveltosClusterScope.Logger + + saExpirationInSecond := sveltosCluster.Spec.TokenRequestRenewalOption.RenewTokenRequestInterval.Duration.Seconds() + // Minimum duration for a TokenRequest is 10 minutes. SveltosCluster reconciler always set the expiration to be + // sveltosCluster.Spec.TokenRequestRenewalOption.RenewTokenRequestInterval plus 30 minutes. That will also allow + // reconciler to renew it again before it current tokenRequest expires + const secondsToAddToTokenRequest = 30 * 60 // 30 minutes + saExpirationInSecond += float64(secondsToAddToTokenRequest) + + data, err := clusterproxy.GetSveltosSecretData(ctx, logger, r.Client, + sveltosCluster.Namespace, sveltosCluster.Name) + if err != nil { + logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to get Secret with Kubeconfig: %v", err)) + return err + } + + var u *unstructured.Unstructured + u, err = utils.GetUnstructured(data) + if err != nil { + logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to get unstructured %v", err)) + return err + } + + config := &apiv1.Config{} + err = runtime.DefaultUnstructuredConverter. + FromUnstructured(u.UnstructuredContent(), config) + if err != nil { + logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to get convert unstructured to v1.Config %v", err)) + return err + } + + for i := range config.Contexts { + cc := &config.Contexts[i] + namespace := cc.Context.Namespace + user := cc.Context.AuthInfo + + tokenRequest, err := r.getServiceAccountTokenRequest(ctx, remoteConfig, namespace, user, saExpirationInSecond, logger) + if err != nil { + logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to get tokenRequest %v", err)) + continue + } + + logger.V(logs.LogDebug).Info("Get Kubeconfig from TokenRequest") + data := r.getKubeconfigFromToken(namespace, user, tokenRequest.Token, remoteConfig) + err = clusterproxy.UpdateSveltosSecretData(ctx, logger, r.Client, sveltosCluster.Namespace, sveltosCluster.Name, data) + if err != nil { + logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to update SveltosCluster's Secret %v", err)) + continue + } + + sveltosCluster.Status.LastReconciledTokenRequestAt = time.Now().Format(time.RFC3339) + } + } + + return nil +} + +// getServiceAccountTokenRequest returns token for a serviceaccount +func (r *SveltosClusterReconciler) getServiceAccountTokenRequest(ctx context.Context, remoteConfig *rest.Config, + serviceAccountNamespace, serviceAccountName string, saExpirationInSecond float64, logger logr.Logger, +) (*authenticationv1.TokenRequestStatus, error) { + + expiration := int64(saExpirationInSecond) + + treq := &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + ExpirationSeconds: &expiration, + }, + } + + clientset, err := kubernetes.NewForConfig(remoteConfig) + if err != nil { + return nil, err + } + + logger.V(logs.LogDebug).Info( + fmt.Sprintf("Create Token for ServiceAccount %s/%s", serviceAccountNamespace, serviceAccountName)) + var tokenRequest *authenticationv1.TokenRequest + tokenRequest, err = clientset.CoreV1().ServiceAccounts(serviceAccountNamespace). + CreateToken(ctx, serviceAccountName, treq, metav1.CreateOptions{}) + if err != nil { + logger.V(logs.LogDebug).Info( + fmt.Sprintf("Failed to create token for ServiceAccount %s/%s: %v", + serviceAccountNamespace, serviceAccountName, err)) + return nil, err + } + + return &tokenRequest.Status, nil +} + +// getKubeconfigFromToken returns Kubeconfig to access management cluster from token. +func (r *SveltosClusterReconciler) getKubeconfigFromToken(namespace, serviceAccountName, token string, + remoteConfig *rest.Config) string { + + template := `apiVersion: v1 +kind: Config +clusters: +- name: local + cluster: + server: %s + certificate-authority-data: "%s" +users: +- name: %s + user: + token: %s +contexts: +- name: sveltos-context + context: + cluster: local + namespace: %s + user: %s +current-context: sveltos-context` + + data := fmt.Sprintf(template, remoteConfig.Host, + base64.StdEncoding.EncodeToString(remoteConfig.CAData), serviceAccountName, token, namespace, serviceAccountName) + + return data +} diff --git a/controllers/sveltoscluster_controller_test.go b/controllers/sveltoscluster_controller_test.go index ca4ee4b..12d42d8 100644 --- a/controllers/sveltoscluster_controller_test.go +++ b/controllers/sveltoscluster_controller_test.go @@ -18,22 +18,30 @@ package controllers_test import ( "context" + "time" + "github.com/go-logr/logr" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2/textlogger" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" libsveltosv1alpha1 "github.com/projectsveltos/libsveltos/api/v1alpha1" + "github.com/projectsveltos/sveltoscluster-manager/controllers" + "github.com/projectsveltos/sveltoscluster-manager/pkg/scope" ) var _ = Describe("SveltosCluster: Reconciler", func() { var sveltosCluster *libsveltosv1alpha1.SveltosCluster + var logger logr.Logger BeforeEach(func() { sveltosCluster = getSveltosClusterInstance(randomString(), randomString()) + logger = textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(1))) }) It("reconcile set status to ready", func() { @@ -82,6 +90,57 @@ var _ = Describe("SveltosCluster: Reconciler", func() { currentSveltosCluster.Status.Ready }, timeout, pollingInterval).Should(BeTrue()) }) + + It("shouldRenewTokenRequest returns true when enough time has passed since last TokenRequest renewal", func() { + sveltosCluster.Spec.TokenRequestRenewalOption = &libsveltosv1alpha1.TokenRequestRenewalOption{ + RenewTokenRequestInterval: metav1.Duration{Duration: time.Minute}, + } + + initObjects := []client.Object{ + sveltosCluster, + } + + c := fake.NewClientBuilder().WithScheme(scheme).WithStatusSubresource(initObjects...).WithObjects(initObjects...).Build() + + reconciler := getClusterProfileReconciler(c) + + sveltosClusterName := client.ObjectKey{ + Name: sveltosCluster.Name, + Namespace: sveltosCluster.Namespace, + } + + now := time.Now() + now = now.Add(-time.Hour) + + currentSveltosCluster := &libsveltosv1alpha1.SveltosCluster{} + Expect(c.Get(context.TODO(), sveltosClusterName, currentSveltosCluster)).To(Succeed()) + currentSveltosCluster.Status.LastReconciledTokenRequestAt = now.Format(time.RFC3339) + Expect(c.Status().Update(context.TODO(), currentSveltosCluster)).To(Succeed()) + + sveltosClusterScope, err := scope.NewSveltosClusterScope(scope.SveltosClusterScopeParams{ + Client: testEnv.Client, + SveltosCluster: currentSveltosCluster, + ControllerName: randomString(), + Logger: logger, + }) + Expect(err).To(BeNil()) + + // last renewal time was set by test to an hour ago. Because RenewTokenRequestInterval is set to a minute + // expect a renewal is needed + Expect(controllers.ShouldRenewTokenRequest(reconciler, sveltosClusterScope, logger)).To(BeTrue()) + + now = time.Now() + Expect(c.Get(context.TODO(), sveltosClusterName, currentSveltosCluster)).To(Succeed()) + currentSveltosCluster.Status.LastReconciledTokenRequestAt = now.Format(time.RFC3339) + Expect(c.Status().Update(context.TODO(), currentSveltosCluster)).To(Succeed()) + + sveltosClusterScope.SveltosCluster = currentSveltosCluster + + // last renewal time was set by test to just now. Because RenewTokenRequestInterval is set to a minute + // expect a renewal is not needed + Expect(controllers.ShouldRenewTokenRequest(reconciler, sveltosClusterScope, logger)).To(BeFalse()) + }) + }) func getSveltosClusterInstance(namespace, name string) *libsveltosv1alpha1.SveltosCluster { diff --git a/go.mod b/go.mod index 01d104a..d939ed8 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,23 @@ module github.com/projectsveltos/sveltoscluster-manager -go 1.21 +go 1.22.0 require ( + github.com/TwiN/go-color v1.4.1 github.com/go-logr/logr v1.4.1 github.com/onsi/ginkgo/v2 v2.17.1 github.com/onsi/gomega v1.32.0 github.com/pkg/errors v0.9.1 - github.com/projectsveltos/libsveltos v0.27.1-0.20240405132615-9e1a36ca5c8f + github.com/projectsveltos/libsveltos v0.27.1-0.20240414121914-1eb0b89fc6c9 github.com/spf13/pflag v1.0.5 - k8s.io/api v0.29.3 - k8s.io/apiextensions-apiserver v0.29.3 - k8s.io/apimachinery v0.29.3 - k8s.io/client-go v0.29.3 - k8s.io/component-base v0.29.3 + k8s.io/api v0.29.4 + k8s.io/apiextensions-apiserver v0.29.4 + k8s.io/apimachinery v0.29.4 + k8s.io/client-go v0.29.4 + k8s.io/component-base v0.29.4 k8s.io/klog/v2 v2.120.1 - sigs.k8s.io/cluster-api v1.6.3 - sigs.k8s.io/controller-runtime v0.17.2 + sigs.k8s.io/cluster-api v1.7.0 + sigs.k8s.io/controller-runtime v0.17.3 ) require ( @@ -27,8 +28,8 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.8.0 // indirect + github.com/evanphx/json-patch v5.7.0+incompatible // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -45,7 +46,7 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -71,27 +72,27 @@ require ( go.opentelemetry.io/otel/trace v1.20.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/oauth2 v0.14.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/oauth2 v0.18.0 // indirect golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.3.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.17.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect google.golang.org/grpc v1.59.0 // 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 - k8s.io/apiserver v0.29.3 // indirect + k8s.io/apiserver v0.29.4 // indirect k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect k8s.io/kubectl v0.29.3 // indirect - k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect + k8s.io/utils v0.0.0-20240310230437-4693a0247e57 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect diff --git a/go.sum b/go.sum index 341162e..fe49247 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7Y github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/TwiN/go-color v1.4.1 h1:mqG0P/KBgHKVqmtL5ye7K0/Gr4l6hTksPgTgMk3mUzc= +github.com/TwiN/go-color v1.4.1/go.mod h1:WcPf/jtiW95WBIsEeY1Lc/b8aaWoiqQpu5cf8WFxu+s= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= @@ -35,10 +37,10 @@ github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro= -github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= +github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -81,8 +83,8 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= @@ -130,8 +132,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/projectsveltos/libsveltos v0.27.1-0.20240405132615-9e1a36ca5c8f h1:FCmjCYxO/5irmocHXcuVfg9fT74NoN1G4k64/SwWdMo= -github.com/projectsveltos/libsveltos v0.27.1-0.20240405132615-9e1a36ca5c8f/go.mod h1:Uq3KYj5LKQYttA3yVb0O/V5Uvi2Qy7B23tnB5fBAMFg= +github.com/projectsveltos/libsveltos v0.27.1-0.20240414121914-1eb0b89fc6c9 h1:RYqAVU6cXVWniqDJGuWRFOzA5xgH3zasf2O11W7hYNw= +github.com/projectsveltos/libsveltos v0.27.1-0.20240414121914-1eb0b89fc6c9/go.mod h1:DVMv0DUlZ2x21jq7Z+LJvs7HesSe/pWsHZgQLV3Mhjw= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= @@ -145,8 +147,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -191,8 +193,8 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -202,10 +204,10 @@ 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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= -golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= 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= @@ -215,17 +217,17 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/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.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -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/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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= @@ -240,12 +242,12 @@ 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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= -google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= -google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= @@ -263,34 +265,34 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= -k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= -k8s.io/apiextensions-apiserver v0.29.3 h1:9HF+EtZaVpFjStakF4yVufnXGPRppWFEQ87qnO91YeI= -k8s.io/apiextensions-apiserver v0.29.3/go.mod h1:po0XiY5scnpJfFizNGo6puNU6Fq6D70UJY2Cb2KwAVc= -k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= -k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= -k8s.io/apiserver v0.29.3 h1:xR7ELlJ/BZSr2n4CnD3lfA4gzFivh0wwfNfz9L0WZcE= -k8s.io/apiserver v0.29.3/go.mod h1:hrvXlwfRulbMbBgmWRQlFru2b/JySDpmzvQwwk4GUOs= -k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= -k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= -k8s.io/cluster-bootstrap v0.28.4 h1:4MKNy1Qd9QY7pl47rSMGIORF+tm3CUaqC1M8U9bjn4Q= -k8s.io/cluster-bootstrap v0.28.4/go.mod h1:/c4ro/R4yf4EtJgFgFtvnHkbDOHwubeKJXh5R1c89Bc= -k8s.io/component-base v0.29.3 h1:Oq9/nddUxlnrCuuR2K/jp6aflVvc0uDvxMzAWxnGzAo= -k8s.io/component-base v0.29.3/go.mod h1:Yuj33XXjuOk2BAaHsIGHhCKZQAgYKhqIxIjIr2UXYio= +k8s.io/api v0.29.4 h1:WEnF/XdxuCxdG3ayHNRR8yH3cI1B/llkWBma6bq4R3w= +k8s.io/api v0.29.4/go.mod h1:DetSv0t4FBTcEpfA84NJV3g9a7+rSzlUHk5ADAYHUv0= +k8s.io/apiextensions-apiserver v0.29.4 h1:M7hbuHU/ckbibR7yPbe6DyNWgTFKNmZDbdZKD8q1Smk= +k8s.io/apiextensions-apiserver v0.29.4/go.mod h1:TTDC9fB+0kHY2rogf5hgBR03KBKCwED+GHUsXGpR7SM= +k8s.io/apimachinery v0.29.4 h1:RaFdJiDmuKs/8cm1M6Dh1Kvyh59YQFDcFuFTSmXes6Q= +k8s.io/apimachinery v0.29.4/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y= +k8s.io/apiserver v0.29.4 h1:wPwGOO58GQOpRiZu59P5eRoDcB7QtV+QBglkRiXwCiM= +k8s.io/apiserver v0.29.4/go.mod h1:VqTF9t98HVfhKZVRohCPezsdUt9u2g3bHKftxGcXoRo= +k8s.io/client-go v0.29.4 h1:79ytIedxVfyXV8rpH3jCBW0u+un0fxHDwX5F9K8dPR8= +k8s.io/client-go v0.29.4/go.mod h1:kC1thZQ4zQWYwldsfI088BbK6RkxK+aF5ebV8y9Q4tk= +k8s.io/cluster-bootstrap v0.29.3 h1:DIMDZSN8gbFMy9CS2mAS2Iqq/fIUG783WN/1lqi5TF8= +k8s.io/cluster-bootstrap v0.29.3/go.mod h1:aPAg1VtXx3uRrx5qU2jTzR7p1rf18zLXWS+pGhiqPto= +k8s.io/component-base v0.29.4 h1:xeKzuuHI/1tjleu5jycDAcYbhAxeGHCQBZUY2eRIkOo= +k8s.io/component-base v0.29.4/go.mod h1:pYjt+oEZP9gtmwSikwAJgfSBikqKX2gOqRat0QjmQt0= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/kubectl v0.29.3 h1:RuwyyIU42MAISRIePaa8Q7A3U74Q9P4MoJbDFz9o3us= k8s.io/kubectl v0.29.3/go.mod h1:yCxfY1dbwgVdEt2zkJ6d5NNLOhhWgTyrqACIoFhpdd4= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= -k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY= +k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 h1:TgtAeesdhpm2SGwkQasmbeqDo8th5wOBA5h/AjTKA4I= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0/go.mod h1:VHVDI/KrK4fjnV61bE2g3sA7tiETLn8sooImelsCx3Y= -sigs.k8s.io/cluster-api v1.6.3 h1:VOlPNg92PQLlhBVLc5pg+cbAuPvGOOBujeFLk9zgnoo= -sigs.k8s.io/cluster-api v1.6.3/go.mod h1:4FzfgPPiYaFq8X9F9j2SvmggH/4OOLEDgVJuWDqKLig= -sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0= -sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s= +sigs.k8s.io/cluster-api v1.7.0 h1:sWK6xs2MkCqPZhumsrti0OdKyGcu/c5aBz9XAWFIq5E= +sigs.k8s.io/cluster-api v1.7.0/go.mod h1:V9ZhKLvQtsDODwjXOKgbitjyCmC71yMBwDcMyNNIov0= +sigs.k8s.io/controller-runtime v0.17.3 h1:65QmN7r3FWgTxDMz9fvGnO1kbf2nu+acg9p2R9oYYYk= +sigs.k8s.io/controller-runtime v0.17.3/go.mod h1:N0jpP5Lo7lMTF9aL56Z/B2oWBJjey6StQM0jRbKQXtY= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/hack/tools/go.mod b/hack/tools/go.mod index 140facd..caf2875 100644 --- a/hack/tools/go.mod +++ b/hack/tools/go.mod @@ -1,12 +1,12 @@ module github.com/projectsveltos/sveltoscluster-manager/hack/tools -go 1.21 +go 1.22.0 require ( github.com/a8m/envsubst v1.4.2 github.com/onsi/ginkgo/v2 v2.17.1 - golang.org/x/oauth2 v0.18.0 - k8s.io/client-go v0.29.3 + golang.org/x/oauth2 v0.19.0 + k8s.io/client-go v0.29.4 sigs.k8s.io/controller-tools v0.14.0 sigs.k8s.io/kind v0.22.0 ) @@ -23,7 +23,6 @@ require ( github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobuffalo/flect v1.0.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect @@ -38,20 +37,18 @@ require ( github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.22.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.17.0 // indirect - google.golang.org/appengine v1.6.7 // 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 - k8s.io/api v0.29.3 // indirect + k8s.io/api v0.29.4 // indirect k8s.io/apiextensions-apiserver v0.29.0 // indirect - k8s.io/apimachinery v0.29.3 // indirect + k8s.io/apimachinery v0.29.4 // indirect k8s.io/klog/v2 v2.110.1 // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/hack/tools/go.sum b/hack/tools/go.sum index 5308769..8b7ef97 100644 --- a/hack/tools/go.sum +++ b/hack/tools/go.sum @@ -40,7 +40,6 @@ github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -133,14 +132,13 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 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.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= 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= @@ -158,7 +156,6 @@ golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= @@ -174,8 +171,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -192,14 +187,14 @@ 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= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= -k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/api v0.29.4 h1:WEnF/XdxuCxdG3ayHNRR8yH3cI1B/llkWBma6bq4R3w= +k8s.io/api v0.29.4/go.mod h1:DetSv0t4FBTcEpfA84NJV3g9a7+rSzlUHk5ADAYHUv0= k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0= k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc= -k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= -k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= -k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= -k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= +k8s.io/apimachinery v0.29.4 h1:RaFdJiDmuKs/8cm1M6Dh1Kvyh59YQFDcFuFTSmXes6Q= +k8s.io/apimachinery v0.29.4/go.mod h1:i3FJVwhvSp/6n8Fl4K97PJEP8C+MM+aoDq4+ZJBf70Y= +k8s.io/client-go v0.29.4 h1:79ytIedxVfyXV8rpH3jCBW0u+un0fxHDwX5F9K8dPR8= +k8s.io/client-go v0.29.4/go.mod h1:kC1thZQ4zQWYwldsfI088BbK6RkxK+aF5ebV8y9Q4tk= k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= diff --git a/manifest/deployment-shard.yaml b/manifest/deployment-shard.yaml index a9eb6f1..69475db 100644 --- a/manifest/deployment-shard.yaml +++ b/manifest/deployment-shard.yaml @@ -24,7 +24,7 @@ spec: - --v=5 command: - /manager - image: projectsveltos/sveltoscluster-manager:main + image: projectsveltos/sveltoscluster-manager:dev livenessProbe: failureThreshold: 3 httpGet: diff --git a/manifest/manifest.yaml b/manifest/manifest.yaml index 764cb69..284ad90 100644 --- a/manifest/manifest.yaml +++ b/manifest/manifest.yaml @@ -21,6 +21,7 @@ rules: verbs: - get - list + - update - watch - apiGroups: - authentication.k8s.io @@ -108,7 +109,7 @@ spec: - --v=5 command: - /manager - image: projectsveltos/sveltoscluster-manager:main + image: projectsveltos/sveltoscluster-manager:dev livenessProbe: failureThreshold: 3 httpGet: diff --git a/test/clusterapi-workload.yaml b/test/clusterapi-workload.yaml new file mode 100644 index 0000000..4ccf452 --- /dev/null +++ b/test/clusterapi-workload.yaml @@ -0,0 +1,312 @@ +apiVersion: cluster.x-k8s.io/v1beta1 +kind: ClusterClass +metadata: + name: quick-start + namespace: default +spec: + controlPlane: + machineInfrastructure: + ref: + apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 + kind: DockerMachineTemplate + name: quick-start-control-plane + ref: + apiVersion: controlplane.cluster.x-k8s.io/v1beta1 + kind: KubeadmControlPlaneTemplate + name: quick-start-control-plane + infrastructure: + ref: + apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 + kind: DockerClusterTemplate + name: quick-start-cluster + patches: + - definitions: + - jsonPatches: + - op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/imageRepository + valueFrom: + variable: imageRepository + selector: + apiVersion: controlplane.cluster.x-k8s.io/v1beta1 + kind: KubeadmControlPlaneTemplate + matchResources: + controlPlane: true + description: Sets the imageRepository used for the KubeadmControlPlane. + enabledIf: '{{ ne .imageRepository "" }}' + name: imageRepository + - definitions: + - jsonPatches: + - op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/etcd + valueFrom: + template: | + local: + imageTag: {{ .etcdImageTag }} + selector: + apiVersion: controlplane.cluster.x-k8s.io/v1beta1 + kind: KubeadmControlPlaneTemplate + matchResources: + controlPlane: true + description: Sets tag to use for the etcd image in the KubeadmControlPlane. + name: etcdImageTag + - definitions: + - jsonPatches: + - op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/dns + valueFrom: + template: | + imageTag: {{ .coreDNSImageTag }} + selector: + apiVersion: controlplane.cluster.x-k8s.io/v1beta1 + kind: KubeadmControlPlaneTemplate + matchResources: + controlPlane: true + description: Sets tag to use for the etcd image in the KubeadmControlPlane. + name: coreDNSImageTag + - definitions: + - jsonPatches: + - op: add + path: /spec/template/spec/customImage + valueFrom: + template: | + kindest/node:{{ .builtin.machineDeployment.version | replace "+" "_" }} + selector: + apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 + kind: DockerMachineTemplate + matchResources: + machineDeploymentClass: + names: + - default-worker + - jsonPatches: + - op: add + path: /spec/template/spec/customImage + valueFrom: + template: | + kindest/node:{{ .builtin.controlPlane.version | replace "+" "_" }} + selector: + apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 + kind: DockerMachineTemplate + matchResources: + controlPlane: true + description: Sets the container image that is used for running dockerMachines + for the controlPlane and default-worker machineDeployments. + name: customImage + - definitions: + - jsonPatches: + - op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraArgs + value: + admission-control-config-file: /etc/kubernetes/kube-apiserver-admission-pss.yaml + - op: add + path: /spec/template/spec/kubeadmConfigSpec/clusterConfiguration/apiServer/extraVolumes + value: + - hostPath: /etc/kubernetes/kube-apiserver-admission-pss.yaml + mountPath: /etc/kubernetes/kube-apiserver-admission-pss.yaml + name: admission-pss + pathType: File + readOnly: true + - op: add + path: /spec/template/spec/kubeadmConfigSpec/files + valueFrom: + template: | + - content: | + apiVersion: apiserver.config.k8s.io/v1 + kind: AdmissionConfiguration + plugins: + - name: PodSecurity + configuration: + apiVersion: pod-security.admission.config.k8s.io/v1{{ if semverCompare "< v1.25" .builtin.controlPlane.version }}beta1{{ end }} + kind: PodSecurityConfiguration + defaults: + audit: "{{ .podSecurityStandard.audit }}" + audit-version: "latest" + warn: "{{ .podSecurityStandard.warn }}" + warn-version: "latest" + exemptions: + usernames: [] + runtimeClasses: [] + namespaces: [kube-system] + path: /etc/kubernetes/kube-apiserver-admission-pss.yaml + selector: + apiVersion: controlplane.cluster.x-k8s.io/v1beta1 + kind: KubeadmControlPlaneTemplate + matchResources: + controlPlane: true + description: Adds an admission configuration for PodSecurity to the kube-apiserver. + enabledIf: '{{ .podSecurityStandard.enabled }}' + name: podSecurityStandard + variables: + - name: imageRepository + required: true + schema: + openAPIV3Schema: + default: "" + description: imageRepository sets the container registry to pull images from. + If empty, nothing will be set and the from of kubeadm will be used. + example: registry.k8s.io + type: string + - name: etcdImageTag + required: true + schema: + openAPIV3Schema: + default: "" + description: etcdImageTag sets the tag for the etcd image. + example: 3.5.3-0 + type: string + - name: coreDNSImageTag + required: true + schema: + openAPIV3Schema: + default: "" + description: coreDNSImageTag sets the tag for the coreDNS image. + example: v1.8.5 + type: string + - name: podSecurityStandard + required: false + schema: + openAPIV3Schema: + properties: + audit: + default: restricted + description: audit sets the level for the audit PodSecurityConfiguration + mode. One of privileged, baseline, restricted. + type: string + enabled: + default: true + description: enabled enables the patches to enable Pod Security Standard + via AdmissionConfiguration. + type: boolean + enforce: + default: baseline + description: enforce sets the level for the enforce PodSecurityConfiguration + mode. One of privileged, baseline, restricted. + type: string + warn: + default: restricted + description: warn sets the level for the warn PodSecurityConfiguration + mode. One of privileged, baseline, restricted. + type: string + type: object + workers: + machineDeployments: + - class: default-worker + template: + bootstrap: + ref: + apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 + kind: KubeadmConfigTemplate + name: quick-start-default-worker-bootstraptemplate + infrastructure: + ref: + apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 + kind: DockerMachineTemplate + name: quick-start-default-worker-machinetemplate +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: DockerClusterTemplate +metadata: + name: quick-start-cluster + namespace: default +spec: + template: + spec: {} +--- +apiVersion: controlplane.cluster.x-k8s.io/v1beta1 +kind: KubeadmControlPlaneTemplate +metadata: + name: quick-start-control-plane + namespace: default +spec: + template: + spec: + kubeadmConfigSpec: + clusterConfiguration: + apiServer: + certSANs: + - localhost + - 127.0.0.1 + - 0.0.0.0 + - host.docker.internal + controllerManager: + extraArgs: + enable-hostpath-provisioner: "true" + initConfiguration: + nodeRegistration: {} + joinConfiguration: + nodeRegistration: {} +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: DockerMachineTemplate +metadata: + name: quick-start-control-plane + namespace: default +spec: + template: + spec: + extraMounts: + - containerPath: /var/run/docker.sock + hostPath: /var/run/docker.sock +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1beta1 +kind: DockerMachineTemplate +metadata: + name: quick-start-default-worker-machinetemplate + namespace: default +spec: + template: + spec: + extraMounts: + - containerPath: /var/run/docker.sock + hostPath: /var/run/docker.sock +--- +apiVersion: bootstrap.cluster.x-k8s.io/v1beta1 +kind: KubeadmConfigTemplate +metadata: + name: quick-start-default-worker-bootstraptemplate + namespace: default +spec: + template: + spec: + joinConfiguration: + nodeRegistration: {} +--- +apiVersion: cluster.x-k8s.io/v1beta1 +kind: Cluster +metadata: + name: clusterapi-workload + namespace: default + labels: + env: fv +spec: + clusterNetwork: + pods: + cidrBlocks: + - 10.220.0.0/16 + serviceDomain: cluster.local + services: + cidrBlocks: + - 10.225.0.0/16 + topology: + class: quick-start + controlPlane: + metadata: {} + replicas: 1 + variables: + - name: imageRepository + value: "" + - name: etcdImageTag + value: "" + - name: coreDNSImageTag + value: "" + - name: podSecurityStandard + value: + audit: restricted + enabled: true + enforce: baseline + warn: restricted + version: v1.27.0 + workers: + machineDeployments: + - class: default-worker + name: md-0 + replicas: 2 diff --git a/test/fv/fv_suite_test.go b/test/fv/fv_suite_test.go new file mode 100644 index 0000000..4be4888 --- /dev/null +++ b/test/fv/fv_suite_test.go @@ -0,0 +1,335 @@ +/* +Copyright 2024. projectsveltos.io. All rights reserved. + +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 fv_test + +import ( + "context" + "encoding/base64" + "fmt" + "testing" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/TwiN/go-color" + ginkgotypes "github.com/onsi/ginkgo/v2/types" + authenticationv1 "k8s.io/api/authentication/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "k8s.io/klog/v2" + "k8s.io/klog/v2/textlogger" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + libsveltosv1alpha1 "github.com/projectsveltos/libsveltos/api/v1alpha1" + "github.com/projectsveltos/libsveltos/lib/clusterproxy" +) + +var ( + k8sClient client.Client + scheme *runtime.Scheme + kindWorkloadCluster *clusterv1.Cluster +) + +const ( + timeout = 2 * time.Minute + pollingInterval = 5 * time.Second + //nolint: gosec // this is not a secret. It is the postfix of the Kubernetes secret with kubeconfig + secretPostfix = "-sveltos-kubeconfig" +) + +func TestFv(t *testing.T) { + RegisterFailHandler(Fail) + + suiteConfig, reporterConfig := GinkgoConfiguration() + reporterConfig.FullTrace = true + reporterConfig.JSONReport = "out.json" + report := func(report ginkgotypes.Report) { + for i := range report.SpecReports { + specReport := report.SpecReports[i] + if specReport.State.String() == "skipped" { + GinkgoWriter.Printf(color.Colorize(color.Blue, fmt.Sprintf("[Skipped]: %s\n", specReport.FullText()))) + } + } + for i := range report.SpecReports { + specReport := report.SpecReports[i] + if specReport.Failed() { + GinkgoWriter.Printf(color.Colorize(color.Red, fmt.Sprintf("[Failed]: %s\n", specReport.FullText()))) + } + } + } + ReportAfterSuite("report", report) + + RunSpecs(t, "FV Suite", suiteConfig, reporterConfig) +} + +var _ = BeforeSuite(func() { + restConfig := ctrl.GetConfigOrDie() + // To get rid of the annoying request.go log + restConfig.QPS = 100 + restConfig.Burst = 100 + + scheme = runtime.NewScheme() + + ctrl.SetLogger(klog.Background()) + + Expect(clientgoscheme.AddToScheme(scheme)).To(Succeed()) + Expect(clusterv1.AddToScheme(scheme)).To(Succeed()) + Expect(libsveltosv1alpha1.AddToScheme(scheme)).To(Succeed()) + + var err error + k8sClient, err = client.New(restConfig, client.Options{Scheme: scheme}) + Expect(err).NotTo(HaveOccurred()) + + clusterList := &clusterv1.ClusterList{} + listOptions := []client.ListOption{ + client.MatchingLabels( + map[string]string{clusterv1.ClusterNameLabel: "clusterapi-workload"}, + ), + } + + Expect(k8sClient.List(context.TODO(), clusterList, listOptions...)).To(Succeed()) + Expect(len(clusterList.Items)).To(Equal(1)) + kindWorkloadCluster = &clusterList.Items[0] + + waitForClusterMachineToBeReady() + + remoteRestConfig := getManagedClusterRestConfig(kindWorkloadCluster) + + // Creates: + // - ServiceAccount + // - ClusterRole + // - ClusterRoleBinding + // - get a TokenRequest for ServiceAccount + // - return a Kubeconfig with such TokenRequest + kubeconfig := generateKubeconfigWithTokenRequest(remoteRestConfig) + + // Register workload cluster as SveltosCluster. + registerCluster(kindWorkloadCluster.Namespace, kindWorkloadCluster.Name, kubeconfig) +}) + +func generateKubeconfigWithTokenRequest(remoteRestConfig *rest.Config) string { + remoteClient, err := client.New(remoteRestConfig, client.Options{Scheme: scheme}) + Expect(err).To(BeNil()) + + projectsveltos := "projectsveltos" + By(fmt.Sprintf("Creating namespace %s", projectsveltos)) + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: projectsveltos, + }, + } + err = remoteClient.Create(context.TODO(), ns) + if err != nil { + Expect(apierrors.IsAlreadyExists(err)).To(BeTrue()) + } + + By(fmt.Sprintf("Creating serviceAccount %s/%s", projectsveltos, projectsveltos)) + serviceAccount := &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: projectsveltos, + Name: projectsveltos, + }, + } + err = remoteClient.Create(context.TODO(), serviceAccount) + if err != nil { + Expect(apierrors.IsAlreadyExists(err)).To(BeTrue()) + } + + By(fmt.Sprintf("Creating clusterRole %s", projectsveltos)) + clusterrole := &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: projectsveltos, + }, + Rules: []rbacv1.PolicyRule{ + { + Verbs: []string{"*"}, + APIGroups: []string{"*"}, + Resources: []string{"*"}, + }, + { + Verbs: []string{"*"}, + NonResourceURLs: []string{"*"}, + }, + }, + } + err = remoteClient.Create(context.TODO(), clusterrole) + if err != nil { + Expect(apierrors.IsAlreadyExists(err)).To(BeTrue()) + } + + By(fmt.Sprintf("Creating clusterRoleBinding %s", projectsveltos)) + clusterrolebinding := &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: projectsveltos, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: rbacv1.SchemeGroupVersion.Group, + Kind: "ClusterRole", + Name: projectsveltos, + }, + Subjects: []rbacv1.Subject{ + { + Namespace: projectsveltos, + Name: projectsveltos, + Kind: "ServiceAccount", + APIGroup: corev1.SchemeGroupVersion.Group, + }, + }, + } + err = remoteClient.Create(context.TODO(), clusterrolebinding) + if err != nil { + Expect(apierrors.IsAlreadyExists(err)).To(BeTrue()) + } + + tokenRequest := getServiceAccountTokenRequest(remoteRestConfig, projectsveltos, projectsveltos) + return getKubeconfigFromToken(remoteRestConfig, projectsveltos, projectsveltos, tokenRequest.Token) +} + +// getServiceAccountTokenRequest returns token for a serviceaccount +func getServiceAccountTokenRequest(restConfig *rest.Config, + serviceAccountNamespace, serviceAccountName string) *authenticationv1.TokenRequestStatus { + + saExpirationInSecond := 365 * 24 * 60 * time.Minute + expiration := int64(saExpirationInSecond.Seconds()) + + treq := &authenticationv1.TokenRequest{ + Spec: authenticationv1.TokenRequestSpec{ + ExpirationSeconds: &expiration, + }, + } + + clientset, err := kubernetes.NewForConfig(restConfig) + Expect(err).To(BeNil()) + + By(fmt.Sprintf("Create Token for ServiceAccount %s/%s", serviceAccountNamespace, serviceAccountName)) + var tokenRequest *authenticationv1.TokenRequest + tokenRequest, err = clientset.CoreV1().ServiceAccounts(serviceAccountNamespace). + CreateToken(context.TODO(), serviceAccountName, treq, metav1.CreateOptions{}) + Expect(err).To(BeNil()) + + return &tokenRequest.Status +} + +// getKubeconfigFromToken returns Kubeconfig to access management cluster from token. +func getKubeconfigFromToken(restConfig *rest.Config, namespace, serviceAccountName, token string) string { + template := `apiVersion: v1 +kind: Config +clusters: +- name: local + cluster: + server: %s + certificate-authority-data: "%s" +users: +- name: %s + user: + token: %s +contexts: +- name: sveltos-context + context: + cluster: local + namespace: %s + user: %s +current-context: sveltos-context` + + data := fmt.Sprintf(template, restConfig.Host, base64.StdEncoding.EncodeToString(restConfig.CAData), + serviceAccountName, token, namespace, serviceAccountName) + + return data +} + +func registerCluster(sveltosClusterNamespace, sveltosClusterName, kubeconfig string) { + createSecretForSveltosClusterWithKubeconfig(sveltosClusterNamespace, sveltosClusterName, kubeconfig) + + createSveltosCluster(sveltosClusterNamespace, sveltosClusterName) +} + +// Creates a Secret for SveltosCluster containing Kubeconfig +func createSecretForSveltosClusterWithKubeconfig(sveltosClusterNamespace, sveltosClusterName, kubeconfig string) { + sveltosSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: sveltosClusterNamespace, + Name: sveltosClusterName + secretPostfix, + }, + Data: map[string][]byte{ + "data": []byte(kubeconfig), + }, + } + err := k8sClient.Create(context.TODO(), sveltosSecret) + if err != nil { + Expect(apierrors.IsAlreadyExists(err)).To(BeTrue()) + } +} + +func createSveltosCluster(sveltosClusterNamespace, sveltosClusterName string) { + sveltosCluster := &libsveltosv1alpha1.SveltosCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: sveltosClusterNamespace, + Name: sveltosClusterName, + }, + Spec: libsveltosv1alpha1.SveltosClusterSpec{ + TokenRequestRenewalOption: &libsveltosv1alpha1.TokenRequestRenewalOption{ + RenewTokenRequestInterval: metav1.Duration{Duration: time.Minute}, + }, + }, + } + + err := k8sClient.Create(context.TODO(), sveltosCluster) + if err != nil { + Expect(apierrors.IsAlreadyExists(err)).To(BeTrue()) + } +} + +func waitForClusterMachineToBeReady() { + By(fmt.Sprintf("Wait for machine in cluster %s/%s to be ready", kindWorkloadCluster.Namespace, kindWorkloadCluster.Name)) + + Eventually(func() bool { + machineList := &clusterv1.MachineList{} + listOptions := []client.ListOption{ + client.InNamespace(kindWorkloadCluster.Namespace), + client.MatchingLabels{clusterv1.ClusterNameLabel: kindWorkloadCluster.Name}, + } + err := k8sClient.List(context.TODO(), machineList, listOptions...) + if err != nil { + return false + } + for i := range machineList.Items { + m := machineList.Items[i] + if m.Status.Phase == string(clusterv1.MachinePhaseRunning) { + return true + } + } + return false + }, timeout, pollingInterval).Should(BeTrue()) +} + +func getManagedClusterRestConfig(workloadCluster *clusterv1.Cluster) *rest.Config { + logger := textlogger.NewLogger(textlogger.NewConfig(textlogger.Verbosity(1))) + remoteRestConfig, err := clusterproxy.GetKubernetesRestConfig(context.TODO(), k8sClient, + workloadCluster.Namespace, workloadCluster.Name, "", "", libsveltosv1alpha1.ClusterTypeCapi, + logger) + Expect(err).To(BeNil()) + return remoteRestConfig +} diff --git a/test/fv/renew_toke_request_test.go b/test/fv/renew_toke_request_test.go new file mode 100644 index 0000000..4424128 --- /dev/null +++ b/test/fv/renew_toke_request_test.go @@ -0,0 +1,108 @@ +/* +Copyright 2023. projectsveltos.io. All rights reserved. + +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 fv_test + +import ( + "context" + "reflect" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + + libsveltosv1alpha1 "github.com/projectsveltos/libsveltos/api/v1alpha1" +) + +var _ = Describe("Renew TokenRequest", func() { + It("SveltosCluster controller renews TokenRequest", Label("FV"), func() { + // BeforeSuite has registered management cluster as a SveltosCluster + // generating a Kubeconfig based on a TokenRequest + // SveltosCluster is configured to renew the TokenRequest (and so update + // secret with Kubeconfig) every minute + + By("Verify SveltosCluster") + currentSveltosCluster := &libsveltosv1alpha1.SveltosCluster{} + Expect(k8sClient.Get(context.TODO(), + types.NamespacedName{Namespace: kindWorkloadCluster.Namespace, Name: kindWorkloadCluster.Name}, + currentSveltosCluster)).To(Succeed()) + + // Verify SveltosCluster is indeed configured to renew TokenRequest every minute + Expect(currentSveltosCluster.Spec.TokenRequestRenewalOption).ToNot(BeNil()) + interval := currentSveltosCluster.Spec.TokenRequestRenewalOption.RenewTokenRequestInterval + Expect(interval.Duration).To(Equal(time.Minute)) + + // Verify SveltosCluster status is set to Ready + Eventually(func() bool { + err := k8sClient.Get(context.TODO(), + types.NamespacedName{Namespace: kindWorkloadCluster.Namespace, Name: kindWorkloadCluster.Name}, + currentSveltosCluster) + if err != nil { + return false + } + return currentSveltosCluster.Status.Ready + }, timeout, pollingInterval).Should(BeTrue()) + + // Get Secret with SveltosCluster kubeconfig + By("Verify Secret with SveltosCluster kubeconfig") + currentSecret := &corev1.Secret{} + Expect(k8sClient.Get(context.TODO(), + types.NamespacedName{ + Namespace: kindWorkloadCluster.Namespace, + Name: kindWorkloadCluster.Name + secretPostfix, + }, + currentSecret, + )).To(Succeed()) + + By("Get current kubeconfig") + var currentKubeconfig []byte + Expect(currentSecret.Data).ToNot(BeNil()) + for k := range currentSecret.Data { + currentKubeconfig = currentSecret.Data[k] + break + } + Expect(currentKubeconfig).ToNot(BeNil()) + + By("Verify TokenRequest is renewed by verifying Secret content changes") + Eventually(func() bool { + err := k8sClient.Get(context.TODO(), + types.NamespacedName{ + Namespace: kindWorkloadCluster.Namespace, + Name: kindWorkloadCluster.Name + secretPostfix, + }, + currentSecret, + ) + if err != nil { + return false + } + if currentSecret.Data == nil { + return false + } + for k := range currentSecret.Data { + if currentSecret.Data[k] == nil { + continue + } + if !reflect.DeepEqual(currentSecret.Data[k], currentKubeconfig) { + return true + } + } + + return false + }, timeout, pollingInterval).Should(BeTrue()) + }) +}) diff --git a/test/kind-cluster.yaml b/test/kind-cluster.yaml new file mode 100644 index 0000000..7b904c1 --- /dev/null +++ b/test/kind-cluster.yaml @@ -0,0 +1,33 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +networking: + podSubnet: "10.110.0.0/16" + serviceSubnet: "10.115.0.0/16" +nodes: +- role: control-plane + kubeadmConfigPatches: + - | + kind: ClusterConfiguration + apiServer: + extraArgs: + v: "10" + image: kindest/node:K8S_VERSION + extraMounts: + - hostPath: /var/run/docker.sock + containerPath: /var/run/docker.sock + - hostPath: /usr/share/zoneinfo + containerPath: /usr/share/zoneinfo +- role: worker + image: kindest/node:K8S_VERSION + extraMounts: + - hostPath: /var/run/docker.sock + containerPath: /var/run/docker.sock + - hostPath: /usr/share/zoneinfo + containerPath: /usr/share/zoneinfo +- role: worker + image: kindest/node:K8S_VERSION + extraMounts: + - hostPath: /var/run/docker.sock + containerPath: /var/run/docker.sock + - hostPath: /usr/share/zoneinfo + containerPath: /usr/share/zoneinfo diff --git a/test/kind-workload-cluster.yaml b/test/kind-workload-cluster.yaml new file mode 100644 index 0000000..e69de29