Skip to content

Commit eb3b81f

Browse files
JuHyung-SonAlexsJonesrenovate[bot]
authored
feat: add label selector (#1201)
* feat: fix the custom-analysis printing (#1195) Signed-off-by: Alex Jones <[email protected]> Signed-off-by: JuHyung-Son <[email protected]> * feat: add label selector Signed-off-by: JuHyung-Son <[email protected]> * feat: add label selector on analyzers Signed-off-by: JuHyung-Son <[email protected]> * chore(deps): pin goreleaser/goreleaser-action action to 286f3b1 (#1171) Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: JuHyung-Son <[email protected]> * fix(deps): update module buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go to v1.4.0-20240715142657-3785f0a44aae.2 (#1196) Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: JuHyung-Son <[email protected]> * chore(deps): update actions/upload-artifact digest to 0b2256b (#1175) Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: JuHyung-Son <[email protected]> * chore: update proto pkg version Signed-off-by: JuHyung-Son <[email protected]> * chore: fix typo Signed-off-by: JuHyung-Son <[email protected]> * feat: add label string to LabelSelector util func Signed-off-by: JuHyung-Son <[email protected]> * feat: add test using 2 label selector Signed-off-by: JuHyung-Son <[email protected]> --------- Signed-off-by: Alex Jones <[email protected]> Signed-off-by: JuHyung-Son <[email protected]> Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Signed-off-by: JuHyung Son <[email protected]> Co-authored-by: Alex Jones <[email protected]> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 parent 5176759 commit eb3b81f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1000
-28
lines changed

cmd/analyze/analyze.go

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var (
3333
language string
3434
nocache bool
3535
namespace string
36+
labelSelector string
3637
anonymize bool
3738
maxConcurrency int
3839
withDoc bool
@@ -55,6 +56,7 @@ var AnalyzeCmd = &cobra.Command{
5556
language,
5657
filters,
5758
namespace,
59+
labelSelector,
5860
nocache,
5961
explain,
6062
maxConcurrency,
@@ -142,4 +144,6 @@ func init() {
142144
AnalyzeCmd.Flags().BoolVarP(&customAnalysis, "custom-analysis", "z", false, "Enable custom analyzers")
143145
// add custom headers flag
144146
AnalyzeCmd.Flags().StringSliceVarP(&customHeaders, "custom-headers", "r", []string{}, "Custom Headers, <key>:<value> (e.g CustomHeaderKey:CustomHeaderValue AnotherHeader:AnotherValue)")
147+
// label selector flag
148+
AnalyzeCmd.Flags().StringVarP(&labelSelector, "selector", "L", "", "Label selector (label query) to filter on, supports '=', '==', and '!='. (e.g. -L key1=value1,key2=value2). Matching objects must satisfy all of the specified label constraints.")
145149
}

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ require github.com/adrg/xdg v0.4.0
2929

3030
require (
3131
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240406062209-1cc152efbf5c.1
32-
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.4.0-20240715142657-3785f0a44aae.2
33-
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240715142657-3785f0a44aae.2
32+
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240406062209-1cc152efbf5c.3
33+
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240717144446-c4efcc29ff16.2
3434
cloud.google.com/go/storage v1.40.0
3535
cloud.google.com/go/vertexai v0.7.1
3636
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0

go.sum

+12-4
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,20 @@ atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
88
atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
99
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240406062209-1cc152efbf5c.1 h1:0x36l6ETxg5YDlfFTxSR+4SpL0bwLezTCUfGdcPUN44=
1010
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240406062209-1cc152efbf5c.1/go.mod h1:/n44w/baTCuEmDgCBgSxQ2GEiO7N645eKxLKbygzW4s=
11+
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240717144446-c4efcc29ff16.2 h1:68+/5HyHF3WAm5PtNvRwuzSqTD/im9JlylgyneHCPVY=
12+
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc-ecosystem/gateway/v2 v2.20.0-20240717144446-c4efcc29ff16.2/go.mod h1:eYww1zlm6K5Tfwo3AfcVNMhnGJXR32t/PbZiPbvzv4s=
13+
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240406062209-1cc152efbf5c.3 h1:EiautHLlnNmBZdh1wFpmrSDvV4t8sucXGwV6vaE8Xuc=
1114
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240406062209-1cc152efbf5c.3/go.mod h1:4QVX5iWdNcwSFhpXXIXwVH7qT/g9LKvxiqa0SvYJ9hE=
12-
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.4.0-20240715142657-3785f0a44aae.2 h1:cUwK1ZqeW7HBL/kVxp16XHz7zXzVsuwXZQBKqAgh35k=
13-
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.4.0-20240715142657-3785f0a44aae.2/go.mod h1:/amuehNhXZEybzOmSYq4ghCe+4j9IoMaQldDOOPsPL4=
15+
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240717144446-c4efcc29ff16.3 h1:3HaNXtw/bEPWPXSqwLgEtBvqh39HLPYnFzG5UmZ00hs=
16+
buf.build/gen/go/k8sgpt-ai/k8sgpt/grpc/go v1.3.0-20240717144446-c4efcc29ff16.3/go.mod h1:2FnWdzuB/BRUpuEQ71s/EviXJvVzzlHv8BvTlFFYgmQ=
1417
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.0-20240406062209-1cc152efbf5c.1/go.mod h1:qFzoT6sNuRF9vPeDFmxd9KZ1YgU2vnnno5E5I0OUjOc=
18+
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.0-20240717144446-c4efcc29ff16.1/go.mod h1:qFzoT6sNuRF9vPeDFmxd9KZ1YgU2vnnno5E5I0OUjOc=
19+
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240406062209-1cc152efbf5c.1 h1:DLKuL/RwZg0bRweSS18Bi67GzKOW3F6YnVU0nZYXZBU=
1520
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240406062209-1cc152efbf5c.1/go.mod h1:qEarbrHjaZEQ5GeUH6XqSqqJMvtPwAGFpAc0nkSBzrQ=
16-
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240715142657-3785f0a44aae.2 h1:rH3TEq0JwQ0AzP3dGkPMwzrjOg3F+548ph7RgSvw2aQ=
17-
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240715142657-3785f0a44aae.2/go.mod h1:1wq1qVxvJkTEUQsF5/XjmhQYXYhbVoLSGhKnzS3ie54=
21+
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240717144446-c4efcc29ff16.1 h1:TJj+JSRc64sitUGL1XaCPY/OU090/5lNi4ABLG9jTSQ=
22+
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.1-20240717144446-c4efcc29ff16.1/go.mod h1:qEarbrHjaZEQ5GeUH6XqSqqJMvtPwAGFpAc0nkSBzrQ=
23+
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240717144446-c4efcc29ff16.2 h1:INIYy743CJ4MEZu+O4by7oeC/m+a/l4HBk79FshPGBI=
24+
buf.build/gen/go/k8sgpt-ai/k8sgpt/protocolbuffers/go v1.34.2-20240717144446-c4efcc29ff16.2/go.mod h1:1wq1qVxvJkTEUQsF5/XjmhQYXYhbVoLSGhKnzS3ie54=
1825
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
1926
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2027
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -3315,6 +3322,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
33153322
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
33163323
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
33173324
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3325+
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
33183326
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
33193327
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
33203328
helm.sh/helm/v3 v3.15.2 h1:/3XINUFinJOBjQplGnjw92eLGpgXXp1L8chWPkCkDuw=

pkg/analysis/analysis.go

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type Analysis struct {
4444
Results []common.Result
4545
Errors []string
4646
Namespace string
47+
LabelSelector string
4748
Cache cache.ICache
4849
Explain bool
4950
MaxConcurrency int
@@ -74,6 +75,7 @@ func NewAnalysis(
7475
language string,
7576
filters []string,
7677
namespace string,
78+
labelSelector string,
7779
noCache bool,
7880
explain bool,
7981
maxConcurrency int,
@@ -105,6 +107,7 @@ func NewAnalysis(
105107
Client: client,
106108
Language: language,
107109
Namespace: namespace,
110+
LabelSelector: labelSelector,
108111
Cache: cache,
109112
Explain: explain,
110113
MaxConcurrency: maxConcurrency,
@@ -200,6 +203,7 @@ func (a *Analysis) RunAnalysis() {
200203
Client: a.Client,
201204
Context: a.Context,
202205
Namespace: a.Namespace,
206+
LabelSelector: a.LabelSelector,
203207
AIClient: a.AIClient,
204208
OpenapiSchema: openapiSchema,
205209
}

pkg/analyzer/cronjob.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func (analyzer CronJobAnalyzer) Analyze(a common.Analyzer) ([]common.Result, err
4343
"analyzer_name": kind,
4444
})
4545

46-
cronJobList, err := a.Client.GetClient().BatchV1().CronJobs(a.Namespace).List(a.Context, v1.ListOptions{})
46+
cronJobList, err := a.Client.GetClient().BatchV1().CronJobs(a.Namespace).List(a.Context, v1.ListOptions{LabelSelector: a.LabelSelector})
4747
if err != nil {
4848
return nil, err
4949
}

pkg/analyzer/cronjob_test.go

+42
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,45 @@ func TestCronJobAnalyzer(t *testing.T) {
156156
require.Equal(t, expectations[i], result.Name)
157157
}
158158
}
159+
160+
func TestCronJobAnalyzerLabelSelectorFiltering(t *testing.T) {
161+
suspend := new(bool)
162+
*suspend = true
163+
164+
invalidStartingDeadline := new(int64)
165+
*invalidStartingDeadline = -7
166+
167+
validStartingDeadline := new(int64)
168+
*validStartingDeadline = 7
169+
170+
config := common.Analyzer{
171+
Client: &kubernetes.Client{
172+
Client: fake.NewSimpleClientset(
173+
&batchv1.CronJob{
174+
ObjectMeta: metav1.ObjectMeta{
175+
Name: "CJ1",
176+
Namespace: "default",
177+
Labels: map[string]string{
178+
"app": "cronjob",
179+
},
180+
},
181+
},
182+
&batchv1.CronJob{
183+
ObjectMeta: metav1.ObjectMeta{
184+
Name: "CJ2",
185+
Namespace: "default",
186+
},
187+
},
188+
),
189+
},
190+
Context: context.Background(),
191+
Namespace: "default",
192+
LabelSelector: "app=cronjob",
193+
}
194+
195+
cjAnalyzer := CronJobAnalyzer{}
196+
results, err := cjAnalyzer.Analyze(config)
197+
require.NoError(t, err)
198+
require.Equal(t, 1, len(results))
199+
require.Equal(t, "default/CJ1", results[0].Name)
200+
}

pkg/analyzer/deployment.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func (d DeploymentAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error)
4646
"analyzer_name": kind,
4747
})
4848

49-
deployments, err := a.Client.GetClient().AppsV1().Deployments(a.Namespace).List(context.Background(), v1.ListOptions{})
49+
deployments, err := a.Client.GetClient().AppsV1().Deployments(a.Namespace).List(context.Background(), v1.ListOptions{LabelSelector: a.LabelSelector})
5050
if err != nil {
5151
return nil, err
5252
}

pkg/analyzer/deployment_test.go

+52
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,55 @@ func TestDeploymentAnalyzerNamespaceFiltering(t *testing.T) {
151151
assert.Equal(t, analysisResults[0].Kind, "Deployment")
152152
assert.Equal(t, analysisResults[0].Name, "default/example")
153153
}
154+
155+
func TestDeploymentAnalyzerLabelSelectorFiltering(t *testing.T) {
156+
clientset := fake.NewSimpleClientset(
157+
&appsv1.Deployment{
158+
ObjectMeta: metav1.ObjectMeta{
159+
Name: "example",
160+
Namespace: "default",
161+
Labels: map[string]string{
162+
"app": "deployment",
163+
},
164+
},
165+
Spec: appsv1.DeploymentSpec{
166+
Replicas: func() *int32 { i := int32(3); return &i }(),
167+
Template: v1.PodTemplateSpec{
168+
Spec: v1.PodSpec{
169+
Containers: []v1.Container{},
170+
},
171+
},
172+
},
173+
},
174+
&appsv1.Deployment{
175+
ObjectMeta: metav1.ObjectMeta{
176+
Name: "example2",
177+
Namespace: "default",
178+
},
179+
Spec: appsv1.DeploymentSpec{
180+
Replicas: func() *int32 { i := int32(3); return &i }(),
181+
Template: v1.PodTemplateSpec{
182+
Spec: v1.PodSpec{
183+
Containers: []v1.Container{},
184+
},
185+
},
186+
},
187+
},
188+
)
189+
190+
config := common.Analyzer{
191+
Client: &kubernetes.Client{
192+
Client: clientset,
193+
},
194+
Context: context.Background(),
195+
Namespace: "default",
196+
LabelSelector: "app=deployment",
197+
}
198+
199+
deploymentAnalyzer := DeploymentAnalyzer{}
200+
analysisResults, err := deploymentAnalyzer.Analyze(config)
201+
if err != nil {
202+
t.Error(err)
203+
}
204+
assert.Equal(t, len(analysisResults), 1)
205+
}

pkg/analyzer/gateway.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ func (GatewayAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error) {
4141
if err != nil {
4242
return nil, err
4343
}
44-
if err := client.List(a.Context, gtwList, &ctrl.ListOptions{}); err != nil {
44+
45+
labelSelector := util.LabelStrToSelector(a.LabelSelector)
46+
if err := client.List(a.Context, gtwList, &ctrl.ListOptions{LabelSelector: labelSelector}); err != nil {
4547
return nil, err
4648
}
4749

pkg/analyzer/gateway_test.go

+74-4
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ func BuildGatewayClass(name string) gtwapi.GatewayClass {
2525
return GatewayClass
2626
}
2727

28-
func BuildGateway(className gtwapi.ObjectName, status metav1.ConditionStatus) gtwapi.Gateway {
28+
func BuildGateway(className gtwapi.ObjectName, status metav1.ConditionStatus, labels map[string]string) gtwapi.Gateway {
2929
Gateway := gtwapi.Gateway{}
3030
Gateway.Name = "foobar"
3131
Gateway.Namespace = "default"
32+
if labels != nil {
33+
Gateway.Labels = labels
34+
}
3235
Gateway.Spec.GatewayClassName = className
3336
Gateway.Spec.Listeners = []gtwapi.Listener{
3437
{
@@ -53,7 +56,7 @@ func TestGatewayAnalyzer(t *testing.T) {
5356
AcceptedStatus := metav1.ConditionTrue
5457
GatewayClass := BuildGatewayClass(string(ClassName))
5558

56-
Gateway := BuildGateway(ClassName, AcceptedStatus)
59+
Gateway := BuildGateway(ClassName, AcceptedStatus, nil)
5760
// Create a Gateway Analyzer instance with the fake client
5861
scheme := scheme.Scheme
5962

@@ -91,7 +94,7 @@ func TestGatewayAnalyzer(t *testing.T) {
9194
func TestMissingClassGatewayAnalyzer(t *testing.T) {
9295
ClassName := gtwapi.ObjectName("non-existed")
9396
AcceptedStatus := metav1.ConditionTrue
94-
Gateway := BuildGateway(ClassName, AcceptedStatus)
97+
Gateway := BuildGateway(ClassName, AcceptedStatus, nil)
9598

9699
// Create a Gateway Analyzer instance with the fake client
97100
scheme := scheme.Scheme
@@ -130,7 +133,7 @@ func TestStatusGatewayAnalyzer(t *testing.T) {
130133
AcceptedStatus := metav1.ConditionUnknown
131134
GatewayClass := BuildGatewayClass(string(ClassName))
132135

133-
Gateway := BuildGateway(ClassName, AcceptedStatus)
136+
Gateway := BuildGateway(ClassName, AcceptedStatus, nil)
134137

135138
// Create a Gateway Analyzer instance with the fake client
136139
scheme := scheme.Scheme
@@ -178,3 +181,70 @@ func TestStatusGatewayAnalyzer(t *testing.T) {
178181
t.Errorf("Expected message, <%v> , not found in Gateway's analysis results", want)
179182
}
180183
}
184+
185+
func TestGatewayAnalyzerLabelSelectorFiltering(t *testing.T) {
186+
ClassName := gtwapi.ObjectName("non-existed")
187+
AcceptedStatus := metav1.ConditionTrue
188+
189+
Gateway := BuildGateway(ClassName, AcceptedStatus, map[string]string{"app": "gateway"})
190+
scheme := scheme.Scheme
191+
err := gtwapi.Install(scheme)
192+
if err != nil {
193+
t.Error(err)
194+
}
195+
err = apiextensionsv1.AddToScheme(scheme)
196+
if err != nil {
197+
t.Error(err)
198+
}
199+
objects := []runtime.Object{
200+
&Gateway,
201+
}
202+
203+
fakeClient := fakeclient.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(objects...).Build()
204+
205+
analyzerInstance := GatewayAnalyzer{}
206+
// without label selector should return 1 result
207+
config := common.Analyzer{
208+
Client: &kubernetes.Client{
209+
CtrlClient: fakeClient,
210+
},
211+
Context: context.Background(),
212+
Namespace: "default",
213+
}
214+
analysisResults, err := analyzerInstance.Analyze(config)
215+
if err != nil {
216+
t.Error(err)
217+
}
218+
assert.Equal(t, len(analysisResults), 1)
219+
220+
// with label selector should return 1 result
221+
config = common.Analyzer{
222+
Client: &kubernetes.Client{
223+
CtrlClient: fakeClient,
224+
},
225+
Context: context.Background(),
226+
Namespace: "default",
227+
LabelSelector: "app=gateway",
228+
}
229+
analysisResults, err = analyzerInstance.Analyze(config)
230+
if err != nil {
231+
t.Error(err)
232+
}
233+
assert.Equal(t, len(analysisResults), 1)
234+
235+
// with wrong label selector should return 0 result
236+
config = common.Analyzer{
237+
Client: &kubernetes.Client{
238+
CtrlClient: fakeClient,
239+
},
240+
Context: context.Background(),
241+
Namespace: "default",
242+
LabelSelector: "app=wrong",
243+
}
244+
analysisResults, err = analyzerInstance.Analyze(config)
245+
if err != nil {
246+
t.Error(err)
247+
}
248+
assert.Equal(t, len(analysisResults), 0)
249+
250+
}

pkg/analyzer/gatewayclass.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ func (GatewayClassAnalyzer) Analyze(a common.Analyzer) ([]common.Result, error)
3939
if err != nil {
4040
return nil, err
4141
}
42-
if err := client.List(a.Context, gcList, &ctrl.ListOptions{}); err != nil {
42+
43+
labelSelector := util.LabelStrToSelector(a.LabelSelector)
44+
if err := client.List(a.Context, gcList, &ctrl.ListOptions{LabelSelector: labelSelector}); err != nil {
4345
return nil, err
4446
}
4547
var preAnalysis = map[string]common.PreAnalysis{}

0 commit comments

Comments
 (0)