Skip to content

Commit d75ca3b

Browse files
committed
fix: refactor catalog polling spec to use more general update strategy field
1 parent 2b93a4b commit d75ca3b

File tree

13 files changed

+231
-98
lines changed

13 files changed

+231
-98
lines changed

deploy/chart/templates/0000_50_olm_06-catalogsource.crd.yaml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,6 @@ spec:
9797
a registry-server with. Only used when SourceType = SourceTypeGrpc.
9898
If present, the address field is ignored.
9999
type: string
100-
poll:
101-
description: Poll is used to determine the time interval between checks
102-
of the latest catalog source version. The catalog operator polls to
103-
see if a new version of the catalog source is available. If available,
104-
the latest image is pulled and gRPC traffic is directed to the latest
105-
catalog source.
106-
type: object
107-
properties:
108-
interval:
109-
type: string
110100
publisher:
111101
type: string
112102
secrets:
@@ -119,6 +109,22 @@ spec:
119109
sourceType:
120110
description: SourceType is the type of source
121111
type: string
112+
updateStrategy:
113+
description: UpdateStrategy defines how updated catalog source images
114+
can be discovered Consists of an interval that defines polling duration
115+
and an embedded strategy type
116+
type: object
117+
properties:
118+
registryPoll:
119+
type: object
120+
properties:
121+
interval:
122+
description: Interval is used to determine the time interval
123+
between checks of the latest catalog source version. The catalog
124+
operator polls to see if a new version of the catalog source
125+
is available. If available, the latest image is pulled and
126+
gRPC traffic is directed to the latest catalog source.
127+
type: string
122128
status:
123129
type: object
124130
properties:

doc/design/catalog-polling.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ This is the latest version of the X operator in the catalog source. Lets say Ope
1111
to include the v2.0 version of the X operator and pushed to the same `master` tag. With catalog polling enabled, OLM will pull down the newer version
1212
of the catalog source image and route service traffic to the newer pod. The existing subscription will seamlessly create the v2.0 operator and remove the old v1.0 one.
1313

14+
Each type of check for an updated catalog source is called an `updateStrategy`. Only one `updateStrategy` is supported at a time.
15+
`registryPoll` is a type of `updateStrategy` that checks an image registry for an updated version of the same tag. The `interval` defines
16+
the amount of time between each successive poll.
17+
1418
## Example Spec
1519
Here is an example catalog source that polls `quay.io/my-catalogs/my-catalog:master` every 45 minutes to see if the image has been updated.
1620

