diff --git a/.github/workflows/argocd-understack-release.yaml b/.github/workflows/argocd-understack-release.yaml new file mode 100644 index 000000000..4c6f91dfa --- /dev/null +++ b/.github/workflows/argocd-understack-release.yaml @@ -0,0 +1,85 @@ +--- +name: argocd-understack release + +on: + push: + tags: + - "argocd-understack-v*.*.*" + workflow_dispatch: + inputs: + chart_version: + description: "Chart version to release (e.g., 0.1.0)" + required: true + type: string + +permissions: + contents: read + packages: write + id-token: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.18.4 + + - name: Install Cosign + uses: sigstore/cosign-installer@v3 + + - name: Extract version from tag or input + id: version + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + VERSION="${{ inputs.chart_version }}" + else + VERSION=${GITHUB_REF#refs/tags/argocd-understack-v} + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Helm lint + run: | + helm lint charts/argocd-understack --strict + + - name: Package chart + run: | + VERSION="${{ steps.version.outputs.version }}" + helm package charts/argocd-understack --version "$VERSION" + + - name: Login to GitHub Container Registry + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Push chart to GHCR + run: | + VERSION="${{ steps.version.outputs.version }}" + CHART_PACKAGE="argocd-understack-${VERSION}.tgz" + + if [[ ! -f "$CHART_PACKAGE" ]]; then + echo "::error::Chart package $CHART_PACKAGE not found" + ls -la *.tgz + exit 1 + fi + + helm push "$CHART_PACKAGE" oci://ghcr.io/${{ github.repository }} + + echo "::notice::Chart pushed to oci://ghcr.io/${{ github.repository }}/argocd-understack:${VERSION}" + + - name: Sign chart with Cosign + run: | + VERSION="${{ steps.version.outputs.version }}" + cosign sign --yes ghcr.io/${{ github.repository }}/argocd-understack:${VERSION} + + echo "::notice::Chart signed with keyless signature" + + - name: Logout from GHCR + if: always() + run: | + helm registry logout ghcr.io diff --git a/.github/workflows/helm-chart-test.yaml b/.github/workflows/helm-chart-test.yaml new file mode 100644 index 000000000..ecff4b399 --- /dev/null +++ b/.github/workflows/helm-chart-test.yaml @@ -0,0 +1,71 @@ +--- +name: Helm Chart Testing + +on: + pull_request: + paths: + - "charts/**" + - ".github/workflows/helm-chart-test.yaml" + push: + branches: + - main + paths: + - "charts/**" + merge_group: + types: [checks_requested] + workflow_dispatch: + +jobs: + lint-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.18.4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + check-latest: true + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2 + + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct list-changed --chart-dirs charts --target-branch ${{ github.event.repository.default_branch }}) + if [[ -n "$changed" ]]; then + echo "changed=true" >> "$GITHUB_OUTPUT" + + # Set individual output variables for each changed chart + for chart in $changed; do + chart_name=$(basename "$chart") + echo "$chart_name=true" >> "$GITHUB_OUTPUT" + echo "Changed: $chart_name" + done + fi + + - name: Run chart-testing (lint) + if: steps.list-changed.outputs.changed == 'true' + run: ct lint --chart-dirs charts --target-branch ${{ github.event.repository.default_branch }} + + - name: Create kind cluster + if: steps.list-changed.outputs.changed == 'true' + uses: helm/kind-action@v1 + + - name: Install ArgoCD + if: steps.list-changed.outputs.argocd-understack == 'true' + run: | + ./bootstrap/argocd.sh + + - name: Run chart-testing (install) + if: steps.list-changed.outputs.argocd-understack == 'true' + run: helm install testsite charts/argocd-understack --namespace argocd --values charts/argocd-understack/ci/example.yaml diff --git a/.gitignore b/.gitignore index f616ac9d9..429c6934e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -# where helm charts will get downloaded by kustomize -/charts/ - # un-encrypted secrets /secret-*.yaml # sealed secrets diff --git a/.typos.toml b/.typos.toml index 589c1bd54..066bf1abf 100644 --- a/.typos.toml +++ b/.typos.toml @@ -19,6 +19,9 @@ extend-exclude = [ extend-ignore-identifiers-re = [ "ironic_retrive_*", ] +extend-ignore-re = [ + "chartVersion:.*", +] [default.extend-words] # Don't correct "HPE" diff --git a/bootstrap/argocd.sh b/bootstrap/argocd.sh old mode 100644 new mode 100755 index b266b1d24..1aec392f4 --- a/bootstrap/argocd.sh +++ b/bootstrap/argocd.sh @@ -10,8 +10,10 @@ argocd_rev=$(cat "${thisdir}/../apps/appsets/argocd/appset-argocd.yaml" | yq -r helm repo add argo "${argocd_repo}" helm repo update argo -helm template argo-cd argo-cd \ +kubectl create ns argocd + +helm template argo/argo-cd \ --version "${argocd_rev}" \ - --create-namespace \ + --namespace argocd \ -f "${thisdir}/../components/argocd/values.yaml" \ | kubectl -n argocd apply -f - diff --git a/charts/argocd-understack/.helmignore b/charts/argocd-understack/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/charts/argocd-understack/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/argocd-understack/Chart.yaml b/charts/argocd-understack/Chart.yaml new file mode 100644 index 000000000..0599dd50a --- /dev/null +++ b/charts/argocd-understack/Chart.yaml @@ -0,0 +1,27 @@ +apiVersion: v2 +name: argocd-understack +description: ArgoCD Application definitions for UnderStack + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +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.1.0 + +# 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. +# It is recommended to use it with quotes. +appVersion: "1.16.0" + +maintainers: + - name: rackerlabs diff --git a/charts/argocd-understack/ci/example.yaml b/charts/argocd-understack/ci/example.yaml new file mode 100644 index 000000000..4b1367296 --- /dev/null +++ b/charts/argocd-understack/ci/example.yaml @@ -0,0 +1,2 @@ +--- +deploy_url: https://github.com/example/example diff --git a/charts/argocd-understack/templates/_helpers.tpl b/charts/argocd-understack/templates/_helpers.tpl new file mode 100644 index 000000000..220e7d194 --- /dev/null +++ b/charts/argocd-understack/templates/_helpers.tpl @@ -0,0 +1,99 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "understack.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "understack.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "understack.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "understack.labels" -}} +helm.sh/chart: {{ include "understack.chart" . }} +{{ include "understack.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "understack.selectorLabels" -}} +app.kubernetes.io/name: {{ include "understack.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "understack.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "understack.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create a valid ArgoCD Application name +*/}} +{{- define "understack.argocdAppName" -}} +{{- $root := index . 0 }} +{{- $appName := index . 1 }} +{{- printf "%s-%s" $root.Release.Name $appName }} +{{- end }} + +{{/* +Get the UnderStack repository URL +*/}} +{{- define "understack.understack_url" -}} +{{- .Values.understack_url }} +{{- end }} + +{{/* +Get the UnderStack repository git reference +*/}} +{{- define "understack.understack_ref" -}} +{{- .Values.understack_ref }} +{{- end }} + +{{/* +Get the deployment repository URL +*/}} +{{- define "understack.deploy_url" -}} +{{- required "deploy_url is required. Please set it in your values file" .Values.deploy_url }} +{{- end }} + +{{/* +Get the deployment repository git reference +*/}} +{{- define "understack.deploy_ref" -}} +{{- .Values.deploy_ref }} +{{- end }} diff --git a/charts/argocd-understack/templates/application-openstack.yaml.tpl b/charts/argocd-understack/templates/application-openstack.yaml.tpl new file mode 100644 index 000000000..87a643026 --- /dev/null +++ b/charts/argocd-understack/templates/application-openstack.yaml.tpl @@ -0,0 +1,49 @@ +{{- range $appName, $app := .Values.site.openstack.apps }} +{{- if $app.enabled }} +--- +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: {{ printf "%s-%s" $.Release.Name $appName }} + {{/* + {{- with $app.wave }} + annotations: + argocd.argoproj.io/sync-wave: {{ quote . }} + {{- end }} + */}} +spec: + destination: + namespace: openstack + server: https://kubernetes.default.svc + project: understack + sources: + - repoURL: {{ $.Values.site.openstack.repoUrl }} + targetRevision: {{ $app.chartVersion }} + chart: {{ $appName }} + helm: + ignoreMissingValueFiles: true + releaseName: {{ $appName }} + valueFiles: + - $understack/components/images-openstack.yaml + - $understack/components/{{ $appName }}/values.yaml + - $deploy/{{ $.Release.Name }}/manifests/secret-openstack.yaml + - $deploy/{{ $.Release.Name }}/manifests/images-openstack.yaml + - $deploy/{{ $.Release.Name }}/helm-configs/{{ $appName }}.yaml + - path: components/{{ $appName }}/ + ref: understack + repoURL: {{ include "understack.understack_url" $ }} + targetRevision: {{ include "understack.understack_ref" $ }} + - path: {{ $.Release.Name }}/manifests/{{ $appName }} + ref: deploy + repoURL: {{ include "understack.deploy_url" $ }} + targetRevision: {{ include "understack.deploy_ref" $ }} + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - ServerSideApply=false + - RespectIgnoreDifferences=true + - ApplyOutOfSyncOnly=true +{{- end }} +{{- end }} diff --git a/charts/argocd-understack/values.yaml b/charts/argocd-understack/values.yaml new file mode 100644 index 000000000..d5a9b8767 --- /dev/null +++ b/charts/argocd-understack/values.yaml @@ -0,0 +1,153 @@ +# -- Defines the UnderStack repository URL +# [[ref]](https://rackerlabs.github.io/understack/deploy-guide/requirements/) +# @default -- https://github.com/rackerlabs/understack.git +understack_url: https://github.com/rackerlabs/understack.git + +# -- Defines the UnderStack repository git reference (commit/branch/tag) +# [[ref]](https://rackerlabs.github.io/understack/deploy-guide/requirements/) +# @default -- HEAD +understack_ref: HEAD + +# -- Defines the deployment repository URL +# [[ref]](https://rackerlabs.github.io/understack/deploy-guide/requirements/) +deploy_url: + +# -- Defines the deployment repository git reference (commit/branch/tag) +# [[ref]](https://rackerlabs.github.io/understack/deploy-guide/requirements/) +# @default -- HEAD +deploy_ref: HEAD + +# -- This block is for setting up the UnderStack site specific ArgoCD Applications +site: + # -- Enable/disable deploying the site specific applications + # @default -- true + enabled: true + + # -- OpenStack service applications configuration + openstack: + # -- OpenStack Helm chart repository URL + # @default -- https://tarballs.opendev.org/openstack/openstack-helm + repoUrl: https://tarballs.opendev.org/openstack/openstack-helm + + # -- Dictionary of OpenStack applications to deploy + # @default -- See below for default apps + apps: + # -- Keystone (Identity Service) + keystone: + # -- Enable/disable deploying Keystone + # @default -- true + enabled: true + # -- Sync wave for deployment ordering (lower numbers deploy first) + # @default -- 1 + wave: 1 + # renovate: datasource=helm depName=keystone registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Keystone + chartVersion: 2025.1.5+95bf0bf6e + + # -- Glance (Image Service) + glance: + # -- Enable/disable deploying Glance + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 2 + wave: 2 + # renovate: datasource=helm depName=glance registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Glance + chartVersion: 2025.2.5+9629a4692 + + # -- Cinder (Block Storage Service) + cinder: + # -- Enable/disable deploying Cinder + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 2 + wave: 2 + # renovate: datasource=helm depName=cinder registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Cinder + chartVersion: 2025.1.3+abd55b4a7 + + # -- Ironic (Bare Metal Service) + ironic: + # -- Enable/disable deploying Ironic + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 2 + wave: 2 + # renovate: datasource=helm depName=ironic registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Ironic + chartVersion: 2025.2.3+2dbc149df + + # -- Neutron (Networking Service) + neutron: + # -- Enable/disable deploying Neutron + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 2 + wave: 2 + # renovate: datasource=helm depName=neutron registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Neutron + chartVersion: 2025.1.9+3225ad74a + + # -- Placement (Placement Service) + placement: + # -- Enable/disable deploying Placement + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 2 + wave: 2 + # renovate: datasource=helm depName=placement registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Placement + chartVersion: 2025.2.3+9629a4692 + + # -- Nova (Compute Service) + nova: + # -- Enable/disable deploying Nova + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 3 + wave: 3 + # renovate: datasource=helm depName=nova registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Nova + chartVersion: 2025.1.19+12458c92d + + # -- Octavia (Load Balancer Service) + octavia: + # -- Enable/disable deploying Octavia + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 3 + wave: 3 + # renovate: datasource=helm depName=octavia registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Octavia + chartVersion: 2025.2.6+9629a4692 + + # -- Horizon (Dashboard) + horizon: + # -- Enable/disable deploying Horizon + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 4 + wave: 4 + # renovate: datasource=helm depName=horizon registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Horizon + chartVersion: 2025.2.2+9629a4692 + + # -- Skyline (Dashboard) + skyline: + # -- Enable/disable deploying Skyline + # @default -- true + enabled: true + # -- Sync wave for deployment ordering + # @default -- 4 + wave: 4 + # renovate: datasource=helm depName=horizon registryUrl=https://tarballs.opendev.org/openstack/openstack-helm + # -- Chart version for Skyline + chartVersion: 2025.1.3+0161bea65