Skip to content

Commit 698c231

Browse files
Merge pull request #285 from perdasilva/sync_04_11
Sync 04 11
2 parents ed7cf0d + 20fee7f commit 698c231

File tree

7 files changed

+259
-72
lines changed

7 files changed

+259
-72
lines changed

staging/operator-lifecycle-manager/Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,10 +279,13 @@ uninstall:
279279
- kubectl delete clusterroles.rbac.authorization.k8s.io "system:controller:operator-lifecycle-manager"
280280
- kubectl delete clusterrolebindings.rbac.authorization.k8s.io "olm-operator-binding-openshift-operator-lifecycle-manager"
281281

282-
.PHONY: run-local
283-
run-local: build-linux build-wait build-util-linux
282+
.PHONY: build-local
283+
build-local: build-linux build-wait build-util-linux
284284
rm -rf build
285285
. ./scripts/build_local.sh
286+
287+
.PHONY: run-local
288+
run-local: build-local
286289
mkdir -p build/resources
287290
. ./scripts/package_release.sh 1.0.0 build/resources doc/install/local-values.yaml
288291
. ./scripts/install_local.sh $(LOCAL_NAMESPACE) build/resources

staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -727,10 +727,15 @@ func (o *Operator) syncRegistryServer(logger *logrus.Entry, in *v1alpha1.Catalog
727727

728728
// requeue the catalog sync based on the polling interval, for accurate syncs of catalogs with polling enabled
729729
if out.Spec.UpdateStrategy != nil {
730-
logger.Debugf("requeuing registry server sync based on polling interval %s", out.Spec.UpdateStrategy.Interval.Duration.String())
731-
resyncPeriod := reconciler.SyncRegistryUpdateInterval(out, time.Now())
732-
o.catsrcQueueSet.RequeueAfter(out.GetNamespace(), out.GetName(), queueinformer.ResyncWithJitter(resyncPeriod, 0.1)())
733-
return
730+
if out.Spec.UpdateStrategy.RegistryPoll != nil {
731+
if out.Spec.UpdateStrategy.RegistryPoll.ParsingError != "" && out.Status.Reason != v1alpha1.CatalogSourceIntervalInvalidError {
732+
out.SetError(v1alpha1.CatalogSourceIntervalInvalidError, fmt.Errorf(out.Spec.UpdateStrategy.RegistryPoll.ParsingError))
733+
}
734+
logger.Debugf("requeuing registry server sync based on polling interval %s", out.Spec.UpdateStrategy.Interval.Duration.String())
735+
resyncPeriod := reconciler.SyncRegistryUpdateInterval(out, time.Now())
736+
o.catsrcQueueSet.RequeueAfter(out.GetNamespace(), out.GetName(), queueinformer.ResyncWithJitter(resyncPeriod, 0.1)())
737+
return
738+
}
734739
}
735740

736741
if err := o.sources.Remove(sourceKey); err != nil {

staging/operator-lifecycle-manager/pkg/controller/operators/decorators/operator.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,32 @@ func (o *Operator) ComponentLabelKey() (string, error) {
128128
return o.componentLabelKey, nil
129129
}
130130

131-
if o.GetName() == "" {
131+
name := o.GetName()
132+
if name == "" {
132133
return "", fmt.Errorf(componentLabelKeyError, "empty name field")
133134
}
134135

135-
name := o.GetName()
136136
if len(name) > 63 {
137137
// Truncate
138138
name = name[0:63]
139+
140+
// Remove trailing illegal characters
141+
idx := len(name) - 1
142+
for ; idx >= 0; idx-- {
143+
lastChar := name[idx]
144+
if lastChar != '.' && lastChar != '_' && lastChar != '-' {
145+
break
146+
}
147+
}
148+
149+
// Just being defensive. This is unlikely to happen since the operator name should
150+
// be compatible kubernetes naming constraints
151+
if idx < 0 {
152+
return "", fmt.Errorf(componentLabelKeyError, "unsupported name field")
153+
}
154+
155+
// Update Label
156+
name = name[0 : idx+1]
139157
}
140158
o.componentLabelKey = ComponentLabelKeyPrefix + name
141159

staging/operator-lifecycle-manager/pkg/controller/operators/decorators/operator_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,61 @@ func TestAddComponents(t *testing.T) {
231231
})
232232
}
233233
}
234+
235+
func TestComponentLabelKey(t *testing.T) {
236+
tests := []struct {
237+
description string
238+
componentLabelKey string
239+
name string
240+
expectedLabel string
241+
returnsError bool
242+
}{
243+
{
244+
description: "when componentLabelKey is set then return it",
245+
componentLabelKey: "my-component-label",
246+
name: "my-operator",
247+
expectedLabel: "my-component-label",
248+
returnsError: false,
249+
},
250+
{
251+
description: "when componentLabelKey is not set and operator name is less than 63 characters then do not truncate",
252+
componentLabelKey: "",
253+
name: "my-operator",
254+
expectedLabel: ComponentLabelKeyPrefix + "my-operator",
255+
returnsError: false,
256+
},
257+
{
258+
description: "when componentLabelKey is not set and operator name is more than 63 characters truncate",
259+
name: "this-is-my-operator-its-the-coolest-you-got-a-problem-with-that-come-at-me-bro",
260+
expectedLabel: ComponentLabelKeyPrefix + "this-is-my-operator-its-the-coolest-you-got-a-problem-with-that",
261+
returnsError: false,
262+
},
263+
{
264+
description: "when componentLabelKey is not set and operator name is more than 63 characters truncate and drop trailing illegal characters",
265+
name: "this-is-my-operator-its-the-coolest-you-got-a-problem-with----...---___...---",
266+
expectedLabel: ComponentLabelKeyPrefix + "this-is-my-operator-its-the-coolest-you-got-a-problem-with",
267+
returnsError: false,
268+
},
269+
{
270+
description: "when componentLabelKey is not set and operator name is more than 63 characters and is made up of illegal characters then return error",
271+
name: "----...---___...-------...---___...-------...---___...-------...---___...---",
272+
expectedLabel: "",
273+
returnsError: true,
274+
},
275+
}
276+
277+
for _, tt := range tests {
278+
operator := &Operator{
279+
Operator: &operatorsv1.Operator{
280+
ObjectMeta: metav1.ObjectMeta{
281+
Name: tt.name,
282+
},
283+
},
284+
componentLabelKey: tt.componentLabelKey,
285+
}
286+
287+
actualLabel, actualErr := operator.ComponentLabelKey()
288+
require.Equal(t, tt.returnsError, actualErr != nil, actualErr)
289+
require.Equal(t, tt.expectedLabel, actualLabel)
290+
}
291+
}

staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go

Lines changed: 138 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const (
4242
catsrcImage = "docker://quay.io/olmtest/catsrc-update-test:"
4343
)
4444

45-
var _ = Describe("Catalog represents a store of bundles which OLM can use to install Operators", func() {
45+
var _ = Describe("Starting CatalogSource e2e tests", func() {
4646
var (
4747
c operatorclient.ClientInterface
4848
crc versioned.Interface
@@ -1074,76 +1074,156 @@ var _ = Describe("Catalog represents a store of bundles which OLM can use to ins
10741074
Expect(err).ShouldNot(HaveOccurred())
10751075
Expect(csv.Spec.Replaces).To(Equal("busybox-dependency.v1.0.0"))
10761076
})
1077-
It("registry polls on the correct interval", func() {
1078-
// Create a catalog source with polling enabled
1079-
// Confirm the following
1080-
// a) the new update pod is spun up roughly in line with the registry polling interval
1081-
// b) the update pod is removed quickly when the image is found to not have changed
1082-
// This is more of a behavioral test that ensures the feature is working as designed.
1083-
1084-
c := newKubeClient()
1085-
crc := newCRClient()
1077+
When("A catalogSource is created with correct polling interval", func() {
10861078

1079+
var source *v1alpha1.CatalogSource
1080+
singlePod := podCount(1)
10871081
sourceName := genName("catalog-")
1088-
source := &v1alpha1.CatalogSource{
1089-
TypeMeta: metav1.TypeMeta{
1090-
Kind: v1alpha1.CatalogSourceKind,
1091-
APIVersion: v1alpha1.CatalogSourceCRDAPIVersion,
1092-
},
1093-
ObjectMeta: metav1.ObjectMeta{
1094-
Name: sourceName,
1095-
Namespace: ns.GetName(),
1096-
Labels: map[string]string{"olm.catalogSource": sourceName},
1097-
},
1098-
Spec: v1alpha1.CatalogSourceSpec{
1099-
SourceType: v1alpha1.SourceTypeGrpc,
1100-
Image: "quay.io/olmtest/catsrc-update-test:new",
1101-
UpdateStrategy: &v1alpha1.UpdateStrategy{
1102-
RegistryPoll: &v1alpha1.RegistryPoll{
1103-
RawInterval: "45s",
1082+
1083+
BeforeEach(func() {
1084+
source = &v1alpha1.CatalogSource{
1085+
TypeMeta: metav1.TypeMeta{
1086+
Kind: v1alpha1.CatalogSourceKind,
1087+
APIVersion: v1alpha1.CatalogSourceCRDAPIVersion,
1088+
},
1089+
ObjectMeta: metav1.ObjectMeta{
1090+
Name: sourceName,
1091+
Namespace: testNamespace,
1092+
Labels: map[string]string{"olm.catalogSource": sourceName},
1093+
},
1094+
Spec: v1alpha1.CatalogSourceSpec{
1095+
SourceType: v1alpha1.SourceTypeGrpc,
1096+
Image: "quay.io/olmtest/catsrc-update-test:new",
1097+
UpdateStrategy: &v1alpha1.UpdateStrategy{
1098+
RegistryPoll: &v1alpha1.RegistryPoll{
1099+
RawInterval: "45s",
1100+
},
11041101
},
11051102
},
1106-
},
1107-
}
1103+
}
11081104

1109-
source, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Create(context.Background(), source, metav1.CreateOptions{})
1110-
Expect(err).ToNot(HaveOccurred())
1105+
source, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Create(context.TODO(), source, metav1.CreateOptions{})
1106+
Expect(err).ToNot(HaveOccurred())
11111107

1112-
// wait for new catalog source pod to be created and report ready
1113-
selector := labels.SelectorFromSet(map[string]string{"olm.catalogSource": source.GetName()})
1114-
singlePod := podCount(1)
1115-
catalogPods, err := awaitPods(GinkgoT(), c, source.GetNamespace(), selector.String(), singlePod)
1116-
Expect(err).ToNot(HaveOccurred())
1117-
Expect(catalogPods).ToNot(BeNil())
1108+
// wait for new catalog source pod to be created and report ready
1109+
selector := labels.SelectorFromSet(map[string]string{"olm.catalogSource": source.GetName()})
11181110

1119-
Eventually(func() (bool, error) {
1120-
podList, err := c.KubernetesInterface().CoreV1().Pods(source.GetNamespace()).List(context.Background(), metav1.ListOptions{LabelSelector: selector.String()})
1121-
if err != nil {
1122-
return false, err
1123-
}
1111+
catalogPods, err := awaitPods(GinkgoT(), c, source.GetNamespace(), selector.String(), singlePod)
1112+
Expect(err).ToNot(HaveOccurred())
1113+
Expect(catalogPods).ToNot(BeNil())
1114+
1115+
Eventually(func() (bool, error) {
1116+
podList, err := c.KubernetesInterface().CoreV1().Pods(source.GetNamespace()).List(context.TODO(), metav1.ListOptions{LabelSelector: selector.String()})
1117+
if err != nil {
1118+
return false, err
1119+
}
11241120

1125-
for _, p := range podList.Items {
1126-
if podReady(&p) {
1127-
return true, nil
1121+
for _, p := range podList.Items {
1122+
if podReady(&p) {
1123+
return true, nil
1124+
}
1125+
return false, nil
11281126
}
1127+
11291128
return false, nil
1130-
}
1129+
}).Should(BeTrue())
1130+
})
11311131

1132-
return false, nil
1133-
}).Should(BeTrue())
1132+
It("registry polls on the correct interval", func() {
1133+
// Wait roughly the polling interval for update pod to show up
1134+
updateSelector := labels.SelectorFromSet(map[string]string{"catalogsource.operators.coreos.com/update": source.GetName()})
1135+
updatePods, err := awaitPodsWithInterval(GinkgoT(), c, source.GetNamespace(), updateSelector.String(), 5*time.Second, 2*time.Minute, singlePod)
1136+
Expect(err).ToNot(HaveOccurred())
1137+
Expect(updatePods).ToNot(BeNil())
1138+
Expect(updatePods.Items).To(HaveLen(1))
1139+
1140+
// No update to image: update pod should be deleted quickly
1141+
noPod := podCount(0)
1142+
updatePods, err = awaitPodsWithInterval(GinkgoT(), c, source.GetNamespace(), updateSelector.String(), 1*time.Second, 30*time.Second, noPod)
1143+
Expect(err).ToNot(HaveOccurred())
1144+
Expect(updatePods.Items).To(HaveLen(0))
1145+
})
11341146

1135-
// Wait roughly the polling interval for update pod to show up
1136-
updateSelector := labels.SelectorFromSet(map[string]string{"catalogsource.operators.coreos.com/update": source.GetName()})
1137-
updatePods, err := awaitPodsWithInterval(GinkgoT(), c, source.GetNamespace(), updateSelector.String(), 5*time.Second, 2*time.Minute, singlePod)
1138-
Expect(err).ToNot(HaveOccurred())
1139-
Expect(updatePods).ToNot(BeNil())
1140-
Expect(updatePods.Items).To(HaveLen(1))
1147+
})
11411148

1142-
// No update to image: update pod should be deleted quickly
1143-
noPod := podCount(0)
1144-
updatePods, err = awaitPodsWithInterval(GinkgoT(), c, source.GetNamespace(), updateSelector.String(), 1*time.Second, 30*time.Second, noPod)
1145-
Expect(err).ToNot(HaveOccurred())
1146-
Expect(updatePods.Items).To(HaveLen(0))
1149+
When("A catalogSource is created with incorrect polling interval", func() {
1150+
1151+
var (
1152+
source *v1alpha1.CatalogSource
1153+
sourceName string
1154+
)
1155+
const (
1156+
incorrectInterval = "45mError.code"
1157+
correctInterval = "45m"
1158+
)
1159+
BeforeEach(func() {
1160+
sourceName = genName("catalog-")
1161+
source = &v1alpha1.CatalogSource{
1162+
TypeMeta: metav1.TypeMeta{
1163+
Kind: v1alpha1.CatalogSourceKind,
1164+
APIVersion: v1alpha1.CatalogSourceCRDAPIVersion,
1165+
},
1166+
ObjectMeta: metav1.ObjectMeta{
1167+
Name: sourceName,
1168+
Namespace: testNamespace,
1169+
Labels: map[string]string{"olm.catalogSource": sourceName},
1170+
},
1171+
Spec: v1alpha1.CatalogSourceSpec{
1172+
SourceType: v1alpha1.SourceTypeGrpc,
1173+
Image: "quay.io/olmtest/catsrc-update-test:new",
1174+
UpdateStrategy: &v1alpha1.UpdateStrategy{
1175+
RegistryPoll: &v1alpha1.RegistryPoll{
1176+
RawInterval: incorrectInterval,
1177+
},
1178+
},
1179+
},
1180+
}
1181+
1182+
_, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Create(context.TODO(), source, metav1.CreateOptions{})
1183+
Expect(err).ToNot(HaveOccurred())
1184+
1185+
})
1186+
AfterEach(func() {
1187+
err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Delete(context.TODO(), source.GetName(), metav1.DeleteOptions{})
1188+
Expect(err).ToNot(HaveOccurred())
1189+
})
1190+
It("the catalogsource status communicates that a default interval time is being used instead", func() {
1191+
Eventually(func() bool {
1192+
catsrc, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Get(context.TODO(), source.GetName(), metav1.GetOptions{})
1193+
Expect(err).ToNot(HaveOccurred())
1194+
if catsrc.Status.Reason == v1alpha1.CatalogSourceIntervalInvalidError {
1195+
if catsrc.Status.Message == "error parsing spec.updateStrategy.registryPoll.interval. Using the default value of 15m0s instead. Error: time: unknown unit \"mError\" in duration \"45mError.code\"" {
1196+
return true
1197+
}
1198+
}
1199+
return false
1200+
}).Should(BeTrue())
1201+
})
1202+
When("the catalogsource is updated with a valid polling interval", func() {
1203+
BeforeEach(func() {
1204+
catsrc, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Get(context.TODO(), source.GetName(), metav1.GetOptions{})
1205+
Expect(err).ToNot(HaveOccurred())
1206+
catsrc.Spec.UpdateStrategy.RegistryPoll.RawInterval = correctInterval
1207+
_, err = crc.OperatorsV1alpha1().CatalogSources(catsrc.GetNamespace()).Update(context.TODO(), catsrc, metav1.UpdateOptions{})
1208+
Expect(err).ToNot(HaveOccurred())
1209+
})
1210+
It("the catalogsource spec shows the updated polling interval, and the error message in the status is cleared", func() {
1211+
Eventually(func() error {
1212+
catsrc, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Get(context.TODO(), source.GetName(), metav1.GetOptions{})
1213+
if err != nil {
1214+
return err
1215+
}
1216+
expectedTime, err := time.ParseDuration(correctInterval)
1217+
if err != nil {
1218+
return err
1219+
}
1220+
if catsrc.Status.Reason != "" || (catsrc.Spec.UpdateStrategy.Interval != &metav1.Duration{expectedTime}) {
1221+
return err
1222+
}
1223+
return nil
1224+
}).Should(Succeed())
1225+
})
1226+
})
11471227
})
11481228

11491229
It("adding catalog template adjusts image used", func() {

vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)