Merge pull request #2781 from fluxcd/create-source-helm-oci

Add OCI support to `create source helm`
pull/2787/head
Stefan Prodan 3 years ago committed by GitHub
commit b84e613b5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -44,23 +44,34 @@ var createSourceHelmCmd = &cobra.Command{
Short: "Create or update a HelmRepository source", Short: "Create or update a HelmRepository source",
Long: `The create source helm command generates a HelmRepository resource and waits for it to fetch the index. Long: `The create source helm command generates a HelmRepository resource and waits for it to fetch the index.
For private Helm repositories, the basic authentication credentials are stored in a Kubernetes secret.`, For private Helm repositories, the basic authentication credentials are stored in a Kubernetes secret.`,
Example: ` # Create a source for a public Helm repository Example: ` # Create a source for an HTTPS public Helm repository
flux create source helm podinfo \ flux create source helm podinfo \
--url=https://stefanprodan.github.io/podinfo \ --url=https://stefanprodan.github.io/podinfo \
--interval=10m --interval=10m
# Create a source for a Helm repository using basic authentication # Create a source for an HTTPS Helm repository using basic authentication
flux create source helm podinfo \ flux create source helm podinfo \
--url=https://stefanprodan.github.io/podinfo \ --url=https://stefanprodan.github.io/podinfo \
--username=username \ --username=username \
--password=password --password=password
# Create a source for a Helm repository using TLS authentication # Create a source for an HTTPS Helm repository using TLS authentication
flux create source helm podinfo \ flux create source helm podinfo \
--url=https://stefanprodan.github.io/podinfo \ --url=https://stefanprodan.github.io/podinfo \
--cert-file=./cert.crt \ --cert-file=./cert.crt \
--key-file=./key.crt \ --key-file=./key.crt \
--ca-file=./ca.crt`, --ca-file=./ca.crt
# Create a source for an OCI Helm repository
flux create source helm podinfo \
--url=oci://ghcr.io/stefanprodan/charts/podinfo
--username=username \
--password=password
# Create a source for an OCI Helm repository using an existing secret with basic auth or dockerconfig credentials
flux create source helm podinfo \
--url=oci://ghcr.io/stefanprodan/charts/podinfo
--secret-ref=docker-config`,
RunE: createSourceHelmCmdRun, RunE: createSourceHelmCmdRun,
} }
@ -84,7 +95,7 @@ func init() {
createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.certFile, "cert-file", "", "TLS authentication cert file path") createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.certFile, "cert-file", "", "TLS authentication cert file path")
createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.keyFile, "key-file", "", "TLS authentication key file path") createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.keyFile, "key-file", "", "TLS authentication key file path")
createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.caFile, "ca-file", "", "TLS authentication CA file path") createSourceHelmCmd.Flags().StringVar(&sourceHelmArgs.caFile, "ca-file", "", "TLS authentication CA file path")
createSourceHelmCmd.Flags().StringVarP(&sourceHelmArgs.secretRef, "secret-ref", "", "", "the name of an existing secret containing TLS or basic auth credentials") createSourceHelmCmd.Flags().StringVarP(&sourceHelmArgs.secretRef, "secret-ref", "", "", "the name of an existing secret containing TLS, basic auth or docker-config credentials")
createSourceHelmCmd.Flags().BoolVarP(&sourceHelmArgs.passCredentials, "pass-credentials", "", false, "pass credentials to all domains") createSourceHelmCmd.Flags().BoolVarP(&sourceHelmArgs.passCredentials, "pass-credentials", "", false, "pass credentials to all domains")
createSourceCmd.AddCommand(createSourceHelmCmd) createSourceCmd.AddCommand(createSourceHelmCmd)
@ -126,6 +137,14 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
}, },
} }
url, err := url.Parse(sourceHelmArgs.url)
if err != nil {
return fmt.Errorf("failed to parse URL: %w", err)
}
if url.Scheme == sourcev1.HelmRepositoryTypeOCI {
helmRepository.Spec.Type = sourcev1.HelmRepositoryTypeOCI
}
if createSourceArgs.fetchTimeout > 0 { if createSourceArgs.fetchTimeout > 0 {
helmRepository.Spec.Timeout = &metav1.Duration{Duration: createSourceArgs.fetchTimeout} helmRepository.Spec.Timeout = &metav1.Duration{Duration: createSourceArgs.fetchTimeout}
} }
@ -196,6 +215,11 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Successf("HelmRepository source reconciliation completed") logger.Successf("HelmRepository source reconciliation completed")
if helmRepository.Spec.Type == sourcev1.HelmRepositoryTypeOCI {
// OCI repos don't expose any artifact so we just return early here
return nil
}
if helmRepository.Status.Artifact == nil { if helmRepository.Status.Artifact == nil {
return fmt.Errorf("HelmRepository source reconciliation completed but no artifact was found") return fmt.Errorf("HelmRepository source reconciliation completed but no artifact was found")
} }

