Skip to content

Commit 5f6fcd1

Browse files
authored
Catalog switcher (#2281)
* Implement catalog switching proposal - implements catalog switching proposal See https://github.com/operator-framework/enhancements/blob/master/enhancements/automatic-catalog-switching-annotations.md - picks up v0.10.3 - change sed command in copy_crds.sh to be posix compliant The command + in sed is non-portable. The posix compliant version of this command is {1,} This change allows this script to run on a mac too (which uses BSD sed) See https://riptutorial.com/sed/topic/9436/bsd-macos-sed-vs--gnu-sed-vs--the-posix-sed-specification Note: GVK was implemented but disabled due to security concerns. Future versions will address these concerns Signed-off-by: John Hunkins <[email protected]> * Address review comments from ecordell - reorganize imports - change logging common case to debug Signed-off-by: John Hunkins <[email protected]> * removed all watcher related code - this is the commit that should be reviewed later when it comes time to re-enable the GVK code Signed-off-by: John Hunkins <[email protected]> * update vendor to remove dynamic lister code Signed-off-by: John Hunkins <[email protected]> * fix incorrect names and improper error usage - fix names that don't match Golang convention - fix misspelled package name - return nil for sync function casting Signed-off-by: John Hunkins <[email protected]> * change code block organization and add mutex Signed-off-by: John Hunkins <[email protected]> * remove all traces of GVK template feature - clean up every instance of the GVK templating feature - add last minute change for RWMutex instead of Mutex - this is the second commit that should be reviewed later when it comes time to re-enable the GVK code Signed-off-by: John Hunkins <[email protected]> * return status update errors and adjust logging Signed-off-by: John Hunkins <[email protected]> * address review comments - update logging for clarity - clean up code blocks - refactor catalogsource helper functions: - remove mutex - remove two step get/update* in preference to update* even though this may result in more "the object has been modified" errors - rename helper functions to clarify usage - clarify the update helper function docs Signed-off-by: John Hunkins <[email protected]>
1 parent 8b80f26 commit 5f6fcd1

File tree

21 files changed

+1920
-29
lines changed

21 files changed

+1920
-29
lines changed

cmd/catalog/main.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client"
1818
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalog"
19+
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalogtemplate"
1920
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
2021
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorstatus"
2122
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/server"
@@ -137,12 +138,20 @@ func main() {
137138
// Create a new instance of the operator.
138139
op, err := catalog.NewOperator(ctx, *kubeConfigPath, utilclock.RealClock{}, logger, *wakeupInterval, *configmapServerImage, *opmImage, *utilImage, *catalogNamespace, k8sscheme.Scheme, *installPlanTimeout, *bundleUnpackTimeout)
139140
if err != nil {
140-
log.Panicf("error configuring operator: %s", err.Error())
141+
log.Panicf("error configuring catalog operator: %s", err.Error())
142+
}
143+
144+
opCatalogTemplate, err := catalogtemplate.NewOperator(ctx, *kubeConfigPath, logger, *wakeupInterval, *catalogNamespace)
145+
if err != nil {
146+
log.Panicf("error configuring catalog template operator: %s", err.Error())
141147
}
142148

143149
op.Run(ctx)
144150
<-op.Ready()
145151

152+
opCatalogTemplate.Run(ctx)
153+
<-opCatalogTemplate.Ready()
154+
146155
if *writeStatusName != "" {
147156
operatorstatus.MonitorClusterStatus(*writeStatusName, op.AtLevel(), op.Done(), opClient, configClient, crClient)
148157
}

deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml

+47
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,53 @@ spec:
106106
status:
107107
type: object
108108
properties:
109+
conditions:
110+
description: Represents the state of a CatalogSource. Note that Message and Reason represent the original status information, which may be migrated to be conditions based in the future. Any new features introduced will use conditions.
111+
type: array
112+
items:
113+
description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
114+
type: object
115+
required:
116+
- lastTransitionTime
117+
- message
118+
- reason
119+
- status
120+
- type
121+
properties:
122+
lastTransitionTime:
123+
description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
124+
type: string
125+
format: date-time
126+
message:
127+
description: message is a human readable message indicating details about the transition. This may be an empty string.
128+
type: string
129+
maxLength: 32768
130+
observedGeneration:
131+
description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
132+
type: integer
133+
format: int64
134+
minimum: 0
135+
reason:
136+
description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
137+
type: string
138+
maxLength: 1024
139+
minLength: 1
140+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
141+
status:
142+
description: status of the condition, one of True, False, Unknown.
143+
type: string
144+
enum:
145+
- "True"
146+
- "False"
147+
- Unknown
148+
type:
149+
description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
150+
type: string
151+
maxLength: 316
152+
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
153+
x-kubernetes-list-map-keys:
154+
- type
155+
x-kubernetes-list-type: map
109156
configMapReference:
110157
type: object
111158
required:

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect
88
github.com/coreos/go-semver v0.3.0
99
github.com/davecgh/go-spew v1.1.1
10+
github.com/distribution/distribution v2.7.1+incompatible
1011
github.com/fsnotify/fsnotify v1.4.9
1112
github.com/ghodss/yaml v1.0.0
1213
github.com/go-bindata/go-bindata/v3 v3.1.3
@@ -24,7 +25,7 @@ require (
2425
github.com/onsi/gomega v1.13.0
2526
github.com/openshift/api v0.0.0-20200331152225-585af27e34fd
2627
github.com/openshift/client-go v0.0.0-20200326155132-2a6cd50aedd0
27-
github.com/operator-framework/api v0.10.2
28+
github.com/operator-framework/api v0.10.3
2829
github.com/operator-framework/operator-registry v1.17.5
2930
github.com/otiai10/copy v1.2.0
3031
github.com/pkg/errors v0.9.1

go.sum

+7-2
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11
256256
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
257257
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
258258
github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc=
259+
github.com/distribution/distribution v2.7.1+incompatible h1:aGFx4EvJWKEh//lHPLwFhFgwFHKH06TzNVPamrMn04M=
260+
github.com/distribution/distribution v2.7.1+incompatible/go.mod h1:EgLm2NgWtdKgzF9NpMzUKgzmR7AMmb0VQi2B+ZzDRjc=
259261
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
260262
github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
261263
github.com/docker/cli v20.10.5+incompatible h1:bjflayQbWg+xOkF2WPEAOi4Y7zWhR7ptoPhV/VqLVDE=
@@ -876,8 +878,8 @@ github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJ
876878
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
877879
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
878880
github.com/operator-framework/api v0.7.1/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY=
879-
github.com/operator-framework/api v0.10.2 h1:fo8Bhyx1v46NdJIz2rUzfzNUpe1KDNPtVpHVpuxZnk0=
880-
github.com/operator-framework/api v0.10.2/go.mod h1:tV0BUNvly7szq28ZPBXhjp1Sqg5yHCOeX19ui9K4vjI=
881+
github.com/operator-framework/api v0.10.3 h1:C4DE7Rr3+ztUw3mKiFyfAiUJSVOty/cJmpwE90/kYro=
882+
github.com/operator-framework/api v0.10.3/go.mod h1:tV0BUNvly7szq28ZPBXhjp1Sqg5yHCOeX19ui9K4vjI=
881883
github.com/operator-framework/operator-registry v1.17.5 h1:LR8m1rFz5Gcyje8WK6iYt+gIhtzqo52zMRALdmTYHT0=
882884
github.com/operator-framework/operator-registry v1.17.5/go.mod h1:sRQIgDMZZdUcmHltzyCnM6RUoDF+WS8Arj1BQIARDS8=
883885
github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k=
@@ -1619,6 +1621,7 @@ k8s.io/api v0.21.2/go.mod h1:Lv6UGJZ1rlMI1qusN8ruAp9PUBFyBwpEHAdG24vIsiU=
16191621
k8s.io/api v0.22.0-rc.0 h1:LcnCE0nmb2CVpvmlbHkIzjZUHcVpSoNcn8mJkIo4FoQ=
16201622
k8s.io/api v0.22.0-rc.0/go.mod h1:EUcKB6RvpW74HMRUSSNwpUzrIHBdGT1FeAvOV+txic0=
16211623
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
1624+
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
16221625
k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk=
16231626
k8s.io/apiextensions-apiserver v0.20.6/go.mod h1:qO8YMqeMmZH+lV21LUNzV41vfpoE9QVAJRA+MNqj0mo=
16241627
k8s.io/apiextensions-apiserver v0.21.0/go.mod h1:gsQGNtGkc/YoDG9loKI0V+oLZM4ljRPjc/sql5tmvzc=
@@ -1638,6 +1641,7 @@ k8s.io/apimachinery v0.21.2/go.mod h1:CdTY8fU/BlvAbJ2z/8kBwimGki5Zp8/fbVuLY8gJum
16381641
k8s.io/apimachinery v0.22.0-rc.0 h1:boMGWXiuYJl4sAEMTEyWJtX4VLEPf0LZ0nUh+vNALIg=
16391642
k8s.io/apimachinery v0.22.0-rc.0/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0=
16401643
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
1644+
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
16411645
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
16421646
k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
16431647
k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
@@ -1670,6 +1674,7 @@ k8s.io/code-generator v0.21.2/go.mod h1:8mXJDCB7HcRo1xiEQstcguZkbxZaqeUOrO9SsicW
16701674
k8s.io/code-generator v0.22.0-rc.0 h1:8ZPtFa3yhlV5mz8DpLZYe7FetNH4qtZGkrDnkl2G1MU=
16711675
k8s.io/code-generator v0.22.0-rc.0/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o=
16721676
k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
1677+
k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM=
16731678
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
16741679
k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
16751680
k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=

pkg/controller/operators/catalog/operator.go

+7-22
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import (
5656
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler"
5757
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver"
5858
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/solver"
59+
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/catalogsource"
5960
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/clients"
6061
controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client"
6162
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/event"
@@ -600,9 +601,11 @@ func validateSourceType(logger *logrus.Entry, in *v1alpha1.CatalogSource) (out *
600601
return
601602
}
602603

603-
// The sourceType is valid, clear (all) status if there's existing invalid spec reason
604+
// The sourceType is valid, clear all status (other than status conditions array) if there's existing invalid spec reason
604605
if out.Status.Reason == v1alpha1.CatalogSourceSpecInvalidError {
605-
out.Status = v1alpha1.CatalogSourceStatus{}
606+
out.Status = v1alpha1.CatalogSourceStatus{
607+
Conditions: out.Status.Conditions,
608+
}
606609
}
607610
continueSync = true
608611

@@ -808,7 +811,7 @@ func (o *Operator) syncCatalogSources(obj interface{}) (syncError error) {
808811
catsrc, ok := obj.(*v1alpha1.CatalogSource)
809812
if !ok {
810813
o.logger.Debugf("wrong type: %#v", obj)
811-
syncError = fmt.Errorf("casting CatalogSource failed")
814+
syncError = nil
812815
return
813816
}
814817

@@ -841,24 +844,6 @@ func (o *Operator) syncCatalogSources(obj interface{}) (syncError error) {
841844
return reflect.DeepEqual(a, b)
842845
}
843846

844-
updateStatusFunc := func(catsrc *v1alpha1.CatalogSource) error {
845-
latest, err := o.client.OperatorsV1alpha1().CatalogSources(catsrc.GetNamespace()).Get(context.TODO(), catsrc.GetName(), metav1.GetOptions{})
846-
if err != nil {
847-
logger.Errorf("error getting catalogsource - %v", err)
848-
return err
849-
}
850-
851-
out := latest.DeepCopy()
852-
out.Status = catsrc.Status
853-
854-
if _, err := o.client.OperatorsV1alpha1().CatalogSources(out.GetNamespace()).UpdateStatus(context.TODO(), out, metav1.UpdateOptions{}); err != nil {
855-
logger.Errorf("error while setting catalogsource status condition - %v", err)
856-
return err
857-
}
858-
859-
return nil
860-
}
861-
862847
chain := []CatalogSourceSyncFunc{
863848
validateSourceType,
864849
o.syncConfigMap,
@@ -879,7 +864,7 @@ func (o *Operator) syncCatalogSources(obj interface{}) (syncError error) {
879864
return
880865
}
881866

882-
updateErr := updateStatusFunc(out)
867+
updateErr := catalogsource.UpdateStatus(logger, o.client, out)
883868
if syncError == nil && updateErr != nil {
884869
syncError = updateErr
885870
}

0 commit comments

Comments
 (0)