Skip to content

Commit

Permalink
Add support for Release CRs (#211)
Browse files Browse the repository at this point in the history
* Add release version Helm value

* Read app versions from the Release CR

* Read app versions (for HelmReleases) from the Release CR

* Read Kubernetes version from the Release CR

* Add template for getting Kubernetes version

* Add config to allow rendering templates offline without Release CR

* Add helper to read Flatcar variant string

* Add helper for getting Flatcar version
  • Loading branch information
nprokopic authored Jun 11, 2024
1 parent f985543 commit a02e57c
Show file tree
Hide file tree
Showing 12 changed files with 294 additions and 8 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- This PR adds support for using Release CRs and getting Kubernetes, Flatcar and apps version, catalog and dependencies
from there. This change is fully backward compatible, and it requires that new flag `$.Values.providerIntegration.useReleases`
is set to `true`. The default value of `$.Values.providerIntegration.useReleases` is `false`, so cluster chart version
can be safely updated.

## [0.30.1] - 2024-06-07

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion Makefile.development.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ endif
template: ## Output the rendered Helm template
$(eval CHART_DIR := "helm/cluster")
$(eval HELM_RELEASE_NAME := $(shell yq .global.metadata.name ${CHART_DIR}/${CI_FILE}))
@helm template -n org-giantswarm ${HELM_RELEASE_NAME} ${CHART_DIR} --values ${CHART_DIR}/${CI_FILE} --debug
@helm template --dry-run=server -n org-giantswarm ${HELM_RELEASE_NAME} ${CHART_DIR} --values ${CHART_DIR}/${CI_FILE} --debug

.PHONY: generate
generate: normalize-schema validate-schema generate-docs generate-values
11 changes: 11 additions & 0 deletions helm/cluster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ For Giant Swarm internal use only, not stable, or not supported by UIs.
| `internal.ephemeralConfiguration.apps.PATTERN.catalogOverride` | **Catalog override** - Name of the catalog from which the app is installed.|**Type:** `string`<br/>**Key pattern:**<br/>`PATTERN`=`[a-z][a-zA-Z]+`<br/>|
| `internal.ephemeralConfiguration.apps.PATTERN.disable` | **Disable** - Flag that indicates if the app is disabled and skipped during the cluster deployment.|**Type:** `boolean`<br/>**Key pattern:**<br/>`PATTERN`=`[a-z][a-zA-Z]+`<br/>|
| `internal.ephemeralConfiguration.apps.PATTERN.versionOverride` | **Version override** - Custom application version that overrides the application version from the release. This is usually a new development version that you want to test, or a newer patch version that you need to deploy in order to put out a production fire in the middle of the night. Use carefully!|**Type:** `string`<br/>**Key pattern:**<br/>`PATTERN`=`[a-z][a-zA-Z]+`<br/>|
| `internal.ephemeralConfiguration.offlineTesting` | **Offline testing** - Configure how Helm template rendering behaves when it is running during testing (e.g. locally or in the CI) and without connection to cluster.|**Type:** `object`<br/>|
| `internal.ephemeralConfiguration.offlineTesting.renderWithoutReleaseResource` | **Render without Release resource** - Flag that indicates that Helm should render templates even when Release CR cannot be fetched from the cluster.|**Type:** `boolean`<br/>|

### Metadata
Properties within the `.global.metadata` object
Expand Down Expand Up @@ -768,6 +770,7 @@ Provider-specific properties that can be set by cluster-$provider chart in order
| `providerIntegration.teleport.enabled` | **Enable teleport**|**Type:** `boolean`<br/>**Default:** `true`|
| `providerIntegration.teleport.proxyAddr` | **Teleport proxy address**|**Type:** `string`<br/>**Default:** `"teleport.giantswarm.io:443"`|
| `providerIntegration.teleport.version` | **Teleport version**|**Type:** `string`<br/>**Default:** `"14.1.3"`|
| `providerIntegration.useReleases` | **Use releases** - Flag that indicates if the provider is using release resources to get app and component versions.|**Type:** `boolean`<br/>**Default:** `false`|
| `providerIntegration.workers` | **Provider-specific workers configuration**|**Type:** `object`<br/>|
| `providerIntegration.workers.defaultNodePools` | **Default node pools**|**Type:** `object`<br/>|
| `providerIntegration.workers.defaultNodePools.PATTERN` | **Node pool**|**Type:** `object`<br/>**Key pattern:**<br/>`PATTERN`=`^[a-z0-9][-a-z0-9]{3,18}[a-z0-9]$`<br/>|
Expand Down Expand Up @@ -864,6 +867,14 @@ Provider-specific properties that can be set by cluster-$provider chart in order
| `providerIntegration.workers.resources` | **Resources configuration** - Infrastructure template for worker resources when using MachineDeployment.|**Type:** `object`<br/>|
| `providerIntegration.workers.resources.infrastructureMachineTemplateSpecTemplateName` | **Infrastructure Machine template spec template name** - The name of Helm template that renders Infrastructure Machine template spec.|**Type:** `string`<br/>|

### Release
Properties within the `.global.release` object
Information about the workload cluster release.

| **Property** | **Description** | **More Details** |
| :----------- | :-------------- | :--------------- |
| `global.release.version` | **Version**|**Type:** `string`<br/>|



<!-- DOCS_END -->
5 changes: 5 additions & 0 deletions helm/cluster/ci/ci-values.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
global:
managementCluster: giantmc
release:
version: v27.0.0-alpha.1
metadata:
name: awesome
organization: giantswarm
Expand Down Expand Up @@ -266,6 +268,8 @@ internal:
chartOperatorExtensions:
catalogOverride: default-test
versionOverride: v100.0.0-dev.8234y65dh92783
offlineTesting:
renderWithoutReleaseResource: true
providerIntegration:
apps:
capiNodeLabeler:
Expand Down Expand Up @@ -599,3 +603,4 @@ providerIntegration:
- echo "aws workers command before kubeadm"
postKubeadmCommands:
- echo "aws workers command after kubeadm"
useReleases: true
2 changes: 2 additions & 0 deletions helm/cluster/ci/test-required-values.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
global:
release:
version: v27.0.0-alpha.1
metadata:
name: awesome
organization: giantswarm
Expand Down
216 changes: 215 additions & 1 deletion helm/cluster/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,218 @@ Where `data` is the data to hash and `global` is the top level scope.
{{- end -}}
{{- end -}}
{{- $registry -}}
{{- end -}}
{{- end -}}

{{/*
cluster.internal.get-provider-integration-values named helper template gets provider-integration Helm values and sets
them in the $.GiantSwarm.providerIntegration object.
For more details about how this works and how and why it is used, see explanation for the named helper template
cluster.internal.get-internal-values, since this template serves the same purpose and works in the same way, just for
$.Values.providerIntegration (vs $.Values.cluster.providerIntegration) Helm values.
*/}}
{{- define "cluster.internal.get-provider-integration-values" }}
{{- $providerIntegration := dict }}
{{- /* Case 1: template is called from the cluster chart itself */}}
{{- if and (eq $.Chart.Name "cluster") $.Values.providerIntegration }}
{{- $providerIntegration = $.Values.providerIntegration }}
{{- /* Case 2: template is called from a parent chart that passes Helm values to cluster chart in .Values.cluster */}}
{{- else if ($.Values.cluster).providerIntegration }}
{{- $providerIntegration = $.Values.cluster.providerIntegration }}
{{- end }}
{{- /* Create $.GiantSwarm object where we put custom Giant Swarm vars */}}
{{- if not $.GiantSwarm }}
{{- $_ := set $ "GiantSwarm" dict }}
{{- end }}
{{- /* Finally set $.GiantSwarm.providerIntegration object that can be used in other templates */}}
{{- $_ := set $.GiantSwarm "providerIntegration" $providerIntegration }}
{{- end }}

{{/*
cluster.internal.get-internal-values named helper template gets internal Helm values and sets them in the
$.GiantSwarm.internal object.
Some public named helper templates from cluster chart are using cluster chart's $.Values.internal Helm values, or to
be more precise, Helm values under 'internal' key that you can see here in the cluster chart repo in values.yaml file.
While all this sounds fine at the first sight, there is a caveat:
- This works without issues when these named helper templates are called from other templates that are rendered in the
cluster chart (e.g. templates for Cluster API resources). In this case Helm values root context is what you see in
cluster chart values.yaml.
- However, when these public named helper templates are called from a parent chart (e.g. cluster-aws, cluster-vsphere,
etc), then Helm values root context is different, because we get the root context of the parent chart, and then
cluster chart's internal Helm values are set in $.Values.cluster.internal Helm value (and not in $.Values.internal).
This template here checks who is making the call to the template and then reads internal Helm values from the correct
place and sets those values in $.GiantSwarm.internal object. This way other templates that need internal values can
just call this first and then use $.GiantSwarm.internal object, e.g.:
{{- $_ := include "cluster.internal.get-internal-values" $ }}
foo: {{ $.GiantSwarm.internal.bar }}
*/}}
{{- define "cluster.internal.get-internal-values" }}
{{- $internalValues := dict }}
{{- /* Case 1: template is called from the cluster chart itself */}}
{{- if and (eq $.Chart.Name "cluster") $.Values.internal }}
{{- $internalValues = $.Values.internal }}
{{- /* Case 2: template is called from a parent chart that passes Helm values to cluster chart in .Values.cluster */}}
{{- else if ($.Values.cluster).internal }}
{{- $internalValues = $.Values.cluster.internal }}
{{- end }}
{{- /* Create $.GiantSwarm.internal object */}}
{{- if not $.GiantSwarm }}
{{- $_ := set $ "GiantSwarm" dict }}
{{- end }}
{{- /* Finally set ".GiantSwarm.internal" property that can be used in other templates */}}
{{- $_ := set $.GiantSwarm "internal" $internalValues }}
{{- end }}

{{/*
cluster.internal.get-release-resource helper gets Release resources from the management cluster
and it sets it in $.GiantSwarm.Release object.
The helper will try to get a Release CR named <provider name>-<release version without 'v'>.
Release version is obtained from Helm value $.Values.global.release.version (Helm value can have
'v' prefix which is then stripped). Example values for $.Values.global.release.version:
- 25.1.0
- v25.1.0
- 26.4.0-alpha.1
- 27.2.0-e2e.h92f8d3456
Provider name is obtained from Helm value $.Values.providerIntegration.provider. Provider names
of the current providers (as of June 2024) are:
- aws
- azure
- vshpere
- cloud-director
If the Release resource is not found, then the behavior depends on the value of
$.GiantSwarm.internal.ephemeralConfiguration.offlineTesting.renderWithoutReleaseResource:
- if renderWithoutReleaseResource is false, template rendering fails,
- if renderWithoutReleaseResource is true, template does nothing.
*/}}
{{- define "cluster.internal.get-release-resource" }}
{{- $_ := include "cluster.internal.get-internal-values" $ }}
{{- $_ = include "cluster.internal.get-provider-integration-values" $ }}
{{- $renderWithoutReleaseResource := ((($.GiantSwarm.internal).ephemeralConfiguration).offlineTesting).renderWithoutReleaseResource | default false }}
{{- $releaseVersion := $.Values.global.release.version | trimPrefix "v" }}
{{- $releaseVersion = printf "%s-%s" $.GiantSwarm.providerIntegration.provider $releaseVersion }}
{{- $release := lookup "release.giantswarm.io/v1alpha1" "Release" "" $releaseVersion }}
{{- if $release }}
{{- $_ := set $.GiantSwarm "Release" $release }}
{{ else if not $renderWithoutReleaseResource }}
{{- fail (printf "Release resource '%s' not found" $releaseVersion) }}
{{- end }}
{{- end }}

{{/*
cluster.app.version is a public named helper template that returns a version of the app that is specified under
property 'appName' in the object that is passed to the template. App version is obtained from the Release resource.
Example usage in template:
{{- $_ := set $ "appName" "foo-bar-controller" }}
{{- $appVersion := include "cluster.app.version" $ }}
version: {{ $appVersion }}
*/}}
{{- define "cluster.app.version" }}
{{- $appVersion := "N/A" }}
{{- $_ := (include "cluster.internal.get-release-resource" $) }}
{{- if $.GiantSwarm.Release }}
{{- range $_, $app := $.GiantSwarm.Release.spec.apps }}
{{- if eq $app.name $.appName }}
{{- $appVersion = $app.version }}
{{- end }}
{{- end }}
{{- end }}
{{- $appVersion }}
{{- end }}

{{/*
cluster.component.version is a public named helper template that returns a version of the component that is specified
under property 'componentName' in the object that is passed to the template. Component version is obtained from the
Release resource.
Example usage in template:
{{- $_ := set $ "componentName" "flatcar" }}
{{- $componentVersion := include "cluster.component.version" $ }}
version: {{ $componentVersion }}
*/}}
{{- define "cluster.component.version" }}
{{- $componentVersion := "N/A" }}
{{- $_ := (include "cluster.internal.get-release-resource" $) }}
{{- if $.GiantSwarm.Release }}
{{- range $_, $component := $.GiantSwarm.Release.spec.components }}
{{- if eq $component.name $.componentName }}
{{- $componentVersion = $component.version }}
{{- end }}
{{- end }}
{{- end }}
{{- $componentVersion }}
{{- end }}

{{/*
cluster.component.kubernetes.version is a public named helper template that returns the Kubernetes version. If the
provider is using new Releases then the Kubernetes version is obtained from the Release resources, otherwise it is
obtained from Helm values.
Example usage in template:
version: {{ include "cluster.component.kubernetes.version" $ }}
*/}}
{{- define "cluster.component.kubernetes.version" }}
{{- $_ := include "cluster.internal.get-provider-integration-values" $ }}
{{- if $.GiantSwarm.providerIntegration.useReleases }}
{{- $_ := set $ "componentName" "kubernetes" }}
{{- include "cluster.component.version" $ | trimPrefix "v" }}
{{- else if $.GiantSwarm.providerIntegration.kubernetesVersion }}
{{- $.GiantSwarm.providerIntegration.kubernetesVersion | trimPrefix "v" }}
{{- else }}
{{- fail "Cannot determine Kubernetes version" }}
{{- end }}
{{- end }}

{{/*
cluster.component.flatcar.version is a public named helper template that returns the Flatcar version. If the
provider is using new Releases then the Flatcar version is obtained from the Release resources, otherwise it is
obtained from Helm values.
Example usage in template:
version: {{ include "cluster.component.flatcar.version" $ }}
*/}}
{{- define "cluster.component.flatcar.version" }}
{{- $_ := include "cluster.internal.get-provider-integration-values" $ }}
{{- if $.GiantSwarm.providerIntegration.useReleases }}
{{- $_ := set $ "componentName" "flatcar" }}
{{- $flatcarVersion := include "cluster.component.version" $ | trimPrefix "v" }}
{{- $flatcarVersion }}
{{- else if $.GiantSwarm.providerIntegration.osImage }}
{{- $.GiantSwarm.providerIntegration.osImage.version }}
{{- else }}
{{- fail "Cannot determine Flatcar version" }}
{{- end }}
{{- end }}

{{/*
cluster.component.flatcar.version is a public named helper template that returns the Flatcar image variant. If the
provider is using new Releases then the Flatcar image variant is obtained from the Release resources, otherwise it is
obtained from Helm values.
Example usage in template:
version: {{ include "cluster.component.flatcar.variant" $ }}
*/}}
{{- define "cluster.component.flatcar.variant" }}
{{- $_ := include "cluster.internal.get-provider-integration-values" $ }}
{{- if $.GiantSwarm.providerIntegration.useReleases }}
{{- $_ := set $ "componentName" "flatcar-variant" }}
{{- $flatcarVariant := include "cluster.component.version" $ | trimPrefix "v" | split "." }}
{{- $flatcarVariant._0 }}
{{- else if $.GiantSwarm.providerIntegration.osImage }}
{{- $.GiantSwarm.providerIntegration.osImage.variant }}
{{- else }}
{{- fail "Cannot determine Flatcar image variant" }}
{{- end }}
{{- end }}
7 changes: 6 additions & 1 deletion helm/cluster/templates/apps/apps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,12 @@ spec:
name: {{ $.Values.global.metadata.name }}-kubeconfig
namespace: {{ $.Release.Namespace}}
{{- end }}
version: {{ $ephemeralConfig.versionOverride | default $app.version | trim | trimPrefix "v" }}
{{- $appVersion := $app.version -}}
{{- if $.Values.providerIntegration.useReleases }}
{{- $_ := set $ "appName" $app.appName }}
{{ $appVersion = include "cluster.app.version" $ }}
{{- end }}
version: {{ $ephemeralConfig.versionOverride | default $appVersion | trim | trimPrefix "v" }}
{{- if or ($app.clusterValues).configMap ($app.clusterValues).secret }}
config:
{{- if ($app.clusterValues).configMap }}
Expand Down
7 changes: 6 additions & 1 deletion helm/cluster/templates/apps/helmreleases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ spec:
chart:
spec:
chart: {{ $app.chartName | default $app.appName }}
version: {{ $ephemeralConfig.versionOverride | default $app.version }}
{{- $appVersion := $app.version -}}
{{- if $.Values.providerIntegration.useReleases }}
{{- $_ := set $ "appName" $app.appName }}
{{- $appVersion = include "cluster.app.version" $ }}
{{- end }}
version: {{ $ephemeralConfig.versionOverride | default $appVersion }}
sourceRef:
kind: HelmRepository
name: {{ include "cluster.resource.name" $ }}-{{ $ephemeralConfig.catalogOverride | default $app.catalog | default "default" }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ spec:
replicas: {{ .Values.global.controlPlane.replicas }}
rolloutBefore:
{{- toYaml $.Values.internal.advancedConfiguration.controlPlane.rolloutBefore | nindent 4 }}
version: v{{ trimPrefix "v" .Values.providerIntegration.kubernetesVersion }}
version: v{{ include "cluster.component.kubernetes.version" $ }}
{{- end }}
2 changes: 1 addition & 1 deletion helm/cluster/templates/clusterapi/workers/machinepool.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ spec:
apiVersion: {{ $.Values.providerIntegration.resourcesApi.infrastructureMachinePool.group }}/{{ $.Values.providerIntegration.resourcesApi.infrastructureMachinePool.version }}
kind: {{ $.Values.providerIntegration.resourcesApi.infrastructureMachinePool.kind }}
name: {{ include "cluster.resource.name" $ }}-{{ $nodePoolName }}
version: {{ $.Values.providerIntegration.kubernetesVersion }}
version: v{{ include "cluster.component.kubernetes.version" $ }}
---
{{- end }}
{{- end }}
Expand Down
Loading

0 comments on commit a02e57c

Please sign in to comment.