From f719d2bf767cd79628ab86c74e941647f0a0da05 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 16 Sep 2025 00:47:12 +0300 Subject: [PATCH 1/5] Use stdout when exporting objects Signed-off-by: Stefan Prodan --- cmd/flux/create_source_bucket.go | 7 ------- cmd/flux/create_source_git.go | 6 ------ cmd/flux/create_source_helm.go | 6 ------ cmd/flux/create_tenant.go | 19 ++++++++++--------- cmd/flux/export.go | 6 +++--- cmd/flux/install.go | 2 +- cmd/flux/main.go | 5 +++++ 7 files changed, 19 insertions(+), 32 deletions(-) diff --git a/cmd/flux/create_source_bucket.go b/cmd/flux/create_source_bucket.go index 70c023ce..43aa99d5 100644 --- a/cmd/flux/create_source_bucket.go +++ b/cmd/flux/create_source_bucket.go @@ -19,7 +19,6 @@ package main import ( "context" "fmt" - "os" "strings" "github.com/spf13/cobra" @@ -114,12 +113,6 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error { return err } - tmpDir, err := os.MkdirTemp("", name) - if err != nil { - return err - } - defer os.RemoveAll(tmpDir) - var ignorePaths *string if len(sourceBucketArgs.ignorePaths) > 0 { ignorePathsStr := strings.Join(sourceBucketArgs.ignorePaths, "\n") diff --git a/cmd/flux/create_source_git.go b/cmd/flux/create_source_git.go index fb76ae59..94a5b943 100644 --- a/cmd/flux/create_source_git.go +++ b/cmd/flux/create_source_git.go @@ -191,12 +191,6 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("specifying a CA file is not supported for Git over SSH") } - tmpDir, err := os.MkdirTemp("", name) - if err != nil { - return err - } - defer os.RemoveAll(tmpDir) - sourceLabels, err := parseLabels() if err != nil { return err diff --git a/cmd/flux/create_source_helm.go b/cmd/flux/create_source_helm.go index 55b18176..0934228b 100644 --- a/cmd/flux/create_source_helm.go +++ b/cmd/flux/create_source_helm.go @@ -114,12 +114,6 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error { return err } - tmpDir, err := os.MkdirTemp("", name) - if err != nil { - return err - } - defer os.RemoveAll(tmpDir) - if _, err := url.Parse(sourceHelmArgs.url); err != nil { return fmt.Errorf("url parse failed: %w", err) } diff --git a/cmd/flux/create_tenant.go b/cmd/flux/create_tenant.go index 442f0f73..f2c98c27 100644 --- a/cmd/flux/create_tenant.go +++ b/cmd/flux/create_tenant.go @@ -21,7 +21,6 @@ import ( "context" "fmt" - "github.com/fluxcd/flux2/v2/internal/utils" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -32,6 +31,8 @@ import ( "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" + + "github.com/fluxcd/flux2/v2/internal/utils" ) var createTenantCmd = &cobra.Command{ @@ -292,10 +293,10 @@ func exportTenant(namespace corev1.Namespace, account corev1.ServiceAccount, rol if err != nil { return err } - - rootCmd.Println("---") data = bytes.Replace(data, []byte("spec: {}\n"), []byte(""), 1) - rootCmd.Println(resourceToString(data)) + + printlnStdout("---") + printlnStdout(resourceToString(data)) account.TypeMeta = metav1.TypeMeta{ APIVersion: "v1", @@ -305,10 +306,10 @@ func exportTenant(namespace corev1.Namespace, account corev1.ServiceAccount, rol if err != nil { return err } - - rootCmd.Println("---") data = bytes.Replace(data, []byte("spec: {}\n"), []byte(""), 1) - rootCmd.Println(resourceToString(data)) + + printlnStdout("---") + printlnStdout(resourceToString(data)) roleBinding.TypeMeta = metav1.TypeMeta{ APIVersion: "rbac.authorization.k8s.io/v1", @@ -319,8 +320,8 @@ func exportTenant(namespace corev1.Namespace, account corev1.ServiceAccount, rol return err } - rootCmd.Println("---") - rootCmd.Println(resourceToString(data)) + printlnStdout("---") + printlnStdout(resourceToString(data)) return nil } diff --git a/cmd/flux/export.go b/cmd/flux/export.go index 3ac9e215..cfad9eb5 100644 --- a/cmd/flux/export.go +++ b/cmd/flux/export.go @@ -109,13 +109,13 @@ func (export exportCommand) run(cmd *cobra.Command, args []string) error { return nil } -func printExport(export interface{}) error { +func printExport(export any) error { data, err := yaml.Marshal(export) if err != nil { return err } - rootCmd.Println("---") - rootCmd.Println(resourceToString(data)) + printlnStdout("---") + printlnStdout(resourceToString(data)) return nil } diff --git a/cmd/flux/install.go b/cmd/flux/install.go index 9e1fecd4..a1f45ec5 100644 --- a/cmd/flux/install.go +++ b/cmd/flux/install.go @@ -246,7 +246,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error { return fmt.Errorf("install failed: %w", err) } - fmt.Fprintln(os.Stderr, applyOutput) + rootCmd.Println(applyOutput) if opts.ImagePullSecret != "" && opts.RegistryCredential != "" { logger.Actionf("generating image pull secret %s", opts.ImagePullSecret) diff --git a/cmd/flux/main.go b/cmd/flux/main.go index 1226a347..b6627caa 100644 --- a/cmd/flux/main.go +++ b/cmd/flux/main.go @@ -247,3 +247,8 @@ While we try our best to not introduce breaking changes, they may occur when we adapt to new features and/or find better ways to facilitate what it does.` return fmt.Sprintf("%s\n\n%s", strings.TrimSpace(desc), previewNote) } + +// printlnStdout prints the given text to stdout with a newline. +func printlnStdout(txt string) { + _, _ = rootCmd.OutOrStdout().Write([]byte(txt + "\n")) +} From c416671ec4b12db0bb70cbd38cb9c8b564d4a801 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 16 Sep 2025 00:57:49 +0300 Subject: [PATCH 2/5] Add `export artifact generator` command Signed-off-by: Stefan Prodan --- cmd/flux/artifact.go | 57 +++++++++++++++++++++ cmd/flux/export_artifact.go | 31 ++++++++++++ cmd/flux/export_artifact_generator.go | 72 +++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 + internal/utils/utils.go | 2 + 6 files changed, 165 insertions(+) create mode 100644 cmd/flux/artifact.go create mode 100644 cmd/flux/export_artifact.go create mode 100644 cmd/flux/export_artifact_generator.go diff --git a/cmd/flux/artifact.go b/cmd/flux/artifact.go new file mode 100644 index 00000000..a4ab2e9f --- /dev/null +++ b/cmd/flux/artifact.go @@ -0,0 +1,57 @@ +/* +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. +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 ( + "sigs.k8s.io/controller-runtime/pkg/client" + + swapi "github.com/fluxcd/source-watcher/api/v2/v1beta1" +) + +// swapi.ArtifactGenerator + +var artifactGeneratorType = apiType{ + kind: swapi.ArtifactGeneratorKind, + humanKind: "artifactgenerator", + groupVersion: swapi.GroupVersion, +} + +type artifactGeneratorAdapter struct { + *swapi.ArtifactGenerator +} + +func (h artifactGeneratorAdapter) asClientObject() client.Object { + return h.ArtifactGenerator +} + +func (h artifactGeneratorAdapter) deepCopyClientObject() client.Object { + return h.ArtifactGenerator.DeepCopy() +} + +// swapi.ArtifactGeneratorList + +type artifactGeneratorListAdapter struct { + *swapi.ArtifactGeneratorList +} + +func (h artifactGeneratorListAdapter) asClientList() client.ObjectList { + return h.ArtifactGeneratorList +} + +func (h artifactGeneratorListAdapter) len() int { + return len(h.ArtifactGeneratorList.Items) +} diff --git a/cmd/flux/export_artifact.go b/cmd/flux/export_artifact.go new file mode 100644 index 00000000..b3917b6e --- /dev/null +++ b/cmd/flux/export_artifact.go @@ -0,0 +1,31 @@ +/* +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. +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 ( + "github.com/spf13/cobra" +) + +var exportArtifactCmd = &cobra.Command{ + Use: "artifact", + Short: "Export artifact objects", + Long: `The export artifact sub-commands export artifacts objects in YAML format.`, +} + +func init() { + exportCmd.AddCommand(exportArtifactCmd) +} diff --git a/cmd/flux/export_artifact_generator.go b/cmd/flux/export_artifact_generator.go new file mode 100644 index 00000000..4f3ae90c --- /dev/null +++ b/cmd/flux/export_artifact_generator.go @@ -0,0 +1,72 @@ +/* +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. +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 ( + "github.com/spf13/cobra" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + swapi "github.com/fluxcd/source-watcher/api/v2/v1beta1" +) + +var exportArtifactGeneratorCmd = &cobra.Command{ + Use: "generator [name]", + Short: "Export ArtifactGenerator resources in YAML format", + Long: "The export artifact generator command exports one or all ArtifactGenerator resources in YAML format.", + Example: ` # Export all ArtifactGenerator resources + flux export artifact generator --all > artifact-generators.yaml + + # Export a specific generator + flux export artifact generator my-generator > my-generator.yaml`, + ValidArgsFunction: resourceNamesCompletionFunc(swapi.GroupVersion.WithKind(swapi.ArtifactGeneratorKind)), + RunE: exportCommand{ + object: artifactGeneratorAdapter{&swapi.ArtifactGenerator{}}, + list: artifactGeneratorListAdapter{&swapi.ArtifactGeneratorList{}}, + }.run, +} + +func init() { + exportArtifactCmd.AddCommand(exportArtifactGeneratorCmd) +} + +// Export returns an ArtifactGenerator value which has +// extraneous information stripped out. +func exportArtifactGenerator(item *swapi.ArtifactGenerator) interface{} { + gvk := swapi.GroupVersion.WithKind(swapi.ArtifactGeneratorKind) + export := swapi.ArtifactGenerator{ + TypeMeta: metav1.TypeMeta{ + Kind: gvk.Kind, + APIVersion: gvk.GroupVersion().String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: item.Name, + Namespace: item.Namespace, + Labels: item.Labels, + Annotations: item.Annotations, + }, + Spec: item.Spec, + } + return export +} + +func (ex artifactGeneratorAdapter) export() interface{} { + return exportArtifactGenerator(ex.ArtifactGenerator) +} + +func (ex artifactGeneratorListAdapter) exportItem(i int) interface{} { + return exportArtifactGenerator(&ex.ArtifactGeneratorList.Items[i]) +} diff --git a/go.mod b/go.mod index 8a20a5c1..6c85ccaa 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,7 @@ require ( github.com/fluxcd/pkg/tar v0.14.0 github.com/fluxcd/pkg/version v0.10.0 github.com/fluxcd/source-controller/api v1.7.0 + github.com/fluxcd/source-watcher/api/v2 v2.0.0 github.com/go-git/go-git/v5 v5.16.2 github.com/go-logr/logr v1.4.3 github.com/gonvenience/bunt v1.4.2 diff --git a/go.sum b/go.sum index 568c183e..afb9874c 100644 --- a/go.sum +++ b/go.sum @@ -224,6 +224,8 @@ github.com/fluxcd/pkg/version v0.10.0 h1:WETlCRbfbocsDItkCCeh/4x4zQkZ5i/lUe7P7Va github.com/fluxcd/pkg/version v0.10.0/go.mod h1:dgmjEq4ykvBnqK1oVXM+hcXx3kAY/b4uZDYUn8XnHjk= github.com/fluxcd/source-controller/api v1.7.0 h1:y6vjvbkIN4JzianhmaJqujeghVpvQn3gcsVW/f1xMeA= github.com/fluxcd/source-controller/api v1.7.0/go.mod h1:UOIEs9AACxPW7fQFqGWw1/FN2QqYDLG6WkvPIyscHkw= +github.com/fluxcd/source-watcher/api/v2 v2.0.0 h1:7SBFX6fnnt/OrU17HkLkwuNXc+1GC2AbVS32cfxSFa0= +github.com/fluxcd/source-watcher/api/v2 v2.0.0/go.mod h1:w1Z6yxPqjerwwvh4ljcSGHkRMA5HmFEdu8EmhiQfWKs= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= diff --git a/internal/utils/utils.go b/internal/utils/utils.go index ce0040b9..67a6aa35 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -51,6 +51,7 @@ import ( runclient "github.com/fluxcd/pkg/runtime/client" "github.com/fluxcd/pkg/version" sourcev1 "github.com/fluxcd/source-controller/api/v1" + swapi "github.com/fluxcd/source-watcher/api/v2/v1beta1" "github.com/fluxcd/flux2/v2/pkg/manifestgen/install" ) @@ -134,6 +135,7 @@ func NewScheme() *apiruntime.Scheme { _ = notificationv1b3.AddToScheme(scheme) _ = imagereflectv1.AddToScheme(scheme) _ = imageautov1.AddToScheme(scheme) + _ = swapi.AddToScheme(scheme) return scheme } From 5556a5cc9a0506a19db426d5d783c8063dafe498 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 16 Sep 2025 01:10:15 +0300 Subject: [PATCH 3/5] Add `get artifact generator` command Signed-off-by: Stefan Prodan --- cmd/flux/get_artifact.go | 32 ++++++++++ cmd/flux/get_artifact_generator.go | 93 ++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 cmd/flux/get_artifact.go create mode 100644 cmd/flux/get_artifact_generator.go diff --git a/cmd/flux/get_artifact.go b/cmd/flux/get_artifact.go new file mode 100644 index 00000000..03ddd81a --- /dev/null +++ b/cmd/flux/get_artifact.go @@ -0,0 +1,32 @@ +/* +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. +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 ( + "github.com/spf13/cobra" +) + +var getArtifactCmd = &cobra.Command{ + Use: "artifacts", + Aliases: []string{"artifact"}, + Short: "Get artifact object status", + Long: `The get artifact sub-commands print the status of artifact objects.`, +} + +func init() { + getCmd.AddCommand(getArtifactCmd) +} diff --git a/cmd/flux/get_artifact_generator.go b/cmd/flux/get_artifact_generator.go new file mode 100644 index 00000000..0a336cbb --- /dev/null +++ b/cmd/flux/get_artifact_generator.go @@ -0,0 +1,93 @@ +/* +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. +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 ( + "fmt" + "strconv" + + "github.com/spf13/cobra" + "golang.org/x/text/cases" + "golang.org/x/text/language" + "k8s.io/apimachinery/pkg/runtime" + + swapi "github.com/fluxcd/source-watcher/api/v2/v1beta1" +) + +var getArtifactGeneratorCmd = &cobra.Command{ + Use: "generators", + Aliases: []string{"generator"}, + Short: "Get artifact generator statuses", + Long: `The get artifact generator command prints the statuses of the resources.`, + Example: ` # List all ArtifactGenerators and their status + flux get artifact generators`, + ValidArgsFunction: resourceNamesCompletionFunc(swapi.GroupVersion.WithKind(swapi.ArtifactGeneratorKind)), + RunE: func(cmd *cobra.Command, args []string) error { + get := getCommand{ + apiType: receiverType, + list: artifactGeneratorListAdapter{&swapi.ArtifactGeneratorList{}}, + funcMap: make(typeMap), + } + + err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) { + o, ok := obj.(*swapi.ArtifactGenerator) + if !ok { + return nil, fmt.Errorf("impossible to cast type %#v generator", obj) + } + + sink := artifactGeneratorListAdapter{&swapi.ArtifactGeneratorList{ + Items: []swapi.ArtifactGenerator{ + *o, + }}} + return sink, nil + }) + + if err != nil { + return err + } + + if err := get.run(cmd, args); err != nil { + return err + } + + return nil + }, +} + +func init() { + getArtifactCmd.AddCommand(getArtifactGeneratorCmd) +} + +func (s artifactGeneratorListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string { + item := s.Items[i] + status, msg := statusAndMessage(item.Status.Conditions) + return append(nameColumns(&item, includeNamespace, includeKind), + cases.Title(language.English).String(strconv.FormatBool(item.IsDisabled())), status, msg) +} + +func (s artifactGeneratorListAdapter) headers(includeNamespace bool) []string { + headers := []string{"Name", "Suspended", "Ready", "Message"} + if includeNamespace { + return append(namespaceHeader, headers...) + } + return headers +} + +func (s artifactGeneratorListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool { + item := s.Items[i] + return statusMatches(conditionType, conditionStatus, item.Status.Conditions) +} From 698a68424f19509e4edc7ab5a797c882998dc3aa Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 16 Sep 2025 10:09:37 +0300 Subject: [PATCH 4/5] Add `tree artifact generator` command Signed-off-by: Stefan Prodan --- cmd/flux/tree_artifact.go | 31 ++++++++ cmd/flux/tree_artifact_generator.go | 115 ++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 cmd/flux/tree_artifact.go create mode 100644 cmd/flux/tree_artifact_generator.go diff --git a/cmd/flux/tree_artifact.go b/cmd/flux/tree_artifact.go new file mode 100644 index 00000000..a1a4b05f --- /dev/null +++ b/cmd/flux/tree_artifact.go @@ -0,0 +1,31 @@ +/* +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. +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 ( + "github.com/spf13/cobra" +) + +var treeArtifactCmd = &cobra.Command{ + Use: "artifact", + Short: "Print artifact objects reconciled by Flux", + Long: `The tree artifact sub-commands print a list of artifact objects.`, +} + +func init() { + treeCmd.AddCommand(treeArtifactCmd) +} diff --git a/cmd/flux/tree_artifact_generator.go b/cmd/flux/tree_artifact_generator.go new file mode 100644 index 00000000..0a87c4f4 --- /dev/null +++ b/cmd/flux/tree_artifact_generator.go @@ -0,0 +1,115 @@ +/* +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. +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 ( + "context" + "encoding/json" + "fmt" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/yaml" + + "github.com/fluxcd/cli-utils/pkg/object" + sourcev1 "github.com/fluxcd/source-controller/api/v1" + swapi "github.com/fluxcd/source-watcher/api/v2/v1beta1" + + "github.com/fluxcd/flux2/v2/internal/tree" + "github.com/fluxcd/flux2/v2/internal/utils" +) + +var treeArtifactGeneratorCmd = &cobra.Command{ + Use: "generator [name]", + Short: "Print the inventory of an ArtifactGenerator", + Long: withPreviewNote(`The tree command prints the ExternalArtifact list managed by an ArtifactGenerator.'`), + Example: ` # Print the ExternalArtifacts managed by an ArtifactGenerator + flux tree artifact generator my-generator`, + RunE: treeArtifactGeneratorCmdRun, + Args: cobra.ExactArgs(1), + ValidArgsFunction: resourceNamesCompletionFunc(swapi.GroupVersion.WithKind(swapi.ArtifactGeneratorKind)), +} + +type TreeArtifactGeneratorFlags struct { + output string +} + +var treeArtifactGeneratorArgs TreeArtifactGeneratorFlags + +func init() { + treeArtifactGeneratorCmd.Flags().StringVarP(&treeArtifactGeneratorArgs.output, "output", "o", "", + "the format in which the tree should be printed. can be 'json' or 'yaml'") + treeArtifactCmd.AddCommand(treeArtifactGeneratorCmd) +} + +func treeArtifactGeneratorCmdRun(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("generator name is required") + } + name := args[0] + + ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) + defer cancel() + + kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions) + if err != nil { + return err + } + + ag := &swapi.ArtifactGenerator{} + err = kubeClient.Get(ctx, client.ObjectKey{ + Namespace: *kubeconfigArgs.Namespace, + Name: name, + }, ag) + if err != nil { + return err + } + + kTree := tree.New(object.ObjMetadata{ + Namespace: ag.Namespace, + Name: ag.Name, + GroupKind: schema.GroupKind{Group: swapi.GroupVersion.Group, Kind: swapi.ArtifactGeneratorKind}, + }) + + for _, ea := range ag.Status.Inventory { + kTree.Add(object.ObjMetadata{ + Namespace: ea.Namespace, + Name: ea.Name, + GroupKind: schema.GroupKind{Group: sourcev1.GroupVersion.Group, Kind: sourcev1.ExternalArtifactKind}, + }) + } + + switch treeArtifactGeneratorArgs.output { + case "json": + data, err := json.MarshalIndent(kTree, "", " ") + if err != nil { + return err + } + rootCmd.Println(string(data)) + case "yaml": + data, err := yaml.Marshal(kTree) + if err != nil { + return err + } + rootCmd.Println(string(data)) + default: + rootCmd.Println(kTree.Print()) + } + + return nil +} From a317f7c4458b5d8f48fee19c129a10b8db756c20 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Tue, 16 Sep 2025 11:17:27 +0300 Subject: [PATCH 5/5] Add support for `events --for ArtifactGenerator/` Signed-off-by: Stefan Prodan --- cmd/flux/events.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/flux/events.go b/cmd/flux/events.go index 04ee62b6..306deb09 100644 --- a/cmd/flux/events.go +++ b/cmd/flux/events.go @@ -20,7 +20,6 @@ package main import ( "context" "fmt" - "os" "sort" "strings" "time" @@ -46,6 +45,7 @@ import ( notificationv1 "github.com/fluxcd/notification-controller/api/v1" notificationv1b3 "github.com/fluxcd/notification-controller/api/v1beta3" sourcev1 "github.com/fluxcd/source-controller/api/v1" + swapi "github.com/fluxcd/source-watcher/api/v2/v1beta1" "github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/pkg/printers" @@ -251,7 +251,7 @@ func eventsCmdWatchRun(ctx context.Context, kubeclient client.WithWatch, listOpt hdr = getHeaders(showNs) firstIteration = false } - return printers.TablePrinter(hdr).Print(os.Stdout, [][]string{rows}) + return printers.TablePrinter(hdr).Print(rootCmd.OutOrStdout(), [][]string{rows}) } for _, refOpts := range refListOpts { @@ -455,6 +455,7 @@ var fluxKindMap = refMap{ sourcev1.HelmRepositoryKind: {gvk: sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)}, autov1.ImageUpdateAutomationKind: {gvk: autov1.GroupVersion.WithKind(autov1.ImageUpdateAutomationKind)}, imagev1.ImageRepositoryKind: {gvk: imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)}, + swapi.ArtifactGeneratorKind: {gvk: swapi.GroupVersion.WithKind(swapi.ArtifactGeneratorKind)}, } func ignoreEvent(e corev1.Event) bool {