Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow multiple namespace flags #159

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cmd/clusterlint/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ func main() {
Name: "C, ignore-checks",
Usage: "run a specific check",
},
cli.StringFlag{
Name: "n, namespace",
cli.StringSliceFlag{
Name: "n, namespaces",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To preserve backward compatibility you can add namespace as another alias here. It will look a little awkward in the help, but I'd like to avoid breaking existing users. I.e.:

Name: "n, namespaces, namespace",

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, makes sense. Do you want to add singular aliases to the checks and groups flags too (ex.: Name: "c, checks, check",) to show a common pattern?

Usage: "run checks in specific namespace",
},
cli.StringFlag{
Name: "N, ignore-namespace",
cli.StringSliceFlag{
Name: "N, ignore-namespaces",
Usage: "run checks not in specific namespace",
},
cli.StringFlag{
Expand Down Expand Up @@ -201,7 +201,7 @@ func runChecks(c *cli.Context) error {

diagnosticFilter := checks.DiagnosticFilter{Severity: checks.Severity(c.String("level"))}

objectFilter, err := kube.NewObjectFilter(c.String("n"), c.String("N"))
objectFilter, err := kube.NewObjectFilter(c.StringSlice("n"), c.StringSlice("N"))
if err != nil {
return err
}
Expand Down
19 changes: 13 additions & 6 deletions kube/object_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ import (

// ObjectFilter stores k8s object's fields that needs to be included or excluded while running checks
type ObjectFilter struct {
IncludeNamespace string
ExcludeNamespace string
IncludeNamespace []string
ExcludeNamespace []string
}

// NewObjectFilter is a constructor to initialize an instance of ObjectFilter
func NewObjectFilter(includeNamespace, excludeNamespace string) (ObjectFilter, error) {
func NewObjectFilter(includeNamespace, excludeNamespace []string) (ObjectFilter, error) {
if len(includeNamespace) > 0 && len(excludeNamespace) > 0 {
return ObjectFilter{}, fmt.Errorf("cannot specify both include and exclude namespace conditions")
}
Expand All @@ -42,11 +42,18 @@ func NewObjectFilter(includeNamespace, excludeNamespace string) (ObjectFilter, e

// NamespaceOptions returns ListOptions for filtering by namespace
func (f ObjectFilter) NamespaceOptions(opts metav1.ListOptions) metav1.ListOptions {
var selectors []fields.Selector
if len(f.IncludeNamespace) > 0 {
opts.FieldSelector = fields.OneTermEqualSelector("metadata.namespace", f.IncludeNamespace).String()
for _, namespace := range f.IncludeNamespace {
selectors = append(selectors, fields.OneTermEqualSelector("metadata.namespace", namespace))
}
} else if len(f.ExcludeNamespace) > 0 {
for _, namespace := range f.ExcludeNamespace {
selectors = append(selectors, fields.OneTermNotEqualSelector("metadata.namespace", namespace))
}
}
if len(f.ExcludeNamespace) > 0 {
opts.FieldSelector = fields.OneTermNotEqualSelector("metadata.namespace", f.ExcludeNamespace).String()
if len(selectors) > 0 {
opts.FieldSelector = fields.AndSelectors(selectors...).String()
}
return opts
}
26 changes: 23 additions & 3 deletions kube/object_filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,44 @@ import (
)

func TestNamespaceError(t *testing.T) {
_, err := NewObjectFilter("kube-system", "kube-system")
_, err := NewObjectFilter([]string{"namespace-1"}, []string{"namespace-2"})

assert.Error(t, err)
assert.Equal(t, fmt.Errorf("cannot specify both include and exclude namespace conditions"), err)
}

func TestNamespaceOptions(t *testing.T) {
filter, err := NewObjectFilter("namespace-1", "")
filter, err := NewObjectFilter([]string{"namespace-1"}, []string{})
assert.NoError(t, err)
assert.Equal(t,
metav1.ListOptions{FieldSelector: fields.OneTermEqualSelector("metadata.namespace", "namespace-1").String()},
filter.NamespaceOptions(metav1.ListOptions{}),
)

filter, err = NewObjectFilter("", "namespace-2")
filter, err = NewObjectFilter([]string{}, []string{"namespace-2"})
assert.NoError(t, err)
assert.Equal(t,
metav1.ListOptions{FieldSelector: fields.OneTermNotEqualSelector("metadata.namespace", "namespace-2").String()},
filter.NamespaceOptions(metav1.ListOptions{}),
)

filter, err = NewObjectFilter([]string{"namespace-1", "namespace-2"}, []string{})
assert.NoError(t, err)
assert.Equal(t,
metav1.ListOptions{FieldSelector: fields.AndSelectors(
fields.OneTermEqualSelector("metadata.namespace", "namespace-1"),
fields.OneTermEqualSelector("metadata.namespace", "namespace-2"),
).String()},
filter.NamespaceOptions(metav1.ListOptions{}),
)

filter, err = NewObjectFilter([]string{}, []string{"namespace-3", "namespace-4"})
assert.NoError(t, err)
assert.Equal(t,
metav1.ListOptions{FieldSelector: fields.AndSelectors(
fields.OneTermNotEqualSelector("metadata.namespace", "namespace-3"),
fields.OneTermNotEqualSelector("metadata.namespace", "namespace-4"),
).String()},
filter.NamespaceOptions(metav1.ListOptions{}),
)
}