From b44f8948a4ec4105ce3e989132199dd6757c65e4 Mon Sep 17 00:00:00 2001 From: wojtekt Date: Mon, 14 Oct 2019 12:53:38 +0200 Subject: [PATCH] Add information from Lease to kubectl describe node --- .../kubectl/pkg/describe/versioned/BUILD | 2 ++ .../pkg/describe/versioned/describe.go | 32 +++++++++++++++++-- .../pkg/describe/versioned/describe_test.go | 32 +++++++++++++------ 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/staging/src/k8s.io/kubectl/pkg/describe/versioned/BUILD b/staging/src/k8s.io/kubectl/pkg/describe/versioned/BUILD index e47978fca41..9b09c0548a2 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/versioned/BUILD +++ b/staging/src/k8s.io/kubectl/pkg/describe/versioned/BUILD @@ -13,6 +13,7 @@ go_library( "//staging/src/k8s.io/api/batch/v1:go_default_library", "//staging/src/k8s.io/api/batch/v1beta1:go_default_library", "//staging/src/k8s.io/api/certificates/v1beta1:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/discovery/v1alpha1:go_default_library", "//staging/src/k8s.io/api/extensions/v1beta1:go_default_library", @@ -63,6 +64,7 @@ go_test( "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v1:go_default_library", "//staging/src/k8s.io/api/autoscaling/v2beta2:go_default_library", + "//staging/src/k8s.io/api/coordination/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/discovery/v1alpha1:go_default_library", "//staging/src/k8s.io/api/networking/v1:go_default_library", diff --git a/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe.go b/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe.go index 2aafb490485..bc1d039b824 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe.go @@ -39,6 +39,7 @@ import ( batchv1 "k8s.io/api/batch/v1" batchv1beta1 "k8s.io/api/batch/v1beta1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1" + coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" discoveryv1alpha1 "k8s.io/api/discovery/v1alpha1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" @@ -3000,6 +3001,15 @@ func (d *NodeDescriber) Describe(namespace, name string, describerSettings descr return "", err } + lease, err := d.CoordinationV1().Leases(corev1.NamespaceNodeLease).Get(name, metav1.GetOptions{}) + if err != nil { + if !errors.IsNotFound(err) { + return "", err + } + // Corresponding Lease object doesn't exist - print it accordingly. + lease = nil + } + fieldSelector, err := fields.ParseSelector("spec.nodeName=" + name + ",status.phase!=" + string(corev1.PodSucceeded) + ",status.phase!=" + string(corev1.PodFailed)) if err != nil { return "", err @@ -3026,10 +3036,10 @@ func (d *NodeDescriber) Describe(namespace, name string, describerSettings descr } } - return describeNode(node, nodeNonTerminatedPodsList, events, canViewPods) + return describeNode(node, lease, nodeNonTerminatedPodsList, events, canViewPods) } -func describeNode(node *corev1.Node, nodeNonTerminatedPodsList *corev1.PodList, events *corev1.EventList, canViewPods bool) (string, error) { +func describeNode(node *corev1.Node, lease *coordinationv1.Lease, nodeNonTerminatedPodsList *corev1.PodList, events *corev1.EventList, canViewPods bool) (string, error) { return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) w.Write(LEVEL_0, "Name:\t%s\n", node.Name) @@ -3043,6 +3053,24 @@ func describeNode(node *corev1.Node, nodeNonTerminatedPodsList *corev1.PodList, w.Write(LEVEL_0, "CreationTimestamp:\t%s\n", node.CreationTimestamp.Time.Format(time.RFC1123Z)) printNodeTaintsMultiline(w, "Taints", node.Spec.Taints) w.Write(LEVEL_0, "Unschedulable:\t%v\n", node.Spec.Unschedulable) + + w.Write(LEVEL_0, "Lease:\n") + holderIdentity := "" + if lease != nil && lease.Spec.HolderIdentity != nil { + holderIdentity = *lease.Spec.HolderIdentity + } + w.Write(LEVEL_1, "HolderIdentity:\t%s\n", holderIdentity) + acquireTime := "" + if lease != nil && lease.Spec.AcquireTime != nil { + acquireTime = lease.Spec.AcquireTime.Time.Format(time.RFC1123Z) + } + w.Write(LEVEL_1, "AcquireTime:\t%s\n", acquireTime) + renewTime := "" + if lease != nil && lease.Spec.RenewTime != nil { + renewTime = lease.Spec.RenewTime.Time.Format(time.RFC1123Z) + } + w.Write(LEVEL_1, "RenewTime:\t%s\n", renewTime) + if len(node.Status.Conditions) > 0 { w.Write(LEVEL_0, "Conditions:\n Type\tStatus\tLastHeartbeatTime\tLastTransitionTime\tReason\tMessage\n") w.Write(LEVEL_1, "----\t------\t-----------------\t------------------\t------\t-------\n") diff --git a/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe_test.go b/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe_test.go index 49ddfa6f30d..6204a66f138 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe_test.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe_test.go @@ -28,6 +28,7 @@ import ( appsv1 "k8s.io/api/apps/v1" autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2" + coordinationv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" discoveryv1alpha1 "k8s.io/api/discovery/v1alpha1" networkingv1 "k8s.io/api/networking/v1" @@ -3179,15 +3180,29 @@ Events: ` + "\n" } func TestDescribeNode(t *testing.T) { - fake := fake.NewSimpleClientset(&corev1.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "bar", - Namespace: "foo", + holderIdentity := "holder" + + fake := fake.NewSimpleClientset( + &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + }, + Spec: corev1.NodeSpec{ + Unschedulable: true, + }, }, - Spec: corev1.NodeSpec{ - Unschedulable: true, + &coordinationv1.Lease{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Namespace: corev1.NamespaceNodeLease, + }, + Spec: coordinationv1.LeaseSpec{ + HolderIdentity: &holderIdentity, + AcquireTime: &metav1.MicroTime{Time: time.Now().Add(-time.Hour)}, + RenewTime: &metav1.MicroTime{Time: time.Now()}, + }, }, - }) + ) c := &describeClient{T: t, Namespace: "foo", Interface: fake} d := NodeDescriber{c} out, err := d.Describe("foo", "bar", describe.DescriberSettings{ShowEvents: true}) @@ -3195,13 +3210,12 @@ func TestDescribeNode(t *testing.T) { t.Errorf("unexpected error: %v", err) } - expectedOut := []string{"Unschedulable", "true"} + expectedOut := []string{"Unschedulable", "true", "holder"} for _, expected := range expectedOut { if !strings.Contains(out, expected) { t.Errorf("expected to find %q in output: %q", expected, out) } } - } func TestDescribeStatefulSet(t *testing.T) {