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  }