@ -0,0 +1,81 @@
//go:build unit
// +build unit
/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"testing"
)
func TestCreateSourceHelm(t *testing.T) {
tests := []struct {
name string
args string
resultFile string
assertFunc string
}{
{
name: "no args",
args: "create source helm",
resultFile: "name is required",
assertFunc: "assertError",
},
{
name: "OCI repo",
args: "create source helm podinfo --url=oci://ghcr.io/stefanprodan/charts/podinfo --interval 5m --export",
resultFile: "./testdata/create_source_helm/oci.golden",
assertFunc: "assertGoldenTemplateFile",
},
{
name: "OCI repo with Secret ref",
args: "create source helm podinfo --url=oci://ghcr.io/stefanprodan/charts/podinfo --interval 5m --secret-ref=creds --export",
resultFile: "./testdata/create_source_helm/oci-with-secret.golden",
assertFunc: "assertGoldenTemplateFile",
},
{
name: "HTTPS repo",
args: "create source helm podinfo --url=https://stefanprodan.github.io/charts/podinfo --interval 5m --export",
resultFile: "./testdata/create_source_helm/https.golden",
assertFunc: "assertGoldenTemplateFile",
},
}
tmpl := map[string]string{
"fluxns": allocateNamespace("flux-system"),
}
setup(t, tmpl)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var assert assertFunc
switch tt.assertFunc {
case "assertGoldenTemplateFile":
assert = assertGoldenTemplateFile(tt.resultFile, tmpl)
case "assertError":
assert = assertError(tt.resultFile)
}
cmd := cmdTestCase{
args: tt.args + " -n " + tmpl["fluxns"],
assert: assert,
}
cmd.runTestCmd(t)
})
}
}

@ -386,6 +386,7 @@ func executeCommand(cmd string) (string, error) {
func resetCmdArgs() { func resetCmdArgs() {
createArgs = createFlags{} createArgs = createFlags{}
getArgs = GetFlags{} getArgs = GetFlags{}
sourceHelmArgs = sourceHelmFlags{}
secretGitArgs = NewSecretGitFlags() secretGitArgs = NewSecretGitFlags()
} }

@ -0,0 +1,10 @@
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
interval: 5m0s
url: https://stefanprodan.github.io/charts/podinfo

@ -0,0 +1,13 @@
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
interval: 5m0s
secretRef:
name: creds
type: oci
url: oci://ghcr.io/stefanprodan/charts/podinfo

@ -0,0 +1,11 @@
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
interval: 5m0s
type: oci
url: oci://ghcr.io/stefanprodan/charts/podinfo

@ -11,7 +11,7 @@ require (
github.com/fluxcd/notification-controller/api v0.23.5 github.com/fluxcd/notification-controller/api v0.23.5
github.com/fluxcd/pkg/apis/meta v0.14.1 github.com/fluxcd/pkg/apis/meta v0.14.1
github.com/fluxcd/pkg/runtime v0.16.1 github.com/fluxcd/pkg/runtime v0.16.1
github.com/fluxcd/source-controller/api v0.24.4 github.com/fluxcd/source-controller/api v0.25.0
github.com/hashicorp/terraform-exec v0.15.0 github.com/hashicorp/terraform-exec v0.15.0
github.com/libgit2/git2go/v31 v31.7.9 github.com/libgit2/git2go/v31 v31.7.9
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5

@ -215,8 +215,8 @@ github.com/fluxcd/pkg/apis/meta v0.14.1 h1:lPDs9yV67DnwalHPb13bbnDkAatALfUiAMRHj
github.com/fluxcd/pkg/apis/meta v0.14.1/go.mod h1:1uJkTJGSZWrZxL5PFpx1IxGLrFmT1Cd0C2fFWrbv77I= github.com/fluxcd/pkg/apis/meta v0.14.1/go.mod h1:1uJkTJGSZWrZxL5PFpx1IxGLrFmT1Cd0C2fFWrbv77I=
github.com/fluxcd/pkg/runtime v0.16.1 h1:WU1vNZz4TAzmATQ/tl2zB/FX6GIUTgYeBn/G5RuTA2c= github.com/fluxcd/pkg/runtime v0.16.1 h1:WU1vNZz4TAzmATQ/tl2zB/FX6GIUTgYeBn/G5RuTA2c=
github.com/fluxcd/pkg/runtime v0.16.1/go.mod h1:cgVJkOXCg9OmrIUGklf/0UtV28MNzkuoBJhaEQICT6E= github.com/fluxcd/pkg/runtime v0.16.1/go.mod h1:cgVJkOXCg9OmrIUGklf/0UtV28MNzkuoBJhaEQICT6E=
github.com/fluxcd/source-controller/api v0.24.4 h1:m54sS1rJlgJf5j9qDRgKLhbPJAnJ9dY+VrstPKj0aQo= github.com/fluxcd/source-controller/api v0.25.0 h1:+uL+hQb/6h2MHuE9/Iq054TrDWF70puAuWBcoBrZK5M=
github.com/fluxcd/source-controller/api v0.24.4/go.mod h1:b0MmMPGE8gcpgSyGXe5m7see77tBW26eZrvGkkPstUs= github.com/fluxcd/source-controller/api v0.25.0/go.mod h1:tuMrqHHpRt7mxdLeRXGIMtTKAMufLwLTm5uXkEOJWFw=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=

Loading…
Cancel
Save