From 3542d61afd315c0aee04cfaba1e17ec53afb7e28 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Mon, 15 Sep 2025 21:23:09 +0300 Subject: [PATCH] Add source-watcher to the `install` and `bootstrap` commands Signed-off-by: Stefan Prodan --- cmd/flux/bootstrap.go | 2 +- cmd/flux/install.go | 22 ++++++---- cmd/flux/install_test.go | 54 ++++++++++++++++++++++++- cmd/flux/main_test.go | 1 + pkg/manifestgen/install/install_test.go | 2 +- pkg/manifestgen/install/options.go | 2 +- pkg/manifestgen/install/templates.go | 14 ++++++- 7 files changed, 83 insertions(+), 14 deletions(-) diff --git a/cmd/flux/bootstrap.go b/cmd/flux/bootstrap.go index d23540e9..e7dbaf4e 100644 --- a/cmd/flux/bootstrap.go +++ b/cmd/flux/bootstrap.go @@ -97,7 +97,7 @@ func init() { bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.defaultComponents, "components", rootArgs.defaults.Components, "list of components, accepts comma-separated values") bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.extraComponents, "components-extra", nil, - "list of components in addition to those supplied or defaulted, accepts values such as 'image-reflector-controller,image-automation-controller'") + "list of components in addition to those supplied or defaulted, accepts values such as 'image-reflector-controller,image-automation-controller,source-watcher'") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.registry, "registry", "ghcr.io/fluxcd", "container registry where the Flux controller images are published") diff --git a/cmd/flux/install.go b/cmd/flux/install.go index 21f4e6cb..9e1fecd4 100644 --- a/cmd/flux/install.go +++ b/cmd/flux/install.go @@ -83,7 +83,7 @@ type installFlags struct { force bool } -var installArgs = NewInstallFlags() +var installArgs = newInstallFlags() func init() { installCmd.Flags().BoolVar(&installArgs.export, "export", false, @@ -93,7 +93,7 @@ func init() { installCmd.Flags().StringSliceVar(&installArgs.defaultComponents, "components", rootArgs.defaults.Components, "list of components, accepts comma-separated values") installCmd.Flags().StringSliceVar(&installArgs.extraComponents, "components-extra", nil, - "list of components in addition to those supplied or defaulted, accepts values such as 'image-reflector-controller,image-automation-controller'") + "list of components in addition to those supplied or defaulted, accepts values such as 'image-reflector-controller,image-automation-controller,source-watcher'") installCmd.Flags().StringVar(&installArgs.manifestsPath, "manifests", "", "path to the manifest directory") installCmd.Flags().StringVar(&installArgs.registry, "registry", rootArgs.defaults.Registry, "container registry where the toolkit images are published") @@ -115,9 +115,14 @@ func init() { rootCmd.AddCommand(installCmd) } -func NewInstallFlags() installFlags { +func newInstallFlags() installFlags { return installFlags{ - logLevel: flags.LogLevel(rootArgs.defaults.LogLevel), + logLevel: flags.LogLevel(rootArgs.defaults.LogLevel), + defaultComponents: rootArgs.defaults.Components, + registry: rootArgs.defaults.Registry, + watchAllNamespaces: rootArgs.defaults.WatchAllNamespaces, + networkPolicy: rootArgs.defaults.NetworkPolicy, + clusterDomain: rootArgs.defaults.ClusterDomain, } } @@ -195,10 +200,13 @@ func installCmdRun(cmd *cobra.Command, args []string) error { } if installArgs.export { - fmt.Print(manifest.Content) - return nil + _, err = rootCmd.OutOrStdout().Write([]byte(manifest.Content)) + return err } else if rootArgs.verbose { - fmt.Print(manifest.Content) + _, err = rootCmd.OutOrStdout().Write([]byte(manifest.Content)) + if err != nil { + return err + } } logger.Successf("manifests build completed") diff --git a/cmd/flux/install_test.go b/cmd/flux/install_test.go index 161a3d36..2406fc6d 100644 --- a/cmd/flux/install_test.go +++ b/cmd/flux/install_test.go @@ -1,5 +1,5 @@ /* -Copyright 2022 The Flux authors +Copyright 2025 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. @@ -16,7 +16,17 @@ limitations under the License. package main -import "testing" +import ( + "strings" + "testing" + + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + + ssautil "github.com/fluxcd/pkg/ssa/utils" + + "github.com/fluxcd/flux2/v2/pkg/manifestgen/install" +) func TestInstall(t *testing.T) { // The pointer to kubeconfigArgs.Namespace is shared across @@ -59,3 +69,43 @@ func TestInstall(t *testing.T) { }) } } + +func TestInstall_ComponentsExtra(t *testing.T) { + g := NewWithT(t) + command := "install --export --components-extra=" + + strings.Join(install.MakeDefaultOptions().ComponentsExtra, ",") + + output, err := executeCommand(command) + g.Expect(err).NotTo(HaveOccurred()) + + manifests, err := ssautil.ReadObjects(strings.NewReader(output)) + g.Expect(err).NotTo(HaveOccurred()) + + foundImageAutomation := false + foundImageReflector := false + foundSourceWatcher := false + foundExternalArtifact := false + for _, obj := range manifests { + if obj.GetKind() == "Deployment" && obj.GetName() == "image-automation-controller" { + foundImageAutomation = true + } + if obj.GetKind() == "Deployment" && obj.GetName() == "image-reflector-controller" { + foundImageReflector = true + } + if obj.GetKind() == "Deployment" && obj.GetName() == "source-watcher" { + foundSourceWatcher = true + } + if obj.GetKind() == "Deployment" && + (obj.GetName() == "kustomize-controller" || obj.GetName() == "helm-controller") { + containers, _, _ := unstructured.NestedSlice(obj.Object, "spec", "template", "spec", "containers") + g.Expect(containers).ToNot(BeEmpty()) + args, _, _ := unstructured.NestedSlice(containers[0].(map[string]any), "args") + g.Expect(args).To(ContainElement("--feature-gates=ExternalArtifact=true")) + foundExternalArtifact = true + } + } + g.Expect(foundImageAutomation).To(BeTrue(), "image-automation-controller deployment not found") + g.Expect(foundImageReflector).To(BeTrue(), "image-reflector-controller deployment not found") + g.Expect(foundSourceWatcher).To(BeTrue(), "source-watcher deployment not found") + g.Expect(foundExternalArtifact).To(BeTrue(), "ExternalArtifact feature gate not found") +} diff --git a/cmd/flux/main_test.go b/cmd/flux/main_test.go index 30673b1f..a3a8c18c 100644 --- a/cmd/flux/main_test.go +++ b/cmd/flux/main_test.go @@ -447,6 +447,7 @@ func resetCmdArgs() { imagePolicyArgs = imagePolicyFlags{} imageRepoArgs = imageRepoFlags{} imageUpdateArgs = imageUpdateFlags{} + installArgs = newInstallFlags() kustomizationArgs = NewKustomizationFlags() receiverArgs = receiverFlags{} resumeArgs = ResumeFlags{} diff --git a/pkg/manifestgen/install/install_test.go b/pkg/manifestgen/install/install_test.go index d9dc7789..7ca8457b 100644 --- a/pkg/manifestgen/install/install_test.go +++ b/pkg/manifestgen/install/install_test.go @@ -46,5 +46,5 @@ func TestGenerate(t *testing.T) { t.Errorf("Generation warning '%s' not found", warning) } - fmt.Println(output) + t.Log(output) } diff --git a/pkg/manifestgen/install/options.go b/pkg/manifestgen/install/options.go index 6b848eae..51ff6ac0 100644 --- a/pkg/manifestgen/install/options.go +++ b/pkg/manifestgen/install/options.go @@ -44,7 +44,7 @@ func MakeDefaultOptions() Options { Version: "latest", Namespace: "flux-system", Components: []string{"source-controller", "kustomize-controller", "helm-controller", "notification-controller"}, - ComponentsExtra: []string{"image-reflector-controller", "image-automation-controller"}, + ComponentsExtra: []string{"image-reflector-controller", "image-automation-controller", "source-watcher"}, EventsAddr: "", Registry: "ghcr.io/fluxcd", RegistryCredential: "", diff --git a/pkg/manifestgen/install/templates.go b/pkg/manifestgen/install/templates.go index ec9209f0..d531d1f2 100644 --- a/pkg/manifestgen/install/templates.go +++ b/pkg/manifestgen/install/templates.go @@ -65,7 +65,7 @@ patches: - op: replace path: /spec/template/spec/containers/0/args/1 value: --log-level={{$logLevel}} -{{- else if eq $component "source-controller" }} +{{- else if or (eq $component "source-controller") (eq $component "source-watcher") }} - target: group: apps version: v1 @@ -102,7 +102,17 @@ patches: value: --log-level={{$logLevel}} {{- end }} {{- end }} - +{{- range $i, $component := .Components }} +{{- if eq $component "source-watcher" }} +- target: + kind: Deployment + name: "(kustomize-controller|helm-controller)" + patch: |- + - op: add + path: /spec/template/spec/containers/0/args/- + value: --feature-gates=ExternalArtifact=true +{{- end }} +{{- end }} {{- if $registry }} images: {{- range $i, $component := .Components }}