diff --git a/cmd/flux/get.go b/cmd/flux/get.go index 51f5b698..54355317 100644 --- a/cmd/flux/get.go +++ b/cmd/flux/get.go @@ -66,6 +66,7 @@ type GetFlags struct { allNamespaces bool noHeader bool statusSelector string + labelSelector string watch bool } @@ -78,6 +79,8 @@ func init() { getCmd.PersistentFlags().BoolVarP(&getArgs.watch, "watch", "w", false, "After listing/getting the requested object, watch for changes.") getCmd.PersistentFlags().StringVar(&getArgs.statusSelector, "status-selector", "", "specify the status condition name and the desired state to filter the get result, e.g. ready=false") + getCmd.PersistentFlags().StringVarP(&getArgs.labelSelector, "label-selector", "l", "", + "filter objects by label selector") rootCmd.AddCommand(getCmd) } @@ -150,6 +153,21 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error { listOpts = append(listOpts, client.MatchingFields{"metadata.name": args[0]}) } + if getArgs.labelSelector != "" { + label, err := metav1.ParseToLabelSelector(getArgs.labelSelector) + if err != nil { + return fmt.Errorf("unable to parse label selector: %w", err) + } + + sel, err := metav1.LabelSelectorAsSelector(label) + if err != nil { + return err + } + listOpts = append(listOpts, client.MatchingLabelsSelector{ + Selector: sel, + }) + } + getAll := cmd.Use == "all" if getArgs.watch { diff --git a/cmd/flux/get_test.go b/cmd/flux/get_test.go new file mode 100644 index 00000000..62a1b725 --- /dev/null +++ b/cmd/flux/get_test.go @@ -0,0 +1,61 @@ +//go:build unit +// +build unit + +/* +Copyright 2023 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 Test_GetCmd(t *testing.T) { + tmpl := map[string]string{ + "fluxns": allocateNamespace("flux-system"), + } + testEnv.CreateObjectFile("./testdata/get/objects.yaml", tmpl, t) + + tests := []struct { + name string + args string + expected string + }{ + { + name: "no label selector", + expected: "testdata/get/get.golden", + }, + { + name: "equal label selector", + args: "-l sharding.fluxcd.io/key=shard1", + expected: "testdata/get/get_label_one.golden", + }, + { + name: "notin label selector", + args: `-l "sharding.fluxcd.io/key notin (shard1, shard2)"`, + expected: "testdata/get/get_label_two.golden", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := cmdTestCase{ + args: "get sources git " + tt.args + " -n " + tmpl["fluxns"], + assert: assertGoldenTemplateFile(tt.expected, nil), + } + + cmd.runTestCmd(t) + }) + } +} diff --git a/cmd/flux/testdata/get/get.golden b/cmd/flux/testdata/get/get.golden new file mode 100644 index 00000000..5d741ccc --- /dev/null +++ b/cmd/flux/testdata/get/get.golden @@ -0,0 +1,4 @@ +NAME REVISION SUSPENDED READY MESSAGE +podinfo main@sha1:696f056d False True Fetched revision: main@sha1:696f056d +podinfo-shard1 main@sha1:696f056d False True Fetched revision: main@sha1:696f056d +podinfo-shard2 main@sha1:696f056d False True Fetched revision: main@sha1:696f056d diff --git a/cmd/flux/testdata/get/get_label_one.golden b/cmd/flux/testdata/get/get_label_one.golden new file mode 100644 index 00000000..1adcb4ae --- /dev/null +++ b/cmd/flux/testdata/get/get_label_one.golden @@ -0,0 +1,2 @@ +NAME REVISION SUSPENDED READY MESSAGE +podinfo-shard1 main@sha1:696f056d False True Fetched revision: main@sha1:696f056d diff --git a/cmd/flux/testdata/get/get_label_two.golden b/cmd/flux/testdata/get/get_label_two.golden new file mode 100644 index 00000000..c001e63f --- /dev/null +++ b/cmd/flux/testdata/get/get_label_two.golden @@ -0,0 +1,2 @@ +NAME REVISION SUSPENDED READY MESSAGE +podinfo main@sha1:696f056d False True Fetched revision: main@sha1:696f056d diff --git a/cmd/flux/testdata/get/objects.yaml b/cmd/flux/testdata/get/objects.yaml new file mode 100644 index 00000000..42913c20 --- /dev/null +++ b/cmd/flux/testdata/get/objects.yaml @@ -0,0 +1,91 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .fluxns }} +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + labels: + kustomize.toolkit.fluxcd.io/name: flux-system + kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }} + name: podinfo + namespace: {{ .fluxns }} +spec: + ref: + branch: main + secretRef: + name: flux-system + url: ssh://git@github.com/example/repo + interval: 5m +status: + artifact: + lastUpdateTime: "2021-08-01T04:28:42Z" + revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f + path: "example" + url: "example" + conditions: + - lastTransitionTime: "2021-07-20T00:48:16Z" + message: 'Fetched revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f' + reason: GitOperationSucceed + status: "True" + type: Ready +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + labels: + kustomize.toolkit.fluxcd.io/name: flux-system + kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }} + sharding.fluxcd.io/key: shard1 + name: podinfo-shard1 + namespace: {{ .fluxns }} +spec: + ref: + branch: main + secretRef: + name: flux-system + url: ssh://git@github.com/example/repo + interval: 5m +status: + artifact: + lastUpdateTime: "2021-08-01T04:28:42Z" + revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f + path: "example" + url: "example" + conditions: + - lastTransitionTime: "2021-07-20T00:48:16Z" + message: 'Fetched revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f' + reason: GitOperationSucceed + status: "True" + type: Ready +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + labels: + kustomize.toolkit.fluxcd.io/name: flux-system + kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }} + sharding.fluxcd.io/key: shard2 + name: podinfo-shard2 + namespace: {{ .fluxns }} +spec: + ref: + branch: main + secretRef: + name: flux-system + url: ssh://git@github.com/example/repo + interval: 5m +status: + artifact: + lastUpdateTime: "2021-08-01T04:28:42Z" + revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f + path: "example" + url: "example" + conditions: + - lastTransitionTime: "2021-07-20T00:48:16Z" + message: 'Fetched revision: main@sha1:696f056df216eea4f9401adbee0ff744d4df390f' + reason: GitOperationSucceed + status: "True" + type: Ready