github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/internal/util/function/matcher.go (about)

     1  // Copyright 2022 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 function
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"github.com/GoogleContainerTools/kpt/porch/api/porch/v1alpha1"
    21  )
    22  
    23  type Matcher interface {
    24  	Match(v1alpha1.Function) bool
    25  }
    26  
    27  var _ Matcher = TypeMatcher{}
    28  var _ Matcher = KeywordsMatcher{}
    29  
    30  type TypeMatcher struct {
    31  	FnType string
    32  }
    33  
    34  // Match determines whether the `function` (which can be multi-typed), belongs
    35  // to the matcher's FnType. type value should only be `validator` or `mutator`.
    36  func (m TypeMatcher) Match(function v1alpha1.Function) bool {
    37  	if m.FnType == "" {
    38  		// type is not given, shown all functions.
    39  		return true
    40  	}
    41  	for _, actualType := range function.Spec.FunctionTypes {
    42  		if string(actualType) == m.FnType {
    43  			return true
    44  		}
    45  	}
    46  	return false
    47  }
    48  
    49  type KeywordsMatcher struct {
    50  	Keywords []string
    51  }
    52  
    53  // Match determines whether the `function` has keywords which match the matcher's `Keywords`.
    54  // Experimental: This logic may change to only if all function keywords are found from  matcher's `Keywords`,
    55  // can it claims a match (return true).
    56  func (m KeywordsMatcher) Match(function v1alpha1.Function) bool {
    57  	if len(m.Keywords) == 0 {
    58  		// Accept all functions if keywords are not given.
    59  		return true
    60  	}
    61  	for _, actual := range function.Spec.Keywords {
    62  		for _, expected := range m.Keywords {
    63  			if actual == expected {
    64  				return true
    65  			}
    66  		}
    67  	}
    68  	return false
    69  }
    70  
    71  func MatchFunctions(functions []v1alpha1.Function, matchers ...Matcher) []v1alpha1.Function {
    72  	var suggestedFunctions []v1alpha1.Function
    73  	for _, function := range functions {
    74  		match := true
    75  		for _, matcher := range matchers {
    76  			if !matcher.Match(function) {
    77  				match = false
    78  			}
    79  		}
    80  		if match {
    81  			suggestedFunctions = append(suggestedFunctions, function)
    82  		}
    83  	}
    84  	return suggestedFunctions
    85  }
    86  
    87  // GetNames returns the list of function names.
    88  // - Porch function name is <PackageRepository>:<ImageName>:<Version>. e.g. kpt-functions:set-annotation:v0.1
    89  // - Catalog v2 function name is trimed to only contain <ImageName>:<Version>, and exclude gcr.io/kpt-fn. e.g. set-annotation:v0.1
    90  func GetNames(functions []v1alpha1.Function) []string {
    91  	var names []string
    92  	for _, function := range functions {
    93  		var name string
    94  		if function.Namespace == CatalogV2 {
    95  			name = function.Name
    96  		} else {
    97  			name = fmt.Sprintf("%v:%v", function.Namespace, function.Name)
    98  		}
    99  		names = append(names, name)
   100  	}
   101  	return names
   102  }