Skip to content

Commit b78cca0

Browse files
committed
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: fluxcd/flux2#2959 Signed-off-by: Max Jonas Werner <max@e13.dev>
1 parent b1a4949 commit b78cca0

File tree

6 files changed

+50
-6
lines changed

6 files changed

+50
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: source.toolkit.fluxcd.io/v1beta2
2+
kind: HelmChart
3+
metadata:
4+
name: helmchart-sample-oci
5+
spec:
6+
chart: stefanprodan/charts/podinfo
7+
version: '>=6.0.0 <7.0.0'
8+
sourceRef:
9+
kind: HelmRepository
10+
name: helmrepository-sample-oci
11+
interval: 1m
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: source.toolkit.fluxcd.io/v1beta2
2+
kind: HelmRepository
3+
metadata:
4+
name: helmrepository-sample-oci
5+
spec:
6+
interval: 1m
7+
type: oci
8+
url: oci://ghcr.io/

hack/ci/e2e.sh

+2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ kubectl -n source-system apply -f "${ROOT_DIR}/config/samples"
7373
kubectl -n source-system rollout status deploy/source-controller --timeout=1m
7474
kubectl -n source-system wait gitrepository/gitrepository-sample --for=condition=ready --timeout=1m
7575
kubectl -n source-system wait helmrepository/helmrepository-sample --for=condition=ready --timeout=1m
76+
kubectl -n source-system wait helmrepository/helmrepository-sample-oci --for=condition=ready --timeout=1m
7677
kubectl -n source-system wait helmchart/helmchart-sample --for=condition=ready --timeout=1m
78+
kubectl -n source-system wait helmchart/helmchart-sample-oci --for=condition=ready --timeout=1m
7779
kubectl -n source-system delete -f "${ROOT_DIR}/config/samples"
7880

7981
echo "Run HelmChart values file tests"

internal/helm/chart/builder.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ func (r RemoteReference) Validate() error {
8181
if r.Name == "" {
8282
return fmt.Errorf("no name set for remote chart reference")
8383
}
84-
name := regexp.MustCompile("^([-a-z0-9]*)$")
84+
name := regexp.MustCompile("^([-a-z0-9]+/?)+$")
8585
if !name.MatchString(r.Name) {
86-
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)
86+
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)
8787
}
8888
return nil
8989
}

internal/helm/chart/builder_remote_test.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ func TestRemoteBuilder_BuildFromOCIChatRepository(t *testing.T) {
234234

235235
registryClient := &mockRegistryClient{
236236
tags: map[string][]string{
237-
"localhost:5000/my_repo/grafana": {"6.17.4"},
237+
"localhost:5000/my_repo/grafana": {"6.17.4"},
238+
"localhost:5000/my_repo/another/grafana": {"6.17.4"},
238239
},
239240
}
240241

@@ -318,6 +319,15 @@ func TestRemoteBuilder_BuildFromOCIChatRepository(t *testing.T) {
318319
"replicaCount": float64(1),
319320
},
320321
},
322+
{
323+
name: "default values",
324+
reference: RemoteReference{Name: "another/grafana"},
325+
repository: mockRepo(),
326+
wantVersion: "0.1.0",
327+
wantValues: chartutil.Values{
328+
"replicaCount": float64(1),
329+
},
330+
},
321331
{
322332
name: "merge values",
323333
reference: RemoteReference{Name: "grafana"},

internal/helm/chart/builder_test.go

+16-3
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,34 @@ func TestRemoteReference_Validate(t *testing.T) {
8585
name: "ref with name",
8686
ref: RemoteReference{Name: "valid-chart-name"},
8787
},
88+
{
89+
name: "ref with single-character name",
90+
ref: RemoteReference{Name: "a"},
91+
},
8892
{
8993
name: "ref with invalid name",
9094
ref: RemoteReference{Name: "iNvAlID-ChArT-NAmE!"},
9195
wantErr: "invalid chart name 'iNvAlID-ChArT-NAmE!'",
9296
},
9397
{
94-
name: "ref with Artifactory specific invalid format",
95-
ref: RemoteReference{Name: "i-shall/not"},
96-
wantErr: "invalid chart name 'i-shall/not'",
98+
name: "ref with Artifactory specific valid format",
99+
ref: RemoteReference{Name: "i-shall/not"},
97100
},
98101
{
99102
name: "ref without name",
100103
ref: RemoteReference{},
101104
wantErr: "no name set for remote chart reference",
102105
},
106+
{
107+
name: "ref with only a slash",
108+
ref: RemoteReference{Name: "/"},
109+
wantErr: "invalid chart name '/'",
110+
},
111+
{
112+
name: "ref with double slash",
113+
ref: RemoteReference{Name: "not//a/valid/chart"},
114+
wantErr: "invalid chart name 'not//a/valid/chart'",
115+
},
103116
}
104117
for _, tt := range tests {
105118
t.Run(tt.name, func(t *testing.T) {

0 commit comments

Comments
 (0)