diff --git a/cmd/clusterctl/validation/validate_cluster_api_objects_test.go b/cmd/clusterctl/validation/validate_cluster_api_objects_test.go index da3858ca8fd8..65a27e8f8757 100644 --- a/cmd/clusterctl/validation/validate_cluster_api_objects_test.go +++ b/cmd/clusterctl/validation/validate_cluster_api_objects_test.go @@ -83,7 +83,7 @@ func getNodeWithReadyStatus(nodeName string, nodeReadyStatus v1.ConditionStatus) func TestGetClusterObjectWithNoCluster(t *testing.T) { // Setup the Manager and Controller. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Fatalf("error creating new manager: %v", err) } @@ -97,7 +97,7 @@ func TestGetClusterObjectWithNoCluster(t *testing.T) { func TestGetClusterObjectWithOneCluster(t *testing.T) { // Setup the Manager and Controller. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Fatalf("error creating new manager: %v", err) } @@ -163,7 +163,7 @@ func TestGetClusterObjectWithOneCluster(t *testing.T) { func TestGetClusterObjectWithMoreThanOneCluster(t *testing.T) { // Setup the Manager and Controller. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Fatalf("error creating new manager: %v", err) } @@ -274,7 +274,7 @@ func TestValidateClusterObject(t *testing.T) { func TestValidateMachineObjects(t *testing.T) { // Setup the Manager and Controller. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Fatalf("error creating new manager: %v", err) } @@ -356,7 +356,7 @@ func TestValidateMachineObjects(t *testing.T) { func TestValidateMachineObjectWithReferredNode(t *testing.T) { // Setup the Manager and Controller. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Fatalf("error creating new manager: %v", err) } @@ -421,7 +421,7 @@ func TestValidateMachineObjectWithReferredNode(t *testing.T) { func TestValidateClusterAPIObjectsOutput(t *testing.T) { // Setup the Manager and Controller. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Fatalf("error creating new manager: %v", err) } diff --git a/go.mod b/go.mod index 2e2de4caa65a..2dd991684e15 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a // indirect k8s.io/klog v0.3.1 k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 - sigs.k8s.io/controller-runtime v0.2.0-beta.3 + sigs.k8s.io/controller-runtime v0.2.0-beta.4 sigs.k8s.io/controller-tools v0.2.0-beta.2.0.20190610175510-203d8e8ab133 sigs.k8s.io/testing_frameworks v0.1.2-0.20190130140139-57f07443c2d4 ) diff --git a/go.sum b/go.sum index e3f79412faec..885e08b24427 100644 --- a/go.sum +++ b/go.sum @@ -275,8 +275,8 @@ k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c h1:3KSCztE7gPitlZmWbNwue/ k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -sigs.k8s.io/controller-runtime v0.2.0-beta.3 h1:K3dddu6/pOVORH2dBOnEbXif6R80oSDa4y/t1jhoh8s= -sigs.k8s.io/controller-runtime v0.2.0-beta.3/go.mod h1:HweyYKQ8fBuzdu2bdaeBJvsFgAi/OqBBnrVGXcqKhME= +sigs.k8s.io/controller-runtime v0.2.0-beta.4 h1:S1XVfRWR1MuIXZdkYx3jN8JDw+bbQxmWZroy0i87z/A= +sigs.k8s.io/controller-runtime v0.2.0-beta.4/go.mod h1:HweyYKQ8fBuzdu2bdaeBJvsFgAi/OqBBnrVGXcqKhME= sigs.k8s.io/controller-tools v0.2.0-beta.2.0.20190610175510-203d8e8ab133 h1:snHWE0FBZKrXqKguv+fz6SrtTtXTc5iYxWzhycBAygE= sigs.k8s.io/controller-tools v0.2.0-beta.2.0.20190610175510-203d8e8ab133/go.mod h1:gC5UAnK1jbxWnDaqTi0yxKIsRsRwshzeRtTUGbM9vos= sigs.k8s.io/testing_frameworks v0.1.1 h1:cP2l8fkA3O9vekpy5Ks8mmA0NW/F7yBdXf8brkWhVrs= diff --git a/pkg/controller/cluster/cluster_reconciler_test.go b/pkg/controller/cluster/cluster_reconciler_test.go index 852a03b189d4..7f9e7bc6f94f 100644 --- a/pkg/controller/cluster/cluster_reconciler_test.go +++ b/pkg/controller/cluster/cluster_reconciler_test.go @@ -43,7 +43,7 @@ func TestReconcile(t *testing.T) { // Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a // channel when it is finished. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Fatalf("error creating new manager: %v", err) } diff --git a/pkg/controller/machine/machine_reconciler_test.go b/pkg/controller/machine/machine_reconciler_test.go index 238e180f0b0f..92febd9ace29 100644 --- a/pkg/controller/machine/machine_reconciler_test.go +++ b/pkg/controller/machine/machine_reconciler_test.go @@ -47,7 +47,7 @@ func TestReconcile(t *testing.T) { // Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a // channel when it is finished. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Fatalf("error creating new manager: %v", err) } diff --git a/pkg/controller/machinedeployment/machinedeployment_reconciler_test.go b/pkg/controller/machinedeployment/machinedeployment_reconciler_test.go index a27ebfb41efa..2fec1075ef8c 100644 --- a/pkg/controller/machinedeployment/machinedeployment_reconciler_test.go +++ b/pkg/controller/machinedeployment/machinedeployment_reconciler_test.go @@ -79,7 +79,7 @@ func TestReconcile(t *testing.T) { // Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a // channel when it is finished. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) if err != nil { t.Errorf("error creating new manager: %v", err) } diff --git a/pkg/controller/machineset/BUILD.bazel b/pkg/controller/machineset/BUILD.bazel index 8ac4cbf2d0ce..671359c685a8 100644 --- a/pkg/controller/machineset/BUILD.bazel +++ b/pkg/controller/machineset/BUILD.bazel @@ -20,6 +20,7 @@ go_library( "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library", diff --git a/pkg/controller/machineset/machineset_reconciler_test.go b/pkg/controller/machineset/machineset_reconciler_test.go index a18d14982119..ad545793efdf 100644 --- a/pkg/controller/machineset/machineset_reconciler_test.go +++ b/pkg/controller/machineset/machineset_reconciler_test.go @@ -69,7 +69,7 @@ func TestReconcile(t *testing.T) { // Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a // channel when it is finished. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) g.Expect(err).To(gomega.BeNil()) c = mgr.GetClient() diff --git a/pkg/controller/noderef/noderef_controller_test.go b/pkg/controller/noderef/noderef_controller_test.go index eaaca1bbf4d4..ee18455eed7d 100644 --- a/pkg/controller/noderef/noderef_controller_test.go +++ b/pkg/controller/noderef/noderef_controller_test.go @@ -63,7 +63,7 @@ func TestReconcile(t *testing.T) { // Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a // channel when it is finished. - mgr, err := manager.New(cfg, manager.Options{}) + mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"}) g.Expect(err).NotTo(gomega.HaveOccurred()) c = mgr.GetClient() diff --git a/vendor/modules.txt b/vendor/modules.txt index a85c9c978c86..adf1218b3e2f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -648,7 +648,7 @@ k8s.io/utils/pointer k8s.io/utils/integer k8s.io/utils/buffer k8s.io/utils/trace -# sigs.k8s.io/controller-runtime v0.2.0-beta.3 +# sigs.k8s.io/controller-runtime v0.2.0-beta.4 sigs.k8s.io/controller-runtime/pkg/client sigs.k8s.io/controller-runtime/pkg/client/config sigs.k8s.io/controller-runtime/pkg/manager diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/client/config/BUILD.bazel b/vendor/sigs.k8s.io/controller-runtime/pkg/client/config/BUILD.bazel index 6c2b8f7d0cbd..715c2734ccb1 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/client/config/BUILD.bazel +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/client/config/BUILD.bazel @@ -12,6 +12,7 @@ go_library( deps = [ "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", + "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/internal/log:go_default_library", ], ) diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/client/config/config.go b/vendor/sigs.k8s.io/controller-runtime/pkg/client/config/config.go index 8d022c5cfa54..25cd32ca181c 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/client/config/config.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/client/config/config.go @@ -25,6 +25,7 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" logf "sigs.k8s.io/controller-runtime/pkg/internal/log" ) @@ -61,7 +62,27 @@ func init() { // // * $HOME/.kube/config if exists func GetConfig() (*rest.Config, error) { - cfg, err := loadConfig() + return GetConfigWithContext("") +} + +// GetConfigWithContext creates a *rest.Config for talking to a Kubernetes API server with a specific context. +// If --kubeconfig is set, will use the kubeconfig file at that location. Otherwise will assume running +// in cluster and use the cluster provided kubeconfig. +// +// It also applies saner defaults for QPS and burst based on the Kubernetes +// controller manager defaults (20 QPS, 30 burst) +// +// Config precedence +// +// * --kubeconfig flag pointing at a file +// +// * KUBECONFIG environment variable pointing at a file +// +// * In-cluster config if running in cluster +// +// * $HOME/.kube/config if exists +func GetConfigWithContext(context string) (*rest.Config, error) { + cfg, err := loadConfig(context) if err != nil { return nil, err } @@ -75,14 +96,15 @@ func GetConfig() (*rest.Config, error) { } // loadConfig loads a REST Config as per the rules specified in GetConfig -func loadConfig() (*rest.Config, error) { +func loadConfig(context string) (*rest.Config, error) { + // If a flag is specified with the config location, use that if len(kubeconfig) > 0 { - return clientcmd.BuildConfigFromFlags(apiServerURL, kubeconfig) + return loadConfigWithContext(apiServerURL, kubeconfig, context) } - // If an env variable is specified with the config locaiton, use that + // If an env variable is specified with the config location, use that if len(os.Getenv("KUBECONFIG")) > 0 { - return clientcmd.BuildConfigFromFlags(apiServerURL, os.Getenv("KUBECONFIG")) + return loadConfigWithContext(apiServerURL, os.Getenv("KUBECONFIG"), context) } // If no explicit location, try the in-cluster config if c, err := rest.InClusterConfig(); err == nil { @@ -90,8 +112,8 @@ func loadConfig() (*rest.Config, error) { } // If no in-cluster config, try the default location in the user's home directory if usr, err := user.Current(); err == nil { - if c, err := clientcmd.BuildConfigFromFlags( - "", filepath.Join(usr.HomeDir, ".kube", "config")); err == nil { + if c, err := loadConfigWithContext(apiServerURL, filepath.Join(usr.HomeDir, ".kube", "config"), + context); err == nil { return c, nil } } @@ -99,6 +121,17 @@ func loadConfig() (*rest.Config, error) { return nil, fmt.Errorf("could not locate a kubeconfig") } +func loadConfigWithContext(apiServerURL, kubeconfig, context string) (*rest.Config, error) { + return clientcmd.NewNonInteractiveDeferredLoadingClientConfig( + &clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeconfig}, + &clientcmd.ConfigOverrides{ + ClusterInfo: clientcmdapi.Cluster{ + Server: apiServerURL, + }, + CurrentContext: context, + }).ClientConfig() +} + // GetConfigOrDie creates a *rest.Config for talking to a Kubernetes apiserver. // If --kubeconfig is set, will use the kubeconfig file at that location. Otherwise will assume running // in cluster and use the cluster provided kubeconfig. diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go b/vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go index 19857bdd0350..ed4ae806e38b 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/manager/internal.go @@ -90,9 +90,10 @@ type controllerManager struct { // metricsListener is used to serve prometheus metrics metricsListener net.Listener - mu sync.Mutex - started bool - errChan chan error + mu sync.Mutex + started bool + startedLeader bool + errChan chan error // internalStop is the stop channel *actually* used by everything involved // with the manager as a stop channel, so that we can pass a stop channel @@ -134,14 +135,18 @@ func (cm *controllerManager) Add(r Runnable) error { return err } + var shouldStart bool + // Add the runnable to the leader election or the non-leaderelection list if leRunnable, ok := r.(LeaderElectionRunnable); ok && !leRunnable.NeedLeaderElection() { + shouldStart = cm.started cm.nonLeaderElectionRunnables = append(cm.nonLeaderElectionRunnables, r) } else { + shouldStart = cm.startedLeader cm.leaderElectionRunnables = append(cm.leaderElectionRunnables, r) } - if cm.started { + if shouldStart { // If already started, start the controller go func() { cm.errChan <- r.Start(cm.internalStop) @@ -225,17 +230,19 @@ func (cm *controllerManager) GetWebhookServer() *webhook.Server { } func (cm *controllerManager) serveMetrics(stop <-chan struct{}) { + var metricsPath = "/metrics" handler := promhttp.HandlerFor(metrics.Registry, promhttp.HandlerOpts{ ErrorHandling: promhttp.HTTPErrorOnError, }) // TODO(JoelSpeed): Use existing Kubernetes machinery for serving metrics mux := http.NewServeMux() - mux.Handle("/metrics", handler) + mux.Handle(metricsPath, handler) server := http.Server{ Handler: mux, } // Run the server go func() { + log.Info("starting metrics server", "path", metricsPath) if err := server.Serve(cm.metricsListener); err != nil && err != http.ErrServerClosed { cm.errChan <- err } @@ -314,6 +321,8 @@ func (cm *controllerManager) startLeaderElectionRunnables() { cm.errChan <- ctrl.Start(cm.internalStop) }() } + + cm.startedLeader = true } func (cm *controllerManager) waitForCache() { diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/manager/manager.go b/vendor/sigs.k8s.io/controller-runtime/pkg/manager/manager.go index 670df79d0816..5469455f1eeb 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/manager/manager.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/manager/manager.go @@ -135,7 +135,8 @@ type Options struct { Namespace string // MetricsBindAddress is the TCP address that the controller should bind to - // for serving prometheus metrics + // for serving prometheus metrics. + // It can be set to "0" to disable the metrics serving. MetricsBindAddress string // Port is the port that the webhook server serves at. diff --git a/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/listener.go b/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/listener.go index e9db3a110ce2..693bff8413d2 100644 --- a/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/listener.go +++ b/vendor/sigs.k8s.io/controller-runtime/pkg/metrics/listener.go @@ -21,11 +21,9 @@ import ( "net" ) -// DefaultBindAddress sets the default bind address for the metrics -// listener -// The metrics is off by default. -// TODO: Flip the default by changing DefaultBindAddress back to ":8080" in the v0.2.0. -var DefaultBindAddress = "0" +// DefaultBindAddress sets the default bind address for the metrics listener +// The metrics is on by default. +var DefaultBindAddress = ":8080" // NewListener creates a new TCP listener bound to the given address. func NewListener(addr string) (net.Listener, error) { @@ -39,9 +37,12 @@ func NewListener(addr string) (net.Listener, error) { return nil, nil } + log.Info("metrics server is starting to listen", "addr", addr) ln, err := net.Listen("tcp", addr) if err != nil { - return nil, fmt.Errorf("error listening on %s: %v", addr, err) + er := fmt.Errorf("error listening on %s: %v", addr, err) + log.Error(er, "metrics server failed to listen. You may want to disable the metrics server or use another port if it is due to conflicts") + return nil, er } return ln, nil }