github.com/cilium/cilium@v1.16.2/pkg/labels/oplabels.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package labels 5 6 import ( 7 "fmt" 8 9 "github.com/sirupsen/logrus" 10 11 "github.com/cilium/cilium/pkg/logging/logfields" 12 ) 13 14 type keepMarks map[string]struct{} 15 16 // set marks the label with 'key' to not be deleted. 17 func (k keepMarks) set(key string) { 18 k[key] = struct{}{} // marked for keeping 19 } 20 21 // OpLabels represents the possible types. 22 type OpLabels struct { 23 // Active labels that are enabled and disabled but not deleted 24 Custom Labels 25 26 // Labels derived from orchestration system 27 OrchestrationIdentity Labels 28 29 // orchestrationIdentity labels which have been disabled 30 Disabled Labels 31 32 // orchestrationInfo - labels from orchestration which are not used in determining a security identity 33 OrchestrationInfo Labels 34 } 35 36 // NewOpLabels creates new initialized OpLabels 37 func NewOpLabels() OpLabels { 38 return OpLabels{ 39 Custom: Labels{}, 40 Disabled: Labels{}, 41 OrchestrationIdentity: Labels{}, 42 OrchestrationInfo: Labels{}, 43 } 44 } 45 46 // SplitUserLabelChanges returns labels to 'add' and 'del'ete to make 47 // the custom labels match 'lbls' 48 // FIXME: Somewhere in the code we crash if the returned maps are non-nil 49 // but length 0. We retain this behaviour here because it's easier. 50 func (o *OpLabels) SplitUserLabelChanges(lbls Labels) (add, del Labels) { 51 for key, lbl := range lbls { 52 if _, found := o.Custom[key]; !found { 53 if add == nil { 54 add = Labels{} 55 } 56 add[key] = lbl 57 } 58 } 59 60 for key, lbl := range o.Custom { 61 if _, found := lbls[key]; !found { 62 if del == nil { 63 del = Labels{} 64 } 65 del[key] = lbl 66 } 67 } 68 69 return add, del 70 } 71 72 // IdentityLabels returns map of labels that are used when determining a 73 // security identity. 74 func (o *OpLabels) IdentityLabels() Labels { 75 enabled := make(Labels, len(o.Custom)+len(o.OrchestrationIdentity)) 76 77 for k, v := range o.Custom { 78 enabled[k] = v 79 } 80 81 for k, v := range o.OrchestrationIdentity { 82 enabled[k] = v 83 } 84 85 return enabled 86 } 87 88 // GetIdentityLabel returns the value of the given Key from all IdentityLabels. 89 func (o *OpLabels) GetIdentityLabel(key string) (l Label, found bool) { 90 l, found = o.OrchestrationIdentity[key] 91 if !found { 92 l, found = o.Custom[key] 93 } 94 return l, found 95 } 96 97 // AllLabels returns all Labels within the provided OpLabels. 98 func (o *OpLabels) AllLabels() Labels { 99 all := make(Labels, len(o.Custom)+len(o.OrchestrationInfo)+len(o.OrchestrationIdentity)+len(o.Disabled)) 100 101 for k, v := range o.Custom { 102 all[k] = v 103 } 104 105 for k, v := range o.Disabled { 106 all[k] = v 107 } 108 109 for k, v := range o.OrchestrationIdentity { 110 all[k] = v 111 } 112 113 for k, v := range o.OrchestrationInfo { 114 all[k] = v 115 } 116 return all 117 } 118 119 func (o *OpLabels) ReplaceInformationLabels(sourceFilter string, l Labels, logger *logrus.Entry) bool { 120 changed := false 121 keepers := make(keepMarks) 122 for _, v := range l { 123 keepers.set(v.Key) 124 if o.OrchestrationInfo.upsertLabel(sourceFilter, v) { 125 changed = true 126 logger.WithField(logfields.Object, logfields.Repr(v)).Debug("Assigning information label") 127 } 128 } 129 o.OrchestrationInfo.deleteUnMarked(sourceFilter, keepers) 130 131 return changed 132 } 133 134 func (o *OpLabels) ReplaceIdentityLabels(sourceFilter string, l Labels, logger *logrus.Entry) bool { 135 changed := false 136 137 keepers := make(keepMarks) 138 disabledKeepers := make(keepMarks) 139 140 for k, v := range l { 141 // A disabled identity label stays disabled without value updates 142 if _, found := o.Disabled[k]; found { 143 disabledKeepers.set(k) 144 } else if keepers.set(v.Key); o.OrchestrationIdentity.upsertLabel(sourceFilter, v) { 145 logger.WithField(logfields.Object, logfields.Repr(v)).Debug("Assigning security relevant label") 146 changed = true 147 } 148 } 149 150 if o.OrchestrationIdentity.deleteUnMarked(sourceFilter, keepers) || o.Disabled.deleteUnMarked(sourceFilter, disabledKeepers) { 151 changed = true 152 } 153 154 return changed 155 } 156 157 func (o *OpLabels) ModifyIdentityLabels(addLabels, delLabels Labels) (changed bool, err error) { 158 for k := range delLabels { 159 // The change request is accepted if the label is on 160 // any of the lists. If the label is already disabled, 161 // we will simply ignore that change. 162 if _, found := o.Custom[k]; !found { 163 if _, found := o.OrchestrationIdentity[k]; !found { 164 if _, found := o.Disabled[k]; !found { 165 return false, fmt.Errorf("label %s not found", k) 166 } 167 } 168 } 169 } 170 171 // Will not fail after this point 172 for k := range delLabels { 173 if v, found := o.OrchestrationIdentity[k]; found { 174 delete(o.OrchestrationIdentity, k) 175 o.Disabled[k] = v 176 changed = true 177 } 178 179 if _, found := o.Custom[k]; found { 180 delete(o.Custom, k) 181 changed = true 182 } 183 } 184 185 for k, v := range addLabels { 186 if _, found := o.Disabled[k]; found { // Restore label. 187 delete(o.Disabled, k) 188 o.OrchestrationIdentity[k] = v 189 changed = true 190 } else if _, found := o.OrchestrationIdentity[k]; found { // Replace label's source and value. 191 o.OrchestrationIdentity[k] = v 192 changed = true 193 } else { 194 o.Custom[k] = v 195 changed = true 196 } 197 } 198 return changed, nil 199 } 200 201 // upsertLabel updates or inserts 'label' in 'l', but only if exactly the same label 202 // was not already in 'l'. Returns 'true' if a label was added, or an old label was 203 // updated, 'false' otherwise. 204 // The label is only updated if its source matches the provided 'sourceFilter' 205 // or in case the provided sourceFilter is 'LabelSourceAny'. The new label must 206 // also match the old label 'source' in order for it to be replaced. 207 func (l Labels) upsertLabel(sourceFilter string, label Label) bool { 208 oldLabel, found := l[label.Key] 209 if found { 210 if sourceFilter != LabelSourceAny && sourceFilter != oldLabel.Source { 211 return false 212 } 213 214 // Key is the same, check if Value and Source are also the same 215 if label.Value == oldLabel.Value && label.Source == oldLabel.Source { 216 return false // No change 217 } 218 219 // If the label is not from the same source, then don't replace it. 220 if oldLabel.Source != label.Source { 221 return false 222 } 223 } 224 225 // Insert or replace old label 226 l[label.Key] = label 227 return true 228 } 229 230 // deleteUnMarked deletes the labels which have not been marked for keeping. 231 // The labels are only deleted if their source matches the provided sourceFilter 232 // or in case the provided sourceFilter is 'LabelSourceAny'. 233 // Returns true if any of them were deleted. 234 func (l Labels) deleteUnMarked(sourceFilter string, marks keepMarks) bool { 235 deleted := false 236 for k, v := range l { 237 if _, keep := marks[k]; !keep && (sourceFilter == LabelSourceAny || sourceFilter == v.Source) { 238 delete(l, k) 239 deleted = true 240 } 241 } 242 243 return deleted 244 }