From a0b1e6a07f2bf34a54d7aa971a93bce28bad678e Mon Sep 17 00:00:00 2001 From: Aleksei Sizov Date: Fri, 3 Jan 2025 14:41:54 -0500 Subject: [PATCH 01/14] Rename module+repos Mirantis/hmc -> K0rdent/kcm --- .github/workflows/build_test.yml | 12 ++++----- .github/workflows/release.yml | 8 +++--- .golangci.yml | 2 +- Makefile | 4 +-- PROJECT | 26 +++++++++---------- README.md | 6 ++--- cmd/main.go | 14 +++++----- docs/dev.md | 8 +++--- go.mod | 2 +- .../controller/accessmanagement_controller.go | 2 +- .../accessmanagement_controller_test.go | 8 +++--- internal/controller/backup_controller.go | 2 +- internal/controller/backup_controller_test.go | 2 +- .../clusterdeployment_controller.go | 14 +++++----- .../clusterdeployment_controller_test.go | 2 +- internal/controller/credential_controller.go | 2 +- internal/controller/management_controller.go | 10 +++---- .../controller/management_controller_test.go | 4 +-- .../multiclusterservice_controller.go | 4 +-- .../multiclusterservice_controller_test.go | 2 +- internal/controller/release_controller.go | 8 +++--- internal/controller/suite_test.go | 4 +-- internal/controller/template_controller.go | 6 ++--- .../controller/template_controller_test.go | 2 +- .../controller/templatechain_controller.go | 4 +-- .../templatechain_controller_test.go | 6 ++--- internal/credspropagation/common.go | 2 +- internal/credspropagation/vsphere.go | 2 +- internal/helm/release.go | 2 +- internal/helm/repo.go | 2 +- internal/sveltos/profile.go | 4 +-- internal/sveltos/status.go | 2 +- internal/telemetry/event.go | 2 +- internal/telemetry/tracker.go | 2 +- internal/webhook/accessmanagement_webhook.go | 2 +- .../webhook/accessmanagement_webhook_test.go | 10 +++---- internal/webhook/clusterdeployment_webhook.go | 2 +- .../webhook/clusterdeployment_webhook_test.go | 12 ++++----- internal/webhook/management_webhook.go | 2 +- internal/webhook/management_webhook_test.go | 12 ++++----- .../webhook/multiclusterservice_webhook.go | 2 +- .../multiclusterservice_webhook_test.go | 8 +++--- internal/webhook/release_webhook.go | 2 +- internal/webhook/release_webhook_test.go | 8 +++--- internal/webhook/template_webhook.go | 4 +-- internal/webhook/template_webhook_test.go | 16 ++++++------ internal/webhook/templatechain_webhook.go | 2 +- .../webhook/templatechain_webhook_test.go | 6 ++--- mkdocs.yml | 2 +- templates/provider/hmc/values.yaml | 4 +-- test/e2e/clusterdeployment/aws/aws.go | 4 +-- test/e2e/clusterdeployment/azure/azure.go | 4 +-- .../clusterdeployment/clusterdeployment.go | 2 +- .../clusteridentity/clusteridentity.go | 4 +-- test/e2e/clusterdeployment/common.go | 2 +- .../clusterdeployment/providervalidator.go | 2 +- .../e2e/clusterdeployment/validate_deleted.go | 6 ++--- .../clusterdeployment/validate_deployed.go | 6 ++--- test/e2e/clusterdeployment/vsphere/vsphere.go | 2 +- test/e2e/e2e_suite_test.go | 8 +++--- test/e2e/kubeclient/kubeclient.go | 2 +- test/e2e/provider_aws_test.go | 12 ++++----- test/e2e/provider_azure_test.go | 12 ++++----- test/e2e/provider_vsphere_test.go | 10 +++---- .../accessmanagement/accessmanagement.go | 2 +- .../clusterdeployment/clusterdeployment.go | 2 +- test/objects/credential/credential.go | 2 +- test/objects/management/management.go | 4 +-- .../multiclusterservice.go | 2 +- test/objects/release/release.go | 2 +- test/objects/template/template.go | 2 +- test/objects/templatechain/templatechain.go | 2 +- test/scheme/scheme.go | 2 +- test/utils/utils.go | 2 +- 74 files changed, 187 insertions(+), 187 deletions(-) diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 5bb4b6e0c..7256958dc 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -18,7 +18,7 @@ on: env: GO_VERSION: '1.23' - REGISTRY_REPO: 'oci://ghcr.io/mirantis/hmc/charts-ci' + REGISTRY_REPO: 'oci://ghcr.io/k0rdent/kcm/charts-ci' jobs: build: @@ -77,11 +77,11 @@ jobs: uses: docker/build-push-action@v6 with: build-args: | - LD_FLAGS=-s -w -X github.com/Mirantis/hmc/internal/build.Version=${{ steps.vars.outputs.version }} + LD_FLAGS=-s -w -X github.com/K0rdent/kcm/internal/build.Version=${{ steps.vars.outputs.version }} context: . platforms: linux/amd64 tags: | - ghcr.io/mirantis/hmc/controller-ci:${{ steps.vars.outputs.version }} + ghcr.io/k0rdent/kcm/controller-ci:${{ steps.vars.outputs.version }} push: true cache-from: type=gha cache-to: type=gha,mode=max @@ -113,7 +113,7 @@ jobs: env: GINKGO_LABEL_FILTER: 'controller' CLUSTER_DEPLOYMENT_NAME: ${{ needs.build.outputs.clustername }} - IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}' + IMG: 'ghcr.io/k0rdent/kcm/controller-ci:${{ needs.build.outputs.version }}' VERSION: ${{ needs.build.outputs.version }} run: | make test-e2e @@ -163,7 +163,7 @@ jobs: env: GINKGO_LABEL_FILTER: 'provider:cloud' CLUSTER_DEPLOYMENT_NAME: ${{ needs.build.outputs.clustername }} - IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}' + IMG: 'ghcr.io/k0rdent/kcm/controller-ci:${{ needs.build.outputs.version }}' VERSION: ${{ needs.build.outputs.version }} run: | make test-e2e @@ -216,7 +216,7 @@ jobs: env: GINKGO_LABEL_FILTER: 'provider:onprem' CLUSTER_DEPLOYMENT_NAME: ${{ needs.build.outputs.clustername }} - IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}' + IMG: 'ghcr.io/k0rdent/kcm/controller-ci:${{ needs.build.outputs.version }}' VERSION: ${{ needs.build.outputs.version }} run: | make test-e2e diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 25cf84dd4..39ac3aede 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,11 +32,11 @@ jobs: uses: docker/build-push-action@v6 with: build-args: | - LD_FLAGS=-s -w -X github.com/Mirantis/hmc/internal/build.Version=${{ env.VERSION }} -X github.com/Mirantis/hmc/internal/telemetry.segmentToken=${{ secrets.SEGMENT_TOKEN }} + LD_FLAGS=-s -w -X github.com/K0rdent/kcm/internal/build.Version=${{ env.VERSION }} -X github.com/K0rdent/kcm/internal/telemetry.segmentToken=${{ secrets.SEGMENT_TOKEN }} context: . platforms: linux/amd64,linux/arm64 tags: | - ghcr.io/mirantis/hmc/controller:${{ env.VERSION }} + ghcr.io/k0rdent/kcm/controller:${{ env.VERSION }} push: true cache-from: type=gha cache-to: type=gha,mode=max @@ -44,7 +44,7 @@ jobs: - name: Prepare HMC chart run: VERSION="${{ env.VERSION }}" make hmc-chart-release - name: Push charts to GHCR - run: REGISTRY_REPO="oci://ghcr.io/mirantis/hmc/charts" make helm-push + run: REGISTRY_REPO="oci://ghcr.io/k0rdent/kcm/charts" make helm-push - name: Prepare manifests run: make hmc-dist-release @@ -61,7 +61,7 @@ jobs: - name: Build airgap bundle env: - IMG: 'ghcr.io/mirantis/hmc/controller:${{ env.VERSION }}' + IMG: 'ghcr.io/k0rdent/kcm/controller:${{ env.VERSION }}' run: | make airgap-package diff --git a/.golangci.yml b/.golangci.yml index ee80ea33b..4330eae8b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -132,7 +132,7 @@ linters-settings: sections: - standard # Standard section: captures all standard packages. - default # Default section: contains all imports that could not be matched to another section type. - - prefix(github.com/Mirantis/hmc) # Custom section: groups all imports with the specified Prefix. + - prefix(github.com/K0rdent/kcm) # Custom section: groups all imports with the specified Prefix. skip-generated: false gofmt: # Apply the rewrite rules to the source before reformatting. diff --git a/Makefile b/Makefile index 230fbd881..b6e5be649 100644 --- a/Makefile +++ b/Makefile @@ -176,8 +176,8 @@ package-chart-%: lint-chart-% ##@ Build LD_FLAGS?= -s -w -LD_FLAGS += -X github.com/Mirantis/hmc/internal/build.Version=$(VERSION) -LD_FLAGS += -X github.com/Mirantis/hmc/internal/telemetry.segmentToken=$(SEGMENT_TOKEN) +LD_FLAGS += -X github.com/K0rdent/kcm/internal/build.Version=$(VERSION) +LD_FLAGS += -X github.com/K0rdent/kcm/internal/telemetry.segmentToken=$(SEGMENT_TOKEN) .PHONY: build build: generate-all ## Build manager binary. diff --git a/PROJECT b/PROJECT index a38ffedb6..2dc3e36ca 100644 --- a/PROJECT +++ b/PROJECT @@ -6,7 +6,7 @@ domain: hmc.mirantis.com layout: - go.kubebuilder.io/v4 projectName: hmc -repo: github.com/Mirantis/hmc +repo: github.com/K0rdent/kcm resources: - api: crdVersion: v1 @@ -15,7 +15,7 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: ClusterDeployment - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -24,14 +24,14 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: Management - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 domain: hmc.mirantis.com group: hmc.mirantis.com kind: Release - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 webhooks: validation: true @@ -43,7 +43,7 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: ClusterTemplate - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -52,7 +52,7 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: ProviderTemplate - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -61,7 +61,7 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: ServiceTemplate - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -70,7 +70,7 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: AccessManagement - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -78,14 +78,14 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: ClusterTemplateChain - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 domain: hmc.mirantis.com group: hmc.mirantis.com kind: ServiceTemplateChain - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -94,7 +94,7 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: Credential - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -102,7 +102,7 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: MultiClusterService - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 - api: crdVersion: v1 @@ -111,6 +111,6 @@ resources: domain: hmc.mirantis.com group: hmc.mirantis.com kind: Backup - path: github.com/Mirantis/hmc/api/v1alpha1 + path: github.com/K0rdent/kcm/api/v1alpha1 version: v1alpha1 version: "3" diff --git a/README.md b/README.md index 537b0e84e..8a8f0e768 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ Detailed documentation is available in [Project 0x2A Docs](https://mirantis.gith ### TL;DR ```bash -kubectl apply -f https://github.com/Mirantis/hmc/releases/download/v0.0.5/install.yaml +kubectl apply -f https://github.com/K0rdent/kcm/releases/download/v0.0.5/install.yaml ``` or install using `helm` ```bash -helm install hmc oci://ghcr.io/mirantis/hmc/charts/hmc --version 0.0.5 -n hmc-system --create-namespace +helm install hmc oci://ghcr.io/k0rdent/kcm/charts/hmc --version 0.0.5 -n hmc-system --create-namespace ``` Then follow the [Deploy a cluster deployment](#deploy-a-cluster-deployment) guide to @@ -63,7 +63,7 @@ see [Documentation](#documentation) ``` export KUBECONFIG= -helm install hmc oci://ghcr.io/mirantis/hmc/charts/hmc --version -n hmc-system --create-namespace +helm install hmc oci://ghcr.io/k0rdent/kcm/charts/hmc --version -n hmc-system --create-namespace ``` #### Extended Management configuration diff --git a/cmd/main.go b/cmd/main.go index 84c9944cb..5a24c834b 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -36,12 +36,12 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/controller" - "github.com/Mirantis/hmc/internal/helm" - "github.com/Mirantis/hmc/internal/telemetry" - "github.com/Mirantis/hmc/internal/utils" - hmcwebhook "github.com/Mirantis/hmc/internal/webhook" + hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/controller" + "github.com/K0rdent/kcm/internal/helm" + "github.com/K0rdent/kcm/internal/telemetry" + "github.com/K0rdent/kcm/internal/utils" + hmcwebhook "github.com/K0rdent/kcm/internal/webhook" ) var ( @@ -88,7 +88,7 @@ func main() { "If set the metrics endpoint is served securely") flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers") - flag.StringVar(&defaultRegistryURL, "default-registry-url", "oci://ghcr.io/mirantis/hmc/charts", + flag.StringVar(&defaultRegistryURL, "default-registry-url", "oci://ghcr.io/k0rdent/kcm/charts", "The default registry to download Helm charts from, prefix with oci:// for OCI registries.") flag.StringVar(®istryCredentialsSecret, "registry-creds-secret", "", "Secret containing authentication credentials for the registry.") diff --git a/docs/dev.md b/docs/dev.md index 0823cc27a..0fddbc2b5 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -8,7 +8,7 @@ a managed cluster on AWS with k0s for testing. The kind cluster acts as manageme ### Clone HMC repository ```bash -git clone https://github.com/Mirantis/hmc.git && cd hmc +git clone https://github.com/K0rdent/kcm.git && cd hmc ``` ### Install required CLIs @@ -141,8 +141,8 @@ and hmc-controller image will need to exist on the registry, for example, using GHCR: ``` -IMG="ghcr.io/mirantis/hmc/controller-ci:v0.0.1-179-ga5bdf29" \ - REGISTRY_REPO="oci://ghcr.io/mirantis/hmc/charts-ci" \ +IMG="ghcr.io/k0rdent/kcm/controller-ci:v0.0.1-179-ga5bdf29" \ + REGISTRY_REPO="oci://ghcr.io/k0rdent/kcm/charts-ci" \ make test-e2e ``` @@ -244,7 +244,7 @@ to ensure the correctly tagged HMC controller image is present in the bundle prefix the `IMG` env var with the desired image, for example: ```bash -IMG="ghcr.io/mirantis/hmc:0.0.4" make airgap-package +IMG="ghcr.io/k0rdent/kcm:0.0.4" make airgap-package ``` Not setting an `IMG` var will use the default image name/tag generated by the diff --git a/go.mod b/go.mod index e22119cc6..6952b610d 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/Mirantis/hmc +module github.com/K0rdent/kcm go 1.23.0 diff --git a/internal/controller/accessmanagement_controller.go b/internal/controller/accessmanagement_controller.go index 7f0c53e2d..1f028e1b0 100644 --- a/internal/controller/accessmanagement_controller.go +++ b/internal/controller/accessmanagement_controller.go @@ -27,7 +27,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) // AccessManagementReconciler reconciles an AccessManagement object diff --git a/internal/controller/accessmanagement_controller_test.go b/internal/controller/accessmanagement_controller_test.go index d53328e35..1f5d0d863 100644 --- a/internal/controller/accessmanagement_controller_test.go +++ b/internal/controller/accessmanagement_controller_test.go @@ -26,10 +26,10 @@ import ( crclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - am "github.com/Mirantis/hmc/test/objects/accessmanagement" - "github.com/Mirantis/hmc/test/objects/credential" - tc "github.com/Mirantis/hmc/test/objects/templatechain" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + am "github.com/K0rdent/kcm/test/objects/accessmanagement" + "github.com/K0rdent/kcm/test/objects/credential" + tc "github.com/K0rdent/kcm/test/objects/templatechain" ) var _ = Describe("Template Management Controller", func() { diff --git a/internal/controller/backup_controller.go b/internal/controller/backup_controller.go index 3572b673a..6b87cd6a6 100644 --- a/internal/controller/backup_controller.go +++ b/internal/controller/backup_controller.go @@ -22,7 +22,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" + hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" ) // BackupReconciler reconciles a Backup object diff --git a/internal/controller/backup_controller_test.go b/internal/controller/backup_controller_test.go index 5fc61af7f..009c7e8b7 100644 --- a/internal/controller/backup_controller_test.go +++ b/internal/controller/backup_controller_test.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/reconcile" - hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" + hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" ) var _ = Describe("Backup Controller", func() { diff --git a/internal/controller/clusterdeployment_controller.go b/internal/controller/clusterdeployment_controller.go index c6f02d4f8..e373e92de 100644 --- a/internal/controller/clusterdeployment_controller.go +++ b/internal/controller/clusterdeployment_controller.go @@ -47,12 +47,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/credspropagation" - "github.com/Mirantis/hmc/internal/helm" - "github.com/Mirantis/hmc/internal/sveltos" - "github.com/Mirantis/hmc/internal/telemetry" - "github.com/Mirantis/hmc/internal/utils/status" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/credspropagation" + "github.com/K0rdent/kcm/internal/helm" + "github.com/K0rdent/kcm/internal/sveltos" + "github.com/K0rdent/kcm/internal/telemetry" + "github.com/K0rdent/kcm/internal/utils/status" ) const ( @@ -558,7 +558,7 @@ func (r *ClusterDeploymentReconciler) Delete(ctx context.Context, clusterDeploym // which prevents Sveltos objects from being removed from the management cluster. // It is detailed in https://github.com/projectsveltos/addon-controller/issues/732. // We may try to remove the explicit call to Delete once a fix for it has been merged. - // TODO(https://github.com/Mirantis/hmc/issues/526). + // TODO(https://github.com/K0rdent/kcm/issues/526). if err := sveltos.DeleteProfile(ctx, r.Client, clusterDeployment.Namespace, clusterDeployment.Name); err != nil { return ctrl.Result{}, err } diff --git a/internal/controller/clusterdeployment_controller_test.go b/internal/controller/clusterdeployment_controller_test.go index 4687c1591..bf6109a37 100644 --- a/internal/controller/clusterdeployment_controller_test.go +++ b/internal/controller/clusterdeployment_controller_test.go @@ -30,7 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) var _ = Describe("ClusterDeployment Controller", func() { diff --git a/internal/controller/credential_controller.go b/internal/controller/credential_controller.go index 661d021f5..33e51dd26 100644 --- a/internal/controller/credential_controller.go +++ b/internal/controller/credential_controller.go @@ -27,7 +27,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) const defaultSyncPeriod = 15 * time.Minute diff --git a/internal/controller/management_controller.go b/internal/controller/management_controller.go index 102cad860..01b527d28 100644 --- a/internal/controller/management_controller.go +++ b/internal/controller/management_controller.go @@ -40,11 +40,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/certmanager" - "github.com/Mirantis/hmc/internal/helm" - "github.com/Mirantis/hmc/internal/utils" - "github.com/Mirantis/hmc/internal/utils/status" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/certmanager" + "github.com/K0rdent/kcm/internal/helm" + "github.com/K0rdent/kcm/internal/utils" + "github.com/K0rdent/kcm/internal/utils/status" ) // ManagementReconciler reconciles a Management object diff --git a/internal/controller/management_controller_test.go b/internal/controller/management_controller_test.go index 4f05de291..a78848989 100644 --- a/internal/controller/management_controller_test.go +++ b/internal/controller/management_controller_test.go @@ -34,8 +34,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/utils" + hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/utils" ) var _ = Describe("Management Controller", func() { diff --git a/internal/controller/multiclusterservice_controller.go b/internal/controller/multiclusterservice_controller.go index 9ab6a7655..9b1fef14a 100644 --- a/internal/controller/multiclusterservice_controller.go +++ b/internal/controller/multiclusterservice_controller.go @@ -35,8 +35,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/sveltos" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/sveltos" ) // MultiClusterServiceReconciler reconciles a MultiClusterService object diff --git a/internal/controller/multiclusterservice_controller_test.go b/internal/controller/multiclusterservice_controller_test.go index f3f7f9b79..ce492a4ab 100644 --- a/internal/controller/multiclusterservice_controller_test.go +++ b/internal/controller/multiclusterservice_controller_test.go @@ -30,7 +30,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/reconcile" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) var _ = Describe("MultiClusterService Controller", func() { diff --git a/internal/controller/release_controller.go b/internal/controller/release_controller.go index be19aa876..5336cf00b 100644 --- a/internal/controller/release_controller.go +++ b/internal/controller/release_controller.go @@ -44,10 +44,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/source" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/build" - "github.com/Mirantis/hmc/internal/helm" - "github.com/Mirantis/hmc/internal/utils" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/build" + "github.com/K0rdent/kcm/internal/helm" + "github.com/K0rdent/kcm/internal/utils" ) // ReleaseReconciler reconciles a Template object diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 1de9d3f6f..33a2bcf08 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -45,8 +45,8 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" - hmcwebhook "github.com/Mirantis/hmc/internal/webhook" + hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + hmcwebhook "github.com/K0rdent/kcm/internal/webhook" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index a4738b42d..d96405956 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -36,9 +36,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/helm" - "github.com/Mirantis/hmc/internal/utils" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/helm" + "github.com/K0rdent/kcm/internal/utils" ) const defaultRequeueTime = 1 * time.Minute diff --git a/internal/controller/template_controller_test.go b/internal/controller/template_controller_test.go index c44f842de..28b4aabd0 100644 --- a/internal/controller/template_controller_test.go +++ b/internal/controller/template_controller_test.go @@ -30,7 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" + hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" ) var _ = Describe("Template Controller", func() { diff --git a/internal/controller/templatechain_controller.go b/internal/controller/templatechain_controller.go index 5d50207da..ccee4fdd0 100644 --- a/internal/controller/templatechain_controller.go +++ b/internal/controller/templatechain_controller.go @@ -25,8 +25,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/utils" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/utils" ) // TemplateChainReconciler reconciles a TemplateChain object diff --git a/internal/controller/templatechain_controller_test.go b/internal/controller/templatechain_controller_test.go index 33ab0ae2d..49cf12969 100644 --- a/internal/controller/templatechain_controller_test.go +++ b/internal/controller/templatechain_controller_test.go @@ -30,9 +30,9 @@ import ( crclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/utils" - "github.com/Mirantis/hmc/test/objects/template" + hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/utils" + "github.com/K0rdent/kcm/test/objects/template" ) var _ = Describe("Template Chain Controller", func() { diff --git a/internal/credspropagation/common.go b/internal/credspropagation/common.go index 02bbf21eb..7d571cdb4 100644 --- a/internal/credspropagation/common.go +++ b/internal/credspropagation/common.go @@ -25,7 +25,7 @@ import ( "k8s.io/client-go/tools/clientcmd" "sigs.k8s.io/controller-runtime/pkg/client" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) type PropagationCfg struct { diff --git a/internal/credspropagation/vsphere.go b/internal/credspropagation/vsphere.go index a4cf3b2f5..bf0cf4dde 100644 --- a/internal/credspropagation/vsphere.go +++ b/internal/credspropagation/vsphere.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) func PropagateVSphereSecrets(ctx context.Context, cfg *PropagationCfg) error { diff --git a/internal/helm/release.go b/internal/helm/release.go index c30f51e7f..36e1835f9 100644 --- a/internal/helm/release.go +++ b/internal/helm/release.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) const ( diff --git a/internal/helm/repo.go b/internal/helm/repo.go index e6756a9da..69abc7a7b 100644 --- a/internal/helm/repo.go +++ b/internal/helm/repo.go @@ -25,7 +25,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) type DefaultRegistryConfig struct { diff --git a/internal/sveltos/profile.go b/internal/sveltos/profile.go index 776200c15..14e777e39 100644 --- a/internal/sveltos/profile.go +++ b/internal/sveltos/profile.go @@ -28,8 +28,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/utils" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/utils" ) type ReconcileProfileOpts struct { diff --git a/internal/sveltos/status.go b/internal/sveltos/status.go index 61bddfe3a..302cbc375 100644 --- a/internal/sveltos/status.go +++ b/internal/sveltos/status.go @@ -22,7 +22,7 @@ import ( apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - hmc "github.com/Mirantis/hmc/api/v1alpha1" + hmc "github.com/K0rdent/kcm/api/v1alpha1" ) // GetStatusConditions returns a list of conditions from provided ClusterSummary. diff --git a/internal/telemetry/event.go b/internal/telemetry/event.go index 3894a08d0..cb77d4e7c 100644 --- a/internal/telemetry/event.go +++ b/internal/telemetry/event.go @@ -17,7 +17,7 @@ package telemetry import ( "github.com/segmentio/analytics-go" - "github.com/Mirantis/hmc/internal/build" + "github.com/K0rdent/kcm/internal/build" ) const ( diff --git a/internal/telemetry/tracker.go b/internal/telemetry/tracker.go index 635ecd341..18b285ca9 100644 --- a/internal/telemetry/tracker.go +++ b/internal/telemetry/tracker.go @@ -23,7 +23,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) type Tracker struct { diff --git a/internal/webhook/accessmanagement_webhook.go b/internal/webhook/accessmanagement_webhook.go index 70178f351..a0569e9d0 100644 --- a/internal/webhook/accessmanagement_webhook.go +++ b/internal/webhook/accessmanagement_webhook.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) var errAccessManagementDeletionForbidden = errors.New("AccessManagement deletion is forbidden") diff --git a/internal/webhook/accessmanagement_webhook_test.go b/internal/webhook/accessmanagement_webhook_test.go index 67b420992..1d4d634e0 100644 --- a/internal/webhook/accessmanagement_webhook_test.go +++ b/internal/webhook/accessmanagement_webhook_test.go @@ -24,11 +24,11 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/utils" - am "github.com/Mirantis/hmc/test/objects/accessmanagement" - "github.com/Mirantis/hmc/test/objects/management" - "github.com/Mirantis/hmc/test/scheme" + "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/utils" + am "github.com/K0rdent/kcm/test/objects/accessmanagement" + "github.com/K0rdent/kcm/test/objects/management" + "github.com/K0rdent/kcm/test/scheme" ) func TestAccessManagementValidateCreate(t *testing.T) { diff --git a/internal/webhook/clusterdeployment_webhook.go b/internal/webhook/clusterdeployment_webhook.go index 2ddff3c5c..2dadeefa6 100644 --- a/internal/webhook/clusterdeployment_webhook.go +++ b/internal/webhook/clusterdeployment_webhook.go @@ -30,7 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - hmcv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" ) type ClusterDeploymentValidator struct { diff --git a/internal/webhook/clusterdeployment_webhook_test.go b/internal/webhook/clusterdeployment_webhook_test.go index 993f35390..a66cd9b8c 100644 --- a/internal/webhook/clusterdeployment_webhook_test.go +++ b/internal/webhook/clusterdeployment_webhook_test.go @@ -26,12 +26,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/test/objects/clusterdeployment" - "github.com/Mirantis/hmc/test/objects/credential" - "github.com/Mirantis/hmc/test/objects/management" - "github.com/Mirantis/hmc/test/objects/template" - "github.com/Mirantis/hmc/test/scheme" + "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/test/objects/clusterdeployment" + "github.com/K0rdent/kcm/test/objects/credential" + "github.com/K0rdent/kcm/test/objects/management" + "github.com/K0rdent/kcm/test/objects/template" + "github.com/K0rdent/kcm/test/scheme" ) var ( diff --git a/internal/webhook/management_webhook.go b/internal/webhook/management_webhook.go index 51a5764a8..d241bb6c7 100644 --- a/internal/webhook/management_webhook.go +++ b/internal/webhook/management_webhook.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - hmcv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" ) type ManagementValidator struct { diff --git a/internal/webhook/management_webhook_test.go b/internal/webhook/management_webhook_test.go index b8ce3d029..4fd99cd6e 100644 --- a/internal/webhook/management_webhook_test.go +++ b/internal/webhook/management_webhook_test.go @@ -25,12 +25,12 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/test/objects/clusterdeployment" - "github.com/Mirantis/hmc/test/objects/management" - "github.com/Mirantis/hmc/test/objects/release" - "github.com/Mirantis/hmc/test/objects/template" - "github.com/Mirantis/hmc/test/scheme" + "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/test/objects/clusterdeployment" + "github.com/K0rdent/kcm/test/objects/management" + "github.com/K0rdent/kcm/test/objects/release" + "github.com/K0rdent/kcm/test/objects/template" + "github.com/K0rdent/kcm/test/scheme" ) func TestManagementValidateCreate(t *testing.T) { diff --git a/internal/webhook/multiclusterservice_webhook.go b/internal/webhook/multiclusterservice_webhook.go index fd84a77b0..f41a9757c 100644 --- a/internal/webhook/multiclusterservice_webhook.go +++ b/internal/webhook/multiclusterservice_webhook.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) type MultiClusterServiceValidator struct { diff --git a/internal/webhook/multiclusterservice_webhook_test.go b/internal/webhook/multiclusterservice_webhook_test.go index 38905431c..31421b5e9 100644 --- a/internal/webhook/multiclusterservice_webhook_test.go +++ b/internal/webhook/multiclusterservice_webhook_test.go @@ -25,10 +25,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/test/objects/multiclusterservice" - "github.com/Mirantis/hmc/test/objects/template" - "github.com/Mirantis/hmc/test/scheme" + "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/test/objects/multiclusterservice" + "github.com/K0rdent/kcm/test/objects/template" + "github.com/K0rdent/kcm/test/scheme" ) const ( diff --git a/internal/webhook/release_webhook.go b/internal/webhook/release_webhook.go index b0a0013a0..8154ad67b 100644 --- a/internal/webhook/release_webhook.go +++ b/internal/webhook/release_webhook.go @@ -28,7 +28,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - hmcv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" ) var errManagementIsNotFound = errors.New("no Management object found") diff --git a/internal/webhook/release_webhook_test.go b/internal/webhook/release_webhook_test.go index 7982ff2a9..b50539577 100644 --- a/internal/webhook/release_webhook_test.go +++ b/internal/webhook/release_webhook_test.go @@ -25,10 +25,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/test/objects/management" - "github.com/Mirantis/hmc/test/objects/release" - "github.com/Mirantis/hmc/test/scheme" + "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/test/objects/management" + "github.com/K0rdent/kcm/test/objects/release" + "github.com/K0rdent/kcm/test/scheme" ) func TestReleaseValidateDelete(t *testing.T) { diff --git a/internal/webhook/template_webhook.go b/internal/webhook/template_webhook.go index 03dd096f8..4987ac55b 100644 --- a/internal/webhook/template_webhook.go +++ b/internal/webhook/template_webhook.go @@ -28,8 +28,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/internal/helm" + "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/helm" ) var errTemplateDeletionForbidden = errors.New("template deletion is forbidden") diff --git a/internal/webhook/template_webhook_test.go b/internal/webhook/template_webhook_test.go index d64bf7f6c..02f36442d 100644 --- a/internal/webhook/template_webhook_test.go +++ b/internal/webhook/template_webhook_test.go @@ -25,14 +25,14 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/test/objects/clusterdeployment" - "github.com/Mirantis/hmc/test/objects/management" - "github.com/Mirantis/hmc/test/objects/multiclusterservice" - "github.com/Mirantis/hmc/test/objects/release" - "github.com/Mirantis/hmc/test/objects/template" - tc "github.com/Mirantis/hmc/test/objects/templatechain" - "github.com/Mirantis/hmc/test/scheme" + "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/test/objects/clusterdeployment" + "github.com/K0rdent/kcm/test/objects/management" + "github.com/K0rdent/kcm/test/objects/multiclusterservice" + "github.com/K0rdent/kcm/test/objects/release" + "github.com/K0rdent/kcm/test/objects/template" + tc "github.com/K0rdent/kcm/test/objects/templatechain" + "github.com/K0rdent/kcm/test/scheme" ) func TestProviderTemplateValidateDelete(t *testing.T) { diff --git a/internal/webhook/templatechain_webhook.go b/internal/webhook/templatechain_webhook.go index f202780dc..572bb1bb3 100644 --- a/internal/webhook/templatechain_webhook.go +++ b/internal/webhook/templatechain_webhook.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) var errInvalidTemplateChainSpec = errors.New("the template chain spec is invalid") diff --git a/internal/webhook/templatechain_webhook_test.go b/internal/webhook/templatechain_webhook_test.go index 7a8feec97..06da07144 100644 --- a/internal/webhook/templatechain_webhook_test.go +++ b/internal/webhook/templatechain_webhook_test.go @@ -23,9 +23,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/Mirantis/hmc/api/v1alpha1" - tc "github.com/Mirantis/hmc/test/objects/templatechain" - "github.com/Mirantis/hmc/test/scheme" + "github.com/K0rdent/kcm/api/v1alpha1" + tc "github.com/K0rdent/kcm/test/objects/templatechain" + "github.com/K0rdent/kcm/test/scheme" ) func TestClusterTemplateChainValidateCreate(t *testing.T) { diff --git a/mkdocs.yml b/mkdocs.yml index 7e34a1d38..87abc8029 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,7 +2,7 @@ site_name: HMC site_author: Mirantis docs_dir: ./docs repo_name: GitHub -repo_url: https://github.com/mirantis/hmc +repo_url: https://github.com/K0rdent/kcm copyright: '© 2005 - 2024 Mirantis, Inc. All rights reserved. “Mirantis” and “FUEL” are registered trademarks of Mirantis, Inc. All other trademarks are the property of their respective owners.' nav: diff --git a/templates/provider/hmc/values.yaml b/templates/provider/hmc/values.yaml index 69fcd2e21..c7a899d0e 100644 --- a/templates/provider/hmc/values.yaml +++ b/templates/provider/hmc/values.yaml @@ -7,7 +7,7 @@ admissionWebhook: certDir: "/tmp/k8s-webhook-server/serving-certs/" controller: - defaultRegistryURL: "oci://ghcr.io/mirantis/hmc/charts" + defaultRegistryURL: "oci://ghcr.io/k0rdent/kcm/charts" registryCredsSecret: "" insecureRegistry: false createManagement: true @@ -23,7 +23,7 @@ containerSecurityContext: - ALL image: - repository: ghcr.io/mirantis/hmc/controller + repository: ghcr.io/k0rdent/kcm/controller tag: latest pullPolicy: IfNotPresent diff --git a/test/e2e/clusterdeployment/aws/aws.go b/test/e2e/clusterdeployment/aws/aws.go index 33b6f6830..61a2a0a21 100644 --- a/test/e2e/clusterdeployment/aws/aws.go +++ b/test/e2e/clusterdeployment/aws/aws.go @@ -25,8 +25,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment" - "github.com/Mirantis/hmc/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment" + "github.com/K0rdent/kcm/test/e2e/kubeclient" ) // PopulateHostedTemplateVars populates the environment variables required for diff --git a/test/e2e/clusterdeployment/azure/azure.go b/test/e2e/clusterdeployment/azure/azure.go index 2880badcf..53e27685a 100644 --- a/test/e2e/clusterdeployment/azure/azure.go +++ b/test/e2e/clusterdeployment/azure/azure.go @@ -29,8 +29,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/utils/ptr" - hmc "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/test/e2e/kubeclient" + hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/test/e2e/kubeclient" ) func getAzureInfo(ctx context.Context, name string, kc *kubeclient.KubeClient) map[string]any { diff --git a/test/e2e/clusterdeployment/clusterdeployment.go b/test/e2e/clusterdeployment/clusterdeployment.go index 4492f4dc0..75d151728 100644 --- a/test/e2e/clusterdeployment/clusterdeployment.go +++ b/test/e2e/clusterdeployment/clusterdeployment.go @@ -27,7 +27,7 @@ import ( "gopkg.in/yaml.v3" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "github.com/Mirantis/hmc/test/utils" + "github.com/K0rdent/kcm/test/utils" ) type ProviderType string diff --git a/test/e2e/clusterdeployment/clusteridentity/clusteridentity.go b/test/e2e/clusterdeployment/clusteridentity/clusteridentity.go index 461e629cb..08068b15b 100644 --- a/test/e2e/clusterdeployment/clusteridentity/clusteridentity.go +++ b/test/e2e/clusterdeployment/clusteridentity/clusteridentity.go @@ -28,8 +28,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment" - "github.com/Mirantis/hmc/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment" + "github.com/K0rdent/kcm/test/e2e/kubeclient" ) type ClusterIdentity struct { diff --git a/test/e2e/clusterdeployment/common.go b/test/e2e/clusterdeployment/common.go index 9eb59211c..02b4a7e56 100644 --- a/test/e2e/clusterdeployment/common.go +++ b/test/e2e/clusterdeployment/common.go @@ -26,7 +26,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" - "github.com/Mirantis/hmc/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/e2e/kubeclient" ) // PatchHostedClusterReady patches a hosted clusters' infrastructure resource diff --git a/test/e2e/clusterdeployment/providervalidator.go b/test/e2e/clusterdeployment/providervalidator.go index 7ca81d1d2..9d4ee121d 100644 --- a/test/e2e/clusterdeployment/providervalidator.go +++ b/test/e2e/clusterdeployment/providervalidator.go @@ -20,7 +20,7 @@ import ( . "github.com/onsi/ginkgo/v2" - "github.com/Mirantis/hmc/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/e2e/kubeclient" ) // ProviderValidator is a struct that contains the necessary information to diff --git a/test/e2e/clusterdeployment/validate_deleted.go b/test/e2e/clusterdeployment/validate_deleted.go index 1789ec879..fdeb6172f 100644 --- a/test/e2e/clusterdeployment/validate_deleted.go +++ b/test/e2e/clusterdeployment/validate_deleted.go @@ -22,9 +22,9 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "github.com/Mirantis/hmc/internal/utils/status" - "github.com/Mirantis/hmc/test/e2e/kubeclient" - "github.com/Mirantis/hmc/test/utils" + "github.com/K0rdent/kcm/internal/utils/status" + "github.com/K0rdent/kcm/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/utils" ) // validateClusterDeleted validates that the Cluster resource has been deleted. diff --git a/test/e2e/clusterdeployment/validate_deployed.go b/test/e2e/clusterdeployment/validate_deployed.go index 7f750ecc1..1dbcd7885 100644 --- a/test/e2e/clusterdeployment/validate_deployed.go +++ b/test/e2e/clusterdeployment/validate_deployed.go @@ -27,9 +27,9 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/Mirantis/hmc/internal/utils/status" - "github.com/Mirantis/hmc/test/e2e/kubeclient" - "github.com/Mirantis/hmc/test/utils" + "github.com/K0rdent/kcm/internal/utils/status" + "github.com/K0rdent/kcm/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/utils" ) // resourceValidationFunc is intended to validate a specific kubernetes diff --git a/test/e2e/clusterdeployment/vsphere/vsphere.go b/test/e2e/clusterdeployment/vsphere/vsphere.go index a708ef0e4..71d0395e1 100644 --- a/test/e2e/clusterdeployment/vsphere/vsphere.go +++ b/test/e2e/clusterdeployment/vsphere/vsphere.go @@ -15,7 +15,7 @@ package vsphere import ( - "github.com/Mirantis/hmc/test/e2e/clusterdeployment" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment" ) func CheckEnv() { diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index 79466577d..cccd0e70f 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -32,10 +32,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" - internalutils "github.com/Mirantis/hmc/internal/utils" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment" - "github.com/Mirantis/hmc/test/e2e/kubeclient" - "github.com/Mirantis/hmc/test/utils" + internalutils "github.com/K0rdent/kcm/internal/utils" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment" + "github.com/K0rdent/kcm/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/utils" ) // Run e2e tests using the Ginkgo runner. diff --git a/test/e2e/kubeclient/kubeclient.go b/test/e2e/kubeclient/kubeclient.go index 45e8fdb97..760426ae4 100644 --- a/test/e2e/kubeclient/kubeclient.go +++ b/test/e2e/kubeclient/kubeclient.go @@ -33,7 +33,7 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - "github.com/Mirantis/hmc/internal/utils/status" + "github.com/K0rdent/kcm/internal/utils/status" ) type KubeClient struct { diff --git a/test/e2e/provider_aws_test.go b/test/e2e/provider_aws_test.go index 276689032..5f11a1061 100644 --- a/test/e2e/provider_aws_test.go +++ b/test/e2e/provider_aws_test.go @@ -24,12 +24,12 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - internalutils "github.com/Mirantis/hmc/internal/utils" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment/aws" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment/clusteridentity" - "github.com/Mirantis/hmc/test/e2e/kubeclient" - "github.com/Mirantis/hmc/test/utils" + internalutils "github.com/K0rdent/kcm/internal/utils" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment/aws" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment/clusteridentity" + "github.com/K0rdent/kcm/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/utils" ) var _ = Describe("AWS Templates", Label("provider:cloud", "provider:aws"), Ordered, func() { diff --git a/test/e2e/provider_azure_test.go b/test/e2e/provider_azure_test.go index 2b1bbb5b1..401aba31a 100644 --- a/test/e2e/provider_azure_test.go +++ b/test/e2e/provider_azure_test.go @@ -24,12 +24,12 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - internalutils "github.com/Mirantis/hmc/internal/utils" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment/azure" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment/clusteridentity" - "github.com/Mirantis/hmc/test/e2e/kubeclient" - "github.com/Mirantis/hmc/test/utils" + internalutils "github.com/K0rdent/kcm/internal/utils" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment/azure" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment/clusteridentity" + "github.com/K0rdent/kcm/test/e2e/kubeclient" + "github.com/K0rdent/kcm/test/utils" ) var _ = Context("Azure Templates", Label("provider:cloud", "provider:azure"), Ordered, func() { diff --git a/test/e2e/provider_vsphere_test.go b/test/e2e/provider_vsphere_test.go index ea9ef55fe..a4f54b3a6 100644 --- a/test/e2e/provider_vsphere_test.go +++ b/test/e2e/provider_vsphere_test.go @@ -22,11 +22,11 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - internalutils "github.com/Mirantis/hmc/internal/utils" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment/clusteridentity" - "github.com/Mirantis/hmc/test/e2e/clusterdeployment/vsphere" - "github.com/Mirantis/hmc/test/e2e/kubeclient" + internalutils "github.com/K0rdent/kcm/internal/utils" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment/clusteridentity" + "github.com/K0rdent/kcm/test/e2e/clusterdeployment/vsphere" + "github.com/K0rdent/kcm/test/e2e/kubeclient" ) var _ = Context("vSphere Templates", Label("provider:onprem", "provider:vsphere"), Ordered, func() { diff --git a/test/objects/accessmanagement/accessmanagement.go b/test/objects/accessmanagement/accessmanagement.go index f7a94c2fc..11154d713 100644 --- a/test/objects/accessmanagement/accessmanagement.go +++ b/test/objects/accessmanagement/accessmanagement.go @@ -17,7 +17,7 @@ package accessmanagement import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) const ( diff --git a/test/objects/clusterdeployment/clusterdeployment.go b/test/objects/clusterdeployment/clusterdeployment.go index 777572d86..87f5a6432 100644 --- a/test/objects/clusterdeployment/clusterdeployment.go +++ b/test/objects/clusterdeployment/clusterdeployment.go @@ -18,7 +18,7 @@ import ( apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) const ( diff --git a/test/objects/credential/credential.go b/test/objects/credential/credential.go index 4e495fa8b..106f4531f 100644 --- a/test/objects/credential/credential.go +++ b/test/objects/credential/credential.go @@ -18,7 +18,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) const ( diff --git a/test/objects/management/management.go b/test/objects/management/management.go index 67ad95970..25ec35967 100644 --- a/test/objects/management/management.go +++ b/test/objects/management/management.go @@ -17,8 +17,8 @@ package management import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/Mirantis/hmc/api/v1alpha1" - "github.com/Mirantis/hmc/test/objects/release" + "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/test/objects/release" ) const ( diff --git a/test/objects/multiclusterservice/multiclusterservice.go b/test/objects/multiclusterservice/multiclusterservice.go index cc6aec977..4328cf2b5 100644 --- a/test/objects/multiclusterservice/multiclusterservice.go +++ b/test/objects/multiclusterservice/multiclusterservice.go @@ -17,7 +17,7 @@ package multiclusterservice import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) const ( diff --git a/test/objects/release/release.go b/test/objects/release/release.go index e34a76d1b..fabff3bd4 100644 --- a/test/objects/release/release.go +++ b/test/objects/release/release.go @@ -17,7 +17,7 @@ package release import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) const ( diff --git a/test/objects/template/template.go b/test/objects/template/template.go index 3699a4583..dbe72f432 100644 --- a/test/objects/template/template.go +++ b/test/objects/template/template.go @@ -21,7 +21,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) const ( diff --git a/test/objects/templatechain/templatechain.go b/test/objects/templatechain/templatechain.go index 4876e865b..0d90dac65 100644 --- a/test/objects/templatechain/templatechain.go +++ b/test/objects/templatechain/templatechain.go @@ -17,7 +17,7 @@ package templatechain import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) const ( diff --git a/test/scheme/scheme.go b/test/scheme/scheme.go index d0155c616..6c1046ccb 100644 --- a/test/scheme/scheme.go +++ b/test/scheme/scheme.go @@ -22,7 +22,7 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" - "github.com/Mirantis/hmc/api/v1alpha1" + "github.com/K0rdent/kcm/api/v1alpha1" ) var ( diff --git a/test/utils/utils.go b/test/utils/utils.go index 56ce5ee33..96c5e52e2 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -25,7 +25,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "github.com/Mirantis/hmc/internal/utils/status" + "github.com/K0rdent/kcm/internal/utils/status" ) const ( From 808c43a84a08a2504865627fe96095271142e43e Mon Sep 17 00:00:00 2001 From: Aleksei Sizov <45825279+a13x5@users.noreply.github.com> Date: Fri, 3 Jan 2025 18:34:53 -0500 Subject: [PATCH 02/14] Add package write permissions to build/release workflows (#858) --- .github/workflows/build_test.yml | 2 ++ .github/workflows/release.yml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml index 7256958dc..ce701771f 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build_test.yml @@ -31,6 +31,8 @@ jobs: version: ${{ steps.vars.outputs.version }} clustername: ${{ steps.vars.outputs.clustername }} pr: ${{ steps.pr.outputs.result }} + permissions: + packages: write steps: - name: Get PR ref uses: actions/github-script@v7 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 39ac3aede..378bb86de 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,6 +5,9 @@ on: tags: - "*" +permissions: + packages: write + jobs: release: runs-on: ubuntu-latest From 97a3a1f4f8af824d78301c237257f681b873e64e Mon Sep 17 00:00:00 2001 From: Aleksei Sizov <45825279+a13x5@users.noreply.github.com> Date: Fri, 3 Jan 2025 18:54:51 -0500 Subject: [PATCH 03/14] Update templates for release 0.0.6 (#857) --- README.md | 4 ++-- templates/provider/hmc-templates/Chart.yaml | 2 +- templates/provider/hmc-templates/files/release.yaml | 6 +++--- templates/provider/hmc-templates/files/templates/hmc.yaml | 4 ++-- templates/provider/hmc/Chart.yaml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 8a8f0e768..6662abb6f 100644 --- a/README.md +++ b/README.md @@ -20,13 +20,13 @@ Detailed documentation is available in [Project 0x2A Docs](https://mirantis.gith ### TL;DR ```bash -kubectl apply -f https://github.com/K0rdent/kcm/releases/download/v0.0.5/install.yaml +kubectl apply -f https://github.com/K0rdent/kcm/releases/download/v0.0.6/install.yaml ``` or install using `helm` ```bash -helm install hmc oci://ghcr.io/k0rdent/kcm/charts/hmc --version 0.0.5 -n hmc-system --create-namespace +helm install hmc oci://ghcr.io/k0rdent/kcm/charts/hmc --version 0.0.6 -n hmc-system --create-namespace ``` Then follow the [Deploy a cluster deployment](#deploy-a-cluster-deployment) guide to diff --git a/templates/provider/hmc-templates/Chart.yaml b/templates/provider/hmc-templates/Chart.yaml index 29a97e1fa..e2317878c 100644 --- a/templates/provider/hmc-templates/Chart.yaml +++ b/templates/provider/hmc-templates/Chart.yaml @@ -13,4 +13,4 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.5 +version: 0.0.6 diff --git a/templates/provider/hmc-templates/files/release.yaml b/templates/provider/hmc-templates/files/release.yaml index 277a2f3fb..45ed38bae 100644 --- a/templates/provider/hmc-templates/files/release.yaml +++ b/templates/provider/hmc-templates/files/release.yaml @@ -1,13 +1,13 @@ apiVersion: hmc.mirantis.com/v1alpha1 kind: Release metadata: - name: hmc-0-0-5 + name: hmc-0-0-6 annotations: helm.sh/resource-policy: keep spec: - version: 0.0.5 + version: 0.0.6 hmc: - template: hmc-0-0-5 + template: hmc-0-0-6 capi: template: cluster-api-0-0-6 providers: diff --git a/templates/provider/hmc-templates/files/templates/hmc.yaml b/templates/provider/hmc-templates/files/templates/hmc.yaml index 8beb29aef..91d8bc2eb 100644 --- a/templates/provider/hmc-templates/files/templates/hmc.yaml +++ b/templates/provider/hmc-templates/files/templates/hmc.yaml @@ -1,14 +1,14 @@ apiVersion: hmc.mirantis.com/v1alpha1 kind: ProviderTemplate metadata: - name: hmc-0-0-5 + name: hmc-0-0-6 annotations: helm.sh/resource-policy: keep spec: helm: chartSpec: chart: hmc - version: 0.0.5 + version: 0.0.6 interval: 10m0s sourceRef: kind: HelmRepository diff --git a/templates/provider/hmc/Chart.yaml b/templates/provider/hmc/Chart.yaml index 1826ef840..405aa5ee1 100644 --- a/templates/provider/hmc/Chart.yaml +++ b/templates/provider/hmc/Chart.yaml @@ -13,7 +13,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.5 +version: 0.0.6 dependencies: - name: flux2 From 2bbd96952eea77898bfda88d465bfd4eed1c323d Mon Sep 17 00:00:00 2001 From: Aleksei Sizov Date: Fri, 3 Jan 2025 19:26:41 -0500 Subject: [PATCH 04/14] Release workflow permission fix --- .github/workflows/release.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 378bb86de..e782e62c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,12 +5,11 @@ on: tags: - "*" -permissions: - packages: write - jobs: release: runs-on: ubuntu-latest + permissions: + packages: write steps: - name: Checkout uses: actions/checkout@v4 From e01778de9474eb3928b2b63914b0a93ccb56c4d2 Mon Sep 17 00:00:00 2001 From: Aleksei Sizov Date: Fri, 3 Jan 2025 20:30:30 -0500 Subject: [PATCH 05/14] Add contents permissions for release workflow --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e782e62c5..a8b24de20 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,7 @@ jobs: runs-on: ubuntu-latest permissions: packages: write + contents: write steps: - name: Checkout uses: actions/checkout@v4 From 7216c7a3964f95a0dbbdcd45e7925802a2d9192c Mon Sep 17 00:00:00 2001 From: Josef Hak Date: Mon, 6 Jan 2025 10:34:52 +0100 Subject: [PATCH 06/14] Fix doc link (#859) --- README.md | 2 +- docs/dev.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6662abb6f..792b809fc 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ in real life! ## Documentation -Detailed documentation is available in [Project 0x2A Docs](https://mirantis.github.io/project-2a-docs/) +Detailed documentation is available in [K0rdent Docs](https://k0rdent.github.io/docs) ## Installation diff --git a/docs/dev.md b/docs/dev.md index 0fddbc2b5..d6f2b13ef 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -8,7 +8,7 @@ a managed cluster on AWS with k0s for testing. The kind cluster acts as manageme ### Clone HMC repository ```bash -git clone https://github.com/K0rdent/kcm.git && cd hmc +git clone https://github.com/K0rdent/kcm.git && cd kcm ``` ### Install required CLIs From b7bd7fed59a0d39f9f40adf2be2e83af3e056c36 Mon Sep 17 00:00:00 2001 From: Josef Hak Date: Mon, 6 Jan 2025 11:19:55 +0100 Subject: [PATCH 07/14] Fix credential doc link (#861) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 792b809fc..f43a61312 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ To create a ClusterDeployment: 1. Create `Credential` object with all credentials required. - See [Credential system docs](https://mirantis.github.io/project-2a-docs/credential/main) + See [Credential system docs](https://k0rdent.github.io/docs/credential/main) for more information regarding this object. 2. Select the `ClusterTemplate` you want to use for the deployment. To list all From a44ad4279796bd686a9d970e0393ee7e2bb1a501 Mon Sep 17 00:00:00 2001 From: Michael Morgen Date: Mon, 6 Jan 2025 14:08:59 +0100 Subject: [PATCH 08/14] Backup implementation part 1 (#815) * new component labels on most components * wide range of new RBAC permission for the backup ctrl * velero stack reconciliation * adjusted backup user-facing roles * added backup ctrl configuration in the hmc chart * removed schema defaults in favor of mutation --- .golangci.yml | 2 +- api/v1alpha1/backup_types.go | 10 +- api/v1alpha1/management_types.go | 6 +- api/v1alpha1/zz_generated.deepcopy.go | 2 +- cmd/main.go | 14 +- config/dev/aws-clusterdeployment.yaml | 2 + config/dev/aws-credentials.yaml | 6 + config/dev/azure-clusterdeployment.yaml | 2 + config/dev/azure-credentials.yaml | 5 + config/dev/eks-clusterdeployment.yaml | 2 + config/dev/vsphere-clusterdeployment.yaml | 2 + config/dev/vsphere-credentials.yaml | 6 + go.mod | 24 +- go.sum | 81 ++-- hack/templates.sh | 2 + .../controller/accessmanagement_controller.go | 6 + internal/controller/backup/install.go | 445 ++++++++++++++++++ internal/controller/backup/oneshot.go | 30 ++ internal/controller/backup/schedule.go | 30 ++ internal/controller/backup/type.go | 62 +++ internal/controller/backup_controller.go | 146 +++++- internal/controller/backup_controller_test.go | 20 +- .../clusterdeployment_controller.go | 6 + internal/controller/credential_controller.go | 6 + internal/controller/management_controller.go | 5 + .../multiclusterservice_controller.go | 8 + .../multiclusterservice_controller_test.go | 7 +- internal/controller/release_controller.go | 6 + internal/controller/template_controller.go | 23 + .../controller/template_controller_test.go | 1 + .../controller/templatechain_controller.go | 5 + .../templatechain_controller_test.go | 10 + internal/utils/label.go | 53 +++ internal/utils/label_test.go | 92 ++++ internal/webhook/management_webhook.go | 11 +- internal/webhook/management_webhook_test.go | 54 +++ .../provider/hmc-templates/files/release.yaml | 2 + .../templates/adopted-cluster-0-0-1.yaml | 2 + .../files/templates/aws-eks-0-0-2.yaml | 2 + .../files/templates/aws-hosted-cp-0-0-3.yaml | 2 + .../templates/aws-standalone-cp-0-0-4.yaml | 2 + .../files/templates/azure-aks-0-0-1.yaml | 2 + .../templates/azure-hosted-cp-0-0-3.yaml | 2 + .../templates/azure-standalone-cp-0-0-4.yaml | 2 + .../files/templates/cert-manager-1-16-2.yaml | 2 + .../templates/cluster-api-provider-aws.yaml | 2 + .../templates/cluster-api-provider-azure.yaml | 2 + .../cluster-api-provider-openstack.yaml | 2 + .../cluster-api-provider-vsphere.yaml | 2 + .../files/templates/cluster-api.yaml | 2 + .../files/templates/dex-0-19-1.yaml | 2 + .../templates/external-secrets-0-11-0.yaml | 2 + .../hmc-templates/files/templates/hmc.yaml | 2 + .../files/templates/ingress-nginx-4-11-0.yaml | 2 + .../files/templates/ingress-nginx-4-11-3.yaml | 2 + .../files/templates/k0smotron.yaml | 2 + .../files/templates/kyverno-3-2-6.yaml | 2 + .../openstack-standalone-cp-0-0-1.yaml | 2 + .../files/templates/projectsveltos.yaml | 2 + .../files/templates/velero-8-1-0.yaml | 2 + .../templates/vsphere-hosted-cp-0-0-3.yaml | 2 + .../vsphere-standalone-cp-0-0-3.yaml | 2 + templates/provider/hmc/templates/_helpers.tpl | 9 + .../crds/hmc.mirantis.com_managements.yaml | 4 - .../provider/hmc/templates/deployment.yaml | 8 + .../hmc/templates/rbac/controller/roles.yaml | 48 +- .../rbac/user-facing/backup-editor.yaml | 5 + .../rbac/user-facing/backup-viewer.yaml | 5 + templates/provider/hmc/values.yaml | 8 + test/objects/management/management.go | 6 + 70 files changed, 1252 insertions(+), 85 deletions(-) create mode 100644 internal/controller/backup/install.go create mode 100644 internal/controller/backup/oneshot.go create mode 100644 internal/controller/backup/schedule.go create mode 100644 internal/controller/backup/type.go create mode 100644 internal/utils/label.go create mode 100644 internal/utils/label_test.go diff --git a/.golangci.yml b/.golangci.yml index 4330eae8b..1a29c45a3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -24,7 +24,7 @@ issues: path: (.*_test\.go|test\/|api\/?.*\/.*_types\.go) # ignore tests, and k8s API-specific files linters: - govet - - text: "max-public-structs: you have exceeded the maximum number of public struct declarations" + - text: "max-public-structs: you have exceeded the maximum number.*of public struct declarations" linters: - revive path: api/ # the api/ pkgs have lots of structs diff --git a/api/v1alpha1/backup_types.go b/api/v1alpha1/backup_types.go index 71dc17fc5..561a6c273 100644 --- a/api/v1alpha1/backup_types.go +++ b/api/v1alpha1/backup_types.go @@ -15,11 +15,19 @@ package v1alpha1 import ( - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + velerov1 "github.com/zerospiel/velero/pkg/apis/velero/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ( + // Name to label most of the HMC-related components. + // Mostly utilized by the backup feature. + GenericComponentLabelName = "hmc.mirantis.com/component" + // Component label value for the HMC-related components. + GenericComponentLabelValueHMC = "hmc" +) + // BackupSpec defines the desired state of Backup type BackupSpec struct { // Oneshot indicates whether the Backup should not be scheduled diff --git a/api/v1alpha1/management_types.go b/api/v1alpha1/management_types.go index 645bf3a65..618c5d19d 100644 --- a/api/v1alpha1/management_types.go +++ b/api/v1alpha1/management_types.go @@ -57,20 +57,16 @@ type Core struct { // ManagementBackup enables a feature to backup HMC objects into a cloud. type ManagementBackup struct { - // +kubebuilder:default="0 */6 * * *" - // Schedule is a Cron expression defining when to run the scheduled Backup. // Default value is to backup every 6 hours. Schedule string `json:"schedule,omitempty"` - // +kubebuilder:default=false - // Flag to indicate whether the backup feature is enabled. // If set to true, [Velero] platform will be installed. // If set to false, creation or modification of Backups/Restores will be blocked. // // [Velero]: https://velero.io - Enabled bool `json:"enabled"` + Enabled bool `json:"enabled,omitempty"` } // Component represents HMC management component diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index aba31457a..75d485b31 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -21,7 +21,7 @@ package v1alpha1 import ( "github.com/fluxcd/helm-controller/api/v2" apiv1 "github.com/fluxcd/source-controller/api/v1" - velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" + velerov1 "github.com/zerospiel/velero/pkg/apis/velero/v1" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/cmd/main.go b/cmd/main.go index 5a24c834b..66e6f88c1 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -22,6 +22,10 @@ import ( hcv2 "github.com/fluxcd/helm-controller/api/v2" sourcev1 "github.com/fluxcd/source-controller/api/v1" sveltosv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1" + velerov1api "github.com/zerospiel/velero/pkg/apis/velero/v1" + velerov2alpha1api "github.com/zerospiel/velero/pkg/apis/velero/v2alpha1" + apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/client-go/dynamic" @@ -52,6 +56,15 @@ var ( func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + // velero deps + utilruntime.Must(velerov1api.AddToScheme(scheme)) + utilruntime.Must(velerov2alpha1api.AddToScheme(scheme)) + utilruntime.Must(apiextv1.AddToScheme(scheme)) + utilruntime.Must(apiextv1beta1.AddToScheme(scheme)) + // WARN: if snapshot is to be used, then the following resources should also be added to the scheme + // snapshotv1api.AddToScheme(scheme) // snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1" + // velero deps + utilruntime.Must(hmcmirantiscomv1alpha1.AddToScheme(scheme)) utilruntime.Must(sourcev1.AddToScheme(scheme)) utilruntime.Must(hcv2.AddToScheme(scheme)) @@ -307,7 +320,6 @@ func main() { // TODO (zerospiel): disabled until the #605 // if err = (&controller.BackupReconciler{ // Client: mgr.GetClient(), - // Scheme: mgr.GetScheme(), // }).SetupWithManager(mgr); err != nil { // setupLog.Error(err, "unable to create controller", "controller", "Backup") // os.Exit(1) diff --git a/config/dev/aws-clusterdeployment.yaml b/config/dev/aws-clusterdeployment.yaml index c4c65ebbd..391b5e5a7 100644 --- a/config/dev/aws-clusterdeployment.yaml +++ b/config/dev/aws-clusterdeployment.yaml @@ -3,6 +3,8 @@ kind: ClusterDeployment metadata: name: aws-dev namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: template: aws-standalone-cp-0-0-4 credential: aws-cluster-identity-cred diff --git a/config/dev/aws-credentials.yaml b/config/dev/aws-credentials.yaml index c85d6c8bc..772c94117 100644 --- a/config/dev/aws-credentials.yaml +++ b/config/dev/aws-credentials.yaml @@ -4,6 +4,8 @@ kind: AWSClusterStaticIdentity metadata: name: aws-cluster-identity namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: secretRef: aws-cluster-identity-secret allowedNamespaces: @@ -15,6 +17,8 @@ kind: Secret metadata: name: aws-cluster-identity-secret namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc type: Opaque stringData: AccessKeyID: ${AWS_ACCESS_KEY_ID} @@ -26,6 +30,8 @@ kind: Credential metadata: name: aws-cluster-identity-cred namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: description: AWS credentials identityRef: diff --git a/config/dev/azure-clusterdeployment.yaml b/config/dev/azure-clusterdeployment.yaml index 99d68ec6c..195e06b17 100644 --- a/config/dev/azure-clusterdeployment.yaml +++ b/config/dev/azure-clusterdeployment.yaml @@ -3,6 +3,8 @@ kind: ClusterDeployment metadata: name: azure-dev namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: template: azure-standalone-cp-0-0-4 credential: azure-cluster-identity-cred diff --git a/config/dev/azure-credentials.yaml b/config/dev/azure-credentials.yaml index e2416dc41..e3c72f4e4 100644 --- a/config/dev/azure-credentials.yaml +++ b/config/dev/azure-credentials.yaml @@ -4,6 +4,7 @@ kind: AzureClusterIdentity metadata: labels: clusterctl.cluster.x-k8s.io/move-hierarchy: "true" + hmc.mirantis.com/component: hmc name: azure-cluster-identity namespace: ${NAMESPACE} spec: @@ -20,6 +21,8 @@ kind: Secret metadata: name: azure-cluster-identity-secret namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc stringData: clientSecret: "${AZURE_CLIENT_SECRET}" type: Opaque @@ -29,6 +32,8 @@ kind: Credential metadata: name: azure-cluster-identity-cred namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: description: Azure credentials identityRef: diff --git a/config/dev/eks-clusterdeployment.yaml b/config/dev/eks-clusterdeployment.yaml index 8973e7ffd..696ec6a8f 100644 --- a/config/dev/eks-clusterdeployment.yaml +++ b/config/dev/eks-clusterdeployment.yaml @@ -3,6 +3,8 @@ kind: ClusterDeployment metadata: name: eks-dev namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: template: aws-eks-0-0-2 credential: "aws-cluster-identity-cred" diff --git a/config/dev/vsphere-clusterdeployment.yaml b/config/dev/vsphere-clusterdeployment.yaml index 833c7272a..09c091674 100644 --- a/config/dev/vsphere-clusterdeployment.yaml +++ b/config/dev/vsphere-clusterdeployment.yaml @@ -3,6 +3,8 @@ kind: ClusterDeployment metadata: name: vsphere-dev namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: template: vsphere-standalone-cp-0-0-3 credential: vsphere-cluster-identity-cred diff --git a/config/dev/vsphere-credentials.yaml b/config/dev/vsphere-credentials.yaml index 98f065d16..1653ea940 100644 --- a/config/dev/vsphere-credentials.yaml +++ b/config/dev/vsphere-credentials.yaml @@ -4,6 +4,8 @@ kind: VSphereClusterIdentity metadata: name: vsphere-cluster-identity namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: secretName: vsphere-cluster-identity-secret allowedNamespaces: @@ -15,6 +17,8 @@ kind: Secret metadata: name: vsphere-cluster-identity-secret namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc stringData: username: ${VSPHERE_USER} password: ${VSPHERE_PASSWORD} @@ -24,6 +28,8 @@ kind: Credential metadata: name: vsphere-cluster-identity-cred namespace: ${NAMESPACE} + labels: + hmc.mirantis.com/component: hmc spec: description: vSphere credentials identityRef: diff --git a/go.mod b/go.mod index 6952b610d..f877bafca 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/projectsveltos/libsveltos v0.44.0 github.com/segmentio/analytics-go v3.1.0+incompatible github.com/stretchr/testify v1.10.0 - github.com/vmware-tanzu/velero v1.15.1 + github.com/zerospiel/velero v0.0.0-20241213181215-1eaa894d12b8 gopkg.in/yaml.v3 v3.0.1 helm.sh/helm/v3 v3.16.4 k8s.io/api v0.31.4 @@ -39,7 +39,7 @@ require ( require ( dario.cat/mergo v1.0.1 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect @@ -109,7 +109,10 @@ require ( github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/huandu/xstrings v1.5.0 // indirect github.com/imdario/mergo v0.3.16 // indirect @@ -117,8 +120,9 @@ require ( github.com/jmoiron/sqlx v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.10 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lib/pq v1.10.9 // indirect @@ -128,6 +132,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/locker v1.0.1 // indirect @@ -138,6 +143,7 @@ require ( github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect + github.com/oklog/run v1.0.0 // indirect github.com/opencontainers/go-digest/blake3 v0.0.0-20240426182413-22b78e47854a // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect @@ -145,7 +151,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.60.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rubenv/sql-migrate v1.7.0 // indirect @@ -166,9 +172,9 @@ require ( github.com/yuin/gopher-lua v1.1.1 // indirect github.com/zeebo/blake3 v0.2.4 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect - go.opentelemetry.io/otel v1.30.0 // indirect - go.opentelemetry.io/otel/metric v1.30.0 // indirect - go.opentelemetry.io/otel/trace v1.30.0 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.31.0 // indirect @@ -183,8 +189,8 @@ require ( golang.org/x/time v0.8.0 // indirect golang.org/x/tools v0.28.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect - google.golang.org/grpc v1.67.1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/grpc v1.68.0 // indirect google.golang.org/protobuf v1.36.1 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 705357dfd..e4f65c9f7 100644 --- a/go.sum +++ b/go.sum @@ -5,10 +5,10 @@ filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4 github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4= @@ -65,6 +65,8 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cert-manager/cert-manager v1.16.2 h1:c9UU2E+8XWGruyvC/mdpc1wuLddtgmNr8foKdP7a8Jg= @@ -133,6 +135,7 @@ github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0 github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -252,6 +255,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1 github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -262,6 +267,8 @@ github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGN github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU= github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= @@ -282,6 +289,8 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6 github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -293,8 +302,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= -github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -306,6 +315,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0 h1:j3YK74myEQRxR/srciTpOrm221SAvz6J5OVWbyfeXFo= +github.com/kubernetes-csi/external-snapshotter/client/v7 v7.0.0/go.mod h1:FlyYFe32mPxKEPaRXKNxfX576d1AoCzstYDoOOnyMA4= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= @@ -318,8 +329,12 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhn github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -332,6 +347,8 @@ github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= @@ -360,6 +377,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= @@ -399,8 +418,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= -github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= @@ -432,6 +451,8 @@ github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+D github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= @@ -453,12 +474,11 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P 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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/vmware-tanzu/velero v1.15.1 h1:kKT4I6ZMQn+aiPYIalF+0Ui8VLbt9XK+3jwnCU09T0M= -github.com/vmware-tanzu/velero v1.15.1/go.mod h1:bZbnBC9OcwXfsovU0uCHwPlbm3ba8N9fwvBkwnU2vls= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -483,14 +503,16 @@ github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI= github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE= github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= +github.com/zerospiel/velero v0.0.0-20241213181215-1eaa894d12b8 h1:26qmmcPx/o0wAxJY/q6u9atuJ8joHf523SeRi+24u/o= +github.com/zerospiel/velero v0.0.0-20241213181215-1eaa894d12b8/go.mod h1:k7TYpNEgFVIXGHwtK26LnGefF9r62pSams2/pPjhq/E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/exporters/autoexport v0.46.1 h1:ysCfPZB9AjUlMa1UHYup3c9dAOCMQX/6sxSfPBUoxHw= go.opentelemetry.io/contrib/exporters/autoexport v0.46.1/go.mod h1:ha0aiYm+DOPsLHjh0zoQ8W8sLT+LJ58J3j47lGpSLrU= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= -go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= -go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.44.0 h1:bflGWrfYyuulcdxf14V6n9+CoQcu5SAAdHmDPAJnlps= @@ -507,14 +529,14 @@ go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.44.0 h1:dEZWPjVN22urgY go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.44.0/go.mod h1:sTt30Evb7hJB/gEk27qLb1+l9n4Tb8HvHkR0Wx3S6CU= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 h1:VhlEQAPp9R1ktYfrPk5SOryw1e9LDDTZCbIPFrho0ec= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0/go.mod h1:kB3ufRbfU+CQ4MlUcqtW8Z7YEOBeK2DJ6CmR5rYYF3E= -go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= -go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= -go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= -go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= -go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI= -go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw= -go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= -go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= +go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -573,10 +595,15 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h 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-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -620,13 +647,13 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU= -google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 h1:fVoAXEKA4+yufmbdVYv+SE73+cPZbbbe8paLsHfkK+U= -google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= -google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28 h1:KJjNNclfpIkVqrZlTWcgOOaVQ00LdBnoEaRfkUx760s= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/hack/templates.sh b/hack/templates.sh index ac73ed156..da1f2b6dd 100755 --- a/hack/templates.sh +++ b/hack/templates.sh @@ -45,6 +45,8 @@ metadata: name: $template_name annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/internal/controller/accessmanagement_controller.go b/internal/controller/accessmanagement_controller.go index 1f028e1b0..c8745e1fc 100644 --- a/internal/controller/accessmanagement_controller.go +++ b/internal/controller/accessmanagement_controller.go @@ -28,6 +28,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/utils" ) // AccessManagementReconciler reconciles an AccessManagement object @@ -52,6 +53,11 @@ func (r *AccessManagementReconciler) Reconcile(ctx context.Context, req ctrl.Req return ctrl.Result{}, err } + if err := utils.AddHMCComponentLabel(ctx, r.Client, accessMgmt); err != nil { + l.Error(err, "adding component label") + return ctrl.Result{}, err + } + defer func() { statusErr := "" if err != nil { diff --git a/internal/controller/backup/install.go b/internal/controller/backup/install.go new file mode 100644 index 000000000..69d89fc60 --- /dev/null +++ b/internal/controller/backup/install.go @@ -0,0 +1,445 @@ +// Copyright 2024 +// +// 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 backup + +import ( + "context" + "fmt" + "io" + "time" + + velerov1api "github.com/zerospiel/velero/pkg/apis/velero/v1" + veleroclient "github.com/zerospiel/velero/pkg/client" + veleroinstall "github.com/zerospiel/velero/pkg/install" + "github.com/zerospiel/velero/pkg/uploader" + "github.com/zerospiel/velero/pkg/util/kube" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +type Config struct { + kubeRestConfig *rest.Config + cl client.Client + + image string + systemNamespace string + features []string + + requeueAfter time.Duration +} + +const veleroName = "velero" + +type ConfigOpt func(*Config) + +func NewConfig(cl client.Client, kc *rest.Config, opts ...ConfigOpt) *Config { + c := newWithDefaults() + + for _, o := range opts { + o(c) + } + + c.cl = cl + c.kubeRestConfig = kc + + return c +} + +func WithRequeueAfter(d time.Duration) ConfigOpt { + return func(c *Config) { + if d == 0 { + return + } + c.requeueAfter = d + } +} + +func WithVeleroSystemNamespace(ns string) ConfigOpt { + return func(c *Config) { + if len(ns) == 0 { + return + } + c.systemNamespace = ns + } +} + +func WithVeleroImage(image string) ConfigOpt { + return func(c *Config) { + if len(image) == 0 { + return + } + c.image = image + } +} + +func WithFeatures(features ...string) ConfigOpt { + return func(c *Config) { + if len(features) == 0 { + return + } + c.features = features + } +} + +func newWithDefaults() *Config { + return &Config{ + requeueAfter: 5 * time.Second, + systemNamespace: veleroName, + image: fmt.Sprintf("%s/%s:%s", veleroName, veleroName, "v1.15.0"), // velero/velero:v1.15.0 + } +} + +// ReconcileVeleroInstallation reconciles installation of velero stack within a management cluster. +func (c *Config) ReconcileVeleroInstallation(ctx context.Context) (ctrl.Result, error) { + deployState, err := c.checkVeleroDeployIsInstalled(ctx) + if err != nil { + return ctrl.Result{}, fmt.Errorf("failed to determine if velero is installed: %w", err) + } + + if deployState.needInstallation { + ctrl.LoggerFrom(ctx).Info("Installing velero stack") + if err := c.installVelero(ctx); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to perform velero stack installation: %w", err) + } + + return ctrl.Result{}, nil + } + + if deployState.needRequeue || deployState.needInstallation { + return ctrl.Result{Requeue: true, RequeueAfter: c.requeueAfter}, nil // either the installation has happened or direct requeue is required + } + + return ctrl.Result{}, nil +} + +// installVelero installs velero stack with all the required components. +func (c *Config) installVelero(ctx context.Context) error { + saName, err := c.ensureVeleroRBAC(ctx) + if err != nil { + return fmt.Errorf("failed to ensure velero RBAC: %w", err) + } + + options := &veleroinstall.VeleroOptions{ + Namespace: c.systemNamespace, + Image: c.image, + Features: c.features, + + ServiceAccountName: saName, + NoDefaultBackupLocation: true, // no need (explicit BSL) + + DefaultRepoMaintenanceFrequency: time.Hour, // default + GarbageCollectionFrequency: time.Hour, // default + PodVolumeOperationTimeout: 4 * time.Hour, // default + UploaderType: uploader.KopiaType, // the only supported + + // TODO: skip null params? + ProviderName: "", // no need, provided through the explicit BSL object + Bucket: "", // no need, provided through the explicit BSL object + + Prefix: "", // no need when out-of-tree + PodAnnotations: nil, // no need, default comes from velero + PodLabels: nil, // no need, default comes from velero + ServiceAccountAnnotations: nil, // customizable through the config? + + VeleroPodResources: corev1.ResourceRequirements{}, // unbounded + NodeAgentPodResources: corev1.ResourceRequirements{}, // not used + PodResources: kube.PodResources{}, // maintenance job resources, unlimited ok + + SecretData: nil, // no need, provided through the explicit BSL object + UseNodeAgent: false, // no need + RestoreOnly: false, // no need + PrivilegedNodeAgent: false, // no need + UseVolumeSnapshots: false, // no need + BSLConfig: nil, // backupstoragelocation + VSLConfig: nil, // volumesnapshotlocation + Plugins: nil, // should be installed on-demand (BSL object) + CACertData: nil, // no need (explicit BSL) + DefaultVolumesToFsBackup: false, // no volume backups, no need + DefaultSnapshotMoveData: false, // no snapshots, no need + DisableInformerCache: false, // dangerous + ScheduleSkipImmediately: false, // might be useful, but easy to customize directly through the deploy + KeepLatestMaintenanceJobs: 0, // optional + BackupRepoConfigMap: "", // no need, backup config through a CM + RepoMaintenanceJobConfigMap: "", // no need, main job config through a CM + NodeAgentConfigMap: "", // no need, node-agent config through a CM + } + + resources := veleroinstall.AllResources(options) + + dc, err := dynamic.NewForConfig(c.kubeRestConfig) + if err != nil { + return fmt.Errorf("failed to construct dynamic client: %w", err) + } + + return veleroinstall.Install(veleroclient.NewDynamicFactory(dc), c.cl, resources, io.Discard) +} + +// ensureVeleroRBAC creates required RBAC objects for velero to be functional +// with the minimal required set of permissions. +// Returns the name of created ServiceAccount referenced by created bindings. +func (c *Config) ensureVeleroRBAC(ctx context.Context) (string, error) { + crbName, clusterRoleName, rbName, roleName, saName := veleroName, veleroName, veleroName, veleroName, veleroName + if c.systemNamespace != veleroName { + vns := veleroName + "-" + c.systemNamespace + crbName, clusterRoleName, saName = vns+"-clusterrolebinding", vns+"-clusterrole", crbName+"-sa" + rbName, roleName = vns+"-rolebinding", vns+"-role" + } + + systemNS := new(corev1.Namespace) + if err := c.cl.Get(ctx, client.ObjectKey{Name: c.systemNamespace}, systemNS); apierrors.IsNotFound(err) { + systemNS.Name = c.systemNamespace + if err := c.cl.Create(ctx, systemNS); err != nil { + return "", fmt.Errorf("failed to create %s namespace for velero: %w", c.systemNamespace, err) + } + } + + sa := &corev1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: saName, Namespace: c.systemNamespace}} + if _, err := controllerutil.CreateOrUpdate(ctx, c.cl, sa, func() error { + sa.Labels = veleroinstall.Labels() + return nil + }); err != nil { + return "", fmt.Errorf("failed to create or update velero service account: %w", err) + } + + role := &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Name: roleName, Namespace: c.systemNamespace}} + if _, err := controllerutil.CreateOrUpdate(ctx, c.cl, role, func() error { + role.Labels = veleroinstall.Labels() + role.Rules = []rbacv1.PolicyRule{ + { + APIGroups: []string{velerov1api.SchemeGroupVersion.Group}, + Resources: []string{"*"}, + Verbs: []string{"*"}, + }, + { + APIGroups: []string{corev1.GroupName}, + Resources: []string{"secrets"}, + Verbs: []string{"create"}, + }, + } + return nil + }); err != nil { + return "", fmt.Errorf("failed to create or update velero role: %w", err) + } + + roleBinding := &rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Name: rbName, Namespace: c.systemNamespace}} + if _, err := controllerutil.CreateOrUpdate(ctx, c.cl, roleBinding, func() error { + roleBinding.Labels = veleroinstall.Labels() + roleBinding.RoleRef = rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, + Kind: "Role", + Name: roleName, + } + roleBinding.Subjects = []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: saName, + Namespace: c.systemNamespace, + }, + } + return nil + }); err != nil { + return "", fmt.Errorf("failed to create or update velero role binding: %w", err) + } + + cr := &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: clusterRoleName}} + if _, err := controllerutil.CreateOrUpdate(ctx, c.cl, cr, func() error { + cr.Labels = veleroinstall.Labels() + cr.Rules = []rbacv1.PolicyRule{ + { + APIGroups: []string{"*"}, + Resources: []string{"*"}, + Verbs: []string{"list", "get"}, + }, + { + APIGroups: []string{""}, + Resources: []string{"namespaces"}, + Verbs: []string{"list", "get"}, + }, + { + APIGroups: []string{apiextv1.GroupName}, + Resources: []string{"customresourcedefinitions"}, + Verbs: []string{"get"}, + }, + } + return nil + }); err != nil { + return "", fmt.Errorf("failed to create or update velero cluster role: %w", err) + } + + crb := &rbacv1.ClusterRoleBinding{ObjectMeta: metav1.ObjectMeta{Name: crbName}} + if _, err := controllerutil.CreateOrUpdate(ctx, c.cl, crb, func() error { + crb.Labels = veleroinstall.Labels() + crb.RoleRef = rbacv1.RoleRef{ + APIGroup: rbacv1.GroupName, + Kind: "ClusterRole", + Name: clusterRoleName, + } + crb.Subjects = []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: saName, + Namespace: c.systemNamespace, + }, + } + return nil + }); err != nil { + return "", fmt.Errorf("failed to create or update velero cluster role binding: %w", err) + } + + return saName, nil +} + +type deployState struct { + needRequeue bool + needInstallation bool +} + +// checkVeleroDeployIsInstalled check whether the velero deploy is already installed: +// - the deployment is presented; +// - is in ready state; +// - the only container has the expected image and replicas. +// +// If image or replica count are not expected, the deploy will be patched regardingly. +// If the deploy has unexpected container name, the deploy will be deleted. +func (c *Config) checkVeleroDeployIsInstalled(ctx context.Context) (deployState, error) { + l := ctrl.LoggerFrom(ctx).WithName("velero-deploy-checker") + + l.Info("Checking if Velero deployment is already installed") + + veleroDeploy := new(appsv1.Deployment) + err := c.cl.Get(ctx, client.ObjectKey{Namespace: c.systemNamespace, Name: veleroName}, veleroDeploy) + if err != nil && !apierrors.IsNotFound(err) { + return deployState{}, fmt.Errorf("failed to get velero deploy: %w", err) + } + + if apierrors.IsNotFound(err) { + l.Info("Deployment is not found, considering the stack has not been (yet) installed") + return deployState{needInstallation: true}, nil + } + + if len(veleroDeploy.Spec.Template.Spec.Containers) == 0 || + veleroDeploy.Spec.Template.Spec.Containers[0].Name != veleroName { + l.Info("Deployment has unexpected container name, considering to reinstall the deployment again") + // the deploy is "corrupted", remove only it and then reinstall + if err := c.cl.Delete(ctx, veleroDeploy); err != nil { + return deployState{}, fmt.Errorf("failed to delete velero deploy: %w", err) + } + + removalCtx, cancel := context.WithCancel(ctx) + var checkErr error + checkFn := func(ctx context.Context) { + key := client.ObjectKeyFromObject(veleroDeploy) + ll := l.V(1).WithValues("velero_deploy", key.String()) + ll.Info("Checking if the deployment has been removed") + if checkErr = c.cl.Get(ctx, client.ObjectKeyFromObject(veleroDeploy), veleroDeploy); checkErr != nil { + if apierrors.IsNotFound(checkErr) { + ll.Info("Removed successfully") + checkErr = nil + } + cancel() + return + } + ll.Info("Not removed yet") + } + + wait.UntilWithContext(removalCtx, checkFn, time.Millisecond*500) + if checkErr != nil { + return deployState{}, fmt.Errorf("failed to wait for velero deploy removal: %w", checkErr) + } + + return deployState{needInstallation: true}, nil + } + + isPatchRequired := false + // process 2 invariants beforehand + cont := veleroDeploy.Spec.Template.Spec.Containers[0] + if cont.Image != c.image { + l.Info("Deployment container has unexpected image", "current_image", cont.Image, "expected_image", c.image) + cont.Image = c.image + veleroDeploy.Spec.Template.Spec.Containers[0] = cont + isPatchRequired = true + } + + if veleroDeploy.Spec.Replicas == nil || *veleroDeploy.Spec.Replicas == 0 { + l.Info("Deployment is scaled to 0, scaling up to 1") + *veleroDeploy.Spec.Replicas = 1 + isPatchRequired = true + } + + if isPatchRequired { + l.Info("Patching the deployment") + if err := c.cl.Patch(ctx, veleroDeploy, client.Merge); err != nil { + return deployState{}, fmt.Errorf("failed to patch velero deploy: %w", err) + } + + l.Info("Need to requeue after the successful patch") + return deployState{needRequeue: true}, nil + } + + r := isDeploymentReady(veleroDeploy) // if no invariants then just check the readiness + if !r { + l.Info("Deployment is not ready yet, will requeue") + return deployState{needRequeue: true}, nil + } + + l.Info("Deployment is in the expected state") + return deployState{}, nil +} + +// https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/kubectl/pkg/polymorphichelpers/rollout_status.go#L76-L89 + +// isDeploymentReady checks if the given Deployment instance is ready. +func isDeploymentReady(d *appsv1.Deployment) bool { + if d.Generation > d.Status.ObservedGeneration { + return false + } + + const timedOutReason = "ProgressDeadlineExceeded" // avoid dependency + var cond *appsv1.DeploymentCondition + for _, c := range d.Status.Conditions { + if c.Type == appsv1.DeploymentProgressing { + cond = &c + break + } + } + + if cond != nil && cond.Reason == timedOutReason { + return false + } + + if d.Spec.Replicas != nil && d.Status.UpdatedReplicas < *d.Spec.Replicas { + return false + } + + if d.Status.Replicas > d.Status.UpdatedReplicas { + return false + } + + if d.Status.AvailableReplicas < d.Status.UpdatedReplicas { + return false + } + + return true +} diff --git a/internal/controller/backup/oneshot.go b/internal/controller/backup/oneshot.go new file mode 100644 index 000000000..2729fb5d0 --- /dev/null +++ b/internal/controller/backup/oneshot.go @@ -0,0 +1,30 @@ +// Copyright 2024 +// +// 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 backup + +import ( + "context" + + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" +) + +func (*Config) ReconcileBackup(ctx context.Context, backup *hmcv1alpha1.Backup) error { + if backup == nil { + return nil + } + + _ = ctx + return nil +} diff --git a/internal/controller/backup/schedule.go b/internal/controller/backup/schedule.go new file mode 100644 index 000000000..db621f678 --- /dev/null +++ b/internal/controller/backup/schedule.go @@ -0,0 +1,30 @@ +// Copyright 2024 +// +// 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 backup + +import ( + "context" + + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" +) + +func (*Config) ReconcileScheduledBackup(ctx context.Context, schedule *hmcv1alpha1.Backup) error { + if schedule == nil { + return nil + } + _ = ctx + + return nil +} diff --git a/internal/controller/backup/type.go b/internal/controller/backup/type.go new file mode 100644 index 000000000..0292506d6 --- /dev/null +++ b/internal/controller/backup/type.go @@ -0,0 +1,62 @@ +// Copyright 2024 +// +// 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 backup + +import ( + "context" + "fmt" + + velerov1api "github.com/zerospiel/velero/pkg/apis/velero/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" +) + +type Typ uint + +const ( + TypeNone Typ = iota + TypeSchedule + TypeBackup +) + +func (c *Config) GetBackupType(ctx context.Context, instance *hmcv1alpha1.Backup, reqName string) (Typ, error) { + if instance.Status.Reference != nil { + gv := velerov1api.SchemeGroupVersion + switch instance.Status.Reference.GroupVersionKind() { + case gv.WithKind("Schedule"): + return TypeSchedule, nil + case gv.WithKind("Backup"): + return TypeBackup, nil + default: + return TypeNone, fmt.Errorf("unexpected kind %s in the backup reference", instance.Status.Reference.Kind) + } + } + + mgmts := new(hmcv1alpha1.ManagementList) + if err := c.cl.List(ctx, mgmts, client.Limit(1)); err != nil { + return TypeNone, fmt.Errorf("failed to list Management: %w", err) + } + + if len(mgmts.Items) == 0 { // nothing to do in such case for both scheduled/non-scheduled backups + return TypeNone, nil + } + + if reqName == mgmts.Items[0].Name { // mgmt name == scheduled-backup + return TypeSchedule, nil + } + + return TypeBackup, nil +} diff --git a/internal/controller/backup_controller.go b/internal/controller/backup_controller.go index 6b87cd6a6..26493e2ae 100644 --- a/internal/controller/backup_controller.go +++ b/internal/controller/backup_controller.go @@ -16,45 +16,151 @@ package controller import ( "context" + "fmt" + "os" + "strings" + "time" - "k8s.io/apimachinery/pkg/runtime" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" - hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/controller/backup" ) // BackupReconciler reconciles a Backup object type BackupReconciler struct { client.Client - Scheme *runtime.Scheme + + kc *rest.Config + + image string + systemNamespace string + features []string + + requeueAfter time.Duration } -// +kubebuilder:rbac:groups=hmc.mirantis.com.hmc.mirantis.com,resources=Backups,verbs=get;list;watch;create;update;patch;delete -// +kubebuilder:rbac:groups=hmc.mirantis.com.hmc.mirantis.com,resources=Backups/status,verbs=get;update;patch -// +kubebuilder:rbac:groups=hmc.mirantis.com.hmc.mirantis.com,resources=Backups/finalizers,verbs=update +func (r *BackupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + l := ctrl.LoggerFrom(ctx) -// Reconcile is part of the main kubernetes reconciliation loop which aims to -// move the current state of the cluster closer to the desired state. -// TODO(user): Modify the Reconcile function to compare the state specified by -// the Backup object against the actual cluster state, and then -// perform operations to make the cluster state reflect the state specified by -// the user. -// -// For more details, check Reconcile and its Result here: -// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/reconcile -func (*BackupReconciler) Reconcile(ctx context.Context, _ ctrl.Request) (ctrl.Result, error) { - _ = log.FromContext(ctx) + backupInstance := new(hmcv1alpha1.Backup) + err := r.Client.Get(ctx, req.NamespacedName, backupInstance) + if ierr := client.IgnoreNotFound(err); ierr != nil { + l.Error(ierr, "unable to fetch Backup") + return ctrl.Result{}, ierr + } + + bcfg := backup.NewConfig(r.Client, r.kc, + backup.WithFeatures(r.features...), + backup.WithRequeueAfter(r.requeueAfter), + backup.WithVeleroImage(r.image), + backup.WithVeleroSystemNamespace(r.systemNamespace), + ) + + if apierrors.IsNotFound(err) { + // if non-scheduled backup is not found(deleted), then just skip the error + // if scheduled backup is not found, then it either does not exist yet + // and we should create it, or it has been removed; + // if the latter is the case, we either should re-create it once again + // or do nothing if mgmt backup is disabled + mgmt := new(hmcv1alpha1.Management) + if err := r.Client.Get(ctx, req.NamespacedName, mgmt); err != nil { + l.Error(err, "unable to fetch Management") + return ctrl.Result{}, client.IgnoreNotFound(err) + } + + if !mgmt.Spec.Backup.Enabled { + l.Info("Management backup is disabled, nothing to do") + return ctrl.Result{}, nil + } + + l.Info("Reconciling velero stack") + installRes, err := bcfg.ReconcileVeleroInstallation(ctx) + if err != nil { + l.Error(err, "velero installation") + return ctrl.Result{}, err + } + if installRes.Requeue || installRes.RequeueAfter > 0 { + return installRes, nil + } - // TODO(user): your logic here + // required during creation + backupInstance.Name = req.Name + backupInstance.Namespace = req.Namespace + } + + btype, err := bcfg.GetBackupType(ctx, backupInstance, req.Name) + if err != nil { + l.Error(err, "failed to determine backup type") + return ctrl.Result{}, err + } + + switch btype { + case backup.TypeNone: + l.Info("There are nothing to reconcile, management does not exists") + // TODO: do we need to reconcile/delete/pause schedules in this case? + return ctrl.Result{}, nil + case backup.TypeBackup: + return ctrl.Result{}, bcfg.ReconcileBackup(ctx, backupInstance) + case backup.TypeSchedule: + return ctrl.Result{}, bcfg.ReconcileScheduledBackup(ctx, backupInstance) + } return ctrl.Result{}, nil } // SetupWithManager sets up the controller with the Manager. func (r *BackupReconciler) SetupWithManager(mgr ctrl.Manager) error { + r.kc = mgr.GetConfig() + + const reqDuration = "BACKUP_CTRL_REQUEUE_DURATION" + r.features = strings.Split(strings.ReplaceAll(os.Getenv("BACKUP_FEATURES"), ", ", ","), ",") + r.systemNamespace = os.Getenv("BACKUP_SYSTEM_NAMESPACE") + r.image = os.Getenv("BACKUP_BASIC_IMAGE") + d, err := time.ParseDuration(os.Getenv(reqDuration)) + if err != nil { + return fmt.Errorf("failed to parse env %s duration: %w", reqDuration, err) + } + r.requeueAfter = d + return ctrl.NewControllerManagedBy(mgr). - For(&hmcmirantiscomv1alpha1.Backup{}). + For(&hmcv1alpha1.Backup{}). + Watches(&hmcv1alpha1.Management{}, handler.EnqueueRequestsFromMapFunc(func(_ context.Context, o client.Object) []ctrl.Request { + return []ctrl.Request{{NamespacedName: client.ObjectKeyFromObject(o)}} + }), builder.WithPredicates( // watch mgmt.spec.backup to manage the (only) scheduled Backup + predicate.Funcs{ + GenericFunc: func(event.TypedGenericEvent[client.Object]) bool { return false }, + DeleteFunc: func(event.TypedDeleteEvent[client.Object]) bool { return false }, + CreateFunc: func(tce event.TypedCreateEvent[client.Object]) bool { + mgmt, ok := tce.Object.(*hmcv1alpha1.Management) + if !ok { + return false + } + + return mgmt.Spec.Backup.Enabled + }, + UpdateFunc: func(tue event.TypedUpdateEvent[client.Object]) bool { + oldMgmt, ok := tue.ObjectOld.(*hmcv1alpha1.Management) + if !ok { + return false + } + + newMgmt, ok := tue.ObjectNew.(*hmcv1alpha1.Management) + if !ok { + return false + } + + return (newMgmt.Spec.Backup.Enabled != oldMgmt.Spec.Backup.Enabled || + newMgmt.Spec.Backup.Schedule != oldMgmt.Spec.Backup.Schedule) + }, + }, + )). Complete(r) } diff --git a/internal/controller/backup_controller_test.go b/internal/controller/backup_controller_test.go index 009c7e8b7..6e78a71ca 100644 --- a/internal/controller/backup_controller_test.go +++ b/internal/controller/backup_controller_test.go @@ -22,7 +22,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/reconcile" hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" ) @@ -35,7 +34,7 @@ var _ = Describe("Backup Controller", func() { typeNamespacedName := types.NamespacedName{ Name: resourceName, - Namespace: "default", // TODO(user):Modify as needed + Namespace: metav1.NamespaceAll, } backup := &hmcmirantiscomv1alpha1.Backup{} @@ -46,16 +45,14 @@ var _ = Describe("Backup Controller", func() { resource := &hmcmirantiscomv1alpha1.Backup{ ObjectMeta: metav1.ObjectMeta{ Name: resourceName, - Namespace: "default", + Namespace: metav1.NamespaceAll, }, - // TODO(user): Specify other spec details if needed. } Expect(k8sClient.Create(ctx, resource)).To(Succeed()) } }) AfterEach(func() { - // TODO(user): Cleanup logic after each test, like removing the resource instance. resource := &hmcmirantiscomv1alpha1.Backup{} err := k8sClient.Get(ctx, typeNamespacedName, resource) Expect(err).NotTo(HaveOccurred()) @@ -63,19 +60,18 @@ var _ = Describe("Backup Controller", func() { By("Cleanup the specific resource instance Backup") Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) }) + It("should successfully reconcile the resource", func() { By("Reconciling the created resource") controllerReconciler := &BackupReconciler{ Client: k8sClient, - Scheme: k8sClient.Scheme(), } + _ = controllerReconciler - _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ - NamespacedName: typeNamespacedName, - }) - Expect(err).NotTo(HaveOccurred()) - // TODO(user): Add more specific assertions depending on your controller's reconciliation logic. - // Example: If you expect a certain status condition after reconciliation, verify it here. + // _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + // NamespacedName: typeNamespacedName, + // }) + // Expect(err).NotTo(HaveOccurred()) }) }) }) diff --git a/internal/controller/clusterdeployment_controller.go b/internal/controller/clusterdeployment_controller.go index e373e92de..fb8381c10 100644 --- a/internal/controller/clusterdeployment_controller.go +++ b/internal/controller/clusterdeployment_controller.go @@ -52,6 +52,7 @@ import ( "github.com/K0rdent/kcm/internal/helm" "github.com/K0rdent/kcm/internal/sveltos" "github.com/K0rdent/kcm/internal/telemetry" + "github.com/K0rdent/kcm/internal/utils" "github.com/K0rdent/kcm/internal/utils/status" ) @@ -146,6 +147,11 @@ func (r *ClusterDeploymentReconciler) reconcileUpdate(ctx context.Context, mc *h return ctrl.Result{}, nil } + if err := utils.AddHMCComponentLabel(ctx, r.Client, mc); err != nil { + l.Error(err, "adding component label") + return ctrl.Result{}, err + } + if len(mc.Status.Conditions) == 0 { mc.InitConditions() } diff --git a/internal/controller/credential_controller.go b/internal/controller/credential_controller.go index 33e51dd26..77ce04f2e 100644 --- a/internal/controller/credential_controller.go +++ b/internal/controller/credential_controller.go @@ -28,6 +28,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" hmc "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/utils" ) const defaultSyncPeriod = 15 * time.Minute @@ -46,6 +47,11 @@ func (r *CredentialReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{}, client.IgnoreNotFound(err) } + if err := utils.AddHMCComponentLabel(ctx, r.Client, cred); err != nil { + l.Error(err, "adding component label") + return ctrl.Result{}, err + } + defer func() { err = errors.Join(err, r.updateStatus(ctx, cred)) }() diff --git a/internal/controller/management_controller.go b/internal/controller/management_controller.go index 01b527d28..bec983e95 100644 --- a/internal/controller/management_controller.go +++ b/internal/controller/management_controller.go @@ -91,6 +91,11 @@ func (r *ManagementReconciler) Update(ctx context.Context, management *hmc.Manag return ctrl.Result{}, nil } + if err := utils.AddHMCComponentLabel(ctx, r.Client, management); err != nil { + l.Error(err, "adding component label") + return ctrl.Result{}, err + } + if err := r.cleanupRemovedComponents(ctx, management); err != nil { l.Error(err, "failed to cleanup removed components") return ctrl.Result{}, err diff --git a/internal/controller/multiclusterservice_controller.go b/internal/controller/multiclusterservice_controller.go index 9b1fef14a..fa922f3de 100644 --- a/internal/controller/multiclusterservice_controller.go +++ b/internal/controller/multiclusterservice_controller.go @@ -37,6 +37,7 @@ import ( hmc "github.com/K0rdent/kcm/api/v1alpha1" "github.com/K0rdent/kcm/internal/sveltos" + "github.com/K0rdent/kcm/internal/utils" ) // MultiClusterServiceReconciler reconciles a MultiClusterService object @@ -70,6 +71,13 @@ func (r *MultiClusterServiceReconciler) Reconcile(ctx context.Context, req ctrl. } func (r *MultiClusterServiceReconciler) reconcileUpdate(ctx context.Context, mcs *hmc.MultiClusterService) (_ ctrl.Result, err error) { + if utils.AddLabel(mcs, hmc.GenericComponentLabelName, hmc.GenericComponentLabelValueHMC) { + if err := r.Update(ctx, mcs); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to update labels: %w", err) + } + return ctrl.Result{Requeue: true}, nil // generation has not changed, need explicit requeue + } + // servicesErr is handled separately from err because we do not want // to set the condition of SveltosClusterProfileReady type to "False" // if there is an error while retrieving status for the services. diff --git a/internal/controller/multiclusterservice_controller_test.go b/internal/controller/multiclusterservice_controller_test.go index ce492a4ab..8e4270b89 100644 --- a/internal/controller/multiclusterservice_controller_test.go +++ b/internal/controller/multiclusterservice_controller_test.go @@ -136,7 +136,8 @@ var _ = Describe("MultiClusterService Controller", func() { Name: serviceTemplate1Name, Namespace: testSystemNamespace, Labels: map[string]string{ - hmc.HMCManagedLabelKey: "true", + hmc.HMCManagedLabelKey: "true", + hmc.GenericComponentLabelName: hmc.GenericComponentLabelValueHMC, }, }, Spec: hmc.ServiceTemplateSpec{ @@ -159,6 +160,7 @@ var _ = Describe("MultiClusterService Controller", func() { ObjectMeta: metav1.ObjectMeta{ Name: serviceTemplate2Name, Namespace: testSystemNamespace, + Labels: map[string]string{hmc.GenericComponentLabelName: hmc.GenericComponentLabelValueHMC}, }, Spec: hmc.ServiceTemplateSpec{ Helm: hmc.HelmSpec{ @@ -206,7 +208,8 @@ var _ = Describe("MultiClusterService Controller", func() { if err != nil && apierrors.IsNotFound(err) { multiClusterService = &hmc.MultiClusterService{ ObjectMeta: metav1.ObjectMeta{ - Name: multiClusterServiceName, + Name: multiClusterServiceName, + Labels: map[string]string{hmc.GenericComponentLabelName: hmc.GenericComponentLabelValueHMC}, Finalizers: []string{ // Reconcile attempts to add this finalizer and returns immediately // if successful. So adding this finalizer here manually in order diff --git a/internal/controller/release_controller.go b/internal/controller/release_controller.go index 5336cf00b..56248a424 100644 --- a/internal/controller/release_controller.go +++ b/internal/controller/release_controller.go @@ -77,6 +77,12 @@ func (r *ReleaseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (re l.Error(err, "failed to get Release") return ctrl.Result{}, err } + + if err := utils.AddHMCComponentLabel(ctx, r.Client, release); err != nil { + l.Error(err, "adding component label") + return ctrl.Result{}, err + } + defer func() { release.Status.ObservedGeneration = release.Generation for _, condition := range release.Status.Conditions { diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index d96405956..60fc43e62 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -80,6 +80,13 @@ func (r *ClusterTemplateReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, err } + if utils.AddLabel(clusterTemplate, hmc.GenericComponentLabelName, hmc.GenericComponentLabelValueHMC) { + if err := r.Update(ctx, clusterTemplate); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to update labels: %w", err) + } + return ctrl.Result{Requeue: true}, nil // generation has not changed, need explicit requeue + } + result, err := r.ReconcileTemplate(ctx, clusterTemplate) if err != nil { l.Error(err, "failed to reconcile template") @@ -113,6 +120,14 @@ func (r *ServiceTemplateReconciler) Reconcile(ctx context.Context, req ctrl.Requ l.Error(err, "Failed to get ServiceTemplate") return ctrl.Result{}, err } + + if utils.AddLabel(serviceTemplate, hmc.GenericComponentLabelName, hmc.GenericComponentLabelValueHMC) { + if err := r.Update(ctx, serviceTemplate); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to update labels: %w", err) + } + return ctrl.Result{Requeue: true}, nil // generation has not changed, need explicit requeue + } + return r.ReconcileTemplate(ctx, serviceTemplate) } @@ -130,6 +145,14 @@ func (r *ProviderTemplateReconciler) Reconcile(ctx context.Context, req ctrl.Req l.Error(err, "Failed to get ProviderTemplate") return ctrl.Result{}, err } + + if utils.AddLabel(providerTemplate, hmc.GenericComponentLabelName, hmc.GenericComponentLabelValueHMC) { + if err := r.Update(ctx, providerTemplate); err != nil { + return ctrl.Result{}, fmt.Errorf("failed to update labels: %w", err) + } + return ctrl.Result{Requeue: true}, nil // generation has not changed, need explicit requeue + } + changed, err := r.setReleaseOwnership(ctx, providerTemplate) if err != nil { l.Error(err, "Failed to set OwnerReferences") diff --git a/internal/controller/template_controller_test.go b/internal/controller/template_controller_test.go index 28b4aabd0..c01e58793 100644 --- a/internal/controller/template_controller_test.go +++ b/internal/controller/template_controller_test.go @@ -218,6 +218,7 @@ var _ = Describe("Template Controller", func() { ObjectMeta: metav1.ObjectMeta{ Name: clusterTemplateName, Namespace: metav1.NamespaceDefault, + Labels: map[string]string{hmcmirantiscomv1alpha1.GenericComponentLabelName: hmcmirantiscomv1alpha1.GenericComponentLabelValueHMC}, }, Spec: hmcmirantiscomv1alpha1.ClusterTemplateSpec{ Helm: helmSpec, diff --git a/internal/controller/templatechain_controller.go b/internal/controller/templatechain_controller.go index ccee4fdd0..faa6f4a75 100644 --- a/internal/controller/templatechain_controller.go +++ b/internal/controller/templatechain_controller.go @@ -90,6 +90,11 @@ func (r *ServiceTemplateChainReconciler) Reconcile(ctx context.Context, req ctrl func (r *TemplateChainReconciler) ReconcileTemplateChain(ctx context.Context, templateChain templateChain) (ctrl.Result, error) { l := ctrl.LoggerFrom(ctx) + if err := utils.AddHMCComponentLabel(ctx, r.Client, templateChain); err != nil { + l.Error(err, "adding component label") + return ctrl.Result{}, err + } + if templateChain.GetNamespace() == r.SystemNamespace { return ctrl.Result{}, nil } diff --git a/internal/controller/templatechain_controller_test.go b/internal/controller/templatechain_controller_test.go index 49cf12969..962be0e00 100644 --- a/internal/controller/templatechain_controller_test.go +++ b/internal/controller/templatechain_controller_test.go @@ -170,6 +170,7 @@ var _ = Describe("Template Chain Controller", func() { ObjectMeta: metav1.ObjectMeta{ Name: chain.Name, Namespace: chain.Namespace, + Labels: map[string]string{hmcmirantiscomv1alpha1.GenericComponentLabelName: hmcmirantiscomv1alpha1.GenericComponentLabelValueHMC}, }, Spec: hmcmirantiscomv1alpha1.TemplateChainSpec{SupportedTemplates: supportedClusterTemplates[chain.Name]}, } @@ -185,6 +186,7 @@ var _ = Describe("Template Chain Controller", func() { ObjectMeta: metav1.ObjectMeta{ Name: chain.Name, Namespace: chain.Namespace, + Labels: map[string]string{hmcmirantiscomv1alpha1.GenericComponentLabelName: hmcmirantiscomv1alpha1.GenericComponentLabelValueHMC}, }, Spec: hmcmirantiscomv1alpha1.TemplateChainSpec{SupportedTemplates: supportedServiceTemplates[chain.Name]}, } @@ -196,6 +198,10 @@ var _ = Describe("Template Chain Controller", func() { ct := &hmcmirantiscomv1alpha1.ClusterTemplate{} err := k8sClient.Get(ctx, types.NamespacedName{Name: name, Namespace: utils.DefaultSystemNamespace}, ct) if err != nil && errors.IsNotFound(err) { + if template.Labels == nil { + template.Labels = make(map[string]string) + } + template.Labels[hmcmirantiscomv1alpha1.GenericComponentLabelName] = hmcmirantiscomv1alpha1.GenericComponentLabelValueHMC template.Spec.Providers = ctProviders Expect(k8sClient.Create(ctx, template)).To(Succeed()) } @@ -207,6 +213,10 @@ var _ = Describe("Template Chain Controller", func() { st := &hmcmirantiscomv1alpha1.ServiceTemplate{} err := k8sClient.Get(ctx, types.NamespacedName{Name: name, Namespace: utils.DefaultSystemNamespace}, st) if err != nil && errors.IsNotFound(err) { + if template.Labels == nil { + template.Labels = make(map[string]string) + } + template.Labels[hmcmirantiscomv1alpha1.GenericComponentLabelName] = hmcmirantiscomv1alpha1.GenericComponentLabelValueHMC template.Spec.Providers = stProviders Expect(k8sClient.Create(ctx, template)).To(Succeed()) } diff --git a/internal/utils/label.go b/internal/utils/label.go new file mode 100644 index 000000000..08215f777 --- /dev/null +++ b/internal/utils/label.go @@ -0,0 +1,53 @@ +// Copyright 2024 +// +// 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 utils + +import ( + "context" + "fmt" + + "sigs.k8s.io/controller-runtime/pkg/client" + + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" +) + +// AddLabel adds the provided label key and value to the object if not presented +// or if the existing label value does not equal the given one. +// Returns an indication of whether it updated the labels of the object. +func AddLabel(o client.Object, labelKey, labelValue string) (labelsUpdated bool) { + l := o.GetLabels() + v, ok := l[labelKey] + if ok && v == labelValue { + return false + } + if l == nil { + l = make(map[string]string) + } + l[labelKey] = labelValue + o.SetLabels(l) + return true +} + +// AddHMCComponentLabel adds the common HMC component label with the hmc value to the given object +// and updates if it is required. +func AddHMCComponentLabel(ctx context.Context, cl client.Client, o client.Object) error { + if !AddLabel(o, hmcv1alpha1.GenericComponentLabelName, hmcv1alpha1.GenericComponentLabelValueHMC) { + return nil + } + if err := cl.Update(ctx, o); err != nil { + return fmt.Errorf("failed to update %s %s labels: %w", o.GetObjectKind().GroupVersionKind().Kind, client.ObjectKeyFromObject(o), err) + } + return nil +} diff --git a/internal/utils/label_test.go b/internal/utils/label_test.go new file mode 100644 index 000000000..a700c95b5 --- /dev/null +++ b/internal/utils/label_test.go @@ -0,0 +1,92 @@ +// Copyright 2024 +// +// 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 utils_test + +import ( + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + hmcv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + "github.com/K0rdent/kcm/internal/utils" +) + +func TestAddLabel(t *testing.T) { + obj := &hmcv1alpha1.Management{ObjectMeta: metav1.ObjectMeta{ + Labels: make(map[string]string), + }} + + withLabels := func(kv ...string) { + if len(kv) == 0 { + return + } + if len(kv)&1 != 0 { + panic("expected even number of args") + } + for k := range obj.Labels { + delete(obj.Labels, k) + } + for i := range len(kv) / 2 { + obj.Labels[kv[i*2]] = kv[i*2+1] + } + } + + type args struct { + mutate func() + labelKey string + labelValue string + } + tests := []struct { + name string + args args + wantLabelsUpdated bool + }{ + { + name: "no labels, expect updated map", + args: args{ + mutate: func() { withLabels() }, + labelKey: "foo", + labelValue: "bar", + }, + wantLabelsUpdated: true, + }, + { + name: "key exist diff value, expect updated map", + args: args{ + mutate: func() { withLabels("foo", "diff") }, + labelKey: "foo", + labelValue: "bar", + }, + wantLabelsUpdated: true, + }, + { + name: "key exist value is equal, expect no update required", + args: args{ + mutate: func() { withLabels("foo", "bar") }, + labelKey: "foo", + labelValue: "bar", + }, + }, + } + for _, tt := range tests { + _ = tt + t.Run(tt.name, func(t *testing.T) { + tt.args.mutate() + if gotLabelsUpdated := utils.AddLabel(obj, tt.args.labelKey, tt.args.labelValue); gotLabelsUpdated != tt.wantLabelsUpdated { + t.Errorf("AddLabel() = %v, want %v", gotLabelsUpdated, tt.wantLabelsUpdated) + } + }) + } +} diff --git a/internal/webhook/management_webhook.go b/internal/webhook/management_webhook.go index d241bb6c7..aa08007f8 100644 --- a/internal/webhook/management_webhook.go +++ b/internal/webhook/management_webhook.go @@ -265,6 +265,15 @@ func validateRelease(ctx context.Context, cl client.Client, releaseName string) } // Default implements webhook.Defaulter so a webhook will be registered for the type. -func (*ManagementValidator) Default(_ context.Context, _ runtime.Object) error { +func (*ManagementValidator) Default(_ context.Context, obj runtime.Object) error { + mgmt, ok := obj.(*hmcv1alpha1.Management) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected Management but got a %T", obj)) + } + + if mgmt.Spec.Backup.Enabled && mgmt.Spec.Backup.Schedule == "" { + mgmt.Spec.Backup.Schedule = "0 */6 * * *" // every 6h + } + return nil } diff --git a/internal/webhook/management_webhook_test.go b/internal/webhook/management_webhook_test.go index 4fd99cd6e..cfa0c49ce 100644 --- a/internal/webhook/management_webhook_test.go +++ b/internal/webhook/management_webhook_test.go @@ -22,6 +22,7 @@ import ( . "github.com/onsi/gomega" admissionv1 "k8s.io/api/admission/v1" "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" @@ -431,3 +432,56 @@ func TestManagementValidateDelete(t *testing.T) { }) } } + +func TestManagementDefault(t *testing.T) { + g := NewWithT(t) + + ctx := context.Background() + + tests := []struct { + name string + input client.Object + expected *v1alpha1.Management + err string + }{ + { + name: "should not set default backup schedule if already set", + input: management.NewManagement(management.WithBackup(v1alpha1.ManagementBackup{Enabled: true, Schedule: "0"})), + expected: management.NewManagement(management.WithBackup(v1alpha1.ManagementBackup{Enabled: true, Schedule: "0"})), + }, + { + name: "should set every six hours default backup schedule if backup is enabled but not set", + input: management.NewManagement(management.WithBackup(v1alpha1.ManagementBackup{Enabled: true})), + expected: management.NewManagement(management.WithBackup(v1alpha1.ManagementBackup{Enabled: true, Schedule: "0 */6 * * *"})), + }, + { + name: "should not set schedule if backup is disabled", + input: management.NewManagement(), + expected: management.NewManagement(), + }, + { + name: "should fail on non mgmt", + input: clusterdeployment.NewClusterDeployment(), + err: "expected Management but got a *v1alpha1.ClusterDeployment", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(_ *testing.T) { + c := fake.NewClientBuilder().WithScheme(scheme.Scheme).Build() + validator := &ManagementValidator{Client: c} + + err := validator.Default(ctx, tt.input) + if tt.err != "" { + g.Expect(err).To(HaveOccurred()) + g.Expect(err).To(MatchError(tt.err)) + } else { + g.Expect(err).To(Succeed()) + } + + if tt.expected != nil { + g.Expect(tt.input).To(BeEquivalentTo(tt.expected)) + } + }) + } +} diff --git a/templates/provider/hmc-templates/files/release.yaml b/templates/provider/hmc-templates/files/release.yaml index 45ed38bae..c1801c8c5 100644 --- a/templates/provider/hmc-templates/files/release.yaml +++ b/templates/provider/hmc-templates/files/release.yaml @@ -4,6 +4,8 @@ metadata: name: hmc-0-0-6 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: version: 0.0.6 hmc: diff --git a/templates/provider/hmc-templates/files/templates/adopted-cluster-0-0-1.yaml b/templates/provider/hmc-templates/files/templates/adopted-cluster-0-0-1.yaml index d7a88a27b..ef6474f52 100644 --- a/templates/provider/hmc-templates/files/templates/adopted-cluster-0-0-1.yaml +++ b/templates/provider/hmc-templates/files/templates/adopted-cluster-0-0-1.yaml @@ -4,6 +4,8 @@ metadata: name: adopted-cluster-0-0-1 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/aws-eks-0-0-2.yaml b/templates/provider/hmc-templates/files/templates/aws-eks-0-0-2.yaml index fa3d75fd7..79843db74 100644 --- a/templates/provider/hmc-templates/files/templates/aws-eks-0-0-2.yaml +++ b/templates/provider/hmc-templates/files/templates/aws-eks-0-0-2.yaml @@ -4,6 +4,8 @@ metadata: name: aws-eks-0-0-2 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/aws-hosted-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/aws-hosted-cp-0-0-3.yaml index 30b3fd57a..8855640d4 100644 --- a/templates/provider/hmc-templates/files/templates/aws-hosted-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/aws-hosted-cp-0-0-3.yaml @@ -4,6 +4,8 @@ metadata: name: aws-hosted-cp-0-0-3 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/aws-standalone-cp-0-0-4.yaml b/templates/provider/hmc-templates/files/templates/aws-standalone-cp-0-0-4.yaml index a72969fdf..5d53756f1 100644 --- a/templates/provider/hmc-templates/files/templates/aws-standalone-cp-0-0-4.yaml +++ b/templates/provider/hmc-templates/files/templates/aws-standalone-cp-0-0-4.yaml @@ -4,6 +4,8 @@ metadata: name: aws-standalone-cp-0-0-4 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/azure-aks-0-0-1.yaml b/templates/provider/hmc-templates/files/templates/azure-aks-0-0-1.yaml index e89e1c24c..87e47903b 100644 --- a/templates/provider/hmc-templates/files/templates/azure-aks-0-0-1.yaml +++ b/templates/provider/hmc-templates/files/templates/azure-aks-0-0-1.yaml @@ -4,6 +4,8 @@ metadata: name: azure-aks-0-0-1 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/azure-hosted-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/azure-hosted-cp-0-0-3.yaml index aabd521bb..5a7151def 100644 --- a/templates/provider/hmc-templates/files/templates/azure-hosted-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/azure-hosted-cp-0-0-3.yaml @@ -4,6 +4,8 @@ metadata: name: azure-hosted-cp-0-0-3 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/azure-standalone-cp-0-0-4.yaml b/templates/provider/hmc-templates/files/templates/azure-standalone-cp-0-0-4.yaml index b053db5e1..0d676e018 100644 --- a/templates/provider/hmc-templates/files/templates/azure-standalone-cp-0-0-4.yaml +++ b/templates/provider/hmc-templates/files/templates/azure-standalone-cp-0-0-4.yaml @@ -4,6 +4,8 @@ metadata: name: azure-standalone-cp-0-0-4 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/cert-manager-1-16-2.yaml b/templates/provider/hmc-templates/files/templates/cert-manager-1-16-2.yaml index 21f5131ec..59d26001f 100644 --- a/templates/provider/hmc-templates/files/templates/cert-manager-1-16-2.yaml +++ b/templates/provider/hmc-templates/files/templates/cert-manager-1-16-2.yaml @@ -4,6 +4,8 @@ metadata: name: cert-manager-1-16-2 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/cluster-api-provider-aws.yaml b/templates/provider/hmc-templates/files/templates/cluster-api-provider-aws.yaml index ddf83128a..7c8da0d40 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api-provider-aws.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api-provider-aws.yaml @@ -4,6 +4,8 @@ metadata: name: cluster-api-provider-aws-0-0-4 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/cluster-api-provider-azure.yaml b/templates/provider/hmc-templates/files/templates/cluster-api-provider-azure.yaml index a92b7d9d8..4b0d97629 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api-provider-azure.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api-provider-azure.yaml @@ -4,6 +4,8 @@ metadata: name: cluster-api-provider-azure-0-0-4 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/cluster-api-provider-openstack.yaml b/templates/provider/hmc-templates/files/templates/cluster-api-provider-openstack.yaml index d4fc2366c..2eddfef11 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api-provider-openstack.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api-provider-openstack.yaml @@ -4,6 +4,8 @@ metadata: name: cluster-api-provider-openstack-0-0-1 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/cluster-api-provider-vsphere.yaml b/templates/provider/hmc-templates/files/templates/cluster-api-provider-vsphere.yaml index 90032a55a..be86df90e 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api-provider-vsphere.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api-provider-vsphere.yaml @@ -4,6 +4,8 @@ metadata: name: cluster-api-provider-vsphere-0-0-5 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/cluster-api.yaml b/templates/provider/hmc-templates/files/templates/cluster-api.yaml index 3a05949e8..b8a6033f8 100644 --- a/templates/provider/hmc-templates/files/templates/cluster-api.yaml +++ b/templates/provider/hmc-templates/files/templates/cluster-api.yaml @@ -4,6 +4,8 @@ metadata: name: cluster-api-0-0-6 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/dex-0-19-1.yaml b/templates/provider/hmc-templates/files/templates/dex-0-19-1.yaml index 28c2b5889..92b45589f 100644 --- a/templates/provider/hmc-templates/files/templates/dex-0-19-1.yaml +++ b/templates/provider/hmc-templates/files/templates/dex-0-19-1.yaml @@ -4,6 +4,8 @@ metadata: name: dex-0-19-1 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/external-secrets-0-11-0.yaml b/templates/provider/hmc-templates/files/templates/external-secrets-0-11-0.yaml index e95ee6158..4542376cf 100644 --- a/templates/provider/hmc-templates/files/templates/external-secrets-0-11-0.yaml +++ b/templates/provider/hmc-templates/files/templates/external-secrets-0-11-0.yaml @@ -4,6 +4,8 @@ metadata: name: external-secrets-0-11-0 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/hmc.yaml b/templates/provider/hmc-templates/files/templates/hmc.yaml index 91d8bc2eb..c340f60c2 100644 --- a/templates/provider/hmc-templates/files/templates/hmc.yaml +++ b/templates/provider/hmc-templates/files/templates/hmc.yaml @@ -4,6 +4,8 @@ metadata: name: hmc-0-0-6 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-0.yaml b/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-0.yaml index c7092d713..a8cf1a7cf 100644 --- a/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-0.yaml +++ b/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-0.yaml @@ -4,6 +4,8 @@ metadata: name: ingress-nginx-4-11-0 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-3.yaml b/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-3.yaml index a55506fc6..e8a139632 100644 --- a/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-3.yaml +++ b/templates/provider/hmc-templates/files/templates/ingress-nginx-4-11-3.yaml @@ -4,6 +4,8 @@ metadata: name: ingress-nginx-4-11-3 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/k0smotron.yaml b/templates/provider/hmc-templates/files/templates/k0smotron.yaml index 14c37dddf..ec4a54f4d 100644 --- a/templates/provider/hmc-templates/files/templates/k0smotron.yaml +++ b/templates/provider/hmc-templates/files/templates/k0smotron.yaml @@ -4,6 +4,8 @@ metadata: name: k0smotron-0-0-5 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/kyverno-3-2-6.yaml b/templates/provider/hmc-templates/files/templates/kyverno-3-2-6.yaml index dc2ecb4da..e133c15f6 100644 --- a/templates/provider/hmc-templates/files/templates/kyverno-3-2-6.yaml +++ b/templates/provider/hmc-templates/files/templates/kyverno-3-2-6.yaml @@ -4,6 +4,8 @@ metadata: name: kyverno-3-2-6 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/openstack-standalone-cp-0-0-1.yaml b/templates/provider/hmc-templates/files/templates/openstack-standalone-cp-0-0-1.yaml index 22dd61798..390f40e8b 100644 --- a/templates/provider/hmc-templates/files/templates/openstack-standalone-cp-0-0-1.yaml +++ b/templates/provider/hmc-templates/files/templates/openstack-standalone-cp-0-0-1.yaml @@ -4,6 +4,8 @@ metadata: name: openstack-standalone-cp-0-0-1 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/projectsveltos.yaml b/templates/provider/hmc-templates/files/templates/projectsveltos.yaml index 95fb9312e..c88f0ef0c 100644 --- a/templates/provider/hmc-templates/files/templates/projectsveltos.yaml +++ b/templates/provider/hmc-templates/files/templates/projectsveltos.yaml @@ -4,6 +4,8 @@ metadata: name: projectsveltos-0-44-0 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/velero-8-1-0.yaml b/templates/provider/hmc-templates/files/templates/velero-8-1-0.yaml index fabb69123..03db61b6e 100644 --- a/templates/provider/hmc-templates/files/templates/velero-8-1-0.yaml +++ b/templates/provider/hmc-templates/files/templates/velero-8-1-0.yaml @@ -4,6 +4,8 @@ metadata: name: velero-8-1-0 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml index 4fcc0b118..4286b87e3 100644 --- a/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml @@ -4,6 +4,8 @@ metadata: name: vsphere-hosted-cp-0-0-3 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml index f628b7350..c60fb35a9 100644 --- a/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml @@ -4,6 +4,8 @@ metadata: name: vsphere-standalone-cp-0-0-3 annotations: helm.sh/resource-policy: keep + labels: + hmc.mirantis.com/component: hmc spec: helm: chartSpec: diff --git a/templates/provider/hmc/templates/_helpers.tpl b/templates/provider/hmc/templates/_helpers.tpl index 2d9e15365..780bffb09 100644 --- a/templates/provider/hmc/templates/_helpers.tpl +++ b/templates/provider/hmc/templates/_helpers.tpl @@ -40,6 +40,7 @@ helm.sh/chart: {{ include "hmc.chart" . }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} +hmc.mirantis.com/component: hmc {{- end }} {{/* @@ -108,3 +109,11 @@ hmc-webhook - list - watch {{- end -}} + +{{- define "backup.imageName" -}} +{{- if (.Values.controller.backup.image.fullName) -}} +{{- .Values.controller.backup.image.fullName -}} +{{- else -}} +{{- printf "%s/%s:%s" .Values.controller.backup.image.repository .Values.controller.backup.image.name .Values.controller.backup.image.tag -}} +{{- end -}} +{{- end -}} diff --git a/templates/provider/hmc/templates/crds/hmc.mirantis.com_managements.yaml b/templates/provider/hmc/templates/crds/hmc.mirantis.com_managements.yaml index a6144d3ed..93ac004f4 100644 --- a/templates/provider/hmc/templates/crds/hmc.mirantis.com_managements.yaml +++ b/templates/provider/hmc/templates/crds/hmc.mirantis.com_managements.yaml @@ -47,7 +47,6 @@ spec: into a cloud. properties: enabled: - default: false description: |- Flag to indicate whether the backup feature is enabled. If set to true, [Velero] platform will be installed. @@ -56,13 +55,10 @@ spec: [Velero]: https://velero.io type: boolean schedule: - default: 0 */6 * * * description: |- Schedule is a Cron expression defining when to run the scheduled Backup. Default value is to backup every 6 hours. type: string - required: - - enabled type: object core: description: |- diff --git a/templates/provider/hmc/templates/deployment.yaml b/templates/provider/hmc/templates/deployment.yaml index 31ae1004a..d2fcbe938 100644 --- a/templates/provider/hmc/templates/deployment.yaml +++ b/templates/provider/hmc/templates/deployment.yaml @@ -39,6 +39,14 @@ spec: env: - name: KUBERNETES_CLUSTER_DOMAIN value: {{ quote .Values.kubernetesClusterDomain }} + - name: BACKUP_BASIC_IMAGE + value: {{ template "backup.imageName" . }} + - name: BACKUP_FEATURES + value: {{ .Values.controller.backup.features }} + - name: BACKUP_SYSTEM_NAMESPACE + value: {{ .Values.controller.backup.namespace }} + - name: BACKUP_CTRL_REQUEUE_DURATION + value: {{ .Values.controller.backup.requeue }} image: {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }} imagePullPolicy: {{ .Values.image.pullPolicy }} diff --git a/templates/provider/hmc/templates/rbac/controller/roles.yaml b/templates/provider/hmc/templates/rbac/controller/roles.yaml index 5101a2519..22876c277 100644 --- a/templates/provider/hmc/templates/rbac/controller/roles.yaml +++ b/templates/provider/hmc/templates/rbac/controller/roles.yaml @@ -214,7 +214,9 @@ rules: - "" resources: - secrets - verbs: {{ include "rbac.viewerVerbs" . | nindent 4 }} + verbs: {{ include "rbac.viewerVerbs" . | nindent 2 }} + - create +# backup-ctrl - apiGroups: - hmc.mirantis.com resources: @@ -234,6 +236,50 @@ rules: - get - patch - update +- apiGroups: + - "" + resources: + - serviceaccounts + - namespaces + verbs: {{ include "rbac.viewerVerbs" . | nindent 2 }} + - create +- apiGroups: + - apps + resources: + - deployments + verbs: {{ include "rbac.viewerVerbs" . | nindent 2 }} + - create + - delete + - patch +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - clusterroles + - rolebindings + - roles + verbs: {{ include "rbac.viewerVerbs" . | nindent 2 }} + - create +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: {{ include "rbac.viewerVerbs" . | nindent 2 }} + - create +- apiGroups: + - velero.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - '*' + resources: + - '*' + verbs: + - list + - get +# backup-ctrl --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role diff --git a/templates/provider/hmc/templates/rbac/user-facing/backup-editor.yaml b/templates/provider/hmc/templates/rbac/user-facing/backup-editor.yaml index 6fae7787e..1b977a065 100644 --- a/templates/provider/hmc/templates/rbac/user-facing/backup-editor.yaml +++ b/templates/provider/hmc/templates/rbac/user-facing/backup-editor.yaml @@ -12,3 +12,8 @@ rules: - backups - backups/status verbs: {{ include "rbac.editorVerbs" . | nindent 6 }} +- apiGroups: + - velero.io + resources: + - '*' + verbs: {{ include "rbac.editorVerbs" . | nindent 6 }} diff --git a/templates/provider/hmc/templates/rbac/user-facing/backup-viewer.yaml b/templates/provider/hmc/templates/rbac/user-facing/backup-viewer.yaml index 373511342..c6b57f6fe 100644 --- a/templates/provider/hmc/templates/rbac/user-facing/backup-viewer.yaml +++ b/templates/provider/hmc/templates/rbac/user-facing/backup-viewer.yaml @@ -12,3 +12,8 @@ rules: - backups - backups/status verbs: {{ include "rbac.viewerVerbs" . | nindent 6 }} +- apiGroups: + - velero.io + resources: + - '*' + verbs: {{ include "rbac.viewerVerbs" . | nindent 6 }} diff --git a/templates/provider/hmc/values.yaml b/templates/provider/hmc/values.yaml index c7a899d0e..0a8795687 100644 --- a/templates/provider/hmc/values.yaml +++ b/templates/provider/hmc/values.yaml @@ -15,6 +15,14 @@ controller: createRelease: true createTemplates: true enableTelemetry: true + backup: + namespace: velero + features: "" + image: + repository: velero + name: velero + tag: v1.15.0 + requeue: 5s containerSecurityContext: allowPrivilegeEscalation: false diff --git a/test/objects/management/management.go b/test/objects/management/management.go index 25ec35967..77ae435ba 100644 --- a/test/objects/management/management.go +++ b/test/objects/management/management.go @@ -89,3 +89,9 @@ func WithRelease(v string) Opt { management.Spec.Release = v } } + +func WithBackup(v v1alpha1.ManagementBackup) Opt { + return func(management *v1alpha1.Management) { + management.Spec.Backup = v + } +} From 08237fdbd94fcaeb462b1403f7011ec3352dc1bf Mon Sep 17 00:00:00 2001 From: Andrey Pavlov Date: Mon, 6 Jan 2025 20:34:37 +0700 Subject: [PATCH 09/14] Wait for hmc helm release before proceeding with other components (#860) Signed-off-by: Andrei Pavlov --- internal/controller/management_controller.go | 13 ++ .../controller/management_controller_test.go | 167 +++++++++++------- 2 files changed, 116 insertions(+), 64 deletions(-) diff --git a/internal/controller/management_controller.go b/internal/controller/management_controller.go index bec983e95..54118b0f4 100644 --- a/internal/controller/management_controller.go +++ b/internal/controller/management_controller.go @@ -131,6 +131,19 @@ func (r *ManagementReconciler) Update(ctx context.Context, management *hmc.Manag for _, component := range components { l.V(1).Info("reconciling components", "component", component) + var notReadyDeps []string + for _, dep := range component.dependsOn { + if !statusAccumulator.components[dep.Name].Success { + notReadyDeps = append(notReadyDeps, dep.Name) + } + } + if len(notReadyDeps) > 0 { + errMsg := "Some dependencies are not ready yet. Waiting for " + strings.Join(notReadyDeps, ", ") + l.Info(errMsg, "template", component.Template) + updateComponentsStatus(statusAccumulator, component, nil, errMsg) + requeue = true + continue + } template := new(hmc.ProviderTemplate) if err := r.Get(ctx, client.ObjectKey{Name: component.Template}, template); err != nil { errMsg := fmt.Sprintf("Failed to get ProviderTemplate %s: %s", component.Template, err) diff --git a/internal/controller/management_controller_test.go b/internal/controller/management_controller_test.go index a78848989..90b85786b 100644 --- a/internal/controller/management_controller_test.go +++ b/internal/controller/management_controller_test.go @@ -34,7 +34,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - hmcmirantiscomv1alpha1 "github.com/K0rdent/kcm/api/v1alpha1" + kcmv1 "github.com/K0rdent/kcm/api/v1alpha1" "github.com/K0rdent/kcm/internal/utils" ) @@ -48,18 +48,18 @@ var _ = Describe("Management Controller", func() { Name: resourceName, Namespace: "default", } - management := &hmcmirantiscomv1alpha1.Management{} + management := &kcmv1.Management{} BeforeEach(func() { By("creating the custom resource for the Kind Management") err := k8sClient.Get(ctx, typeNamespacedName, management) if err != nil && apierrors.IsNotFound(err) { - resource := &hmcmirantiscomv1alpha1.Management{ + resource := &kcmv1.Management{ ObjectMeta: metav1.ObjectMeta{ Name: resourceName, Namespace: "default", }, - Spec: hmcmirantiscomv1alpha1.ManagementSpec{ + Spec: kcmv1.ManagementSpec{ Release: "test-release-name", }, } @@ -68,7 +68,7 @@ var _ = Describe("Management Controller", func() { }) AfterEach(func() { - resource := &hmcmirantiscomv1alpha1.Management{} + resource := &kcmv1.Management{} err := k8sClient.Get(ctx, typeNamespacedName, resource) Expect(err).NotTo(HaveOccurred()) @@ -114,13 +114,13 @@ var _ = Describe("Management Controller", func() { templateName string helmReleaseName string }{ - "hmc": { + kcmv1.CoreHMCName: { templateName: "test-release-hmc", - helmReleaseName: "hmc", + helmReleaseName: kcmv1.CoreHMCName, }, - "capi": { + kcmv1.CoreCAPIName: { templateName: "test-release-capi", - helmReleaseName: "capi", + helmReleaseName: kcmv1.CoreCAPIName, }, } @@ -136,14 +136,14 @@ var _ = Describe("Management Controller", func() { WithTimeout(10 * time.Second).WithPolling(250 * time.Millisecond).Should(Succeed()) By("Creating the Release object") - release := &hmcmirantiscomv1alpha1.Release{ + release := &kcmv1.Release{ ObjectMeta: metav1.ObjectMeta{ Name: "test-release-name", }, - Spec: hmcmirantiscomv1alpha1.ReleaseSpec{ + Spec: kcmv1.ReleaseSpec{ Version: "test-version", - HMC: hmcmirantiscomv1alpha1.CoreProviderTemplate{Template: coreComponents["hmc"].templateName}, - CAPI: hmcmirantiscomv1alpha1.CoreProviderTemplate{Template: coreComponents["capi"].templateName}, + HMC: kcmv1.CoreProviderTemplate{Template: coreComponents[kcmv1.CoreHMCName].templateName}, + CAPI: kcmv1.CoreProviderTemplate{Template: coreComponents[kcmv1.CoreCAPIName].templateName}, }, } Expect(k8sClient.Create(ctx, release)).To(Succeed()) @@ -151,12 +151,12 @@ var _ = Describe("Management Controller", func() { WithTimeout(10 * time.Second).WithPolling(250 * time.Millisecond).Should(Succeed()) By("Creating a ProviderTemplate object for other required components") - providerTemplateRequired := &hmcmirantiscomv1alpha1.ProviderTemplate{ + providerTemplateRequired := &kcmv1.ProviderTemplate{ ObjectMeta: metav1.ObjectMeta{ Name: providerTemplateRequiredComponent, }, - Spec: hmcmirantiscomv1alpha1.ProviderTemplateSpec{ - Helm: hmcmirantiscomv1alpha1.HelmSpec{ + Spec: kcmv1.ProviderTemplateSpec{ + Helm: kcmv1.HelmSpec{ ChartSpec: &sourcev1.HelmChartSpec{ Chart: "required-chart", Version: "required-version", @@ -165,9 +165,9 @@ var _ = Describe("Management Controller", func() { }, } Expect(k8sClient.Create(ctx, providerTemplateRequired)).To(Succeed()) - providerTemplateRequired.Status = hmcmirantiscomv1alpha1.ProviderTemplateStatus{ - TemplateStatusCommon: hmcmirantiscomv1alpha1.TemplateStatusCommon{ - TemplateValidationStatus: hmcmirantiscomv1alpha1.TemplateValidationStatus{ + providerTemplateRequired.Status = kcmv1.ProviderTemplateStatus{ + TemplateStatusCommon: kcmv1.TemplateStatusCommon{ + TemplateValidationStatus: kcmv1.TemplateValidationStatus{ Valid: true, }, ChartRef: &helmcontrollerv2.CrossNamespaceSourceReference{ @@ -185,7 +185,7 @@ var _ = Describe("Management Controller", func() { Name: helmReleaseName, Namespace: helmReleaseNamespace, Labels: map[string]string{ - hmcmirantiscomv1alpha1.HMCManagedLabelKey: hmcmirantiscomv1alpha1.HMCManagedLabelValue, + kcmv1.HMCManagedLabelKey: kcmv1.HMCManagedLabelValue, }, }, Spec: helmcontrollerv2.HelmReleaseSpec{ @@ -205,14 +205,14 @@ var _ = Describe("Management Controller", func() { Namespace: helmReleaseNamespace, OwnerReferences: []metav1.OwnerReference{ { - APIVersion: hmcmirantiscomv1alpha1.GroupVersion.String(), - Kind: hmcmirantiscomv1alpha1.ClusterDeploymentKind, + APIVersion: kcmv1.GroupVersion.String(), + Kind: kcmv1.ClusterDeploymentKind, Name: "any-owner-ref", UID: types.UID("some-owner-uid"), }, }, Labels: map[string]string{ - hmcmirantiscomv1alpha1.HMCManagedLabelKey: hmcmirantiscomv1alpha1.HMCManagedLabelValue, + kcmv1.HMCManagedLabelKey: kcmv1.HMCManagedLabelValue, }, }, Spec: helmcontrollerv2.HelmReleaseSpec{ @@ -226,27 +226,27 @@ var _ = Describe("Management Controller", func() { Expect(k8sClient.Create(ctx, someOtherHelmRelease)).To(Succeed()) By("Creating a Management object with removed component in the spec and containing it in the status") - mgmt := &hmcmirantiscomv1alpha1.Management{ + mgmt := &kcmv1.Management{ ObjectMeta: metav1.ObjectMeta{ Name: mgmtName, - Finalizers: []string{hmcmirantiscomv1alpha1.ManagementFinalizer}, + Finalizers: []string{kcmv1.ManagementFinalizer}, }, - Spec: hmcmirantiscomv1alpha1.ManagementSpec{ + Spec: kcmv1.ManagementSpec{ Release: release.Name, - Core: &hmcmirantiscomv1alpha1.Core{ - HMC: hmcmirantiscomv1alpha1.Component{ + Core: &kcmv1.Core{ + HMC: kcmv1.Component{ Template: providerTemplateRequiredComponent, }, - CAPI: hmcmirantiscomv1alpha1.Component{ + CAPI: kcmv1.Component{ Template: providerTemplateRequiredComponent, }, }, }, } Expect(k8sClient.Create(ctx, mgmt)).To(Succeed()) - mgmt.Status = hmcmirantiscomv1alpha1.ManagementStatus{ + mgmt.Status = kcmv1.ManagementStatus{ AvailableProviders: []string{someComponentName}, - Components: map[string]hmcmirantiscomv1alpha1.ComponentStatus{ + Components: map[string]kcmv1.ComponentStatus{ someComponentName: {Template: providerTemplateName}, }, } @@ -296,48 +296,87 @@ var _ = Describe("Management Controller", func() { By("Checking the Management object does not have the removed component in its spec") Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(mgmt), mgmt)).To(Succeed()) - Expect(mgmt.Status.AvailableProviders).To(BeEquivalentTo(hmcmirantiscomv1alpha1.Providers{"infrastructure-internal"})) + Expect(mgmt.Status.AvailableProviders).To(BeEquivalentTo(kcmv1.Providers{"infrastructure-internal"})) By("Checking the other (managed) helm-release has not been removed") Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(someOtherHelmRelease), someOtherHelmRelease)).To(Succeed()) By("Checking the Management components status is populated") Expect(mgmt.Status.Components).To(HaveLen(2)) // required: capi, hmc - Expect(mgmt.Status.Components).To(BeEquivalentTo(map[string]hmcmirantiscomv1alpha1.ComponentStatus{ - hmcmirantiscomv1alpha1.CoreHMCName: { + Expect(mgmt.Status.Components).To(BeEquivalentTo(map[string]kcmv1.ComponentStatus{ + kcmv1.CoreHMCName: { Success: false, Template: providerTemplateRequiredComponent, - Error: fmt.Sprintf("HelmRelease %s/%s Ready condition is not updated yet", helmReleaseNamespace, coreComponents["hmc"].helmReleaseName), + Error: fmt.Sprintf("HelmRelease %s/%s Ready condition is not updated yet", helmReleaseNamespace, coreComponents[kcmv1.CoreHMCName].helmReleaseName), }, - hmcmirantiscomv1alpha1.CoreCAPIName: { + kcmv1.CoreCAPIName: { Success: false, Template: providerTemplateRequiredComponent, - Error: fmt.Sprintf("HelmRelease %s/%s Ready condition is not updated yet", helmReleaseNamespace, coreComponents["capi"].helmReleaseName), + Error: "Some dependencies are not ready yet. Waiting for hmc", }, })) - By("Updating core HelmReleases with Ready condition") - for _, coreComponent := range coreComponents { - helmRelease := &helmcontrollerv2.HelmRelease{} - Expect(k8sClient.Get(ctx, types.NamespacedName{ - Namespace: helmReleaseNamespace, - Name: coreComponent.helmReleaseName, - }, helmRelease)).To(Succeed()) - - fluxconditions.Set(helmRelease, &metav1.Condition{ - Type: fluxmeta.ReadyCondition, - Reason: helmcontrollerv2.InstallSucceededReason, - Status: metav1.ConditionTrue, - }) - helmRelease.Status.History = helmcontrollerv2.Snapshots{ - { - Name: coreComponent.helmReleaseName, - FirstDeployed: metav1.Now(), - LastDeployed: metav1.Now(), - }, - } - Expect(k8sClient.Status().Update(ctx, helmRelease)).To(Succeed()) + By("Updating hmc HelmRelease with Ready condition") + helmRelease = &helmcontrollerv2.HelmRelease{} + Expect(k8sClient.Get(ctx, types.NamespacedName{ + Namespace: helmReleaseNamespace, + Name: coreComponents[kcmv1.CoreHMCName].helmReleaseName, + }, helmRelease)).To(Succeed()) + + fluxconditions.Set(helmRelease, &metav1.Condition{ + Type: fluxmeta.ReadyCondition, + Reason: helmcontrollerv2.InstallSucceededReason, + Status: metav1.ConditionTrue, + }) + helmRelease.Status.History = helmcontrollerv2.Snapshots{ + { + Name: coreComponents[kcmv1.CoreHMCName].helmReleaseName, + FirstDeployed: metav1.Now(), + LastDeployed: metav1.Now(), + }, + } + Expect(k8sClient.Status().Update(ctx, helmRelease)).To(Succeed()) + + By("Reconciling the Management object") + _, err = controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: client.ObjectKeyFromObject(mgmt), + }) + Expect(err).NotTo(HaveOccurred()) + + By("Checking the Management components status is populated") + Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(mgmt), mgmt)).To(Succeed()) + Expect(mgmt.Status.Components).To(BeEquivalentTo(map[string]kcmv1.ComponentStatus{ + kcmv1.CoreHMCName: { + Success: true, + Template: providerTemplateRequiredComponent, + }, + kcmv1.CoreCAPIName: { + Success: false, + Template: providerTemplateRequiredComponent, + Error: fmt.Sprintf("HelmRelease %s/%s Ready condition is not updated yet", helmReleaseNamespace, coreComponents[kcmv1.CoreCAPIName].helmReleaseName), + }, + })) + + By("Updating capi HelmRelease with Ready condition") + helmRelease = &helmcontrollerv2.HelmRelease{} + Expect(k8sClient.Get(ctx, types.NamespacedName{ + Namespace: helmReleaseNamespace, + Name: coreComponents[kcmv1.CoreCAPIName].helmReleaseName, + }, helmRelease)).To(Succeed()) + + fluxconditions.Set(helmRelease, &metav1.Condition{ + Type: fluxmeta.ReadyCondition, + Reason: helmcontrollerv2.InstallSucceededReason, + Status: metav1.ConditionTrue, + }) + helmRelease.Status.History = helmcontrollerv2.Snapshots{ + { + Name: coreComponents[kcmv1.CoreCAPIName].helmReleaseName, + FirstDeployed: metav1.Now(), + LastDeployed: metav1.Now(), + }, } + Expect(k8sClient.Status().Update(ctx, helmRelease)).To(Succeed()) By("Creating Cluster API CoreProvider object") coreProvider := &capioperator.CoreProvider{ @@ -380,9 +419,9 @@ var _ = Describe("Management Controller", func() { Expect(err).NotTo(HaveOccurred()) Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(mgmt), mgmt)).To(Succeed()) - Expect(mgmt.Status.Components).To(BeEquivalentTo(map[string]hmcmirantiscomv1alpha1.ComponentStatus{ - hmcmirantiscomv1alpha1.CoreHMCName: {Success: true, Template: providerTemplateRequiredComponent}, - hmcmirantiscomv1alpha1.CoreCAPIName: {Success: true, Template: providerTemplateRequiredComponent}, + Expect(mgmt.Status.Components).To(BeEquivalentTo(map[string]kcmv1.ComponentStatus{ + kcmv1.CoreHMCName: {Success: true, Template: providerTemplateRequiredComponent}, + kcmv1.CoreCAPIName: {Success: true, Template: providerTemplateRequiredComponent}, })) By("Removing the leftover objects") @@ -390,17 +429,17 @@ var _ = Describe("Management Controller", func() { Expect(k8sClient.Update(ctx, mgmt)).To(Succeed()) Expect(k8sClient.Delete(ctx, mgmt)).To(Succeed()) Eventually(func() bool { - return apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(mgmt), &hmcmirantiscomv1alpha1.Management{})) + return apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(mgmt), &kcmv1.Management{})) }).WithTimeout(timeout).WithPolling(interval).Should(BeTrue()) Expect(k8sClient.Delete(ctx, release)).To(Succeed()) Eventually(func() bool { - return apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(release), &hmcmirantiscomv1alpha1.Release{})) + return apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(release), &kcmv1.Release{})) }).WithTimeout(timeout).WithPolling(interval).Should(BeTrue()) Expect(k8sClient.Delete(ctx, providerTemplateRequired)).To(Succeed()) Eventually(func() bool { - return apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(providerTemplateRequired), &hmcmirantiscomv1alpha1.ProviderTemplate{})) + return apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(providerTemplateRequired), &kcmv1.ProviderTemplate{})) }).WithTimeout(timeout).WithPolling(interval).Should(BeTrue()) Expect(k8sClient.Delete(ctx, someOtherHelmRelease)).To(Succeed()) From c6ade422e97e01b5f978dcc189f1dd5ab8827826 Mon Sep 17 00:00:00 2001 From: Josef Hak Date: Mon, 6 Jan 2025 15:00:24 +0100 Subject: [PATCH 10/14] Makefile: fixes and improvements (#862) - fix comments to include some items to "make help" output - add useful "make help" instruction to docs/dev.md --- Makefile | 14 +++++++------- docs/dev.md | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index b6e5be649..bab327cb1 100644 --- a/Makefile +++ b/Makefile @@ -93,15 +93,15 @@ templates-generate: generate-all: generate manifests templates-generate add-license .PHONY: fmt -fmt: ## Run go fmt against code. +fmt: ## Run 'go fmt' against code. go fmt ./... .PHONY: vet -vet: ## Run go vet against code. +vet: ## Run 'go vet' against code. go vet ./... .PHONY: tidy -tidy: +tidy: ## Run 'go mod tidy' against code. go mod tidy .PHONY: test @@ -110,8 +110,8 @@ test: generate-all envtest tidy external-crd ## Run tests. # Utilize Kind or modify the e2e tests to load the image locally, enabling # compatibility with other vendors. -.PHONY: test-e2e # Run the e2e tests using a Kind k8s instance as the management cluster. -test-e2e: cli-install +.PHONY: test-e2e +test-e2e: cli-install ## Run the e2e tests using a Kind k8s instance as the management cluster. @if [ "$$GINKGO_LABEL_FILTER" ]; then \ ginkgo_label_flag="-ginkgo.label-filter=$$GINKGO_LABEL_FILTER"; \ fi; \ @@ -360,8 +360,8 @@ dev-aks-creds: envsubst dev-openstack-creds: envsubst @NAMESPACE=$(NAMESPACE) $(ENVSUBST) -no-unset -i config/dev/openstack-credentials.yaml | $(KUBECTL) apply -f - -.PHONY: dev-apply ## Apply the development environment by deploying the kind cluster, local registry and the HMC helm chart. -dev-apply: kind-deploy registry-deploy dev-push dev-deploy dev-templates dev-release +.PHONY: dev-apply +dev-apply: kind-deploy registry-deploy dev-push dev-deploy dev-templates dev-release ## Apply the development environment by deploying the kind cluster, local registry and the HMC helm chart. .PHONY: test-apply test-apply: set-hmc-version helm-package dev-deploy dev-templates dev-release diff --git a/docs/dev.md b/docs/dev.md index d6f2b13ef..af5b9d3f5 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -9,6 +9,7 @@ a managed cluster on AWS with k0s for testing. The kind cluster acts as manageme ```bash git clone https://github.com/K0rdent/kcm.git && cd kcm +make help # Check available commands ``` ### Install required CLIs From 0adc43fbe9e7a4e5e75c5997b75a1473447a0c8c Mon Sep 17 00:00:00 2001 From: Artem Bortnikov <26360954+BROngineer@users.noreply.github.com> Date: Mon, 6 Jan 2025 16:37:35 +0200 Subject: [PATCH 11/14] managedcluster-controller tests (#830) * managedcluster controller test Signed-off-by: Artem Bortnikov * minor rework Signed-off-by: Artem Bortnikov * rework objects creation in tests Signed-off-by: Artem Bortnikov * fix linting Signed-off-by: Artem Bortnikov * abstract interaction with helm by interface Signed-off-by: Artem Bortnikov * separate tests for dry-run and normal reconciliation Signed-off-by: Artem Bortnikov * enhance clusterdeployment tests Signed-off-by: Artem Bortnikov * update according to review comments Signed-off-by: Artem Bortnikov * fix shadowing ctx declaration Signed-off-by: Artem Bortnikov --------- Signed-off-by: Artem Bortnikov --- .golangci.yml | 2 +- Makefile | 13 +- .../clusterdeployment_controller.go | 35 +- .../clusterdeployment_controller_test.go | 595 ++++++++++++++---- .../controller/management_controller_test.go | 3 - .../multiclusterservice_controller_test.go | 2 - internal/controller/suite_test.go | 48 ++ .../controller/template_controller_test.go | 23 +- internal/helm/actor.go | 81 +++ 9 files changed, 639 insertions(+), 163 deletions(-) create mode 100644 internal/helm/actor.go diff --git a/.golangci.yml b/.golangci.yml index 1a29c45a3..eab84070a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -230,7 +230,7 @@ linters-settings: - ["call-chain", "loop", "method-call", "recover", "immediate-recover", "return"] - name: dot-imports arguments: - - { allowedPackages: ["github.com/onsi/ginkgo/v2","github.com/onsi/gomega"] } + - { allowedPackages: ["github.com/onsi/ginkgo/v2","github.com/onsi/gomega","sigs.k8s.io/controller-runtime/pkg/envtest/komega"] } - name: duplicated-imports - name: early-return - name: empty-block diff --git a/Makefile b/Makefile index bab327cb1..b718ef181 100644 --- a/Makefile +++ b/Makefile @@ -431,6 +431,10 @@ CAPI_OPERATOR_VERSION ?= v$(shell $(YQ) -r '.dependencies.[] | select(.name == " CAPI_OPERATOR_CRD_PREFIX ?= "operator.cluster.x-k8s.io_" CAPI_OPERATOR_CRDS ?= capi-operator-crds +CLUSTER_API_VERSION ?= v1.9.3 +CLUSTER_API_CRD_PREFIX ?= "cluster.x-k8s.io_" +CLUSTER_API_CRDS ?= cluster-api-crds + ## Tool Binaries KUBECTL ?= kubectl CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION) @@ -511,8 +515,15 @@ $(CAPI_OPERATOR_CRDS): | $(YQ) $(EXTERNAL_CRD_DIR) curl -s --fail https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-operator/$(CAPI_OPERATOR_VERSION)/config/crd/bases/$(CAPI_OPERATOR_CRD_PREFIX)${name}.yaml \ > $(EXTERNAL_CRD_DIR)/$(CAPI_OPERATOR_CRD_PREFIX)${name}-$(CAPI_OPERATOR_VERSION).yaml;) +$(CLUSTER_API_CRDS): | $(YQ) $(EXTERNAL_CRD_DIR) + rm -f $(EXTERNAL_CRD_DIR)/$(CLUSTER_API_CRD_PREFIX)* + @$(foreach name, \ + clusters machinedeployments, \ + curl -s --fail https://raw.githubusercontent.com/kubernetes-sigs/cluster-api/$(CLUSTER_API_VERSION)/config/crd/bases/$(CLUSTER_API_CRD_PREFIX)${name}.yaml \ + > $(EXTERNAL_CRD_DIR)/$(CLUSTER_API_CRD_PREFIX)${name}-$(CLUSTER_API_VERSION).yaml;) + .PHONY: external-crd -external-crd: $(FLUX_HELM_CRD) $(FLUX_SOURCE_CHART_CRD) $(FLUX_SOURCE_REPO_CRD) $(SVELTOS_CRD) $(CAPI_OPERATOR_CRDS) +external-crd: $(FLUX_HELM_CRD) $(FLUX_SOURCE_CHART_CRD) $(FLUX_SOURCE_REPO_CRD) $(SVELTOS_CRD) $(CAPI_OPERATOR_CRDS) $(CLUSTER_API_CRDS) .PHONY: kind kind: $(KIND) ## Download kind locally if necessary. diff --git a/internal/controller/clusterdeployment_controller.go b/internal/controller/clusterdeployment_controller.go index fb8381c10..f0b3bec30 100644 --- a/internal/controller/clusterdeployment_controller.go +++ b/internal/controller/clusterdeployment_controller.go @@ -60,9 +60,16 @@ const ( DefaultRequeueInterval = 10 * time.Second ) +type helmActor interface { + DownloadChartFromArtifact(ctx context.Context, artifact *sourcev1.Artifact) (*chart.Chart, error) + InitializeConfiguration(clusterDeployment *hmc.ClusterDeployment, log action.DebugLog) (*action.Configuration, error) + EnsureReleaseWithValues(ctx context.Context, actionConfig *action.Configuration, hcChart *chart.Chart, clusterDeployment *hmc.ClusterDeployment) error +} + // ClusterDeploymentReconciler reconciles a ClusterDeployment object type ClusterDeploymentReconciler struct { client.Client + helmActor Config *rest.Config DynamicClient *dynamic.DynamicClient SystemNamespace string @@ -128,7 +135,7 @@ func (r *ClusterDeploymentReconciler) setStatusFromChildObjects(ctx context.Cont if metaCondition.Reason == "" && metaCondition.Status == metav1.ConditionTrue { metaCondition.Message += " is Ready" - metaCondition.Reason = "Succeeded" + metaCondition.Reason = hmc.SucceededReason } apimeta.SetStatusCondition(clusterDeployment.GetConditions(), metaCondition) } @@ -231,7 +238,7 @@ func (r *ClusterDeploymentReconciler) updateCluster(ctx context.Context, mc *hmc return ctrl.Result{}, err } l.Info("Downloading Helm chart") - hcChart, err := helm.DownloadChartFromArtifact(ctx, source.GetArtifact()) + hcChart, err := r.DownloadChartFromArtifact(ctx, source.GetArtifact()) if err != nil { apimeta.SetStatusCondition(mc.GetConditions(), metav1.Condition{ Type: hmc.HelmChartReadyCondition, @@ -243,15 +250,13 @@ func (r *ClusterDeploymentReconciler) updateCluster(ctx context.Context, mc *hmc } l.Info("Initializing Helm client") - getter := helm.NewMemoryRESTClientGetter(r.Config, r.RESTMapper()) - actionConfig := new(action.Configuration) - err = actionConfig.Init(getter, mc.Namespace, "secret", l.Info) + actionConfig, err := r.InitializeConfiguration(mc, l.Info) if err != nil { return ctrl.Result{}, err } l.Info("Validating Helm chart with provided values") - if err := validateReleaseWithValues(ctx, actionConfig, mc, hcChart); err != nil { + if err = r.EnsureReleaseWithValues(ctx, actionConfig, hcChart, mc); err != nil { apimeta.SetStatusCondition(mc.GetConditions(), metav1.Condition{ Type: hmc.HelmChartReadyCondition, Status: metav1.ConditionFalse, @@ -492,22 +497,6 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *hm return ctrl.Result{}, nil } -func validateReleaseWithValues(ctx context.Context, actionConfig *action.Configuration, clusterDeployment *hmc.ClusterDeployment, hcChart *chart.Chart) error { - install := action.NewInstall(actionConfig) - install.DryRun = true - install.ReleaseName = clusterDeployment.Name - install.Namespace = clusterDeployment.Namespace - install.ClientOnly = true - - vals, err := clusterDeployment.HelmValues() - if err != nil { - return err - } - - _, err = install.RunWithContext(ctx, hcChart, vals) - return err -} - // updateStatus updates the status for the ClusterDeployment object. func (r *ClusterDeploymentReconciler) updateStatus(ctx context.Context, clusterDeployment *hmc.ClusterDeployment, template *hmc.ClusterTemplate) error { clusterDeployment.Status.ObservedGeneration = clusterDeployment.Generation @@ -854,6 +843,8 @@ func (r *ClusterDeploymentReconciler) setAvailableUpgrades(ctx context.Context, // SetupWithManager sets up the controller with the Manager. func (r *ClusterDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error { + r.helmActor = helm.NewActor(r.Config, r.RESTMapper()) + return ctrl.NewControllerManagedBy(mgr). For(&hmc.ClusterDeployment{}). Watches(&hcv2.HelmRelease{}, diff --git a/internal/controller/clusterdeployment_controller_test.go b/internal/controller/clusterdeployment_controller_test.go index bf6109a37..0c62feccd 100644 --- a/internal/controller/clusterdeployment_controller_test.go +++ b/internal/controller/clusterdeployment_controller_test.go @@ -19,142 +19,214 @@ import ( "time" hcv2 "github.com/fluxcd/helm-controller/api/v2" + meta2 "github.com/fluxcd/pkg/apis/meta" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chart" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/rest" + clusterapiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + . "sigs.k8s.io/controller-runtime/pkg/envtest/komega" "sigs.k8s.io/controller-runtime/pkg/reconcile" hmc "github.com/K0rdent/kcm/api/v1alpha1" ) +type fakeHelmActor struct{} + +func (*fakeHelmActor) DownloadChartFromArtifact(_ context.Context, _ *sourcev1.Artifact) (*chart.Chart, error) { + return &chart.Chart{ + Metadata: &chart.Metadata{ + APIVersion: "v2", + Version: "0.1.0", + Name: "test-cluster-chart", + }, + }, nil +} + +func (*fakeHelmActor) InitializeConfiguration(_ *hmc.ClusterDeployment, _ action.DebugLog) (*action.Configuration, error) { + return &action.Configuration{}, nil +} + +func (*fakeHelmActor) EnsureReleaseWithValues(_ context.Context, _ *action.Configuration, _ *chart.Chart, _ *hmc.ClusterDeployment) error { + return nil +} + var _ = Describe("ClusterDeployment Controller", func() { Context("When reconciling a resource", func() { const ( - clusterDeploymentName = "test-cluster-deployment" - clusterDeploymentNamespace = "test" - - templateName = "test-template" - svcTemplateName = "test-svc-template" - credentialName = "test-credential" + helmChartURL = "http://source-controller.hmc-system.svc.cluster.local/helmchart/hmc-system/test-chart/0.1.0.tar.gz" ) - ctx := context.Background() + // resources required for ClusterDeployment reconciliation + var ( + namespace = corev1.Namespace{} + secret = corev1.Secret{} + awsCredential = hmc.Credential{} + clusterTemplate = hmc.ClusterTemplate{} + serviceTemplate = hmc.ServiceTemplate{} + helmRepo = sourcev1.HelmRepository{} + clusterTemplateHelmChart = sourcev1.HelmChart{} + serviceTemplateHelmChart = sourcev1.HelmChart{} + + clusterDeployment = hmc.ClusterDeployment{} - typeNamespacedName := types.NamespacedName{ - Name: clusterDeploymentName, - Namespace: clusterDeploymentNamespace, - } - clusterDeployment := &hmc.ClusterDeployment{} - template := &hmc.ClusterTemplate{} - svcTemplate := &hmc.ServiceTemplate{} - management := &hmc.Management{} - credential := &hmc.Credential{} - namespace := &corev1.Namespace{} + cluster = clusterapiv1beta1.Cluster{} + machineDeployment = clusterapiv1beta1.MachineDeployment{} + helmRelease = hcv2.HelmRelease{} + ) BeforeEach(func() { - By("creating ClusterDeployment namespace") - err := k8sClient.Get(ctx, types.NamespacedName{Name: clusterDeploymentNamespace}, namespace) - if err != nil && errors.IsNotFound(err) { - namespace = &corev1.Namespace{ + By("ensure namespace", func() { + namespace = corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ - Name: clusterDeploymentNamespace, + GenerateName: "test-namespace-", }, } - Expect(k8sClient.Create(ctx, namespace)).To(Succeed()) - } + Expect(k8sClient.Create(ctx, &namespace)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &namespace) + }) + + By("ensure HelmRepository resource", func() { + helmRepo = sourcev1.HelmRepository{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "test-repository-", + Namespace: namespace.Name, + }, + Spec: sourcev1.HelmRepositorySpec{ + Insecure: true, + Interval: metav1.Duration{ + Duration: 10 * time.Minute, + }, + Provider: "generic", + Type: "oci", + URL: "oci://hmc-local-registry:5000/charts", + }, + } + Expect(k8sClient.Create(ctx, &helmRepo)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &helmRepo) + }) - By("creating the custom resource for the Kind ClusterTemplate") - err = k8sClient.Get(ctx, typeNamespacedName, template) - if err != nil && errors.IsNotFound(err) { - template = &hmc.ClusterTemplate{ + By("ensure HelmChart resources", func() { + clusterTemplateHelmChart = sourcev1.HelmChart{ ObjectMeta: metav1.ObjectMeta{ - Name: templateName, - Namespace: clusterDeploymentNamespace, + GenerateName: "test-cluster-template-chart-", + Namespace: namespace.Name, + }, + Spec: sourcev1.HelmChartSpec{ + Chart: "test-cluster", + Interval: metav1.Duration{ + Duration: 10 * time.Minute, + }, + ReconcileStrategy: sourcev1.ReconcileStrategyChartVersion, + SourceRef: sourcev1.LocalHelmChartSourceReference{ + Kind: "HelmRepository", + Name: helmRepo.Name, + }, + Version: "0.1.0", + }, + } + Expect(k8sClient.Create(ctx, &clusterTemplateHelmChart)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &clusterTemplateHelmChart) + + serviceTemplateHelmChart = sourcev1.HelmChart{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "test-service-template-chart-", + Namespace: namespace.Name, + }, + Spec: sourcev1.HelmChartSpec{ + Chart: "test-service", + Interval: metav1.Duration{ + Duration: 10 * time.Minute, + }, + ReconcileStrategy: sourcev1.ReconcileStrategyChartVersion, + SourceRef: sourcev1.LocalHelmChartSourceReference{ + Kind: "HelmRepository", + Name: helmRepo.Name, + }, + Version: "0.1.0", + }, + } + Expect(k8sClient.Create(ctx, &serviceTemplateHelmChart)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &serviceTemplateHelmChart) + }) + + By("ensure ClusterTemplate resource", func() { + clusterTemplate = hmc.ClusterTemplate{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "test-cluster-template-", + Namespace: namespace.Name, }, Spec: hmc.ClusterTemplateSpec{ Helm: hmc.HelmSpec{ ChartRef: &hcv2.CrossNamespaceSourceReference{ Kind: "HelmChart", - Name: "ref-test", - Namespace: "default", + Name: clusterTemplateHelmChart.Name, + Namespace: namespace.Name, }, }, }, } - Expect(k8sClient.Create(ctx, template)).To(Succeed()) - template.Status = hmc.ClusterTemplateStatus{ + Expect(k8sClient.Create(ctx, &clusterTemplate)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &clusterTemplate) + + clusterTemplate.Status = hmc.ClusterTemplateStatus{ TemplateStatusCommon: hmc.TemplateStatusCommon{ TemplateValidationStatus: hmc.TemplateValidationStatus{ Valid: true, }, - Config: &apiextensionsv1.JSON{ - Raw: []byte(`{"foo":"bar"}`), - }, }, Providers: hmc.Providers{"infrastructure-aws"}, } - Expect(k8sClient.Status().Update(ctx, template)).To(Succeed()) - } + Expect(k8sClient.Status().Update(ctx, &clusterTemplate)).To(Succeed()) + }) - By("creating the custom resource for the Kind ServiceTemplate") - err = k8sClient.Get(ctx, client.ObjectKey{Namespace: clusterDeploymentNamespace, Name: svcTemplateName}, svcTemplate) - if err != nil && errors.IsNotFound(err) { - svcTemplate = &hmc.ServiceTemplate{ + By("ensure ServiceTemplate resource", func() { + serviceTemplate = hmc.ServiceTemplate{ ObjectMeta: metav1.ObjectMeta{ - Name: svcTemplateName, - Namespace: clusterDeploymentNamespace, + GenerateName: "test-service-template-", + Namespace: namespace.Name, }, Spec: hmc.ServiceTemplateSpec{ Helm: hmc.HelmSpec{ ChartRef: &hcv2.CrossNamespaceSourceReference{ Kind: "HelmChart", - Name: "ref-test", - Namespace: "default", + Name: serviceTemplateHelmChart.Name, + Namespace: namespace.Name, }, }, }, } - Expect(k8sClient.Create(ctx, svcTemplate)).To(Succeed()) - svcTemplate.Status = hmc.ServiceTemplateStatus{ + Expect(k8sClient.Create(ctx, &serviceTemplate)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &serviceTemplate) + + serviceTemplate.Status = hmc.ServiceTemplateStatus{ TemplateStatusCommon: hmc.TemplateStatusCommon{ + ChartRef: &hcv2.CrossNamespaceSourceReference{ + Kind: "HelmChart", + Name: serviceTemplateHelmChart.Name, + Namespace: namespace.Name, + }, TemplateValidationStatus: hmc.TemplateValidationStatus{ Valid: true, }, }, } - Expect(k8sClient.Status().Update(ctx, svcTemplate)).To(Succeed()) - } + Expect(k8sClient.Status().Update(ctx, &serviceTemplate)).To(Succeed()) + }) - By("creating the custom resource for the Kind Management") - err = k8sClient.Get(ctx, typeNamespacedName, management) - if err != nil && errors.IsNotFound(err) { - management = &hmc.Management{ - ObjectMeta: metav1.ObjectMeta{ - Name: hmc.ManagementName, - }, - Spec: hmc.ManagementSpec{ - Release: "test-release", - }, - } - Expect(k8sClient.Create(ctx, management)).To(Succeed()) - management.Status = hmc.ManagementStatus{ - AvailableProviders: hmc.Providers{"infrastructure-aws"}, - } - Expect(k8sClient.Status().Update(ctx, management)).To(Succeed()) - } - By("creating the custom resource for the Kind Credential") - err = k8sClient.Get(ctx, typeNamespacedName, credential) - if err != nil && errors.IsNotFound(err) { - credential = &hmc.Credential{ + By("ensure AWS Credential resource", func() { + awsCredential = hmc.Credential{ ObjectMeta: metav1.ObjectMeta{ - Name: credentialName, - Namespace: clusterDeploymentNamespace, + GenerateName: "test-credential-aws-", + Namespace: namespace.Name, }, Spec: hmc.CredentialSpec{ IdentityRef: &corev1.ObjectReference{ @@ -164,65 +236,358 @@ var _ = Describe("ClusterDeployment Controller", func() { }, }, } - Expect(k8sClient.Create(ctx, credential)).To(Succeed()) - credential.Status = hmc.CredentialStatus{ + Expect(k8sClient.Create(ctx, &awsCredential)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &awsCredential) + + awsCredential.Status = hmc.CredentialStatus{ Ready: true, } - Expect(k8sClient.Status().Update(ctx, credential)).To(Succeed()) + Expect(k8sClient.Status().Update(ctx, &awsCredential)).To(Succeed()) + }) + }) + + AfterEach(func() { + By("cleanup finalizer", func() { + Expect(controllerutil.RemoveFinalizer(&clusterDeployment, hmc.ClusterDeploymentFinalizer)).To(BeTrue()) + Expect(k8sClient.Update(ctx, &clusterDeployment)).To(Succeed()) + }) + }) + + It("should reconcile ClusterDeployment in dry-run mode", func() { + controllerReconciler := &ClusterDeploymentReconciler{ + Client: mgrClient, + helmActor: &fakeHelmActor{}, + Config: &rest.Config{}, } - By("creating the custom resource for the Kind ClusterDeployment") - err = k8sClient.Get(ctx, typeNamespacedName, clusterDeployment) - if err != nil && errors.IsNotFound(err) { - clusterDeployment = &hmc.ClusterDeployment{ + By("creating ClusterDeployment resource", func() { + clusterDeployment = hmc.ClusterDeployment{ ObjectMeta: metav1.ObjectMeta{ - Name: clusterDeploymentName, - Namespace: clusterDeploymentNamespace, + GenerateName: "test-cluster-deployment-", + Namespace: namespace.Name, }, Spec: hmc.ClusterDeploymentSpec{ - Template: templateName, - Credential: credentialName, + Template: clusterTemplate.Name, + Credential: awsCredential.Name, + DryRun: true, + }, + } + Expect(k8sClient.Create(ctx, &clusterDeployment)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &clusterDeployment) + }) + + By("ensuring finalizer is added", func() { + Eventually(func(g Gomega) { + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: client.ObjectKeyFromObject(&clusterDeployment), + }) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(Object(&clusterDeployment)()).Should(SatisfyAll( + HaveField("Finalizers", ContainElement(hmc.ClusterDeploymentFinalizer)), + )) + }).Should(Succeed()) + }) + + By("reconciling resource with finalizer", func() { + Eventually(func(g Gomega) { + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: client.ObjectKeyFromObject(&clusterDeployment), + }) + g.Expect(err).To(HaveOccurred()) + g.Expect(Object(&clusterDeployment)()).Should(SatisfyAll( + HaveField("Status.Conditions", ContainElement(SatisfyAll( + HaveField("Type", hmc.TemplateReadyCondition), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + HaveField("Message", "Template is valid"), + ))), + )) + }).Should(Succeed()) + }) + + By("reconciling when dependencies are not in valid state", func() { + Eventually(func(g Gomega) { + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: client.ObjectKeyFromObject(&clusterDeployment), + }) + g.Expect(err).To(HaveOccurred()) + g.Expect(err.Error()).To(ContainSubstring("helm chart source is not provided")) + }).Should(Succeed()) + }) + + By("patching ClusterTemplate and corresponding HelmChart statuses", func() { + Expect(Get(&clusterTemplate)()).To(Succeed()) + clusterTemplate.Status.ChartRef = &hcv2.CrossNamespaceSourceReference{ + Kind: "HelmChart", + Name: clusterTemplateHelmChart.Name, + Namespace: namespace.Name, + } + Expect(k8sClient.Status().Update(ctx, &clusterTemplate)).To(Succeed()) + + Expect(Get(&clusterTemplateHelmChart)()).To(Succeed()) + clusterTemplateHelmChart.Status.URL = helmChartURL + clusterTemplateHelmChart.Status.Artifact = &sourcev1.Artifact{ + URL: helmChartURL, + LastUpdateTime: metav1.Now(), + } + Expect(k8sClient.Status().Update(ctx, &clusterTemplateHelmChart)).To(Succeed()) + + Eventually(func(g Gomega) { + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: client.ObjectKeyFromObject(&clusterDeployment), + }) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(Object(&clusterDeployment)()).Should(SatisfyAll( + HaveField("Status.Conditions", ContainElements( + SatisfyAll( + HaveField("Type", hmc.HelmChartReadyCondition), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + HaveField("Message", "Helm chart is valid"), + ), + SatisfyAll( + HaveField("Type", hmc.CredentialReadyCondition), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + HaveField("Message", "Credential is Ready"), + ), + )))) + }).Should(Succeed()) + }) + }) + + It("should reconcile ClusterDeployment with AWS credentials", func() { + controllerReconciler := &ClusterDeploymentReconciler{ + Client: mgrClient, + helmActor: &fakeHelmActor{}, + Config: &rest.Config{}, + DynamicClient: dynamicClient, + } + + By("creating ClusterDeployment resource", func() { + clusterDeployment = hmc.ClusterDeployment{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "test-cluster-deployment-", + Namespace: namespace.Name, + }, + Spec: hmc.ClusterDeploymentSpec{ + Template: clusterTemplate.Name, + Credential: awsCredential.Name, Services: []hmc.ServiceSpec{ { - Template: svcTemplateName, - Name: "test-svc-name", + Template: serviceTemplate.Name, + Name: "test-service", }, }, + Config: &apiextensionsv1.JSON{ + Raw: []byte(`{"foo":"bar"}`), + }, }, } - Expect(k8sClient.Create(ctx, clusterDeployment)).To(Succeed()) - } - }) + Expect(k8sClient.Create(ctx, &clusterDeployment)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &clusterDeployment) + }) - AfterEach(func() { - By("Cleanup") + By("ensuring related resources exist", func() { + Expect(Get(&clusterTemplate)()).To(Succeed()) + clusterTemplate.Status.ChartRef = &hcv2.CrossNamespaceSourceReference{ + Kind: "HelmChart", + Name: clusterTemplateHelmChart.Name, + Namespace: namespace.Name, + } + Expect(k8sClient.Status().Update(ctx, &clusterTemplate)).To(Succeed()) - controllerReconciler := &ClusterDeploymentReconciler{ - Client: k8sClient, - } + Expect(Get(&clusterTemplateHelmChart)()).To(Succeed()) + clusterTemplateHelmChart.Status.URL = helmChartURL + clusterTemplateHelmChart.Status.Artifact = &sourcev1.Artifact{ + URL: helmChartURL, + LastUpdateTime: metav1.Now(), + } + Expect(k8sClient.Status().Update(ctx, &clusterTemplateHelmChart)).To(Succeed()) + + cluster = clusterapiv1beta1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterDeployment.Name, + Namespace: namespace.Name, + Labels: map[string]string{hmc.FluxHelmChartNameKey: clusterDeployment.Name}, + }, + } + Expect(k8sClient.Create(ctx, &cluster)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &cluster) - Expect(k8sClient.Delete(ctx, clusterDeployment)).To(Succeed()) - // Running reconcile to remove the finalizer and delete the ClusterDeployment - _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{NamespacedName: typeNamespacedName}) - Expect(err).NotTo(HaveOccurred()) + machineDeployment = clusterapiv1beta1.MachineDeployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterDeployment.Name + "-md", + Namespace: namespace.Name, + Labels: map[string]string{hmc.FluxHelmChartNameKey: clusterDeployment.Name}, + }, + Spec: clusterapiv1beta1.MachineDeploymentSpec{ + ClusterName: cluster.Name, + Template: clusterapiv1beta1.MachineTemplateSpec{ + Spec: clusterapiv1beta1.MachineSpec{ + ClusterName: cluster.Name, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, &machineDeployment)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &machineDeployment) - Eventually(k8sClient.Get, 1*time.Minute, 5*time.Second).WithArguments(ctx, typeNamespacedName, clusterDeployment).Should(HaveOccurred()) + secret = corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterDeployment.Name + "-kubeconfig", + Namespace: namespace.Name, + }, + } + Expect(k8sClient.Create(ctx, &secret)).To(Succeed()) + DeferCleanup(k8sClient.Delete, &secret) + }) - Expect(k8sClient.Delete(ctx, template)).To(Succeed()) - Expect(k8sClient.Delete(ctx, management)).To(Succeed()) - Expect(k8sClient.Delete(ctx, namespace)).To(Succeed()) - }) - It("should successfully reconcile the resource", func() { - By("Reconciling the created resource") - controllerReconciler := &ClusterDeploymentReconciler{ - Client: k8sClient, - Config: &rest.Config{}, - } + By("ensuring conditions updates after reconciliation", func() { + Eventually(func(g Gomega) { + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: client.ObjectKeyFromObject(&clusterDeployment), + }) + g.Expect(err).To(HaveOccurred()) + g.Expect(Object(&clusterDeployment)()).Should(SatisfyAll( + HaveField("Finalizers", ContainElement(hmc.ClusterDeploymentFinalizer)), + HaveField("Status.Conditions", ContainElements( + SatisfyAll( + HaveField("Type", hmc.TemplateReadyCondition), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + HaveField("Message", "Template is valid"), + ), + SatisfyAll( + HaveField("Type", hmc.HelmChartReadyCondition), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + HaveField("Message", "Helm chart is valid"), + ), + SatisfyAll( + HaveField("Type", hmc.CredentialReadyCondition), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + HaveField("Message", "Credential is Ready"), + ), + )))) + }).Should(Succeed()) + }) - _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ - NamespacedName: typeNamespacedName, + By("ensuring related resources in proper state", func() { + helmRelease = hcv2.HelmRelease{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterDeployment.Name, + Namespace: namespace.Name, + }, + } + Expect(Get(&helmRelease)()).To(Succeed()) + meta.SetStatusCondition(&helmRelease.Status.Conditions, metav1.Condition{ + Type: meta2.ReadyCondition, + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Now(), + Reason: hcv2.InstallSucceededReason, + }) + Expect(k8sClient.Status().Update(ctx, &helmRelease)).To(Succeed()) + + Expect(Get(&cluster)()).To(Succeed()) + cluster.SetConditions([]clusterapiv1beta1.Condition{ + { + Type: clusterapiv1beta1.ControlPlaneInitializedCondition, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + }, + { + Type: clusterapiv1beta1.ControlPlaneReadyCondition, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + }, + { + Type: clusterapiv1beta1.InfrastructureReadyCondition, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + }, + }) + Expect(k8sClient.Status().Update(ctx, &cluster)).To(Succeed()) + + Expect(Get(&machineDeployment)()).To(Succeed()) + machineDeployment.SetConditions([]clusterapiv1beta1.Condition{ + { + Type: clusterapiv1beta1.MachineDeploymentAvailableCondition, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + }, + }) + Expect(k8sClient.Status().Update(ctx, &machineDeployment)).To(Succeed()) }) - Expect(err).NotTo(HaveOccurred()) + + By("ensuring ClusterDeployment is reconciled", func() { + Eventually(func(g Gomega) { + _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ + NamespacedName: client.ObjectKeyFromObject(&clusterDeployment), + }) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(Object(&clusterDeployment)()).Should(SatisfyAll( + HaveField("Status.Conditions", ContainElements( + SatisfyAll( + HaveField("Type", hmc.HelmReleaseReadyCondition), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hcv2.InstallSucceededReason), + ), + SatisfyAll( + HaveField("Type", hmc.SveltosProfileReadyCondition), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + ), + SatisfyAll( + HaveField("Type", string(clusterapiv1beta1.ControlPlaneInitializedCondition)), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + ), + SatisfyAll( + HaveField("Type", string(clusterapiv1beta1.ControlPlaneReadyCondition)), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + ), + SatisfyAll( + HaveField("Type", string(clusterapiv1beta1.InfrastructureReadyCondition)), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + ), + SatisfyAll( + HaveField("Type", string(clusterapiv1beta1.MachineDeploymentAvailableCondition)), + HaveField("Status", metav1.ConditionTrue), + HaveField("Reason", hmc.SucceededReason), + ), + // TODO (#852 brongineer): add corresponding resources with expected state for successful reconciliation + // SatisfyAll( + // HaveField("Type", hmc.FetchServicesStatusSuccessCondition), + // HaveField("Status", metav1.ConditionTrue), + // HaveField("Reason", hmc.SucceededReason), + // ), + // SatisfyAll( + // HaveField("Type", hmc.ReadyCondition), + // HaveField("Status", metav1.ConditionTrue), + // HaveField("Reason", hmc.SucceededReason), + // ), + )))) + }).Should(Succeed()) + }) + }) + + // TODO (#852 brongineer): Add test for ClusterDeployment reconciliation with Azure credentials + PIt("should reconcile ClusterDeployment with Azure credentials", func() { + // TBD + }) + + // TODO (#852 brongineer): Add tests for ClusterDeployment reconciliation with other providers' credentials + PIt("should reconcile ClusterDeployment with XXX credentials", func() { + // TBD + }) + + // TODO (#852 brongineer): Add test for ClusterDeployment deletion + PIt("should reconcile ClusterDeployment deletion", func() { + // TBD }) }) }) diff --git a/internal/controller/management_controller_test.go b/internal/controller/management_controller_test.go index 90b85786b..39bd600b7 100644 --- a/internal/controller/management_controller_test.go +++ b/internal/controller/management_controller_test.go @@ -15,7 +15,6 @@ package controller import ( - "context" "fmt" "time" @@ -42,8 +41,6 @@ var _ = Describe("Management Controller", func() { Context("When reconciling a resource", func() { const resourceName = "test-resource" - ctx := context.Background() - typeNamespacedName := types.NamespacedName{ Name: resourceName, Namespace: "default", diff --git a/internal/controller/multiclusterservice_controller_test.go b/internal/controller/multiclusterservice_controller_test.go index 8e4270b89..d8094774f 100644 --- a/internal/controller/multiclusterservice_controller_test.go +++ b/internal/controller/multiclusterservice_controller_test.go @@ -56,8 +56,6 @@ var _ = Describe("MultiClusterService Controller", func() { }, nil } - ctx := context.Background() - namespace := &corev1.Namespace{} helmChart := &sourcev1.HelmChart{} helmRepo := &sourcev1.HelmRepository{} diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 33a2bcf08..5632b2bef 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -32,14 +32,18 @@ import ( . "github.com/onsi/gomega" sveltosv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1" admissionv1 "k8s.io/api/admissionregistration/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" capioperator "sigs.k8s.io/cluster-api-operator/api/v1alpha2" + clusterapiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1" utilyaml "sigs.k8s.io/cluster-api/util/yaml" 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/envtest/komega" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" @@ -56,6 +60,9 @@ const ( mutatingWebhookKind = "MutatingWebhookConfiguration" validatingWebhookKind = "ValidatingWebhookConfiguration" testSystemNamespace = "test-system-namespace" + + pollingInterval = 30 * time.Millisecond + eventuallyTimeout = 3 * time.Second ) var ( @@ -69,6 +76,8 @@ var ( ) func TestControllers(t *testing.T) { + SetDefaultEventuallyPollingInterval(pollingInterval) + SetDefaultEventuallyTimeout(eventuallyTimeout) RegisterFailHandler(Fail) RunSpecs(t, "Controller Suite") @@ -120,12 +129,15 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) err = capioperator.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + err = clusterapiv1beta1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) // +kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) + SetClient(k8sClient) dynamicClient, err = dynamic.NewForConfig(cfg) Expect(err).NotTo(HaveOccurred()) @@ -198,6 +210,8 @@ var _ = BeforeSuite(func() { } return conn.Close() }).Should(Succeed()) + + Expect(seedClusterScopedResources(ctx, k8sClient)).To(Succeed()) }) var _ = AfterSuite(func() { @@ -245,3 +259,37 @@ func loadWebhooks(path string) ([]*admissionv1.ValidatingWebhookConfiguration, [ } return validatingWebhooks, mutatingWebhooks, err } + +func seedClusterScopedResources(ctx context.Context, k8sClient client.Client) error { + var ( + someProviderName = "test-provider-name" + otherProviderName = "test-provider-name-other" + someExposedContract = "v1beta1_v1beta2" + otherExposedContract = "v1beta1" + capiVersion = "v1beta1" + ) + management := &hmcmirantiscomv1alpha1.Management{} + + By("creating the custom resource for the Kind Management") + managementKey := client.ObjectKey{ + Name: hmcmirantiscomv1alpha1.ManagementName, + } + err := mgrClient.Get(ctx, managementKey, management) + if errors.IsNotFound(err) { + management = &hmcmirantiscomv1alpha1.Management{ + ObjectMeta: metav1.ObjectMeta{ + Name: hmcmirantiscomv1alpha1.ManagementName, + }, + Spec: hmcmirantiscomv1alpha1.ManagementSpec{ + Release: "test-release", + }, + } + Expect(k8sClient.Create(ctx, management)).To(Succeed()) + management.Status = hmcmirantiscomv1alpha1.ManagementStatus{ + AvailableProviders: []string{someProviderName, otherProviderName}, + CAPIContracts: map[string]hmcmirantiscomv1alpha1.CompatibilityContracts{someProviderName: {capiVersion: someExposedContract}, otherProviderName: {capiVersion: otherExposedContract}}, + } + Expect(k8sClient.Status().Update(ctx, management)).To(Succeed()) + } + return client.IgnoreNotFound(err) +} diff --git a/internal/controller/template_controller_test.go b/internal/controller/template_controller_test.go index c01e58793..6402aef4f 100644 --- a/internal/controller/template_controller_test.go +++ b/internal/controller/template_controller_test.go @@ -257,22 +257,9 @@ var _ = Describe("Template Controller", func() { return nil }).WithTimeout(timeout).WithPolling(interval).Should(Succeed()) - By("Creating a management cluster object with proper required versions in status") - // must set status here since it's controller by another ctrl - mgmt := &hmcmirantiscomv1alpha1.Management{ - ObjectMeta: metav1.ObjectMeta{ - Name: mgmtName, - }, - Spec: hmcmirantiscomv1alpha1.ManagementSpec{ - Release: "test-release", - }, - } - Expect(k8sClient.Create(ctx, mgmt)).To(Succeed()) - mgmt.Status = hmcmirantiscomv1alpha1.ManagementStatus{ - AvailableProviders: []string{someProviderName, otherProviderName}, - CAPIContracts: map[string]hmcmirantiscomv1alpha1.CompatibilityContracts{someProviderName: {capiVersion: someExposedContract}, otherProviderName: {capiVersion: otherExposedContract}}, - } - Expect(k8sClient.Status().Update(ctx, mgmt)).To(Succeed()) + mgmt := &hmcmirantiscomv1alpha1.Management{} + key := client.ObjectKey{Name: mgmtName} + Expect(k8sClient.Get(ctx, key, mgmt)).To(Succeed()) By("Checking the management cluster appears") Eventually(func() error { @@ -324,13 +311,11 @@ var _ = Describe("Template Controller", func() { Expect(clusterTemplate.Status.ProviderContracts).To(BeEquivalentTo(map[string]string{otherProviderName: otherRequiredContract, someProviderName: someRequiredContract})) By("Removing the created objects") - Expect(k8sClient.Delete(ctx, mgmt)).To(Succeed()) Expect(k8sClient.Delete(ctx, clusterTemplate)).To(Succeed()) By("Checking the created objects have been removed") Eventually(func() bool { - return apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(mgmt), &hmcmirantiscomv1alpha1.Management{})) && - apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterTemplate), &hmcmirantiscomv1alpha1.ClusterTemplate{})) + return apierrors.IsNotFound(k8sClient.Get(ctx, client.ObjectKeyFromObject(clusterTemplate), &hmcmirantiscomv1alpha1.ClusterTemplate{})) }).WithTimeout(timeout).WithPolling(interval).Should(BeTrue()) }) }) diff --git a/internal/helm/actor.go b/internal/helm/actor.go new file mode 100644 index 000000000..f33ba08a6 --- /dev/null +++ b/internal/helm/actor.go @@ -0,0 +1,81 @@ +// Copyright 2024 +// +// 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 helm + +import ( + "context" + "errors" + + sourcev1 "github.com/fluxcd/source-controller/api/v1" + "helm.sh/helm/v3/pkg/action" + "helm.sh/helm/v3/pkg/chart" + apimeta "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/client-go/rest" + + "github.com/K0rdent/kcm/api/v1alpha1" +) + +type Actor struct { + Config *rest.Config + RESTMapper apimeta.RESTMapper +} + +func NewActor(config *rest.Config, mapper apimeta.RESTMapper) *Actor { + return &Actor{ + Config: config, + RESTMapper: mapper, + } +} + +func (*Actor) DownloadChartFromArtifact(ctx context.Context, artifact *sourcev1.Artifact) (*chart.Chart, error) { + if artifact == nil { + return nil, errors.New("helm chart artifact is not ready yet") + } + return DownloadChart(ctx, artifact.URL, artifact.Digest) +} + +func (a *Actor) InitializeConfiguration( + clusterDeployment *v1alpha1.ClusterDeployment, + log action.DebugLog, +) (*action.Configuration, error) { + getter := NewMemoryRESTClientGetter(a.Config, a.RESTMapper) + actionConfig := new(action.Configuration) + err := actionConfig.Init(getter, clusterDeployment.Namespace, "secret", log) + if err != nil { + return nil, err + } + return actionConfig, nil +} + +func (*Actor) EnsureReleaseWithValues( + ctx context.Context, + actionConfig *action.Configuration, + hcChart *chart.Chart, + clusterDeployment *v1alpha1.ClusterDeployment, +) error { + install := action.NewInstall(actionConfig) + install.DryRun = true + install.ReleaseName = clusterDeployment.Name + install.Namespace = clusterDeployment.Namespace + install.ClientOnly = true + + vals, err := clusterDeployment.HelmValues() + if err != nil { + return err + } + + _, err = install.RunWithContext(ctx, hcChart, vals) + return err +} From b785be7e957210670b0d1b7355c20bbe191a7189 Mon Sep 17 00:00:00 2001 From: Josef Hak Date: Tue, 7 Jan 2025 11:33:49 +0100 Subject: [PATCH 12/14] Fixes in Makefile and *.md files (#863) * Add other "make dev-..." commands comments * Fix providers related doc links * Fix #create-a-clusterdeployment README link --- Makefile | 6 +++--- README.md | 2 +- docs/dev.md | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index b718ef181..b8e26809c 100644 --- a/Makefile +++ b/Makefile @@ -370,15 +370,15 @@ test-apply: set-hmc-version helm-package dev-deploy dev-templates dev-release dev-destroy: kind-undeploy registry-undeploy ## Destroy the development environment by deleting the kind cluster and local registry. .PHONY: dev-mcluster-apply -dev-mcluster-apply: envsubst +dev-mcluster-apply: envsubst ## Create dev managed cluster using 'config/dev/$(DEV_PROVIDER)-clusterdeployment.yaml' @NAMESPACE=$(NAMESPACE) $(ENVSUBST) -no-unset -i config/dev/$(DEV_PROVIDER)-clusterdeployment.yaml | $(KUBECTL) apply -f - .PHONY: dev-mcluster-delete -dev-mcluster-delete: envsubst +dev-mcluster-delete: envsubst ## Delete dev managed cluster using 'config/dev/$(DEV_PROVIDER)-clusterdeployment.yaml' @NAMESPACE=$(NAMESPACE) $(ENVSUBST) -no-unset -i config/dev/$(DEV_PROVIDER)-clusterdeployment.yaml | $(KUBECTL) delete -f - .PHONY: dev-creds-apply -dev-creds-apply: dev-$(DEV_PROVIDER)-creds +dev-creds-apply: dev-$(DEV_PROVIDER)-creds ## Create credentials resources for $DEV_PROVIDER .PHONY: dev-aws-nuke dev-aws-nuke: envsubst awscli yq cloud-nuke ## Warning: Destructive! Nuke all AWS resources deployed by 'DEV_PROVIDER=aws dev-mcluster-apply' diff --git a/README.md b/README.md index f43a61312..1ede333bf 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ or install using `helm` helm install hmc oci://ghcr.io/k0rdent/kcm/charts/hmc --version 0.0.6 -n hmc-system --create-namespace ``` -Then follow the [Deploy a cluster deployment](#deploy-a-cluster-deployment) guide to +Then follow the [Deploy a cluster deployment](#create-a-clusterdeployment) guide to create a cluster deployment. > [!NOTE] diff --git a/docs/dev.md b/docs/dev.md index af5b9d3f5..2df2c9804 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -22,7 +22,7 @@ make cli-install ### AWS Provider Setup -Follow the instruction to configure AWS Provider: [AWS Provider Setup](aws/main.md#prepare-the-aws-infra-provider) +Follow the instruction to configure AWS Provider: [AWS Provider Setup](https://k0rdent.github.io/docs/quick-start/aws/) The following env variables must be set in order to deploy dev cluster on AWS: @@ -36,7 +36,7 @@ The following environment variables are optional but can enhance functionality: ### Azure Provider Setup -Follow the instruction on how to configure [Azure Provider](azure/main.md). +Follow the instruction on how to configure [Azure Provider](https://k0rdent.github.io/docs/quick-start/azure/). Additionally to deploy dev cluster on Azure the following env variables should be set before running deployment: @@ -51,7 +51,7 @@ More detailed description of these parameters can be found ### vSphere Provider Setup -Follow the instruction on how to configure [vSphere Provider](vsphere/main.md). +Follow the instruction on how to configure [vSphere Provider](https://k0rdent.github.io/docs/quick-start/vsphere/). To properly deploy dev cluster you need to have the following variables set: From e5d2dbd6908f1360e7b09de663ddf565f1541082 Mon Sep 17 00:00:00 2001 From: Aleksei Sizov <45825279+a13x5@users.noreply.github.com> Date: Tue, 7 Jan 2025 09:31:42 -0500 Subject: [PATCH 13/14] Fix k0s installation in airgap env (#791) --- Makefile | 12 +++++++++-- hack/k0s-ag-image/Dockerfile | 19 +++++++++++++++++ hack/k0s-ag-image/default.conf | 21 +++++++++++++++++++ scripts/bundle-images.sh | 2 +- .../cluster/vsphere-hosted-cp/Chart.yaml | 2 +- .../templates/k0sworkerconfigtemplate.yaml | 7 +++++++ .../vsphere-hosted-cp/values.schema.json | 12 +++++++++++ .../cluster/vsphere-hosted-cp/values.yaml | 4 ++++ .../cluster/vsphere-standalone-cp/Chart.yaml | 2 +- .../templates/k0scontrolplane.yaml | 7 +++++++ .../templates/k0sworkerconfigtemplate.yaml | 7 +++++++ .../vsphere-standalone-cp/values.schema.json | 12 +++++++++++ .../cluster/vsphere-standalone-cp/values.yaml | 4 ++++ ...-0-3.yaml => vsphere-hosted-cp-0-0-4.yaml} | 4 ++-- ....yaml => vsphere-standalone-cp-0-0-4.yaml} | 4 ++-- 15 files changed, 110 insertions(+), 9 deletions(-) create mode 100644 hack/k0s-ag-image/Dockerfile create mode 100644 hack/k0s-ag-image/default.conf rename templates/provider/hmc-templates/files/templates/{vsphere-hosted-cp-0-0-3.yaml => vsphere-hosted-cp-0-0-4.yaml} (85%) rename templates/provider/hmc-templates/files/templates/{vsphere-standalone-cp-0-0-3.yaml => vsphere-standalone-cp-0-0-4.yaml} (85%) diff --git a/Makefile b/Makefile index b8e26809c..a54fb035a 100644 --- a/Makefile +++ b/Makefile @@ -134,8 +134,11 @@ add-license: addlicense TEMPLATES_DIR := templates PROVIDER_TEMPLATES_DIR := $(TEMPLATES_DIR)/provider export PROVIDER_TEMPLATES_DIR +CLUSTER_TEMPLATES_DIR := $(TEMPLATES_DIR)/cluster CHARTS_PACKAGE_DIR ?= $(LOCALBIN)/charts EXTENSION_CHARTS_PACKAGE_DIR ?= $(LOCALBIN)/charts/extensions +K0S_VERSION = $(shell $(YQ) '.k0s.version' $(CLUSTER_TEMPLATES_DIR)/vsphere-standalone-cp/values.yaml) +K0S_AG_IMAGE = k0s-ag-image:$(subst +,-,$(K0S_VERSION)) $(EXTENSION_CHARTS_PACKAGE_DIR): | $(LOCALBIN) mkdir -p $(EXTENSION_CHARTS_PACKAGE_DIR) $(CHARTS_PACKAGE_DIR): | $(LOCALBIN) @@ -156,8 +159,13 @@ collect-airgap-providers: yq helm clusterctl $(PROVIDER_TEMPLATES_DIR) $(LOCALBI helm-package: $(CHARTS_PACKAGE_DIR) $(EXTENSION_CHARTS_PACKAGE_DIR) helm collect-airgap-providers @make $(patsubst %,package-%-tmpl,$(TEMPLATE_FOLDERS)) -bundle-images: dev-apply $(IMAGES_PACKAGE_DIR) ## Create a tarball with all images used by HMC. - @BUNDLE_TARBALL=$(IMAGES_PACKAGE_DIR)/hmc-images-$(VERSION).tgz EXTENSIONS_BUNDLE_TARBALL=$(IMAGES_PACKAGE_DIR)/hmc-extension-images-$(VERSION).tgz IMG=$(IMG) KUBECTL=$(KUBECTL) YQ=$(YQ) HELM=$(HELM) NAMESPACE=$(NAMESPACE) TEMPLATES_DIR=$(TEMPLATES_DIR) KIND_CLUSTER_NAME=$(KIND_CLUSTER_NAME) $(SHELL) $(CURDIR)/scripts/bundle-images.sh +.PHONY: k0s-image +k0s-image: + export DOCKER_BUILDKIT=1 + $(CONTAINER_TOOL) build --build-arg K0S_VERSION=$(K0S_VERSION) -t $(K0S_AG_IMAGE) hack/k0s-ag-image + +bundle-images: dev-apply $(IMAGES_PACKAGE_DIR) k0s-image ## Create a tarball with all images used by HMC. + @BUNDLE_TARBALL=$(IMAGES_PACKAGE_DIR)/hmc-images-$(VERSION).tgz EXTENSIONS_BUNDLE_TARBALL=$(IMAGES_PACKAGE_DIR)/hmc-extension-images-$(VERSION).tgz IMG=$(IMG) KUBECTL=$(KUBECTL) YQ=$(YQ) HELM=$(HELM) NAMESPACE=$(NAMESPACE) TEMPLATES_DIR=$(TEMPLATES_DIR) KIND_CLUSTER_NAME=$(KIND_CLUSTER_NAME) K0S_AG_IMAGE=$(K0S_AG_IMAGE) $(SHELL) $(CURDIR)/scripts/bundle-images.sh airgap-package: bundle-images ## Create a tarball with all images and Helm charts used by HMC, useful for deploying in air-gapped environments. @TEMPLATES_DIR=$(TEMPLATES_DIR) EXTENSION_CHARTS_PACKAGE_DIR=$(EXTENSION_CHARTS_PACKAGE_DIR) HELM=$(HELM) YQ=$(YQ) $(SHELL) $(CURDIR)/scripts/package-k0s-extensions-helm.sh diff --git a/hack/k0s-ag-image/Dockerfile b/hack/k0s-ag-image/Dockerfile new file mode 100644 index 000000000..f0bf57a94 --- /dev/null +++ b/hack/k0s-ag-image/Dockerfile @@ -0,0 +1,19 @@ +# Copyright 2024 +# +# 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. + +FROM nginx:1.27 +ARG K0S_VERSION +ADD default.conf /etc/nginx/conf.d/default.conf +ADD --chown=nginx https://github.com/k0sproject/k0s/releases/download/${K0S_VERSION}/k0s-${K0S_VERSION}-amd64 /var/www/html/k0s +ADD --chown=nginx https://github.com/k0sproject/k0s/releases/download/${K0S_VERSION}/k0s-airgap-bundle-${K0S_VERSION}-amd64 /var/www/html/k0s-airgap-bundle diff --git a/hack/k0s-ag-image/default.conf b/hack/k0s-ag-image/default.conf new file mode 100644 index 000000000..ccc4bc98f --- /dev/null +++ b/hack/k0s-ag-image/default.conf @@ -0,0 +1,21 @@ +server { + proxy_max_temp_file_size 0; + listen 80; + sendfile on; + tcp_nopush on; + tcp_nodelay on; + server_name localhost; + + keepalive_timeout 70; + + root /var/www/html; + location / { + } + + client_max_body_size 512m; + + location /heathz { + return 200 'OK'; + } + +} diff --git a/scripts/bundle-images.sh b/scripts/bundle-images.sh index 3db645498..fa54c4295 100755 --- a/scripts/bundle-images.sh +++ b/scripts/bundle-images.sh @@ -21,7 +21,7 @@ # Usage: make bundle-images # This script should not be run directly. Use 'make bundle-images' instead. LABEL_KEY="cluster.x-k8s.io/provider" -IMAGES_BUNDLED="$IMG" +IMAGES_BUNDLED="$IMG $K0S_AG_IMAGE" EXTENSION_IMAGES_BUNDLED="" echo -e "Bundling images for HMC, this may take awhile...\n" diff --git a/templates/cluster/vsphere-hosted-cp/Chart.yaml b/templates/cluster/vsphere-hosted-cp/Chart.yaml index 30c953f1d..4449eb3dc 100644 --- a/templates/cluster/vsphere-hosted-cp/Chart.yaml +++ b/templates/cluster/vsphere-hosted-cp/Chart.yaml @@ -7,7 +7,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.3 +version: 0.0.4 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. diff --git a/templates/cluster/vsphere-hosted-cp/templates/k0sworkerconfigtemplate.yaml b/templates/cluster/vsphere-hosted-cp/templates/k0sworkerconfigtemplate.yaml index 37e09dd2c..942b18eb6 100644 --- a/templates/cluster/vsphere-hosted-cp/templates/k0sworkerconfigtemplate.yaml +++ b/templates/cluster/vsphere-hosted-cp/templates/k0sworkerconfigtemplate.yaml @@ -6,9 +6,16 @@ spec: template: spec: version: {{ .Values.k0s.version }} + {{- if .Values.airgap }} + downloadURL: {{ required ".Values.k0s.downloadURL is required on airgap deployment" .Values.k0s.downloadURL }} + {{- end }} files: - path: /home/{{ .Values.ssh.user }}/.ssh/authorized_keys permissions: "0600" content: "{{ trim .Values.ssh.publicKey }}" preStartCommands: + {{- if .Values.airgap }} + - mkdir -p /var/lib/k0s/images + - curl -fsL {{ required ".Values.k0s.bundleURL is required on airgap deployment" .Values.k0s.bundleURL }} -o /var/lib/k0s/images/k0s-airgap-bundle + {{- end }} - chown {{ .Values.ssh.user }} /home/{{ .Values.ssh.user }}/.ssh/authorized_keys diff --git a/templates/cluster/vsphere-hosted-cp/values.schema.json b/templates/cluster/vsphere-hosted-cp/values.schema.json index 1d89a3f28..c4c8137d3 100644 --- a/templates/cluster/vsphere-hosted-cp/values.schema.json +++ b/templates/cluster/vsphere-hosted-cp/values.schema.json @@ -26,6 +26,10 @@ "type": "number", "minimum": 1 }, + "airgap": { + "description": "Cluster created in airgap env", + "type": "boolean" + }, "clusterNetwork": { "type": "object", "properties": { @@ -146,6 +150,14 @@ "version":{ "description": "K0s version to use", "type": "string" + }, + "downloadURL":{ + "description": "K0s download URL", + "type": "string" + }, + "bundleURL":{ + "description": "K0s airgap bundle URL", + "type": "string" } } } diff --git a/templates/cluster/vsphere-hosted-cp/values.yaml b/templates/cluster/vsphere-hosted-cp/values.yaml index 187774dc8..161fc9bd3 100644 --- a/templates/cluster/vsphere-hosted-cp/values.yaml +++ b/templates/cluster/vsphere-hosted-cp/values.yaml @@ -42,9 +42,13 @@ k0smotron: # K0s parameters k0s: version: v1.31.1+k0s.1 + downloadURL: "" + bundleURL: "" # extensions defines custom Helm and image repositories to use for pulling # k0s extensions. extensions: chartRepository: "" imageRepository: "" + +airgap: false diff --git a/templates/cluster/vsphere-standalone-cp/Chart.yaml b/templates/cluster/vsphere-standalone-cp/Chart.yaml index bce65dc31..1c17ffd1e 100644 --- a/templates/cluster/vsphere-standalone-cp/Chart.yaml +++ b/templates/cluster/vsphere-standalone-cp/Chart.yaml @@ -6,7 +6,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.3 +version: 0.0.4 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. diff --git a/templates/cluster/vsphere-standalone-cp/templates/k0scontrolplane.yaml b/templates/cluster/vsphere-standalone-cp/templates/k0scontrolplane.yaml index e20112915..7d5b3b55c 100644 --- a/templates/cluster/vsphere-standalone-cp/templates/k0scontrolplane.yaml +++ b/templates/cluster/vsphere-standalone-cp/templates/k0scontrolplane.yaml @@ -6,11 +6,18 @@ spec: replicas: {{ .Values.controlPlaneNumber }} version: {{ .Values.k0s.version }} k0sConfigSpec: + {{- if .Values.airgap }} + downloadURL: {{ required ".Values.k0s.downloadURL is required on airgap deployment" .Values.k0s.downloadURL }} + {{- end }} files: - path: /home/{{ .Values.controlPlane.ssh.user }}/.ssh/authorized_keys permissions: "0600" content: "{{ trim .Values.controlPlane.ssh.publicKey }}" preStartCommands: + {{- if .Values.airgap }} + - mkdir -p /var/lib/k0s/images + - curl -fsL {{ required ".Values.k0s.bundleURL is required on airgap deployment" .Values.k0s.bundleURL }} -o /var/lib/k0s/images/k0s-airgap-bundle + {{- end }} - chown {{ .Values.controlPlane.ssh.user }} /home/{{ .Values.controlPlane.ssh.user }}/.ssh/authorized_keys - sed -i 's/"externalAddress":"{{ .Values.controlPlaneEndpointIP }}",//' /etc/k0s.yaml args: diff --git a/templates/cluster/vsphere-standalone-cp/templates/k0sworkerconfigtemplate.yaml b/templates/cluster/vsphere-standalone-cp/templates/k0sworkerconfigtemplate.yaml index 332f52125..17638faf6 100644 --- a/templates/cluster/vsphere-standalone-cp/templates/k0sworkerconfigtemplate.yaml +++ b/templates/cluster/vsphere-standalone-cp/templates/k0sworkerconfigtemplate.yaml @@ -6,9 +6,16 @@ spec: template: spec: version: {{ .Values.k0s.version }} + {{- if .Values.airgap }} + downloadURL: {{ required ".Values.k0s.downloadURL is required on airgap deployment" .Values.k0s.downloadURL }} + {{- end }} files: - path: /home/{{ .Values.worker.ssh.user }}/.ssh/authorized_keys permissions: "0600" content: "{{ trim .Values.worker.ssh.publicKey }}" preStartCommands: + {{- if .Values.airgap }} + - mkdir -p /var/lib/k0s/images + - curl -fsL {{ required ".Values.k0s.bundleURL is required on airgap deployment" .Values.k0s.bundleURL }} -o /var/lib/k0s/images/k0s-airgap-bundle + {{- end }} - chown {{ .Values.worker.ssh.user }} /home/{{ .Values.worker.ssh.user }}/.ssh/authorized_keys diff --git a/templates/cluster/vsphere-standalone-cp/values.schema.json b/templates/cluster/vsphere-standalone-cp/values.schema.json index f2be23fb4..0283e145b 100644 --- a/templates/cluster/vsphere-standalone-cp/values.schema.json +++ b/templates/cluster/vsphere-standalone-cp/values.schema.json @@ -20,6 +20,10 @@ "type": "number", "minimum": 1 }, + "airgap": { + "description": "Cluster created in airgap env", + "type": "boolean" + }, "clusterNetwork": { "type": "object", "properties": { @@ -198,6 +202,14 @@ "version":{ "description": "K0s version to use", "type": "string" + }, + "downloadURL":{ + "description": "K0s download URL", + "type": "string" + }, + "bundleURL":{ + "description": "K0s airgap bundle URL", + "type": "string" } } } diff --git a/templates/cluster/vsphere-standalone-cp/values.yaml b/templates/cluster/vsphere-standalone-cp/values.yaml index eb64d7080..0236a8c0b 100644 --- a/templates/cluster/vsphere-standalone-cp/values.yaml +++ b/templates/cluster/vsphere-standalone-cp/values.yaml @@ -46,9 +46,13 @@ worker: # K0s parameters k0s: version: v1.31.1+k0s.1 + downloadURL: "" + bundleURL: "" # extensions defines custom Helm and image repositories to use for pulling # k0s extensions. extensions: chartRepository: "" imageRepository: "" + +airgap: false diff --git a/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-4.yaml similarity index 85% rename from templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml rename to templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-4.yaml index 4286b87e3..55d99aba9 100644 --- a/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/vsphere-hosted-cp-0-0-4.yaml @@ -1,7 +1,7 @@ apiVersion: hmc.mirantis.com/v1alpha1 kind: ClusterTemplate metadata: - name: vsphere-hosted-cp-0-0-3 + name: vsphere-hosted-cp-0-0-4 annotations: helm.sh/resource-policy: keep labels: @@ -10,7 +10,7 @@ spec: helm: chartSpec: chart: vsphere-hosted-cp - version: 0.0.3 + version: 0.0.4 interval: 10m0s sourceRef: kind: HelmRepository diff --git a/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml b/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-4.yaml similarity index 85% rename from templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml rename to templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-4.yaml index c60fb35a9..f3feebf9b 100644 --- a/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-3.yaml +++ b/templates/provider/hmc-templates/files/templates/vsphere-standalone-cp-0-0-4.yaml @@ -1,7 +1,7 @@ apiVersion: hmc.mirantis.com/v1alpha1 kind: ClusterTemplate metadata: - name: vsphere-standalone-cp-0-0-3 + name: vsphere-standalone-cp-0-0-4 annotations: helm.sh/resource-policy: keep labels: @@ -10,7 +10,7 @@ spec: helm: chartSpec: chart: vsphere-standalone-cp - version: 0.0.3 + version: 0.0.4 interval: 10m0s sourceRef: kind: HelmRepository From a2bae4e1bdc5dc118db7f410b5d5b1566d902644 Mon Sep 17 00:00:00 2001 From: Michael Morgen Date: Tue, 7 Jan 2025 17:28:47 +0100 Subject: [PATCH 14/14] Fix insufficient RBAC to update Releases labels (#870) --- templates/provider/hmc/templates/rbac/controller/roles.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/provider/hmc/templates/rbac/controller/roles.yaml b/templates/provider/hmc/templates/rbac/controller/roles.yaml index 22876c277..f5f30d8ad 100644 --- a/templates/provider/hmc/templates/rbac/controller/roles.yaml +++ b/templates/provider/hmc/templates/rbac/controller/roles.yaml @@ -69,6 +69,7 @@ rules: - get - list - watch + - update # labels - apiGroups: - hmc.mirantis.com resources: