knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/webhook/psbinding/index.go (about) 1 /* 2 Copyright 2019 The Knative 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 http://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 psbinding 18 19 import ( 20 "sync" 21 22 "k8s.io/apimachinery/pkg/labels" 23 ) 24 25 // exactKey is the type for keys that match exactly. 26 type exactKey struct { 27 Group string 28 Kind string 29 Namespace string 30 Name string 31 } 32 33 // exactMatcher is our reverse index from subjects to the Bindings that apply to 34 // them. 35 type exactMatcher map[exactKey][]Bindable 36 37 // add associates a Binding with a key in the reverse index. 38 func (em exactMatcher) add(key exactKey, b Bindable) { 39 em[key] = append(em[key], b) 40 } 41 42 // get fetches the key from the reverse index, if present. 43 func (em exactMatcher) get(key exactKey) []Bindable { 44 return em[key] 45 } 46 47 // inexactKey is the type for keys that match inexactly (via selector) 48 type inexactKey struct { 49 Group string 50 Kind string 51 Namespace string 52 } 53 54 // pair holds selectors and bindables for a particular inexactKey. 55 type pair struct { 56 selector labels.Selector 57 sb Bindable 58 } 59 60 // inexactMatcher is our reverse index from subjects to the Bindings that apply to 61 // them. 62 type inexactMatcher map[inexactKey][]pair 63 64 // add writes a key into the reverse index. 65 func (im inexactMatcher) add(key inexactKey, selector labels.Selector, b Bindable) { 66 pl := im[key] 67 pl = append(pl, pair{ 68 selector: selector, 69 sb: b, 70 }) 71 im[key] = pl 72 } 73 74 // get fetches the key from the reverse index, if present. 75 func (im inexactMatcher) get(key inexactKey, ls labels.Set) []Bindable { 76 found := []Bindable{} 77 // Iterate over the list of pairs matched for this GK + namespace and collect the 78 // Bindables that matches our selector. 79 for _, p := range im[key] { 80 if p.selector.Matches(ls) { 81 found = append(found, p.sb) 82 } 83 } 84 return found 85 } 86 87 // index is a collection of Bindables indexed by their subject resources. 88 type index struct { 89 // lock protects access to exact and inexact 90 lock sync.RWMutex 91 exact exactMatcher 92 inexact inexactMatcher 93 } 94 95 // indexBuilder allows an index to be built atomically 96 type indexBuilder struct { 97 exact exactMatcher 98 inexact inexactMatcher 99 } 100 101 // newIndexBuilder constructs a new IndexBuilder. 102 func newIndexBuilder() *indexBuilder { 103 return &indexBuilder{ 104 exact: make(exactMatcher), 105 inexact: make(inexactMatcher), 106 } 107 } 108 109 // associate associates a resource with a given exact key with a given Bindable. 110 func (ib *indexBuilder) associate(key exactKey, fb Bindable) *indexBuilder { 111 ib.exact.add(key, fb) 112 return ib 113 } 114 115 // associateSelection associates resources with the given inexact key and labels matching the given selector with a given Bindable. 116 func (ib *indexBuilder) associateSelection(inexactKey inexactKey, selector labels.Selector, fb Bindable) *indexBuilder { 117 ib.inexact.add(inexactKey, selector, fb) 118 return ib 119 } 120 121 // build sets the given index to the built value. 122 func (ib *indexBuilder) build(index *index) { 123 index.setIndex(ib.exact, ib.inexact) 124 } 125 126 // setIndex replaces the index atomically with the given matchers. 127 func (idx *index) setIndex(exact exactMatcher, inexact inexactMatcher) { 128 idx.lock.Lock() 129 defer idx.lock.Unlock() 130 idx.exact = exact 131 idx.inexact = inexact 132 } 133 134 // lookUp returns the Bindables associated with a resource with the given group, kind, namespace, name, and labels. 135 func (idx *index) lookUp(key exactKey, labels labels.Set) []Bindable { 136 idx.lock.RLock() 137 defer idx.lock.RUnlock() 138 139 exactMatches := idx.exact.get(key) 140 141 inexactMatches := idx.inexact.get(inexactKey{ 142 Group: key.Group, 143 Kind: key.Kind, 144 Namespace: key.Namespace, 145 }, labels) 146 147 return append(exactMatches, inexactMatches...) 148 }