diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 3a2cbb707..80e5471b9 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -222,7 +222,8 @@ jobs: devbox run -- \ kind load docker-image \ --name chart-testing \ - "ko.local/cluster-api-runtime-extensions-nutanix:$(devbox run -- gojq -r .version dist/metadata.json)" + "ko.local/cluster-api-runtime-extensions-nutanix:$(devbox run -- gojq -r .version dist/metadata.json)" \ + "ghcr.io/nutanix-cloud-native/caren-helm-reg:$(devbox run -- gojq -r .version dist/metadata.json)" - if: steps.list-changed.outputs.changed == 'true' name: Setup Cluster API and cert-manager @@ -238,7 +239,7 @@ jobs: devbox run -- \ ct install \ --config charts/ct-config.yaml \ - --helm-extra-set-args "--set-string image.repository=ko.local/cluster-api-runtime-extensions-nutanix --set-string image.tag=$(devbox run -- gojq -r .version dist/metadata.json)" + --helm-extra-set-args "--set-string image.repository=ko.local/cluster-api-runtime-extensions-nutanix --set-string image.tag=$(devbox run -- gojq -r .version dist/metadata.json) --set-string helmRepositoryImage.tag=$(devbox run -- gojq -r .version dist/metadata.json)" env: KUBECONFIG: ct-kind-kubeconfig diff --git a/.goreleaser.yml b/.goreleaser.yml index 7effc0c0a..1fbf48aba 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -42,6 +42,7 @@ before: $(helm template {{ .ProjectName }} ./charts/{{ .ProjectName }} \ --namespace caren-system \ --set-string image.tag=v{{ trimprefix .Version "v" }} \ + --set-string helmRepositoryImage.tag=v{{ trimprefix .Version "v" }} \ {{ if .IsSnapshot }}--set-string image.repository=ko.local/{{ .ProjectName }}{{ end }} \ ) EOF' @@ -50,6 +51,8 @@ before: sh -ec 'gojq --yaml-input --yaml-output \ ".releaseSeries |= (. + [{contract: \"v1beta1\", major: {{ .Major }}, minor: {{ .Minor }}}] | unique)" \ metadata.yaml >release-metadata.yaml' + - make template-helm-repository + builds: - id: cluster-api-runtime-extensions-nutanix @@ -92,6 +95,15 @@ archives: builds: - cluster-api-runtime-extensions-nutanix +dockers: + - id: helm-registry-container + use: buildx + dockerfile: ./hack/addons/mindthegap-helm-registry/Dockerfile + extra_files: + - hack/addons/mindthegap-helm-registry/repos.yaml + image_templates: + - 'ghcr.io/nutanix-cloud-native/caren-helm-reg:{{ .Version }}' + kos: - id: cluster-api-runtime-extensions-nutanix build: cluster-api-runtime-extensions-nutanix diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7a1a4ee57..839b4cb7b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,11 +34,11 @@ repos: language: system files: "^(hack/addons/|charts/cluster-api-runtime-extensions-nutanix/templates/.+/manifests/|make/addons.mk$)" pass_filenames: false - - id: addons-configmap - name: addons-configmap - entry: make generate-helm-configmap + - id: addons-repo-yaml + name: addons-repo-yaml + entry: make template-helm-repository language: system - files: "^(hack/addons/|charts/cluster-api-runtime-extensions-nutanix/templates/.+|make/addons.mk$)" + files: "hack/addons/mindthegap-helm-registry/repos.yaml" pass_filenames: false - id: check-devbox-lock name: check-devbox-lock diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 0753fdc56..bba68f41b 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -10,7 +10,7 @@ package v1alpha1 import ( "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/external/github.com/nutanix-cloud-native/cluster-api-provider-nutanix/api/v1beta1" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/external/sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -1129,7 +1129,9 @@ func (in *NutanixNodeSpec) DeepCopy() *NutanixNodeSpec { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *NutanixPrismCentralEndpointCredentials) DeepCopyInto(out *NutanixPrismCentralEndpointCredentials) { +func (in *NutanixPrismCentralEndpointCredentials) DeepCopyInto( + out *NutanixPrismCentralEndpointCredentials, +) { *out = *in out.SecretRef = in.SecretRef } diff --git a/charts/cluster-api-runtime-extensions-nutanix/README.md b/charts/cluster-api-runtime-extensions-nutanix/README.md index 1fd633607..510f0e5e1 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/README.md +++ b/charts/cluster-api-runtime-extensions-nutanix/README.md @@ -32,6 +32,9 @@ A Helm chart for cluster-api-runtime-extensions-nutanix | deployment.replicas | int | `1` | | | env | object | `{}` | | | helmAddonsConfigMap | string | `"default-helm-addons-config"` | | +| helmRepositoryImage.pullPolicy | string | `"IfNotPresent"` | | +| helmRepositoryImage.repository | string | `"ghcr.io/nutanix-cloud-native/caren-helm-reg"` | | +| helmRepositoryImage.tag | string | `""` | | | hooks.ccm.nutanix.helmAddonStrategy.defaultValueTemplateConfigMap.create | bool | `true` | | | hooks.ccm.nutanix.helmAddonStrategy.defaultValueTemplateConfigMap.name | string | `"default-nutanix-ccm-helm-values-template"` | | | hooks.clusterAutoscaler.crsStrategy.defaultInstallationConfigMap.name | string | `"cluster-autoscaler"` | | @@ -77,6 +80,7 @@ A Helm chart for cluster-api-runtime-extensions-nutanix | resources.requests.cpu | string | `"100m"` | | | resources.requests.memory | string | `"128Mi"` | | | securityContext.runAsUser | int | `65532` | | +| selfHostedRegistry | bool | `true` | | | service.annotations | object | `{}` | | | service.port | int | `443` | | | service.type | string | `"ClusterIP"` | | diff --git a/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml b/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml index cf5de6dde..497b3ce6b 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml @@ -10,39 +10,39 @@ data: cilium: | ChartName: cilium ChartVersion: 1.15.5 - RepositoryURL: https://helm.cilium.io/ + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://helm.cilium.io/{{ end }} cluster-autoscaler: | ChartName: cluster-autoscaler ChartVersion: 9.37.0 - RepositoryURL: https://kubernetes.github.io/autoscaler + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://kubernetes.github.io/autoscaler{{ end }} local-path-provisioner-csi: | ChartName: local-path-provisioner - ChartVersion: v0.0.29 - RepositoryURL: https://charts.containeroo.ch + ChartVersion: 0.0.29 + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://charts.containeroo.ch{{ end }} metallb: | ChartName: metallb - ChartVersion: v0.14.5 - RepositoryURL: https://metallb.github.io/metallb + ChartVersion: 0.14.5 + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://metallb.github.io/metallb{{ end }} nfd: | ChartName: node-feature-discovery ChartVersion: 0.15.2 - RepositoryURL: https://kubernetes-sigs.github.io/node-feature-discovery/charts + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://kubernetes-sigs.github.io/node-feature-discovery/charts{{ end }} nutanix-ccm: | ChartName: nutanix-cloud-provider ChartVersion: 0.3.3 - RepositoryURL: https://nutanix.github.io/helm/ + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://nutanix.github.io/helm/{{ end }} nutanix-snapshot-csi: | ChartName: nutanix-csi-snapshot - ChartVersion: v6.3.2 - RepositoryURL: https://nutanix.github.io/helm/ + ChartVersion: 6.3.2 + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://nutanix.github.io/helm/{{ end }} nutanix-storage-csi: | ChartName: nutanix-csi-storage - ChartVersion: v3.0.0-beta.1912 - RepositoryURL: https://nutanix.github.io/helm-releases/ + ChartVersion: 3.0.0-beta.1912 + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://nutanix.github.io/helm-releases/{{ end }} tigera-operator: | ChartName: tigera-operator ChartVersion: v3.28.0 - RepositoryURL: https://docs.tigera.io/calico/charts + RepositoryURL: {{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}https://docs.tigera.io/calico/charts{{ end }} kind: ConfigMap metadata: creationTimestamp: null diff --git a/charts/cluster-api-runtime-extensions-nutanix/templates/helm-repository.yaml b/charts/cluster-api-runtime-extensions-nutanix/templates/helm-repository.yaml new file mode 100644 index 000000000..dae1a3369 --- /dev/null +++ b/charts/cluster-api-runtime-extensions-nutanix/templates/helm-repository.yaml @@ -0,0 +1,78 @@ +# Copyright 2024 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# This file contains the manifests to run a helmRepository deployment which contains helm charts for our addons. +# The pod is built via goreleaser with configuration from hack/addons. +# +{{ if .Values.selfHostedRegistry }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: helm-repository-selfsigned + namespace: {{ .Release.Namespace }} +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: helm-repository-tls + namespace: {{ .Release.Namespace }} +spec: + dnsNames: + - helm-repository.{{ .Release.Namespace }}.svc + - helm-repository.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + name: helm-repository-selfsigned + kind: Issuer + secretName: helm-repository-tls +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: helm-repository + namespace: {{ .Release.Namespace }} + labels: + app: helm-repository +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: helm-repository # deployment will track pods it generates because of this + template: + metadata: + labels: + app: helm-repository # pods have this label, and Service and Deployment depend on it + spec: + containers: + - name: helm-repository + ports: + - name: serve + protocol: TCP + containerPort: 5000 + image: "{{ .Values.helmRepositoryImage.repository }}:{{ .Values.helmRepositoryImage.tag | default $.Chart.AppVersion }}" + imagePullPolicy: "{{ .Values.image.pullPolicy }}" + volumeMounts: + - name: certs-vol + mountPath: "/certs" + readOnly: true + env: + volumes: + - name: certs-vol + secret: + secretName: helm-repository-tls +--- +apiVersion: v1 +kind: Service +metadata: + name: helm-repository + namespace: {{ .Release.Namespace }} +spec: + selector: + app: helm-repository + ports: + - port: 443 + targetPort: 5000 + type: ClusterIP +{{ end }} diff --git a/charts/cluster-api-runtime-extensions-nutanix/values.yaml b/charts/cluster-api-runtime-extensions-nutanix/values.yaml index d2e078afd..33062ba13 100644 --- a/charts/cluster-api-runtime-extensions-nutanix/values.yaml +++ b/charts/cluster-api-runtime-extensions-nutanix/values.yaml @@ -84,6 +84,9 @@ hooks: helmAddonsConfigMap: default-helm-addons-config +selfHostedRegistry: true + + deployDefaultClusterClasses: true deployment: @@ -94,6 +97,11 @@ image: tag: "" pullPolicy: IfNotPresent +helmRepositoryImage: + repository: ghcr.io/nutanix-cloud-native/caren-helm-reg + tag: "" + pullPolicy: IfNotPresent + # -- Optional secrets used for pulling the container image imagePullSecrets: [] # - name: Secret with Registry credentials diff --git a/devbox.lock b/devbox.lock index f9855fd86..c34cf03c5 100644 --- a/devbox.lock +++ b/devbox.lock @@ -98,8 +98,8 @@ } }, "coreutils@latest": { - "last_modified": "2024-05-22T06:18:38Z", - "resolved": "github:NixOS/nixpkgs/3f316d2a50699a78afe5e77ca486ad553169061e#coreutils", + "last_modified": "2024-06-09T00:38:05Z", + "resolved": "github:NixOS/nixpkgs/3bcedce9f4de37570242faf16e1e143583407eab#coreutils", "source": "devbox-search", "version": "9.5", "systems": { @@ -156,13 +156,13 @@ "path": "/nix/store/php4qidg2bxzmm79vpri025bqi0fa889-coreutils-9.5", "default": true }, - { - "name": "info", - "path": "/nix/store/xp1fkjjkw9l63815ll6mzwbjm0jqjwkl-coreutils-9.5-info" - }, { "name": "debug", "path": "/nix/store/8slafzx35rrfhzqwzqv3nb2nnbwq1630-coreutils-9.5-debug" + }, + { + "name": "info", + "path": "/nix/store/xp1fkjjkw9l63815ll6mzwbjm0jqjwkl-coreutils-9.5-info" } ], "store_path": "/nix/store/php4qidg2bxzmm79vpri025bqi0fa889-coreutils-9.5" @@ -218,8 +218,8 @@ } }, "findutils@latest": { - "last_modified": "2024-05-30T12:09:21Z", - "resolved": "github:NixOS/nixpkgs/aa61b27554a5fc282758bf0324781e3464ef2cde#findutils", + "last_modified": "2024-06-04T00:03:09Z", + "resolved": "github:NixOS/nixpkgs/3b01abcc24846ae49957b30f4345bab4b3f1d14b#findutils", "source": "devbox-search", "version": "4.9.0", "systems": { @@ -230,13 +230,13 @@ "path": "/nix/store/v2f2czixsg2vqjck84n879whz8bc1zg5-findutils-4.9.0", "default": true }, - { - "name": "info", - "path": "/nix/store/kp3pv46r60zflkz2kbpk26nv6rka5wsr-findutils-4.9.0-info" - }, { "name": "locate", "path": "/nix/store/zai9zalsmh0fc052x3grch9g0k27i4br-findutils-4.9.0-locate" + }, + { + "name": "info", + "path": "/nix/store/kp3pv46r60zflkz2kbpk26nv6rka5wsr-findutils-4.9.0-info" } ], "store_path": "/nix/store/v2f2czixsg2vqjck84n879whz8bc1zg5-findutils-4.9.0" @@ -394,8 +394,8 @@ } }, "git@latest": { - "last_modified": "2024-05-22T06:18:38Z", - "resolved": "github:NixOS/nixpkgs/3f316d2a50699a78afe5e77ca486ad553169061e#git", + "last_modified": "2024-06-04T00:03:09Z", + "resolved": "github:NixOS/nixpkgs/3b01abcc24846ae49957b30f4345bab4b3f1d14b#git", "source": "devbox-search", "version": "2.44.1", "systems": { @@ -466,8 +466,8 @@ } }, "gnumake@latest": { - "last_modified": "2024-05-22T06:18:38Z", - "resolved": "github:NixOS/nixpkgs/3f316d2a50699a78afe5e77ca486ad553169061e#gnumake", + "last_modified": "2024-06-04T00:03:09Z", + "resolved": "github:NixOS/nixpkgs/3b01abcc24846ae49957b30f4345bab4b3f1d14b#gnumake", "source": "devbox-search", "version": "4.4.1", "systems": { @@ -862,50 +862,50 @@ } }, "govulncheck@latest": { - "last_modified": "2024-05-29T10:04:41Z", - "resolved": "github:NixOS/nixpkgs/ac82a513e55582291805d6f09d35b6d8b60637a1#govulncheck", + "last_modified": "2024-06-07T15:28:25Z", + "resolved": "github:NixOS/nixpkgs/d226935fd75012939397c83f6c385e4d6d832288#govulncheck", "source": "devbox-search", - "version": "1.1.1", + "version": "1.1.2", "systems": { "aarch64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/p7yy5vcwxdwk1yxjc7ki024yh615w73h-govulncheck-1.1.1", + "path": "/nix/store/3iyrx1iwmrr5ggl9gj964zbswzwbqp6m-govulncheck-1.1.2", "default": true } ], - "store_path": "/nix/store/p7yy5vcwxdwk1yxjc7ki024yh615w73h-govulncheck-1.1.1" + "store_path": "/nix/store/3iyrx1iwmrr5ggl9gj964zbswzwbqp6m-govulncheck-1.1.2" }, "aarch64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/v2jxc5slkbbfcfpqwr959cfvp1fasz6h-govulncheck-1.1.1", + "path": "/nix/store/02gz1gyz01b890s8r52c9vmaf0k1p2cs-govulncheck-1.1.2", "default": true } ], - "store_path": "/nix/store/v2jxc5slkbbfcfpqwr959cfvp1fasz6h-govulncheck-1.1.1" + "store_path": "/nix/store/02gz1gyz01b890s8r52c9vmaf0k1p2cs-govulncheck-1.1.2" }, "x86_64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/s4fi5h5dld3vc4zj45pcahy2yscnp8ph-govulncheck-1.1.1", + "path": "/nix/store/21l0mpphg07hhaxzqa328gfj3v4f6b2g-govulncheck-1.1.2", "default": true } ], - "store_path": "/nix/store/s4fi5h5dld3vc4zj45pcahy2yscnp8ph-govulncheck-1.1.1" + "store_path": "/nix/store/21l0mpphg07hhaxzqa328gfj3v4f6b2g-govulncheck-1.1.2" }, "x86_64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/5f9fb3w0qk7l7sh062i8rdhzyz5nhkan-govulncheck-1.1.1", + "path": "/nix/store/wfs0ga9di8kamsh0860qjaqs16hz4zmq-govulncheck-1.1.2", "default": true } ], - "store_path": "/nix/store/5f9fb3w0qk7l7sh062i8rdhzyz5nhkan-govulncheck-1.1.1" + "store_path": "/nix/store/wfs0ga9di8kamsh0860qjaqs16hz4zmq-govulncheck-1.1.2" } } }, @@ -1282,8 +1282,8 @@ } }, "kustomize@latest": { - "last_modified": "2024-06-06T04:00:50Z", - "resolved": "github:NixOS/nixpkgs/818dbe2f96df233d2041739d6079bb616d3e5597#kustomize", + "last_modified": "2024-06-08T17:34:36Z", + "resolved": "github:NixOS/nixpkgs/cd18e2ae9ab8e2a0a8d715b60c91b54c0ac35ff9#kustomize", "source": "devbox-search", "version": "5.4.2", "systems": { @@ -1330,8 +1330,8 @@ } }, "pre-commit@latest": { - "last_modified": "2024-06-04T00:03:09Z", - "resolved": "github:NixOS/nixpkgs/3b01abcc24846ae49957b30f4345bab4b3f1d14b#pre-commit", + "last_modified": "2024-06-06T04:00:50Z", + "resolved": "github:NixOS/nixpkgs/818dbe2f96df233d2041739d6079bb616d3e5597#pre-commit", "source": "devbox-search", "version": "3.7.1", "systems": { @@ -1339,43 +1339,43 @@ "outputs": [ { "name": "out", - "path": "/nix/store/0z03a4cpv2jshqlms3727iwqc715j4vf-pre-commit-3.7.1", + "path": "/nix/store/pxd2jrn0hk62jc68r34rnvwha8v03n2v-pre-commit-3.7.1", "default": true }, { "name": "dist", - "path": "/nix/store/1pkf93j2mad19l57pkdrs8nifsjzdmhy-pre-commit-3.7.1-dist" + "path": "/nix/store/17cs6hywf9i7xcshyz1qhm5g5ic24qs1-pre-commit-3.7.1-dist" } ], - "store_path": "/nix/store/0z03a4cpv2jshqlms3727iwqc715j4vf-pre-commit-3.7.1" + "store_path": "/nix/store/pxd2jrn0hk62jc68r34rnvwha8v03n2v-pre-commit-3.7.1" }, "aarch64-linux": { "outputs": [ { "name": "out", - "path": "/nix/store/csf42gw742isqh5m2j6zz89chkjr6dr9-pre-commit-3.7.1", + "path": "/nix/store/g42v1discdsllvnx3q9k1ar2z59n4ymw-pre-commit-3.7.1", "default": true }, { "name": "dist", - "path": "/nix/store/cpwj3gkdglf8y8c56982yl0mg1lg81g2-pre-commit-3.7.1-dist" + "path": "/nix/store/xqm3swfzp22502nmjpzqf6pnqb39y9k9-pre-commit-3.7.1-dist" } ], - "store_path": "/nix/store/csf42gw742isqh5m2j6zz89chkjr6dr9-pre-commit-3.7.1" + "store_path": "/nix/store/g42v1discdsllvnx3q9k1ar2z59n4ymw-pre-commit-3.7.1" }, "x86_64-darwin": { "outputs": [ { "name": "out", - "path": "/nix/store/wxvq4rnbh0bl047v5jnqq9scvppnfg8x-pre-commit-3.7.1", + "path": "/nix/store/yi6f9fm26zacl6ww5dfslliclqldz2s1-pre-commit-3.7.1", "default": true }, { "name": "dist", - "path": "/nix/store/qf0icrlw7n3l2pdq2dw3nx0mdb5pfn5s-pre-commit-3.7.1-dist" + "path": "/nix/store/2ziiyvmn9sf9sw9k407w5ibbw259jsyx-pre-commit-3.7.1-dist" } ], - "store_path": "/nix/store/wxvq4rnbh0bl047v5jnqq9scvppnfg8x-pre-commit-3.7.1" + "store_path": "/nix/store/yi6f9fm26zacl6ww5dfslliclqldz2s1-pre-commit-3.7.1" }, "x86_64-linux": { "outputs": [ diff --git a/hack/addons/generate-mindthegap-repofile.sh b/hack/addons/generate-mindthegap-repofile.sh new file mode 100755 index 000000000..dc5406603 --- /dev/null +++ b/hack/addons/generate-mindthegap-repofile.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +readonly SCRIPT_DIR + +# shellcheck source=hack/common.sh +source "${SCRIPT_DIR}/../common.sh" + +ASSETS_DIR="$(mktemp -d -p "${TMPDIR:-/tmp}")" + +cp "${GIT_REPO_ROOT}/charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml" "${ASSETS_DIR}" + +# this sed line is needed because the go library is unable to parse yaml with a template string. +sed -i s/"{{ .Values.helmAddonsConfigMap }}"/placeholder/g "${ASSETS_DIR}/helm-config.yaml" +go run "${GIT_REPO_ROOT}/hack/tools/mindthegap-helm-reg/main.go" --input-configmap-file="${ASSETS_DIR}/helm-config.yaml" --output-file="${ASSETS_DIR}/repos.yaml" + +# add warning not to edit file directly +cat <"${GIT_REPO_ROOT}/hack/addons/mindthegap-helm-registry/repos.yaml" +$(cat "${GIT_REPO_ROOT}/hack/license-header.yaml.txt") + +#================================================================= +# DO NOT EDIT THIS FILE +# IT HAS BEEN GENERATED BY /hack/addons/generate-mindthegap-repofile.sh +#================================================================= +$(cat "${ASSETS_DIR}/repos.yaml") +EOF diff --git a/hack/addons/mindthegap-helm-registry/Dockerfile b/hack/addons/mindthegap-helm-registry/Dockerfile new file mode 100644 index 000000000..9d05ad4f1 --- /dev/null +++ b/hack/addons/mindthegap-helm-registry/Dockerfile @@ -0,0 +1,5 @@ +FROM ghcr.io/mesosphere/mindthegap:v1.13.4 +# this gets called by goreleaser so the copy source has to be the path relative to the repo root. +RUN --mount=source=./hack/addons/mindthegap-helm-registry/repos.yaml,target=/repos.yaml ["/ko-app/mindthegap", "create", "helm-bundle", "--helm-charts-file=/repos.yaml", "--output-file=/tmp/helm-charts.tar"] +VOLUME /certs +CMD ["serve", "bundle", "--bundle=/tmp/helm-charts.tar", "--listen-port=5000", "--listen-address=0.0.0.0", "--tls-private-key-file=/certs/tls.key", "--tls-cert-file=/certs/tls.crt"] diff --git a/hack/addons/mindthegap-helm-registry/repos.yaml b/hack/addons/mindthegap-helm-registry/repos.yaml new file mode 100644 index 000000000..db390c266 --- /dev/null +++ b/hack/addons/mindthegap-helm-registry/repos.yaml @@ -0,0 +1,53 @@ +# Copyright 2024 Nutanix. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +#================================================================= +# DO NOT EDIT THIS FILE +# IT HAS BEEN GENERATED BY /hack/addons/generate-mindthegap-repofile.sh +#================================================================= +repositories: + cilium: + repoURL: https://helm.cilium.io/ + charts: + cilium: + - 1.15.5 + cluster-autoscaler: + repoURL: https://kubernetes.github.io/autoscaler + charts: + cluster-autoscaler: + - 9.37.0 + local-path-provisioner: + repoURL: https://charts.containeroo.ch + charts: + local-path-provisioner: + - 0.0.29 + metallb: + repoURL: https://metallb.github.io/metallb + charts: + metallb: + - 0.14.5 + node-feature-discovery: + repoURL: https://kubernetes-sigs.github.io/node-feature-discovery/charts + charts: + node-feature-discovery: + - 0.15.2 + nutanix-cloud-provider: + repoURL: https://nutanix.github.io/helm/ + charts: + nutanix-cloud-provider: + - 0.3.3 + nutanix-csi-snapshot: + repoURL: https://nutanix.github.io/helm/ + charts: + nutanix-csi-snapshot: + - 6.3.2 + nutanix-csi-storage: + repoURL: https://nutanix.github.io/helm-releases/ + charts: + nutanix-csi-storage: + - 3.0.0-beta.1912 + tigera-operator: + repoURL: https://docs.tigera.io/calico/charts + charts: + tigera-operator: + - v3.28.0 diff --git a/hack/tools/mindthegap-helm-reg/main.go b/hack/tools/mindthegap-helm-reg/main.go new file mode 100644 index 000000000..2e18775e2 --- /dev/null +++ b/hack/tools/mindthegap-helm-reg/main.go @@ -0,0 +1,111 @@ +// Copyright 2024 Nutanix. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 +package main + +import ( + "bytes" + "context" + "flag" + "fmt" + "os" + "path" + + "gopkg.in/yaml.v2" + corev1 "k8s.io/api/core/v1" + yamlDecode "k8s.io/apimachinery/pkg/util/yaml" + ctrl "sigs.k8s.io/controller-runtime" +) + +type HelmChartFromConfigMap struct { + Name string `yaml:"ChartName"` + Version string `yaml:"ChartVersion"` + Repository string `yaml:"RepositoryURL"` +} + +type Repository struct { + RepoURL string `yaml:"repoURL,omitempty"` + Charts map[string][]string `yaml:"charts,omitempty"` +} + +type HelmChartsConfig struct { + Repositories map[string]Repository `yaml:"repositories,omitempty"` +} + +var log = ctrl.LoggerFrom(context.Background()) + +func main() { + args := os.Args + var ( + outputFile string + inputConfigMapFile string + ) + flagSet := flag.NewFlagSet("mindthegap-helm-registry", flag.ExitOnError) + flagSet.StringVar(&outputFile, "output-file", "", + "output file name to write config map to.") + flagSet.StringVar(&inputConfigMapFile, "input-configmap-file", "", + "input configmap file to create the mindthegap repo file from") + err := flagSet.Parse(args[1:]) + if err != nil { + log.Error(err, "failed to parse args") + } + fullPath := inputConfigMapFile + if !path.IsAbs(fullPath) { + wd, err := os.Getwd() + if err != nil { + log.Error(err, "failed to get wd") + return + } + fullPath = path.Join(wd, inputConfigMapFile) + } + f, err := os.Open(fullPath) + if err != nil { + log.Error(err, "failed to open file") + return + } + defer f.Close() + cm := &corev1.ConfigMap{} + err = yamlDecode.NewYAMLOrJSONDecoder(f, 1024).Decode(cm) + if err != nil { + log.Error(err, fmt.Sprintf("failed to unmarshal file %s", fullPath)) + } + out := HelmChartsConfig{ + map[string]Repository{}, + } + for _, info := range cm.Data { + var settings HelmChartFromConfigMap + err = yaml.Unmarshal([]byte(info), &settings) + if err != nil { + log.Error(err, "failed unmarshl settings") + return + } + out.Repositories[settings.Name] = Repository{ + RepoURL: settings.Repository, + Charts: map[string][]string{ + settings.Name: { + settings.Version, + }, + }, + } + } + b, err := yaml.Marshal(out) + if err != nil { + log.Error(err, fmt.Sprintf("failed to marshal obj %v", out)) + } + fullOutputfilePath := outputFile + if !path.IsAbs(outputFile) { + wd, err := os.Getwd() + if err != nil { + log.Error(err, "failed") + } + fullOutputfilePath = path.Join(wd, outputFile) + } + f, err = os.OpenFile(fullOutputfilePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o666) + if err != nil { + log.Error(err, "failed to create file") + } + defer f.Close() + _, err = bytes.NewBuffer(b).WriteTo(f) + if err != nil { + log.Error(err, "failed to write to file") + } +} diff --git a/make/addons.mk b/make/addons.mk index e9f8601e0..531471f6c 100644 --- a/make/addons.mk +++ b/make/addons.mk @@ -7,9 +7,9 @@ export NODE_FEATURE_DISCOVERY_VERSION := 0.15.2 export CLUSTER_AUTOSCALER_VERSION := 9.37.0 export AWS_CSI_SNAPSHOT_CONTROLLER_VERSION := v6.3.3 export AWS_EBS_CSI_CHART_VERSION := v2.28.1 -export NUTANIX_STORAGE_CSI_CHART_VERSION := v3.0.0-beta.1912 -export NUTANIX_SNAPSHOT_CSI_CHART_VERSION := v6.3.2 -export LOCAL_PATH_CSI_CHART_VERSION := v0.0.29 +export NUTANIX_STORAGE_CSI_CHART_VERSION := 3.0.0-beta.1912 +export NUTANIX_SNAPSHOT_CSI_CHART_VERSION := 6.3.2 +export LOCAL_PATH_CSI_CHART_VERSION := 0.0.29 # a map of AWS CCM versions export AWS_CCM_VERSION_127 := v1.27.1 export AWS_CCM_CHART_VERSION_127 := 0.0.8 @@ -22,7 +22,7 @@ export NUTANIX_CCM_CHART_VERSION := 0.3.3 export KUBE_VIP_VERSION := v0.8.0 -export METALLB_CHART_VERSION := v0.14.5 +export METALLB_CHART_VERSION := 0.14.5 # Below are the lists of CSI Providers allowed for a specific infrastructure. # - When we support a new infrastructure, we need to a create a new list using the same convention. @@ -63,7 +63,7 @@ update-addon.kube-vip: ; $(info $(M) updating kube-vip manifests) ./hack/addons/update-kube-vip-manifests.sh .PHONY: generate-helm-configmap -generate-helm-configmap: +generate-helm-configmap: ; $(info $(M) genrating helm configmap) ## this file is now used by generate-mindthegap-repofile go run hack/tools/helm-cm/main.go -kustomize-directory="./hack/addons/kustomize" -output-file="./charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml" ./hack/addons/add-warning-helm-configmap.sh @@ -71,3 +71,11 @@ generate-helm-configmap: .PHONY: configure-csi-providers configure-csi-providers: ; $(info $(M) configuring supported csi providers) ./hack/addons/configure-supported-csi-providers.sh + +.PHONY: generate-mindthegap-repofile +generate-mindthegap-repofile: generate-helm-configmap ; $(info $(M) generating helm repofile for mindthgap) + ./hack/addons/generate-mindthegap-repofile.sh + +.PHONY: template-helm-repository +template-helm-repository: generate-mindthegap-repofile ## this is used by gorealeaser to set the helm value to this. + sed -i '/RepositoryURL:/s#\(RepositoryURL: *\)\(.*\)#\1{{ if .Values.selfHostedRegistry }}oci://helm-repository.{{ .Release.Namespace }}.svc/charts{{ else }}\2{{ end }}#' "./charts/cluster-api-runtime-extensions-nutanix/templates/helm-config.yaml" diff --git a/make/dev.mk b/make/dev.mk index 33ba9f7e1..5e6c71e43 100644 --- a/make/dev.mk +++ b/make/dev.mk @@ -9,9 +9,12 @@ ifndef SKIP_BUILD endif kind load docker-image --name $(KIND_CLUSTER_NAME) \ ko.local/cluster-api-runtime-extensions-nutanix:$$(gojq -r .version dist/metadata.json) + kind load docker-image --name $(KIND_CLUSTER_NAME) \ + ghcr.io/nutanix-cloud-native/caren-helm-reg:$$(gojq -r .version dist/metadata.json) helm upgrade --install cluster-api-runtime-extensions-nutanix ./charts/cluster-api-runtime-extensions-nutanix \ --set-string image.repository=ko.local/cluster-api-runtime-extensions-nutanix \ --set-string image.tag=$$(gojq -r .version dist/metadata.json) \ + --set-string helmRepositoryImage.tag=$$(gojq -r .version dist/metadata.json) \ --wait --wait-for-jobs kubectl rollout restart deployment cluster-api-runtime-extensions-nutanix kubectl rollout status deployment cluster-api-runtime-extensions-nutanix diff --git a/pkg/handlers/generic/lifecycle/ccm/nutanix/handler.go b/pkg/handlers/generic/lifecycle/ccm/nutanix/handler.go index aa2f30961..7e1a03c32 100644 --- a/pkg/handlers/generic/lifecycle/ccm/nutanix/handler.go +++ b/pkg/handlers/generic/lifecycle/ccm/nutanix/handler.go @@ -161,7 +161,7 @@ func (p *provider) Apply( ValuesTemplate: values, }, } - + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(hcp) if err = controllerutil.SetOwnerReference(cluster, hcp, p.client.Scheme()); err != nil { return fmt.Errorf( "failed to set owner reference on nutanix-ccm installation HelmChartProxy: %w", diff --git a/pkg/handlers/generic/lifecycle/clusterautoscaler/strategy_helmaddon.go b/pkg/handlers/generic/lifecycle/clusterautoscaler/strategy_helmaddon.go index b7fc5a551..ebaf7c830 100644 --- a/pkg/handlers/generic/lifecycle/clusterautoscaler/strategy_helmaddon.go +++ b/pkg/handlers/generic/lifecycle/clusterautoscaler/strategy_helmaddon.go @@ -103,6 +103,7 @@ func (s helmAddonStrategy) apply( }, } + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(hcp) if err = controllerutil.SetOwnerReference(&req.Cluster, hcp, s.client.Scheme()); err != nil { return fmt.Errorf( "failed to set owner reference on cluster-autoscaler installation HelmChartProxy: %w", diff --git a/pkg/handlers/generic/lifecycle/cni/calico/strategy_helmaddon.go b/pkg/handlers/generic/lifecycle/cni/calico/strategy_helmaddon.go index 3d1886f61..eb4a60fd6 100644 --- a/pkg/handlers/generic/lifecycle/cni/calico/strategy_helmaddon.go +++ b/pkg/handlers/generic/lifecycle/cni/calico/strategy_helmaddon.go @@ -102,7 +102,7 @@ func (s helmAddonStrategy) apply( ValuesTemplate: values, }, } - + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(hcp) if err := controllerutil.SetOwnerReference(&req.Cluster, hcp, s.client.Scheme()); err != nil { return fmt.Errorf( "failed to set owner reference on Calico CNI installation HelmChartProxy: %w", diff --git a/pkg/handlers/generic/lifecycle/cni/cilium/strategy_helmaddon.go b/pkg/handlers/generic/lifecycle/cni/cilium/strategy_helmaddon.go index 1d3a00095..5eef86521 100644 --- a/pkg/handlers/generic/lifecycle/cni/cilium/strategy_helmaddon.go +++ b/pkg/handlers/generic/lifecycle/cni/cilium/strategy_helmaddon.go @@ -87,6 +87,7 @@ func (s helmAddonStrategy) apply( }, } + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(hcp) if err := controllerutil.SetOwnerReference(&req.Cluster, hcp, s.client.Scheme()); err != nil { return fmt.Errorf( "failed to set owner reference on Cilium CNI installation HelmChartProxy: %w", diff --git a/pkg/handlers/generic/lifecycle/csi/localpath/handler.go b/pkg/handlers/generic/lifecycle/csi/localpath/handler.go index bd1cb1758..62f185ec0 100644 --- a/pkg/handlers/generic/lifecycle/csi/localpath/handler.go +++ b/pkg/handlers/generic/lifecycle/csi/localpath/handler.go @@ -118,7 +118,7 @@ helperImage: ValuesTemplate: valuesTemplate, }, } - + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(chartProxy) if err = controllerutil.SetOwnerReference(&req.Cluster, chartProxy, l.client.Scheme()); err != nil { return fmt.Errorf( "failed to set owner reference on HelmChartProxy %q: %w", diff --git a/pkg/handlers/generic/lifecycle/csi/nutanix-csi/handler.go b/pkg/handlers/generic/lifecycle/csi/nutanix-csi/handler.go index 39c5beba7..8449c037b 100644 --- a/pkg/handlers/generic/lifecycle/csi/nutanix-csi/handler.go +++ b/pkg/handlers/generic/lifecycle/csi/nutanix-csi/handler.go @@ -194,7 +194,7 @@ func (n *NutanixCSI) handleHelmAddonApply( ValuesTemplate: values, }, } - + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(storageChartProxy) snapshotChartProxy := &caaphv1.HelmChartProxy{ TypeMeta: metav1.TypeMeta{ APIVersion: caaphv1.GroupVersion.String(), @@ -215,7 +215,7 @@ func (n *NutanixCSI) handleHelmAddonApply( Version: snapshotChart.Version, }, } - + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(snapshotChartProxy) // We use a slice of pointers to satisfy the gocritic linter rangeValCopy check. for _, cp := range []*caaphv1.HelmChartProxy{storageChartProxy, snapshotChartProxy} { if err = controllerutil.SetOwnerReference(&req.Cluster, cp, n.client.Scheme()); err != nil { diff --git a/pkg/handlers/generic/lifecycle/nfd/strategy_helmaddon.go b/pkg/handlers/generic/lifecycle/nfd/strategy_helmaddon.go index b8ad76acc..5040d66fb 100644 --- a/pkg/handlers/generic/lifecycle/nfd/strategy_helmaddon.go +++ b/pkg/handlers/generic/lifecycle/nfd/strategy_helmaddon.go @@ -93,6 +93,7 @@ image: }, } + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(hcp) if err := controllerutil.SetOwnerReference(&req.Cluster, hcp, s.client.Scheme()); err != nil { return fmt.Errorf( "failed to set owner reference on NFD installation HelmChartProxy: %w", diff --git a/pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb/handler.go b/pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb/handler.go index bc69351a1..b99983e51 100644 --- a/pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb/handler.go +++ b/pkg/handlers/generic/lifecycle/serviceloadbalancer/metallb/handler.go @@ -140,6 +140,7 @@ func (n *MetalLB) Apply( }, } + lifecycleutils.SetTLSConfigForHelmChartProxyIfNeeded(hcp) if err = controllerutil.SetOwnerReference(cluster, hcp, n.client.Scheme()); err != nil { return fmt.Errorf( "failed to set owner reference on MetalLB installation HelmChartProxy: %w", diff --git a/pkg/handlers/generic/lifecycle/utils/utils.go b/pkg/handlers/generic/lifecycle/utils/utils.go index e8d6b7fb8..17cfb427d 100644 --- a/pkg/handlers/generic/lifecycle/utils/utils.go +++ b/pkg/handlers/generic/lifecycle/utils/utils.go @@ -6,6 +6,8 @@ package utils import ( "context" "fmt" + "os" + "strings" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -17,6 +19,7 @@ import ( ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + caaphv1 "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/api/external/sigs.k8s.io/cluster-api-addon-provider-helm/api/v1alpha1" "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/k8s/client" ) @@ -219,3 +222,19 @@ func CreateConfigMapForCRS(configMapName, configMapNamespace string, cm.Data[defaultCRSConfigMapKey] = string(utilyaml.JoinYaml(l...)) return cm, nil } + +func SetTLSConfigForHelmChartProxyIfNeeded(hcp *caaphv1.HelmChartProxy) { + // this is set as an environment variable from the downward API on deployment + deploymentNS := os.Getenv("POD_NAMESPACE") + if deploymentNS == "" { + deploymentNS = metav1.NamespaceDefault + } + if strings.Contains(hcp.Spec.RepoURL, "helm-repository") { + hcp.Spec.TLSConfig = &caaphv1.TLSConfig{ + CASecretRef: &corev1.SecretReference{ + Name: "helm-repository-tls", + Namespace: deploymentNS, + }, + } + } +} diff --git a/test/e2e/config/caren.yaml b/test/e2e/config/caren.yaml index 7900be089..a46f1ff85 100644 --- a/test/e2e/config/caren.yaml +++ b/test/e2e/config/caren.yaml @@ -6,6 +6,8 @@ managementClusterName: caren-e2e images: - name: ko.local/cluster-api-runtime-extensions-nutanix:${E2E_IMAGE_TAG} loadBehavior: mustLoad + - name: ghcr.io/nutanix-cloud-native/caren-helm-reg:${E2E_IMAGE_TAG} + loadBehavior: mustLoad providers: - name: cluster-api