mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Merge pull request #65351 from dtaniwaki/fix-deletion-timestamp-printing
Automatic merge from submit-queue (batch tested with PRs 65993, 65986, 65351, 65996, 65985). 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>. Fix DeletionTimestamp printing **What this PR does / why we need it**: I found a bug that `ObjectMeta.DeletionTimestamp` is not displayed correctly because it's a future time but it uses the time difference until now. So I fixed it by calculating the time difference from now instead of until now. Before this fix: ``` Name: test-pod-7bd594bd96-hf5kk Namespace: default Node: kube-node-2/10.192.0.4 Start Time: Fri, 22 Jun 2018 14:57:09 +0900 Labels: pod-template-hash=3681506852 run=test-pod Annotations: <none> Status: Terminating (lasts <invalid>) Termination Grace Period: 30s IP: 10.244.3.5 Controlled By: ReplicaSet/test-pod-7bd594bd96 Containers: ... ``` After this fix: ``` Name: test-pod-7bd594bd96-85cdd Namespace: default Node: kube-node-2/10.192.0.4 Start Time: Fri, 22 Jun 2018 14:56:44 +0900 Labels: pod-template-hash=3681506852 run=test-pod Annotations: <none> Status: Terminating (lasts 2m) Termination Grace Period: 123s IP: 10.244.3.4 Controlled By: ReplicaSet/test-pod-7bd594bd96 ... ``` Could you consider merging it? We heavily use preemptible jobs in my company and knowing deletion time and grace periods is really important when jobs trap `SIGTERM` and decide if it should continue to run until the deletion time or just stop immediately. **Which issue(s) this PR fixes** N/A **Special notes for your reviewer**: N/A **Release note**: ```release-note NONE ```
This commit is contained in:
commit
5f55fd21cc
@ -643,7 +643,7 @@ func describePod(pod *api.Pod, events *api.EventList) (string, error) {
|
||||
printLabelsMultiline(w, "Labels", pod.Labels)
|
||||
printAnnotationsMultiline(w, "Annotations", pod.Annotations)
|
||||
if pod.DeletionTimestamp != nil {
|
||||
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestamp(*pod.DeletionTimestamp))
|
||||
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestampUntil(*pod.DeletionTimestamp))
|
||||
w.Write(LEVEL_0, "Termination Grace Period:\t%ds\n", *pod.DeletionGracePeriodSeconds)
|
||||
} else {
|
||||
w.Write(LEVEL_0, "Status:\t%s\n", string(pod.Status.Phase))
|
||||
@ -1202,7 +1202,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
|
||||
w.Write(LEVEL_0, "Finalizers:\t%v\n", pv.ObjectMeta.Finalizers)
|
||||
w.Write(LEVEL_0, "StorageClass:\t%s\n", helper.GetPersistentVolumeClass(pv))
|
||||
if pv.ObjectMeta.DeletionTimestamp != nil {
|
||||
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestamp(*pv.ObjectMeta.DeletionTimestamp))
|
||||
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestampUntil(*pv.ObjectMeta.DeletionTimestamp))
|
||||
} else {
|
||||
w.Write(LEVEL_0, "Status:\t%v\n", pv.Status.Phase)
|
||||
}
|
||||
@ -1343,7 +1343,7 @@ func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.E
|
||||
w.Write(LEVEL_0, "Namespace:\t%s\n", pvc.Namespace)
|
||||
w.Write(LEVEL_0, "StorageClass:\t%s\n", helper.GetPersistentVolumeClaimClass(pvc))
|
||||
if pvc.ObjectMeta.DeletionTimestamp != nil {
|
||||
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestamp(*pvc.ObjectMeta.DeletionTimestamp))
|
||||
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestampUntil(*pvc.ObjectMeta.DeletionTimestamp))
|
||||
} else {
|
||||
w.Write(LEVEL_0, "Status:\t%v\n", pvc.Status.Phase)
|
||||
}
|
||||
@ -3130,9 +3130,9 @@ func DescribeEvents(el *api.EventList, w PrefixWriter) {
|
||||
for _, e := range el.Items {
|
||||
var interval string
|
||||
if e.Count > 1 {
|
||||
interval = fmt.Sprintf("%s (x%d over %s)", translateTimestamp(e.LastTimestamp), e.Count, translateTimestamp(e.FirstTimestamp))
|
||||
interval = fmt.Sprintf("%s (x%d over %s)", translateTimestampSince(e.LastTimestamp), e.Count, translateTimestampSince(e.FirstTimestamp))
|
||||
} else {
|
||||
interval = translateTimestamp(e.FirstTimestamp)
|
||||
interval = translateTimestampSince(e.FirstTimestamp)
|
||||
}
|
||||
w.Write(LEVEL_1, "%v\t%v\t%s\t%v\t%v\n",
|
||||
e.Type,
|
||||
|
@ -54,10 +54,14 @@ type describeClient struct {
|
||||
}
|
||||
|
||||
func TestDescribePod(t *testing.T) {
|
||||
deletionTimestamp := metav1.Time{Time: time.Now().UTC().AddDate(10, 0, 0)}
|
||||
gracePeriod := int64(1234)
|
||||
fake := fake.NewSimpleClientset(&api.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
Namespace: "foo",
|
||||
DeletionTimestamp: &deletionTimestamp,
|
||||
DeletionGracePeriodSeconds: &gracePeriod,
|
||||
},
|
||||
})
|
||||
c := &describeClient{T: t, Namespace: "foo", Interface: fake}
|
||||
@ -69,6 +73,9 @@ func TestDescribePod(t *testing.T) {
|
||||
if !strings.Contains(out, "bar") || !strings.Contains(out, "Status:") {
|
||||
t.Errorf("unexpected out: %s", out)
|
||||
}
|
||||
if !strings.Contains(out, "Terminating (lasts 10y)") || !strings.Contains(out, "1234s") {
|
||||
t.Errorf("unexpected out: %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDescribePodNode(t *testing.T) {
|
||||
@ -892,6 +899,7 @@ func TestGetPodsTotalRequests(t *testing.T) {
|
||||
func TestPersistentVolumeDescriber(t *testing.T) {
|
||||
block := api.PersistentVolumeBlock
|
||||
file := api.PersistentVolumeFilesystem
|
||||
deletionTimestamp := metav1.Time{Time: time.Now().UTC().AddDate(10, 0, 0)}
|
||||
testCases := []struct {
|
||||
name string
|
||||
plugin string
|
||||
@ -1137,6 +1145,22 @@ func TestPersistentVolumeDescriber(t *testing.T) {
|
||||
"foo in [val1, val2]",
|
||||
"foo exists"},
|
||||
},
|
||||
{
|
||||
name: "test15",
|
||||
plugin: "local",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bar",
|
||||
DeletionTimestamp: &deletionTimestamp,
|
||||
},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
Local: &api.LocalVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedElements: []string{"Terminating (lasts 10y)"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
@ -1169,6 +1193,7 @@ func TestPersistentVolumeClaimDescriber(t *testing.T) {
|
||||
file := api.PersistentVolumeFilesystem
|
||||
goldClassName := "gold"
|
||||
now := time.Now()
|
||||
deletionTimestamp := metav1.Time{Time: time.Now().UTC().AddDate(10, 0, 0)}
|
||||
testCases := []struct {
|
||||
name string
|
||||
pvc *api.PersistentVolumeClaim
|
||||
@ -1316,6 +1341,22 @@ func TestPersistentVolumeClaimDescriber(t *testing.T) {
|
||||
},
|
||||
expectedElements: []string{"Conditions", "Message", "User request resize"},
|
||||
},
|
||||
{
|
||||
name: "deletion-timestamp",
|
||||
pvc: &api.PersistentVolumeClaim{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "foo",
|
||||
Name: "bar",
|
||||
DeletionTimestamp: &deletionTimestamp,
|
||||
},
|
||||
Spec: api.PersistentVolumeClaimSpec{
|
||||
VolumeName: "volume10",
|
||||
StorageClassName: &goldClassName,
|
||||
},
|
||||
Status: api.PersistentVolumeClaimStatus{},
|
||||
},
|
||||
expectedElements: []string{"Terminating (lasts 10y)"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
@ -467,7 +467,7 @@ func printObjectMeta(obj runtime.Object, options printers.PrintOptions) ([]metav
|
||||
row := metav1beta1.TableRow{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
row.Cells = append(row.Cells, m.GetName(), translateTimestamp(m.GetCreationTimestamp()))
|
||||
row.Cells = append(row.Cells, m.GetName(), translateTimestampSince(m.GetCreationTimestamp()))
|
||||
rows = append(rows, row)
|
||||
return rows, nil
|
||||
}
|
||||
@ -507,9 +507,9 @@ func formatEndpoints(endpoints *api.Endpoints, ports sets.String) string {
|
||||
return ret
|
||||
}
|
||||
|
||||
// translateTimestamp returns the elapsed time since timestamp in
|
||||
// translateTimestampSince returns the elapsed time since timestamp in
|
||||
// human-readable approximation.
|
||||
func translateTimestamp(timestamp metav1.Time) string {
|
||||
func translateTimestampSince(timestamp metav1.Time) string {
|
||||
if timestamp.IsZero() {
|
||||
return "<unknown>"
|
||||
}
|
||||
@ -517,6 +517,16 @@ func translateTimestamp(timestamp metav1.Time) string {
|
||||
return duration.ShortHumanDuration(time.Since(timestamp.Time))
|
||||
}
|
||||
|
||||
// translateTimestampUntil returns the elapsed time until timestamp in
|
||||
// human-readable approximation.
|
||||
func translateTimestampUntil(timestamp metav1.Time) string {
|
||||
if timestamp.IsZero() {
|
||||
return "<unknown>"
|
||||
}
|
||||
|
||||
return duration.ShortHumanDuration(time.Until(timestamp.Time))
|
||||
}
|
||||
|
||||
var (
|
||||
podSuccessConditions = []metav1beta1.TableRowCondition{{Type: metav1beta1.RowCompleted, Status: metav1beta1.ConditionTrue, Reason: string(api.PodSucceeded), Message: "The pod has completed successfully."}}
|
||||
podFailedConditions = []metav1beta1.TableRowCondition{{Type: metav1beta1.RowCompleted, Status: metav1beta1.ConditionTrue, Reason: string(api.PodFailed), Message: "The pod failed."}}
|
||||
@ -618,7 +628,7 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR
|
||||
reason = "Terminating"
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, int64(restarts), translateTimestamp(pod.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, int64(restarts), translateTimestampSince(pod.CreationTimestamp))
|
||||
|
||||
if options.Wide {
|
||||
nodeName := pod.Spec.NodeName
|
||||
@ -678,7 +688,7 @@ func printPodDisruptionBudget(obj *policy.PodDisruptionBudget, options printers.
|
||||
maxUnavailable = "N/A"
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, int64(obj.Status.PodDisruptionsAllowed), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, int64(obj.Status.PodDisruptionsAllowed), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -704,7 +714,7 @@ func printReplicationController(obj *api.ReplicationController, options printers
|
||||
currentReplicas := obj.Status.Replicas
|
||||
readyReplicas := obj.Status.ReadyReplicas
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestampSince(obj.CreationTimestamp))
|
||||
if options.Wide {
|
||||
names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
|
||||
row.Cells = append(row.Cells, names, images, labels.FormatLabels(obj.Spec.Selector))
|
||||
@ -733,7 +743,7 @@ func printReplicaSet(obj *extensions.ReplicaSet, options printers.PrintOptions)
|
||||
currentReplicas := obj.Status.Replicas
|
||||
readyReplicas := obj.Status.ReadyReplicas
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestampSince(obj.CreationTimestamp))
|
||||
if options.Wide {
|
||||
names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
|
||||
row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector))
|
||||
@ -781,7 +791,7 @@ func printJob(obj *batch.Job, options printers.PrintOptions) ([]metav1beta1.Tabl
|
||||
jobDuration = duration.HumanDuration(obj.Status.CompletionTime.Sub(obj.Status.StartTime.Time))
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, completions, jobDuration, translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, completions, jobDuration, translateTimestampSince(obj.CreationTimestamp))
|
||||
if options.Wide {
|
||||
names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
|
||||
row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector))
|
||||
@ -808,10 +818,10 @@ func printCronJob(obj *batch.CronJob, options printers.PrintOptions) ([]metav1be
|
||||
|
||||
lastScheduleTime := "<none>"
|
||||
if obj.Status.LastScheduleTime != nil {
|
||||
lastScheduleTime = translateTimestamp(*obj.Status.LastScheduleTime)
|
||||
lastScheduleTime = translateTimestampSince(*obj.Status.LastScheduleTime)
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), int64(len(obj.Status.Active)), lastScheduleTime, translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), int64(len(obj.Status.Active)), lastScheduleTime, translateTimestampSince(obj.CreationTimestamp))
|
||||
if options.Wide {
|
||||
names, images := layoutContainerCells(obj.Spec.JobTemplate.Spec.Template.Spec.Containers)
|
||||
row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.JobTemplate.Spec.Selector))
|
||||
@ -910,7 +920,7 @@ func printService(obj *api.Service, options printers.PrintOptions) ([]metav1beta
|
||||
svcPorts = "<none>"
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, string(svcType), internalIP, externalIP, svcPorts, translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, string(svcType), internalIP, externalIP, svcPorts, translateTimestampSince(obj.CreationTimestamp))
|
||||
if options.Wide {
|
||||
row.Cells = append(row.Cells, labels.FormatLabels(obj.Spec.Selector))
|
||||
}
|
||||
@ -974,7 +984,7 @@ func printIngress(obj *extensions.Ingress, options printers.PrintOptions) ([]met
|
||||
hosts := formatHosts(obj.Spec.Rules)
|
||||
address := loadBalancerStatusStringer(obj.Status.LoadBalancer, options.Wide)
|
||||
ports := formatPorts(obj.Spec.TLS)
|
||||
createTime := translateTimestamp(obj.CreationTimestamp)
|
||||
createTime := translateTimestampSince(obj.CreationTimestamp)
|
||||
row.Cells = append(row.Cells, obj.Name, hosts, address, ports, createTime)
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
@ -997,7 +1007,7 @@ func printStatefulSet(obj *apps.StatefulSet, options printers.PrintOptions) ([]m
|
||||
}
|
||||
desiredReplicas := obj.Spec.Replicas
|
||||
currentReplicas := obj.Status.Replicas
|
||||
createTime := translateTimestamp(obj.CreationTimestamp)
|
||||
createTime := translateTimestampSince(obj.CreationTimestamp)
|
||||
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), createTime)
|
||||
if options.Wide {
|
||||
names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
|
||||
@ -1029,7 +1039,7 @@ func printDaemonSet(obj *extensions.DaemonSet, options printers.PrintOptions) ([
|
||||
numberUpdated := obj.Status.UpdatedNumberScheduled
|
||||
numberAvailable := obj.Status.NumberAvailable
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, int64(desiredScheduled), int64(currentScheduled), int64(numberReady), int64(numberUpdated), int64(numberAvailable), labels.FormatLabels(obj.Spec.Template.Spec.NodeSelector), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, int64(desiredScheduled), int64(currentScheduled), int64(numberReady), int64(numberUpdated), int64(numberAvailable), labels.FormatLabels(obj.Spec.Template.Spec.NodeSelector), translateTimestampSince(obj.CreationTimestamp))
|
||||
if options.Wide {
|
||||
names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
|
||||
row.Cells = append(row.Cells, names, images, metav1.FormatLabelSelector(obj.Spec.Selector))
|
||||
@ -1053,7 +1063,7 @@ func printEndpoints(obj *api.Endpoints, options printers.PrintOptions) ([]metav1
|
||||
row := metav1beta1.TableRow{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
row.Cells = append(row.Cells, obj.Name, formatEndpoints(obj, nil), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, formatEndpoints(obj, nil), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1073,7 +1083,7 @@ func printNamespace(obj *api.Namespace, options printers.PrintOptions) ([]metav1
|
||||
row := metav1beta1.TableRow{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
row.Cells = append(row.Cells, obj.Name, string(obj.Status.Phase), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, string(obj.Status.Phase), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1093,7 +1103,7 @@ func printSecret(obj *api.Secret, options printers.PrintOptions) ([]metav1beta1.
|
||||
row := metav1beta1.TableRow{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
row.Cells = append(row.Cells, obj.Name, string(obj.Type), int64(len(obj.Data)), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, string(obj.Type), int64(len(obj.Data)), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1113,7 +1123,7 @@ func printServiceAccount(obj *api.ServiceAccount, options printers.PrintOptions)
|
||||
row := metav1beta1.TableRow{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
row.Cells = append(row.Cells, obj.Name, int64(len(obj.Secrets)), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, int64(len(obj.Secrets)), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1162,7 +1172,7 @@ func printNode(obj *api.Node, options printers.PrintOptions) ([]metav1beta1.Tabl
|
||||
roles = "<none>"
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, strings.Join(status, ","), roles, translateTimestamp(obj.CreationTimestamp), obj.Status.NodeInfo.KubeletVersion)
|
||||
row.Cells = append(row.Cells, obj.Name, strings.Join(status, ","), roles, translateTimestampSince(obj.CreationTimestamp), obj.Status.NodeInfo.KubeletVersion)
|
||||
if options.Wide {
|
||||
osImage, kernelVersion, crVersion := obj.Status.NodeInfo.OSImage, obj.Status.NodeInfo.KernelVersion, obj.Status.NodeInfo.ContainerRuntimeVersion
|
||||
if osImage == "" {
|
||||
@ -1260,7 +1270,7 @@ func printPersistentVolume(obj *api.PersistentVolume, options printers.PrintOpti
|
||||
row.Cells = append(row.Cells, obj.Name, aSize, modesStr, reclaimPolicyStr,
|
||||
string(phase), claimRefUID, helper.GetPersistentVolumeClass(obj),
|
||||
obj.Status.Reason,
|
||||
translateTimestamp(obj.CreationTimestamp))
|
||||
translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1295,7 +1305,7 @@ func printPersistentVolumeClaim(obj *api.PersistentVolumeClaim, options printers
|
||||
capacity = storage.String()
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, string(phase), obj.Spec.VolumeName, capacity, accessModes, helper.GetPersistentVolumeClaimClass(obj), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, string(phase), obj.Spec.VolumeName, capacity, accessModes, helper.GetPersistentVolumeClaimClass(obj), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1321,8 +1331,8 @@ func printEvent(obj *api.Event, options printers.PrintOptions) ([]metav1beta1.Ta
|
||||
FirstTimestamp = obj.FirstTimestamp.String()
|
||||
LastTimestamp = obj.LastTimestamp.String()
|
||||
} else {
|
||||
FirstTimestamp = translateTimestamp(obj.FirstTimestamp)
|
||||
LastTimestamp = translateTimestamp(obj.LastTimestamp)
|
||||
FirstTimestamp = translateTimestampSince(obj.FirstTimestamp)
|
||||
LastTimestamp = translateTimestampSince(obj.LastTimestamp)
|
||||
}
|
||||
row.Cells = append(row.Cells, LastTimestamp, FirstTimestamp,
|
||||
int64(obj.Count), obj.Name, obj.InvolvedObject.Kind,
|
||||
@ -1351,7 +1361,7 @@ func printRoleBinding(obj *rbac.RoleBinding, options printers.PrintOptions) ([]m
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, translateTimestampSince(obj.CreationTimestamp))
|
||||
if options.Wide {
|
||||
roleRef := fmt.Sprintf("%s/%s", obj.RoleRef.Kind, obj.RoleRef.Name)
|
||||
users, groups, sas, _ := rbac.SubjectsStrings(obj.Subjects)
|
||||
@ -1378,7 +1388,7 @@ func printClusterRoleBinding(obj *rbac.ClusterRoleBinding, options printers.Prin
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, translateTimestampSince(obj.CreationTimestamp))
|
||||
if options.Wide {
|
||||
roleRef := fmt.Sprintf("%s/%s", obj.RoleRef.Kind, obj.RoleRef.Name)
|
||||
users, groups, sas, _ := rbac.SubjectsStrings(obj.Subjects)
|
||||
@ -1408,7 +1418,7 @@ func printCertificateSigningRequest(obj *certificates.CertificateSigningRequest,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
row.Cells = append(row.Cells, obj.Name, translateTimestamp(obj.CreationTimestamp), obj.Spec.Username, status)
|
||||
row.Cells = append(row.Cells, obj.Name, translateTimestampSince(obj.CreationTimestamp), obj.Spec.Username, status)
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1501,7 +1511,7 @@ func printDeployment(obj *extensions.Deployment, options printers.PrintOptions)
|
||||
currentReplicas := obj.Status.Replicas
|
||||
updatedReplicas := obj.Status.UpdatedReplicas
|
||||
availableReplicas := obj.Status.AvailableReplicas
|
||||
age := translateTimestamp(obj.CreationTimestamp)
|
||||
age := translateTimestampSince(obj.CreationTimestamp)
|
||||
containers := obj.Spec.Template.Spec.Containers
|
||||
selector, err := metav1.LabelSelectorAsSelector(obj.Spec.Selector)
|
||||
if err != nil {
|
||||
@ -1617,7 +1627,7 @@ func printHorizontalPodAutoscaler(obj *autoscaling.HorizontalPodAutoscaler, opti
|
||||
}
|
||||
maxPods := obj.Spec.MaxReplicas
|
||||
currentReplicas := obj.Status.CurrentReplicas
|
||||
row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, int64(maxPods), int64(currentReplicas), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, int64(maxPods), int64(currentReplicas), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1637,7 +1647,7 @@ func printConfigMap(obj *api.ConfigMap, options printers.PrintOptions) ([]metav1
|
||||
row := metav1beta1.TableRow{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
row.Cells = append(row.Cells, obj.Name, int64(len(obj.Data)), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, int64(len(obj.Data)), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1690,7 +1700,7 @@ func printNetworkPolicy(obj *networking.NetworkPolicy, options printers.PrintOpt
|
||||
row := metav1beta1.TableRow{
|
||||
Object: runtime.RawExtension{Object: obj},
|
||||
}
|
||||
row.Cells = append(row.Cells, obj.Name, metav1.FormatLabelSelector(&obj.Spec.PodSelector), translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, metav1.FormatLabelSelector(&obj.Spec.PodSelector), translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1716,7 +1726,7 @@ func printStorageClass(obj *storage.StorageClass, options printers.PrintOptions)
|
||||
name += " (default)"
|
||||
}
|
||||
provtype := obj.Provisioner
|
||||
row.Cells = append(row.Cells, name, provtype, translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, name, provtype, translateTimestampSince(obj.CreationTimestamp))
|
||||
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
@ -1742,7 +1752,7 @@ func printLease(obj *coordination.Lease, options printers.PrintOptions) ([]metav
|
||||
if obj.Spec.HolderIdentity != nil {
|
||||
holderIdentity = *obj.Spec.HolderIdentity
|
||||
}
|
||||
row.Cells = append(row.Cells, obj.Name, holderIdentity, translateTimestamp(obj.CreationTimestamp))
|
||||
row.Cells = append(row.Cells, obj.Name, holderIdentity, translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
@ -1827,7 +1837,7 @@ func printControllerRevision(obj *apps.ControllerRevision, options printers.Prin
|
||||
controllerName = printers.FormatResourceName(gvk.GroupKind(), controllerRef.Name, withKind)
|
||||
}
|
||||
revision := obj.Revision
|
||||
age := translateTimestamp(obj.CreationTimestamp)
|
||||
age := translateTimestampSince(obj.CreationTimestamp)
|
||||
row.Cells = append(row.Cells, obj.Name, controllerName, revision, age)
|
||||
return []metav1beta1.TableRow{row}, nil
|
||||
}
|
||||
|
@ -1919,18 +1919,43 @@ type stringTestList []struct {
|
||||
name, got, exp string
|
||||
}
|
||||
|
||||
func TestTranslateTimestamp(t *testing.T) {
|
||||
func TestTranslateTimestampSince(t *testing.T) {
|
||||
tl := stringTestList{
|
||||
{"a while from now", translateTimestamp(metav1.Time{Time: time.Now().Add(2.1e9)}), "<invalid>"},
|
||||
{"almost now", translateTimestamp(metav1.Time{Time: time.Now().Add(1.9e9)}), "0s"},
|
||||
{"now", translateTimestamp(metav1.Time{Time: time.Now()}), "0s"},
|
||||
{"unknown", translateTimestamp(metav1.Time{}), "<unknown>"},
|
||||
{"30 seconds ago", translateTimestamp(metav1.Time{Time: time.Now().Add(-3e10)}), "30s"},
|
||||
{"5 minutes ago", translateTimestamp(metav1.Time{Time: time.Now().Add(-3e11)}), "5m"},
|
||||
{"an hour ago", translateTimestamp(metav1.Time{Time: time.Now().Add(-6e12)}), "1h"},
|
||||
{"2 days ago", translateTimestamp(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -2)}), "2d"},
|
||||
{"months ago", translateTimestamp(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -90)}), "90d"},
|
||||
{"10 years ago", translateTimestamp(metav1.Time{Time: time.Now().UTC().AddDate(-10, 0, 0)}), "10y"},
|
||||
{"a while from now", translateTimestampSince(metav1.Time{Time: time.Now().Add(2.1e9)}), "<invalid>"},
|
||||
{"almost now", translateTimestampSince(metav1.Time{Time: time.Now().Add(1.9e9)}), "0s"},
|
||||
{"now", translateTimestampSince(metav1.Time{Time: time.Now()}), "0s"},
|
||||
{"unknown", translateTimestampSince(metav1.Time{}), "<unknown>"},
|
||||
{"30 seconds ago", translateTimestampSince(metav1.Time{Time: time.Now().Add(-3e10)}), "30s"},
|
||||
{"5 minutes ago", translateTimestampSince(metav1.Time{Time: time.Now().Add(-3e11)}), "5m"},
|
||||
{"an hour ago", translateTimestampSince(metav1.Time{Time: time.Now().Add(-6e12)}), "1h"},
|
||||
{"2 days ago", translateTimestampSince(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -2)}), "2d"},
|
||||
{"months ago", translateTimestampSince(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, -90)}), "90d"},
|
||||
{"10 years ago", translateTimestampSince(metav1.Time{Time: time.Now().UTC().AddDate(-10, 0, 0)}), "10y"},
|
||||
}
|
||||
for _, test := range tl {
|
||||
if test.got != test.exp {
|
||||
t.Errorf("On %v, expected '%v', but got '%v'",
|
||||
test.name, test.exp, test.got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTranslateTimestampUntil(t *testing.T) {
|
||||
// Since this method compares the time with time.Now() internally,
|
||||
// small buffers of 0.1 seconds are added on comparing times to consider method call overhead.
|
||||
// Otherwise, the output strings become shorter than expected.
|
||||
const buf = 1e8
|
||||
tl := stringTestList{
|
||||
{"a while ago", translateTimestampUntil(metav1.Time{Time: time.Now().Add(-2.1e9)}), "<invalid>"},
|
||||
{"almost now", translateTimestampUntil(metav1.Time{Time: time.Now().Add(-1.9e9)}), "0s"},
|
||||
{"now", translateTimestampUntil(metav1.Time{Time: time.Now()}), "0s"},
|
||||
{"unknown", translateTimestampUntil(metav1.Time{}), "<unknown>"},
|
||||
{"in 30 seconds", translateTimestampUntil(metav1.Time{Time: time.Now().Add(3e10 + buf)}), "30s"},
|
||||
{"in 5 minutes", translateTimestampUntil(metav1.Time{Time: time.Now().Add(3e11 + buf)}), "5m"},
|
||||
{"in an hour", translateTimestampUntil(metav1.Time{Time: time.Now().Add(6e12 + buf)}), "1h"},
|
||||
{"in 2 days", translateTimestampUntil(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, 2).Add(buf)}), "2d"},
|
||||
{"in months", translateTimestampUntil(metav1.Time{Time: time.Now().UTC().AddDate(0, 0, 90).Add(buf)}), "90d"},
|
||||
{"in 10 years", translateTimestampUntil(metav1.Time{Time: time.Now().UTC().AddDate(10, 0, 0).Add(buf)}), "10y"},
|
||||
}
|
||||
for _, test := range tl {
|
||||
if test.got != test.exp {
|
||||
|
Loading…
Reference in New Issue
Block a user