github.com/operator-framework/operator-lifecycle-manager@v0.30.0/pkg/controller/operators/olm/labeler.go (about)

     1  package olm
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/operator-framework/api/pkg/operators/v1alpha1"
     8  	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache"
     9  	opregistry "github.com/operator-framework/operator-registry/pkg/registry"
    10  	extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    11  	extv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
    12  	"k8s.io/apimachinery/pkg/labels"
    13  )
    14  
    15  const (
    16  	// APILabelKeyPrefix is the key prefix for a CSV's APIs label
    17  	APILabelKeyPrefix = "olm.api."
    18  )
    19  
    20  type operatorSurface struct {
    21  	ProvidedAPIs cache.APISet
    22  	RequiredAPIs cache.APISet
    23  }
    24  
    25  func apiSurfaceOfCSV(csv *v1alpha1.ClusterServiceVersion) (*operatorSurface, error) {
    26  	surface := operatorSurface{
    27  		ProvidedAPIs: cache.EmptyAPISet(),
    28  		RequiredAPIs: cache.EmptyAPISet(),
    29  	}
    30  
    31  	for _, crdDef := range csv.Spec.CustomResourceDefinitions.Owned {
    32  		parts := strings.SplitN(crdDef.Name, ".", 2)
    33  		if len(parts) < 2 {
    34  			return nil, fmt.Errorf("error parsing crd name: %s", crdDef.Name)
    35  		}
    36  		surface.ProvidedAPIs[opregistry.APIKey{Plural: parts[0], Group: parts[1], Version: crdDef.Version, Kind: crdDef.Kind}] = struct{}{}
    37  	}
    38  	for _, api := range csv.Spec.APIServiceDefinitions.Owned {
    39  		surface.ProvidedAPIs[opregistry.APIKey{Group: api.Group, Version: api.Version, Kind: api.Kind, Plural: api.Name}] = struct{}{}
    40  	}
    41  
    42  	requiredAPIs := cache.EmptyAPISet()
    43  	for _, crdDef := range csv.Spec.CustomResourceDefinitions.Required {
    44  		parts := strings.SplitN(crdDef.Name, ".", 2)
    45  		if len(parts) < 2 {
    46  			return nil, fmt.Errorf("error parsing crd name: %s", crdDef.Name)
    47  		}
    48  		requiredAPIs[opregistry.APIKey{Plural: parts[0], Group: parts[1], Version: crdDef.Version, Kind: crdDef.Kind}] = struct{}{}
    49  	}
    50  	for _, api := range csv.Spec.APIServiceDefinitions.Required {
    51  		requiredAPIs[opregistry.APIKey{Group: api.Group, Version: api.Version, Kind: api.Kind, Plural: api.Name}] = struct{}{}
    52  	}
    53  
    54  	return &surface, nil
    55  }
    56  
    57  // LabelSetsFor returns API label sets for the given object.
    58  // Concrete types other than OperatorSurface and CustomResource definition no-op.
    59  func LabelSetsFor(obj interface{}) ([]labels.Set, error) {
    60  	switch v := obj.(type) {
    61  	case operatorSurface:
    62  		return labelSetsForOperatorSurface(v)
    63  	case *extv1beta1.CustomResourceDefinition:
    64  		return labelSetsForCRDv1beta1(v)
    65  	case *extv1.CustomResourceDefinition:
    66  		return labelSetsForCRDv1(v)
    67  	default:
    68  		return nil, nil
    69  	}
    70  }
    71  
    72  func labelSetsForOperatorSurface(surface operatorSurface) ([]labels.Set, error) {
    73  	labelSet := labels.Set{}
    74  	for key := range surface.ProvidedAPIs.StripPlural() {
    75  		hash, err := cache.APIKeyToGVKHash(key)
    76  		if err != nil {
    77  			return nil, err
    78  		}
    79  		labelSet[APILabelKeyPrefix+hash] = "provided"
    80  	}
    81  	for key := range surface.RequiredAPIs.StripPlural() {
    82  		hash, err := cache.APIKeyToGVKHash(key)
    83  		if err != nil {
    84  			return nil, err
    85  		}
    86  		labelSet[APILabelKeyPrefix+hash] = "required"
    87  	}
    88  
    89  	return []labels.Set{labelSet}, nil
    90  }
    91  
    92  func labelSetsForCRDv1beta1(crd *extv1beta1.CustomResourceDefinition) ([]labels.Set, error) {
    93  	labelSets := []labels.Set{}
    94  	if crd == nil {
    95  		return labelSets, nil
    96  	}
    97  
    98  	// Add label sets for each version
    99  	for _, version := range crd.Spec.Versions {
   100  		hash, err := cache.APIKeyToGVKHash(opregistry.APIKey{
   101  			Group:   crd.Spec.Group,
   102  			Version: version.Name,
   103  			Kind:    crd.Spec.Names.Kind,
   104  		})
   105  		if err != nil {
   106  			return nil, err
   107  		}
   108  		key := APILabelKeyPrefix + hash
   109  		sets := []labels.Set{
   110  			{
   111  				key: "provided",
   112  			},
   113  			{
   114  				key: "required",
   115  			},
   116  		}
   117  		labelSets = append(labelSets, sets...)
   118  	}
   119  
   120  	return labelSets, nil
   121  }
   122  
   123  func labelSetsForCRDv1(crd *extv1.CustomResourceDefinition) ([]labels.Set, error) {
   124  	labelSets := []labels.Set{}
   125  	if crd == nil {
   126  		return labelSets, nil
   127  	}
   128  
   129  	// Add label sets for each version
   130  	for _, version := range crd.Spec.Versions {
   131  		hash, err := cache.APIKeyToGVKHash(opregistry.APIKey{
   132  			Group:   crd.Spec.Group,
   133  			Version: version.Name,
   134  			Kind:    crd.Spec.Names.Kind,
   135  		})
   136  		if err != nil {
   137  			return nil, err
   138  		}
   139  		key := APILabelKeyPrefix + hash
   140  		sets := []labels.Set{
   141  			{
   142  				key: "provided",
   143  			},
   144  			{
   145  				key: "required",
   146  			},
   147  		}
   148  		labelSets = append(labelSets, sets...)
   149  	}
   150  
   151  	return labelSets, nil
   152  }