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 <max@e13.dev>
This commit is contained in:
Max Jonas Werner 2022-08-03 15:00:27 +02:00
parent 1db1626fe1
commit 64c1b065a8
No known key found for this signature in database
GPG Key ID: EB525E0F02B52140
6 changed files with 50 additions and 6 deletions

View File

@ -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

View File

@ -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/

View File

@ -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"

View File

@ -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
}

View File

@ -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"},

View File

@ -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) {