From 8ff3b4fd47bcba514c9e904b6bee481ff0f3703e Mon Sep 17 00:00:00 2001 From: Beata Skiba Date: Wed, 17 Jul 2019 13:54:01 +0200 Subject: [PATCH] Add support for cronjobs in VPA --- vertical-pod-autoscaler/deploy/vpa-rbac.yaml | 1 + .../controller_fetcher/controller_fetcher.go | 11 +++++- .../controller_fetcher_test.go | 39 +++++++++++++++++-- vertical-pod-autoscaler/pkg/target/fetcher.go | 9 +++++ 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/vertical-pod-autoscaler/deploy/vpa-rbac.yaml b/vertical-pod-autoscaler/deploy/vpa-rbac.yaml index d512aab1e966..2dc8e33a2bcd 100644 --- a/vertical-pod-autoscaler/deploy/vpa-rbac.yaml +++ b/vertical-pod-autoscaler/deploy/vpa-rbac.yaml @@ -178,6 +178,7 @@ rules: - batch resources: - jobs + - cronjobs verbs: - get - list diff --git a/vertical-pod-autoscaler/pkg/recommender/input/controller_fetcher/controller_fetcher.go b/vertical-pod-autoscaler/pkg/recommender/input/controller_fetcher/controller_fetcher.go index 4ee2e13ef3e2..fc248df7af01 100644 --- a/vertical-pod-autoscaler/pkg/recommender/input/controller_fetcher/controller_fetcher.go +++ b/vertical-pod-autoscaler/pkg/recommender/input/controller_fetcher/controller_fetcher.go @@ -22,6 +22,7 @@ import ( appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" corev1 "k8s.io/api/core/v1" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -48,10 +49,9 @@ const ( statefulSet wellKnownController = "StatefulSet" replicationController wellKnownController = "ReplicationController" job wellKnownController = "Job" + cronJob wellKnownController = "CronJob" ) -var wellKnownControllers = []wellKnownController{daemonSet, deployment, replicaSet, statefulSet, replicationController, job} - const ( discoveryResetPeriod time.Duration = 5 * time.Minute ) @@ -102,6 +102,7 @@ func NewControllerFetcher(config *rest.Config, kubeClient kube_client.Interface, statefulSet: factory.Apps().V1().StatefulSets().Informer(), replicationController: factory.Core().V1().ReplicationControllers().Informer(), job: factory.Batch().V1().Jobs().Informer(), + cronJob: factory.Batch().V1beta1().CronJobs().Informer(), } for kind, informer := range informersMap { @@ -182,6 +183,12 @@ func getParentOfWellKnownController(informer cache.SharedIndexInformer, controll return nil, fmt.Errorf("Failed to parse %s %s/%s", kind, namespace, name) } return getOwnerController(apiObj.OwnerReferences, namespace), nil + case (*batchv1beta1.CronJob): + apiObj, ok := obj.(*batchv1beta1.CronJob) + if !ok { + return nil, fmt.Errorf("Failed to parse %s %s/%s", kind, namespace, name) + } + return getOwnerController(apiObj.OwnerReferences, namespace), nil case (*corev1.ReplicationController): apiObj, ok := obj.(*corev1.ReplicationController) if !ok { diff --git a/vertical-pod-autoscaler/pkg/recommender/input/controller_fetcher/controller_fetcher_test.go b/vertical-pod-autoscaler/pkg/recommender/input/controller_fetcher/controller_fetcher_test.go index 574db5175931..b52d58a5f68e 100644 --- a/vertical-pod-autoscaler/pkg/recommender/input/controller_fetcher/controller_fetcher_test.go +++ b/vertical-pod-autoscaler/pkg/recommender/input/controller_fetcher/controller_fetcher_test.go @@ -25,12 +25,14 @@ import ( appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/cache" ) +var wellKnownControllers = []wellKnownController{daemonSet, deployment, replicaSet, statefulSet, replicationController, job, cronJob} var trueVar = true func simpleControllerFetcher() *controllerFetcher { @@ -153,18 +155,49 @@ func TestControllerFetcher(t *testing.T) { }, { key: &ControllerKeyWithAPIVersion{ControllerKey: ControllerKey{ - Name: "test-job", Kind: "Job", Namespace: "test-namesapce"}}, + Name: "test-job", Kind: "Job", Namespace: "test-namespace"}}, objects: []runtime.Object{&batchv1.Job{ TypeMeta: metav1.TypeMeta{ Kind: "Job", }, ObjectMeta: metav1.ObjectMeta{ Name: "test-job", - Namespace: "test-namesapce", + Namespace: "test-namespace", + OwnerReferences: []metav1.OwnerReference{ + { + Controller: &trueVar, + Kind: "CronJob", + Name: "test-cronjob", + }, + }, + }, + }, &batchv1beta1.CronJob{ + TypeMeta: metav1.TypeMeta{ + Kind: "CronJob", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cronjob", + Namespace: "test-namespace", + }, + }}, + expectedKey: &ControllerKeyWithAPIVersion{ControllerKey: ControllerKey{ + Name: "test-cronjob", Kind: "CronJob", Namespace: "test-namespace"}}, // CronJob has no parent + expectedError: nil, + }, + { + key: &ControllerKeyWithAPIVersion{ControllerKey: ControllerKey{ + Name: "test-cronjob", Kind: "CronJob", Namespace: "test-namespace"}}, + objects: []runtime.Object{&batchv1beta1.CronJob{ + TypeMeta: metav1.TypeMeta{ + Kind: "CronJob", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test-cronjob", + Namespace: "test-namespace", }, }}, expectedKey: &ControllerKeyWithAPIVersion{ControllerKey: ControllerKey{ - Name: "test-job", Kind: "Job", Namespace: "test-namesapce"}}, // Job has no parent + Name: "test-cronjob", Kind: "CronJob", Namespace: "test-namespace"}}, // CronJob has no parent expectedError: nil, }, { diff --git a/vertical-pod-autoscaler/pkg/target/fetcher.go b/vertical-pod-autoscaler/pkg/target/fetcher.go index 70f399d095c0..ee92b24d3d48 100644 --- a/vertical-pod-autoscaler/pkg/target/fetcher.go +++ b/vertical-pod-autoscaler/pkg/target/fetcher.go @@ -22,6 +22,7 @@ import ( appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" + batchv1beta1 "k8s.io/api/batch/v1beta1" corev1 "k8s.io/api/core/v1" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -61,6 +62,7 @@ const ( statefulSet wellKnownController = "StatefulSet" replicationController wellKnownController = "ReplicationController" job wellKnownController = "Job" + cronJob wellKnownController = "CronJob" ) // NewVpaTargetSelectorFetcher returns new instance of VpaTargetSelectorFetcher @@ -84,6 +86,7 @@ func NewVpaTargetSelectorFetcher(config *rest.Config, kubeClient kube_client.Int statefulSet: factory.Apps().V1().StatefulSets().Informer(), replicationController: factory.Core().V1().ReplicationControllers().Informer(), job: factory.Batch().V1().Jobs().Informer(), + cronJob: factory.Batch().V1beta1().CronJobs().Informer(), } for kind, informer := range informersMap { @@ -181,6 +184,12 @@ func getLabelSelector(informer cache.SharedIndexInformer, kind, namespace, name return nil, fmt.Errorf("Failed to parse %s %s/%s", kind, namespace, name) } return metav1.LabelSelectorAsSelector(apiObj.Spec.Selector) + case (*batchv1beta1.CronJob): + apiObj, ok := obj.(*batchv1beta1.CronJob) + if !ok { + return nil, fmt.Errorf("Failed to parse %s %s/%s", kind, namespace, name) + } + return metav1.LabelSelectorAsSelector(metav1.SetAsLabelSelector(apiObj.Spec.JobTemplate.Spec.Template.Labels)) case (*corev1.ReplicationController): apiObj, ok := obj.(*corev1.ReplicationController) if !ok {