github.phpd.cn/cilium/cilium@v1.6.12/pkg/labels/oplabels.go (about)

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