vendor update for CSI 0.3.0

This commit is contained in:
gman
2018-07-18 16:47:22 +02:00
parent 6f484f92fc
commit 8ea659f0d5
6810 changed files with 438061 additions and 193861 deletions

View File

@ -27,11 +27,13 @@ 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/genericclioptions:go_default_library",
"//pkg/kubectl/genericclioptions/printers:go_default_library",
"//pkg/printers:go_default_library",
"//pkg/util/pointer:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/k8s.io/api/apps/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
@ -70,6 +72,7 @@ go_library(
"//pkg/apis/networking:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac/v1:go_default_library",
"//pkg/apis/scheduling:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/apis/storage/util:go_default_library",
@ -83,6 +86,7 @@ go_library(
"//pkg/util/slice:go_default_library",
"//vendor/github.com/fatih/camelcase:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/apps/v1:go_default_library",
"//vendor/k8s.io/api/apps/v1beta1:go_default_library",
"//vendor/k8s.io/api/autoscaling/v2beta1:go_default_library",
"//vendor/k8s.io/api/batch/v1:go_default_library",
@ -90,6 +94,7 @@ go_library(
"//vendor/k8s.io/api/certificates/v1beta1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/api/rbac/v1beta1:go_default_library",
"//vendor/k8s.io/api/storage/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
@ -106,7 +111,8 @@ go_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",
"//vendor/k8s.io/client-go/kubernetes/typed/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
],
)

View File

@ -33,7 +33,9 @@ import (
"github.com/golang/glog"
"github.com/fatih/camelcase"
versionedextension "k8s.io/api/extensions/v1beta1"
appsv1 "k8s.io/api/apps/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource"
@ -45,7 +47,8 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/dynamic"
clientextensionsv1beta1 "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
externalclient "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api/events"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/api/ref"
@ -61,6 +64,7 @@ import (
"k8s.io/kubernetes/pkg/apis/networking"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/apis/rbac"
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
"k8s.io/kubernetes/pkg/apis/scheduling"
"k8s.io/kubernetes/pkg/apis/storage"
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
@ -122,7 +126,16 @@ func (pw *prefixWriter) Flush() {
}
}
func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer {
func describerMap(clientConfig *rest.Config) (map[schema.GroupKind]printers.Describer, error) {
c, err := clientset.NewForConfig(clientConfig)
if err != nil {
return nil, err
}
externalclient, err := externalclient.NewForConfig(clientConfig)
if err != nil {
return nil, err
}
m := map[schema.GroupKind]printers.Describer{
api.Kind("Pod"): &PodDescriber{c},
api.Kind("ReplicationController"): &ReplicationControllerDescriber{c},
@ -144,43 +157,38 @@ func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer
extensions.Kind("PodSecurityPolicy"): &PodSecurityPolicyDescriber{c},
autoscaling.Kind("HorizontalPodAutoscaler"): &HorizontalPodAutoscalerDescriber{c},
extensions.Kind("DaemonSet"): &DaemonSetDescriber{c},
extensions.Kind("Deployment"): &DeploymentDescriber{c, versionedExtensionsClientV1beta1(c)},
extensions.Kind("Deployment"): &DeploymentDescriber{c, externalclient},
extensions.Kind("Ingress"): &IngressDescriber{c},
batch.Kind("Job"): &JobDescriber{c},
batch.Kind("CronJob"): &CronJobDescriber{c},
batch.Kind("CronJob"): &CronJobDescriber{c, externalclient},
apps.Kind("StatefulSet"): &StatefulSetDescriber{c},
apps.Kind("Deployment"): &DeploymentDescriber{c, versionedExtensionsClientV1beta1(c)},
apps.Kind("Deployment"): &DeploymentDescriber{c, externalclient},
apps.Kind("DaemonSet"): &DaemonSetDescriber{c},
apps.Kind("ReplicaSet"): &ReplicaSetDescriber{c},
certificates.Kind("CertificateSigningRequest"): &CertificateSigningRequestDescriber{c},
storage.Kind("StorageClass"): &StorageClassDescriber{c},
policy.Kind("PodDisruptionBudget"): &PodDisruptionBudgetDescriber{c},
rbac.Kind("Role"): &RoleDescriber{c},
rbac.Kind("ClusterRole"): &ClusterRoleDescriber{c},
rbac.Kind("RoleBinding"): &RoleBindingDescriber{c},
rbac.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{c},
rbac.Kind("Role"): &RoleDescriber{externalclient},
rbac.Kind("ClusterRole"): &ClusterRoleDescriber{externalclient},
rbac.Kind("RoleBinding"): &RoleBindingDescriber{externalclient},
rbac.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{externalclient},
networking.Kind("NetworkPolicy"): &NetworkPolicyDescriber{c},
scheduling.Kind("PriorityClass"): &PriorityClassDescriber{c},
}
return m
}
// DescribableResources lists all resource types we can describe.
func DescribableResources() []string {
keys := make([]string, 0)
for k := range describerMap(nil) {
resource := strings.ToLower(k.Kind)
keys = append(keys, resource)
}
return keys
return m, nil
}
// DescriberFor returns the default describe functions for each of the standard
// Kubernetes types.
func DescriberFor(kind schema.GroupKind, c clientset.Interface) (printers.Describer, bool) {
f, ok := describerMap(c)[kind]
func DescriberFor(kind schema.GroupKind, clientConfig *rest.Config) (printers.Describer, bool) {
describers, err := describerMap(clientConfig)
if err != nil {
glog.V(1).Info(err)
return nil, false
}
f, ok := describers[kind]
return f, ok
}
@ -197,12 +205,7 @@ type genericDescriber struct {
}
func (g *genericDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (output string, err error) {
apiResource := &metav1.APIResource{
Name: g.mapping.Resource,
Namespaced: g.mapping.Scope.Name() == meta.RESTScopeNameNamespace,
Kind: g.mapping.GroupVersionKind.Kind,
}
obj, err := g.dynamic.Resource(apiResource, namespace).Get(name, metav1.GetOptions{})
obj, err := g.dynamic.Resource(g.mapping.Resource).Namespace(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return "", err
}
@ -963,7 +966,17 @@ func printCinderVolumeSource(cinder *api.CinderVolumeSource, w PrefixWriter) {
" VolumeID:\t%v\n"+
" FSType:\t%v\n"+
" ReadOnly:\t%v\n",
cinder.VolumeID, cinder.FSType, cinder.ReadOnly)
" SecretRef:\t%v\n"+
cinder.VolumeID, cinder.FSType, cinder.ReadOnly, cinder.SecretRef)
}
func printCinderPersistentVolumeSource(cinder *api.CinderPersistentVolumeSource, w PrefixWriter) {
w.Write(LEVEL_2, "Type:\tCinder (a Persistent Disk resource in OpenStack)\n"+
" VolumeID:\t%v\n"+
" FSType:\t%v\n"+
" ReadOnly:\t%v\n",
" SecretRef:\t%v\n"+
cinder.VolumeID, cinder.SecretRef, cinder.FSType, cinder.ReadOnly, cinder.SecretRef)
}
func printScaleIOVolumeSource(sio *api.ScaleIOVolumeSource, w PrefixWriter) {
@ -1225,7 +1238,7 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
case pv.Spec.VsphereVolume != nil:
printVsphereVolumeSource(pv.Spec.VsphereVolume, w)
case pv.Spec.Cinder != nil:
printCinderVolumeSource(pv.Spec.Cinder, w)
printCinderPersistentVolumeSource(pv.Spec.Cinder, w)
case pv.Spec.AzureDisk != nil:
printAzureDiskVolumeSource(pv.Spec.AzureDisk, w)
case pv.Spec.PhotonPersistentDisk != nil:
@ -1307,6 +1320,20 @@ func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.E
if pvc.Spec.VolumeMode != nil {
w.Write(LEVEL_0, "VolumeMode:\t%v\n", *pvc.Spec.VolumeMode)
}
if len(pvc.Status.Conditions) > 0 {
w.Write(LEVEL_0, "Conditions:\n")
w.Write(LEVEL_1, "Type\tStatus\tLastProbeTime\tLastTransitionTime\tReason\tMessage\n")
w.Write(LEVEL_1, "----\t------\t-----------------\t------------------\t------\t-------\n")
for _, c := range pvc.Status.Conditions {
w.Write(LEVEL_1, "%v \t%v \t%s \t%s \t%v \t%v\n",
c.Type,
c.Status,
c.LastProbeTime.Time.Format(time.RFC1123Z),
c.LastTransitionTime.Time.Format(time.RFC1123Z),
c.Reason,
c.Message)
}
}
if events != nil {
DescribeEvents(events, w)
}
@ -1840,10 +1867,11 @@ func describeJob(job *batch.Job, events *api.EventList) (string, error) {
// CronJobDescriber generates information about a cron job and the jobs it has created.
type CronJobDescriber struct {
clientset.Interface
external externalclient.Interface
}
func (d *CronJobDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
cronJob, err := d.Batch().CronJobs(namespace).Get(name, metav1.GetOptions{})
cronJob, err := d.external.BatchV1beta1().CronJobs(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return "", err
}
@ -1853,7 +1881,12 @@ func (d *CronJobDescriber) Describe(namespace, name string, describerSettings pr
events, _ = d.Core().Events(namespace).Search(legacyscheme.Scheme, cronJob)
}
return describeCronJob(cronJob, events)
internalCronJob := &batch.CronJob{}
if err := legacyscheme.Scheme.Convert(cronJob, internalCronJob, nil); err != nil {
return "", err
}
return describeCronJob(internalCronJob, events)
}
func describeCronJob(cronJob *batch.CronJob, events *api.EventList) (string, error) {
@ -2422,7 +2455,7 @@ func describeServiceAccount(serviceAccount *api.ServiceAccount, tokens []api.Sec
// RoleDescriber generates information about a node.
type RoleDescriber struct {
clientset.Interface
externalclient.Interface
}
func (d *RoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
@ -2431,7 +2464,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print
return "", err
}
breakdownRules := []rbac.PolicyRule{}
breakdownRules := []rbacv1.PolicyRule{}
for _, rule := range role.Rules {
breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...)
}
@ -2440,7 +2473,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print
if err != nil {
return "", err
}
sort.Stable(rbac.SortableRuleSlice(compactRules))
sort.Stable(rbacv1helpers.SortableRuleSlice(compactRules))
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
@ -2461,7 +2494,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print
// ClusterRoleDescriber generates information about a node.
type ClusterRoleDescriber struct {
clientset.Interface
externalclient.Interface
}
func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
@ -2470,7 +2503,7 @@ func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSetting
return "", err
}
breakdownRules := []rbac.PolicyRule{}
breakdownRules := []rbacv1.PolicyRule{}
for _, rule := range role.Rules {
breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...)
}
@ -2479,7 +2512,7 @@ func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSetting
if err != nil {
return "", err
}
sort.Stable(rbac.SortableRuleSlice(compactRules))
sort.Stable(rbacv1helpers.SortableRuleSlice(compactRules))
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
@ -2517,7 +2550,7 @@ func combineResourceGroup(resource, group []string) string {
// RoleBindingDescriber generates information about a node.
type RoleBindingDescriber struct {
clientset.Interface
externalclient.Interface
}
func (d *RoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
@ -2549,7 +2582,7 @@ func (d *RoleBindingDescriber) Describe(namespace, name string, describerSetting
// ClusterRoleBindingDescriber generates information about a node.
type ClusterRoleBindingDescriber struct {
clientset.Interface
externalclient.Interface
}
func (d *ClusterRoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
@ -2689,9 +2722,6 @@ func describeNode(node *api.Node, nodeNonTerminatedPodsList *api.PodList, events
if len(node.Spec.PodCIDR) > 0 {
w.Write(LEVEL_0, "PodCIDR:\t%s\n", node.Spec.PodCIDR)
}
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)
}
@ -2746,6 +2776,14 @@ func describeStatefulSet(ps *apps.StatefulSet, selector labels.Selector, events
printLabelsMultiline(w, "Labels", ps.Labels)
printAnnotationsMultiline(w, "Annotations", ps.Annotations)
w.Write(LEVEL_0, "Replicas:\t%d desired | %d total\n", ps.Spec.Replicas, ps.Status.Replicas)
w.Write(LEVEL_0, "Update Strategy:\t%s\n", ps.Spec.UpdateStrategy.Type)
if ps.Spec.UpdateStrategy.RollingUpdate != nil {
ru := ps.Spec.UpdateStrategy.RollingUpdate
if ru.Partition != 0 {
w.Write(LEVEL_1, "Partition:\t%d\n", ru.Partition)
}
}
w.Write(LEVEL_0, "Pods Status:\t%d Running / %d Waiting / %d Succeeded / %d Failed\n", running, waiting, succeeded, failed)
DescribePodTemplate(&ps.Spec.Template, w)
describeVolumeClaimTemplates(ps.Spec.VolumeClaimTemplates, w)
@ -2924,17 +2962,9 @@ func describeHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, e
}
w.Write(LEVEL_0, "Min replicas:\t%s\n", minReplicas)
w.Write(LEVEL_0, "Max replicas:\t%d\n", hpa.Spec.MaxReplicas)
w.Write(LEVEL_0, "%s pods:\t", hpa.Spec.ScaleTargetRef.Kind)
w.Write(LEVEL_0, "%d current / %d desired\n", hpa.Status.CurrentReplicas, hpa.Status.DesiredReplicas)
// TODO: switch to scale subresource once the required code is submitted.
if strings.ToLower(hpa.Spec.ScaleTargetRef.Kind) == "replicationcontroller" {
w.Write(LEVEL_0, "ReplicationController pods:\t")
rc, err := d.client.Core().ReplicationControllers(hpa.Namespace).Get(hpa.Spec.ScaleTargetRef.Name, metav1.GetOptions{})
if err == nil {
w.Write(LEVEL_0, "%d current / %d desired\n", rc.Status.Replicas, rc.Spec.Replicas)
} else {
w.Write(LEVEL_0, "failed to check Replication Controller\n")
}
}
if len(hpa.Status.Conditions) > 0 {
w.Write(LEVEL_0, "Conditions:\n")
w.Write(LEVEL_1, "Type\tStatus\tReason\tMessage\n")
@ -2973,8 +3003,9 @@ func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node
memoryReq.String(), int64(fractionMemoryReq), memoryLimit.String(), int64(fractionMemoryLimit))
}
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")
w.Write(LEVEL_0, "Allocated resources:\n (Total limits may be over 100 percent, i.e., overcommitted.)\n")
w.Write(LEVEL_1, "Resource\tRequests\tLimits\n")
w.Write(LEVEL_1, "--------\t--------\t------\n")
reqs, limits := getPodsTotalRequestsAndLimits(nodeNonTerminatedPodsList)
cpuReqs, cpuLimits, memoryReqs, memoryLimits := reqs[api.ResourceCPU], limits[api.ResourceCPU], reqs[api.ResourceMemory], limits[api.ResourceMemory]
fractionCpuReqs := float64(0)
@ -2989,9 +3020,21 @@ func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node
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))
w.Write(LEVEL_1, "%s\t%s (%d%%)\t%s (%d%%)\n",
api.ResourceCPU, cpuReqs.String(), int64(fractionCpuReqs), cpuLimits.String(), int64(fractionCpuLimits))
w.Write(LEVEL_1, "%s\t%s (%d%%)\t%s (%d%%)\n",
api.ResourceMemory, memoryReqs.String(), int64(fractionMemoryReqs), memoryLimits.String(), int64(fractionMemoryLimits))
extResources := make([]string, 0, len(allocatable))
for resource := range allocatable {
if !helper.IsStandardContainerResourceName(string(resource)) && resource != api.ResourcePods {
extResources = append(extResources, string(resource))
}
}
sort.Strings(extResources)
for _, ext := range extResources {
extRequests, extLimits := reqs[api.ResourceName(ext)], limits[api.ResourceName(ext)]
w.Write(LEVEL_1, "%s\t%s\t%s\n", ext, extRequests.String(), extLimits.String())
}
}
func getPodsTotalRequestsAndLimits(podList *api.PodList) (reqs map[api.ResourceName]resource.Quantity, limits map[api.ResourceName]resource.Quantity) {
@ -3047,11 +3090,11 @@ func DescribeEvents(el *api.EventList, w PrefixWriter) {
// DeploymentDescriber generates information about a deployment.
type DeploymentDescriber struct {
clientset.Interface
extensionV1beta1Client clientextensionsv1beta1.ExtensionsV1beta1Interface
external externalclient.Interface
}
func (dd *DeploymentDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
d, err := dd.extensionV1beta1Client.Deployments(namespace).Get(name, metav1.GetOptions{})
d, err := dd.external.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return "", err
}
@ -3072,7 +3115,7 @@ func (dd *DeploymentDescriber) Describe(namespace, name string, describerSetting
return describeDeployment(d, selector, internalDeployment, events, dd)
}
func describeDeployment(d *versionedextension.Deployment, selector labels.Selector, internalDeployment *extensions.Deployment, events *api.EventList, dd *DeploymentDescriber) (string, error) {
func describeDeployment(d *appsv1.Deployment, selector labels.Selector, internalDeployment *extensions.Deployment, events *api.EventList, dd *DeploymentDescriber) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", d.ObjectMeta.Name)
@ -3096,10 +3139,10 @@ func describeDeployment(d *versionedextension.Deployment, selector labels.Select
w.Write(LEVEL_1, "%v \t%v\t%v\n", c.Type, c.Status, c.Reason)
}
}
oldRSs, _, newRS, err := deploymentutil.GetAllReplicaSets(d, dd.extensionV1beta1Client)
oldRSs, _, newRS, err := deploymentutil.GetAllReplicaSets(d, dd.external.AppsV1())
if err == nil {
w.Write(LEVEL_0, "OldReplicaSets:\t%s\n", printReplicaSetsByLabels(oldRSs))
var newRSs []*versionedextension.ReplicaSet
var newRSs []*appsv1.ReplicaSet
if newRS != nil {
newRSs = append(newRSs, newRS)
}
@ -3113,7 +3156,7 @@ func describeDeployment(d *versionedextension.Deployment, selector labels.Select
})
}
func printReplicaSetsByLabels(matchingRSs []*versionedextension.ReplicaSet) string {
func printReplicaSetsByLabels(matchingRSs []*appsv1.ReplicaSet) string {
// Format the matching ReplicaSets into strings.
rsStrings := make([]string, 0, len(matchingRSs))
for _, rs := range matchingRSs {
@ -3258,15 +3301,18 @@ func printNetworkPolicySpecIngressFrom(npirs []networking.NetworkPolicyIngressRu
w.Write(LEVEL_0, "%s%s\n", initialIndent, "From: <any> (traffic not restricted by source)")
} else {
for _, from := range npir.From {
w.Write(LEVEL_0, "%s", initialIndent)
if from.PodSelector != nil {
w.Write(LEVEL_0, "%s: %s\n", "From PodSelector", metav1.FormatLabelSelector(from.PodSelector))
w.Write(LEVEL_0, "%s%s\n", initialIndent, "From:")
if from.PodSelector != nil && from.NamespaceSelector != nil {
w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "NamespaceSelector", metav1.FormatLabelSelector(from.NamespaceSelector))
w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "PodSelector", metav1.FormatLabelSelector(from.PodSelector))
} else if from.PodSelector != nil {
w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "PodSelector", metav1.FormatLabelSelector(from.PodSelector))
} else if from.NamespaceSelector != nil {
w.Write(LEVEL_0, "%s: %s\n", "From NamespaceSelector", metav1.FormatLabelSelector(from.NamespaceSelector))
w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "NamespaceSelector", metav1.FormatLabelSelector(from.NamespaceSelector))
} else if from.IPBlock != nil {
w.Write(LEVEL_0, "From IPBlock:\n")
w.Write(LEVEL_0, "%s%sCIDR: %s\n", initialIndent, initialIndent, from.IPBlock.CIDR)
w.Write(LEVEL_0, "%s%sExcept: %v\n", initialIndent, initialIndent, strings.Join(from.IPBlock.Except, ", "))
w.Write(LEVEL_1, "%sIPBlock:\n", initialIndent)
w.Write(LEVEL_2, "%sCIDR: %s\n", initialIndent, from.IPBlock.CIDR)
w.Write(LEVEL_2, "%sExcept: %v\n", initialIndent, strings.Join(from.IPBlock.Except, ", "))
}
}
}
@ -3299,15 +3345,18 @@ func printNetworkPolicySpecEgressTo(npers []networking.NetworkPolicyEgressRule,
w.Write(LEVEL_0, "%s%s\n", initialIndent, "To: <any> (traffic not restricted by source)")
} else {
for _, to := range nper.To {
w.Write(LEVEL_0, "%s", initialIndent)
if to.PodSelector != nil {
w.Write(LEVEL_0, "%s: %s\n", "To PodSelector", metav1.FormatLabelSelector(to.PodSelector))
w.Write(LEVEL_0, "%s%s\n", initialIndent, "To:")
if to.PodSelector != nil && to.NamespaceSelector != nil {
w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "NamespaceSelector", metav1.FormatLabelSelector(to.NamespaceSelector))
w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "PodSelector", metav1.FormatLabelSelector(to.PodSelector))
} else if to.PodSelector != nil {
w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "PodSelector", metav1.FormatLabelSelector(to.PodSelector))
} else if to.NamespaceSelector != nil {
w.Write(LEVEL_0, "%s: %s\n", "To NamespaceSelector", metav1.FormatLabelSelector(to.NamespaceSelector))
w.Write(LEVEL_1, "%s%s: %s\n", initialIndent, "NamespaceSelector", metav1.FormatLabelSelector(to.NamespaceSelector))
} else if to.IPBlock != nil {
w.Write(LEVEL_0, "To IPBlock:\n")
w.Write(LEVEL_0, "%s%sCIDR: %s\n", initialIndent, initialIndent, to.IPBlock.CIDR)
w.Write(LEVEL_0, "%s%sExcept: %v\n", initialIndent, initialIndent, strings.Join(to.IPBlock.Except, ", "))
w.Write(LEVEL_1, "%sIPBlock:\n", initialIndent)
w.Write(LEVEL_2, "%sCIDR: %s\n", initialIndent, to.IPBlock.CIDR)
w.Write(LEVEL_2, "%sExcept: %v\n", initialIndent, strings.Join(to.IPBlock.Except, ", "))
}
}
}
@ -3456,7 +3505,7 @@ type PodSecurityPolicyDescriber struct {
}
func (d *PodSecurityPolicyDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
psp, err := d.Extensions().PodSecurityPolicies().Get(name, metav1.GetOptions{})
psp, err := d.Policy().PodSecurityPolicies().Get(name, metav1.GetOptions{})
if err != nil {
return "", err
}
@ -3464,7 +3513,7 @@ func (d *PodSecurityPolicyDescriber) Describe(namespace, name string, describerS
return describePodSecurityPolicy(psp)
}
func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error) {
func describePodSecurityPolicy(psp *policy.PodSecurityPolicy) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", psp.Name)
@ -3501,13 +3550,13 @@ func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error
w.Write(LEVEL_2, "Level:\t%s\n", stringOrNone(level))
w.Write(LEVEL_1, "Run As User Strategy: %s\t\n", string(psp.Spec.RunAsUser.Rule))
w.Write(LEVEL_2, "Ranges:\t%s\n", userIDRangeToString(psp.Spec.RunAsUser.Ranges))
w.Write(LEVEL_2, "Ranges:\t%s\n", idRangeToString(psp.Spec.RunAsUser.Ranges))
w.Write(LEVEL_1, "FSGroup Strategy: %s\t\n", string(psp.Spec.FSGroup.Rule))
w.Write(LEVEL_2, "Ranges:\t%s\n", groupIDRangeToString(psp.Spec.FSGroup.Ranges))
w.Write(LEVEL_2, "Ranges:\t%s\n", idRangeToString(psp.Spec.FSGroup.Ranges))
w.Write(LEVEL_1, "Supplemental Groups Strategy: %s\t\n", string(psp.Spec.SupplementalGroups.Rule))
w.Write(LEVEL_2, "Ranges:\t%s\n", groupIDRangeToString(psp.Spec.SupplementalGroups.Ranges))
w.Write(LEVEL_2, "Ranges:\t%s\n", idRangeToString(psp.Spec.SupplementalGroups.Ranges))
return nil
})
@ -3524,7 +3573,7 @@ func stringOrDefaultValue(s, defaultValue string) string {
return defaultValue
}
func fsTypeToString(volumes []extensions.FSType) string {
func fsTypeToString(volumes []policy.FSType) string {
strVolumes := []string{}
for _, v := range volumes {
strVolumes = append(strVolumes, string(v))
@ -3532,7 +3581,7 @@ func fsTypeToString(volumes []extensions.FSType) string {
return stringOrNone(strings.Join(strVolumes, ","))
}
func flexVolumesToString(flexVolumes []extensions.AllowedFlexVolume) string {
func flexVolumesToString(flexVolumes []policy.AllowedFlexVolume) string {
volumes := []string{}
for _, flexVolume := range flexVolumes {
volumes = append(volumes, "driver="+flexVolume.Driver)
@ -3540,7 +3589,7 @@ func flexVolumesToString(flexVolumes []extensions.AllowedFlexVolume) string {
return stringOrDefaultValue(strings.Join(volumes, ","), "<all>")
}
func hostPortRangeToString(ranges []extensions.HostPortRange) string {
func hostPortRangeToString(ranges []policy.HostPortRange) string {
formattedString := ""
if ranges != nil {
strRanges := []string{}
@ -3552,19 +3601,7 @@ func hostPortRangeToString(ranges []extensions.HostPortRange) string {
return stringOrNone(formattedString)
}
func userIDRangeToString(ranges []extensions.UserIDRange) string {
formattedString := ""
if ranges != nil {
strRanges := []string{}
for _, r := range ranges {
strRanges = append(strRanges, fmt.Sprintf("%d-%d", r.Min, r.Max))
}
formattedString = strings.Join(strRanges, ",")
}
return stringOrNone(formattedString)
}
func groupIDRangeToString(ranges []extensions.GroupIDRange) string {
func idRangeToString(ranges []policy.IDRange) string {
formattedString := ""
if ranges != nil {
strRanges := []string{}
@ -3794,23 +3831,19 @@ func printTaintsMultilineWithIndent(w PrefixWriter, initialIndent, title, innerI
}
// to print taints in the sorted order
keys := make([]string, 0, len(taints))
for _, taint := range taints {
keys = append(keys, string(taint.Effect)+","+taint.Key)
}
sort.Strings(keys)
for i, key := range keys {
for _, taint := range taints {
if string(taint.Effect)+","+taint.Key == key {
if i != 0 {
w.Write(LEVEL_0, "%s", initialIndent)
w.Write(LEVEL_0, "%s", innerIndent)
}
w.Write(LEVEL_0, "%s\n", taint.ToString())
i++
}
sort.Slice(taints, func(i, j int) bool {
cmpKey := func(taint api.Taint) string {
return string(taint.Effect) + "," + taint.Key
}
return cmpKey(taints[i]) < cmpKey(taints[j])
})
for i, taint := range taints {
if i != 0 {
w.Write(LEVEL_0, "%s", initialIndent)
w.Write(LEVEL_0, "%s", innerIndent)
}
w.Write(LEVEL_0, "%s\n", taint.ToString())
}
}
@ -3829,33 +3862,26 @@ func printTolerationsMultilineWithIndent(w PrefixWriter, initialIndent, title, i
}
// to print tolerations in the sorted order
keys := make([]string, 0, len(tolerations))
for _, toleration := range tolerations {
keys = append(keys, toleration.Key)
}
sort.Strings(keys)
sort.Slice(tolerations, func(i, j int) bool {
return tolerations[i].Key < tolerations[j].Key
})
for i, key := range keys {
for _, toleration := range tolerations {
if toleration.Key == key {
if i != 0 {
w.Write(LEVEL_0, "%s", initialIndent)
w.Write(LEVEL_0, "%s", innerIndent)
}
w.Write(LEVEL_0, "%s", toleration.Key)
if len(toleration.Value) != 0 {
w.Write(LEVEL_0, "=%s", toleration.Value)
}
if len(toleration.Effect) != 0 {
w.Write(LEVEL_0, ":%s", toleration.Effect)
}
if toleration.TolerationSeconds != nil {
w.Write(LEVEL_0, " for %ds", *toleration.TolerationSeconds)
}
w.Write(LEVEL_0, "\n")
i++
}
for i, toleration := range tolerations {
if i != 0 {
w.Write(LEVEL_0, "%s", initialIndent)
w.Write(LEVEL_0, "%s", innerIndent)
}
w.Write(LEVEL_0, "%s", toleration.Key)
if len(toleration.Value) != 0 {
w.Write(LEVEL_0, "=%s", toleration.Value)
}
if len(toleration.Effect) != 0 {
w.Write(LEVEL_0, ":%s", toleration.Effect)
}
if toleration.TolerationSeconds != nil {
w.Write(LEVEL_0, " for %ds", *toleration.TolerationSeconds)
}
w.Write(LEVEL_0, "\n")
}
}
@ -3944,14 +3970,6 @@ func (list SortableVolumeDevices) Less(i, j int) bool {
return list[i].DevicePath < list[j].DevicePath
}
// TODO: get rid of this and plumb the caller correctly
func versionedExtensionsClientV1beta1(internalClient clientset.Interface) clientextensionsv1beta1.ExtensionsV1beta1Interface {
if internalClient == nil {
return &clientextensionsv1beta1.ExtensionsV1beta1Client{}
}
return clientextensionsv1beta1.New(internalClient.Extensions().RESTClient())
}
var maxAnnotationLen = 200
// printAnnotationsMultilineWithFilter prints filtered multiple annotations with a proper alignment.

View File

@ -25,14 +25,15 @@ import (
"testing"
"time"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/intstr"
versionedfake "k8s.io/client-go/kubernetes/fake"
"k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/autoscaling"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/extensions"
@ -282,10 +283,12 @@ func getResourceList(cpu, memory string) api.ResourceList {
func TestDescribeService(t *testing.T) {
testCases := []struct {
name string
service *api.Service
expect []string
}{
{
name: "test1",
service: &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
@ -323,6 +326,7 @@ func TestDescribeService(t *testing.T) {
},
},
{
name: "test2",
service: &api.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
@ -361,18 +365,20 @@ func TestDescribeService(t *testing.T) {
},
}
for _, testCase := range testCases {
fake := fake.NewSimpleClientset(testCase.service)
c := &describeClient{T: t, Namespace: "foo", Interface: fake}
d := ServiceDescriber{c}
out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
for _, expected := range testCase.expect {
if !strings.Contains(out, expected) {
t.Errorf("expected to find %q in output: %q", expected, out)
t.Run(testCase.name, func(t *testing.T) {
fake := fake.NewSimpleClientset(testCase.service)
c := &describeClient{T: t, Namespace: "foo", Interface: fake}
d := ServiceDescriber{c}
out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
}
for _, expected := range testCase.expect {
if !strings.Contains(out, expected) {
t.Errorf("expected to find %q in output: %q", expected, out)
}
}
})
}
}
@ -452,12 +458,14 @@ func VerifyDatesInOrder(
func TestDescribeContainers(t *testing.T) {
trueVal := true
testCases := []struct {
name string
container api.Container
status api.ContainerStatus
expectedElements []string
}{
// Running state.
{
name: "test1",
container: api.Container{Name: "test", Image: "image"},
status: api.ContainerStatus{
Name: "test",
@ -473,6 +481,7 @@ func TestDescribeContainers(t *testing.T) {
},
// Waiting state.
{
name: "test2",
container: api.Container{Name: "test", Image: "image"},
status: api.ContainerStatus{
Name: "test",
@ -488,6 +497,7 @@ func TestDescribeContainers(t *testing.T) {
},
// Terminated state.
{
name: "test3",
container: api.Container{Name: "test", Image: "image"},
status: api.ContainerStatus{
Name: "test",
@ -506,6 +516,7 @@ func TestDescribeContainers(t *testing.T) {
},
// Last Terminated
{
name: "test4",
container: api.Container{Name: "test", Image: "image"},
status: api.ContainerStatus{
Name: "test",
@ -529,6 +540,7 @@ func TestDescribeContainers(t *testing.T) {
},
// No state defaults to waiting.
{
name: "test5",
container: api.Container{Name: "test", Image: "image"},
status: api.ContainerStatus{
Name: "test",
@ -539,6 +551,7 @@ func TestDescribeContainers(t *testing.T) {
},
// Env
{
name: "test6",
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{ConfigMapRef: &api.ConfigMapEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}},
status: api.ContainerStatus{
Name: "test",
@ -548,6 +561,7 @@ func TestDescribeContainers(t *testing.T) {
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap\tOptional: false"},
},
{
name: "test7",
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{Prefix: "p_", ConfigMapRef: &api.ConfigMapEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}},
status: api.ContainerStatus{
Name: "test",
@ -557,6 +571,7 @@ func TestDescribeContainers(t *testing.T) {
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap with prefix 'p_'\tOptional: false"},
},
{
name: "test8",
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{ConfigMapRef: &api.ConfigMapEnvSource{Optional: &trueVal, LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}},
status: api.ContainerStatus{
Name: "test",
@ -566,6 +581,7 @@ func TestDescribeContainers(t *testing.T) {
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tConfigMap\tOptional: true"},
},
{
name: "test9",
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{SecretRef: &api.SecretEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}, Optional: &trueVal}}}},
status: api.ContainerStatus{
Name: "test",
@ -575,6 +591,7 @@ func TestDescribeContainers(t *testing.T) {
expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "envname", "xyz", "a123\tSecret\tOptional: true"},
},
{
name: "test10",
container: api.Container{Name: "test", Image: "image", Env: []api.EnvVar{{Name: "envname", Value: "xyz"}}, EnvFrom: []api.EnvFromSource{{Prefix: "p_", SecretRef: &api.SecretEnvSource{LocalObjectReference: api.LocalObjectReference{Name: "a123"}}}}},
status: api.ContainerStatus{
Name: "test",
@ -585,6 +602,7 @@ func TestDescribeContainers(t *testing.T) {
},
// Command
{
name: "test11",
container: api.Container{Name: "test", Image: "image", Command: []string{"sleep", "1000"}},
status: api.ContainerStatus{
Name: "test",
@ -595,6 +613,7 @@ func TestDescribeContainers(t *testing.T) {
},
// Args
{
name: "test12",
container: api.Container{Name: "test", Image: "image", Args: []string{"time", "1000"}},
status: api.ContainerStatus{
Name: "test",
@ -605,6 +624,7 @@ func TestDescribeContainers(t *testing.T) {
},
// Using limits.
{
name: "test13",
container: api.Container{
Name: "test",
Image: "image",
@ -625,6 +645,7 @@ func TestDescribeContainers(t *testing.T) {
},
// Using requests.
{
name: "test14",
container: api.Container{
Name: "test",
Image: "image",
@ -640,6 +661,7 @@ func TestDescribeContainers(t *testing.T) {
},
// volumeMounts read/write
{
name: "test15",
container: api.Container{
Name: "test",
Image: "image",
@ -654,6 +676,7 @@ func TestDescribeContainers(t *testing.T) {
},
// volumeMounts readonly
{
name: "test16",
container: api.Container{
Name: "test",
Image: "image",
@ -670,6 +693,7 @@ func TestDescribeContainers(t *testing.T) {
// volumeDevices
{
name: "test17",
container: api.Container{
Name: "test",
Image: "image",
@ -685,23 +709,25 @@ func TestDescribeContainers(t *testing.T) {
}
for i, testCase := range testCases {
out := new(bytes.Buffer)
pod := api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{testCase.container},
},
Status: api.PodStatus{
ContainerStatuses: []api.ContainerStatus{testCase.status},
},
}
writer := NewPrefixWriter(out)
describeContainers("Containers", pod.Spec.Containers, pod.Status.ContainerStatuses, EnvValueRetriever(&pod), writer, "")
output := out.String()
for _, expected := range testCase.expectedElements {
if !strings.Contains(output, expected) {
t.Errorf("Test case %d: expected to find %q in output: %q", i, expected, output)
t.Run(testCase.name, func(t *testing.T) {
out := new(bytes.Buffer)
pod := api.Pod{
Spec: api.PodSpec{
Containers: []api.Container{testCase.container},
},
Status: api.PodStatus{
ContainerStatuses: []api.ContainerStatus{testCase.status},
},
}
}
writer := NewPrefixWriter(out)
describeContainers("Containers", pod.Spec.Containers, pod.Status.ContainerStatuses, EnvValueRetriever(&pod), writer, "")
output := out.String()
for _, expected := range testCase.expectedElements {
if !strings.Contains(output, expected) {
t.Errorf("Test case %d: expected to find %q in output: %q", i, expected, output)
}
}
})
}
}
@ -787,10 +813,12 @@ func TestDefaultDescribers(t *testing.T) {
func TestGetPodsTotalRequests(t *testing.T) {
testCases := []struct {
name string
pods *api.PodList
expectedReqs map[api.ResourceName]resource.Quantity
}{
{
name: "test1",
pods: &api.PodList{
Items: []api.Pod{
{
@ -852,10 +880,12 @@ func TestGetPodsTotalRequests(t *testing.T) {
}
for _, testCase := range testCases {
reqs, _ := getPodsTotalRequestsAndLimits(testCase.pods)
if !apiequality.Semantic.DeepEqual(reqs, testCase.expectedReqs) {
t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs)
}
t.Run(testCase.name, func(t *testing.T) {
reqs, _ := getPodsTotalRequestsAndLimits(testCase.pods)
if !apiequality.Semantic.DeepEqual(reqs, testCase.expectedReqs) {
t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs)
}
})
}
}
@ -863,12 +893,14 @@ func TestPersistentVolumeDescriber(t *testing.T) {
block := api.PersistentVolumeBlock
file := api.PersistentVolumeFilesystem
testCases := []struct {
name string
plugin string
pv *api.PersistentVolume
expectedElements []string
unexpectedElements []string
}{
{
name: "test0",
plugin: "hostpath",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -881,6 +913,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"VolumeMode", "Filesystem"},
},
{
name: "test1",
plugin: "gce",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -894,6 +927,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
expectedElements: []string{"VolumeMode", "Filesystem"},
},
{
name: "test2",
plugin: "ebs",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -906,6 +940,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"VolumeMode", "Filesystem"},
},
{
name: "test3",
plugin: "nfs",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -918,6 +953,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"VolumeMode", "Filesystem"},
},
{
name: "test4",
plugin: "iscsi",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -931,6 +967,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
expectedElements: []string{"VolumeMode", "Block"},
},
{
name: "test5",
plugin: "gluster",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -943,6 +980,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"VolumeMode", "Filesystem"},
},
{
name: "test6",
plugin: "rbd",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -955,6 +993,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"VolumeMode", "Filesystem"},
},
{
name: "test7",
plugin: "quobyte",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -967,18 +1006,20 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"VolumeMode", "Filesystem"},
},
{
name: "test8",
plugin: "cinder",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
Spec: api.PersistentVolumeSpec{
PersistentVolumeSource: api.PersistentVolumeSource{
Cinder: &api.CinderVolumeSource{},
Cinder: &api.CinderPersistentVolumeSource{},
},
},
},
unexpectedElements: []string{"VolumeMode", "Filesystem"},
},
{
name: "test9",
plugin: "fc",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -992,6 +1033,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
expectedElements: []string{"VolumeMode", "Block"},
},
{
name: "test10",
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -1005,6 +1047,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"Required Terms", "Term "},
},
{
name: "test11",
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -1019,6 +1062,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"Required Terms", "Term "},
},
{
name: "test12",
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -1035,6 +1079,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
unexpectedElements: []string{"Term "},
},
{
name: "test13",
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -1059,6 +1104,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
expectedElements: []string{"Node Affinity", "Required Terms", "Term 0", "Term 1"},
},
{
name: "test14",
plugin: "local",
pv: &api.PersistentVolume{
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
@ -1094,25 +1140,27 @@ func TestPersistentVolumeDescriber(t *testing.T) {
}
for _, test := range testCases {
fake := fake.NewSimpleClientset(test.pv)
c := PersistentVolumeDescriber{fake}
str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("Unexpected error for test %s: %v", test.plugin, err)
}
if str == "" {
t.Errorf("Unexpected empty string for test %s. Expected PV Describer output", test.plugin)
}
for _, expected := range test.expectedElements {
if !strings.Contains(str, expected) {
t.Errorf("expected to find %q in output: %q", expected, str)
t.Run(test.name, func(t *testing.T) {
fake := fake.NewSimpleClientset(test.pv)
c := PersistentVolumeDescriber{fake}
str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("Unexpected error for test %s: %v", test.plugin, err)
}
}
for _, unexpected := range test.unexpectedElements {
if strings.Contains(str, unexpected) {
t.Errorf("unexpected to find %q in output: %q", unexpected, str)
if str == "" {
t.Errorf("Unexpected empty string for test %s. Expected PV Describer output", test.plugin)
}
}
for _, expected := range test.expectedElements {
if !strings.Contains(str, expected) {
t.Errorf("expected to find %q in output: %q", expected, str)
}
}
for _, unexpected := range test.unexpectedElements {
if strings.Contains(str, unexpected) {
t.Errorf("unexpected to find %q in output: %q", unexpected, str)
}
}
})
}
}
@ -1120,6 +1168,7 @@ func TestPersistentVolumeClaimDescriber(t *testing.T) {
block := api.PersistentVolumeBlock
file := api.PersistentVolumeFilesystem
goldClassName := "gold"
now := time.Now()
testCases := []struct {
name string
pvc *api.PersistentVolumeClaim
@ -1170,39 +1219,138 @@ func TestPersistentVolumeClaimDescriber(t *testing.T) {
},
expectedElements: []string{"VolumeMode", "Block"},
},
// Tests for Status.Condition.
{
name: "condition-type",
pvc: &api.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
Spec: api.PersistentVolumeClaimSpec{
VolumeName: "volume4",
StorageClassName: &goldClassName,
},
Status: api.PersistentVolumeClaimStatus{
Conditions: []api.PersistentVolumeClaimCondition{
{Type: api.PersistentVolumeClaimResizing},
},
},
},
expectedElements: []string{"Conditions", "Type", "Resizing"},
},
{
name: "condition-status",
pvc: &api.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
Spec: api.PersistentVolumeClaimSpec{
VolumeName: "volume5",
StorageClassName: &goldClassName,
},
Status: api.PersistentVolumeClaimStatus{
Conditions: []api.PersistentVolumeClaimCondition{
{Status: api.ConditionTrue},
},
},
},
expectedElements: []string{"Conditions", "Status", "True"},
},
{
name: "condition-last-probe-time",
pvc: &api.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
Spec: api.PersistentVolumeClaimSpec{
VolumeName: "volume6",
StorageClassName: &goldClassName,
},
Status: api.PersistentVolumeClaimStatus{
Conditions: []api.PersistentVolumeClaimCondition{
{LastProbeTime: metav1.Time{Time: now}},
},
},
},
expectedElements: []string{"Conditions", "LastProbeTime", now.Format(time.RFC1123Z)},
},
{
name: "condition-last-transition-time",
pvc: &api.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
Spec: api.PersistentVolumeClaimSpec{
VolumeName: "volume7",
StorageClassName: &goldClassName,
},
Status: api.PersistentVolumeClaimStatus{
Conditions: []api.PersistentVolumeClaimCondition{
{LastTransitionTime: metav1.Time{Time: now}},
},
},
},
expectedElements: []string{"Conditions", "LastTransitionTime", now.Format(time.RFC1123Z)},
},
{
name: "condition-reason",
pvc: &api.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
Spec: api.PersistentVolumeClaimSpec{
VolumeName: "volume8",
StorageClassName: &goldClassName,
},
Status: api.PersistentVolumeClaimStatus{
Conditions: []api.PersistentVolumeClaimCondition{
{Reason: "OfflineResize"},
},
},
},
expectedElements: []string{"Conditions", "Reason", "OfflineResize"},
},
{
name: "condition-message",
pvc: &api.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
Spec: api.PersistentVolumeClaimSpec{
VolumeName: "volume9",
StorageClassName: &goldClassName,
},
Status: api.PersistentVolumeClaimStatus{
Conditions: []api.PersistentVolumeClaimCondition{
{Message: "User request resize"},
},
},
},
expectedElements: []string{"Conditions", "Message", "User request resize"},
},
}
for _, test := range testCases {
fake := fake.NewSimpleClientset(test.pvc)
c := PersistentVolumeClaimDescriber{fake}
str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("Unexpected error for test %s: %v", test.name, err)
}
if str == "" {
t.Errorf("Unexpected empty string for test %s. Expected PVC Describer output", test.name)
}
for _, expected := range test.expectedElements {
if !strings.Contains(str, expected) {
t.Errorf("expected to find %q in output: %q", expected, str)
t.Run(test.name, func(t *testing.T) {
fake := fake.NewSimpleClientset(test.pvc)
c := PersistentVolumeClaimDescriber{fake}
str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("Unexpected error for test %s: %v", test.name, err)
}
}
for _, unexpected := range test.unexpectedElements {
if strings.Contains(str, unexpected) {
t.Errorf("unexpected to find %q in output: %q", unexpected, str)
if str == "" {
t.Errorf("Unexpected empty string for test %s. Expected PVC Describer output", test.name)
}
}
for _, expected := range test.expectedElements {
if !strings.Contains(str, expected) {
t.Errorf("expected to find %q in output: %q", expected, str)
}
}
for _, unexpected := range test.unexpectedElements {
if strings.Contains(str, unexpected) {
t.Errorf("unexpected to find %q in output: %q", unexpected, str)
}
}
})
}
}
func TestDescribeDeployment(t *testing.T) {
fake := fake.NewSimpleClientset()
versionedFake := versionedfake.NewSimpleClientset(&v1beta1.Deployment{
versionedFake := versionedfake.NewSimpleClientset(&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "foo",
},
Spec: v1beta1.DeploymentSpec{
Spec: appsv1.DeploymentSpec{
Replicas: utilpointer.Int32Ptr(1),
Selector: &metav1.LabelSelector{},
Template: v1.PodTemplateSpec{
@ -1214,7 +1362,7 @@ func TestDescribeDeployment(t *testing.T) {
},
},
})
d := DeploymentDescriber{fake, versionedFake.ExtensionsV1beta1()}
d := DeploymentDescriber{fake, versionedFake}
out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("unexpected error: %v", err)
@ -1781,20 +1929,22 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
}
for _, test := range tests {
test.hpa.ObjectMeta = metav1.ObjectMeta{
Name: "bar",
Namespace: "foo",
}
fake := fake.NewSimpleClientset(&test.hpa)
desc := HorizontalPodAutoscalerDescriber{fake}
str, err := desc.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("Unexpected error for test %s: %v", test.name, err)
}
if str == "" {
t.Errorf("Unexpected empty string for test %s. Expected HPA Describer output", test.name)
}
t.Logf("Description for %q:\n%s", test.name, str)
t.Run(test.name, func(t *testing.T) {
test.hpa.ObjectMeta = metav1.ObjectMeta{
Name: "bar",
Namespace: "foo",
}
fake := fake.NewSimpleClientset(&test.hpa)
desc := HorizontalPodAutoscalerDescriber{fake}
str, err := desc.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("Unexpected error for test %s: %v", test.name, err)
}
if str == "" {
t.Errorf("Unexpected empty string for test %s. Expected HPA Describer output", test.name)
}
t.Logf("Description for %q:\n%s", test.name, str)
})
}
}
@ -1827,16 +1977,16 @@ func TestDescribeEvents(t *testing.T) {
},
"DeploymentDescriber": &DeploymentDescriber{
fake.NewSimpleClientset(events),
versionedfake.NewSimpleClientset(&v1beta1.Deployment{
versionedfake.NewSimpleClientset(&appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "foo",
},
Spec: v1beta1.DeploymentSpec{
Spec: appsv1.DeploymentSpec{
Replicas: utilpointer.Int32Ptr(1),
Selector: &metav1.LabelSelector{},
},
}).ExtensionsV1beta1(),
}),
},
"EndpointsDescriber": &EndpointsDescriber{
fake.NewSimpleClientset(&api.Endpoints{
@ -1924,27 +2074,29 @@ func TestDescribeEvents(t *testing.T) {
}
for name, d := range m {
out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("unexpected error for %q: %v", name, err)
}
if !strings.Contains(out, "bar") {
t.Errorf("unexpected out for %q: %s", name, out)
}
if !strings.Contains(out, "Events:") {
t.Errorf("events not found for %q when ShowEvents=true: %s", name, out)
}
t.Run(name, func(t *testing.T) {
out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("unexpected error for %q: %v", name, err)
}
if !strings.Contains(out, "bar") {
t.Errorf("unexpected out for %q: %s", name, out)
}
if !strings.Contains(out, "Events:") {
t.Errorf("events not found for %q when ShowEvents=true: %s", name, out)
}
out, err = d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: false})
if err != nil {
t.Errorf("unexpected error for %q: %s", name, err)
}
if !strings.Contains(out, "bar") {
t.Errorf("unexpected out for %q: %s", name, out)
}
if strings.Contains(out, "Events:") {
t.Errorf("events found for %q when ShowEvents=false: %s", name, out)
}
out, err = d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: false})
if err != nil {
t.Errorf("unexpected error for %q: %s", name, err)
}
if !strings.Contains(out, "bar") {
t.Errorf("unexpected out for %q: %s", name, out)
}
if strings.Contains(out, "Events:") {
t.Errorf("events found for %q when ShowEvents=false: %s", name, out)
}
})
}
}
@ -1972,13 +2124,15 @@ func TestPrintLabelsMultiline(t *testing.T) {
},
}
for i, testCase := range testCases {
out := new(bytes.Buffer)
writer := NewPrefixWriter(out)
printAnnotationsMultiline(writer, "Annotations", testCase.annotations)
output := out.String()
if output != testCase.expectPrint {
t.Errorf("Test case %d: expected to find %q in output: %q", i, testCase.expectPrint, output)
}
t.Run(testCase.expectPrint, func(t *testing.T) {
out := new(bytes.Buffer)
writer := NewPrefixWriter(out)
printAnnotationsMultiline(writer, "Annotations", testCase.annotations)
output := out.String()
if output != testCase.expectPrint {
t.Errorf("Test case %d: expected to find %q in output: %q", i, testCase.expectPrint, output)
}
})
}
}
@ -2089,22 +2243,22 @@ func TestDescribePodSecurityPolicy(t *testing.T) {
"Supplemental Groups Strategy: RunAsAny",
}
fake := fake.NewSimpleClientset(&extensions.PodSecurityPolicy{
fake := fake.NewSimpleClientset(&policy.PodSecurityPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "mypsp",
},
Spec: extensions.PodSecurityPolicySpec{
SELinux: extensions.SELinuxStrategyOptions{
Rule: extensions.SELinuxStrategyRunAsAny,
Spec: policy.PodSecurityPolicySpec{
SELinux: policy.SELinuxStrategyOptions{
Rule: policy.SELinuxStrategyRunAsAny,
},
RunAsUser: extensions.RunAsUserStrategyOptions{
Rule: extensions.RunAsUserStrategyRunAsAny,
RunAsUser: policy.RunAsUserStrategyOptions{
Rule: policy.RunAsUserStrategyRunAsAny,
},
FSGroup: extensions.FSGroupStrategyOptions{
Rule: extensions.FSGroupStrategyRunAsAny,
FSGroup: policy.FSGroupStrategyOptions{
Rule: policy.FSGroupStrategyRunAsAny,
},
SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{
Rule: extensions.SupplementalGroupsStrategyRunAsAny,
SupplementalGroups: policy.SupplementalGroupsStrategyOptions{
Rule: policy.SupplementalGroupsStrategyRunAsAny,
},
},
})
@ -2177,10 +2331,17 @@ Spec:
Allowing ingress traffic:
To Port: 80/TCP
To Port: 82/TCP
From PodSelector: id=app2,id2=app3
From NamespaceSelector: id=app2,id2=app3
From NamespaceSelector: foo in (bar1,bar2),id=app2,id2=app3
From IPBlock:
From:
NamespaceSelector: id=ns1,id2=ns2
PodSelector: id=pod1,id2=pod2
From:
PodSelector: id=app2,id2=app3
From:
NamespaceSelector: id=app2,id2=app3
From:
NamespaceSelector: foo in (bar1,bar2),id=app2,id2=app3
From:
IPBlock:
CIDR: 192.168.0.0/16
Except: 192.168.3.0/24, 192.168.4.0/24
----------
@ -2189,10 +2350,17 @@ Spec:
Allowing egress traffic:
To Port: 80/TCP
To Port: 82/TCP
To PodSelector: id=app2,id2=app3
To NamespaceSelector: id=app2,id2=app3
To NamespaceSelector: foo in (bar1,bar2),id=app2,id2=app3
To IPBlock:
To:
NamespaceSelector: id=ns1,id2=ns2
PodSelector: id=pod1,id2=pod2
To:
PodSelector: id=app2,id2=app3
To:
NamespaceSelector: id=app2,id2=app3
To:
NamespaceSelector: foo in (bar1,bar2),id=app2,id2=app3
To:
IPBlock:
CIDR: 192.168.0.0/16
Except: 192.168.3.0/24, 192.168.4.0/24
----------
@ -2229,6 +2397,20 @@ Spec:
{Port: &port82, Protocol: &protoTCP},
},
From: []networking.NetworkPolicyPeer{
{
PodSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"id": "pod1",
"id2": "pod2",
},
},
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"id": "ns1",
"id2": "ns2",
},
},
},
{
PodSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
@ -2273,6 +2455,20 @@ Spec:
{Port: &port82, Protocol: &protoTCP},
},
To: []networking.NetworkPolicyPeer{
{
PodSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"id": "pod1",
"id2": "pod2",
},
},
NamespaceSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"id": "ns1",
"id2": "ns2",
},
},
},
{
PodSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
@ -2386,6 +2582,46 @@ func TestDescribeNode(t *testing.T) {
}
func TestDescribeStatefulSet(t *testing.T) {
fake := fake.NewSimpleClientset(&apps.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
Namespace: "foo",
},
Spec: apps.StatefulSetSpec{
Replicas: 1,
Selector: &metav1.LabelSelector{},
Template: api.PodTemplateSpec{
Spec: api.PodSpec{
Containers: []api.Container{
{Image: "mytest-image:latest"},
},
},
},
UpdateStrategy: apps.StatefulSetUpdateStrategy{
Type: apps.RollingUpdateStatefulSetStrategyType,
RollingUpdate: &apps.RollingUpdateStatefulSetStrategy{
Partition: 2,
},
},
},
})
d := StatefulSetDescriber{fake}
out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil {
t.Errorf("unexpected error: %v", err)
}
expectedOutputs := []string{
"bar", "foo", "Containers:", "mytest-image:latest", "Update Strategy", "RollingUpdate", "Partition",
}
for _, o := range expectedOutputs {
if !strings.Contains(out, o) {
t.Errorf("unexpected out: %s", out)
break
}
}
}
// boolPtr returns a pointer to a bool
func boolPtr(b bool) *bool {
o := b

View File

@ -40,6 +40,7 @@ import (
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/duration"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/pkg/api/events"
@ -220,6 +221,7 @@ func AddHandlers(h printers.PrintHandler) {
{Name: "Roles", Type: "string", Description: "The roles of the node"},
{Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
{Name: "Version", Type: "string", Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kubeletVersion"]},
{Name: "Internal-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]},
{Name: "External-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]},
{Name: "OS-Image", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["osImage"]},
{Name: "Kernel-Version", Type: "string", Priority: 1, Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kernelVersion"]},
@ -286,7 +288,7 @@ func AddHandlers(h printers.PrintHandler) {
persistentVolumeClaimColumnDefinitions := []metav1beta1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
{Name: "Status", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["phase"]},
{Name: "Volume", Type: "string", Description: apiv1.PersistentVolumeSpec{}.SwaggerDoc()["volumeName"]},
{Name: "Volume", Type: "string", Description: apiv1.PersistentVolumeClaimSpec{}.SwaggerDoc()["volumeName"]},
{Name: "Capacity", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["capacity"]},
{Name: "Access Modes", Type: "string", Description: apiv1.PersistentVolumeClaimStatus{}.SwaggerDoc()["accessModes"]},
{Name: "StorageClass", Type: "string", Description: "StorageClass of the pvc"},
@ -340,7 +342,7 @@ func AddHandlers(h printers.PrintHandler) {
podSecurityPolicyColumnDefinitions := []metav1beta1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
{Name: "Data", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["privileged"]},
{Name: "Priv", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["privileged"]},
{Name: "Caps", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["allowedCapabilities"]},
{Name: "SELinux", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["seLinux"]},
{Name: "RunAsUser", Type: "string", Description: extensionsv1beta1.PodSecurityPolicySpec{}.SwaggerDoc()["runAsUser"]},
@ -501,7 +503,8 @@ func translateTimestamp(timestamp metav1.Time) string {
if timestamp.IsZero() {
return "<unknown>"
}
return duration.ShortHumanDuration(time.Now().Sub(timestamp.Time))
return duration.ShortHumanDuration(time.Since(timestamp.Time))
}
var (
@ -572,6 +575,7 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR
}
if !initializing {
restarts = 0
hasRunning := false
for i := len(pod.Status.ContainerStatuses) - 1; i >= 0; i-- {
container := pod.Status.ContainerStatuses[i]
@ -587,9 +591,15 @@ func printPod(pod *api.Pod, options printers.PrintOptions) ([]metav1beta1.TableR
reason = fmt.Sprintf("ExitCode:%d", container.State.Terminated.ExitCode)
}
} else if container.Ready && container.State.Running != nil {
hasRunning = true
readyContainers++
}
}
// change pod status back to "Running" if there is at least one container still reporting as "Running" status
if reason == "Completed" && hasRunning {
reason = "Running"
}
}
if pod.DeletionTimestamp != nil && pod.Status.Reason == node.NodeUnreachablePodReason {
@ -598,7 +608,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, restarts, translateTimestamp(pod.CreationTimestamp))
row.Cells = append(row.Cells, pod.Name, fmt.Sprintf("%d/%d", readyContainers, totalContainers), reason, int64(restarts), translateTimestamp(pod.CreationTimestamp))
if options.Wide {
nodeName := pod.Spec.NodeName
@ -658,7 +668,7 @@ func printPodDisruptionBudget(obj *policy.PodDisruptionBudget, options printers.
maxUnavailable = "N/A"
}
row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, obj.Status.PodDisruptionsAllowed, translateTimestamp(obj.CreationTimestamp))
row.Cells = append(row.Cells, obj.Name, minAvailable, maxUnavailable, int64(obj.Status.PodDisruptionsAllowed), translateTimestamp(obj.CreationTimestamp))
return []metav1beta1.TableRow{row}, nil
}
@ -684,7 +694,7 @@ func printReplicationController(obj *api.ReplicationController, options printers
currentReplicas := obj.Status.Replicas
readyReplicas := obj.Status.ReadyReplicas
row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, readyReplicas, translateTimestamp(obj.CreationTimestamp))
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestamp(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))
@ -713,7 +723,7 @@ func printReplicaSet(obj *extensions.ReplicaSet, options printers.PrintOptions)
currentReplicas := obj.Status.Replicas
readyReplicas := obj.Status.ReadyReplicas
row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, readyReplicas, translateTimestamp(obj.CreationTimestamp))
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(readyReplicas), translateTimestamp(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))
@ -745,7 +755,7 @@ func printJob(obj *batch.Job, options printers.PrintOptions) ([]metav1beta1.Tabl
completions = "<none>"
}
row.Cells = append(row.Cells, obj.Name, completions, obj.Status.Succeeded, translateTimestamp(obj.CreationTimestamp))
row.Cells = append(row.Cells, obj.Name, completions, int64(obj.Status.Succeeded), translateTimestamp(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))
@ -775,7 +785,7 @@ func printCronJob(obj *batch.CronJob, options printers.PrintOptions) ([]metav1be
lastScheduleTime = translateTimestamp(*obj.Status.LastScheduleTime)
}
row.Cells = append(row.Cells, obj.Name, obj.Spec.Schedule, printBoolPtr(obj.Spec.Suspend), 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, translateTimestamp(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))
@ -962,7 +972,7 @@ func printStatefulSet(obj *apps.StatefulSet, options printers.PrintOptions) ([]m
desiredReplicas := obj.Spec.Replicas
currentReplicas := obj.Status.Replicas
createTime := translateTimestamp(obj.CreationTimestamp)
row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, createTime)
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), createTime)
if options.Wide {
names, images := layoutContainerCells(obj.Spec.Template.Spec.Containers)
row.Cells = append(row.Cells, names, images)
@ -993,7 +1003,7 @@ func printDaemonSet(obj *extensions.DaemonSet, options printers.PrintOptions) ([
numberUpdated := obj.Status.UpdatedNumberScheduled
numberAvailable := obj.Status.NumberAvailable
row.Cells = append(row.Cells, obj.Name, desiredScheduled, currentScheduled, numberReady, numberUpdated, 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), translateTimestamp(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))
@ -1057,7 +1067,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, obj.Type, len(obj.Data), translateTimestamp(obj.CreationTimestamp))
row.Cells = append(row.Cells, obj.Name, string(obj.Type), int64(len(obj.Data)), translateTimestamp(obj.CreationTimestamp))
return []metav1beta1.TableRow{row}, nil
}
@ -1077,7 +1087,7 @@ func printServiceAccount(obj *api.ServiceAccount, options printers.PrintOptions)
row := metav1beta1.TableRow{
Object: runtime.RawExtension{Object: obj},
}
row.Cells = append(row.Cells, obj.Name, len(obj.Secrets), translateTimestamp(obj.CreationTimestamp))
row.Cells = append(row.Cells, obj.Name, int64(len(obj.Secrets)), translateTimestamp(obj.CreationTimestamp))
return []metav1beta1.TableRow{row}, nil
}
@ -1138,7 +1148,7 @@ func printNode(obj *api.Node, options printers.PrintOptions) ([]metav1beta1.Tabl
if crVersion == "" {
crVersion = "<unknown>"
}
row.Cells = append(row.Cells, getNodeExternalIP(obj), osImage, kernelVersion, crVersion)
row.Cells = append(row.Cells, getNodeInternalIP(obj), getNodeExternalIP(obj), osImage, kernelVersion, crVersion)
}
return []metav1beta1.TableRow{row}, nil
@ -1155,6 +1165,17 @@ func getNodeExternalIP(node *api.Node) string {
return "<none>"
}
// Returns the internal IP of the node or "<none>" if none is found.
func getNodeInternalIP(node *api.Node) string {
for _, address := range node.Status.Addresses {
if address.Type == api.NodeInternalIP {
return address.Address
}
}
return "<none>"
}
// findNodeRoles returns the roles of a given node.
// The roles are determined by looking for:
// * a node-role.kubernetes.io/<role>="" label
@ -1211,7 +1232,7 @@ func printPersistentVolume(obj *api.PersistentVolume, options printers.PrintOpti
}
row.Cells = append(row.Cells, obj.Name, aSize, modesStr, reclaimPolicyStr,
phase, claimRefUID, helper.GetPersistentVolumeClass(obj),
string(phase), claimRefUID, helper.GetPersistentVolumeClass(obj),
obj.Status.Reason,
translateTimestamp(obj.CreationTimestamp))
return []metav1beta1.TableRow{row}, nil
@ -1248,7 +1269,7 @@ func printPersistentVolumeClaim(obj *api.PersistentVolumeClaim, options printers
capacity = storage.String()
}
row.Cells = append(row.Cells, obj.Name, 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), translateTimestamp(obj.CreationTimestamp))
return []metav1beta1.TableRow{row}, nil
}
@ -1278,7 +1299,7 @@ func printEvent(obj *api.Event, options printers.PrintOptions) ([]metav1beta1.Ta
LastTimestamp = translateTimestamp(obj.LastTimestamp)
}
row.Cells = append(row.Cells, LastTimestamp, FirstTimestamp,
obj.Count, obj.Name, obj.InvolvedObject.Kind,
int64(obj.Count), obj.Name, obj.InvolvedObject.Kind,
obj.InvolvedObject.FieldPath, obj.Type, obj.Reason,
formatEventSource(obj.Source), obj.Message)
@ -1461,7 +1482,7 @@ func printDeployment(obj *extensions.Deployment, options printers.PrintOptions)
// this shouldn't happen if LabelSelector passed validation
return nil, err
}
row.Cells = append(row.Cells, obj.Name, desiredReplicas, currentReplicas, updatedReplicas, availableReplicas, age)
row.Cells = append(row.Cells, obj.Name, int64(desiredReplicas), int64(currentReplicas), int64(updatedReplicas), int64(availableReplicas), age)
if options.Wide {
containers, images := layoutContainerCells(containers)
row.Cells = append(row.Cells, containers, images, selector.String())
@ -1570,7 +1591,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, maxPods, currentReplicas, translateTimestamp(obj.CreationTimestamp))
row.Cells = append(row.Cells, obj.Name, reference, metrics, minPods, int64(maxPods), int64(currentReplicas), translateTimestamp(obj.CreationTimestamp))
return []metav1beta1.TableRow{row}, nil
}
@ -1590,7 +1611,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, len(obj.Data), translateTimestamp(obj.CreationTimestamp))
row.Cells = append(row.Cells, obj.Name, int64(len(obj.Data)), translateTimestamp(obj.CreationTimestamp))
return []metav1beta1.TableRow{row}, nil
}
@ -1606,17 +1627,28 @@ func printConfigMapList(list *api.ConfigMapList, options printers.PrintOptions)
return rows, nil
}
func printPodSecurityPolicy(obj *extensions.PodSecurityPolicy, options printers.PrintOptions) ([]metav1beta1.TableRow, error) {
func printPodSecurityPolicy(obj *policy.PodSecurityPolicy, options printers.PrintOptions) ([]metav1beta1.TableRow, error) {
row := metav1beta1.TableRow{
Object: runtime.RawExtension{Object: obj},
}
row.Cells = append(row.Cells, obj.Name, obj.Spec.Privileged,
obj.Spec.AllowedCapabilities, obj.Spec.SELinux.Rule,
obj.Spec.RunAsUser.Rule, obj.Spec.FSGroup.Rule, obj.Spec.SupplementalGroups.Rule, obj.Spec.ReadOnlyRootFilesystem, obj.Spec.Volumes)
capabilities := make([]string, len(obj.Spec.AllowedCapabilities))
for i, c := range obj.Spec.AllowedCapabilities {
capabilities[i] = string(c)
}
volumes := make([]string, len(obj.Spec.Volumes))
for i, v := range obj.Spec.Volumes {
volumes[i] = string(v)
}
row.Cells = append(row.Cells, obj.Name, fmt.Sprintf("%v", obj.Spec.Privileged),
strings.Join(capabilities, ","), string(obj.Spec.SELinux.Rule),
string(obj.Spec.RunAsUser.Rule), string(obj.Spec.FSGroup.Rule),
string(obj.Spec.SupplementalGroups.Rule), obj.Spec.ReadOnlyRootFilesystem,
strings.Join(volumes, ","))
return []metav1beta1.TableRow{row}, nil
}
func printPodSecurityPolicyList(list *extensions.PodSecurityPolicyList, options printers.PrintOptions) ([]metav1beta1.TableRow, error) {
func printPodSecurityPolicyList(list *policy.PodSecurityPolicyList, options printers.PrintOptions) ([]metav1beta1.TableRow, error) {
rows := make([]metav1beta1.TableRow, 0, len(list.Items))
for i := range list.Items {
r, err := printPodSecurityPolicy(&list.Items[i], options)
@ -1736,7 +1768,12 @@ func printControllerRevision(obj *apps.ControllerRevision, options printers.Prin
controllerName := "<none>"
if controllerRef != nil {
withKind := true
controllerName = printers.FormatResourceName(controllerRef.Kind, controllerRef.Name, withKind)
gv, err := schema.ParseGroupVersion(controllerRef.APIVersion)
if err != nil {
return nil, err
}
gvk := gv.WithKind(controllerRef.Kind)
controllerName = printers.FormatResourceName(gvk.GroupKind(), controllerRef.Name, withKind)
}
revision := obj.Revision
age := translateTimestamp(obj.CreationTimestamp)

File diff suppressed because it is too large Load Diff