diff --git a/lib/resourcebuilder/apiext.go b/lib/resourcebuilder/apiext.go index c25646bb4b..e4bc6bce04 100644 --- a/lib/resourcebuilder/apiext.go +++ b/lib/resourcebuilder/apiext.go @@ -24,7 +24,7 @@ type crdBuilder struct { func newCRDBuilder(config *rest.Config, m lib.Manifest) Interface { return &crdBuilder{ - client: apiextclientv1beta1.NewForConfigOrDie(config), + client: apiextclientv1beta1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } diff --git a/lib/resourcebuilder/apps.go b/lib/resourcebuilder/apps.go index bc5cccfcac..e74c011445 100644 --- a/lib/resourcebuilder/apps.go +++ b/lib/resourcebuilder/apps.go @@ -25,7 +25,7 @@ type deploymentBuilder struct { func newDeploymentBuilder(config *rest.Config, m lib.Manifest) Interface { return &deploymentBuilder{ - client: appsclientv1.NewForConfigOrDie(config), + client: appsclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } @@ -89,7 +89,7 @@ type daemonsetBuilder struct { func newDaemonsetBuilder(config *rest.Config, m lib.Manifest) Interface { return &daemonsetBuilder{ - client: appsclientv1.NewForConfigOrDie(config), + client: appsclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } diff --git a/lib/resourcebuilder/batch.go b/lib/resourcebuilder/batch.go index e57953e98a..ce5d46c4bc 100644 --- a/lib/resourcebuilder/batch.go +++ b/lib/resourcebuilder/batch.go @@ -24,7 +24,7 @@ type jobBuilder struct { func newJobBuilder(config *rest.Config, m lib.Manifest) Interface { return &jobBuilder{ - client: batchclientv1.NewForConfigOrDie(config), + client: batchclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } diff --git a/lib/resourcebuilder/core.go b/lib/resourcebuilder/core.go index fedab3e666..93d5c23c22 100644 --- a/lib/resourcebuilder/core.go +++ b/lib/resourcebuilder/core.go @@ -16,7 +16,7 @@ type serviceAccountBuilder struct { func newServiceAccountBuilder(config *rest.Config, m lib.Manifest) Interface { return &serviceAccountBuilder{ - client: coreclientv1.NewForConfigOrDie(config), + client: coreclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } @@ -43,7 +43,7 @@ type configMapBuilder struct { func newConfigMapBuilder(config *rest.Config, m lib.Manifest) Interface { return &configMapBuilder{ - client: coreclientv1.NewForConfigOrDie(config), + client: coreclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } @@ -70,7 +70,7 @@ type namespaceBuilder struct { func newNamespaceBuilder(config *rest.Config, m lib.Manifest) Interface { return &namespaceBuilder{ - client: coreclientv1.NewForConfigOrDie(config), + client: coreclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } @@ -97,7 +97,7 @@ type serviceBuilder struct { func newServiceBuilder(config *rest.Config, m lib.Manifest) Interface { return &serviceBuilder{ - client: coreclientv1.NewForConfigOrDie(config), + client: coreclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } diff --git a/lib/resourcebuilder/helper.go b/lib/resourcebuilder/helper.go new file mode 100644 index 0000000000..b231cb2b7d --- /dev/null +++ b/lib/resourcebuilder/helper.go @@ -0,0 +1,11 @@ +package resourcebuilder + +import "k8s.io/client-go/rest" + +// withProtobuf makes a client use protobuf. +func withProtobuf(config *rest.Config) *rest.Config { + config = rest.CopyConfig(config) + config.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json" + config.ContentType = "application/vnd.kubernetes.protobuf" + return config +} diff --git a/lib/resourcebuilder/rbac.go b/lib/resourcebuilder/rbac.go index 9189b55b55..698dae37e2 100644 --- a/lib/resourcebuilder/rbac.go +++ b/lib/resourcebuilder/rbac.go @@ -16,7 +16,7 @@ type clusterRoleBuilder struct { func newClusterRoleBuilder(config *rest.Config, m lib.Manifest) Interface { return &clusterRoleBuilder{ - client: rbacclientv1.NewForConfigOrDie(config), + client: rbacclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } @@ -43,7 +43,7 @@ type clusterRoleBindingBuilder struct { func newClusterRoleBindingBuilder(config *rest.Config, m lib.Manifest) Interface { return &clusterRoleBindingBuilder{ - client: rbacclientv1.NewForConfigOrDie(config), + client: rbacclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } @@ -70,7 +70,7 @@ type roleBuilder struct { func newRoleBuilder(config *rest.Config, m lib.Manifest) Interface { return &roleBuilder{ - client: rbacclientv1.NewForConfigOrDie(config), + client: rbacclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } @@ -97,7 +97,7 @@ type roleBindingBuilder struct { func newRoleBindingBuilder(config *rest.Config, m lib.Manifest) Interface { return &roleBindingBuilder{ - client: rbacclientv1.NewForConfigOrDie(config), + client: rbacclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } diff --git a/lib/resourcebuilder/security.go b/lib/resourcebuilder/security.go index d331dd2ab9..18f58ca2ae 100644 --- a/lib/resourcebuilder/security.go +++ b/lib/resourcebuilder/security.go @@ -16,7 +16,7 @@ type securityBuilder struct { func newSecurityBuilder(config *rest.Config, m lib.Manifest) Interface { return &securityBuilder{ - client: securityclientv1.NewForConfigOrDie(config), + client: securityclientv1.NewForConfigOrDie(withProtobuf(config)), raw: m.Raw, } } diff --git a/pkg/cvo/cvo.go b/pkg/cvo/cvo.go index ff1510af31..7b8f569238 100644 --- a/pkg/cvo/cvo.go +++ b/pkg/cvo/cvo.go @@ -12,7 +12,6 @@ import ( "github.com/golang/glog" "github.com/google/uuid" corev1 "k8s.io/api/core/v1" - apiextclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -83,7 +82,6 @@ type Operator struct { client clientset.Interface kubeClient kubernetes.Interface - apiExtClient apiextclientset.Interface eventRecorder record.EventRecorder // minimumUpdateCheckInterval is the minimum duration to check for updates from @@ -132,7 +130,6 @@ func New( restConfig *rest.Config, client clientset.Interface, kubeClient kubernetes.Interface, - apiExtClient apiextclientset.Interface, enableMetrics bool, ) *Operator { eventBroadcaster := record.NewBroadcaster() @@ -153,8 +150,7 @@ func New( restConfig: restConfig, client: client, kubeClient: kubeClient, - apiExtClient: apiExtClient, - eventRecorder: eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: "clusterversionoperator"}), + eventRecorder: eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: namespace}), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "clusterversion"), availableUpdatesQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "availableupdates"), diff --git a/pkg/start/start.go b/pkg/start/start.go index c5761d1b6f..05781b3bd7 100644 --- a/pkg/start/start.go +++ b/pkg/start/start.go @@ -1,3 +1,5 @@ +// package start initializes and launches the core cluster version operator +// loops. package start import ( @@ -19,7 +21,6 @@ import ( "github.com/openshift/cluster-version-operator/pkg/cvo" "github.com/prometheus/client_golang/prometheus/promhttp" v1 "k8s.io/api/core/v1" - apiext "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" @@ -42,6 +43,7 @@ const ( retryPeriod = 30 * time.Second ) +// Options are the valid inputs to starting the CVO. type Options struct { ReleaseImage string @@ -67,6 +69,8 @@ func defaultEnv(name, defaultValue string) string { return env } +// NewOptions creates the default options for the CVO and loads any environment +// variable overrides. func NewOptions() *Options { return &Options{ ListenAddr: "0.0.0.0:9099", @@ -227,25 +231,28 @@ func resyncPeriod(minResyncPeriod time.Duration) func() time.Duration { } } +// ClientBuilder simplifies returning Kubernetes client and client configs with +// an appropriate user agent. type ClientBuilder struct { config *rest.Config } -func (cb *ClientBuilder) RestConfig() *rest.Config { +// RestConfig returns a copy of the ClientBuilder's rest.Config with any overrides +// from the provided configFns applied. +func (cb *ClientBuilder) RestConfig(configFns ...func(*rest.Config)) *rest.Config { c := rest.CopyConfig(cb.config) + for _, fn := range configFns { + fn(c) + } return c } -func (cb *ClientBuilder) ClientOrDie(name string) clientset.Interface { - return clientset.NewForConfigOrDie(rest.AddUserAgent(cb.config, name)) -} - -func (cb *ClientBuilder) KubeClientOrDie(name string) kubernetes.Interface { - return kubernetes.NewForConfigOrDie(rest.AddUserAgent(cb.config, name)) +func (cb *ClientBuilder) ClientOrDie(name string, configFns ...func(*rest.Config)) clientset.Interface { + return clientset.NewForConfigOrDie(rest.AddUserAgent(cb.RestConfig(configFns...), name)) } -func (cb *ClientBuilder) APIExtClientOrDie(name string) apiext.Interface { - return apiext.NewForConfigOrDie(rest.AddUserAgent(cb.config, name)) +func (cb *ClientBuilder) KubeClientOrDie(name string, configFns ...func(*rest.Config)) kubernetes.Interface { + return kubernetes.NewForConfigOrDie(rest.AddUserAgent(cb.RestConfig(configFns...), name)) } func newClientBuilder(kubeconfig string) (*ClientBuilder, error) { @@ -263,6 +270,17 @@ func newClientBuilder(kubeconfig string) (*ClientBuilder, error) { }, nil } +func increaseQPS(config *rest.Config) { + config.QPS = 20 + config.Burst = 40 +} + +func useProtobuf(config *rest.Config) { + config.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json" + config.ContentType = "application/vnd.kubernetes.protobuf" +} + +// Context holds the controllers for this operator and exposes a unified start command. type Context struct { CVO *cvo.Operator AutoUpdate *autoupdate.Controller @@ -271,6 +289,8 @@ type Context struct { InformerFactory informers.SharedInformerFactory } +// NewControllerContext initializes the default Context for the current Options. It does +// not start any background processes. func (o *Options) NewControllerContext(cb *ClientBuilder) *Context { client := cb.ClientOrDie("shared-informer") @@ -291,10 +311,9 @@ func (o *Options) NewControllerContext(cb *ClientBuilder) *Context { resyncPeriod(o.ResyncInterval)(), cvInformer.Config().V1().ClusterVersions(), sharedInformers.Config().V1().ClusterOperators(), - cb.RestConfig(), + cb.RestConfig(increaseQPS), cb.ClientOrDie(o.Namespace), - cb.KubeClientOrDie(o.Namespace), - cb.APIExtClientOrDie(o.Namespace), + cb.KubeClientOrDie(o.Namespace, useProtobuf), o.EnableMetrics, ), } @@ -310,6 +329,8 @@ func (o *Options) NewControllerContext(cb *ClientBuilder) *Context { return ctx } +// Start launches the controllers in the provided context and any supporting +// infrastructure. When ch is closed the controllers will be shut down. func (ctx *Context) Start(ch <-chan struct{}) { go ctx.CVO.Run(2, ch) if ctx.AutoUpdate != nil {