Skip to content

Commit

Permalink
Fix: exclude multi (#228)
Browse files Browse the repository at this point in the history
* FIX: support multi exclude

* FIX: support multi exclude

---------

Co-authored-by: Yonah Dissen <yonahdissen@Yonahs-MacBook-Pro.local>
  • Loading branch information
yonahd and Yonah Dissen committed Mar 24, 2024
1 parent cdff99c commit 06a2b4e
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 22 deletions.
4 changes: 2 additions & 2 deletions cmd/kor/root.go
Expand Up @@ -76,10 +76,10 @@ func Execute() {
}

func addFilterOptionsFlag(cmd *cobra.Command, opts *filters.Options) {
cmd.PersistentFlags().StringVarP(&opts.ExcludeLabels, "exclude-labels", "l", opts.ExcludeLabels, "Selector to filter out, Example: --exclude-labels key1=value1,key2=value2. If --include-labels is set, --exclude-labels will be ignored.")
cmd.PersistentFlags().StringSliceVarP(&opts.ExcludeLabels, "exclude-labels", "l", opts.ExcludeLabels, "Selector to filter out, Example: --exclude-labels key1=value1,key2=value2. If --include-labels is set, --exclude-labels will be ignored.")
cmd.PersistentFlags().StringVar(&opts.NewerThan, "newer-than", opts.NewerThan, "The maximum age of the resources to be considered unused. This flag cannot be used together with older-than flag. Example: --newer-than=1h2m")
cmd.PersistentFlags().StringVar(&opts.OlderThan, "older-than", opts.OlderThan, "The minimum age of the resources to be considered unused. This flag cannot be used together with newer-than flag. Example: --older-than=1h2m")
cmd.PersistentFlags().StringVar(&opts.IncludeLabels, "include-labels", opts.IncludeLabels, "Selector to filter in, Example: --include-labels key1=value1,key2=value2.")
cmd.PersistentFlags().StringVar(&opts.IncludeLabels, "include-labels", opts.IncludeLabels, "Selector to filter in, Example: --include-labels key1=value1.(currently supports one label)")
cmd.PersistentFlags().StringSliceVar(&opts.ExcludeNamespaces, "exclude-namespaces", opts.ExcludeNamespaces, "Namespaces to be excluded, split by commas. Example: --exclude-namespace ns1,ns2,ns3. If --include-namespace is set, --exclude-namespaces will be ignored.")
cmd.PersistentFlags().StringSliceVarP(&opts.IncludeNamespaces, "include-namespaces", "n", opts.IncludeNamespaces, "Namespaces to run on, split by commas. Example: --include-namespace ns1,ns2,ns3. ")
}
23 changes: 17 additions & 6 deletions pkg/filters/filters.go
Expand Up @@ -46,17 +46,28 @@ func AgeFilter(object runtime.Object, opts *Options) bool {
}

// HasExcludedLabel parses the excluded selector into a label selector object
func HasExcludedLabel(resourcelabels map[string]string, excludeSelector string) (bool, error) {
if excludeSelector == "" {
func HasExcludedLabel(resourcelabels map[string]string, excludeSelector []string) (bool, error) {
excludes := make([]labels.Selector, 0)

if len(excludeSelector) == 0 {
return false, nil
}
exclude, err := labels.Parse(excludeSelector)
if err != nil {
return false, err

for _, labelStr := range excludeSelector {
exclude, err := labels.Parse(labelStr)
if err != nil {
return false, err
}
excludes = append(excludes, exclude)
}

labelSet := labels.Set(resourcelabels)
return exclude.Matches(labelSet), nil
for _, exclude := range excludes {
if exclude.Matches(labelSet) {
return true, nil
}
}
return false, nil
}

// HasIncludedAge checks if a resource has an age that matches the included criteria specified by the filter options
Expand Down
4 changes: 2 additions & 2 deletions pkg/filters/filters_test.go
Expand Up @@ -32,7 +32,7 @@ func TestLabelFilter(t *testing.T) {
args: args{
object: node,
opts: &Options{
ExcludeLabels: "foo=barbar",
ExcludeLabels: []string{"foo=barbar"},
},
},
want: false,
Expand All @@ -42,7 +42,7 @@ func TestLabelFilter(t *testing.T) {
args: args{
object: node,
opts: &Options{
ExcludeLabels: "foo=bar",
ExcludeLabels: []string{"foo=bar"},
},
},
want: true,
Expand Down
39 changes: 28 additions & 11 deletions pkg/filters/options.go
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"os"
"strings"
"sync"
"time"

Expand All @@ -29,7 +30,7 @@ type Options struct {
NewerThan string
// ExcludeLabels is a label selector to exclude resources with matching labels
// IncludeLabels conflicts with it, and when setting IncludeLabels, ExcludeLabels is ignored and set to empty
ExcludeLabels string
ExcludeLabels []string
// IncludeLabels is a label selector to include resources with matching labels
IncludeLabels string
// ExcludeNamespaces is a namespace selector to exclude resources in matching namespaces
Expand All @@ -45,19 +46,35 @@ type Options struct {
// NewFilterOptions returns a new FilterOptions instance with default values
func NewFilterOptions() *Options {
return &Options{
OlderThan: "",
NewerThan: "",
ExcludeLabels: "",
OlderThan: "",
NewerThan: "",
}
}

func parseLabels(labelsStr string) (labels.Set, error) {
labelMap := map[string]string{}

labelPairs := strings.Split(labelsStr, ",")

for _, pair := range labelPairs {
parts := strings.SplitN(pair, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid label format: %s", pair)
}
labelMap[parts[0]] = parts[1]
}

return labels.Set(labelMap), nil
}

// Validate makes sure provided values for FilterOptions are valid
func (o *Options) Validate() error {
if _, err := labels.Parse(o.ExcludeLabels); err != nil {
return err
}
if _, err := labels.Parse(o.IncludeLabels); err != nil {
return err

// Parse and validate the labels
for _, labelStr := range o.ExcludeLabels {
if _, err := parseLabels(labelStr); err != nil {
return err
}
}

// Parse the older-than flag value into a time.Duration value
Expand Down Expand Up @@ -145,9 +162,9 @@ func (o *Options) Namespaces(clientset kubernetes.Interface) []string {

func (o *Options) modifyLabels() {
if o.IncludeLabels != "" {
if o.ExcludeLabels != "" {
if len(o.ExcludeLabels) > 0 {
fmt.Fprintf(os.Stderr, "Exclude labels can't be used together with include labels. Ignoring --exclude-label(-l) flag\n")
}
o.ExcludeLabels = ""
o.ExcludeLabels = nil
}
}
2 changes: 1 addition & 1 deletion pkg/kor/ingresses.go
Expand Up @@ -68,7 +68,7 @@ func retrieveUsedIngress(clientset kubernetes.Interface, namespace string, filte
}

func retrieveIngressNames(clientset kubernetes.Interface, namespace string, filterOpts *filters.Options) ([]string, []string, error) {
ingresses, err := clientset.NetworkingV1().Ingresses(namespace).List(context.TODO(), metav1.ListOptions{})
ingresses, err := clientset.NetworkingV1().Ingresses(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: filterOpts.IncludeLabels})
if err != nil {
return nil, nil, err
}
Expand Down

0 comments on commit 06a2b4e

Please sign in to comment.