@@ -23,8 +27,9 @@ spec:
2327
displayName: CatalogSource Test
2428
sourceType: grpc
2529
image: quay.io/my-catalogs/my-catalog:master
26-
poll:
27-
interval: 45m
30+
updateStrategy:
31+
registryPoll:
32+
interval: 2m
2833
```
2934
3035
It is required for the catalog source to be sourceType grpc and be backed by an image for polling to work.
@@ -33,4 +38,7 @@ It is required for the catalog source to be sourceType grpc and be backed by an
3338
* The polling sequence is not instantaneous - it can take up to 15 minutes from each poll for the new catalog source pod to be deployed
3439
into the cluster. It may take longer for larger clusters.
3540
* Because OLM pulls down the image every poll interval and starts the pod, to see if its updated, the updated catalog pod must be able to be
36-
scheduled onto the cluster. If the cluster is at absolutely maximum capacity, without autoscaling enabled, this feature may not work.
41+
scheduled onto the cluster. If the cluster is at absolutely maximum capacity, without autoscaling enabled, this feature may not work.
42+
* OLM checks to see whether the container ImageID has changed between the old and new catalog source image when determining if an upgrade
43+
is in order. It does not actually parse the image content itself to check for later CSVs. If there is a bad upgrade to the catalog source image,
44+
simply overwrite the tag with another version and it will be pulled down, or delete and recreate the catalog source.

manifests/0000_50_olm_06-catalogsource.crd.yaml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,6 @@ spec:
9797
a registry-server with. Only used when SourceType = SourceTypeGrpc.
9898
If present, the address field is ignored.
9999
type: string
100-
poll:
101-
description: Poll is used to determine the time interval between checks
102-
of the latest catalog source version. The catalog operator polls to
103-
see if a new version of the catalog source is available. If available,
104-
the latest image is pulled and gRPC traffic is directed to the latest
105-
catalog source.
106-
type: object
107-
properties:
108-
interval:
109-
type: string
110100
publisher:
111101
type: string
112102
secrets:
@@ -119,6 +109,22 @@ spec:
119109
sourceType:
120110
description: SourceType is the type of source
121111
type: string
112+
updateStrategy:
113+
description: UpdateStrategy defines how updated catalog source images
114+
can be discovered Consists of an interval that defines polling duration
115+
and an embedded strategy type
116+
type: object
117+
properties:
118+
registryPoll:
119+
type: object
120+
properties:
121+
interval:
122+
description: Interval is used to determine the time interval
123+
between checks of the latest catalog source version. The catalog
124+
operator polls to see if a new version of the catalog source
125+
is available. If available, the latest image is pulled and
126+
gRPC traffic is directed to the latest catalog source.
127+
type: string
122128
status:
123129
type: object
124130
properties:

pkg/api/apis/operators/catalogsource_types.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,10 @@ type CatalogSourceSpec struct {
4747
// +Optional
4848
Image string
4949

50-
// Poll is used to determine the time interval between checks of the latest catalog source version.
51-
// The catalog operator polls to see if a new version of the catalog source is available.
52-
// If available, the latest image is pulled and gRPC traffic is directed to the latest catalog source.
50+
// UpdateStrategy defines how updated catalog source images can be discovered
51+
// Consists of an interval that defines polling duration and an embedded strategy type
5352
// +Optional
54-
Poll *Poll
53+
UpdateStrategy *UpdateStrategy
5554

5655
// Secrets represent set of secrets that can be used to access the contents of the catalog.
5756
// It is best to keep this list small, since each will need to be tried for every catalog entry.
@@ -65,8 +64,17 @@ type CatalogSourceSpec struct {
6564
Icon Icon
6665
}
6766

68-
type Poll struct {
69-
Interval metav1.Duration
67+
// UpdateStrategy holds all the different types of catalog source update strategies
68+
// Currently only registry polling strategy is implemented
69+
type UpdateStrategy struct {
70+
*RegistryPoll
71+
}
72+
73+
type RegistryPoll struct {
74+
// Interval is used to determine the time interval between checks of the latest catalog source version.
75+
// The catalog operator polls to see if a new version of the catalog source is available.
76+
// If available, the latest image is pulled and gRPC traffic is directed to the latest catalog source.
77+
Interval *metav1.Duration
7078
}
7179

7280
type RegistryServiceStatus struct {

pkg/api/apis/operators/v1alpha1/catalogsource_types.go

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,10 @@ type CatalogSourceSpec struct {
5555
// +Optional
5656
Image string `json:"image,omitempty"`
5757

58-
// Poll is used to determine the time interval between checks of the latest catalog source version.
59-
// The catalog operator polls to see if a new version of the catalog source is available.
60-
// If available, the latest image is pulled and gRPC traffic is directed to the latest catalog source.
58+
// UpdateStrategy defines how updated catalog source images can be discovered
59+
// Consists of an interval that defines polling duration and an embedded strategy type
6160
// +Optional
62-
Poll *Poll `json:"poll,omitempty"`
61+
UpdateStrategy *UpdateStrategy `json:"updateStrategy,omitempty"`
6362

6463
// Secrets represent set of secrets that can be used to access the contents of the catalog.
6564
// It is best to keep this list small, since each will need to be tried for every catalog entry.
@@ -73,8 +72,17 @@ type CatalogSourceSpec struct {
7372
Icon Icon `json:"icon,omitempty"`
7473
}
7574

76-
type Poll struct {
77-
Interval metav1.Duration `json:"interval,omitempty"`
75+
// UpdateStrategy holds all the different types of catalog source update strategies
76+
// Currently only registry polling strategy is implemented
77+
type UpdateStrategy struct {
78+
*RegistryPoll `json:"registryPoll,omitempty"`
79+
}
80+
81+
type RegistryPoll struct {
82+
// Interval is used to determine the time interval between checks of the latest catalog source version.
83+
// The catalog operator polls to see if a new version of the catalog source is available.
84+
// If available, the latest image is pulled and gRPC traffic is directed to the latest catalog source.
85+
Interval *metav1.Duration `json:"interval,omitempty"`
7886
}
7987

8088
type RegistryServiceStatus struct {
@@ -157,28 +165,26 @@ func (c *CatalogSource) SetLastUpdateTime() {
157165
}
158166

159167
// Check if it is time to update based on polling setting
160-
func (c *CatalogSource) ReadyToUpdate() bool {
161-
if !c.PollingEnabled() {
168+
func (c *CatalogSource) Update() bool {
169+
if !c.Poll() {
162170
return false
163171
}
164-
interval := c.Spec.Poll.Interval.Duration
165-
logrus.WithField("CatalogSource", c.Name).Infof("polling interval %v", interval)
172+
interval := c.Spec.UpdateStrategy.Interval.Duration
166173
latest := c.Status.LatestImageRegistryPoll
167174
if latest == nil {
168-
logrus.WithField("CatalogSource", c.Name).Infof("latest poll %v", latest)
175+
logrus.WithField("CatalogSource", c.Name).Debugf("latest poll %v", latest)
169176
} else {
170-
logrus.WithField("CatalogSource", c.Name).Infof("latest poll %v", *c.Status.LatestImageRegistryPoll)
177+
logrus.WithField("CatalogSource", c.Name).Debugf("latest poll %v", *c.Status.LatestImageRegistryPoll)
171178
}
172179

173180

174-
logrus.WithField("CatalogSource", c.Name).Infof("polling interval is zero %t", c.Status.LatestImageRegistryPoll.IsZero())
175181
if c.Status.LatestImageRegistryPoll.IsZero() {
176-
logrus.WithField("CatalogSource", c.Name).Infof("creation interval plus interval before now %t", c.CreationTimestamp.Add(interval).Before(time.Now()))
182+
logrus.WithField("CatalogSource", c.Name).Debugf("creation timestamp plus interval before now %t", c.CreationTimestamp.Add(interval).Before(time.Now()))
177183
if c.CreationTimestamp.Add(interval).Before(time.Now()) {
178184
return true
179185
}
180186
} else {
181-
logrus.WithField("CatalogSource", c.Name).Infof("latest poll plus interval before now %t", c.Status.LatestImageRegistryPoll.Add(interval).Before(time.Now()))
187+
logrus.WithField("CatalogSource", c.Name).Debugf("latest poll plus interval before now %t", c.Status.LatestImageRegistryPoll.Add(interval).Before(time.Now()))
182188
if c.Status.LatestImageRegistryPoll.Add(interval).Before(time.Now()) {
183189
return true
184190
}
@@ -187,10 +193,13 @@ func (c *CatalogSource) ReadyToUpdate() bool {
187193
return false
188194
}
189195

190-
// CatalogPollingEnabled determines whether the polling feature is enabled on the particular catalog source
191-
func (c *CatalogSource) PollingEnabled() bool {
196+
// Poll determines whether the polling feature is enabled on the particular catalog source
197+
func (c *CatalogSource) Poll() bool {
198+
if c.Spec.UpdateStrategy == nil {
199+
return false
200+
}
192201
// if polling interval is zero polling will not be done
193-
if c.Spec.Poll == nil {
202+
if c.Spec.UpdateStrategy.RegistryPoll == nil {
194203
return false
195204
}
196205
// if catalog source is not backed by an image polling will not be done

pkg/api/apis/operators/v1alpha1/types_test.go

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func TestOwnsCRD(t *testing.T) {
105105
}
106106
}
107107

108-
func TestCatalogSource_ReadyToUpdate(t *testing.T) {
108+
func TestCatalogSource_Update(t *testing.T) {
109109
var table = []struct {
110110
description string
111111
catsrc CatalogSource
@@ -117,7 +117,11 @@ func TestCatalogSource_ReadyToUpdate(t *testing.T) {
117117
catsrc: CatalogSource{
118118
ObjectMeta: metav1.ObjectMeta{CreationTimestamp: metav1.Time{Time: time.Now()}},
119119
Spec: CatalogSourceSpec{
120-
Poll: &Poll{Interval: metav1.Duration{Duration: 1 * time.Second}},
120+
UpdateStrategy: &UpdateStrategy{
121+
RegistryPoll: &RegistryPoll{
122+
Interval: &metav1.Duration{Duration: 1 * time.Second},
123+
},
124+
},
121125
Image: "mycatsrcimage",
122126
SourceType: SourceTypeGrpc},
123127
},
@@ -129,7 +133,11 @@ func TestCatalogSource_ReadyToUpdate(t *testing.T) {
129133
catsrc: CatalogSource{
130134
ObjectMeta: metav1.ObjectMeta{CreationTimestamp: metav1.Time{Time: time.Now()}},
131135
Spec: CatalogSourceSpec{
132-
Poll: &Poll{Interval: metav1.Duration{Duration: 1 * time.Second}},
136+
UpdateStrategy: &UpdateStrategy{
137+
RegistryPoll: &RegistryPoll{
138+
Interval: &metav1.Duration{Duration: 1 * time.Second},
139+
},
140+
},
133141
Image: "mycatsrcimage",
134142
SourceType: SourceTypeGrpc,
135143
},
@@ -143,7 +151,11 @@ func TestCatalogSource_ReadyToUpdate(t *testing.T) {
143151
catsrc: CatalogSource{
144152
ObjectMeta: metav1.ObjectMeta{CreationTimestamp: metav1.Time{Time: time.Now()}},
145153
Spec: CatalogSourceSpec{
146-
Poll: &Poll{Interval: metav1.Duration{Duration: 1 * time.Second}},
154+
UpdateStrategy: &UpdateStrategy{
155+
RegistryPoll: &RegistryPoll{
156+
Interval: &metav1.Duration{Duration: 1 * time.Second},
157+
},
158+
},
147159
Image: "mycatsrcimage",
148160
SourceType: SourceTypeGrpc,
149161
},
@@ -156,11 +168,11 @@ func TestCatalogSource_ReadyToUpdate(t *testing.T) {
156168

157169
for i, tt := range table {
158170
time.Sleep(table[i].sleep)
159-
require.Equal(t, tt.result, table[i].catsrc.ReadyToUpdate(), table[i].description)
171+
require.Equal(t, tt.result, table[i].catsrc.Update(), table[i].description)
160172
}
161173
}
162174

163-
func TestCatalogSource_PollingEnabled(t *testing.T) {
175+
func TestCatalogSource_Poll(t *testing.T) {
164176
var table = []struct {
165177
description string
166178
catsrc CatalogSource
@@ -182,14 +194,17 @@ func TestCatalogSource_PollingEnabled(t *testing.T) {
182194
catsrc: CatalogSource{Spec: CatalogSourceSpec{
183195
Image: "my-image",
184196
SourceType: SourceTypeGrpc,
185-
Poll: &Poll{Interval: metav1.Duration{
186-
Duration: 1 * time.Minute,
187-
}}},
197+
UpdateStrategy: &UpdateStrategy{
198+
RegistryPoll: &RegistryPoll{
199+
Interval: &metav1.Duration{Duration: 1 * time.Second},
200+
},
201+
},
202+
},
188203
},
189204
result: true,
190205
},
191206
}
192207
for i, tt := range table {
193-
require.Equal(t, tt.result, table[i].catsrc.PollingEnabled(), table[i].description)
208+
require.Equal(t, tt.result, table[i].catsrc.Poll(), table[i].description)
194209
}
195210
}

0 commit comments

Comments
 (0)