Skip to content
Open
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
40 changes: 39 additions & 1 deletion internal/model/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package model

import (
"fmt"
"regexp"

"github.com/pkg/errors"
"github.com/spf13/pflag"
Expand All @@ -31,6 +32,8 @@ type Namespaced interface {
type Filters struct {
includes []string
excludes []string
regexpObjectIncludes []*regexp.Regexp
regexpObjectExcludes []*regexp.Regexp
excludeClusterObjects bool
kindFilter Filter
componentFilter Filter
Expand All @@ -39,11 +42,13 @@ type Filters struct {

// NewFilters sets up options in the supplied flags and returns a function to return filters.
func NewFilters(flags *pflag.FlagSet, includeAllFilters bool) func() (Filters, error) {
var includes, excludes, kindIncludes, kindExcludes, nsIncludes, nsExcludes []string
var includes, excludes, kindIncludes, kindExcludes, nsIncludes, nsExcludes, regexpObjectIncludes, regexpObjectExcludes []string
var includeClusterScopedObjects bool

flags.StringArrayVarP(&includes, "component", "c", nil, "include just this component")
flags.StringArrayVarP(&excludes, "exclude-component", "C", nil, "exclude this component")
flags.StringArrayVarP(&regexpObjectIncludes, "object", "t", nil, "include k8s components matching this regexp")
flags.StringArrayVarP(&regexpObjectExcludes, "exclude-object", "T", nil, "exclude k8s components matching this regexp")
if includeAllFilters {
flags.StringArrayVarP(&kindIncludes, "kind", "k", nil, "include objects with this kind")
flags.StringArrayVarP(&kindExcludes, "exclude-kind", "K", nil, "exclude objects with this kind")
Expand All @@ -69,9 +74,21 @@ func NewFilters(flags *pflag.FlagSet, includeAllFilters bool) func() (Filters, e
includeClusterScopedObjects = false
}
}

regexpIncludes := make([]*regexp.Regexp, 0, len(regexpObjectIncludes))
regexpExcludes := make([]*regexp.Regexp, 0, len(regexpObjectExcludes))
for _, re := range regexpObjectIncludes {
regexpIncludes = append(regexpIncludes, regexp.MustCompile(fmt.Sprintf(`(?i)^%s$`, re)))
}
for _, re := range regexpObjectExcludes {
regexpExcludes = append(regexpExcludes, regexp.MustCompile(fmt.Sprintf(`(?i)^%s$`, re)))
}

return Filters{
includes: includes,
excludes: excludes,
regexpObjectIncludes: regexpIncludes,
regexpObjectExcludes: regexpExcludes,
kindFilter: of,
componentFilter: cf,
namespaceFilter: nf,
Expand All @@ -95,6 +112,24 @@ func (f Filters) GVKFilter(gvk schema.GroupVersionKind) bool {
return f.kindFilter != nil && f.kindFilter.ShouldInclude(gvk.Kind)
}

// ObjectFilter returns true if the name matches all include regexes and does not match all exclude regexes
// This code was inspired and adapted from grafana tanka
// https://github.com/grafana/tanka/blob/a6a63ac17f713d5fd64bb6d7972bc84c6b5902a6/pkg/process/filter.go#L74
func (f Filters) ObjectFilter(object K8sQbecMeta) bool {
kindName := object.GetKind() + "/" + object.GetName()
for _, re := range f.regexpObjectIncludes {
if !re.MatchString(kindName) {
return false
}
}
for _, re := range f.regexpObjectExcludes {
if re.MatchString(kindName) {
return false
}
}
return true
}

// HasNamespaceFilters returns true if filters based on namespace scope are in effect.
func (f Filters) HasNamespaceFilters() bool {
return (f.namespaceFilter != nil && f.namespaceFilter.HasFilters()) || f.excludeClusterObjects
Expand All @@ -103,6 +138,9 @@ func (f Filters) HasNamespaceFilters() bool {
// Match returns true if the current filters match the supplied object. The client can be nil
// if namespace scope filters are not in effect.
func (f Filters) Match(o K8sQbecMeta, client Namespaced, defaultNS string) (bool, error) {
if !f.ObjectFilter(o) {
return false, nil
}
if f.HasNamespaceFilters() && client == nil {
return false, fmt.Errorf("no namespace metadata when namespace filters present")
}
Expand Down