Skip to content

Commit 8b04080

Browse files
committed
fix(olm): use hashes for provided api labels
1 parent 9ee66d0 commit 8b04080

File tree

10 files changed

+83
-42
lines changed

10 files changed

+83
-42
lines changed

Documentation/install/local-values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
installType: "upstream"
1+
installType: upstream
22
rbacApiVersion: rbac.authorization.k8s.io
33
namespace: local
44
writeStatusName: '""'

deploy/chart/values.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
installType: upstream
12
rbacApiVersion: rbac.authorization.k8s.io
23
namespace: operator-lifecycle-manager
34
catalog_namespace: operator-lifecycle-manager
@@ -18,7 +19,7 @@ olm:
1819

1920
catalog:
2021
replicaCount: 1
21-
commandArgs: -configmapServerImage=quay.io/operatorframework/configmap-operator-registry:latest
22+
commandArgs: -configmapServerImage=quay.io/operator-framework/configmap-operator-registry:latest
2223
image:
2324
ref: quay.io/operator-framework/olm:master
2425
pullPolicy: Always

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require (
1313
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
1414
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef // indirect
1515
github.com/golang/mock v1.1.1
16+
github.com/google/btree v1.0.0 // indirect
1617
github.com/gregjones/httpcache v0.0.0-20181110185634-c63ab54fda8f // indirect
1718
github.com/grpc-ecosystem/grpc-gateway v1.7.0 // indirect
1819
github.com/json-iterator/go v1.1.6 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
7373
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
7474
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
7575
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
76+
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
77+
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
7678
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
7779
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
7880
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

pkg/controller/operators/olm/operator.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,9 @@ func (a *Operator) syncObject(obj interface{}) (syncError error) {
335335
}
336336

337337
// Requeue CSVs with provided and required labels (for CRDs)
338-
if labelSets := a.apiLabeler.LabelSetsFor(metaObj); len(labelSets) > 0 {
338+
if labelSets, err := a.apiLabeler.LabelSetsFor(metaObj); err != nil {
339+
logger.WithError(err).Warn("couldn't create label set")
340+
} else if len(labelSets) > 0 {
339341
logger.Debug("requeueing providing/requiring csvs")
340342
a.requeueCSVsByLabelSet(logger, labelSets...)
341343
}
@@ -757,16 +759,19 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
757759
}
758760

759761
// Ensure required and provided API labels
760-
updated, err := a.ensureLabels(out, a.apiLabeler.LabelSetsFor(operatorSurface)...)
761-
if err != nil {
762-
logger.WithError(err).Warn("issue ensuring csv api labels")
763-
syncError = err
764-
return
762+
if labelSets, err := a.apiLabeler.LabelSetsFor(operatorSurface); err != nil {
763+
logger.WithError(err).Warn("couldn't create label set")
764+
} else if len(labelSets) > 0 {
765+
updated, err := a.ensureLabels(out, labelSets...)
766+
if err != nil {
767+
logger.WithError(err).Warn("issue ensuring csv api labels")
768+
syncError = err
769+
return
770+
}
771+
// Update the underlying value of out to preserve changes
772+
*out = *updated
765773
}
766774

767-
// Update the underlying value of out to preserve changes
768-
*out = *updated
769-
770775
// Check if the current CSV is being replaced, return with replacing status if so
771776
if err := a.checkReplacementsAndUpdateStatus(out); err != nil {
772777
logger.WithError(err).Info("replacement check")
@@ -1318,7 +1323,9 @@ func (a *Operator) handleDeletion(obj interface{}) {
13181323
a.requeueOwnerCSVs(metaObj)
13191324

13201325
// Requeue CSVs with provided and required labels (for CRDs)
1321-
if labelSets := a.apiLabeler.LabelSetsFor(metaObj); len(labelSets) > 0 {
1326+
if labelSets, err := a.apiLabeler.LabelSetsFor(metaObj); err != nil {
1327+
logger.WithError(err).Warn("couldn't create label set")
1328+
} else if len(labelSets) > 0 {
13221329
logger.Debug("requeueing providing/requiring csvs")
13231330
a.requeueCSVsByLabelSet(logger, labelSets...)
13241331
}

pkg/controller/operators/olm/operator_test.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"testing"
1616
"time"
1717

18-
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
18+
"github.com/operator-framework/operator-registry/pkg/registry"
1919
"github.com/sirupsen/logrus"
2020
"github.com/stretchr/testify/assert"
2121
"github.com/stretchr/testify/require"
@@ -39,6 +39,8 @@ import (
3939
apiregistrationfake "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake"
4040
kagg "k8s.io/kube-aggregator/pkg/client/informers/externalversions"
4141

42+
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
43+
4244
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
4345
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha2"
4446
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
@@ -740,6 +742,9 @@ func TestTransitionCSV(t *testing.T) {
740742
logrus.SetLevel(logrus.DebugLevel)
741743
namespace := "ns"
742744

745+
apiHash, err := resolver.APIKeyToGVKHash(registry.APIKey{Group: "g1", Version: "v1", Kind: "c1"})
746+
require.NoError(t, err)
747+
743748
defaultOperatorGroup := &v1alpha2.OperatorGroup{
744749
TypeMeta: metav1.TypeMeta{
745750
Kind: "OperatorGroup",
@@ -2349,7 +2354,7 @@ func TestTransitionCSV(t *testing.T) {
23492354
[]*v1beta1.CustomResourceDefinition{},
23502355
v1alpha1.CSVPhaseSucceeded,
23512356
), defaultTemplateAnnotations), labels.Set{
2352-
resolver.APILabelKeyPrefix + "c1.v1.g1": "provided",
2357+
resolver.APILabelKeyPrefix + apiHash: "provided",
23532358
}),
23542359
csvWithLabels(csvWithAnnotations(csv("csv1",
23552360
namespace,
@@ -2360,7 +2365,7 @@ func TestTransitionCSV(t *testing.T) {
23602365
[]*v1beta1.CustomResourceDefinition{},
23612366
v1alpha1.CSVPhaseReplacing,
23622367
), defaultTemplateAnnotations), labels.Set{
2363-
resolver.APILabelKeyPrefix + "c1.v1.g1": "provided",
2368+
resolver.APILabelKeyPrefix + apiHash: "provided",
23642369
}),
23652370
csvWithLabels(csvWithAnnotations(csv("csv2",
23662371
namespace,
@@ -2371,7 +2376,7 @@ func TestTransitionCSV(t *testing.T) {
23712376
[]*v1beta1.CustomResourceDefinition{},
23722377
v1alpha1.CSVPhaseReplacing,
23732378
), defaultTemplateAnnotations), labels.Set{
2374-
resolver.APILabelKeyPrefix + "c1.v1.g1": "provided",
2379+
resolver.APILabelKeyPrefix + apiHash: "provided",
23752380
}),
23762381
},
23772382
clientObjs: []runtime.Object{defaultOperatorGroup},
@@ -2891,7 +2896,7 @@ func TestSyncOperatorGroups(t *testing.T) {
28912896
[]*v1beta1.CustomResourceDefinition{crd},
28922897
[]*v1beta1.CustomResourceDefinition{},
28932898
v1alpha1.CSVPhaseNone,
2894-
), labels.Set{resolver.APILabelKeyPrefix + "c1.v1.fake.api.group": "provided"})
2899+
), labels.Set{resolver.APILabelKeyPrefix + "9f4c46c37bdff8d0": "provided"})
28952900

28962901
serverVersion := version.Get().String()
28972902
// after state transitions from operatorgroups, this is the operator csv we expect
Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package resolver
22

33
import (
4-
"fmt"
5-
4+
"github.com/operator-framework/operator-registry/pkg/registry"
65
extv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
76
"k8s.io/apimachinery/pkg/labels"
87
)
@@ -14,39 +13,54 @@ const (
1413

1514
// LabelSetsFor returns API label sets for the given object.
1615
// Concrete types other than OperatorSurface and CustomResource definition no-op.
17-
func LabelSetsFor(obj interface{}) []labels.Set {
18-
var labelSets []labels.Set
16+
func LabelSetsFor(obj interface{}) ([]labels.Set, error) {
1917
switch v := obj.(type) {
2018
case OperatorSurface:
21-
labelSets = labelSetsForOperatorSurface(v)
19+
return labelSetsForOperatorSurface(v)
2220
case *extv1beta1.CustomResourceDefinition:
23-
labelSets = labelSetsForCRD(v)
21+
return labelSetsForCRD(v)
22+
default:
23+
return nil, nil
2424
}
25-
26-
return labelSets
2725
}
2826

29-
func labelSetsForOperatorSurface(surface OperatorSurface) []labels.Set {
27+
func labelSetsForOperatorSurface(surface OperatorSurface) ([]labels.Set, error) {
3028
labelSet := labels.Set{}
3129
for key := range surface.ProvidedAPIs().StripPlural() {
32-
labelSet[APILabelKeyPrefix+APIKeyToGVKString(key)] = "provided"
30+
hash, err := APIKeyToGVKHash(key)
31+
if err != nil {
32+
return nil, err
33+
}
34+
labelSet[APILabelKeyPrefix+hash] = "provided"
3335
}
3436
for key := range surface.RequiredAPIs().StripPlural() {
35-
labelSet[APILabelKeyPrefix+APIKeyToGVKString(key)] = "required"
37+
hash, err := APIKeyToGVKHash(key)
38+
if err != nil {
39+
return nil, err
40+
}
41+
labelSet[APILabelKeyPrefix+hash] = "required"
3642
}
3743

38-
return []labels.Set{labelSet}
44+
return []labels.Set{labelSet}, nil
3945
}
4046

41-
func labelSetsForCRD(crd *extv1beta1.CustomResourceDefinition) []labels.Set {
47+
func labelSetsForCRD(crd *extv1beta1.CustomResourceDefinition) ([]labels.Set, error) {
4248
labelSets := []labels.Set{}
4349
if crd == nil {
44-
return labelSets
50+
return labelSets, nil
4551
}
4652

4753
// Add label sets for each version
4854
for _, version := range crd.Spec.Versions {
49-
key := fmt.Sprintf("%s%s.%s.%s", APILabelKeyPrefix, crd.Spec.Names.Kind, version.Name, crd.Spec.Group)
55+
hash, err := APIKeyToGVKHash(registry.APIKey{
56+
Group: crd.Spec.Group,
57+
Version: version.Name,
58+
Kind: crd.Spec.Names.Kind,
59+
})
60+
if err != nil {
61+
return nil, err
62+
}
63+
key := APILabelKeyPrefix + hash
5064
sets := []labels.Set{
5165
{
5266
key: "provided",
@@ -58,5 +72,5 @@ func labelSetsForCRD(crd *extv1beta1.CustomResourceDefinition) []labels.Set {
5872
labelSets = append(labelSets, sets...)
5973
}
6074

61-
return labelSets
75+
return labelSets, nil
6276
}

pkg/controller/registry/resolver/labeler_test.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ func TestLabelSetsFor(t *testing.T) {
3434
}),
3535
expected: []labels.Set{
3636
{
37-
APILabelKeyPrefix + "Ghost.v1alpha1.ghouls": "provided",
37+
APILabelKeyPrefix + "6435ab0d7c6bda64": "provided",
3838
},
3939
{
40-
APILabelKeyPrefix + "Ghost.v1alpha1.ghouls": "required",
40+
APILabelKeyPrefix + "6435ab0d7c6bda64": "required",
4141
},
4242
},
4343
},
@@ -50,7 +50,7 @@ func TestLabelSetsFor(t *testing.T) {
5050
},
5151
expected: []labels.Set{
5252
{
53-
APILabelKeyPrefix + "Ghost.v1alpha1.ghouls": "provided",
53+
APILabelKeyPrefix + "6435ab0d7c6bda64": "provided",
5454
},
5555
},
5656
},
@@ -66,15 +66,17 @@ func TestLabelSetsFor(t *testing.T) {
6666
},
6767
expected: []labels.Set{
6868
{
69-
APILabelKeyPrefix + "Ghost.v1alpha1.ghouls": "provided",
70-
APILabelKeyPrefix + "Goblin.v1alpha1.ghouls": "required",
69+
APILabelKeyPrefix + "6435ab0d7c6bda64": "provided",
70+
APILabelKeyPrefix + "557c9f42470aa352": "required",
7171
},
7272
},
7373
},
7474
}
7575
for _, tt := range tests {
7676
t.Run(tt.name, func(t *testing.T) {
77-
require.ElementsMatch(t, tt.expected, LabelSetsFor(tt.obj))
77+
labelSets, err := LabelSetsFor(tt.obj)
78+
require.NoError(t, err)
79+
require.ElementsMatch(t, tt.expected, labelSets)
7880
})
7981
}
8082
}

pkg/controller/registry/resolver/operators.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package resolver
22

33
import (
44
"fmt"
5+
"hash/fnv"
56
"sort"
67
"strings"
78

@@ -58,6 +59,14 @@ func APIKeyToGVKString(key opregistry.APIKey) string {
5859
return strings.Join([]string{key.Kind, key.Version, key.Group}, ".")
5960
}
6061

62+
func APIKeyToGVKHash(key opregistry.APIKey) (string, error) {
63+
hash := fnv.New64a()
64+
if _, err := hash.Write([]byte(APIKeyToGVKString(key))); err != nil {
65+
return "", err
66+
}
67+
return fmt.Sprintf("%x", hash.Sum64()), nil
68+
}
69+
6170
func (s APISet) String() string {
6271
gvkStrs := make([]string, len(s))
6372
i := 0

pkg/lib/labeler/labeler.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import (
77
// Labeler can provide label sets that describe an object
88
type Labeler interface {
99
// LabelSetsFor returns label sets that describe the given object
10-
LabelSetsFor(obj interface{}) []labels.Set
10+
LabelSetsFor(obj interface{}) ([]labels.Set, error)
1111
}
1212

1313
// Func is a function type that implements the Labeler interface
14-
type Func func(obj interface{}) []labels.Set
14+
type Func func(obj interface{}) ([]labels.Set, error)
1515

1616
// LabelSetsFor calls LabelSetsFor on itself to satisfy the Labeler interface
17-
func (l Func) LabelSetsFor(obj interface{}) []labels.Set {
17+
func (l Func) LabelSetsFor(obj interface{}) ([]labels.Set, error) {
1818
return l(obj)
1919
}

0 commit comments

Comments
 (0)