diff --git a/bootstrap/bootstrap-pod.yaml b/bootstrap/bootstrap-pod.yaml index 66db1e3e3..bc9374628 100644 --- a/bootstrap/bootstrap-pod.yaml +++ b/bootstrap/bootstrap-pod.yaml @@ -14,6 +14,7 @@ spec: - "start" - "--release-image={{.ReleaseImage}}" - "--enable-auto-update=false" + - "--enable-default-cluster-version=false" - "--v=4" - "--kubeconfig=/etc/kubernetes/kubeconfig" securityContext: diff --git a/cmd/start.go b/cmd/start.go index 0227baa89..20fae2301 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -28,6 +28,7 @@ func init() { cmd.PersistentFlags().StringVar(&opts.Kubeconfig, "kubeconfig", opts.Kubeconfig, "Kubeconfig file to access a remote cluster (testing only)") cmd.PersistentFlags().StringVar(&opts.NodeName, "node-name", opts.NodeName, "kubernetes node name CVO is scheduled on.") cmd.PersistentFlags().BoolVar(&opts.EnableAutoUpdate, "enable-auto-update", opts.EnableAutoUpdate, "Enables the autoupdate controller.") + cmd.PersistentFlags().BoolVar(&opts.EnableDefaultClusterVersion, "enable-default-cluster-version", opts.EnableDefaultClusterVersion, "Allows the operator to create a ClusterVersion object if one does not already exist.") cmd.PersistentFlags().StringVar(&opts.ReleaseImage, "release-image", opts.ReleaseImage, "The Openshift release image url.") rootCmd.AddCommand(cmd) } diff --git a/install/0000_00_cluster-version-operator_03_deployment.yaml b/install/0000_00_cluster-version-operator_03_deployment.yaml index c286dadc8..5eb9b90a8 100644 --- a/install/0000_00_cluster-version-operator_03_deployment.yaml +++ b/install/0000_00_cluster-version-operator_03_deployment.yaml @@ -23,6 +23,7 @@ spec: - "start" - "--release-image={{.ReleaseImage}}" - "--enable-auto-update=false" + - "--enable-default-cluster-version=true" - "--v=4" resources: requests: diff --git a/pkg/cvo/cvo.go b/pkg/cvo/cvo.go index 9c2c20dc6..32ae3af9a 100644 --- a/pkg/cvo/cvo.go +++ b/pkg/cvo/cvo.go @@ -85,6 +85,10 @@ type Operator struct { // releaseCreated, if set, is the timestamp of the current update. releaseCreated time.Time + // enableDefaultClusterVersion allows the operator to create a + // ClusterVersion object if one does not already exist. + enableDefaultClusterVersion bool + client clientset.Interface kubeClient kubernetes.Interface eventRecorder record.EventRecorder @@ -133,6 +137,7 @@ func New( nodename string, namespace, name string, releaseImage string, + enableDefaultClusterVersion bool, overridePayloadDir string, minimumInterval time.Duration, cvInformer configinformersv1.ClusterVersionInformer, @@ -153,6 +158,8 @@ func New( name: name, releaseImage: releaseImage, + enableDefaultClusterVersion: enableDefaultClusterVersion, + statusInterval: 15 * time.Second, minimumUpdateCheckInterval: minimumInterval, payloadDir: overridePayloadDir, @@ -349,7 +356,7 @@ func (optr *Operator) sync(key string) error { // ensure the cluster version exists, that the object is valid, and that // all initial conditions are set. - original, changed, err := optr.getOrCreateClusterVersion() + original, changed, err := optr.getOrCreateClusterVersion(optr.enableDefaultClusterVersion) if err != nil { return err } @@ -357,6 +364,10 @@ func (optr *Operator) sync(key string) error { klog.V(4).Infof("Cluster version changed, waiting for newer event") return nil } + if original == nil { + klog.V(4).Infof("No ClusterVersion object and defaulting not enabled, waiting for one") + return nil + } // ensure that the object we do have is valid errs := validation.ValidateClusterVersion(original) @@ -448,7 +459,7 @@ func (optr *Operator) rememberLastUpdate(config *configv1.ClusterVersion) { optr.lastResourceVersion = i } -func (optr *Operator) getOrCreateClusterVersion() (*configv1.ClusterVersion, bool, error) { +func (optr *Operator) getOrCreateClusterVersion(enableDefault bool) (*configv1.ClusterVersion, bool, error) { obj, err := optr.cvLister.Get(optr.name) if err == nil { // if we are waiting to see a newer cached version, just exit @@ -462,6 +473,10 @@ func (optr *Operator) getOrCreateClusterVersion() (*configv1.ClusterVersion, boo return nil, false, err } + if !enableDefault { + return nil, false, nil + } + var upstream configv1.URL if len(optr.defaultUpstreamServer) > 0 { u := configv1.URL(optr.defaultUpstreamServer) diff --git a/pkg/cvo/cvo_scenarios_test.go b/pkg/cvo/cvo_scenarios_test.go index 3cc8d3c4e..ced9b8d2a 100644 --- a/pkg/cvo/cvo_scenarios_test.go +++ b/pkg/cvo/cvo_scenarios_test.go @@ -69,11 +69,12 @@ func setupCVOTest(payloadDir string) (*Operator, map[string]runtime.Object, *fak }) o := &Operator{ - namespace: "test", - name: "version", - queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "cvo-loop-test"), - client: client, - cvLister: &clientCVLister{client: client}, + namespace: "test", + name: "version", + enableDefaultClusterVersion: true, + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "cvo-loop-test"), + client: client, + cvLister: &clientCVLister{client: client}, } dynamicScheme := runtime.NewScheme() diff --git a/pkg/cvo/cvo_test.go b/pkg/cvo/cvo_test.go index 9e422c8b5..4770ee11f 100644 --- a/pkg/cvo/cvo_test.go +++ b/pkg/cvo/cvo_test.go @@ -255,11 +255,12 @@ func TestOperator_sync(t *testing.T) { { name: "create version and status", optr: Operator{ - releaseVersion: "4.0.1", - releaseImage: "image/image:v4.0.1", - namespace: "test", - name: "default", - client: fake.NewSimpleClientset(), + releaseVersion: "4.0.1", + releaseImage: "image/image:v4.0.1", + enableDefaultClusterVersion: true, + namespace: "test", + name: "default", + client: fake.NewSimpleClientset(), }, wantActions: func(t *testing.T, optr *Operator) { f := optr.client.(*fake.Clientset) diff --git a/pkg/start/start.go b/pkg/start/start.go index 8242ec30c..e28708dab 100644 --- a/pkg/start/start.go +++ b/pkg/start/start.go @@ -55,7 +55,8 @@ type Options struct { NodeName string ListenAddr string - EnableAutoUpdate bool + EnableAutoUpdate bool + EnableDefaultClusterVersion bool // for testing only Name string @@ -326,6 +327,7 @@ func (o *Options) NewControllerContext(cb *ClientBuilder) *Context { o.NodeName, o.Namespace, o.Name, o.ReleaseImage, + o.EnableDefaultClusterVersion, o.PayloadOverride, resyncPeriod(o.ResyncInterval)(), cvInformer.Config().V1().ClusterVersions(), diff --git a/pkg/start/start_integration_test.go b/pkg/start/start_integration_test.go index 94c7bb501..5d0e657c5 100644 --- a/pkg/start/start_integration_test.go +++ b/pkg/start/start_integration_test.go @@ -234,6 +234,7 @@ func TestIntegrationCVO_initializeAndUpgrade(t *testing.T) { options.Namespace = ns options.Name = ns options.ListenAddr = "" + options.EnableDefaultClusterVersion = true options.NodeName = "test-node" options.ReleaseImage = payloadImage1 options.PayloadOverride = filepath.Join(dir, "ignored") @@ -385,6 +386,7 @@ func TestIntegrationCVO_initializeAndHandleError(t *testing.T) { options.Namespace = ns options.Name = ns options.ListenAddr = "" + options.EnableDefaultClusterVersion = true options.NodeName = "test-node" options.ReleaseImage = payloadImage1 options.PayloadOverride = filepath.Join(dir, "ignored")