From 64c1b065a8b63cedadf25094a758cbe98ffaf594 Mon Sep 17 00:00:00 2001 From: Max Jonas Werner Date: Wed, 3 Aug 2022 15:00:27 +0200 Subject: [PATCH] allow for charts from OCI registries to specify a chart path This change allows for a HelmRepository to point to e.g. "ghcr.io" and then a HelmRelease pointing to the chart "stefanprodan/charts/podinfo" in its `.spec.chart.spec.chart` field. Related discussion: https://github.com/fluxcd/flux2/discussions/2959 Signed-off-by: Max Jonas Werner --- ..._v1beta2_helmchart_helmrepository-oci.yaml | 11 +++++++++++ .../source_v1beta2_helmrepository-oci.yaml | 8 ++++++++ hack/ci/e2e.sh | 2 ++ internal/helm/chart/builder.go | 4 ++-- internal/helm/chart/builder_remote_test.go | 12 +++++++++++- internal/helm/chart/builder_test.go | 19 ++++++++++++++++--- 6 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 config/samples/source_v1beta2_helmchart_helmrepository-oci.yaml create mode 100644 config/samples/source_v1beta2_helmrepository-oci.yaml diff --git a/config/samples/source_v1beta2_helmchart_helmrepository-oci.yaml b/config/samples/source_v1beta2_helmchart_helmrepository-oci.yaml new file mode 100644 index 000000000..d2cdc15c6 --- /dev/null +++ b/config/samples/source_v1beta2_helmchart_helmrepository-oci.yaml @@ -0,0 +1,11 @@ +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: HelmChart +metadata: + name: helmchart-sample-oci +spec: + chart: stefanprodan/charts/podinfo + version: '>=6.0.0 <7.0.0' + sourceRef: + kind: HelmRepository + name: helmrepository-sample-oci + interval: 1m diff --git a/config/samples/source_v1beta2_helmrepository-oci.yaml b/config/samples/source_v1beta2_helmrepository-oci.yaml new file mode 100644 index 000000000..bc487c990 --- /dev/null +++ b/config/samples/source_v1beta2_helmrepository-oci.yaml @@ -0,0 +1,8 @@ +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: HelmRepository +metadata: + name: helmrepository-sample-oci +spec: + interval: 1m + type: oci + url: oci://ghcr.io/ diff --git a/hack/ci/e2e.sh b/hack/ci/e2e.sh index ccb2540f3..3d7dcb5bd 100755 --- a/hack/ci/e2e.sh +++ b/hack/ci/e2e.sh @@ -75,7 +75,9 @@ kubectl -n source-system rollout status deploy/source-controller --timeout=1m kubectl -n source-system wait gitrepository/gitrepository-sample --for=condition=ready --timeout=1m kubectl -n source-system wait ocirepository/ocirepository-sample --for=condition=ready --timeout=1m kubectl -n source-system wait helmrepository/helmrepository-sample --for=condition=ready --timeout=1m +kubectl -n source-system wait helmrepository/helmrepository-sample-oci --for=condition=ready --timeout=1m kubectl -n source-system wait helmchart/helmchart-sample --for=condition=ready --timeout=1m +kubectl -n source-system wait helmchart/helmchart-sample-oci --for=condition=ready --timeout=1m kubectl -n source-system delete -f "${ROOT_DIR}/config/samples" echo "Run HelmChart values file tests" diff --git a/internal/helm/chart/builder.go b/internal/helm/chart/builder.go index 36486c9bf..76dc517c7 100644 --- a/internal/helm/chart/builder.go +++ b/internal/helm/chart/builder.go @@ -81,9 +81,9 @@ func (r RemoteReference) Validate() error { if r.Name == "" { return fmt.Errorf("no name set for remote chart reference") } - name := regexp.MustCompile("^([-a-z0-9]*)$") + name := regexp.MustCompile("^([-a-z0-9]+/?)+$") if !name.MatchString(r.Name) { - return fmt.Errorf("invalid chart name '%s': a valid name must be lower case letters and numbers and MAY be separated with dashes (-)", r.Name) + return fmt.Errorf("invalid chart name '%s': a valid name must be lower case letters and numbers and MAY be separated with dashes (-) or slashes (/)", r.Name) } return nil } diff --git a/internal/helm/chart/builder_remote_test.go b/internal/helm/chart/builder_remote_test.go index 01ed111bc..c72f19d88 100644 --- a/internal/helm/chart/builder_remote_test.go +++ b/internal/helm/chart/builder_remote_test.go @@ -234,7 +234,8 @@ func TestRemoteBuilder_BuildFromOCIChatRepository(t *testing.T) { registryClient := &mockRegistryClient{ tags: map[string][]string{ - "localhost:5000/my_repo/grafana": {"6.17.4"}, + "localhost:5000/my_repo/grafana": {"6.17.4"}, + "localhost:5000/my_repo/another/grafana": {"6.17.4"}, }, } @@ -318,6 +319,15 @@ func TestRemoteBuilder_BuildFromOCIChatRepository(t *testing.T) { "replicaCount": float64(1), }, }, + { + name: "default values", + reference: RemoteReference{Name: "another/grafana"}, + repository: mockRepo(), + wantVersion: "0.1.0", + wantValues: chartutil.Values{ + "replicaCount": float64(1), + }, + }, { name: "merge values", reference: RemoteReference{Name: "grafana"}, diff --git a/internal/helm/chart/builder_test.go b/internal/helm/chart/builder_test.go index 0671cea17..0fac78cbe 100644 --- a/internal/helm/chart/builder_test.go +++ b/internal/helm/chart/builder_test.go @@ -85,21 +85,34 @@ func TestRemoteReference_Validate(t *testing.T) { name: "ref with name", ref: RemoteReference{Name: "valid-chart-name"}, }, + { + name: "ref with single-character name", + ref: RemoteReference{Name: "a"}, + }, { name: "ref with invalid name", ref: RemoteReference{Name: "iNvAlID-ChArT-NAmE!"}, wantErr: "invalid chart name 'iNvAlID-ChArT-NAmE!'", }, { - name: "ref with Artifactory specific invalid format", - ref: RemoteReference{Name: "i-shall/not"}, - wantErr: "invalid chart name 'i-shall/not'", + name: "ref with Artifactory specific valid format", + ref: RemoteReference{Name: "i-shall/not"}, }, { name: "ref without name", ref: RemoteReference{}, wantErr: "no name set for remote chart reference", }, + { + name: "ref with only a slash", + ref: RemoteReference{Name: "/"}, + wantErr: "invalid chart name '/'", + }, + { + name: "ref with double slash", + ref: RemoteReference{Name: "not//a/valid/chart"}, + wantErr: "invalid chart name 'not//a/valid/chart'", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {