Update godeps

This commit is contained in:
Manuel de Brito Fontes 2016-11-10 19:57:28 -03:00
parent 1c8773fc98
commit 1bc383f9c5
1723 changed files with 287976 additions and 411028 deletions

View file

@ -30,10 +30,9 @@ import (
"text/template"
"time"
"github.com/ghodss/yaml"
"github.com/golang/glog"
"k8s.io/kubernetes/federation/apis/federation"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/events"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/apps"
@ -43,11 +42,16 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/rbac"
"k8s.io/kubernetes/pkg/apis/storage"
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/jsonpath"
"k8s.io/kubernetes/pkg/util/node"
"k8s.io/kubernetes/pkg/util/sets"
"github.com/ghodss/yaml"
"github.com/golang/glog"
)
const (
@ -150,7 +154,7 @@ type ResourcePrinter interface {
HandledResources() []string
//Can be used to print out warning/clarifications if needed
//after all objects were printed
FinishPrint(io.Writer, string) error
AfterPrint(io.Writer, string) error
}
// ResourcePrinterFunc is a function that can print objects
@ -166,7 +170,7 @@ func (fn ResourcePrinterFunc) HandledResources() []string {
return []string{}
}
func (fn ResourcePrinterFunc) FinishPrint(io.Writer, string) error {
func (fn ResourcePrinterFunc) AfterPrint(io.Writer, string) error {
return nil
}
@ -187,7 +191,7 @@ func NewVersionedPrinter(printer ResourcePrinter, converter runtime.ObjectConver
}
}
func (p *VersionedPrinter) FinishPrint(w io.Writer, res string) error {
func (p *VersionedPrinter) AfterPrint(w io.Writer, res string) error {
return nil
}
@ -214,7 +218,7 @@ type NamePrinter struct {
Typer runtime.ObjectTyper
}
func (p *NamePrinter) FinishPrint(w io.Writer, res string) error {
func (p *NamePrinter) AfterPrint(w io.Writer, res string) error {
return nil
}
@ -237,8 +241,6 @@ func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
return nil
}
// TODO: this is wrong, runtime.Unknown and runtime.Unstructured are not handled properly here.
name := "<unknown>"
if acc, err := meta.Accessor(obj); err == nil {
if n := acc.GetName(); len(n) > 0 {
@ -246,12 +248,22 @@ func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
}
}
if gvks, _, err := p.Typer.ObjectKinds(obj); err == nil {
// TODO: this is wrong, it assumes that meta knows about all Kinds - should take a RESTMapper
_, resource := meta.KindToResource(gvks[0])
fmt.Fprintf(w, "%s/%s\n", resource.Resource, name)
if kind := obj.GetObjectKind().GroupVersionKind(); len(kind.Kind) == 0 {
// this is the old code. It's unnecessary on decoded external objects, but on internal objects
// you may have to do it. Tests are definitely calling it with internals and I'm not sure who else
// is
if gvks, _, err := p.Typer.ObjectKinds(obj); err == nil {
// TODO: this is wrong, it assumes that meta knows about all Kinds - should take a RESTMapper
_, resource := meta.KindToResource(gvks[0])
fmt.Fprintf(w, "%s/%s\n", resource.Resource, name)
} else {
fmt.Fprintf(w, "<unknown>/%s\n", name)
}
} else {
fmt.Fprintf(w, "<unknown>/%s\n", name)
// TODO: this is wrong, it assumes that meta knows about all Kinds - should take a RESTMapper
_, resource := meta.KindToResource(kind)
fmt.Fprintf(w, "%s/%s\n", resource.Resource, name)
}
return nil
@ -266,7 +278,7 @@ func (p *NamePrinter) HandledResources() []string {
type JSONPrinter struct {
}
func (p *JSONPrinter) FinishPrint(w io.Writer, res string) error {
func (p *JSONPrinter) AfterPrint(w io.Writer, res string) error {
return nil
}
@ -274,7 +286,13 @@ func (p *JSONPrinter) FinishPrint(w io.Writer, res string) error {
func (p *JSONPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
switch obj := obj.(type) {
case *runtime.Unknown:
_, err := w.Write(obj.Raw)
var buf bytes.Buffer
err := json.Indent(&buf, obj.Raw, "", " ")
if err != nil {
return err
}
buf.WriteRune('\n')
_, err = buf.WriteTo(w)
return err
}
@ -300,7 +318,7 @@ type YAMLPrinter struct {
converter runtime.ObjectConvertor
}
func (p *YAMLPrinter) FinishPrint(w io.Writer, res string) error {
func (p *YAMLPrinter) AfterPrint(w io.Writer, res string) error {
return nil
}
@ -447,62 +465,55 @@ func (h *HumanReadablePrinter) HandledResources() []string {
return keys
}
func (h *HumanReadablePrinter) FinishPrint(output io.Writer, res string) error {
if !h.options.NoHeaders && !h.options.ShowAll && h.hiddenObjNum > 0 {
_, err := fmt.Fprintf(output, " info: %d completed object(s) was(were) not shown in %s list. Pass --show-all to see all objects.\n\n", h.hiddenObjNum, res)
return err
}
func (h *HumanReadablePrinter) AfterPrint(output io.Writer, res string) error {
return nil
}
// NOTE: When adding a new resource type here, please update the list
// pkg/kubectl/cmd/get.go to reflect the new resource type.
var podColumns = []string{"NAME", "READY", "STATUS", "RESTARTS", "AGE"}
var podTemplateColumns = []string{"TEMPLATE", "CONTAINER(S)", "IMAGE(S)", "PODLABELS"}
var replicationControllerColumns = []string{"NAME", "DESIRED", "CURRENT", "READY", "AGE"}
var replicaSetColumns = []string{"NAME", "DESIRED", "CURRENT", "READY", "AGE"}
var jobColumns = []string{"NAME", "DESIRED", "SUCCESSFUL", "AGE"}
var scheduledJobColumns = []string{"NAME", "SCHEDULE", "SUSPEND", "ACTIVE", "LAST-SCHEDULE"}
var serviceColumns = []string{"NAME", "CLUSTER-IP", "EXTERNAL-IP", "PORT(S)", "AGE"}
var ingressColumns = []string{"NAME", "HOSTS", "ADDRESS", "PORTS", "AGE"}
var petSetColumns = []string{"NAME", "DESIRED", "CURRENT", "AGE"}
var endpointColumns = []string{"NAME", "ENDPOINTS", "AGE"}
var nodeColumns = []string{"NAME", "STATUS", "AGE"}
var daemonSetColumns = []string{"NAME", "DESIRED", "CURRENT", "NODE-SELECTOR", "AGE"}
var eventColumns = []string{"LASTSEEN", "FIRSTSEEN", "COUNT", "NAME", "KIND", "SUBOBJECT", "TYPE", "REASON", "SOURCE", "MESSAGE"}
var limitRangeColumns = []string{"NAME", "AGE"}
var resourceQuotaColumns = []string{"NAME", "AGE"}
var namespaceColumns = []string{"NAME", "STATUS", "AGE"}
var secretColumns = []string{"NAME", "TYPE", "DATA", "AGE"}
var serviceAccountColumns = []string{"NAME", "SECRETS", "AGE"}
var persistentVolumeColumns = []string{"NAME", "CAPACITY", "ACCESSMODES", "RECLAIMPOLICY", "STATUS", "CLAIM", "REASON", "AGE"}
var persistentVolumeClaimColumns = []string{"NAME", "STATUS", "VOLUME", "CAPACITY", "ACCESSMODES", "AGE"}
var componentStatusColumns = []string{"NAME", "STATUS", "MESSAGE", "ERROR"}
var thirdPartyResourceColumns = []string{"NAME", "DESCRIPTION", "VERSION(S)"}
var roleColumns = []string{"NAME", "AGE"}
var roleBindingColumns = []string{"NAME", "AGE"}
var clusterRoleColumns = []string{"NAME", "AGE"}
var clusterRoleBindingColumns = []string{"NAME", "AGE"}
var storageClassColumns = []string{"NAME", "TYPE"}
var (
podColumns = []string{"NAME", "READY", "STATUS", "RESTARTS", "AGE"}
podTemplateColumns = []string{"TEMPLATE", "CONTAINER(S)", "IMAGE(S)", "PODLABELS"}
replicationControllerColumns = []string{"NAME", "DESIRED", "CURRENT", "READY", "AGE"}
replicaSetColumns = []string{"NAME", "DESIRED", "CURRENT", "READY", "AGE"}
jobColumns = []string{"NAME", "DESIRED", "SUCCESSFUL", "AGE"}
cronJobColumns = []string{"NAME", "SCHEDULE", "SUSPEND", "ACTIVE", "LAST-SCHEDULE"}
serviceColumns = []string{"NAME", "CLUSTER-IP", "EXTERNAL-IP", "PORT(S)", "AGE"}
ingressColumns = []string{"NAME", "HOSTS", "ADDRESS", "PORTS", "AGE"}
statefulSetColumns = []string{"NAME", "DESIRED", "CURRENT", "AGE"}
endpointColumns = []string{"NAME", "ENDPOINTS", "AGE"}
nodeColumns = []string{"NAME", "STATUS", "AGE"}
daemonSetColumns = []string{"NAME", "DESIRED", "CURRENT", "READY", "NODE-SELECTOR", "AGE"}
eventColumns = []string{"LASTSEEN", "FIRSTSEEN", "COUNT", "NAME", "KIND", "SUBOBJECT", "TYPE", "REASON", "SOURCE", "MESSAGE"}
limitRangeColumns = []string{"NAME", "AGE"}
resourceQuotaColumns = []string{"NAME", "AGE"}
namespaceColumns = []string{"NAME", "STATUS", "AGE"}
secretColumns = []string{"NAME", "TYPE", "DATA", "AGE"}
serviceAccountColumns = []string{"NAME", "SECRETS", "AGE"}
persistentVolumeColumns = []string{"NAME", "CAPACITY", "ACCESSMODES", "RECLAIMPOLICY", "STATUS", "CLAIM", "REASON", "AGE"}
persistentVolumeClaimColumns = []string{"NAME", "STATUS", "VOLUME", "CAPACITY", "ACCESSMODES", "AGE"}
componentStatusColumns = []string{"NAME", "STATUS", "MESSAGE", "ERROR"}
thirdPartyResourceColumns = []string{"NAME", "DESCRIPTION", "VERSION(S)"}
roleColumns = []string{"NAME", "AGE"}
roleBindingColumns = []string{"NAME", "AGE"}
clusterRoleColumns = []string{"NAME", "AGE"}
clusterRoleBindingColumns = []string{"NAME", "AGE"}
storageClassColumns = []string{"NAME", "TYPE"}
statusColumns = []string{"STATUS", "REASON", "MESSAGE"}
// TODO: consider having 'KIND' for third party resource data
var thirdPartyResourceDataColumns = []string{"NAME", "LABELS", "DATA"}
var horizontalPodAutoscalerColumns = []string{"NAME", "REFERENCE", "TARGET", "CURRENT", "MINPODS", "MAXPODS", "AGE"}
var withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print cluster name too.
var deploymentColumns = []string{"NAME", "DESIRED", "CURRENT", "UP-TO-DATE", "AVAILABLE", "AGE"}
var configMapColumns = []string{"NAME", "DATA", "AGE"}
var podSecurityPolicyColumns = []string{"NAME", "PRIV", "CAPS", "VOLUMEPLUGINS", "SELINUX", "RUNASUSER"}
var clusterColumns = []string{"NAME", "STATUS", "AGE"}
var networkPolicyColumns = []string{"NAME", "POD-SELECTOR", "AGE"}
var certificateSigningRequestColumns = []string{"NAME", "AGE", "REQUESTOR", "CONDITION"}
// TODO: consider having 'KIND' for third party resource data
thirdPartyResourceDataColumns = []string{"NAME", "LABELS", "DATA"}
horizontalPodAutoscalerColumns = []string{"NAME", "REFERENCE", "TARGET", "CURRENT", "MINPODS", "MAXPODS", "AGE"}
withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print cluster name too.
deploymentColumns = []string{"NAME", "DESIRED", "CURRENT", "UP-TO-DATE", "AVAILABLE", "AGE"}
configMapColumns = []string{"NAME", "DATA", "AGE"}
podSecurityPolicyColumns = []string{"NAME", "PRIV", "CAPS", "VOLUMEPLUGINS", "SELINUX", "RUNASUSER"}
clusterColumns = []string{"NAME", "STATUS", "AGE"}
networkPolicyColumns = []string{"NAME", "POD-SELECTOR", "AGE"}
certificateSigningRequestColumns = []string{"NAME", "AGE", "REQUESTOR", "CONDITION"}
)
func (h *HumanReadablePrinter) printPod(pod *api.Pod, w io.Writer, options PrintOptions) error {
reason := string(pod.Status.Phase)
// if not printing all pods, skip terminated pods (default)
if !options.ShowAll && (reason == string(api.PodSucceeded) || reason == string(api.PodFailed)) {
h.hiddenObjNum++
return nil
}
if err := printPodBase(pod, w, options); err != nil {
return err
}
@ -512,13 +523,6 @@ func (h *HumanReadablePrinter) printPod(pod *api.Pod, w io.Writer, options Print
func (h *HumanReadablePrinter) printPodList(podList *api.PodList, w io.Writer, options PrintOptions) error {
for _, pod := range podList.Items {
reason := string(pod.Status.Phase)
// if not printing all pods, skip terminated pods (default)
if !options.ShowAll && (reason == string(api.PodSucceeded) || reason == string(api.PodFailed)) {
h.hiddenObjNum++
continue
}
if err := printPodBase(&pod, w, options); err != nil {
return err
}
@ -540,14 +544,14 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
h.Handler(daemonSetColumns, printDaemonSetList)
h.Handler(jobColumns, printJob)
h.Handler(jobColumns, printJobList)
h.Handler(scheduledJobColumns, printScheduledJob)
h.Handler(scheduledJobColumns, printScheduledJobList)
h.Handler(cronJobColumns, printCronJob)
h.Handler(cronJobColumns, printCronJobList)
h.Handler(serviceColumns, printService)
h.Handler(serviceColumns, printServiceList)
h.Handler(ingressColumns, printIngress)
h.Handler(ingressColumns, printIngressList)
h.Handler(petSetColumns, printPetSet)
h.Handler(petSetColumns, printPetSetList)
h.Handler(statefulSetColumns, printStatefulSet)
h.Handler(statefulSetColumns, printStatefulSetList)
h.Handler(endpointColumns, printEndpoints)
h.Handler(endpointColumns, printEndpointsList)
h.Handler(nodeColumns, printNode)
@ -598,6 +602,7 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
h.Handler(certificateSigningRequestColumns, printCertificateSigningRequestList)
h.Handler(storageClassColumns, printStorageClass)
h.Handler(storageClassColumns, printStorageClassList)
h.Handler(statusColumns, printStatus)
}
func (h *HumanReadablePrinter) unknown(data []byte, w io.Writer) error {
@ -736,7 +741,10 @@ func printPodBase(pod *api.Pod, w io.Writer, options PrintOptions) error {
}
}
}
if pod.DeletionTimestamp != nil {
if pod.DeletionTimestamp != nil && pod.Status.Reason == node.NodeUnreachablePodReason {
reason = "Unknown"
} else if pod.DeletionTimestamp != nil {
reason = "Terminating"
}
@ -1020,9 +1028,9 @@ func printJobList(list *batch.JobList, w io.Writer, options PrintOptions) error
return nil
}
func printScheduledJob(scheduledJob *batch.ScheduledJob, w io.Writer, options PrintOptions) error {
name := scheduledJob.Name
namespace := scheduledJob.Namespace
func printCronJob(cronJob *batch.CronJob, w io.Writer, options PrintOptions) error {
name := cronJob.Name
namespace := cronJob.Namespace
if options.WithNamespace {
if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil {
@ -1031,14 +1039,14 @@ func printScheduledJob(scheduledJob *batch.ScheduledJob, w io.Writer, options Pr
}
lastScheduleTime := "<none>"
if scheduledJob.Status.LastScheduleTime != nil {
lastScheduleTime = scheduledJob.Status.LastScheduleTime.Time.Format(time.RFC1123Z)
if cronJob.Status.LastScheduleTime != nil {
lastScheduleTime = cronJob.Status.LastScheduleTime.Time.Format(time.RFC1123Z)
}
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%d\t%s\n",
name,
scheduledJob.Spec.Schedule,
printBoolPtr(scheduledJob.Spec.Suspend),
len(scheduledJob.Status.Active),
cronJob.Spec.Schedule,
printBoolPtr(cronJob.Spec.Suspend),
len(cronJob.Status.Active),
lastScheduleTime,
); err != nil {
return err
@ -1047,9 +1055,9 @@ func printScheduledJob(scheduledJob *batch.ScheduledJob, w io.Writer, options Pr
return nil
}
func printScheduledJobList(list *batch.ScheduledJobList, w io.Writer, options PrintOptions) error {
for _, scheduledJob := range list.Items {
if err := printScheduledJob(&scheduledJob, w, options); err != nil {
func printCronJobList(list *batch.CronJobList, w io.Writer, options PrintOptions) error {
for _, cronJob := range list.Items {
if err := printCronJob(&cronJob, w, options); err != nil {
return err
}
}
@ -1108,6 +1116,9 @@ func makePortString(ports []api.ServicePort) string {
for ix := range ports {
port := &ports[ix]
pieces[ix] = fmt.Sprintf("%d/%s", port.Port, port.Protocol)
if port.NodePort > 0 {
pieces[ix] = fmt.Sprintf("%d:%d/%s", port.Port, port.NodePort, port.Protocol)
}
}
return strings.Join(pieces, ",")
}
@ -1231,7 +1242,7 @@ func printIngressList(ingressList *extensions.IngressList, w io.Writer, options
return nil
}
func printPetSet(ps *apps.PetSet, w io.Writer, options PrintOptions) error {
func printStatefulSet(ps *apps.StatefulSet, w io.Writer, options PrintOptions) error {
name := formatResourceName(options.Kind, ps.Name, options.WithKind)
namespace := ps.Namespace
@ -1270,9 +1281,9 @@ func printPetSet(ps *apps.PetSet, w io.Writer, options PrintOptions) error {
return nil
}
func printPetSetList(petSetList *apps.PetSetList, w io.Writer, options PrintOptions) error {
for _, ps := range petSetList.Items {
if err := printPetSet(&ps, w, options); err != nil {
func printStatefulSetList(statefulSetList *apps.StatefulSetList, w io.Writer, options PrintOptions) error {
for _, ps := range statefulSetList.Items {
if err := printStatefulSet(&ps, w, options); err != nil {
return err
}
}
@ -1294,15 +1305,17 @@ func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, options PrintOptions)
desiredScheduled := ds.Status.DesiredNumberScheduled
currentScheduled := ds.Status.CurrentNumberScheduled
numberReady := ds.Status.NumberReady
selector, err := unversioned.LabelSelectorAsSelector(ds.Spec.Selector)
if err != nil {
// this shouldn't happen if LabelSelector passed validation
return err
}
if _, err := fmt.Fprintf(w, "%s\t%d\t%d\t%s\t%s",
if _, err := fmt.Fprintf(w, "%s\t%d\t%d\t%d\t%s\t%s",
name,
desiredScheduled,
currentScheduled,
numberReady,
labels.FormatLabels(ds.Spec.Template.Spec.NodeSelector),
translateTimestamp(ds.CreationTimestamp),
); err != nil {
@ -1482,6 +1495,12 @@ func printNode(node *api.Node, w io.Writer, options PrintOptions) error {
if _, err := fmt.Fprintf(w, "%s\t%s\t%s", name, strings.Join(status, ","), translateTimestamp(node.CreationTimestamp)); err != nil {
return err
}
if options.Wide {
if _, err := fmt.Fprintf(w, "\t%s", getNodeExternalIP(node)); err != nil {
return err
}
}
// Display caller specify column labels first.
if _, err := fmt.Fprint(w, AppendLabels(node.Labels, options.ColumnLabels)); err != nil {
return err
@ -1490,6 +1509,17 @@ func printNode(node *api.Node, w io.Writer, options PrintOptions) error {
return err
}
// Returns first external ip of the node or "<none>" if none is found.
func getNodeExternalIP(node *api.Node) string {
for _, address := range node.Status.Addresses {
if address.Type == api.NodeExternalIP {
return address.Address
}
}
return "<none>"
}
func printNodeList(list *api.NodeList, w io.Writer, options PrintOptions) error {
for _, node := range list.Items {
if err := printNode(&node, w, options); err != nil {
@ -1629,7 +1659,7 @@ func printEvent(event *api.Event, w io.Writer, options PrintOptions) error {
// Sorts and prints the EventList in a human-friendly format.
func printEventList(list *api.EventList, w io.Writer, options PrintOptions) error {
sort.Sort(SortableEvents(list.Items))
sort.Sort(events.SortableEvents(list.Items))
for i := range list.Items {
if err := printEvent(&list.Items[i], w, options); err != nil {
return err
@ -2071,6 +2101,10 @@ func printNetworkPolicyList(list *extensions.NetworkPolicyList, w io.Writer, opt
func printStorageClass(sc *storage.StorageClass, w io.Writer, options PrintOptions) error {
name := sc.Name
if storageutil.IsDefaultAnnotation(sc.ObjectMeta) {
name += " (default)"
}
provtype := sc.Provisioner
if _, err := fmt.Fprintf(w, "%s\t%s\t", name, provtype); err != nil {
@ -2095,6 +2129,14 @@ func printStorageClassList(scList *storage.StorageClassList, w io.Writer, option
return nil
}
func printStatus(status *unversioned.Status, w io.Writer, options PrintOptions) error {
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", status.Status, status.Reason, status.Message); err != nil {
return err
}
return nil
}
func AppendLabels(itemLabels map[string]string, columnLabels []string) string {
var buffer bytes.Buffer
@ -2187,6 +2229,9 @@ func formatWideHeaders(wide bool, t reflect.Type) []string {
if t.String() == "*extensions.ReplicaSet" || t.String() == "*extensions.ReplicaSetList" {
return []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"}
}
if t.String() == "*api.Node" || t.String() == "*api.NodeList" {
return []string{"EXTERNAL-IP"}
}
}
return nil
}
@ -2214,6 +2259,18 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
w = GetNewTabWriter(output)
defer w.Flush()
}
// check if the object is unstructured. If so, let's attempt to convert it to a type we can understand before
// trying to print, since the printers are keyed by type. This is extremely expensive.
switch obj.(type) {
case *runtime.Unstructured, *runtime.Unknown:
if objBytes, err := runtime.Encode(api.Codecs.LegacyCodec(), obj); err == nil {
if decodedObj, err := runtime.Decode(api.Codecs.UniversalDecoder(), objBytes); err == nil {
obj = decodedObj
}
}
}
t := reflect.TypeOf(obj)
if handler := h.handlerMap[t]; handler != nil {
if !h.options.NoHeaders && t != h.lastType {
@ -2234,9 +2291,78 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
}
return resultValue.Interface().(error)
}
// we don't recognize this type, but we can still attempt to print some reasonable information about.
unstructured, ok := obj.(*runtime.Unstructured)
if !ok {
return fmt.Errorf("error: unknown type %#v", obj)
}
if _, err := meta.Accessor(obj); err == nil {
if !h.options.NoHeaders && t != h.lastType {
headers := []string{"NAME", "KIND"}
headers = append(headers, formatLabelHeaders(h.options.ColumnLabels)...)
// LABELS is always the last column.
headers = append(headers, formatShowLabelsHeader(h.options.ShowLabels, t)...)
if h.options.WithNamespace {
headers = append(withNamespacePrefixColumns, headers...)
}
h.printHeader(headers, w)
h.lastType = t
}
// if the error isn't nil, report the "I don't recognize this" error
if err := printUnstructured(unstructured, w, h.options); err != nil {
return err
}
return nil
}
// we failed all reasonable printing efforts, report failure
return fmt.Errorf("error: unknown type %#v", obj)
}
func printUnstructured(unstructured *runtime.Unstructured, w io.Writer, options PrintOptions) error {
metadata, err := meta.Accessor(unstructured)
if err != nil {
return err
}
if options.WithNamespace {
if _, err := fmt.Fprintf(w, "%s\t", metadata.GetNamespace()); err != nil {
return err
}
}
kind := "<missing>"
if objKind, ok := unstructured.Object["kind"]; ok {
if str, ok := objKind.(string); ok {
kind = str
}
}
if objAPIVersion, ok := unstructured.Object["apiVersion"]; ok {
if str, ok := objAPIVersion.(string); ok {
version, err := unversioned.ParseGroupVersion(str)
if err != nil {
return err
}
kind = kind + "." + version.Version + "." + version.Group
}
}
name := formatResourceName(options.Kind, metadata.GetName(), options.WithKind)
if _, err := fmt.Fprintf(w, "%s\t%s", name, kind); err != nil {
return err
}
if _, err := fmt.Fprint(w, AppendLabels(metadata.GetLabels(), options.ColumnLabels)); err != nil {
return err
}
if _, err := fmt.Fprint(w, AppendAllLabels(options.ShowLabels, metadata.GetLabels())); err != nil {
return err
}
return nil
}
// TemplatePrinter is an implementation of ResourcePrinter which formats data with a Go Template.
type TemplatePrinter struct {
rawTemplate string
@ -2256,16 +2382,24 @@ func NewTemplatePrinter(tmpl []byte) (*TemplatePrinter, error) {
}, nil
}
func (p *TemplatePrinter) FinishPrint(w io.Writer, res string) error {
func (p *TemplatePrinter) AfterPrint(w io.Writer, res string) error {
return nil
}
// PrintObj formats the obj with the Go Template.
func (p *TemplatePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
data, err := json.Marshal(obj)
var data []byte
var err error
if unstructured, ok := obj.(*runtime.Unstructured); ok {
data, err = json.Marshal(unstructured.Object)
} else {
data, err = json.Marshal(obj)
}
if err != nil {
return err
}
out := map[string]interface{}{}
if err := json.Unmarshal(data, &out); err != nil {
return err
@ -2407,7 +2541,7 @@ func NewJSONPathPrinter(tmpl string) (*JSONPathPrinter, error) {
return &JSONPathPrinter{tmpl, j}, nil
}
func (j *JSONPathPrinter) FinishPrint(w io.Writer, res string) error {
func (j *JSONPathPrinter) AfterPrint(w io.Writer, res string) error {
return nil
}
@ -2425,6 +2559,20 @@ func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error {
}
}
if unknown, ok := obj.(*runtime.Unknown); ok {
data, err := json.Marshal(unknown)
if err != nil {
return err
}
queryObj = map[string]interface{}{}
if err := json.Unmarshal(data, &queryObj); err != nil {
return err
}
}
if unstructured, ok := obj.(*runtime.Unstructured); ok {
queryObj = unstructured.Object
}
if err := j.JSONPath.Execute(w, queryObj); err != nil {
fmt.Fprintf(w, "Error executing template: %v. Printing more information for debugging the template:\n", err)
fmt.Fprintf(w, "\ttemplate was:\n\t\t%v\n", j.rawTemplate)