github.com/opendevstack/tailor@v1.3.5-0.20220119161809-cab064e60a67/pkg/openshift/filter.go (about)

     1  package openshift
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/opendevstack/tailor/pkg/utils"
    10  )
    11  
    12  var availableKinds = []string{
    13  	"Service",
    14  	"Route",
    15  	"DeploymentConfig",
    16  	"Deployment",
    17  	"BuildConfig",
    18  	"ImageStream",
    19  	"PersistentVolumeClaim",
    20  	"Template",
    21  	"ConfigMap",
    22  	"Secret",
    23  	"RoleBinding",
    24  	"ServiceAccount",
    25  	"CronJob",
    26  	"Job",
    27  	"LimitRange",
    28  	"ResourceQuota",
    29  	"HorizontalPodAutoscaler",
    30  	"StatefulSet",
    31  }
    32  
    33  type ResourceFilter struct {
    34  	Kinds          []string
    35  	Name           string
    36  	Label          string
    37  	ExcludedKinds  []string
    38  	ExcludedNames  []string
    39  	ExcludedLabels []string
    40  }
    41  
    42  // NewResourceFilter returns a filter based on kinds and flags.
    43  // kindArg might be blank, or a list of kinds (e.g. 'pvc,dc') or
    44  // a kind/name combination (e.g. 'dc/foo').
    45  // selectorFlag might be blank or a key and a label, e.g. 'name=foo'.
    46  func NewResourceFilter(kindArg string, selectorFlag string, excludes []string) (*ResourceFilter, error) {
    47  	filter := &ResourceFilter{
    48  		Kinds: []string{},
    49  		Name:  "",
    50  		Label: selectorFlag,
    51  	}
    52  
    53  	if len(kindArg) > 0 {
    54  		kindArg = strings.ToLower(kindArg)
    55  
    56  		if strings.Contains(kindArg, "/") {
    57  			if strings.Contains(kindArg, ",") {
    58  				return nil, errors.New(
    59  					"You cannot target more than one resource name",
    60  				)
    61  			}
    62  			nameParts := strings.Split(kindArg, "/")
    63  			filter.Name = KindMapping[nameParts[0]] + "/" + nameParts[1]
    64  			return filter, nil
    65  		}
    66  
    67  		targetedKinds := make(map[string]bool)
    68  		unknownKinds := []string{}
    69  		kinds := strings.Split(kindArg, ",")
    70  		for _, kind := range kinds {
    71  			if _, ok := KindMapping[kind]; !ok {
    72  				unknownKinds = append(unknownKinds, kind)
    73  			} else {
    74  				targetedKinds[KindMapping[kind]] = true
    75  			}
    76  		}
    77  
    78  		if len(unknownKinds) > 0 {
    79  			return nil, fmt.Errorf(
    80  				"Unknown resource kinds: %s",
    81  				strings.Join(unknownKinds, ","),
    82  			)
    83  		}
    84  
    85  		for kind := range targetedKinds {
    86  			filter.Kinds = append(filter.Kinds, kind)
    87  		}
    88  
    89  		sort.Strings(filter.Kinds)
    90  	}
    91  
    92  	unknownKinds := []string{}
    93  	for _, v := range excludes {
    94  		v = strings.ToLower(v)
    95  		if strings.Contains(v, "/") { // Name
    96  			nameParts := strings.Split(v, "/")
    97  			k := nameParts[0]
    98  			if _, ok := KindMapping[k]; !ok {
    99  				unknownKinds = append(unknownKinds, k)
   100  			} else {
   101  				filter.ExcludedNames = append(filter.ExcludedNames, KindMapping[k]+"/"+nameParts[1])
   102  			}
   103  		} else if strings.Contains(v, "=") { // Label
   104  			filter.ExcludedLabels = append(filter.ExcludedLabels, v)
   105  		} else { // Kind
   106  			if _, ok := KindMapping[v]; !ok {
   107  				unknownKinds = append(unknownKinds, v)
   108  			} else {
   109  				filter.ExcludedKinds = append(filter.ExcludedKinds, KindMapping[v])
   110  			}
   111  		}
   112  	}
   113  
   114  	if len(unknownKinds) > 0 {
   115  		return nil, fmt.Errorf(
   116  			"Unknown excluded resource kinds: %s",
   117  			strings.Join(unknownKinds, ","),
   118  		)
   119  	}
   120  
   121  	return filter, nil
   122  }
   123  
   124  func (f *ResourceFilter) String() string {
   125  	return fmt.Sprintf("Kinds: %s, Name: %s, Label: %s, ExcludedKinds: %s, ExcludedNames: %s, ExcludedLabels: %s", f.Kinds, f.Name, f.Label, f.ExcludedKinds, f.ExcludedNames, f.ExcludedLabels)
   126  }
   127  
   128  func (f *ResourceFilter) SatisfiedBy(item *ResourceItem) bool {
   129  	if len(f.Name) > 0 && f.Name != item.FullName() {
   130  		return false
   131  	}
   132  
   133  	if len(f.Kinds) > 0 && !utils.Includes(f.Kinds, item.Kind) {
   134  		return false
   135  	}
   136  
   137  	if len(f.Label) > 0 {
   138  		labels := strings.Split(f.Label, ",")
   139  		for _, label := range labels {
   140  			if !item.HasLabel(label) {
   141  				return false
   142  			}
   143  		}
   144  	}
   145  
   146  	if len(f.ExcludedNames) > 0 {
   147  		if utils.Includes(f.ExcludedNames, item.FullName()) {
   148  			return false
   149  		}
   150  	}
   151  
   152  	if len(f.ExcludedKinds) > 0 {
   153  		if utils.Includes(f.ExcludedKinds, item.Kind) {
   154  			return false
   155  		}
   156  	}
   157  
   158  	if len(f.ExcludedLabels) > 0 {
   159  		for _, el := range f.ExcludedLabels {
   160  			if item.HasLabel(el) {
   161  				return false
   162  			}
   163  		}
   164  	}
   165  
   166  	return true
   167  }
   168  
   169  func (f *ResourceFilter) ConvertToTarget() string {
   170  	if len(f.Name) > 0 {
   171  		return f.Name
   172  	}
   173  	kinds := f.Kinds
   174  	if len(kinds) == 0 {
   175  		kinds = availableKinds
   176  	}
   177  	return strings.Join(kinds, ",")
   178  }
   179  
   180  func (f *ResourceFilter) ConvertToKinds() string {
   181  	if len(f.Name) > 0 {
   182  		nameParts := strings.Split(f.Name, "/")
   183  		return nameParts[0]
   184  	}
   185  	kinds := f.Kinds
   186  	if len(kinds) == 0 {
   187  		kinds = availableKinds
   188  	}
   189  	kindsWithoutExcluded := []string{}
   190  	for _, k := range kinds {
   191  		if !utils.Includes(f.ExcludedKinds, k) {
   192  			kindsWithoutExcluded = append(kindsWithoutExcluded, k)
   193  		}
   194  	}
   195  	return strings.Join(kindsWithoutExcluded, ",")
   196  }