github.com/paketo-buildpacks/libpak@v1.70.0/bindings/resolve.go (about) 1 /* 2 * Copyright 2018-2020 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package bindings 18 19 import ( 20 "fmt" 21 "strings" 22 23 "github.com/buildpacks/libcnb" 24 ) 25 26 // Predicate should return true if it matches a given binding. 27 type Predicate func(bind libcnb.Binding) bool 28 29 // OfType returns a Predicate that returns true if a given binding has Type that matches t. The comparison is 30 // case-insensitive. 31 func OfType(t string) Predicate { 32 return func(bind libcnb.Binding) bool { 33 return strings.EqualFold(bind.Type, t) 34 } 35 } 36 37 // OfProvider returns a Predicate that returns true if a given binding has Provider that matches p. The comparison is 38 // case-insensitive. 39 func OfProvider(p string) Predicate { 40 return func(bind libcnb.Binding) bool { 41 return strings.EqualFold(bind.Provider, p) 42 } 43 } 44 45 // WithName returns a Predicate that returns true if a given binding has Name that matches n. The comparison is 46 // case-insensitive. 47 func WithName(n string) Predicate { 48 return func(bind libcnb.Binding) bool { 49 return strings.EqualFold(bind.Name, n) 50 } 51 } 52 53 // Resolve returns all bindings from binds that match every Predicate in predicates. 54 func Resolve(binds libcnb.Bindings, predicates ...Predicate) libcnb.Bindings { 55 var result libcnb.Bindings 56 // deep copy 57 result = append(result, binds...) 58 59 // filter on predicates 60 for _, p := range predicates { 61 result = filter(result, p) 62 } 63 return result 64 } 65 66 // ResolveOne returns a single binding from bindings that match every Predicate if present. If exactly one match is found 67 // ResolveOne returns the binding and true. If zero matches are found, ResolveOne returns an empty binding and false. 68 // An error is returned if multiple matches are found. 69 func ResolveOne(binds libcnb.Bindings, predicates ...Predicate) (libcnb.Binding, bool, error) { 70 resolved := Resolve(binds, predicates...) 71 if len(resolved) == 0 { 72 return libcnb.Binding{}, false, nil 73 } 74 if len(resolved) > 1 { 75 return libcnb.Binding{}, false, errTooManyBindings(resolved) 76 } 77 return resolved[0], true, nil 78 } 79 80 func errTooManyBindings(binds libcnb.Bindings) error { 81 var names []string 82 for _, bind := range binds { 83 names = append(names, bind.Name) 84 } 85 return fmt.Errorf("multiple bindings matched the given predicates %+v", names) 86 } 87 88 func filter(binds libcnb.Bindings, p Predicate) libcnb.Bindings { 89 var result []libcnb.Binding 90 for _, bind := range binds { 91 if p(bind) { 92 result = append(result, bind) 93 } 94 } 95 return result 96 }