knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/kmeta/labels.go (about)

     1  /*
     2  Copyright 2018 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 kmeta
    18  
    19  import (
    20  	"fmt"
    21  
    22  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    23  	"k8s.io/apimachinery/pkg/labels"
    24  	"k8s.io/apimachinery/pkg/selection"
    25  )
    26  
    27  // The methods in this file are used for managing subresources in cases where
    28  // a controller instantiates different resources for each version of itself.
    29  // There are two sets of methods available here:
    30  // * `*VersionLabel*`: these methods act on `metadata.resourceVersion` and
    31  //  create new labels for EVERY change to the resource (incl. `/status`).
    32  // * `*GenerationLabel*`: these methods act on `metadata.generation` and
    33  //  create new labels for changes to the resource's "spec" (typically, but
    34  //  some K8s resources change `metadata.generation` for annotations as well
    35  //  e.g. Deployment).
    36  //
    37  // For example, if an A might instantiate N B's at version 1 and M B's at
    38  // version 2 then it can use MakeVersionLabels to decorate each subresource
    39  // with the appropriate labels for the version at which it was instantiated.
    40  //
    41  // During reconciliation, MakeVersionLabelSelector can be used with the
    42  // informer listers to access the appropriate subresources for the current
    43  // version of the parent resource.
    44  //
    45  // Likewise during reconciliation, MakeOldVersionLabelSelector can be used
    46  // with the API client's DeleteCollection method to clean up subresources
    47  // for older versions of the resource.
    48  
    49  // MakeVersionLabels constructs a set of labels to apply to subresources
    50  // instantiated at this version of the parent resource, so that we can
    51  // efficiently select them.
    52  func MakeVersionLabels(om metav1.ObjectMetaAccessor) labels.Set {
    53  	return map[string]string{
    54  		"controller": string(om.GetObjectMeta().GetUID()),
    55  		"version":    om.GetObjectMeta().GetResourceVersion(),
    56  	}
    57  }
    58  
    59  // MakeVersionLabelSelector constructs a selector for subresources
    60  // instantiated at this version of the parent resource.  This keys
    61  // off of the labels populated by MakeVersionLabels.
    62  func MakeVersionLabelSelector(om metav1.ObjectMetaAccessor) labels.Selector {
    63  	return labels.SelectorFromSet(MakeVersionLabels(om))
    64  }
    65  
    66  // MakeOldVersionLabelSelector constructs a selector for subresources
    67  // instantiated at an older version of the parent resource.  This keys
    68  // off of the labels populated by MakeVersionLabels.
    69  func MakeOldVersionLabelSelector(om metav1.ObjectMetaAccessor) labels.Selector {
    70  	return labels.NewSelector().Add(
    71  		mustNewRequirement("controller", selection.Equals, []string{string(om.GetObjectMeta().GetUID())}),
    72  		mustNewRequirement("version", selection.NotEquals, []string{om.GetObjectMeta().GetResourceVersion()}),
    73  	)
    74  }
    75  
    76  // MakeGenerationLabels constructs a set of labels to apply to subresources
    77  // instantiated at this version of the parent resource, so that we can
    78  // efficiently select them.
    79  func MakeGenerationLabels(om metav1.ObjectMetaAccessor) labels.Set {
    80  	return map[string]string{
    81  		"controller": string(om.GetObjectMeta().GetUID()),
    82  		"generation": genStr(om),
    83  	}
    84  }
    85  
    86  // MakeGenerationLabelSelector constructs a selector for subresources
    87  // instantiated at this version of the parent resource.  This keys
    88  // off of the labels populated by MakeGenerationLabels.
    89  func MakeGenerationLabelSelector(om metav1.ObjectMetaAccessor) labels.Selector {
    90  	return labels.SelectorFromSet(MakeGenerationLabels(om))
    91  }
    92  
    93  // MakeOldGenerationLabelSelector constructs a selector for subresources
    94  // instantiated at an older version of the parent resource.  This keys
    95  // off of the labels populated by MakeGenerationLabels.
    96  func MakeOldGenerationLabelSelector(om metav1.ObjectMetaAccessor) labels.Selector {
    97  	return labels.NewSelector().Add(
    98  		mustNewRequirement("controller", selection.Equals, []string{string(om.GetObjectMeta().GetUID())}),
    99  		mustNewRequirement("generation", selection.NotEquals, []string{genStr(om)}),
   100  	)
   101  }
   102  
   103  func genStr(om metav1.ObjectMetaAccessor) string {
   104  	return fmt.Sprintf("%05d", om.GetObjectMeta().GetGeneration())
   105  }
   106  
   107  // mustNewRequirement panics if there are any errors constructing our selectors.
   108  func mustNewRequirement(key string, op selection.Operator, vals []string) labels.Requirement {
   109  	r, err := labels.NewRequirement(key, op, vals)
   110  	if err != nil {
   111  		panic(fmt.Sprintf("mustNewRequirement(%v, %v, %v) = %v", key, op, vals, err))
   112  	}
   113  	return *r
   114  }