vendor updates

This commit is contained in:
Serguei Bezverkhi
2018-03-06 17:33:18 -05:00
parent 4b3ebc171b
commit e9033989a0
5854 changed files with 248382 additions and 119809 deletions

View File

@ -13,8 +13,7 @@ go_test(
"printers_test.go",
"sorted_resource_name_list_test.go",
],
importpath = "k8s.io/kubernetes/pkg/printers/internalversion",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/api/testapi:go_default_library",
@ -28,7 +27,6 @@ go_test(
"//pkg/apis/storage:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/kubectl/testing:go_default_library",
"//pkg/printers:go_default_library",
"//pkg/util/pointer:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
@ -38,7 +36,7 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/yaml:go_default_library",
@ -98,12 +96,13 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/duration:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/client-go/dynamic:go_default_library",

View File

@ -87,7 +87,7 @@ type PrefixWriter interface {
Write(level int, format string, a ...interface{})
// WriteLine writes an entire line with no indentation level.
WriteLine(a ...interface{})
// Flush forces indendation to be reset.
// Flush forces indentation to be reset.
Flush()
}
@ -636,7 +636,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 (expires %s)\n", pod.DeletionTimestamp.Time.Format(time.RFC1123Z))
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestamp(*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))
@ -651,6 +651,9 @@ func describePod(pod *api.Pod, events *api.EventList) (string, error) {
if controlledBy := printController(pod); len(controlledBy) > 0 {
w.Write(LEVEL_0, "Controlled By:\t%s\n", controlledBy)
}
if len(pod.Status.NominatedNodeName) > 0 {
w.Write(LEVEL_0, "NominatedNodeName:\t%s\n", pod.Status.NominatedNodeName)
}
if len(pod.Spec.InitContainers) > 0 {
describeContainers("Init Containers", pod.Spec.InitContainers, pod.Status.InitContainerStatuses, EnvValueRetriever(pod), w, "")
@ -943,7 +946,7 @@ func printAzureDiskVolumeSource(d *api.AzureDiskVolumeSource, w PrefixWriter) {
func printVsphereVolumeSource(vsphere *api.VsphereVirtualDiskVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tvSphereVolume (a Persistent Disk resource in vSphere)\n"+
" VolumePath:\t%v\n"+
" FSType:\t%v\n",
" FSType:\t%v\n"+
" StoragePolicyName:\t%v\n",
vsphere.VolumePath, vsphere.FSType, vsphere.StoragePolicyName)
}
@ -1076,12 +1079,22 @@ func printAzureFilePersistentVolumeSource(azureFile *api.AzureFilePersistentVolu
azureFile.SecretName, ns, azureFile.ShareName, azureFile.ReadOnly)
}
func printFlexPersistentVolumeSource(flex *api.FlexPersistentVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tFlexVolume (a generic volume resource that is provisioned/attached using an exec based plugin)\n"+
" Driver:\t%v\n"+
" FSType:\t%v\n"+
" SecretRef:\t%v\n"+
" ReadOnly:\t%v\n"+
" Options:\t%v\n",
flex.Driver, flex.FSType, flex.SecretRef, flex.ReadOnly, flex.Options)
}
func printFlexVolumeSource(flex *api.FlexVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tFlexVolume (a generic volume resource that is provisioned/attached using an exec based plugin)\n"+
" Driver:\t%v\n"+
" FSType:\t%v\n"+
" SecretRef:\t%v\n"+
" ReadOnly:\t%v\n",
" ReadOnly:\t%v\n"+
" Options:\t%v\n",
flex.Driver, flex.FSType, flex.SecretRef, flex.ReadOnly, flex.Options)
}
@ -1096,7 +1109,7 @@ func printFlockerVolumeSource(flocker *api.FlockerVolumeSource, w PrefixWriter)
func printCSIPersistentVolumeSource(csi *api.CSIPersistentVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tCSI (a Container Storage Interface (CSI) volume source)\n"+
" Driver:\t%v\n"+
" VolumeHandle:\t%v\n",
" VolumeHandle:\t%v\n"+
" ReadOnly:\t%v\n",
csi.Driver, csi.VolumeHandle, csi.ReadOnly)
}
@ -1121,14 +1134,61 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe
return describePersistentVolume(pv, events)
}
func printVolumeNodeAffinity(w PrefixWriter, affinity *api.VolumeNodeAffinity) {
w.Write(LEVEL_0, "Node Affinity:\t")
if affinity == nil || affinity.Required == nil {
w.WriteLine("<none>")
return
}
w.WriteLine("")
if affinity.Required != nil {
w.Write(LEVEL_1, "Required Terms:\t")
if len(affinity.Required.NodeSelectorTerms) == 0 {
w.WriteLine("<none>")
} else {
w.WriteLine("")
for i, term := range affinity.Required.NodeSelectorTerms {
printNodeSelectorTermsMultilineWithIndent(w, LEVEL_2, fmt.Sprintf("Term %v", i), "\t", term.MatchExpressions)
}
}
}
}
// printLabelsMultiline prints multiple labels with a user-defined alignment.
func printNodeSelectorTermsMultilineWithIndent(w PrefixWriter, indentLevel int, title, innerIndent string, reqs []api.NodeSelectorRequirement) {
w.Write(indentLevel, "%s:%s", title, innerIndent)
if len(reqs) == 0 {
w.WriteLine("<none>")
return
}
for i, req := range reqs {
if i != 0 {
w.Write(indentLevel, "%s", innerIndent)
}
exprStr := fmt.Sprintf("%s %s", req.Key, strings.ToLower(string(req.Operator)))
if len(req.Values) > 0 {
exprStr = fmt.Sprintf("%s [%s]", exprStr, strings.Join(req.Values, ", "))
}
w.Write(LEVEL_0, "%s\n", exprStr)
}
}
func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", pv.Name)
printLabelsMultiline(w, "Labels", pv.Labels)
printAnnotationsMultiline(w, "Annotations", pv.Annotations)
w.Write(LEVEL_0, "Finalizers:\t%v\n", pv.ObjectMeta.Finalizers)
w.Write(LEVEL_0, "StorageClass:\t%s\n", helper.GetPersistentVolumeClass(pv))
w.Write(LEVEL_0, "Status:\t%s\n", pv.Status.Phase)
if pv.ObjectMeta.DeletionTimestamp != nil {
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestamp(*pv.ObjectMeta.DeletionTimestamp))
} else {
w.Write(LEVEL_0, "Status:\t%v\n", pv.Status.Phase)
}
if pv.Spec.ClaimRef != nil {
w.Write(LEVEL_0, "Claim:\t%s\n", pv.Spec.ClaimRef.Namespace+"/"+pv.Spec.ClaimRef.Name)
} else {
@ -1141,6 +1201,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
}
storage := pv.Spec.Capacity[api.ResourceStorage]
w.Write(LEVEL_0, "Capacity:\t%s\n", storage.String())
printVolumeNodeAffinity(w, pv.Spec.NodeAffinity)
w.Write(LEVEL_0, "Message:\t%s\n", pv.Status.Message)
w.Write(LEVEL_0, "Source:\n")
@ -1184,7 +1245,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
case pv.Spec.AzureFile != nil:
printAzureFilePersistentVolumeSource(pv.Spec.AzureFile, w)
case pv.Spec.FlexVolume != nil:
printFlexVolumeSource(pv.Spec.FlexVolume, w)
printFlexPersistentVolumeSource(pv.Spec.FlexVolume, w)
case pv.Spec.Flocker != nil:
printFlockerVolumeSource(pv.Spec.Flocker, w)
case pv.Spec.CSI != nil:
@ -1225,7 +1286,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 (since %s)\n", pvc.ObjectMeta.DeletionTimestamp.Time.Format(time.RFC1123Z))
w.Write(LEVEL_0, "Status:\tTerminating (lasts %s)\n", translateTimestamp(*pvc.ObjectMeta.DeletionTimestamp))
} else {
w.Write(LEVEL_0, "Status:\t%v\n", pvc.Status.Phase)
}
@ -1305,11 +1366,13 @@ func describeContainerBasicInfo(container api.Container, status api.ContainerSta
if strings.Contains(portString, ",") {
w.Write(LEVEL_2, "Ports:\t%s\n", portString)
} else {
if len(portString) == 0 {
w.Write(LEVEL_2, "Port:\t<none>\n")
} else {
w.Write(LEVEL_2, "Port:\t%s\n", portString)
}
w.Write(LEVEL_2, "Port:\t%s\n", stringOrNone(portString))
}
hostPortString := describeContainerHostPorts(container.Ports)
if strings.Contains(hostPortString, ",") {
w.Write(LEVEL_2, "Host Ports:\t%s\n", hostPortString)
} else {
w.Write(LEVEL_2, "Host Port:\t%s\n", stringOrNone(hostPortString))
}
}
@ -1321,6 +1384,14 @@ func describeContainerPorts(cPorts []api.ContainerPort) string {
return strings.Join(ports, ", ")
}
func describeContainerHostPorts(cPorts []api.ContainerPort) string {
ports := make([]string, 0, len(cPorts))
for _, cPort := range cPorts {
ports = append(ports, fmt.Sprintf("%d/%s", cPort.HostPort, cPort.Protocol))
}
return strings.Join(ports, ", ")
}
func describeContainerCommand(container api.Container, w PrefixWriter) {
if len(container.Command) > 0 {
w.Write(LEVEL_2, "Command:\n")
@ -2054,12 +2125,7 @@ func describeIngressTLS(w PrefixWriter, ingTLS []extensions.IngressTLS) {
func describeIngressAnnotations(w PrefixWriter, annotations map[string]string) {
w.Write(LEVEL_0, "Annotations:\n")
for k, v := range annotations {
if !strings.HasPrefix(k, "ingress") {
continue
}
parts := strings.Split(k, "/")
name := parts[len(parts)-1]
w.Write(LEVEL_1, "%v:\t%s\n", name, v)
w.Write(LEVEL_1, "%v:\t%s\n", k, v)
}
return
}
@ -2565,8 +2631,9 @@ func describeNode(node *api.Node, nodeNonTerminatedPodsList *api.PodList, events
}
printLabelsMultiline(w, "Labels", node.Labels)
printAnnotationsMultiline(w, "Annotations", node.Annotations)
printNodeTaintsMultiline(w, "Taints", node.Spec.Taints)
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)
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")
@ -2625,10 +2692,11 @@ func describeNode(node *api.Node, nodeNonTerminatedPodsList *api.PodList, events
if len(node.Spec.ExternalID) > 0 {
w.Write(LEVEL_0, "ExternalID:\t%s\n", node.Spec.ExternalID)
}
if len(node.Spec.ProviderID) > 0 {
w.Write(LEVEL_0, "ProviderID:\t%s\n", node.Spec.ProviderID)
}
if canViewPods && nodeNonTerminatedPodsList != nil {
if err := describeNodeResource(nodeNonTerminatedPodsList, node, w); err != nil {
return err
}
describeNodeResource(nodeNonTerminatedPodsList, node, w)
} else {
w.Write(LEVEL_0, "Pods:\tnot authorized\n")
}
@ -2798,6 +2866,22 @@ func describeHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, e
w.Write(LEVEL_0, "Metrics:\t( current / target )\n")
for i, metric := range hpa.Spec.Metrics {
switch metric.Type {
case autoscaling.ExternalMetricSourceType:
if metric.External.TargetAverageValue != nil {
current := "<unknown>"
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].External != nil &&
hpa.Status.CurrentMetrics[i].External.CurrentAverageValue != nil {
current = hpa.Status.CurrentMetrics[i].External.CurrentAverageValue.String()
}
w.Write(LEVEL_1, "%q (target average value):\t%s / %s\n", metric.External.MetricName, current, metric.External.TargetAverageValue.String())
} else {
current := "<unknown>"
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].External != nil {
current = hpa.Status.CurrentMetrics[i].External.CurrentValue.String()
}
w.Write(LEVEL_1, "%q (target value):\t%s / %s\n", metric.External.MetricName, current, metric.External.TargetValue.String())
}
case autoscaling.PodsMetricSourceType:
current := "<unknown>"
if len(hpa.Status.CurrentMetrics) > i && hpa.Status.CurrentMetrics[i].Pods != nil {
@ -2868,7 +2952,7 @@ func describeHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, e
})
}
func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node, w PrefixWriter) error {
func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node, w PrefixWriter) {
w.Write(LEVEL_0, "Non-terminated Pods:\t(%d in total)\n", len(nodeNonTerminatedPodsList.Items))
w.Write(LEVEL_1, "Namespace\tName\t\tCPU Requests\tCPU Limits\tMemory Requests\tMemory Limits\n")
w.Write(LEVEL_1, "---------\t----\t\t------------\t----------\t---------------\t-------------\n")
@ -2878,10 +2962,7 @@ func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node
}
for _, pod := range nodeNonTerminatedPodsList.Items {
req, limit, err := resourcehelper.PodRequestsAndLimits(&pod)
if err != nil {
return err
}
req, limit := resourcehelper.PodRequestsAndLimits(&pod)
cpuReq, cpuLimit, memoryReq, memoryLimit := req[api.ResourceCPU], limit[api.ResourceCPU], req[api.ResourceMemory], limit[api.ResourceMemory]
fractionCpuReq := float64(cpuReq.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100
fractionCpuLimit := float64(cpuLimit.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100
@ -2894,28 +2975,29 @@ func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node
w.Write(LEVEL_0, "Allocated resources:\n (Total limits may be over 100 percent, i.e., overcommitted.)\n CPU Requests\tCPU Limits\tMemory Requests\tMemory Limits\n")
w.Write(LEVEL_1, "------------\t----------\t---------------\t-------------\n")
reqs, limits, err := getPodsTotalRequestsAndLimits(nodeNonTerminatedPodsList)
if err != nil {
return err
}
reqs, limits := getPodsTotalRequestsAndLimits(nodeNonTerminatedPodsList)
cpuReqs, cpuLimits, memoryReqs, memoryLimits := reqs[api.ResourceCPU], limits[api.ResourceCPU], reqs[api.ResourceMemory], limits[api.ResourceMemory]
fractionCpuReqs := float64(cpuReqs.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100
fractionCpuLimits := float64(cpuLimits.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100
fractionMemoryReqs := float64(memoryReqs.Value()) / float64(allocatable.Memory().Value()) * 100
fractionMemoryLimits := float64(memoryLimits.Value()) / float64(allocatable.Memory().Value()) * 100
fractionCpuReqs := float64(0)
fractionCpuLimits := float64(0)
if allocatable.Cpu().MilliValue() != 0 {
fractionCpuReqs = float64(cpuReqs.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100
fractionCpuLimits = float64(cpuLimits.MilliValue()) / float64(allocatable.Cpu().MilliValue()) * 100
}
fractionMemoryReqs := float64(0)
fractionMemoryLimits := float64(0)
if allocatable.Memory().Value() != 0 {
fractionMemoryReqs = float64(memoryReqs.Value()) / float64(allocatable.Memory().Value()) * 100
fractionMemoryLimits = float64(memoryLimits.Value()) / float64(allocatable.Memory().Value()) * 100
}
w.Write(LEVEL_1, "%s (%d%%)\t%s (%d%%)\t%s (%d%%)\t%s (%d%%)\n",
cpuReqs.String(), int64(fractionCpuReqs), cpuLimits.String(), int64(fractionCpuLimits),
memoryReqs.String(), int64(fractionMemoryReqs), memoryLimits.String(), int64(fractionMemoryLimits))
return nil
}
func getPodsTotalRequestsAndLimits(podList *api.PodList) (reqs map[api.ResourceName]resource.Quantity, limits map[api.ResourceName]resource.Quantity, err error) {
func getPodsTotalRequestsAndLimits(podList *api.PodList) (reqs map[api.ResourceName]resource.Quantity, limits map[api.ResourceName]resource.Quantity) {
reqs, limits = map[api.ResourceName]resource.Quantity{}, map[api.ResourceName]resource.Quantity{}
for _, pod := range podList.Items {
podReqs, podLimits, err := resourcehelper.PodRequestsAndLimits(&pod)
if err != nil {
return nil, nil, err
}
podReqs, podLimits := resourcehelper.PodRequestsAndLimits(&pod)
for podReqName, podReqValue := range podReqs {
if value, ok := reqs[podReqName]; !ok {
reqs[podReqName] = *podReqValue.Copy()
@ -3261,6 +3343,15 @@ func describeStorageClass(sc *storage.StorageClass, events *api.EventList) (stri
w.Write(LEVEL_0, "Annotations:\t%s\n", labels.FormatLabels(sc.Annotations))
w.Write(LEVEL_0, "Provisioner:\t%s\n", sc.Provisioner)
w.Write(LEVEL_0, "Parameters:\t%s\n", labels.FormatLabels(sc.Parameters))
w.Write(LEVEL_0, "AllowVolumeExpansion:\t%s\n", printBoolPtr(sc.AllowVolumeExpansion))
if len(sc.MountOptions) == 0 {
w.Write(LEVEL_0, "MountOptions:\t<none>\n")
} else {
w.Write(LEVEL_0, "MountOptions:\n")
for _, option := range sc.MountOptions {
w.Write(LEVEL_1, "%s\n", option)
}
}
if sc.ReclaimPolicy != nil {
w.Write(LEVEL_0, "ReclaimPolicy:\t%s\n", *sc.ReclaimPolicy)
}
@ -3346,8 +3437,8 @@ func describePriorityClass(pc *scheduling.PriorityClass, events *api.EventList)
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", pc.Name)
w.Write(LEVEL_0, "Value:\t%s\n", pc.Value)
w.Write(LEVEL_0, "GlobalDefault:\t%s\n", pc.GlobalDefault)
w.Write(LEVEL_0, "Value:\t%v\n", pc.Value)
w.Write(LEVEL_0, "GlobalDefault:\t%v\n", pc.GlobalDefault)
w.Write(LEVEL_0, "Description:\t%s\n", pc.Description)
w.Write(LEVEL_0, "Annotations:\t%s\n", labels.FormatLabels(pc.Annotations))
@ -3381,6 +3472,7 @@ func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error
w.Write(LEVEL_0, "\nSettings:\n")
w.Write(LEVEL_1, "Allow Privileged:\t%t\n", psp.Spec.Privileged)
w.Write(LEVEL_1, "Allow Privilege Escalation:\t%v\n", psp.Spec.AllowPrivilegeEscalation)
w.Write(LEVEL_1, "Default Add Capabilities:\t%v\n", capsToString(psp.Spec.DefaultAddCapabilities))
w.Write(LEVEL_1, "Required Drop Capabilities:\t%s\n", capsToString(psp.Spec.RequiredDropCapabilities))
w.Write(LEVEL_1, "Allowed Capabilities:\t%s\n", capsToString(psp.Spec.AllowedCapabilities))

View File

@ -80,7 +80,8 @@ func TestDescribePodNode(t *testing.T) {
NodeName: "all-in-one",
},
Status: api.PodStatus{
HostIP: "127.0.0.1",
HostIP: "127.0.0.1",
NominatedNodeName: "nodeA",
},
})
c := &describeClient{T: t, Namespace: "foo", Interface: fake}
@ -92,6 +93,9 @@ func TestDescribePodNode(t *testing.T) {
if !strings.Contains(out, "all-in-one/127.0.0.1") {
t.Errorf("unexpected out: %s", out)
}
if !strings.Contains(out, "nodeA") {
t.Errorf("unexpected out: %s", out)
}
}
func TestDescribePodTolerations(t *testing.T) {
@ -783,8 +787,8 @@ func TestDefaultDescribers(t *testing.T) {
func TestGetPodsTotalRequests(t *testing.T) {
testCases := []struct {
pods *api.PodList
expectedReqs, expectedLimits map[api.ResourceName]resource.Quantity
pods *api.PodList
expectedReqs map[api.ResourceName]resource.Quantity
}{
{
pods: &api.PodList{
@ -848,10 +852,7 @@ func TestGetPodsTotalRequests(t *testing.T) {
}
for _, testCase := range testCases {
reqs, _, err := getPodsTotalRequestsAndLimits(testCase.pods)
if err != nil {
t.Errorf("Unexpected error %v", err)
}
reqs, _ := getPodsTotalRequestsAndLimits(testCase.pods)
if !apiequality.Semantic.DeepEqual(reqs, testCase.expectedReqs) {
t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs)
}
@ -990,6 +991,106 @@ func TestPersistentVolumeDescriber(t *testing.T) {
},
expectedElements: []string{"VolumeMode", "Block"},
},
{
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
Local: &api.LocalVolumeSource{},
},
},
},
expectedElements: []string{"Node Affinity: <none>"},
unexpectedElements: []string{"Required Terms", "Term "},
},
{
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
Local: &api.LocalVolumeSource{},
},
NodeAffinity: &api.VolumeNodeAffinity{},
},
},
expectedElements: []string{"Node Affinity: <none>"},
unexpectedElements: []string{"Required Terms", "Term "},
},
{
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
Local: &api.LocalVolumeSource{},
},
NodeAffinity: &api.VolumeNodeAffinity{
Required: &api.NodeSelector{},
},
},
},
expectedElements: []string{"Node Affinity", "Required Terms: <none>"},
unexpectedElements: []string{"Term "},
},
{
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
Local: &api.LocalVolumeSource{},
},
NodeAffinity: &api.VolumeNodeAffinity{
Required: &api.NodeSelector{
NodeSelectorTerms: []api.NodeSelectorTerm{
{
MatchExpressions: []api.NodeSelectorRequirement{},
},
{
MatchExpressions: []api.NodeSelectorRequirement{},
},
},
},
},
},
},
expectedElements: []string{"Node Affinity", "Required Terms", "Term 0", "Term 1"},
},
{
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
Local: &api.LocalVolumeSource{},
},
NodeAffinity: &api.VolumeNodeAffinity{
Required: &api.NodeSelector{
NodeSelectorTerms: []api.NodeSelectorTerm{
{
MatchExpressions: []api.NodeSelectorRequirement{
{
Key: "foo",
Operator: "In",
Values: []string{"val1", "val2"},
},
{
Key: "foo",
Operator: "Exists",
},
},
},
},
},
},
},
},
expectedElements: []string{"Node Affinity", "Required Terms", "Term 0",
"foo in [val1, val2]",
"foo exists"},
},
}
for _, test := range testCases {
@ -1211,6 +1312,158 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
},
},
},
{
"external source type, target average value (no current)",
autoscaling.HorizontalPodAutoscaler{
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
},
Status: autoscaling.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
},
},
},
{
"external source type, target average value (with current)",
autoscaling.HorizontalPodAutoscaler{
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
},
Status: autoscaling.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
CurrentMetrics: []autoscaling.MetricStatus{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricStatus{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
CurrentAverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
},
},
},
},
},
},
{
"external source type, target value (no current)",
autoscaling.HorizontalPodAutoscaler{
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
TargetValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
},
Status: autoscaling.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
},
},
},
{
"external source type, target value (with current)",
autoscaling.HorizontalPodAutoscaler{
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
TargetValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
},
Status: autoscaling.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
CurrentMetrics: []autoscaling.MetricStatus{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricStatus{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
CurrentValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
},
},
},
},
},
},
{
"pods source type (no current)",
autoscaling.HorizontalPodAutoscaler{
@ -2107,6 +2360,32 @@ Events: <none>` + "\n"
}
func TestDescribeNode(t *testing.T) {
fake := fake.NewSimpleClientset(&api.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "foo",
},
Spec: api.NodeSpec{
Unschedulable: true,
},
})
c := &describeClient{T: t, Namespace: "foo", Interface: fake}
d := NodeDescriber{c}
out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
expectedOut := []string{"Unschedulable", "true"}
for _, expected := range expectedOut {
if !strings.Contains(out, expected) {
t.Errorf("expected to find %q in output: %q", expected, out)
}
}
}
// boolPtr returns a pointer to a bool
func boolPtr(b bool) *bool {
o := b

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
metav1alpha1 "k8s.io/apimachinery/pkg/apis/meta/v1alpha1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
yamlserializer "k8s.io/apimachinery/pkg/runtime/serializer/yaml"
@ -50,35 +50,48 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/apis/storage"
kubectltesting "k8s.io/kubernetes/pkg/kubectl/testing"
"k8s.io/kubernetes/pkg/printers"
)
func init() {
legacyscheme.Scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &kubectltesting.TestStruct{})
legacyscheme.Scheme.AddKnownTypes(legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, &kubectltesting.TestStruct{})
legacyscheme.Scheme.AddKnownTypes(testapi.Default.InternalGroupVersion(), &TestPrintType{})
legacyscheme.Scheme.AddKnownTypes(legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, &TestPrintType{})
}
var testData = kubectltesting.TestStruct{
var testData = TestStruct{
Key: "testValue",
Map: map[string]int{"TestSubkey": 1},
StringList: []string{"a", "b", "c"},
IntList: []int{1, 2, 3},
}
type TestStruct struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Key string `json:"Key"`
Map map[string]int `json:"Map"`
StringList []string `json:"StringList"`
IntList []int `json:"IntList"`
}
func (in *TestStruct) DeepCopyObject() runtime.Object {
panic("never called")
}
func TestVersionedPrinter(t *testing.T) {
original := &kubectltesting.TestStruct{Key: "value"}
original := &TestPrintType{Data: "value"}
p := printers.NewVersionedPrinter(
printers.ResourcePrinterFunc(func(obj runtime.Object, w io.Writer) error {
if obj == original {
t.Fatalf("object should not be identical: %#v", obj)
}
if obj.(*kubectltesting.TestStruct).Key != "value" {
if obj.(*TestPrintType).Data != "value" {
t.Fatalf("object was not converted: %#v", obj)
}
return nil
}),
legacyscheme.Scheme,
legacyscheme.Scheme,
legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion,
)
if err := p.PrintObj(original, nil); err != nil {
@ -96,7 +109,7 @@ func TestPrintDefault(t *testing.T) {
}
for _, test := range printerTests {
printer, err := printers.GetStandardPrinter(nil, nil, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{AllowMissingKeys: false})
printer, err := printers.GetStandardPrinter(nil, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{AllowMissingKeys: false})
if err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
}
@ -266,17 +279,17 @@ func TestPrinter(t *testing.T) {
{"test jsonpath", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.metadata.name}", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo"},
{"test jsonpath list", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.items[*].metadata.name}", AllowMissingKeys: true}, podListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo bar"},
{"test jsonpath empty list", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.items[*].metadata.name}", AllowMissingKeys: true}, emptyListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, ""},
{"test name", &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "pods/foo\n"},
{"test name", &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "pod/foo\n"},
{"emits versioned objects", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{.kind}}", AllowMissingKeys: true}, testapi, []schema.GroupVersion{v1.SchemeGroupVersion}, "Pod"},
}
for _, test := range printerTests {
buf := bytes.NewBuffer([]byte{})
printer, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
printer, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
if err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
}
if printer.IsGeneric() && len(test.OutputVersions) > 0 {
printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, test.OutputVersions...)
printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, test.OutputVersions...)
}
if err := printer.PrintObj(test.Input, buf); err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
@ -301,7 +314,7 @@ func TestBadPrinter(t *testing.T) {
{"unknown format", &printers.PrintOptions{OutputFormatType: "anUnknownFormat", OutputFormatArgument: "", AllowMissingKeys: false}, fmt.Errorf("output format \"anUnknownFormat\" not recognized")},
}
for _, test := range badPrinterTests {
_, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
_, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
if err == nil || err.Error() != test.Error.Error() {
t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err)
}
@ -315,14 +328,14 @@ func testPrinter(t *testing.T, printer printers.ResourcePrinter, unmarshalFunc f
if err != nil {
t.Fatal(err)
}
var poutput kubectltesting.TestStruct
var poutput TestStruct
// Verify that given function runs without error.
err = unmarshalFunc(buf.Bytes(), &poutput)
if err != nil {
t.Fatal(err)
}
// Use real decode function to undo the versioning process.
poutput = kubectltesting.TestStruct{}
poutput = TestStruct{}
s := yamlserializer.NewDecodingSerializer(testapi.Default.Codec())
if err := runtime.DecodeInto(s, buf.Bytes(), &poutput); err != nil {
t.Fatal(err)
@ -477,7 +490,7 @@ func TestNamePrinter(t *testing.T) {
Name: "foo",
},
},
"pods/foo\n"},
"pod/foo\n"},
"List": {
&v1.List{
TypeMeta: metav1.TypeMeta{
@ -492,10 +505,10 @@ func TestNamePrinter(t *testing.T) {
},
},
},
"pods/foo\npods/bar\n"},
"pod/foo\npod/bar\n"},
}
printOpts := &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: false}
printer, _ := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *printOpts)
printer, _ := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *printOpts)
for name, item := range tests {
buff := &bytes.Buffer{}
err := printer.PrintObj(item.obj, buff)
@ -610,7 +623,7 @@ func TestTemplateStrings(t *testing.T) {
t.Fatalf("tmpl fail: %v", err)
}
printer := printers.NewVersionedPrinter(p, legacyscheme.Scheme, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion)
printer := printers.NewVersionedPrinter(p, legacyscheme.Scheme, legacyscheme.Scheme, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion)
for name, item := range table {
buffer := &bytes.Buffer{}
@ -643,19 +656,19 @@ func TestPrinters(t *testing.T) {
if err != nil {
t.Fatal(err)
}
templatePrinter = printers.NewVersionedPrinter(templatePrinter, legacyscheme.Scheme, v1.SchemeGroupVersion)
templatePrinter = printers.NewVersionedPrinter(templatePrinter, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion)
templatePrinter2, err = printers.NewTemplatePrinter([]byte("{{len .items}}"))
if err != nil {
t.Fatal(err)
}
templatePrinter2 = printers.NewVersionedPrinter(templatePrinter2, legacyscheme.Scheme, v1.SchemeGroupVersion)
templatePrinter2 = printers.NewVersionedPrinter(templatePrinter2, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion)
jsonpathPrinter, err = printers.NewJSONPathPrinter("{.metadata.name}")
if err != nil {
t.Fatal(err)
}
jsonpathPrinter = printers.NewVersionedPrinter(jsonpathPrinter, legacyscheme.Scheme, v1.SchemeGroupVersion)
jsonpathPrinter = printers.NewVersionedPrinter(jsonpathPrinter, legacyscheme.Scheme, legacyscheme.Scheme, v1.SchemeGroupVersion)
allPrinters := map[string]printers.ResourcePrinter{
"humanReadable": printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
@ -670,7 +683,6 @@ func TestPrinters(t *testing.T) {
"name": &printers.NamePrinter{
Typer: legacyscheme.Scheme,
Decoders: []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme},
Mapper: legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...),
},
}
AddHandlers((allPrinters["humanReadable"]).(*printers.HumanReadablePrinter))
@ -1578,7 +1590,7 @@ func TestPrintPodTable(t *testing.T) {
func TestPrintPod(t *testing.T) {
tests := []struct {
pod api.Pod
expect []metav1alpha1.TableRow
expect []metav1beta1.TableRow
}{
{
// Test name, num of containers, restarts, container ready status
@ -1593,7 +1605,7 @@ func TestPrintPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>"}}},
},
{
// Test container error overwrites pod phase
@ -1608,7 +1620,7 @@ func TestPrintPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", 6, "<unknown>"}}},
},
{
// Test the same as the above but with Terminated state and the first container overwrites the rest
@ -1623,7 +1635,7 @@ func TestPrintPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test3", "0/2", "ContainerWaitingReason", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test3", "0/2", "ContainerWaitingReason", 6, "<unknown>"}}},
},
{
// Test ready is not enough for reporting running
@ -1638,7 +1650,7 @@ func TestPrintPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test4", "1/2", "podPhase", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "podPhase", 6, "<unknown>"}}},
},
{
// Test ready is not enough for reporting running
@ -1654,7 +1666,7 @@ func TestPrintPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test5", "1/2", "podReason", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "podReason", 6, "<unknown>"}}},
},
}
@ -1675,7 +1687,7 @@ func TestPrintPod(t *testing.T) {
func TestPrintPodwide(t *testing.T) {
tests := []struct {
pod api.Pod
expect []metav1alpha1.TableRow
expect []metav1beta1.TableRow
}{
{
// Test when the NodeName and PodIP are not none
@ -1692,9 +1704,10 @@ func TestPrintPodwide(t *testing.T) {
{Ready: true, RestartCount: 3, State: api.ContainerState{Running: &api.ContainerStateRunning{}}},
{RestartCount: 3},
},
NominatedNodeName: "node1",
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>", "1.1.1.1", "test1"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>", "1.1.1.1", "test1", "node1"}}},
},
{
// Test when the NodeName and PodIP are none
@ -1713,7 +1726,7 @@ func TestPrintPodwide(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", 6, "<unknown>", "<none>", "<none>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "ContainerWaitingReason", 6, "<unknown>", "<none>", "<none>"}}},
},
}
@ -1734,7 +1747,7 @@ func TestPrintPodwide(t *testing.T) {
func TestPrintPodList(t *testing.T) {
tests := []struct {
pods api.PodList
expect []metav1alpha1.TableRow
expect []metav1beta1.TableRow
}{
// Test podList's pod: name, num of containers, restarts, container ready status
{
@ -1763,7 +1776,7 @@ func TestPrintPodList(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test1", "2/2", "podPhase", 6, "<unknown>"}}, {Cells: []interface{}{"test2", "1/1", "podPhase", 1, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test1", "2/2", "podPhase", 6, "<unknown>"}}, {Cells: []interface{}{"test2", "1/1", "podPhase", 1, "<unknown>"}}},
},
}
@ -1785,7 +1798,7 @@ func TestPrintPodList(t *testing.T) {
func TestPrintNonTerminatedPod(t *testing.T) {
tests := []struct {
pod api.Pod
expect []metav1alpha1.TableRow
expect []metav1beta1.TableRow
}{
{
// Test pod phase Running should be printed
@ -1800,7 +1813,7 @@ func TestPrintNonTerminatedPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test1", "1/2", "Running", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "Running", 6, "<unknown>"}}},
},
{
// Test pod phase Pending should be printed
@ -1815,7 +1828,7 @@ func TestPrintNonTerminatedPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test2", "1/2", "Pending", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test2", "1/2", "Pending", 6, "<unknown>"}}},
},
{
// Test pod phase Unknown should be printed
@ -1830,7 +1843,7 @@ func TestPrintNonTerminatedPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test3", "1/2", "Unknown", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test3", "1/2", "Unknown", 6, "<unknown>"}}},
},
{
// Test pod phase Succeeded shouldn't be printed
@ -1845,7 +1858,7 @@ func TestPrintNonTerminatedPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test4", "1/2", "Succeeded", 6, "<unknown>"}, Conditions: podSuccessConditions}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test4", "1/2", "Succeeded", 6, "<unknown>"}, Conditions: podSuccessConditions}},
},
{
// Test pod phase Failed shouldn't be printed
@ -1860,7 +1873,7 @@ func TestPrintNonTerminatedPod(t *testing.T) {
},
},
},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test5", "1/2", "Failed", 6, "<unknown>"}, Conditions: podFailedConditions}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test5", "1/2", "Failed", 6, "<unknown>"}, Conditions: podFailedConditions}},
},
}
@ -1883,7 +1896,7 @@ func TestPrintPodWithLabels(t *testing.T) {
tests := []struct {
pod api.Pod
labelColumns []string
expect []metav1alpha1.TableRow
expect []metav1beta1.TableRow
}{
{
// Test name, num of containers, restarts, container ready status
@ -1902,7 +1915,7 @@ func TestPrintPodWithLabels(t *testing.T) {
},
},
[]string{"col1", "COL2"},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>", "asd", "zxc"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>", "asd", "zxc"}}},
},
{
// Test name, num of containers, restarts, container ready status
@ -1921,7 +1934,7 @@ func TestPrintPodWithLabels(t *testing.T) {
},
},
[]string{},
[]metav1alpha1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>"}}},
},
}
@ -2156,6 +2169,161 @@ func TestPrintHPA(t *testing.T) {
},
"some-hpa\tReplicationController/some-rc\t<none>\t<unset>\t10\t4\t<unknown>\n",
},
// external source type, target average value (no current)
{
autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
},
Status: autoscaling.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
},
},
"some-hpa\tReplicationController/some-rc\t<unknown>/100m (avg)\t2\t10\t4\t<unknown>\n",
},
// external source type, target average value
{
autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
TargetAverageValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
},
Status: autoscaling.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
CurrentMetrics: []autoscaling.MetricStatus{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricStatus{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
CurrentAverageValue: resource.NewMilliQuantity(50, resource.DecimalSI),
},
},
},
},
},
"some-hpa\tReplicationController/some-rc\t50m/100m (avg)\t2\t10\t4\t<unknown>\n",
},
// external source type, target value (no current)
{
autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-service-metric",
TargetValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
},
Status: autoscaling.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
},
},
"some-hpa\tReplicationController/some-rc\t<unknown>/100m\t2\t10\t4\t<unknown>\n",
},
// external source type, target value
{
autoscaling.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{Name: "some-hpa"},
Spec: autoscaling.HorizontalPodAutoscalerSpec{
ScaleTargetRef: autoscaling.CrossVersionObjectReference{
Name: "some-rc",
Kind: "ReplicationController",
},
MinReplicas: &minReplicasVal,
MaxReplicas: 10,
Metrics: []autoscaling.MetricSpec{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricSource{
MetricSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"label": "value",
},
},
MetricName: "some-external-metric",
TargetValue: resource.NewMilliQuantity(100, resource.DecimalSI),
},
},
},
},
Status: autoscaling.HorizontalPodAutoscalerStatus{
CurrentReplicas: 4,
DesiredReplicas: 5,
CurrentMetrics: []autoscaling.MetricStatus{
{
Type: autoscaling.ExternalMetricSourceType,
External: &autoscaling.ExternalMetricStatus{
MetricName: "some-external-metric",
CurrentValue: *resource.NewMilliQuantity(50, resource.DecimalSI),
},
},
},
},
},
"some-hpa\tReplicationController/some-rc\t50m/100m\t2\t10\t4\t<unknown>\n",
},
// pods source type (no current)
{
autoscaling.HorizontalPodAutoscaler{
@ -2182,7 +2350,7 @@ func TestPrintHPA(t *testing.T) {
DesiredReplicas: 5,
},
},
"some-hpa\tReplicationController/some-rc\t<unknown> / 100m\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t<unknown>/100m\t2\t10\t4\t<unknown>\n",
},
// pods source type
{
@ -2219,7 +2387,7 @@ func TestPrintHPA(t *testing.T) {
},
},
},
"some-hpa\tReplicationController/some-rc\t50m / 100m\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t50m/100m\t2\t10\t4\t<unknown>\n",
},
// object source type (no current)
{
@ -2251,7 +2419,7 @@ func TestPrintHPA(t *testing.T) {
DesiredReplicas: 5,
},
},
"some-hpa\tReplicationController/some-rc\t<unknown> / 100m\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t<unknown>/100m\t2\t10\t4\t<unknown>\n",
},
// object source type
{
@ -2296,7 +2464,7 @@ func TestPrintHPA(t *testing.T) {
},
},
},
"some-hpa\tReplicationController/some-rc\t50m / 100m\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t50m/100m\t2\t10\t4\t<unknown>\n",
},
// resource source type, targetVal (no current)
{
@ -2324,7 +2492,7 @@ func TestPrintHPA(t *testing.T) {
DesiredReplicas: 5,
},
},
"some-hpa\tReplicationController/some-rc\t<unknown> / 100m\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t<unknown>/100m\t2\t10\t4\t<unknown>\n",
},
// resource source type, targetVal
{
@ -2361,7 +2529,7 @@ func TestPrintHPA(t *testing.T) {
},
},
},
"some-hpa\tReplicationController/some-rc\t50m / 100m\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t50m/100m\t2\t10\t4\t<unknown>\n",
},
// resource source type, targetUtil (no current)
{
@ -2389,7 +2557,7 @@ func TestPrintHPA(t *testing.T) {
DesiredReplicas: 5,
},
},
"some-hpa\tReplicationController/some-rc\t<unknown> / 80%\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t<unknown>/80%\t2\t10\t4\t<unknown>\n",
},
// resource source type, targetUtil
{
@ -2427,7 +2595,7 @@ func TestPrintHPA(t *testing.T) {
},
},
},
"some-hpa\tReplicationController/some-rc\t50% / 80%\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t50%/80%\t2\t10\t4\t<unknown>\n",
},
// multiple specs
{
@ -2486,7 +2654,7 @@ func TestPrintHPA(t *testing.T) {
},
},
},
"some-hpa\tReplicationController/some-rc\t50m / 100m, 50% / 80% + 1 more...\t2\t10\t4\t<unknown>\n",
"some-hpa\tReplicationController/some-rc\t50m/100m, 50%/80% + 1 more...\t2\t10\t4\t<unknown>\n",
},
}
@ -2511,7 +2679,7 @@ func TestPrintPodShowLabels(t *testing.T) {
tests := []struct {
pod api.Pod
showLabels bool
expect []metav1alpha1.TableRow
expect []metav1beta1.TableRow
}{
{
// Test name, num of containers, restarts, container ready status
@ -2530,7 +2698,7 @@ func TestPrintPodShowLabels(t *testing.T) {
},
},
true,
[]metav1alpha1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>", "COL2=zxc,col1=asd"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>", "COL2=zxc,col1=asd"}}},
},
{
// Test name, num of containers, restarts, container ready status
@ -2549,7 +2717,7 @@ func TestPrintPodShowLabels(t *testing.T) {
},
},
false,
[]metav1alpha1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>"}}},
[]metav1beta1.TableRow{{Cells: []interface{}{"test1", "1/2", "podPhase", 6, "<unknown>"}}},
},
}
@ -2806,7 +2974,7 @@ func TestAllowMissingKeys(t *testing.T) {
}
for _, test := range tests {
buf := bytes.NewBuffer([]byte{})
printer, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
printer, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
if err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
}