Unverified Commit 576c9118 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #53592 from frodenas/bootstrap-controller

Automatic merge from submit-queue (batch tested with PRs 53592, 52562, 55175, 55213). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Check RegisterMetricAndTrackRateLimiterUsage error when starting BootstrapSigner & TokenCleaner controllers **What this PR does / why we need it**: Prevent `BootstrapSigner` and `TokenCleaner` controllers to start if `metrics.RegisterMetricAndTrackRateLimiterUsage` returns an error. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: complements #53571 **Special notes for your reviewer**: **Release note**: ```release-note NONE ```
parents 45bdf707 d67898b8
...@@ -21,6 +21,8 @@ limitations under the License. ...@@ -21,6 +21,8 @@ limitations under the License.
package app package app
import ( import (
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/controller/cronjob" "k8s.io/kubernetes/pkg/controller/cronjob"
"k8s.io/kubernetes/pkg/controller/job" "k8s.io/kubernetes/pkg/controller/job"
...@@ -42,8 +44,12 @@ func startCronJobController(ctx ControllerContext) (bool, error) { ...@@ -42,8 +44,12 @@ func startCronJobController(ctx ControllerContext) (bool, error) {
if !ctx.AvailableResources[schema.GroupVersionResource{Group: "batch", Version: "v1beta1", Resource: "cronjobs"}] { if !ctx.AvailableResources[schema.GroupVersionResource{Group: "batch", Version: "v1beta1", Resource: "cronjobs"}] {
return false, nil return false, nil
} }
go cronjob.NewCronJobController( cjc, err := cronjob.NewCronJobController(
ctx.ClientBuilder.ClientOrDie("cronjob-controller"), ctx.ClientBuilder.ClientOrDie("cronjob-controller"),
).Run(ctx.Stop) )
if err != nil {
return true, fmt.Errorf("error creating CronJob controller: %v", err)
}
go cjc.Run(ctx.Stop)
return true, nil return true, nil
} }
...@@ -16,20 +16,32 @@ limitations under the License. ...@@ -16,20 +16,32 @@ limitations under the License.
package app package app
import "k8s.io/kubernetes/pkg/controller/bootstrap" import (
"fmt"
"k8s.io/kubernetes/pkg/controller/bootstrap"
)
func startBootstrapSignerController(ctx ControllerContext) (bool, error) { func startBootstrapSignerController(ctx ControllerContext) (bool, error) {
go bootstrap.NewBootstrapSigner( bsc, err := bootstrap.NewBootstrapSigner(
ctx.ClientBuilder.ClientGoClientOrDie("bootstrap-signer"), ctx.ClientBuilder.ClientGoClientOrDie("bootstrap-signer"),
bootstrap.DefaultBootstrapSignerOptions(), bootstrap.DefaultBootstrapSignerOptions(),
).Run(ctx.Stop) )
if err != nil {
return true, fmt.Errorf("error creating BootstrapSigner controller: %v", err)
}
go bsc.Run(ctx.Stop)
return true, nil return true, nil
} }
func startTokenCleanerController(ctx ControllerContext) (bool, error) { func startTokenCleanerController(ctx ControllerContext) (bool, error) {
go bootstrap.NewTokenCleaner( tcc, err := bootstrap.NewTokenCleaner(
ctx.ClientBuilder.ClientGoClientOrDie("token-cleaner"), ctx.ClientBuilder.ClientGoClientOrDie("token-cleaner"),
bootstrap.DefaultTokenCleanerOptions(), bootstrap.DefaultTokenCleanerOptions(),
).Run(ctx.Stop) )
if err != nil {
return true, fmt.Errorf("error creating TokenCleaner controller: %v", err)
}
go tcc.Run(ctx.Stop)
return true, nil return true, nil
} }
...@@ -525,7 +525,7 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController ...@@ -525,7 +525,7 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController
rootCA = c.rootClientBuilder.ConfigOrDie("tokens-controller").CAData rootCA = c.rootClientBuilder.ConfigOrDie("tokens-controller").CAData
} }
controller := serviceaccountcontroller.NewTokensController( controller, err := serviceaccountcontroller.NewTokensController(
ctx.InformerFactory.Core().V1().ServiceAccounts(), ctx.InformerFactory.Core().V1().ServiceAccounts(),
ctx.InformerFactory.Core().V1().Secrets(), ctx.InformerFactory.Core().V1().Secrets(),
c.rootClientBuilder.ClientOrDie("tokens-controller"), c.rootClientBuilder.ClientOrDie("tokens-controller"),
...@@ -534,6 +534,9 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController ...@@ -534,6 +534,9 @@ func (c serviceAccountTokenControllerStarter) startServiceAccountTokenController
RootCA: rootCA, RootCA: rootCA,
}, },
) )
if err != nil {
return true, fmt.Errorf("error creating Tokens controller: %v", err)
}
go controller.Run(int(ctx.Options.ConcurrentSATokenSyncs), ctx.Stop) go controller.Run(int(ctx.Options.ConcurrentSATokenSyncs), ctx.Stop)
// start the first set of informers now so that other controllers can start // start the first set of informers now so that other controllers can start
......
...@@ -68,6 +68,7 @@ func startServiceController(ctx ControllerContext) (bool, error) { ...@@ -68,6 +68,7 @@ func startServiceController(ctx ControllerContext) (bool, error) {
ctx.Options.ClusterName, ctx.Options.ClusterName,
) )
if err != nil { if err != nil {
// This error shouldn't fail. It lives like this as a legacy.
glog.Errorf("Failed to start service controller: %v", err) glog.Errorf("Failed to start service controller: %v", err)
return false, nil return false, nil
} }
...@@ -258,7 +259,9 @@ func startResourceQuotaController(ctx ControllerContext) (bool, error) { ...@@ -258,7 +259,9 @@ func startResourceQuotaController(ctx ControllerContext) (bool, error) {
Registry: generic.NewRegistry(quotaConfiguration.Evaluators()), Registry: generic.NewRegistry(quotaConfiguration.Evaluators()),
} }
if resourceQuotaControllerClient.CoreV1().RESTClient().GetRateLimiter() != nil { if resourceQuotaControllerClient.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("resource_quota_controller", resourceQuotaControllerClient.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("resource_quota_controller", resourceQuotaControllerClient.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return true, err
}
} }
resourceQuotaController, err := resourcequotacontroller.NewResourceQuotaController(resourceQuotaControllerOptions) resourceQuotaController, err := resourcequotacontroller.NewResourceQuotaController(resourceQuotaControllerOptions)
...@@ -302,12 +305,16 @@ func startNamespaceController(ctx ControllerContext) (bool, error) { ...@@ -302,12 +305,16 @@ func startNamespaceController(ctx ControllerContext) (bool, error) {
} }
func startServiceAccountController(ctx ControllerContext) (bool, error) { func startServiceAccountController(ctx ControllerContext) (bool, error) {
go serviceaccountcontroller.NewServiceAccountsController( sac, err := serviceaccountcontroller.NewServiceAccountsController(
ctx.InformerFactory.Core().V1().ServiceAccounts(), ctx.InformerFactory.Core().V1().ServiceAccounts(),
ctx.InformerFactory.Core().V1().Namespaces(), ctx.InformerFactory.Core().V1().Namespaces(),
ctx.ClientBuilder.ClientOrDie("service-account-controller"), ctx.ClientBuilder.ClientOrDie("service-account-controller"),
serviceaccountcontroller.DefaultServiceAccountsControllerOptions(), serviceaccountcontroller.DefaultServiceAccountsControllerOptions(),
).Run(1, ctx.Stop) )
if err != nil {
return true, fmt.Errorf("error creating ServiceAccount controller: %v", err)
}
go sac.Run(1, ctx.Stop)
return true, nil return true, nil
} }
......
...@@ -21,6 +21,8 @@ limitations under the License. ...@@ -21,6 +21,8 @@ limitations under the License.
package app package app
import ( import (
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/controller/daemon" "k8s.io/kubernetes/pkg/controller/daemon"
"k8s.io/kubernetes/pkg/controller/deployment" "k8s.io/kubernetes/pkg/controller/deployment"
...@@ -31,13 +33,17 @@ func startDaemonSetController(ctx ControllerContext) (bool, error) { ...@@ -31,13 +33,17 @@ func startDaemonSetController(ctx ControllerContext) (bool, error) {
if !ctx.AvailableResources[schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "daemonsets"}] { if !ctx.AvailableResources[schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "daemonsets"}] {
return false, nil return false, nil
} }
go daemon.NewDaemonSetsController( dsc, err := daemon.NewDaemonSetsController(
ctx.InformerFactory.Extensions().V1beta1().DaemonSets(), ctx.InformerFactory.Extensions().V1beta1().DaemonSets(),
ctx.InformerFactory.Apps().V1beta1().ControllerRevisions(), ctx.InformerFactory.Apps().V1beta1().ControllerRevisions(),
ctx.InformerFactory.Core().V1().Pods(), ctx.InformerFactory.Core().V1().Pods(),
ctx.InformerFactory.Core().V1().Nodes(), ctx.InformerFactory.Core().V1().Nodes(),
ctx.ClientBuilder.ClientOrDie("daemon-set-controller"), ctx.ClientBuilder.ClientOrDie("daemon-set-controller"),
).Run(int(ctx.Options.ConcurrentDaemonSetSyncs), ctx.Stop) )
if err != nil {
return true, fmt.Errorf("error creating DaemonSets controller: %v", err)
}
go dsc.Run(int(ctx.Options.ConcurrentDaemonSetSyncs), ctx.Stop)
return true, nil return true, nil
} }
...@@ -45,12 +51,16 @@ func startDeploymentController(ctx ControllerContext) (bool, error) { ...@@ -45,12 +51,16 @@ func startDeploymentController(ctx ControllerContext) (bool, error) {
if !ctx.AvailableResources[schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"}] { if !ctx.AvailableResources[schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"}] {
return false, nil return false, nil
} }
go deployment.NewDeploymentController( dc, err := deployment.NewDeploymentController(
ctx.InformerFactory.Extensions().V1beta1().Deployments(), ctx.InformerFactory.Extensions().V1beta1().Deployments(),
ctx.InformerFactory.Extensions().V1beta1().ReplicaSets(), ctx.InformerFactory.Extensions().V1beta1().ReplicaSets(),
ctx.InformerFactory.Core().V1().Pods(), ctx.InformerFactory.Core().V1().Pods(),
ctx.ClientBuilder.ClientOrDie("deployment-controller"), ctx.ClientBuilder.ClientOrDie("deployment-controller"),
).Run(int(ctx.Options.ConcurrentDeploymentSyncs), ctx.Stop) )
if err != nil {
return true, fmt.Errorf("error creating Deployment controller: %v", err)
}
go dc.Run(int(ctx.Options.ConcurrentDeploymentSyncs), ctx.Stop)
return true, nil return true, nil
} }
......
...@@ -92,7 +92,7 @@ type BootstrapSigner struct { ...@@ -92,7 +92,7 @@ type BootstrapSigner struct {
// NewBootstrapSigner returns a new *BootstrapSigner. // NewBootstrapSigner returns a new *BootstrapSigner.
// //
// TODO: Switch to shared informers // TODO: Switch to shared informers
func NewBootstrapSigner(cl clientset.Interface, options BootstrapSignerOptions) *BootstrapSigner { func NewBootstrapSigner(cl clientset.Interface, options BootstrapSignerOptions) (*BootstrapSigner, error) {
e := &BootstrapSigner{ e := &BootstrapSigner{
client: cl, client: cl,
configMapKey: options.ConfigMapNamespace + "/" + options.ConfigMapName, configMapKey: options.ConfigMapNamespace + "/" + options.ConfigMapName,
...@@ -100,7 +100,9 @@ func NewBootstrapSigner(cl clientset.Interface, options BootstrapSignerOptions) ...@@ -100,7 +100,9 @@ func NewBootstrapSigner(cl clientset.Interface, options BootstrapSignerOptions)
syncQueue: workqueue.NewNamed("bootstrap_signer_queue"), syncQueue: workqueue.NewNamed("bootstrap_signer_queue"),
} }
if cl.CoreV1().RESTClient().GetRateLimiter() != nil { if cl.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("bootstrap_signer", cl.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("bootstrap_signer", cl.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return nil, err
}
} }
configMapSelector := fields.SelectorFromSet(map[string]string{api.ObjectNameField: options.ConfigMapName}) configMapSelector := fields.SelectorFromSet(map[string]string{api.ObjectNameField: options.ConfigMapName})
e.configMaps, e.configMapsController = cache.NewInformer( e.configMaps, e.configMapsController = cache.NewInformer(
...@@ -142,7 +144,7 @@ func NewBootstrapSigner(cl clientset.Interface, options BootstrapSignerOptions) ...@@ -142,7 +144,7 @@ func NewBootstrapSigner(cl clientset.Interface, options BootstrapSignerOptions)
DeleteFunc: func(_ interface{}) { e.pokeConfigMapSync() }, DeleteFunc: func(_ interface{}) { e.pokeConfigMapSync() },
}, },
) )
return e return e, nil
} }
// Run runs controller loops and returns when they are done // Run runs controller loops and returns when they are done
......
...@@ -36,10 +36,14 @@ func init() { ...@@ -36,10 +36,14 @@ func init() {
const testTokenID = "abc123" const testTokenID = "abc123"
func newBootstrapSigner() (*BootstrapSigner, *fake.Clientset) { func newBootstrapSigner() (*BootstrapSigner, *fake.Clientset, error) {
options := DefaultBootstrapSignerOptions() options := DefaultBootstrapSignerOptions()
cl := fake.NewSimpleClientset() cl := fake.NewSimpleClientset()
return NewBootstrapSigner(cl, options), cl bsc, err := NewBootstrapSigner(cl, options)
if err != nil {
return nil, nil, err
}
return bsc, cl, nil
} }
func newConfigMap(tokenID, signature string) *v1.ConfigMap { func newConfigMap(tokenID, signature string) *v1.ConfigMap {
...@@ -60,13 +64,19 @@ func newConfigMap(tokenID, signature string) *v1.ConfigMap { ...@@ -60,13 +64,19 @@ func newConfigMap(tokenID, signature string) *v1.ConfigMap {
} }
func TestNoConfigMap(t *testing.T) { func TestNoConfigMap(t *testing.T) {
signer, cl := newBootstrapSigner() signer, cl, err := newBootstrapSigner()
if err != nil {
t.Fatalf("error creating BootstrapSigner: %v", err)
}
signer.signConfigMap() signer.signConfigMap()
verifyActions(t, []core.Action{}, cl.Actions()) verifyActions(t, []core.Action{}, cl.Actions())
} }
func TestSimpleSign(t *testing.T) { func TestSimpleSign(t *testing.T) {
signer, cl := newBootstrapSigner() signer, cl, err := newBootstrapSigner()
if err != nil {
t.Fatalf("error creating BootstrapSigner: %v", err)
}
cm := newConfigMap("", "") cm := newConfigMap("", "")
signer.configMaps.Add(cm) signer.configMaps.Add(cm)
...@@ -87,7 +97,10 @@ func TestSimpleSign(t *testing.T) { ...@@ -87,7 +97,10 @@ func TestSimpleSign(t *testing.T) {
} }
func TestNoSignNeeded(t *testing.T) { func TestNoSignNeeded(t *testing.T) {
signer, cl := newBootstrapSigner() signer, cl, err := newBootstrapSigner()
if err != nil {
t.Fatalf("error creating BootstrapSigner: %v", err)
}
cm := newConfigMap(testTokenID, "eyJhbGciOiJIUzI1NiIsImtpZCI6ImFiYzEyMyJ9..QSxpUG7Q542CirTI2ECPSZjvBOJURUW5a7XqFpNI958") cm := newConfigMap(testTokenID, "eyJhbGciOiJIUzI1NiIsImtpZCI6ImFiYzEyMyJ9..QSxpUG7Q542CirTI2ECPSZjvBOJURUW5a7XqFpNI958")
signer.configMaps.Add(cm) signer.configMaps.Add(cm)
...@@ -102,7 +115,10 @@ func TestNoSignNeeded(t *testing.T) { ...@@ -102,7 +115,10 @@ func TestNoSignNeeded(t *testing.T) {
} }
func TestUpdateSignature(t *testing.T) { func TestUpdateSignature(t *testing.T) {
signer, cl := newBootstrapSigner() signer, cl, err := newBootstrapSigner()
if err != nil {
t.Fatalf("error creating BootstrapSigner: %v", err)
}
cm := newConfigMap(testTokenID, "old signature") cm := newConfigMap(testTokenID, "old signature")
signer.configMaps.Add(cm) signer.configMaps.Add(cm)
...@@ -123,7 +139,10 @@ func TestUpdateSignature(t *testing.T) { ...@@ -123,7 +139,10 @@ func TestUpdateSignature(t *testing.T) {
} }
func TestRemoveSignature(t *testing.T) { func TestRemoveSignature(t *testing.T) {
signer, cl := newBootstrapSigner() signer, cl, err := newBootstrapSigner()
if err != nil {
t.Fatalf("error creating BootstrapSigner: %v", err)
}
cm := newConfigMap(testTokenID, "old signature") cm := newConfigMap(testTokenID, "old signature")
signer.configMaps.Add(cm) signer.configMaps.Add(cm)
......
...@@ -66,13 +66,15 @@ type TokenCleaner struct { ...@@ -66,13 +66,15 @@ type TokenCleaner struct {
// NewTokenCleaner returns a new *NewTokenCleaner. // NewTokenCleaner returns a new *NewTokenCleaner.
// //
// TODO: Switch to shared informers // TODO: Switch to shared informers
func NewTokenCleaner(cl clientset.Interface, options TokenCleanerOptions) *TokenCleaner { func NewTokenCleaner(cl clientset.Interface, options TokenCleanerOptions) (*TokenCleaner, error) {
e := &TokenCleaner{ e := &TokenCleaner{
client: cl, client: cl,
tokenSecretNamespace: options.TokenSecretNamespace, tokenSecretNamespace: options.TokenSecretNamespace,
} }
if cl.CoreV1().RESTClient().GetRateLimiter() != nil { if cl.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("token_cleaner", cl.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("token_cleaner", cl.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return nil, err
}
} }
secretSelector := fields.SelectorFromSet(map[string]string{api.SecretTypeField: string(bootstrapapi.SecretTypeBootstrapToken)}) secretSelector := fields.SelectorFromSet(map[string]string{api.SecretTypeField: string(bootstrapapi.SecretTypeBootstrapToken)})
...@@ -94,7 +96,7 @@ func NewTokenCleaner(cl clientset.Interface, options TokenCleanerOptions) *Token ...@@ -94,7 +96,7 @@ func NewTokenCleaner(cl clientset.Interface, options TokenCleanerOptions) *Token
UpdateFunc: func(oldSecret, newSecret interface{}) { e.evalSecret(newSecret) }, UpdateFunc: func(oldSecret, newSecret interface{}) { e.evalSecret(newSecret) },
}, },
) )
return e return e, nil
} }
// Run runs controller loops and returns when they are done // Run runs controller loops and returns when they are done
......
...@@ -32,14 +32,21 @@ func init() { ...@@ -32,14 +32,21 @@ func init() {
spew.Config.DisableMethods = true spew.Config.DisableMethods = true
} }
func newTokenCleaner() (*TokenCleaner, *fake.Clientset) { func newTokenCleaner() (*TokenCleaner, *fake.Clientset, error) {
options := DefaultTokenCleanerOptions() options := DefaultTokenCleanerOptions()
cl := fake.NewSimpleClientset() cl := fake.NewSimpleClientset()
return NewTokenCleaner(cl, options), cl tcc, err := NewTokenCleaner(cl, options)
if err != nil {
return nil, nil, err
}
return tcc, cl, nil
} }
func TestCleanerNoExpiration(t *testing.T) { func TestCleanerNoExpiration(t *testing.T) {
cleaner, cl := newTokenCleaner() cleaner, cl, err := newTokenCleaner()
if err != nil {
t.Fatalf("error creating TokenCleaner: %v", err)
}
secret := newTokenSecret("tokenID", "tokenSecret") secret := newTokenSecret("tokenID", "tokenSecret")
cleaner.secrets.Add(secret) cleaner.secrets.Add(secret)
...@@ -52,7 +59,10 @@ func TestCleanerNoExpiration(t *testing.T) { ...@@ -52,7 +59,10 @@ func TestCleanerNoExpiration(t *testing.T) {
} }
func TestCleanerExpired(t *testing.T) { func TestCleanerExpired(t *testing.T) {
cleaner, cl := newTokenCleaner() cleaner, cl, err := newTokenCleaner()
if err != nil {
t.Fatalf("error creating TokenCleaner: %v", err)
}
secret := newTokenSecret("tokenID", "tokenSecret") secret := newTokenSecret("tokenID", "tokenSecret")
addSecretExpiration(secret, timeString(-time.Hour)) addSecretExpiration(secret, timeString(-time.Hour))
...@@ -71,7 +81,10 @@ func TestCleanerExpired(t *testing.T) { ...@@ -71,7 +81,10 @@ func TestCleanerExpired(t *testing.T) {
} }
func TestCleanerNotExpired(t *testing.T) { func TestCleanerNotExpired(t *testing.T) {
cleaner, cl := newTokenCleaner() cleaner, cl, err := newTokenCleaner()
if err != nil {
t.Fatalf("error creating TokenCleaner: %v", err)
}
secret := newTokenSecret("tokenID", "tokenSecret") secret := newTokenSecret("tokenID", "tokenSecret")
addSecretExpiration(secret, timeString(time.Hour)) addSecretExpiration(secret, timeString(time.Hour))
......
...@@ -66,14 +66,16 @@ type CronJobController struct { ...@@ -66,14 +66,16 @@ type CronJobController struct {
recorder record.EventRecorder recorder record.EventRecorder
} }
func NewCronJobController(kubeClient clientset.Interface) *CronJobController { func NewCronJobController(kubeClient clientset.Interface) (*CronJobController, error) {
eventBroadcaster := record.NewBroadcaster() eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartLogging(glog.Infof)
// TODO: remove the wrapper when every clients have moved to use the clientset. // TODO: remove the wrapper when every clients have moved to use the clientset.
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")})
if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("cronjob_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("cronjob_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return nil, err
}
} }
jm := &CronJobController{ jm := &CronJobController{
...@@ -84,12 +86,15 @@ func NewCronJobController(kubeClient clientset.Interface) *CronJobController { ...@@ -84,12 +86,15 @@ func NewCronJobController(kubeClient clientset.Interface) *CronJobController {
recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cronjob-controller"}), recorder: eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "cronjob-controller"}),
} }
return jm return jm, nil
} }
func NewCronJobControllerFromClient(kubeClient clientset.Interface) *CronJobController { func NewCronJobControllerFromClient(kubeClient clientset.Interface) (*CronJobController, error) {
jm := NewCronJobController(kubeClient) jm, err := NewCronJobController(kubeClient)
return jm if err != nil {
return nil, err
}
return jm, nil
} }
// Run the main goroutine responsible for watching and syncing jobs. // Run the main goroutine responsible for watching and syncing jobs.
......
...@@ -130,14 +130,16 @@ type DaemonSetsController struct { ...@@ -130,14 +130,16 @@ type DaemonSetsController struct {
suspendedDaemonPods map[string]sets.String suspendedDaemonPods map[string]sets.String
} }
func NewDaemonSetsController(daemonSetInformer extensionsinformers.DaemonSetInformer, historyInformer appsinformers.ControllerRevisionInformer, podInformer coreinformers.PodInformer, nodeInformer coreinformers.NodeInformer, kubeClient clientset.Interface) *DaemonSetsController { func NewDaemonSetsController(daemonSetInformer extensionsinformers.DaemonSetInformer, historyInformer appsinformers.ControllerRevisionInformer, podInformer coreinformers.PodInformer, nodeInformer coreinformers.NodeInformer, kubeClient clientset.Interface) (*DaemonSetsController, error) {
eventBroadcaster := record.NewBroadcaster() eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartLogging(glog.Infof)
// TODO: remove the wrapper when every clients have moved to use the clientset. // TODO: remove the wrapper when every clients have moved to use the clientset.
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")}) eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(kubeClient.CoreV1().RESTClient()).Events("")})
if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("daemon_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("daemon_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return nil, err
}
} }
dsc := &DaemonSetsController{ dsc := &DaemonSetsController{
kubeClient: kubeClient, kubeClient: kubeClient,
...@@ -201,7 +203,7 @@ func NewDaemonSetsController(daemonSetInformer extensionsinformers.DaemonSetInfo ...@@ -201,7 +203,7 @@ func NewDaemonSetsController(daemonSetInformer extensionsinformers.DaemonSetInfo
dsc.syncHandler = dsc.syncDaemonSet dsc.syncHandler = dsc.syncDaemonSet
dsc.enqueueDaemonSet = dsc.enqueue dsc.enqueueDaemonSet = dsc.enqueue
dsc.enqueueDaemonSetRateLimited = dsc.enqueueRateLimited dsc.enqueueDaemonSetRateLimited = dsc.enqueueRateLimited
return dsc return dsc, nil
} }
func (dsc *DaemonSetsController) deleteDaemonset(obj interface{}) { func (dsc *DaemonSetsController) deleteDaemonset(obj interface{}) {
......
...@@ -27,7 +27,10 @@ import ( ...@@ -27,7 +27,10 @@ import (
func TestDaemonSetUpdatesPods(t *testing.T) { func TestDaemonSetUpdatesPods(t *testing.T) {
ds := newDaemonSet("foo") ds := newDaemonSet("foo")
manager, podControl, _ := newTestController(ds) manager, podControl, _, err := newTestController(ds)
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
maxUnavailable := 2 maxUnavailable := 2
addNodes(manager.nodeStore, 0, 5, nil) addNodes(manager.nodeStore, 0, 5, nil)
manager.dsStore.Add(ds) manager.dsStore.Add(ds)
...@@ -66,7 +69,10 @@ func TestDaemonSetUpdatesPods(t *testing.T) { ...@@ -66,7 +69,10 @@ func TestDaemonSetUpdatesPods(t *testing.T) {
func TestDaemonSetUpdatesWhenNewPosIsNotReady(t *testing.T) { func TestDaemonSetUpdatesWhenNewPosIsNotReady(t *testing.T) {
ds := newDaemonSet("foo") ds := newDaemonSet("foo")
manager, podControl, _ := newTestController(ds) manager, podControl, _, err := newTestController(ds)
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
maxUnavailable := 3 maxUnavailable := 3
addNodes(manager.nodeStore, 0, 5, nil) addNodes(manager.nodeStore, 0, 5, nil)
manager.dsStore.Add(ds) manager.dsStore.Add(ds)
...@@ -93,7 +99,10 @@ func TestDaemonSetUpdatesWhenNewPosIsNotReady(t *testing.T) { ...@@ -93,7 +99,10 @@ func TestDaemonSetUpdatesWhenNewPosIsNotReady(t *testing.T) {
func TestDaemonSetUpdatesAllOldPodsNotReady(t *testing.T) { func TestDaemonSetUpdatesAllOldPodsNotReady(t *testing.T) {
ds := newDaemonSet("foo") ds := newDaemonSet("foo")
manager, podControl, _ := newTestController(ds) manager, podControl, _, err := newTestController(ds)
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
maxUnavailable := 3 maxUnavailable := 3
addNodes(manager.nodeStore, 0, 5, nil) addNodes(manager.nodeStore, 0, 5, nil)
manager.dsStore.Add(ds) manager.dsStore.Add(ds)
...@@ -119,7 +128,10 @@ func TestDaemonSetUpdatesAllOldPodsNotReady(t *testing.T) { ...@@ -119,7 +128,10 @@ func TestDaemonSetUpdatesAllOldPodsNotReady(t *testing.T) {
func TestDaemonSetUpdatesNoTemplateChanged(t *testing.T) { func TestDaemonSetUpdatesNoTemplateChanged(t *testing.T) {
ds := newDaemonSet("foo") ds := newDaemonSet("foo")
manager, podControl, _ := newTestController(ds) manager, podControl, _, err := newTestController(ds)
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
maxUnavailable := 3 maxUnavailable := 3
addNodes(manager.nodeStore, 0, 5, nil) addNodes(manager.nodeStore, 0, 5, nil)
manager.dsStore.Add(ds) manager.dsStore.Add(ds)
...@@ -149,7 +161,10 @@ func TestGetUnavailableNumbers(t *testing.T) { ...@@ -149,7 +161,10 @@ func TestGetUnavailableNumbers(t *testing.T) {
{ {
name: "No nodes", name: "No nodes",
Manager: func() *daemonSetsController { Manager: func() *daemonSetsController {
manager, _, _ := newTestController() manager, _, _, err := newTestController()
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
return manager return manager
}(), }(),
ds: func() *extensions.DaemonSet { ds: func() *extensions.DaemonSet {
...@@ -165,7 +180,10 @@ func TestGetUnavailableNumbers(t *testing.T) { ...@@ -165,7 +180,10 @@ func TestGetUnavailableNumbers(t *testing.T) {
{ {
name: "Two nodes with ready pods", name: "Two nodes with ready pods",
Manager: func() *daemonSetsController { Manager: func() *daemonSetsController {
manager, _, _ := newTestController() manager, _, _, err := newTestController()
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
addNodes(manager.nodeStore, 0, 2, nil) addNodes(manager.nodeStore, 0, 2, nil)
return manager return manager
}(), }(),
...@@ -191,7 +209,10 @@ func TestGetUnavailableNumbers(t *testing.T) { ...@@ -191,7 +209,10 @@ func TestGetUnavailableNumbers(t *testing.T) {
{ {
name: "Two nodes, one node without pods", name: "Two nodes, one node without pods",
Manager: func() *daemonSetsController { Manager: func() *daemonSetsController {
manager, _, _ := newTestController() manager, _, _, err := newTestController()
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
addNodes(manager.nodeStore, 0, 2, nil) addNodes(manager.nodeStore, 0, 2, nil)
return manager return manager
}(), }(),
...@@ -214,7 +235,10 @@ func TestGetUnavailableNumbers(t *testing.T) { ...@@ -214,7 +235,10 @@ func TestGetUnavailableNumbers(t *testing.T) {
{ {
name: "Two nodes with pods, MaxUnavailable in percents", name: "Two nodes with pods, MaxUnavailable in percents",
Manager: func() *daemonSetsController { Manager: func() *daemonSetsController {
manager, _, _ := newTestController() manager, _, _, err := newTestController()
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
addNodes(manager.nodeStore, 0, 2, nil) addNodes(manager.nodeStore, 0, 2, nil)
return manager return manager
}(), }(),
...@@ -240,7 +264,10 @@ func TestGetUnavailableNumbers(t *testing.T) { ...@@ -240,7 +264,10 @@ func TestGetUnavailableNumbers(t *testing.T) {
{ {
name: "Two nodes with pods, MaxUnavailable in percents, pod terminating", name: "Two nodes with pods, MaxUnavailable in percents, pod terminating",
Manager: func() *daemonSetsController { Manager: func() *daemonSetsController {
manager, _, _ := newTestController() manager, _, _, err := newTestController()
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
addNodes(manager.nodeStore, 0, 2, nil) addNodes(manager.nodeStore, 0, 2, nil)
return manager return manager
}(), }(),
......
...@@ -97,14 +97,16 @@ type DeploymentController struct { ...@@ -97,14 +97,16 @@ type DeploymentController struct {
} }
// NewDeploymentController creates a new DeploymentController. // NewDeploymentController creates a new DeploymentController.
func NewDeploymentController(dInformer extensionsinformers.DeploymentInformer, rsInformer extensionsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, client clientset.Interface) *DeploymentController { func NewDeploymentController(dInformer extensionsinformers.DeploymentInformer, rsInformer extensionsinformers.ReplicaSetInformer, podInformer coreinformers.PodInformer, client clientset.Interface) (*DeploymentController, error) {
eventBroadcaster := record.NewBroadcaster() eventBroadcaster := record.NewBroadcaster()
eventBroadcaster.StartLogging(glog.Infof) eventBroadcaster.StartLogging(glog.Infof)
// TODO: remove the wrapper when every clients have moved to use the clientset. // TODO: remove the wrapper when every clients have moved to use the clientset.
eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(client.CoreV1().RESTClient()).Events("")}) eventBroadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: v1core.New(client.CoreV1().RESTClient()).Events("")})
if client != nil && client.CoreV1().RESTClient().GetRateLimiter() != nil { if client != nil && client.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("deployment_controller", client.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("deployment_controller", client.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return nil, err
}
} }
dc := &DeploymentController{ dc := &DeploymentController{
client: client, client: client,
...@@ -140,7 +142,7 @@ func NewDeploymentController(dInformer extensionsinformers.DeploymentInformer, r ...@@ -140,7 +142,7 @@ func NewDeploymentController(dInformer extensionsinformers.DeploymentInformer, r
dc.dListerSynced = dInformer.Informer().HasSynced dc.dListerSynced = dInformer.Informer().HasSynced
dc.rsListerSynced = rsInformer.Informer().HasSynced dc.rsListerSynced = rsInformer.Informer().HasSynced
dc.podListerSynced = podInformer.Informer().HasSynced dc.podListerSynced = podInformer.Informer().HasSynced
return dc return dc, nil
} }
// Run begins watching and syncing. // Run begins watching and syncing.
......
...@@ -187,10 +187,13 @@ func newFixture(t *testing.T) *fixture { ...@@ -187,10 +187,13 @@ func newFixture(t *testing.T) *fixture {
return f return f
} }
func (f *fixture) newController() (*DeploymentController, informers.SharedInformerFactory) { func (f *fixture) newController() (*DeploymentController, informers.SharedInformerFactory, error) {
f.client = fake.NewSimpleClientset(f.objects...) f.client = fake.NewSimpleClientset(f.objects...)
informers := informers.NewSharedInformerFactory(f.client, controller.NoResyncPeriodFunc()) informers := informers.NewSharedInformerFactory(f.client, controller.NoResyncPeriodFunc())
c := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), f.client) c, err := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), f.client)
if err != nil {
return nil, nil, err
}
c.eventRecorder = &record.FakeRecorder{} c.eventRecorder = &record.FakeRecorder{}
c.dListerSynced = alwaysReady c.dListerSynced = alwaysReady
c.rsListerSynced = alwaysReady c.rsListerSynced = alwaysReady
...@@ -204,7 +207,7 @@ func (f *fixture) newController() (*DeploymentController, informers.SharedInform ...@@ -204,7 +207,7 @@ func (f *fixture) newController() (*DeploymentController, informers.SharedInform
for _, pod := range f.podLister { for _, pod := range f.podLister {
informers.Core().V1().Pods().Informer().GetIndexer().Add(pod) informers.Core().V1().Pods().Informer().GetIndexer().Add(pod)
} }
return c, informers return c, informers, nil
} }
func (f *fixture) runExpectError(deploymentName string, startInformers bool) { func (f *fixture) runExpectError(deploymentName string, startInformers bool) {
...@@ -216,14 +219,17 @@ func (f *fixture) run(deploymentName string) { ...@@ -216,14 +219,17 @@ func (f *fixture) run(deploymentName string) {
} }
func (f *fixture) run_(deploymentName string, startInformers bool, expectError bool) { func (f *fixture) run_(deploymentName string, startInformers bool, expectError bool) {
c, informers := f.newController() c, informers, err := f.newController()
if err != nil {
f.t.Fatalf("error creating Deployment controller: %v", err)
}
if startInformers { if startInformers {
stopCh := make(chan struct{}) stopCh := make(chan struct{})
defer close(stopCh) defer close(stopCh)
informers.Start(stopCh) informers.Start(stopCh)
} }
err := c.syncDeployment(deploymentName) err = c.syncDeployment(deploymentName)
if !expectError && err != nil { if !expectError && err != nil {
f.t.Errorf("error syncing deployment: %v", err) f.t.Errorf("error syncing deployment: %v", err)
} else if expectError && err == nil { } else if expectError && err == nil {
...@@ -378,7 +384,10 @@ func TestPodDeletionEnqueuesRecreateDeployment(t *testing.T) { ...@@ -378,7 +384,10 @@ func TestPodDeletionEnqueuesRecreateDeployment(t *testing.T) {
f.rsLister = append(f.rsLister, rs) f.rsLister = append(f.rsLister, rs)
f.objects = append(f.objects, foo, rs) f.objects = append(f.objects, foo, rs)
c, _ := f.newController() c, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
enqueued := false enqueued := false
c.enqueueDeployment = func(d *extensions.Deployment) { c.enqueueDeployment = func(d *extensions.Deployment) {
if d.Name == "foo" { if d.Name == "foo" {
...@@ -411,7 +420,10 @@ func TestPodDeletionDoesntEnqueueRecreateDeployment(t *testing.T) { ...@@ -411,7 +420,10 @@ func TestPodDeletionDoesntEnqueueRecreateDeployment(t *testing.T) {
// return a non-empty list. // return a non-empty list.
f.podLister = append(f.podLister, pod1, pod2) f.podLister = append(f.podLister, pod1, pod2)
c, _ := f.newController() c, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
enqueued := false enqueued := false
c.enqueueDeployment = func(d *extensions.Deployment) { c.enqueueDeployment = func(d *extensions.Deployment) {
if d.Name == "foo" { if d.Name == "foo" {
...@@ -444,7 +456,10 @@ func TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment(t *testi ...@@ -444,7 +456,10 @@ func TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment(t *testi
f.rsLister = append(f.rsLister, rs1, rs2) f.rsLister = append(f.rsLister, rs1, rs2)
f.objects = append(f.objects, foo, rs1, rs2) f.objects = append(f.objects, foo, rs1, rs2)
c, _ := f.newController() c, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
enqueued := false enqueued := false
c.enqueueDeployment = func(d *extensions.Deployment) { c.enqueueDeployment = func(d *extensions.Deployment) {
if d.Name == "foo" { if d.Name == "foo" {
...@@ -480,7 +495,10 @@ func TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment(t ...@@ -480,7 +495,10 @@ func TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment(t
// return a non-empty list. // return a non-empty list.
f.podLister = append(f.podLister, pod) f.podLister = append(f.podLister, pod)
c, _ := f.newController() c, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
enqueued := false enqueued := false
c.enqueueDeployment = func(d *extensions.Deployment) { c.enqueueDeployment = func(d *extensions.Deployment) {
if d.Name == "foo" { if d.Name == "foo" {
...@@ -512,7 +530,10 @@ func TestGetReplicaSetsForDeployment(t *testing.T) { ...@@ -512,7 +530,10 @@ func TestGetReplicaSetsForDeployment(t *testing.T) {
f.objects = append(f.objects, d1, d2, rs1, rs2) f.objects = append(f.objects, d1, d2, rs1, rs2)
// Start the fixture. // Start the fixture.
c, informers := f.newController() c, informers, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
stopCh := make(chan struct{}) stopCh := make(chan struct{})
defer close(stopCh) defer close(stopCh)
informers.Start(stopCh) informers.Start(stopCh)
...@@ -559,7 +580,10 @@ func TestGetReplicaSetsForDeploymentAdoptRelease(t *testing.T) { ...@@ -559,7 +580,10 @@ func TestGetReplicaSetsForDeploymentAdoptRelease(t *testing.T) {
f.objects = append(f.objects, d, rsAdopt, rsRelease) f.objects = append(f.objects, d, rsAdopt, rsRelease)
// Start the fixture. // Start the fixture.
c, informers := f.newController() c, informers, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
stopCh := make(chan struct{}) stopCh := make(chan struct{})
defer close(stopCh) defer close(stopCh)
informers.Start(stopCh) informers.Start(stopCh)
...@@ -603,7 +627,10 @@ func TestGetPodMapForReplicaSets(t *testing.T) { ...@@ -603,7 +627,10 @@ func TestGetPodMapForReplicaSets(t *testing.T) {
f.objects = append(f.objects, d, rs1, rs2, pod1, pod2, pod3, pod4) f.objects = append(f.objects, d, rs1, rs2, pod1, pod2, pod3, pod4)
// Start the fixture. // Start the fixture.
c, informers := f.newController() c, informers, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
stopCh := make(chan struct{}) stopCh := make(chan struct{})
defer close(stopCh) defer close(stopCh)
informers.Start(stopCh) informers.Start(stopCh)
...@@ -656,7 +683,10 @@ func TestAddReplicaSet(t *testing.T) { ...@@ -656,7 +683,10 @@ func TestAddReplicaSet(t *testing.T) {
// Create the fixture but don't start it, // Create the fixture but don't start it,
// so nothing happens in the background. // so nothing happens in the background.
dc, _ := f.newController() dc, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
dc.addReplicaSet(rs1) dc.addReplicaSet(rs1)
if got, want := dc.queue.Len(), 1; got != want { if got, want := dc.queue.Len(), 1; got != want {
...@@ -703,7 +733,10 @@ func TestAddReplicaSetOrphan(t *testing.T) { ...@@ -703,7 +733,10 @@ func TestAddReplicaSetOrphan(t *testing.T) {
// Create the fixture but don't start it, // Create the fixture but don't start it,
// so nothing happens in the background. // so nothing happens in the background.
dc, _ := f.newController() dc, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
dc.addReplicaSet(rs) dc.addReplicaSet(rs)
if got, want := dc.queue.Len(), 2; got != want { if got, want := dc.queue.Len(), 2; got != want {
...@@ -728,7 +761,10 @@ func TestUpdateReplicaSet(t *testing.T) { ...@@ -728,7 +761,10 @@ func TestUpdateReplicaSet(t *testing.T) {
// Create the fixture but don't start it, // Create the fixture but don't start it,
// so nothing happens in the background. // so nothing happens in the background.
dc, _ := f.newController() dc, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
prev := *rs1 prev := *rs1
next := *rs1 next := *rs1
...@@ -779,7 +815,10 @@ func TestUpdateReplicaSetOrphanWithNewLabels(t *testing.T) { ...@@ -779,7 +815,10 @@ func TestUpdateReplicaSetOrphanWithNewLabels(t *testing.T) {
// Create the fixture but don't start it, // Create the fixture but don't start it,
// so nothing happens in the background. // so nothing happens in the background.
dc, _ := f.newController() dc, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
// Change labels and expect all matching controllers to queue. // Change labels and expect all matching controllers to queue.
prev := *rs prev := *rs
...@@ -806,7 +845,10 @@ func TestUpdateReplicaSetChangeControllerRef(t *testing.T) { ...@@ -806,7 +845,10 @@ func TestUpdateReplicaSetChangeControllerRef(t *testing.T) {
// Create the fixture but don't start it, // Create the fixture but don't start it,
// so nothing happens in the background. // so nothing happens in the background.
dc, _ := f.newController() dc, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
// Change ControllerRef and expect both old and new to queue. // Change ControllerRef and expect both old and new to queue.
prev := *rs prev := *rs
...@@ -833,7 +875,10 @@ func TestUpdateReplicaSetRelease(t *testing.T) { ...@@ -833,7 +875,10 @@ func TestUpdateReplicaSetRelease(t *testing.T) {
// Create the fixture but don't start it, // Create the fixture but don't start it,
// so nothing happens in the background. // so nothing happens in the background.
dc, _ := f.newController() dc, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
// Remove ControllerRef and expect all matching controller to sync orphan. // Remove ControllerRef and expect all matching controller to sync orphan.
prev := *rs prev := *rs
...@@ -863,7 +908,10 @@ func TestDeleteReplicaSet(t *testing.T) { ...@@ -863,7 +908,10 @@ func TestDeleteReplicaSet(t *testing.T) {
// Create the fixture but don't start it, // Create the fixture but don't start it,
// so nothing happens in the background. // so nothing happens in the background.
dc, _ := f.newController() dc, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
dc.deleteReplicaSet(rs1) dc.deleteReplicaSet(rs1)
if got, want := dc.queue.Len(), 1; got != want { if got, want := dc.queue.Len(), 1; got != want {
...@@ -908,7 +956,10 @@ func TestDeleteReplicaSetOrphan(t *testing.T) { ...@@ -908,7 +956,10 @@ func TestDeleteReplicaSetOrphan(t *testing.T) {
// Create the fixture but don't start it, // Create the fixture but don't start it,
// so nothing happens in the background. // so nothing happens in the background.
dc, _ := f.newController() dc, _, err := f.newController()
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
dc.deleteReplicaSet(rs) dc.deleteReplicaSet(rs)
if got, want := dc.queue.Len(), 0; got != want { if got, want := dc.queue.Len(), 0; got != want {
......
...@@ -65,7 +65,10 @@ func TestScaleDownOldReplicaSets(t *testing.T) { ...@@ -65,7 +65,10 @@ func TestScaleDownOldReplicaSets(t *testing.T) {
kc := fake.NewSimpleClientset(expected...) kc := fake.NewSimpleClientset(expected...)
informers := informers.NewSharedInformerFactory(kc, controller.NoResyncPeriodFunc()) informers := informers.NewSharedInformerFactory(kc, controller.NoResyncPeriodFunc())
c := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), kc) c, err := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), kc)
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
c.eventRecorder = &record.FakeRecorder{} c.eventRecorder = &record.FakeRecorder{}
c.scaleDownOldReplicaSetsForRecreate(oldRSs, test.d) c.scaleDownOldReplicaSetsForRecreate(oldRSs, test.d)
......
...@@ -399,7 +399,10 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) { ...@@ -399,7 +399,10 @@ func TestDeploymentController_cleanupDeployment(t *testing.T) {
fake := &fake.Clientset{} fake := &fake.Clientset{}
informers := informers.NewSharedInformerFactory(fake, controller.NoResyncPeriodFunc()) informers := informers.NewSharedInformerFactory(fake, controller.NoResyncPeriodFunc())
controller := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), fake) controller, err := NewDeploymentController(informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().ReplicaSets(), informers.Core().V1().Pods(), fake)
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
controller.eventRecorder = &record.FakeRecorder{} controller.eventRecorder = &record.FakeRecorder{}
controller.dListerSynced = alwaysReady controller.dListerSynced = alwaysReady
......
...@@ -119,7 +119,9 @@ func New( ...@@ -119,7 +119,9 @@ func New(
recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "service-controller"}) recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "service-controller"})
if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil { if kubeClient != nil && kubeClient.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("service_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("service_controller", kubeClient.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return nil, err
}
} }
s := &ServiceController{ s := &ServiceController{
......
...@@ -61,14 +61,16 @@ func DefaultServiceAccountsControllerOptions() ServiceAccountsControllerOptions ...@@ -61,14 +61,16 @@ func DefaultServiceAccountsControllerOptions() ServiceAccountsControllerOptions
} }
// NewServiceAccountsController returns a new *ServiceAccountsController. // NewServiceAccountsController returns a new *ServiceAccountsController.
func NewServiceAccountsController(saInformer coreinformers.ServiceAccountInformer, nsInformer coreinformers.NamespaceInformer, cl clientset.Interface, options ServiceAccountsControllerOptions) *ServiceAccountsController { func NewServiceAccountsController(saInformer coreinformers.ServiceAccountInformer, nsInformer coreinformers.NamespaceInformer, cl clientset.Interface, options ServiceAccountsControllerOptions) (*ServiceAccountsController, error) {
e := &ServiceAccountsController{ e := &ServiceAccountsController{
client: cl, client: cl,
serviceAccountsToEnsure: options.ServiceAccounts, serviceAccountsToEnsure: options.ServiceAccounts,
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "serviceaccount"), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "serviceaccount"),
} }
if cl != nil && cl.CoreV1().RESTClient().GetRateLimiter() != nil { if cl != nil && cl.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_controller", cl.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_controller", cl.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return nil, err
}
} }
saInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ saInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
...@@ -86,7 +88,7 @@ func NewServiceAccountsController(saInformer coreinformers.ServiceAccountInforme ...@@ -86,7 +88,7 @@ func NewServiceAccountsController(saInformer coreinformers.ServiceAccountInforme
e.syncHandler = e.syncNamespace e.syncHandler = e.syncNamespace
return e return e, nil
} }
// ServiceAccountsController manages ServiceAccount objects inside Namespaces // ServiceAccountsController manages ServiceAccount objects inside Namespaces
......
...@@ -165,12 +165,15 @@ func TestServiceAccountCreation(t *testing.T) { ...@@ -165,12 +165,15 @@ func TestServiceAccountCreation(t *testing.T) {
} }
saInformer := informers.Core().V1().ServiceAccounts() saInformer := informers.Core().V1().ServiceAccounts()
nsInformer := informers.Core().V1().Namespaces() nsInformer := informers.Core().V1().Namespaces()
controller := NewServiceAccountsController( controller, err := NewServiceAccountsController(
saInformer, saInformer,
nsInformer, nsInformer,
client, client,
options, options,
) )
if err != nil {
t.Fatalf("error creating ServiceAccounts controller: %v", err)
}
controller.saListerSynced = alwaysReady controller.saListerSynced = alwaysReady
controller.nsListerSynced = alwaysReady controller.nsListerSynced = alwaysReady
......
...@@ -70,7 +70,7 @@ type TokensControllerOptions struct { ...@@ -70,7 +70,7 @@ type TokensControllerOptions struct {
} }
// NewTokensController returns a new *TokensController. // NewTokensController returns a new *TokensController.
func NewTokensController(serviceAccounts informers.ServiceAccountInformer, secrets informers.SecretInformer, cl clientset.Interface, options TokensControllerOptions) *TokensController { func NewTokensController(serviceAccounts informers.ServiceAccountInformer, secrets informers.SecretInformer, cl clientset.Interface, options TokensControllerOptions) (*TokensController, error) {
maxRetries := options.MaxRetries maxRetries := options.MaxRetries
if maxRetries == 0 { if maxRetries == 0 {
maxRetries = 10 maxRetries = 10
...@@ -87,7 +87,9 @@ func NewTokensController(serviceAccounts informers.ServiceAccountInformer, secre ...@@ -87,7 +87,9 @@ func NewTokensController(serviceAccounts informers.ServiceAccountInformer, secre
maxRetries: maxRetries, maxRetries: maxRetries,
} }
if cl != nil && cl.CoreV1().RESTClient().GetRateLimiter() != nil { if cl != nil && cl.CoreV1().RESTClient().GetRateLimiter() != nil {
metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_tokens_controller", cl.CoreV1().RESTClient().GetRateLimiter()) if err := metrics.RegisterMetricAndTrackRateLimiterUsage("serviceaccount_tokens_controller", cl.CoreV1().RESTClient().GetRateLimiter()); err != nil {
return nil, err
}
} }
e.serviceAccounts = serviceAccounts.Lister() e.serviceAccounts = serviceAccounts.Lister()
...@@ -124,7 +126,7 @@ func NewTokensController(serviceAccounts informers.ServiceAccountInformer, secre ...@@ -124,7 +126,7 @@ func NewTokensController(serviceAccounts informers.ServiceAccountInformer, secre
options.SecretResync, options.SecretResync,
) )
return e return e, nil
} }
// TokensController manages ServiceAccountToken secrets for ServiceAccount objects // TokensController manages ServiceAccountToken secrets for ServiceAccount objects
......
...@@ -586,7 +586,10 @@ func TestTokenCreation(t *testing.T) { ...@@ -586,7 +586,10 @@ func TestTokenCreation(t *testing.T) {
secretInformer := informers.Core().V1().Secrets().Informer() secretInformer := informers.Core().V1().Secrets().Informer()
secrets := secretInformer.GetStore() secrets := secretInformer.GetStore()
serviceAccounts := informers.Core().V1().ServiceAccounts().Informer().GetStore() serviceAccounts := informers.Core().V1().ServiceAccounts().Informer().GetStore()
controller := NewTokensController(informers.Core().V1().ServiceAccounts(), informers.Core().V1().Secrets(), client, TokensControllerOptions{TokenGenerator: generator, RootCA: []byte("CA Data"), MaxRetries: tc.MaxRetries}) controller, err := NewTokensController(informers.Core().V1().ServiceAccounts(), informers.Core().V1().Secrets(), client, TokensControllerOptions{TokenGenerator: generator, RootCA: []byte("CA Data"), MaxRetries: tc.MaxRetries})
if err != nil {
t.Fatalf("error creating Tokens controller: %v", err)
}
if tc.ExistingServiceAccount != nil { if tc.ExistingServiceAccount != nil {
serviceAccounts.Add(tc.ExistingServiceAccount) serviceAccounts.Add(tc.ExistingServiceAccount)
......
...@@ -34,40 +34,66 @@ const ( ...@@ -34,40 +34,66 @@ const (
var ( var (
metricsLock sync.Mutex metricsLock sync.Mutex
rateLimiterMetrics = make(map[string]prometheus.Gauge) rateLimiterMetrics = make(map[string]rateLimiterMetric)
) )
type rateLimiterMetric struct {
metric prometheus.Gauge
stopCh chan struct{}
}
func registerRateLimiterMetric(ownerName string) error { func registerRateLimiterMetric(ownerName string) error {
metricsLock.Lock() metricsLock.Lock()
defer metricsLock.Unlock() defer metricsLock.Unlock()
if _, ok := rateLimiterMetrics[ownerName]; ok { if _, ok := rateLimiterMetrics[ownerName]; ok {
glog.Errorf("Metric for %v already registered", ownerName) return fmt.Errorf("Rate Limiter Metric for %v already registered", ownerName)
return fmt.Errorf("Metric for %v already registered", ownerName)
} }
metric := prometheus.NewGauge(prometheus.GaugeOpts{ metric := prometheus.NewGauge(prometheus.GaugeOpts{
Name: "rate_limiter_use", Name: "rate_limiter_use",
Subsystem: ownerName, Subsystem: ownerName,
Help: fmt.Sprintf("A metric measuring the saturation of the rate limiter for %v", ownerName), Help: fmt.Sprintf("A metric measuring the saturation of the rate limiter for %v", ownerName),
}) })
rateLimiterMetrics[ownerName] = metric
if err := prometheus.Register(metric); err != nil { if err := prometheus.Register(metric); err != nil {
return fmt.Errorf("error registering rate limiter usage metric: %v", err) return fmt.Errorf("error registering rate limiter usage metric: %v", err)
} }
stopCh := make(chan struct{})
rateLimiterMetrics[ownerName] = rateLimiterMetric{
metric: metric,
stopCh: stopCh,
}
return nil return nil
} }
// RegisterMetricAndTrackRateLimiterUsage registers a metric ownerName_rate_limiter_use in prometheus to track // RegisterMetricAndTrackRateLimiterUsage registers a metric ownerName_rate_limiter_use in prometheus to track
// how much used rateLimiter is and starts a goroutine that updates this metric every updatePeriod // how much used rateLimiter is and starts a goroutine that updates this metric every updatePeriod
func RegisterMetricAndTrackRateLimiterUsage(ownerName string, rateLimiter flowcontrol.RateLimiter) error { func RegisterMetricAndTrackRateLimiterUsage(ownerName string, rateLimiter flowcontrol.RateLimiter) error {
err := registerRateLimiterMetric(ownerName) if err := registerRateLimiterMetric(ownerName); err != nil {
if err != nil {
return err return err
} }
go wait.Forever(func() { go wait.Until(func() {
metricsLock.Lock() metricsLock.Lock()
defer metricsLock.Unlock() defer metricsLock.Unlock()
rateLimiterMetrics[ownerName].Set(rateLimiter.Saturation()) rateLimiterMetrics[ownerName].metric.Set(rateLimiter.Saturation())
}, updatePeriod) }, updatePeriod, rateLimiterMetrics[ownerName].stopCh)
return nil return nil
} }
// UnregisterMetricAndUntrackRateLimiterUsage unregisters a metric ownerName_rate_limiter_use from prometheus and
// stops the goroutine that updates this metric
func UnregisterMetricAndUntrackRateLimiterUsage(ownerName string) bool {
metricsLock.Lock()
defer metricsLock.Unlock()
rlm, ok := rateLimiterMetrics[ownerName]
if !ok {
glog.Warningf("Rate Limiter Metric for %v not registered", ownerName)
return false
}
close(rlm.stopCh)
prometheus.Unregister(rlm.metric)
delete(rateLimiterMetrics, ownerName)
return true
}
...@@ -35,6 +35,11 @@ func TestRegisterMetricAndTrackRateLimiterUsage(t *testing.T) { ...@@ -35,6 +35,11 @@ func TestRegisterMetricAndTrackRateLimiterUsage(t *testing.T) {
err: "", err: "",
}, },
{ {
ownerName: "owner_name",
rateLimiter: flowcontrol.NewTokenBucketRateLimiter(1, 1),
err: "already registered",
},
{
ownerName: "invalid-owner-name", ownerName: "invalid-owner-name",
rateLimiter: flowcontrol.NewTokenBucketRateLimiter(1, 1), rateLimiter: flowcontrol.NewTokenBucketRateLimiter(1, 1),
err: "error registering rate limiter usage metric", err: "error registering rate limiter usage metric",
...@@ -52,3 +57,27 @@ func TestRegisterMetricAndTrackRateLimiterUsage(t *testing.T) { ...@@ -52,3 +57,27 @@ func TestRegisterMetricAndTrackRateLimiterUsage(t *testing.T) {
} }
} }
} }
func TestUnregisterMetricAndUntrackRateLimiterUsage(t *testing.T) {
RegisterMetricAndTrackRateLimiterUsage("owner_name", flowcontrol.NewTokenBucketRateLimiter(1, 1))
testCases := []struct {
ownerName string
ok bool
}{
{
ownerName: "owner_name",
ok: true,
},
{
ownerName: "owner_name",
ok: false,
},
}
for i, tc := range testCases {
ok := UnregisterMetricAndUntrackRateLimiterUsage(tc.ownerName)
if tc.ok != ok {
t.Errorf("Case[%d] Expected %v, got %v", i, tc.ok, ok)
}
}
}
...@@ -17,6 +17,7 @@ go_test( ...@@ -17,6 +17,7 @@ go_test(
deps = [ deps = [
"//pkg/api/v1/pod:go_default_library", "//pkg/api/v1/pod:go_default_library",
"//pkg/controller/daemon:go_default_library", "//pkg/controller/daemon:go_default_library",
"//pkg/util/metrics:go_default_library",
"//test/integration/framework:go_default_library", "//test/integration/framework:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
......
...@@ -36,6 +36,7 @@ import ( ...@@ -36,6 +36,7 @@ import (
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
podutil "k8s.io/kubernetes/pkg/api/v1/pod" podutil "k8s.io/kubernetes/pkg/api/v1/pod"
"k8s.io/kubernetes/pkg/controller/daemon" "k8s.io/kubernetes/pkg/controller/daemon"
"k8s.io/kubernetes/pkg/util/metrics"
"k8s.io/kubernetes/test/integration/framework" "k8s.io/kubernetes/test/integration/framework"
) )
...@@ -50,13 +51,17 @@ func setup(t *testing.T) (*httptest.Server, framework.CloseFunc, *daemon.DaemonS ...@@ -50,13 +51,17 @@ func setup(t *testing.T) (*httptest.Server, framework.CloseFunc, *daemon.DaemonS
} }
resyncPeriod := 12 * time.Hour resyncPeriod := 12 * time.Hour
informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "daemonset-informers")), resyncPeriod) informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "daemonset-informers")), resyncPeriod)
dc := daemon.NewDaemonSetsController( metrics.UnregisterMetricAndUntrackRateLimiterUsage("daemon_controller")
dc, err := daemon.NewDaemonSetsController(
informers.Extensions().V1beta1().DaemonSets(), informers.Extensions().V1beta1().DaemonSets(),
informers.Apps().V1beta1().ControllerRevisions(), informers.Apps().V1beta1().ControllerRevisions(),
informers.Core().V1().Pods(), informers.Core().V1().Pods(),
informers.Core().V1().Nodes(), informers.Core().V1().Nodes(),
clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "daemonset-controller")), clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "daemonset-controller")),
) )
if err != nil {
t.Fatalf("error creating DaemonSets controller: %v", err)
}
return server, closeFn, dc, informers, clientSet return server, closeFn, dc, informers, clientSet
} }
......
...@@ -35,6 +35,7 @@ go_library( ...@@ -35,6 +35,7 @@ go_library(
"//pkg/controller/deployment:go_default_library", "//pkg/controller/deployment:go_default_library",
"//pkg/controller/deployment/util:go_default_library", "//pkg/controller/deployment/util:go_default_library",
"//pkg/controller/replicaset:go_default_library", "//pkg/controller/replicaset:go_default_library",
"//pkg/util/metrics:go_default_library",
"//test/integration/framework:go_default_library", "//test/integration/framework:go_default_library",
"//test/utils:go_default_library", "//test/utils:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
......
...@@ -33,6 +33,7 @@ import ( ...@@ -33,6 +33,7 @@ import (
"k8s.io/kubernetes/pkg/controller/deployment" "k8s.io/kubernetes/pkg/controller/deployment"
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
"k8s.io/kubernetes/pkg/controller/replicaset" "k8s.io/kubernetes/pkg/controller/replicaset"
"k8s.io/kubernetes/pkg/util/metrics"
"k8s.io/kubernetes/test/integration/framework" "k8s.io/kubernetes/test/integration/framework"
testutil "k8s.io/kubernetes/test/utils" testutil "k8s.io/kubernetes/test/utils"
) )
...@@ -150,12 +151,16 @@ func dcSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *replicaset.R ...@@ -150,12 +151,16 @@ func dcSetup(t *testing.T) (*httptest.Server, framework.CloseFunc, *replicaset.R
resyncPeriod := 12 * time.Hour resyncPeriod := 12 * time.Hour
informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "deployment-informers")), resyncPeriod) informers := informers.NewSharedInformerFactory(clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "deployment-informers")), resyncPeriod)
dc := deployment.NewDeploymentController( metrics.UnregisterMetricAndUntrackRateLimiterUsage("deployment_controller")
dc, err := deployment.NewDeploymentController(
informers.Extensions().V1beta1().Deployments(), informers.Extensions().V1beta1().Deployments(),
informers.Extensions().V1beta1().ReplicaSets(), informers.Extensions().V1beta1().ReplicaSets(),
informers.Core().V1().Pods(), informers.Core().V1().Pods(),
clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "deployment-controller")), clientset.NewForConfigOrDie(restclient.AddUserAgent(&config, "deployment-controller")),
) )
if err != nil {
t.Fatalf("error creating Deployment controller: %v", err)
}
rm := replicaset.NewReplicaSetController( rm := replicaset.NewReplicaSetController(
informers.Extensions().V1beta1().ReplicaSets(), informers.Extensions().V1beta1().ReplicaSets(),
informers.Core().V1().Pods(), informers.Core().V1().Pods(),
......
...@@ -21,6 +21,7 @@ go_test( ...@@ -21,6 +21,7 @@ go_test(
"//pkg/controller:go_default_library", "//pkg/controller:go_default_library",
"//pkg/controller/serviceaccount:go_default_library", "//pkg/controller/serviceaccount:go_default_library",
"//pkg/serviceaccount:go_default_library", "//pkg/serviceaccount:go_default_library",
"//pkg/util/metrics:go_default_library",
"//plugin/pkg/admission/serviceaccount:go_default_library", "//plugin/pkg/admission/serviceaccount:go_default_library",
"//test/integration/framework:go_default_library", "//test/integration/framework:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library",
......
...@@ -50,6 +50,7 @@ import ( ...@@ -50,6 +50,7 @@ import (
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount" serviceaccountcontroller "k8s.io/kubernetes/pkg/controller/serviceaccount"
"k8s.io/kubernetes/pkg/serviceaccount" "k8s.io/kubernetes/pkg/serviceaccount"
"k8s.io/kubernetes/pkg/util/metrics"
serviceaccountadmission "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount" serviceaccountadmission "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
"k8s.io/kubernetes/test/integration/framework" "k8s.io/kubernetes/test/integration/framework"
) )
...@@ -63,13 +64,16 @@ const ( ...@@ -63,13 +64,16 @@ const (
) )
func TestServiceAccountAutoCreate(t *testing.T) { func TestServiceAccountAutoCreate(t *testing.T) {
c, _, stopFunc := startServiceAccountTestServer(t) c, _, stopFunc, err := startServiceAccountTestServer(t)
defer stopFunc() defer stopFunc()
if err != nil {
t.Fatalf("failed to setup ServiceAccounts server: %v", err)
}
ns := "test-service-account-creation" ns := "test-service-account-creation"
// Create namespace // Create namespace
_, err := c.Core().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}}) _, err = c.Core().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}})
if err != nil { if err != nil {
t.Fatalf("could not create namespace: %v", err) t.Fatalf("could not create namespace: %v", err)
} }
...@@ -97,14 +101,17 @@ func TestServiceAccountAutoCreate(t *testing.T) { ...@@ -97,14 +101,17 @@ func TestServiceAccountAutoCreate(t *testing.T) {
} }
func TestServiceAccountTokenAutoCreate(t *testing.T) { func TestServiceAccountTokenAutoCreate(t *testing.T) {
c, _, stopFunc := startServiceAccountTestServer(t) c, _, stopFunc, err := startServiceAccountTestServer(t)
defer stopFunc() defer stopFunc()
if err != nil {
t.Fatalf("failed to setup ServiceAccounts server: %v", err)
}
ns := "test-service-account-token-creation" ns := "test-service-account-token-creation"
name := "my-service-account" name := "my-service-account"
// Create namespace // Create namespace
_, err := c.Core().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}}) _, err = c.Core().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}})
if err != nil { if err != nil {
t.Fatalf("could not create namespace: %v", err) t.Fatalf("could not create namespace: %v", err)
} }
...@@ -192,13 +199,16 @@ func TestServiceAccountTokenAutoCreate(t *testing.T) { ...@@ -192,13 +199,16 @@ func TestServiceAccountTokenAutoCreate(t *testing.T) {
} }
func TestServiceAccountTokenAutoMount(t *testing.T) { func TestServiceAccountTokenAutoMount(t *testing.T) {
c, _, stopFunc := startServiceAccountTestServer(t) c, _, stopFunc, err := startServiceAccountTestServer(t)
defer stopFunc() defer stopFunc()
if err != nil {
t.Fatalf("failed to setup ServiceAccounts server: %v", err)
}
ns := "auto-mount-ns" ns := "auto-mount-ns"
// Create "my" namespace // Create "my" namespace
_, err := c.Core().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}}) _, err = c.Core().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: ns}})
if err != nil && !errors.IsAlreadyExists(err) { if err != nil && !errors.IsAlreadyExists(err) {
t.Fatalf("could not create namespace: %v", err) t.Fatalf("could not create namespace: %v", err)
} }
...@@ -271,14 +281,17 @@ func TestServiceAccountTokenAutoMount(t *testing.T) { ...@@ -271,14 +281,17 @@ func TestServiceAccountTokenAutoMount(t *testing.T) {
} }
func TestServiceAccountTokenAuthentication(t *testing.T) { func TestServiceAccountTokenAuthentication(t *testing.T) {
c, config, stopFunc := startServiceAccountTestServer(t) c, config, stopFunc, err := startServiceAccountTestServer(t)
defer stopFunc() defer stopFunc()
if err != nil {
t.Fatalf("failed to setup ServiceAccounts server: %v", err)
}
myns := "auth-ns" myns := "auth-ns"
otherns := "other-ns" otherns := "other-ns"
// Create "my" namespace // Create "my" namespace
_, err := c.Core().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: myns}}) _, err = c.Core().Namespaces().Create(&v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: myns}})
if err != nil && !errors.IsAlreadyExists(err) { if err != nil && !errors.IsAlreadyExists(err) {
t.Fatalf("could not create namespace: %v", err) t.Fatalf("could not create namespace: %v", err)
} }
...@@ -337,7 +350,7 @@ func TestServiceAccountTokenAuthentication(t *testing.T) { ...@@ -337,7 +350,7 @@ func TestServiceAccountTokenAuthentication(t *testing.T) {
// startServiceAccountTestServer returns a started server // startServiceAccountTestServer returns a started server
// It is the responsibility of the caller to ensure the returned stopFunc is called // It is the responsibility of the caller to ensure the returned stopFunc is called
func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclient.Config, func()) { func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclient.Config, func(), error) {
// Listener // Listener
h := &framework.MasterHolder{Initialized: make(chan struct{})} h := &framework.MasterHolder{Initialized: make(chan struct{})}
apiServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { apiServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
...@@ -419,30 +432,38 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie ...@@ -419,30 +432,38 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie
// Start the service account and service account token controllers // Start the service account and service account token controllers
stopCh := make(chan struct{}) stopCh := make(chan struct{})
tokenController := serviceaccountcontroller.NewTokensController( stop := func() {
close(stopCh)
apiServer.Close()
}
metrics.UnregisterMetricAndUntrackRateLimiterUsage("serviceaccount_tokens_controller")
tokenController, err := serviceaccountcontroller.NewTokensController(
informers.Core().V1().ServiceAccounts(), informers.Core().V1().ServiceAccounts(),
informers.Core().V1().Secrets(), informers.Core().V1().Secrets(),
rootClientset, rootClientset,
serviceaccountcontroller.TokensControllerOptions{TokenGenerator: serviceaccount.JWTTokenGenerator(serviceAccountKey)}, serviceaccountcontroller.TokensControllerOptions{TokenGenerator: serviceaccount.JWTTokenGenerator(serviceAccountKey)},
) )
if err != nil {
return rootClientset, clientConfig, stop, err
}
go tokenController.Run(1, stopCh) go tokenController.Run(1, stopCh)
serviceAccountController := serviceaccountcontroller.NewServiceAccountsController( metrics.UnregisterMetricAndUntrackRateLimiterUsage("serviceaccount_controller")
serviceAccountController, err := serviceaccountcontroller.NewServiceAccountsController(
informers.Core().V1().ServiceAccounts(), informers.Core().V1().ServiceAccounts(),
informers.Core().V1().Namespaces(), informers.Core().V1().Namespaces(),
rootClientset, rootClientset,
serviceaccountcontroller.DefaultServiceAccountsControllerOptions(), serviceaccountcontroller.DefaultServiceAccountsControllerOptions(),
) )
if err != nil {
return rootClientset, clientConfig, stop, err
}
informers.Start(stopCh) informers.Start(stopCh)
internalInformers.Start(stopCh) internalInformers.Start(stopCh)
go serviceAccountController.Run(5, stopCh) go serviceAccountController.Run(5, stopCh)
stop := func() { return rootClientset, clientConfig, stop, nil
close(stopCh)
apiServer.Close()
}
return rootClientset, clientConfig, stop
} }
func getServiceAccount(c *clientset.Clientset, ns string, name string, shouldWait bool) (*v1.ServiceAccount, error) { func getServiceAccount(c *clientset.Clientset, ns string, name string, shouldWait bool) (*v1.ServiceAccount, error) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment