From 17c1aaa1316298cfcedb1b062e76118a4366065c Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sat, 21 Sep 2019 15:52:29 +0000 Subject: [PATCH 1/2] chore(probe): for Kubernetes 1.16 move to 'v1' APIs Scope will no longer work with Kubernetes 1.8 and below. For CronJob there is no 'v1' as yet, but we can remove the alpha version. --- probe/kubernetes/client.go | 38 ++++++++++---------------- probe/kubernetes/cronjob.go | 44 +++---------------------------- probe/kubernetes/daemonset.go | 6 ++--- probe/kubernetes/deployment.go | 6 ++--- probe/kubernetes/reporter_test.go | 6 ++--- probe/kubernetes/statefulset.go | 10 +++---- 6 files changed, 30 insertions(+), 80 deletions(-) diff --git a/probe/kubernetes/client.go b/probe/kubernetes/client.go index 352ba855d..a6e077a36 100644 --- a/probe/kubernetes/client.go +++ b/probe/kubernetes/client.go @@ -17,12 +17,10 @@ import ( "github.com/pborman/uuid" log "github.com/sirupsen/logrus" apiappsv1 "k8s.io/api/apps/v1" - apiappsv1beta1 "k8s.io/api/apps/v1beta1" + autoscalingv1 "k8s.io/api/autoscaling/v1" apibatchv1 "k8s.io/api/batch/v1" apibatchv1beta1 "k8s.io/api/batch/v1beta1" - apibatchv2alpha1 "k8s.io/api/batch/v2alpha1" apiv1 "k8s.io/api/core/v1" - apiextensionsv1beta1 "k8s.io/api/extensions/v1beta1" storagev1 "k8s.io/api/storage/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" apimeta "k8s.io/apimachinery/pkg/api/meta" @@ -242,28 +240,19 @@ func (c *client) clientAndType(resource string) (rest.Interface, interface{}, er case "storageclasses": return c.client.StorageV1().RESTClient(), &storagev1.StorageClass{}, nil case "deployments": - return c.client.ExtensionsV1beta1().RESTClient(), &apiextensionsv1beta1.Deployment{}, nil + return c.client.AppsV1().RESTClient(), &apiappsv1.Deployment{}, nil case "daemonsets": - return c.client.ExtensionsV1beta1().RESTClient(), &apiextensionsv1beta1.DaemonSet{}, nil + return c.client.AppsV1().RESTClient(), &apiappsv1.DaemonSet{}, nil case "jobs": return c.client.BatchV1().RESTClient(), &apibatchv1.Job{}, nil case "statefulsets": - return c.client.AppsV1beta1().RESTClient(), &apiappsv1beta1.StatefulSet{}, nil + return c.client.AppsV1().RESTClient(), &apiappsv1.StatefulSet{}, nil case "volumesnapshots": return c.snapshotClient.VolumesnapshotV1().RESTClient(), &snapshotv1.VolumeSnapshot{}, nil case "volumesnapshotdatas": return c.snapshotClient.VolumesnapshotV1().RESTClient(), &snapshotv1.VolumeSnapshotData{}, nil case "cronjobs": - ok, err := c.isResourceSupported(c.client.BatchV1beta1().RESTClient().APIVersion(), resource) - if err != nil { - return nil, nil, err - } - if ok { - // kubernetes >= 1.8 - return c.client.BatchV1beta1().RESTClient(), &apibatchv1beta1.CronJob{}, nil - } - // kubernetes < 1.8 - return c.client.BatchV2alpha1().RESTClient(), &apibatchv2alpha1.CronJob{}, nil + return c.client.BatchV1beta1().RESTClient(), &apibatchv1beta1.CronJob{}, nil } return nil, nil, fmt.Errorf("Invalid resource: %v", resource) } @@ -372,7 +361,7 @@ func (c *client) WalkDeployments(f func(Deployment) error) error { return nil } for _, m := range c.deploymentStore.List() { - d := m.(*apiextensionsv1beta1.Deployment) + d := m.(*apiappsv1.Deployment) if err := f(NewDeployment(d)); err != nil { return err } @@ -386,7 +375,7 @@ func (c *client) WalkDaemonSets(f func(DaemonSet) error) error { return nil } for _, m := range c.daemonSetStore.List() { - ds := m.(*apiextensionsv1beta1.DaemonSet) + ds := m.(*apiappsv1.DaemonSet) if err := f(NewDaemonSet(ds)); err != nil { return err } @@ -400,7 +389,7 @@ func (c *client) WalkStatefulSets(f func(StatefulSet) error) error { return nil } for _, m := range c.statefulSetStore.List() { - s := m.(*apiappsv1beta1.StatefulSet) + s := m.(*apiappsv1.StatefulSet) if err := f(NewStatefulSet(s)); err != nil { return err } @@ -420,7 +409,8 @@ func (c *client) WalkCronJobs(f func(CronJob) error) error { jobs[j.UID] = j } for _, m := range c.cronJobStore.List() { - if err := f(NewCronJob(m, jobs)); err != nil { + cj := m.(*apibatchv1beta1.CronJob) + if err := f(NewCronJob(cj, jobs)); err != nil { return err } } @@ -609,19 +599,19 @@ func (c *client) DeleteVolumeSnapshot(namespaceID, volumeSnapshotID string) erro } func (c *client) ScaleUp(namespaceID, id string) error { - return c.modifyScale(namespaceID, id, func(scale *apiextensionsv1beta1.Scale) { + return c.modifyScale(namespaceID, id, func(scale *autoscalingv1.Scale) { scale.Spec.Replicas++ }) } func (c *client) ScaleDown(namespaceID, id string) error { - return c.modifyScale(namespaceID, id, func(scale *apiextensionsv1beta1.Scale) { + return c.modifyScale(namespaceID, id, func(scale *autoscalingv1.Scale) { scale.Spec.Replicas-- }) } -func (c *client) modifyScale(namespaceID, id string, f func(*apiextensionsv1beta1.Scale)) error { - scaler := c.client.ExtensionsV1beta1().Deployments(namespaceID) +func (c *client) modifyScale(namespaceID, id string, f func(*autoscalingv1.Scale)) error { + scaler := c.client.AppsV1().Deployments(namespaceID) scale, err := scaler.GetScale(id, metav1.GetOptions{}) if err != nil { return err diff --git a/probe/kubernetes/cronjob.go b/probe/kubernetes/cronjob.go index e6543efb9..5598fc256 100644 --- a/probe/kubernetes/cronjob.go +++ b/probe/kubernetes/cronjob.go @@ -5,8 +5,7 @@ import ( "time" batchv1 "k8s.io/api/batch/v1" - batchv1beta1 "k8s.io/api/batch/v1beta1" - batchv2alpha1 "k8s.io/api/batch/v2alpha1" + apibatchv1beta1 "k8s.io/api/batch/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/types" @@ -30,25 +29,14 @@ type CronJob interface { } type cronJob struct { - *batchv1beta1.CronJob + *apibatchv1beta1.CronJob Meta jobs []*batchv1.Job } // NewCronJob creates a new cron job. jobs should be all jobs, which will be filtered // for those matching this cron job. -func NewCronJob(cji interface{}, jobs map[types.UID]*batchv1.Job) CronJob { - switch cj := cji.(type) { - case *batchv2alpha1.CronJob: - return newCronJob(upgradeCronJob(cj), jobs) - case *batchv1beta1.CronJob: - return newCronJob(cj, jobs) - default: - panic(fmt.Sprintf("interface conversion: interface{} is %T, not *batchv2alpha1.CronJob or *batchv1beta1.CronJob", cj)) - } -} - -func newCronJob(cj *batchv1beta1.CronJob, jobs map[types.UID]*batchv1.Job) CronJob { +func NewCronJob(cj *apibatchv1beta1.CronJob, jobs map[types.UID]*batchv1.Job) CronJob { myJobs := []*batchv1.Job{} for _, o := range cj.Status.Active { if j, ok := jobs[o.UID]; ok { @@ -89,29 +77,3 @@ func (cj *cronJob) GetNode(probeID string) report.Node { WithLatests(latest). WithLatestActiveControls(Describe) } - -func upgradeCronJob(legacy *batchv2alpha1.CronJob) *batchv1beta1.CronJob { - jobTemplate := batchv1beta1.JobTemplateSpec{ - ObjectMeta: legacy.Spec.JobTemplate.ObjectMeta, - Spec: legacy.Spec.JobTemplate.Spec, - } - spec := batchv1beta1.CronJobSpec{ - Schedule: legacy.Spec.Schedule, - StartingDeadlineSeconds: legacy.Spec.StartingDeadlineSeconds, - ConcurrencyPolicy: batchv1beta1.ConcurrencyPolicy(legacy.Spec.ConcurrencyPolicy), - Suspend: legacy.Spec.Suspend, - JobTemplate: jobTemplate, - SuccessfulJobsHistoryLimit: legacy.Spec.SuccessfulJobsHistoryLimit, - FailedJobsHistoryLimit: legacy.Spec.FailedJobsHistoryLimit, - } - status := batchv1beta1.CronJobStatus{ - Active: legacy.Status.Active, - LastScheduleTime: legacy.Status.LastScheduleTime, - } - return &batchv1beta1.CronJob{ - TypeMeta: legacy.TypeMeta, - ObjectMeta: legacy.ObjectMeta, - Spec: spec, - Status: status, - } -} diff --git a/probe/kubernetes/daemonset.go b/probe/kubernetes/daemonset.go index d7dd638b3..ab2115db7 100644 --- a/probe/kubernetes/daemonset.go +++ b/probe/kubernetes/daemonset.go @@ -3,7 +3,7 @@ package kubernetes import ( "fmt" - apiv1beta1 "k8s.io/api/extensions/v1beta1" + apiv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -23,12 +23,12 @@ type DaemonSet interface { } type daemonSet struct { - *apiv1beta1.DaemonSet + *apiv1.DaemonSet Meta } // NewDaemonSet creates a new daemonset -func NewDaemonSet(d *apiv1beta1.DaemonSet) DaemonSet { +func NewDaemonSet(d *apiv1.DaemonSet) DaemonSet { return &daemonSet{ DaemonSet: d, Meta: meta{d.ObjectMeta}, diff --git a/probe/kubernetes/deployment.go b/probe/kubernetes/deployment.go index 78777e27c..4f85bc2e0 100644 --- a/probe/kubernetes/deployment.go +++ b/probe/kubernetes/deployment.go @@ -5,8 +5,8 @@ import ( "github.com/weaveworks/scope/report" + apiappsv1 "k8s.io/api/apps/v1" apiv1 "k8s.io/api/core/v1" - apiv1beta1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" ) @@ -27,13 +27,13 @@ type Deployment interface { } type deployment struct { - *apiv1beta1.Deployment + *apiappsv1.Deployment Meta Node *apiv1.Node } // NewDeployment creates a new Deployment -func NewDeployment(d *apiv1beta1.Deployment) Deployment { +func NewDeployment(d *apiappsv1.Deployment) Deployment { return &deployment{Deployment: d, Meta: meta{d.ObjectMeta}} } diff --git a/probe/kubernetes/reporter_test.go b/probe/kubernetes/reporter_test.go index d742fb79d..1abd9b624 100644 --- a/probe/kubernetes/reporter_test.go +++ b/probe/kubernetes/reporter_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" + appsv1 "k8s.io/api/apps/v1" apiv1 "k8s.io/api/core/v1" - apiv1beta1 "k8s.io/api/extensions/v1beta1" k8smeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -323,10 +323,10 @@ func BenchmarkReporter(b *testing.B) { pod := apiPod1 pod.ObjectMeta.UID = types.UID(fmt.Sprintf("pod%d", i)) mockK8s.pods = append(mockK8s.pods, kubernetes.NewPod(&pod)) - deployment := apiv1beta1.Deployment{ + deployment := appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ Kind: "Deployment", - APIVersion: "v1beta1", + APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("deployment%d", i), diff --git a/probe/kubernetes/statefulset.go b/probe/kubernetes/statefulset.go index db5539372..4f388cefc 100644 --- a/probe/kubernetes/statefulset.go +++ b/probe/kubernetes/statefulset.go @@ -3,7 +3,7 @@ package kubernetes import ( "fmt" - "k8s.io/api/apps/v1beta1" + appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -18,12 +18,12 @@ type StatefulSet interface { } type statefulSet struct { - *v1beta1.StatefulSet + *appsv1.StatefulSet Meta } // NewStatefulSet creates a new statefulset -func NewStatefulSet(s *v1beta1.StatefulSet) StatefulSet { +func NewStatefulSet(s *appsv1.StatefulSet) StatefulSet { return &statefulSet{ StatefulSet: s, Meta: meta{s.ObjectMeta}, @@ -48,9 +48,7 @@ func (s *statefulSet) GetNode(probeID string) report.Node { DesiredReplicas: fmt.Sprint(desiredReplicas), Replicas: fmt.Sprint(s.Status.Replicas), report.ControlProbeID: probeID, - } - if s.Status.ObservedGeneration != nil { - latests[ObservedGeneration] = fmt.Sprint(*s.Status.ObservedGeneration) + ObservedGeneration: fmt.Sprint(s.Status.ObservedGeneration), } return s.MetaNode(report.MakeStatefulSetNodeID(s.UID())). WithLatests(latests). From d375f3c07d7c805a8d702c814069073b47cbe56f Mon Sep 17 00:00:00 2001 From: Bryan Boreham Date: Sat, 21 Sep 2019 16:00:58 +0000 Subject: [PATCH 2/2] chore(example): update example Kubernetes app to apps/v1 --- extras/example/k8s/app-deployment.yaml | 5 ++++- extras/example/k8s/client-deployment.yaml | 5 ++++- extras/example/k8s/echo-deployment.yaml | 5 ++++- extras/example/k8s/elasticsearch-deployment.yaml | 5 ++++- extras/example/k8s/frontend-deployment.yaml | 5 ++++- extras/example/k8s/qotd-deployment.yaml | 5 ++++- extras/example/k8s/redis-deployment.yaml | 5 ++++- extras/example/k8s/search-deployment.yaml | 5 ++++- 8 files changed, 32 insertions(+), 8 deletions(-) diff --git a/extras/example/k8s/app-deployment.yaml b/extras/example/k8s/app-deployment.yaml index b91b145fa..5a9f7f2e9 100644 --- a/extras/example/k8s/app-deployment.yaml +++ b/extras/example/k8s/app-deployment.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: app spec: replicas: 2 + selector: + matchLabels: + name: app template: metadata: labels: diff --git a/extras/example/k8s/client-deployment.yaml b/extras/example/k8s/client-deployment.yaml index eeedd65c8..4979fc515 100644 --- a/extras/example/k8s/client-deployment.yaml +++ b/extras/example/k8s/client-deployment.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: client spec: replicas: 1 + selector: + matchLabels: + name: client template: metadata: labels: diff --git a/extras/example/k8s/echo-deployment.yaml b/extras/example/k8s/echo-deployment.yaml index cfeb6deee..072612e68 100644 --- a/extras/example/k8s/echo-deployment.yaml +++ b/extras/example/k8s/echo-deployment.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: echo spec: replicas: 1 + selector: + matchLabels: + name: echo template: metadata: labels: diff --git a/extras/example/k8s/elasticsearch-deployment.yaml b/extras/example/k8s/elasticsearch-deployment.yaml index b5e3e02bb..bb0474d85 100644 --- a/extras/example/k8s/elasticsearch-deployment.yaml +++ b/extras/example/k8s/elasticsearch-deployment.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: elasticsearch spec: replicas: 1 + selector: + matchLabels: + name: elasticsearch template: metadata: labels: diff --git a/extras/example/k8s/frontend-deployment.yaml b/extras/example/k8s/frontend-deployment.yaml index 7a5abe390..52f979b86 100644 --- a/extras/example/k8s/frontend-deployment.yaml +++ b/extras/example/k8s/frontend-deployment.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: frontend spec: replicas: 2 + selector: + matchLabels: + name: frontend template: metadata: labels: diff --git a/extras/example/k8s/qotd-deployment.yaml b/extras/example/k8s/qotd-deployment.yaml index 7b53eba57..0fefe7057 100644 --- a/extras/example/k8s/qotd-deployment.yaml +++ b/extras/example/k8s/qotd-deployment.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: qotd spec: replicas: 1 + selector: + matchLabels: + name: qotd template: metadata: labels: diff --git a/extras/example/k8s/redis-deployment.yaml b/extras/example/k8s/redis-deployment.yaml index 8a2910d83..3ad2fd044 100644 --- a/extras/example/k8s/redis-deployment.yaml +++ b/extras/example/k8s/redis-deployment.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: redis spec: replicas: 1 + selector: + matchLabels: + name: redis template: metadata: labels: diff --git a/extras/example/k8s/search-deployment.yaml b/extras/example/k8s/search-deployment.yaml index 85b053c68..2b3471069 100644 --- a/extras/example/k8s/search-deployment.yaml +++ b/extras/example/k8s/search-deployment.yaml @@ -1,9 +1,12 @@ -apiVersion: extensions/v1beta1 +apiVersion: apps/v1 kind: Deployment metadata: name: search spec: replicas: 1 + selector: + matchLabels: + name: search template: metadata: labels: