Skip to content

Commit 3162d4e

Browse files
authored
feat(googlecloudk8scommon): default kind filter to all kinds except leases (#975)
1 parent 7a94157 commit 3162d4e

3 files changed

Lines changed: 196 additions & 11 deletions

File tree

pkg/task/inspection/googlecloudk8scommon/impl/inputkindfilter_task.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,37 @@ import (
2525
googlecloudk8scommon_contract "github.com/GoogleCloudPlatform/khi/pkg/task/inspection/googlecloudk8scommon/contract"
2626
)
2727

28-
var inputKindNameAliasMap gcpqueryutil.SetFilterAliasToItemsMap = map[string][]string{
29-
"default": strings.Split("pods replicasets daemonsets nodes deployments namespaces statefulsets services servicenetworkendpointgroups ingresses poddisruptionbudgets jobs cronjobs endpointslices persistentvolumes persistentvolumeclaims storageclasses horizontalpodautoscalers verticalpodautoscalers multidimpodautoscalers", " "),
28+
var inputKindsAliasMap gcpqueryutil.SetFilterAliasToItemsMap = map[string][]string{
29+
"legacy_default": strings.Split("pods replicasets daemonsets nodes deployments namespaces statefulsets services servicenetworkendpointgroups ingresses poddisruptionbudgets jobs cronjobs endpointslices persistentvolumes persistentvolumeclaims storageclasses horizontalpodautoscalers verticalpodautoscalers multidimpodautoscalers", " "),
3030
}
3131

3232
// InputKindFilterTask is a form task for inputting the kind filter.
3333
var InputKindFilterTask = formtask.NewSetFormTaskBuilder(googlecloudk8scommon_contract.InputKindFilterTaskID, googlecloudcommon_contract.PriorityForK8sResourceFilterGroup+5000, "Kind").
34-
WithDefaultValueConstant([]string{"@default"}, true).
35-
WithDescription("The kinds of resources to gather logs. `@default` is a alias of set of kinds that frequently queried. Specify `@any` to query every kinds of resources").
34+
WithDefaultValueConstant([]string{"@any", "-leases"}, true).
35+
WithDescription("The kinds of resources to gather logs. Specify `@any` to query all kinds of resources, or prefix with `-` to exclude specific kinds (e.g., `-leases`). `@legacy_default` matches a set of kinds frequently queried in legacy KHI versions.").
3636
WithAllowAddAll(false).
3737
WithAllowRemoveAll(false).
3838
WithAllowCustomValue(true).
3939
WithOptionsFunc(func(ctx context.Context, previousValues []string) ([]inspectionmetadata.SetParameterFormFieldOptionItem, error) {
40-
result := []inspectionmetadata.SetParameterFormFieldOptionItem{}
41-
result = append(result, inspectionmetadata.SetParameterFormFieldOptionItem{ID: "@any", Description: "[Alias] An alias matches any of the kinds"})
42-
result = append(result, inspectionmetadata.SetParameterFormFieldOptionItem{ID: "@default", Description: "[Alias] An alias matches a set of kinds that frequently queried."})
43-
return result, nil
40+
return []inspectionmetadata.SetParameterFormFieldOptionItem{
41+
{ID: "@any", Description: "[Alias] An alias matches any of the kinds"},
42+
{ID: "@legacy_default", Description: "[Alias] An alias matches a set of kinds frequently queried in legacy KHI versions."},
43+
}, nil
4444
}).
4545
WithValidator(func(ctx context.Context, value []string) (string, error) {
4646
if len(value) == 0 {
4747
return "kind filter can't be empty", nil
4848
}
4949
filterInStr := strings.Join(value, " ")
50-
result, err := gcpqueryutil.ParseSetFilter(filterInStr, inputKindNameAliasMap, true, true, true)
50+
result, err := gcpqueryutil.ParseSetFilter(filterInStr, inputKindsAliasMap, true, true, true)
5151
if err != nil {
5252
return "", err
5353
}
5454
return result.ValidationError, nil
5555
}).
5656
WithConverter(func(ctx context.Context, value []string) (*gcpqueryutil.SetFilterParseResult, error) {
5757
filterInStr := strings.Join(value, " ")
58-
result, err := gcpqueryutil.ParseSetFilter(filterInStr, inputKindNameAliasMap, true, true, true)
58+
result, err := gcpqueryutil.ParseSetFilter(filterInStr, inputKindsAliasMap, true, true, true)
5959
if err != nil {
6060
return nil, err
6161
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
// Copyright 2026 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package googlecloudk8scommon_impl
16+
17+
import (
18+
"context"
19+
"slices"
20+
"strings"
21+
"testing"
22+
23+
"github.com/GoogleCloudPlatform/khi/pkg/common/typedmap"
24+
"github.com/GoogleCloudPlatform/khi/pkg/core/inspection/gcpqueryutil"
25+
inspectionmetadata "github.com/GoogleCloudPlatform/khi/pkg/core/inspection/metadata"
26+
inspectiontest "github.com/GoogleCloudPlatform/khi/pkg/core/inspection/test"
27+
googlecloudk8scommon_contract "github.com/GoogleCloudPlatform/khi/pkg/task/inspection/googlecloudk8scommon/contract"
28+
inspectioncore_contract "github.com/GoogleCloudPlatform/khi/pkg/task/inspection/inspectioncore/contract"
29+
"github.com/google/go-cmp/cmp"
30+
"github.com/google/go-cmp/cmp/cmpopts"
31+
)
32+
33+
var expectedLegacyDefaultKinds = func() []string {
34+
kinds := strings.Split("pods replicasets daemonsets nodes deployments namespaces statefulsets services servicenetworkendpointgroups ingresses poddisruptionbudgets jobs cronjobs endpointslices persistentvolumes persistentvolumeclaims storageclasses horizontalpodautoscalers verticalpodautoscalers multidimpodautoscalers", " ")
35+
slices.Sort(kinds)
36+
return kinds
37+
}()
38+
39+
func TestInputKindFilterTask_Metadata(t *testing.T) {
40+
ctx := inspectiontest.WithDefaultTestInspectionTaskContext(context.Background())
41+
_, metadata, err := inspectiontest.RunInspectionTask(ctx, InputKindFilterTask, inspectioncore_contract.TaskModeDryRun, nil)
42+
if err != nil {
43+
t.Fatalf("unexpected error on DryRun mode: %v", err)
44+
}
45+
46+
fields, found := typedmap.Get(metadata, inspectionmetadata.FormFieldSetMetadataKey)
47+
if !found {
48+
t.Fatal("FormFieldSet not found on metadata")
49+
}
50+
51+
rawField := fields.DangerouslyGetField(googlecloudk8scommon_contract.InputKindFilterTaskID.ReferenceIDString())
52+
field, ok := rawField.(inspectionmetadata.SetParameterFormField)
53+
if !ok {
54+
t.Fatalf("expected SetParameterFormField, got %T", rawField)
55+
}
56+
57+
wantDefault := []string{"@any", "-leases"}
58+
if diff := cmp.Diff(wantDefault, field.Default); diff != "" {
59+
t.Errorf("default value mismatch (-want +got):\n%s", diff)
60+
}
61+
62+
wantOptions := []inspectionmetadata.SetParameterFormFieldOptionItem{
63+
{ID: "@any", Description: "[Alias] An alias matches any of the kinds"},
64+
{ID: "@legacy_default", Description: "[Alias] An alias matches a set of kinds frequently queried in legacy KHI versions."},
65+
}
66+
if diff := cmp.Diff(wantOptions, field.Options); diff != "" {
67+
t.Errorf("options mismatch (-want +got):\n%s", diff)
68+
}
69+
}
70+
71+
func TestInputKindFilterTask_Run(t *testing.T) {
72+
testCases := []struct {
73+
name string
74+
inputValue any
75+
wantResult *gcpqueryutil.SetFilterParseResult
76+
wantErrSub string
77+
}{
78+
{
79+
name: "default value used when input is nil",
80+
inputValue: nil,
81+
wantResult: &gcpqueryutil.SetFilterParseResult{
82+
SubtractMode: true,
83+
Subtractives: []string{"leases"},
84+
Additives: []string{},
85+
},
86+
},
87+
{
88+
name: "explicit default @any -leases",
89+
inputValue: []any{"@any", "-leases"},
90+
wantResult: &gcpqueryutil.SetFilterParseResult{
91+
SubtractMode: true,
92+
Subtractives: []string{"leases"},
93+
Additives: []string{},
94+
},
95+
},
96+
{
97+
name: "legacy_default alias expands to legacy kinds",
98+
inputValue: []any{"@legacy_default"},
99+
wantResult: &gcpqueryutil.SetFilterParseResult{
100+
SubtractMode: false,
101+
Subtractives: []string{},
102+
Additives: expectedLegacyDefaultKinds,
103+
},
104+
},
105+
{
106+
name: "legacy_default with subtractive element",
107+
inputValue: []any{"@legacy_default", "-pods"},
108+
wantResult: func() *gcpqueryutil.SetFilterParseResult {
109+
withoutPods := make([]string, 0, len(expectedLegacyDefaultKinds)-1)
110+
for _, k := range expectedLegacyDefaultKinds {
111+
if k != "pods" {
112+
withoutPods = append(withoutPods, k)
113+
}
114+
}
115+
return &gcpqueryutil.SetFilterParseResult{
116+
SubtractMode: false,
117+
Subtractives: []string{},
118+
Additives: withoutPods,
119+
}
120+
}(),
121+
},
122+
{
123+
name: "@any with multiple subtractive kinds",
124+
inputValue: []any{"@any", "-leases", "-configmaps"},
125+
wantResult: &gcpqueryutil.SetFilterParseResult{
126+
SubtractMode: true,
127+
Subtractives: []string{"configmaps", "leases"},
128+
Additives: []string{},
129+
},
130+
},
131+
{
132+
name: "custom kinds",
133+
inputValue: []any{"pods", "services"},
134+
wantResult: &gcpqueryutil.SetFilterParseResult{
135+
SubtractMode: false,
136+
Subtractives: []string{},
137+
Additives: []string{"pods", "services"},
138+
},
139+
},
140+
{
141+
name: "empty filter produces validation error",
142+
inputValue: []any{},
143+
wantErrSub: "kind filter can't be empty",
144+
},
145+
{
146+
name: "old @default alias is rejected",
147+
inputValue: []any{"@default"},
148+
wantErrSub: "alias `default` was not found",
149+
},
150+
{
151+
name: "invalid character produces validation error",
152+
inputValue: []any{"invalid$$$"},
153+
wantErrSub: "filter value must be whitespace split series",
154+
},
155+
}
156+
157+
for _, tc := range testCases {
158+
t.Run(tc.name, func(t *testing.T) {
159+
ctx := inspectiontest.WithDefaultTestInspectionTaskContext(context.Background())
160+
inputMap := map[string]any{}
161+
if tc.inputValue != nil {
162+
inputMap[googlecloudk8scommon_contract.InputKindFilterTaskID.ReferenceIDString()] = tc.inputValue
163+
}
164+
165+
result, _, err := inspectiontest.RunInspectionTask(ctx, InputKindFilterTask, inspectioncore_contract.TaskModeRun, inputMap)
166+
if tc.wantErrSub != "" {
167+
if err == nil {
168+
t.Fatalf("expected error containing %q, got nil", tc.wantErrSub)
169+
}
170+
if !strings.Contains(err.Error(), tc.wantErrSub) {
171+
t.Fatalf("expected error containing %q, got %q", tc.wantErrSub, err.Error())
172+
}
173+
return
174+
}
175+
176+
if err != nil {
177+
t.Fatalf("unexpected error: %v", err)
178+
}
179+
180+
if diff := cmp.Diff(tc.wantResult, result, cmpopts.EquateEmpty()); diff != "" {
181+
t.Errorf("RunInspectionTask() mismatch (-want +got):\n%s", diff)
182+
}
183+
})
184+
}
185+
}

pkg/task/inspection/googlecloudlogk8saudit/impl/parser_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func getAuditLogJobTestConfig() *taskrecord.JobTestConfig {
5959
"cloud.google.com/common/input-query-resource-names/cloud.google.com/log/k8s-audit/audit-list-log-entries": "projects/khi-testing-with-auditlog",
6060
"cloud.google.com/k8s/input-cluster-name": "p0-gke-basic-1",
6161
"cloud.google.com/k8s/input-kinds": []any{
62-
"@default",
62+
"@legacy_default",
6363
},
6464
"cloud.google.com/k8s/input-namespaces": []any{
6565
"@all_cluster_scoped",

0 commit comments

Comments
 (0)