From bd2994f9ab1d009d13b3c6f033bc6c4c7c9bdade Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Wed, 23 Sep 2020 16:44:31 +0300 Subject: [PATCH 1/2] Add support for Bucket sources to Kustomizations/HRs --- cmd/gotk/create_helmrelease.go | 6 ++++++ cmd/gotk/create_kustomization.go | 31 +++++++++++++++++---------- cmd/gotk/main.go | 19 ++++++++-------- cmd/gotk/reconcile_helmrelease.go | 6 ++++-- cmd/gotk/reconcile_kustomization.go | 8 ++++++- cmd/gotk/reconcile_source_bucket.go | 4 ++-- cmd/gotk/reconcile_source_git.go | 5 ++--- cmd/gotk/reconcile_source_helm.go | 4 ++-- docs/cmd/gotk_create_helmrelease.md | 6 ++++++ docs/cmd/gotk_create_kustomization.md | 14 +++++------- 10 files changed, 64 insertions(+), 39 deletions(-) diff --git a/cmd/gotk/create_helmrelease.go b/cmd/gotk/create_helmrelease.go index 2b6a61f5..d78278be 100644 --- a/cmd/gotk/create_helmrelease.go +++ b/cmd/gotk/create_helmrelease.go @@ -55,6 +55,12 @@ var createHelmReleaseCmd = &cobra.Command{ --source=GitRepository/podinfo \ --chart=./charts/podinfo + # Create a HelmRelease with a chart from a Bucket source + gotk create hr podinfo \ + --interval=10m \ + --source=Bucket/podinfo \ + --chart=./charts/podinfo + # Create a HelmRelease with values from a local YAML file gotk create hr podinfo \ --source=HelmRepository/podinfo \ diff --git a/cmd/gotk/create_kustomization.go b/cmd/gotk/create_kustomization.go index e5898692..c6e884e5 100644 --- a/cmd/gotk/create_kustomization.go +++ b/cmd/gotk/create_kustomization.go @@ -60,15 +60,11 @@ var createKsCmd = &cobra.Command{ --interval=5m \ --validation=client - # Create a Kustomization resource that runs under a service account - gotk create kustomization webapp \ - --source=webapp \ - --path="./deploy/overlays/staging" \ + # Create a Kustomization resource that references a Bucket + gotk create kustomization secrets \ + --source=Bucket/secrets \ --prune=true \ - --interval=5m \ - --validation=client \ - --sa-name=reconclier \ - --sa-namespace=staging + --interval=5m `, RunE: createKsCmdRun, } @@ -88,7 +84,8 @@ var ( ) func init() { - createKsCmd.Flags().StringVar(&ksSource, "source", "", "GitRepository name") + createKsCmd.Flags().StringVar(&ksSource, "source", "", + "source that contains the Kubernetes manifests, format '/' where kind can be GitRepository or Bucket, if kind is not specified it defaults to GitRepository") createKsCmd.Flags().StringVar(&ksPath, "path", "./", "path to the directory containing the Kustomization file") createKsCmd.Flags().BoolVar(&ksPrune, "prune", false, "enable garbage collection") createKsCmd.Flags().StringArrayVar(&ksHealthCheck, "health-check", nil, "workload to be included in the health assessment, in the format '/.'") @@ -111,6 +108,18 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error { if ksSource == "" { return fmt.Errorf("source is required") } + + ksSourceKind := sourcev1.GitRepositoryKind + ksSourceName := ksSource + ksSourceElements := strings.Split(ksSource, "/") + if len(ksSourceElements) == 2 { + ksSourceKind, ksSourceName = ksSourceElements[0], ksSourceElements[1] + if !utils.containsItemString(supportedKustomizationSourceKinds, ksSourceKind) { + return fmt.Errorf("source kind %s is not supported, can be %v", + ksSourceKind, supportedKustomizationSourceKinds) + } + } + if ksPath == "" { return fmt.Errorf("path is required") } @@ -141,8 +150,8 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error { Path: ksPath, Prune: ksPrune, SourceRef: kustomizev1.CrossNamespaceSourceReference{ - Kind: sourcev1.GitRepositoryKind, - Name: ksSource, + Kind: ksSourceKind, + Name: ksSourceName, }, Suspend: false, Validation: ksValidation, diff --git a/cmd/gotk/main.go b/cmd/gotk/main.go index 7087b818..1e24926d 100644 --- a/cmd/gotk/main.go +++ b/cmd/gotk/main.go @@ -106,15 +106,16 @@ var ( ) var ( - defaultComponents = []string{"source-controller", "kustomize-controller", "helm-controller", "notification-controller"} - defaultVersion = "latest" - defaultNamespace = "gitops-system" - defaultNotification = "notification-controller" - supportedLogLevels = []string{"debug", "info", "error"} - supportedArch = []string{"amd64", "arm", "arm64"} - supportedDecryptionProviders = []string{"sops"} - supportedHelmChartSourceKinds = []string{sourcev1.HelmRepositoryKind, sourcev1.GitRepositoryKind} - supportedSourceBucketProviders = []string{sourcev1.GenericBucketProvider, sourcev1.AmazonBucketProvider} + defaultComponents = []string{"source-controller", "kustomize-controller", "helm-controller", "notification-controller"} + defaultVersion = "latest" + defaultNamespace = "gitops-system" + defaultNotification = "notification-controller" + supportedLogLevels = []string{"debug", "info", "error"} + supportedArch = []string{"amd64", "arm", "arm64"} + supportedDecryptionProviders = []string{"sops"} + supportedKustomizationSourceKinds = []string{sourcev1.GitRepositoryKind, sourcev1.BucketKind} + supportedHelmChartSourceKinds = []string{sourcev1.HelmRepositoryKind, sourcev1.GitRepositoryKind, sourcev1.BucketKind} + supportedSourceBucketProviders = []string{sourcev1.GenericBucketProvider, sourcev1.AmazonBucketProvider} ) func init() { diff --git a/cmd/gotk/reconcile_helmrelease.go b/cmd/gotk/reconcile_helmrelease.go index 5bce49bf..06083b0b 100644 --- a/cmd/gotk/reconcile_helmrelease.go +++ b/cmd/gotk/reconcile_helmrelease.go @@ -85,9 +85,11 @@ func reconcileHrCmdRun(cmd *cobra.Command, args []string) error { if syncHrWithSource { switch helmRelease.Spec.Chart.Spec.SourceRef.Kind { case sourcev1.HelmRepositoryKind: - err = syncSourceHelmCmdRun(nil, []string{helmRelease.Spec.Chart.Spec.SourceRef.Name}) + err = reconcileSourceHelmCmdRun(nil, []string{helmRelease.Spec.Chart.Spec.SourceRef.Name}) case sourcev1.GitRepositoryKind: - err = syncSourceGitCmdRun(nil, []string{helmRelease.Spec.Chart.Spec.SourceRef.Name}) + err = reconcileSourceGitCmdRun(nil, []string{helmRelease.Spec.Chart.Spec.SourceRef.Name}) + case sourcev1.BucketKind: + err = reconcileSourceBucketCmdRun(nil, []string{helmRelease.Spec.Chart.Spec.SourceRef.Name}) } if err != nil { return err diff --git a/cmd/gotk/reconcile_kustomization.go b/cmd/gotk/reconcile_kustomization.go index 3dd5aa9b..07ff6a04 100644 --- a/cmd/gotk/reconcile_kustomization.go +++ b/cmd/gotk/reconcile_kustomization.go @@ -27,6 +27,7 @@ import ( kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1alpha1" consts "github.com/fluxcd/pkg/runtime" + sourcev1 "github.com/fluxcd/source-controller/api/v1alpha1" ) var reconcileKsCmd = &cobra.Command{ @@ -80,7 +81,12 @@ func reconcileKsCmdRun(cmd *cobra.Command, args []string) error { } if syncKsWithSource { - err := syncSourceGitCmdRun(nil, []string{kustomization.Spec.SourceRef.Name}) + switch kustomization.Spec.SourceRef.Kind { + case sourcev1.GitRepositoryKind: + err = reconcileSourceGitCmdRun(nil, []string{kustomization.Spec.SourceRef.Name}) + case sourcev1.BucketKind: + err = reconcileSourceBucketCmdRun(nil, []string{kustomization.Spec.SourceRef.Name}) + } if err != nil { return err } diff --git a/cmd/gotk/reconcile_source_bucket.go b/cmd/gotk/reconcile_source_bucket.go index fb4fbbbf..15b33e2a 100644 --- a/cmd/gotk/reconcile_source_bucket.go +++ b/cmd/gotk/reconcile_source_bucket.go @@ -38,14 +38,14 @@ var reconcileSourceBucketCmd = &cobra.Command{ Example: ` # Trigger a reconciliation for an existing source gotk reconcile source bucket podinfo `, - RunE: syncSourceBucketCmdRun, + RunE: reconcileSourceBucketCmdRun, } func init() { reconcileSourceCmd.AddCommand(reconcileSourceBucketCmd) } -func syncSourceBucketCmdRun(cmd *cobra.Command, args []string) error { +func reconcileSourceBucketCmdRun(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("source name is required") } diff --git a/cmd/gotk/reconcile_source_git.go b/cmd/gotk/reconcile_source_git.go index 934c6e1c..7f2af513 100644 --- a/cmd/gotk/reconcile_source_git.go +++ b/cmd/gotk/reconcile_source_git.go @@ -19,7 +19,6 @@ package main import ( "context" "fmt" - "time" "github.com/spf13/cobra" @@ -37,14 +36,14 @@ var reconcileSourceGitCmd = &cobra.Command{ Example: ` # Trigger a git pull for an existing source gotk reconcile source git podinfo `, - RunE: syncSourceGitCmdRun, + RunE: reconcileSourceGitCmdRun, } func init() { reconcileSourceCmd.AddCommand(reconcileSourceGitCmd) } -func syncSourceGitCmdRun(cmd *cobra.Command, args []string) error { +func reconcileSourceGitCmdRun(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("source name is required") } diff --git a/cmd/gotk/reconcile_source_helm.go b/cmd/gotk/reconcile_source_helm.go index 510da6f8..4e6fdac7 100644 --- a/cmd/gotk/reconcile_source_helm.go +++ b/cmd/gotk/reconcile_source_helm.go @@ -38,14 +38,14 @@ var reconcileSourceHelmCmd = &cobra.Command{ Example: ` # Trigger a reconciliation for an existing source gotk reconcile source helm podinfo `, - RunE: syncSourceHelmCmdRun, + RunE: reconcileSourceHelmCmdRun, } func init() { reconcileSourceCmd.AddCommand(reconcileSourceHelmCmd) } -func syncSourceHelmCmdRun(cmd *cobra.Command, args []string) error { +func reconcileSourceHelmCmdRun(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("source name is required") } diff --git a/docs/cmd/gotk_create_helmrelease.md b/docs/cmd/gotk_create_helmrelease.md index 09e9803a..052a2c30 100644 --- a/docs/cmd/gotk_create_helmrelease.md +++ b/docs/cmd/gotk_create_helmrelease.md @@ -26,6 +26,12 @@ gotk create helmrelease [name] [flags] --source=GitRepository/podinfo \ --chart=./charts/podinfo + # Create a HelmRelease with a chart from a Bucket source + gotk create hr podinfo \ + --interval=10m \ + --source=Bucket/podinfo \ + --chart=./charts/podinfo + # Create a HelmRelease with values from a local YAML file gotk create hr podinfo \ --source=HelmRepository/podinfo \ diff --git a/docs/cmd/gotk_create_kustomization.md b/docs/cmd/gotk_create_kustomization.md index 436cc329..9792283b 100644 --- a/docs/cmd/gotk_create_kustomization.md +++ b/docs/cmd/gotk_create_kustomization.md @@ -33,15 +33,11 @@ gotk create kustomization [name] [flags] --interval=5m \ --validation=client - # Create a Kustomization resource that runs under a service account - gotk create kustomization webapp \ - --source=webapp \ - --path="./deploy/overlays/staging" \ + # Create a Kustomization resource that references a Bucket + gotk create kustomization secrets \ + --source=Bucket/secrets \ --prune=true \ - --interval=5m \ - --validation=client \ - --sa-name=reconclier \ - --sa-namespace=staging + --interval=5m ``` @@ -58,7 +54,7 @@ gotk create kustomization [name] [flags] --prune enable garbage collection --sa-name string service account name --sa-namespace string service account namespace - --source string GitRepository name + --source string source that contains the Kubernetes manifests, format '/' where kind can be GitRepository or Bucket, if kind is not specified it defaults to GitRepository --validation string validate the manifests before applying them on the cluster, can be 'client' or 'server' ``` From d11fa476e11a29a8439dbbbe19acce65cfafb68e Mon Sep 17 00:00:00 2001 From: stefanprodan Date: Wed, 23 Sep 2020 18:19:33 +0300 Subject: [PATCH 2/2] Refactor object kind/name parsing --- cmd/gotk/create_helmrelease.go | 14 ++++++-------- cmd/gotk/create_kustomization.go | 24 +++++++++++------------- cmd/gotk/utils.go | 11 +++++++++++ docs/cmd/gotk_create_kustomization.md | 4 ++-- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/cmd/gotk/create_helmrelease.go b/cmd/gotk/create_helmrelease.go index d78278be..780c469b 100644 --- a/cmd/gotk/create_helmrelease.go +++ b/cmd/gotk/create_helmrelease.go @@ -20,7 +20,6 @@ import ( "context" "fmt" "io/ioutil" - "strings" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" @@ -119,14 +118,13 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { if hrSource == "" { return fmt.Errorf("source is required") } - hrSourceElements := strings.Split(hrSource, "/") - if len(hrSourceElements) != 2 { + sourceKind, sourceName := utils.parseObjectKindName(hrSource) + if sourceKind == "" { return fmt.Errorf("invalid source '%s', must be in format /", hrSource) } - hrSourceKind, hrSourceName := hrSourceElements[0], hrSourceElements[1] - if !utils.containsItemString(supportedHelmChartSourceKinds, hrSourceKind) { + if !utils.containsItemString(supportedHelmChartSourceKinds, sourceKind) { return fmt.Errorf("source kind %s is not supported, can be %v", - hrSourceKind, supportedHelmChartSourceKinds) + sourceKind, supportedHelmChartSourceKinds) } if hrChart == "" { return fmt.Errorf("chart name or path is required") @@ -159,8 +157,8 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { Chart: hrChart, Version: hrChartVersion, SourceRef: helmv2.CrossNamespaceObjectReference{ - Kind: hrSourceKind, - Name: hrSourceName, + Kind: sourceKind, + Name: sourceName, }, }, }, diff --git a/cmd/gotk/create_kustomization.go b/cmd/gotk/create_kustomization.go index c6e884e5..5dca097b 100644 --- a/cmd/gotk/create_kustomization.go +++ b/cmd/gotk/create_kustomization.go @@ -39,7 +39,7 @@ var createKsCmd = &cobra.Command{ Use: "kustomization [name]", Aliases: []string{"ks"}, Short: "Create or update a Kustomization resource", - Long: "The kustomization source create command generates a Kustomize resource for a given GitRepository source.", + Long: "The kustomization source create command generates a Kustomize resource for a given source.", Example: ` # Create a Kustomization resource from a source at a given path gotk create kustomization contour \ --source=contour \ @@ -85,7 +85,7 @@ var ( func init() { createKsCmd.Flags().StringVar(&ksSource, "source", "", - "source that contains the Kubernetes manifests, format '/' where kind can be GitRepository or Bucket, if kind is not specified it defaults to GitRepository") + "source that contains the Kubernetes manifests in the format '[/]', where kind can be GitRepository or Bucket, if kind is not specified it defaults to GitRepository") createKsCmd.Flags().StringVar(&ksPath, "path", "./", "path to the directory containing the Kustomization file") createKsCmd.Flags().BoolVar(&ksPrune, "prune", false, "enable garbage collection") createKsCmd.Flags().StringArrayVar(&ksHealthCheck, "health-check", nil, "workload to be included in the health assessment, in the format '/.'") @@ -109,15 +109,13 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("source is required") } - ksSourceKind := sourcev1.GitRepositoryKind - ksSourceName := ksSource - ksSourceElements := strings.Split(ksSource, "/") - if len(ksSourceElements) == 2 { - ksSourceKind, ksSourceName = ksSourceElements[0], ksSourceElements[1] - if !utils.containsItemString(supportedKustomizationSourceKinds, ksSourceKind) { - return fmt.Errorf("source kind %s is not supported, can be %v", - ksSourceKind, supportedKustomizationSourceKinds) - } + sourceKind, sourceName := utils.parseObjectKindName(ksSource) + if sourceKind == "" { + sourceKind = sourcev1.GitRepositoryKind + } + if !utils.containsItemString(supportedKustomizationSourceKinds, sourceKind) { + return fmt.Errorf("source kind %s is not supported, can be %v", + sourceKind, supportedKustomizationSourceKinds) } if ksPath == "" { @@ -150,8 +148,8 @@ func createKsCmdRun(cmd *cobra.Command, args []string) error { Path: ksPath, Prune: ksPrune, SourceRef: kustomizev1.CrossNamespaceSourceReference{ - Kind: ksSourceKind, - Name: ksSourceName, + Kind: sourceKind, + Name: sourceName, }, Suspend: false, Validation: ksValidation, diff --git a/cmd/gotk/utils.go b/cmd/gotk/utils.go index e1e7c752..17a5a386 100644 --- a/cmd/gotk/utils.go +++ b/cmd/gotk/utils.go @@ -180,6 +180,17 @@ func (*Utils) containsItemString(s []string, e string) bool { return false } +func (*Utils) parseObjectKindName(input string) (string, string) { + kind := "" + name := input + parts := strings.Split(input, "/") + if len(parts) == 2 { + kind, name = parts[0], parts[1] + } + + return kind, name +} + func (*Utils) makeDependsOn(deps []string) []dependency.CrossNamespaceDependencyReference { refs := []dependency.CrossNamespaceDependencyReference{} for _, dep := range deps { diff --git a/docs/cmd/gotk_create_kustomization.md b/docs/cmd/gotk_create_kustomization.md index 9792283b..b42eee1a 100644 --- a/docs/cmd/gotk_create_kustomization.md +++ b/docs/cmd/gotk_create_kustomization.md @@ -4,7 +4,7 @@ Create or update a Kustomization resource ### Synopsis -The kustomization source create command generates a Kustomize resource for a given GitRepository source. +The kustomization source create command generates a Kustomize resource for a given source. ``` gotk create kustomization [name] [flags] @@ -54,7 +54,7 @@ gotk create kustomization [name] [flags] --prune enable garbage collection --sa-name string service account name --sa-namespace string service account namespace - --source string source that contains the Kubernetes manifests, format '/' where kind can be GitRepository or Bucket, if kind is not specified it defaults to GitRepository + --source string source that contains the Kubernetes manifests in the format '[/]', where kind can be GitRepository or Bucket, if kind is not specified it defaults to GitRepository --validation string validate the manifests before applying them on the cluster, can be 'client' or 'server' ```