Refactor printers to separate typed printers from generic code

This commit is contained in:
Clayton Coleman 2017-02-19 17:37:24 -05:00
parent 6d1c7308a5
commit 3704ceffd2
No known key found for this signature in database
GPG Key ID: 3D16906B4F1C5CB3
16 changed files with 729 additions and 529 deletions

View File

@ -13,7 +13,7 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/printers:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/runtime", "//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema", "//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/util/validation/field", "//vendor:k8s.io/apimachinery/pkg/util/validation/field",

View File

@ -30,7 +30,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/printers"
) )
// Based on: https://github.com/openshift/origin/blob/master/pkg/api/compatibility_test.go // Based on: https://github.com/openshift/origin/blob/master/pkg/api/compatibility_test.go
@ -94,7 +94,7 @@ func TestCompatibility(
} }
if hasError { if hasError {
printer := new(kubectl.JSONPrinter) printer := &printers.JSONPrinter{}
printer.PrintObj(obj, os.Stdout) printer.PrintObj(obj, os.Stdout)
t.Logf("2: Encoded value: %#v", string(output)) t.Logf("2: Encoded value: %#v", string(output))
} }

View File

@ -63,6 +63,7 @@ go_test(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/api:go_default_library", "//pkg/api:go_default_library",
"//pkg/api/install:go_default_library",
"//pkg/api/testing/compat:go_default_library", "//pkg/api/testing/compat:go_default_library",
"//pkg/api/v1:go_default_library", "//pkg/api/v1:go_default_library",
"//pkg/api/validation:go_default_library", "//pkg/api/validation:go_default_library",

View File

@ -25,6 +25,8 @@ import (
"k8s.io/kubernetes/pkg/api/testing/compat" "k8s.io/kubernetes/pkg/api/testing/compat"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/api/validation" "k8s.io/kubernetes/pkg/api/validation"
_ "k8s.io/kubernetes/pkg/api/install"
) )
func TestCompatibility_v1_PodSecurityContext(t *testing.T) { func TestCompatibility_v1_PodSecurityContext(t *testing.T) {

41
pkg/printers/common.go Normal file
View File

@ -0,0 +1,41 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package printers
import (
"fmt"
"time"
)
func ShortHumanDuration(d time.Duration) string {
// Allow deviation no more than 2 seconds(excluded) to tolerate machine time
// inconsistence, it can be considered as almost now.
if seconds := int(d.Seconds()); seconds < -1 {
return fmt.Sprintf("<invalid>")
} else if seconds < 0 {
return fmt.Sprintf("0s")
} else if seconds < 60 {
return fmt.Sprintf("%ds", seconds)
} else if minutes := int(d.Minutes()); minutes < 60 {
return fmt.Sprintf("%dm", minutes)
} else if hours := int(d.Hours()); hours < 24 {
return fmt.Sprintf("%dh", hours)
} else if hours < 24*364 {
return fmt.Sprintf("%dd", hours/24)
}
return fmt.Sprintf("%dy", int(d.Hours()/24/365))
}

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package kubectl package printers
import ( import (
"bufio" "bufio"
@ -41,14 +41,14 @@ const (
var jsonRegexp = regexp.MustCompile("^\\{\\.?([^{}]+)\\}$|^\\.?([^{}]+)$") var jsonRegexp = regexp.MustCompile("^\\{\\.?([^{}]+)\\}$|^\\.?([^{}]+)$")
// MassageJSONPath attempts to be flexible with JSONPath expressions, it accepts: // RelaxedJSONPathExpression attempts to be flexible with JSONPath expressions, it accepts:
// * metadata.name (no leading '.' or curly brances '{...}' // * metadata.name (no leading '.' or curly brances '{...}'
// * {metadata.name} (no leading '.') // * {metadata.name} (no leading '.')
// * .metadata.name (no curly braces '{...}') // * .metadata.name (no curly braces '{...}')
// * {.metadata.name} (complete expression) // * {.metadata.name} (complete expression)
// And transforms them all into a valid jsonpat expression: // And transforms them all into a valid jsonpath expression:
// {.metadata.name} // {.metadata.name}
func massageJSONPath(pathExpression string) (string, error) { func RelaxedJSONPathExpression(pathExpression string) (string, error) {
if len(pathExpression) == 0 { if len(pathExpression) == 0 {
return pathExpression, nil return pathExpression, nil
} }
@ -84,7 +84,7 @@ func NewCustomColumnsPrinterFromSpec(spec string, decoder runtime.Decoder, noHea
if len(colSpec) != 2 { if len(colSpec) != 2 {
return nil, fmt.Errorf("unexpected custom-columns spec: %s, expected <header>:<json-path-expr>", parts[ix]) return nil, fmt.Errorf("unexpected custom-columns spec: %s, expected <header>:<json-path-expr>", parts[ix])
} }
spec, err := massageJSONPath(colSpec[1]) spec, err := RelaxedJSONPathExpression(colSpec[1])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -126,7 +126,7 @@ func NewCustomColumnsPrinterFromTemplate(templateReader io.Reader, decoder runti
columns := make([]Column, len(headers)) columns := make([]Column, len(headers))
for ix := range headers { for ix := range headers {
spec, err := massageJSONPath(specs[ix]) spec, err := RelaxedJSONPathExpression(specs[ix])
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package kubectl package printers_test
import ( import (
"bytes" "bytes"
@ -26,6 +26,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/printers"
) )
func TestMassageJSONPath(t *testing.T) { func TestMassageJSONPath(t *testing.T) {
@ -45,7 +46,7 @@ func TestMassageJSONPath(t *testing.T) {
{input: "{{foo.bar}", expectErr: true}, {input: "{{foo.bar}", expectErr: true},
} }
for _, test := range tests { for _, test := range tests {
output, err := massageJSONPath(test.input) output, err := printers.RelaxedJSONPathExpression(test.input)
if err != nil && !test.expectErr { if err != nil && !test.expectErr {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
continue continue
@ -65,7 +66,7 @@ func TestMassageJSONPath(t *testing.T) {
func TestNewColumnPrinterFromSpec(t *testing.T) { func TestNewColumnPrinterFromSpec(t *testing.T) {
tests := []struct { tests := []struct {
spec string spec string
expectedColumns []Column expectedColumns []printers.Column
expectErr bool expectErr bool
name string name string
noHeaders bool noHeaders bool
@ -93,7 +94,7 @@ func TestNewColumnPrinterFromSpec(t *testing.T) {
{ {
spec: "NAME:metadata.name,API_VERSION:apiVersion", spec: "NAME:metadata.name,API_VERSION:apiVersion",
name: "ok", name: "ok",
expectedColumns: []Column{ expectedColumns: []printers.Column{
{ {
Header: "NAME", Header: "NAME",
FieldSpec: "{.metadata.name}", FieldSpec: "{.metadata.name}",
@ -111,7 +112,7 @@ func TestNewColumnPrinterFromSpec(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
printer, err := NewCustomColumnsPrinterFromSpec(test.spec, api.Codecs.UniversalDecoder(), test.noHeaders) printer, err := printers.NewCustomColumnsPrinterFromSpec(test.spec, api.Codecs.UniversalDecoder(), test.noHeaders)
if test.expectErr { if test.expectErr {
if err == nil { if err == nil {
t.Errorf("[%s] unexpected non-error", test.name) t.Errorf("[%s] unexpected non-error", test.name)
@ -141,6 +142,15 @@ func TestNewColumnPrinterFromSpec(t *testing.T) {
} }
} }
func contains(arr []string, s string) bool {
for i := range arr {
if arr[i] == s {
return true
}
}
return false
}
const exampleTemplateOne = `NAME API_VERSION const exampleTemplateOne = `NAME API_VERSION
{metadata.name} {apiVersion}` {metadata.name} {apiVersion}`
@ -150,7 +160,7 @@ const exampleTemplateTwo = `NAME API_VERSION
func TestNewColumnPrinterFromTemplate(t *testing.T) { func TestNewColumnPrinterFromTemplate(t *testing.T) {
tests := []struct { tests := []struct {
spec string spec string
expectedColumns []Column expectedColumns []printers.Column
expectErr bool expectErr bool
name string name string
}{ }{
@ -177,7 +187,7 @@ func TestNewColumnPrinterFromTemplate(t *testing.T) {
{ {
spec: exampleTemplateOne, spec: exampleTemplateOne,
name: "ok", name: "ok",
expectedColumns: []Column{ expectedColumns: []printers.Column{
{ {
Header: "NAME", Header: "NAME",
FieldSpec: "{.metadata.name}", FieldSpec: "{.metadata.name}",
@ -191,7 +201,7 @@ func TestNewColumnPrinterFromTemplate(t *testing.T) {
{ {
spec: exampleTemplateTwo, spec: exampleTemplateTwo,
name: "ok-2", name: "ok-2",
expectedColumns: []Column{ expectedColumns: []printers.Column{
{ {
Header: "NAME", Header: "NAME",
FieldSpec: "{.metadata.name}", FieldSpec: "{.metadata.name}",
@ -205,7 +215,7 @@ func TestNewColumnPrinterFromTemplate(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
reader := bytes.NewBufferString(test.spec) reader := bytes.NewBufferString(test.spec)
printer, err := NewCustomColumnsPrinterFromTemplate(reader, api.Codecs.UniversalDecoder()) printer, err := printers.NewCustomColumnsPrinterFromTemplate(reader, api.Codecs.UniversalDecoder())
if test.expectErr { if test.expectErr {
if err == nil { if err == nil {
t.Errorf("[%s] unexpected non-error", test.name) t.Errorf("[%s] unexpected non-error", test.name)
@ -226,12 +236,12 @@ func TestNewColumnPrinterFromTemplate(t *testing.T) {
func TestColumnPrint(t *testing.T) { func TestColumnPrint(t *testing.T) {
tests := []struct { tests := []struct {
columns []Column columns []printers.Column
obj runtime.Object obj runtime.Object
expectedOutput string expectedOutput string
}{ }{
{ {
columns: []Column{ columns: []printers.Column{
{ {
Header: "NAME", Header: "NAME",
FieldSpec: "{.metadata.name}", FieldSpec: "{.metadata.name}",
@ -243,7 +253,7 @@ foo
`, `,
}, },
{ {
columns: []Column{ columns: []printers.Column{
{ {
Header: "NAME", Header: "NAME",
FieldSpec: "{.metadata.name}", FieldSpec: "{.metadata.name}",
@ -261,7 +271,7 @@ bar
`, `,
}, },
{ {
columns: []Column{ columns: []printers.Column{
{ {
Header: "NAME", Header: "NAME",
FieldSpec: "{.metadata.name}", FieldSpec: "{.metadata.name}",
@ -279,7 +289,7 @@ foo baz
} }
for _, test := range tests { for _, test := range tests {
printer := &CustomColumnsPrinter{ printer := &printers.CustomColumnsPrinter{
Columns: test.columns, Columns: test.columns,
Decoder: api.Codecs.UniversalDecoder(), Decoder: api.Codecs.UniversalDecoder(),
} }

View File

@ -17,14 +17,23 @@ limitations under the License.
package printers package printers
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"reflect" "reflect"
"strings" "strings"
"text/tabwriter"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
) )
var withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print cluster name too.
type handlerEntry struct { type handlerEntry struct {
columns []string columns []string
columnsWithWide []string columnsWithWide []string
@ -49,20 +58,9 @@ func NewHumanReadablePrinter(options PrintOptions) *HumanReadablePrinter {
handlerMap: make(map[reflect.Type]*handlerEntry), handlerMap: make(map[reflect.Type]*handlerEntry),
options: options, options: options,
} }
printer.addDefaultHandlers()
return printer return printer
} }
// formatResourceName receives a resource kind, name, and boolean specifying
// whether or not to update the current name to "kind/name"
func formatResourceName(kind, name string, withKind bool) string {
if !withKind || kind == "" {
return name
}
return kind + "/" + name
}
// GetResourceKind returns the type currently set for a resource // GetResourceKind returns the type currently set for a resource
func (h *HumanReadablePrinter) GetResourceKind() string { func (h *HumanReadablePrinter) GetResourceKind() string {
return h.options.Kind return h.options.Kind
@ -157,3 +155,175 @@ func (h *HumanReadablePrinter) printHeader(columnNames []string, w io.Writer) er
} }
return nil return nil
} }
// PrintObj prints the obj in a human-friendly format according to the type of the obj.
func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error {
// if output is a tabwriter (when it's called by kubectl get), we use it; create a new tabwriter otherwise
w, found := output.(*tabwriter.Writer)
if !found {
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.
//obj, _ = DecodeUnknownObject(obj)
t := reflect.TypeOf(obj)
if handler := h.handlerMap[t]; handler != nil {
if !h.options.NoHeaders && t != h.lastType {
headers := handler.columns
if h.options.Wide {
headers = append(headers, handler.columnsWithWide...)
}
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
}
args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(w), reflect.ValueOf(h.options)}
resultValue := handler.printFunc.Call(args)[0]
if resultValue.IsNil() {
return nil
}
return resultValue.Interface().(error)
}
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
}
// 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 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)
}
// TODO: this method assumes the meta/v1 server API, so should be refactored out of this package
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
}
}
content := unstructured.UnstructuredContent()
kind := "<missing>"
if objKind, ok := content["kind"]; ok {
if str, ok := objKind.(string); ok {
kind = str
}
}
if objAPIVersion, ok := content["apiVersion"]; ok {
if str, ok := objAPIVersion.(string); ok {
version, err := schema.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
}
func formatLabelHeaders(columnLabels []string) []string {
formHead := make([]string, len(columnLabels))
for i, l := range columnLabels {
p := strings.Split(l, "/")
formHead[i] = strings.ToUpper((p[len(p)-1]))
}
return formHead
}
// headers for --show-labels=true
func formatShowLabelsHeader(showLabels bool, t reflect.Type) []string {
if showLabels {
// TODO: this is all sorts of hack, fix
if t.String() != "*api.ThirdPartyResource" && t.String() != "*api.ThirdPartyResourceList" {
return []string{"LABELS"}
}
}
return nil
}
// formatResourceName receives a resource kind, name, and boolean specifying
// whether or not to update the current name to "kind/name"
// TODO: dedup this with printers/internalversions
func formatResourceName(kind, name string, withKind bool) string {
if !withKind || kind == "" {
return name
}
return kind + "/" + name
}
// TODO: dedup this with printers/internalversions
func appendLabels(itemLabels map[string]string, columnLabels []string) string {
var buffer bytes.Buffer
for _, cl := range columnLabels {
buffer.WriteString(fmt.Sprint("\t"))
if il, ok := itemLabels[cl]; ok {
buffer.WriteString(fmt.Sprint(il))
} else {
buffer.WriteString("<none>")
}
}
return buffer.String()
}
// Append all labels to a single column. We need this even when show-labels flag* is
// false, since this adds newline delimiter to the end of each row.
// TODO: dedup this with printers/internalversions
func appendAllLabels(showLabels bool, itemLabels map[string]string) string {
var buffer bytes.Buffer
if showLabels {
buffer.WriteString(fmt.Sprint("\t"))
buffer.WriteString(labels.FormatLabels(itemLabels))
}
buffer.WriteString("\n")
return buffer.String()
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package printers package printers
import ( import (
"fmt"
"io" "io"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -60,3 +61,36 @@ type PrintOptions struct {
Kind string Kind string
ColumnLabels []string ColumnLabels []string
} }
// Describer generates output for the named resource or an error
// if the output could not be generated. Implementers typically
// abstract the retrieval of the named object from a remote server.
type Describer interface {
Describe(namespace, name string, describerSettings DescriberSettings) (output string, err error)
}
// DescriberSettings holds display configuration for each object
// describer to control what is printed.
type DescriberSettings struct {
ShowEvents bool
}
// ObjectDescriber is an interface for displaying arbitrary objects with extra
// information. Use when an object is in hand (on disk, or already retrieved).
// Implementers may ignore the additional information passed on extra, or use it
// by default. ObjectDescribers may return ErrNoDescriber if no suitable describer
// is found.
type ObjectDescriber interface {
DescribeObject(object interface{}, extra ...interface{}) (output string, err error)
}
// ErrNoDescriber is a structured error indicating the provided object or objects
// cannot be described.
type ErrNoDescriber struct {
Types []string
}
// Error implements the error interface.
func (e ErrNoDescriber) Error() string {
return fmt.Sprintf("no describer has been defined for %v", e.Types)
}

View File

@ -0,0 +1,113 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"describe_test.go",
"printers_test.go",
"sorted_resource_name_list_test.go",
],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//federation/apis/federation:go_default_library",
"//federation/client/clientset_generated/federation_internalclientset/fake:go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/testapi:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/apis/autoscaling:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/client/clientset_generated/clientset/fake:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/kubectl/testing:go_default_library",
"//pkg/printers:go_default_library",
"//pkg/util:go_default_library",
"//vendor:github.com/ghodss/yaml",
"//vendor:k8s.io/apimachinery/pkg/api/equality",
"//vendor:k8s.io/apimachinery/pkg/api/resource",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"//vendor:k8s.io/apimachinery/pkg/runtime",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/runtime/serializer/yaml",
"//vendor:k8s.io/apimachinery/pkg/util/diff",
"//vendor:k8s.io/apimachinery/pkg/util/intstr",
"//vendor:k8s.io/apimachinery/pkg/util/sets",
],
)
go_library(
name = "go_default_library",
srcs = [
"describe.go",
"printers.go",
],
tags = ["automanaged"],
deps = [
"//federation/apis/federation:go_default_library",
"//federation/client/clientset_generated/federation_internalclientset:go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/annotations:go_default_library",
"//pkg/api/events:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/autoscaling:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/certificates:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/apis/storage/util:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/core/v1:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/extensions/v1beta1:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library",
"//pkg/controller/deployment/util:go_default_library",
"//pkg/fieldpath:go_default_library",
"//pkg/kubelet/qos:go_default_library",
"//pkg/printers:go_default_library",
"//pkg/util/node:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/api/meta",
"//vendor:k8s.io/apimachinery/pkg/api/resource",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/fields",
"//vendor:k8s.io/apimachinery/pkg/labels",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/types",
"//vendor:k8s.io/apimachinery/pkg/util/intstr",
"//vendor:k8s.io/apimachinery/pkg/util/sets",
"//vendor:k8s.io/client-go/dynamic",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package kubectl package internalversion
import ( import (
"bytes" "bytes"
@ -26,8 +26,11 @@ import (
"reflect" "reflect"
"sort" "sort"
"strings" "strings"
"text/tabwriter"
"time" "time"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
@ -42,7 +45,6 @@ import (
"k8s.io/kubernetes/federation/apis/federation" "k8s.io/kubernetes/federation/apis/federation"
fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset" fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/annotations" "k8s.io/kubernetes/pkg/api/annotations"
"k8s.io/kubernetes/pkg/api/events" "k8s.io/kubernetes/pkg/api/events"
"k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/apps"
@ -55,48 +57,17 @@ import (
"k8s.io/kubernetes/pkg/apis/storage" "k8s.io/kubernetes/pkg/apis/storage"
storageutil "k8s.io/kubernetes/pkg/apis/storage/util" storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
versionedclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" versionedclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
coreclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/core/v1"
extensionsclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/extensions/v1beta1"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion" extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
"k8s.io/kubernetes/pkg/fieldpath" "k8s.io/kubernetes/pkg/fieldpath"
"k8s.io/kubernetes/pkg/kubelet/qos"
"github.com/golang/glog" "k8s.io/kubernetes/pkg/printers"
) )
// Describer generates output for the named resource or an error
// if the output could not be generated. Implementers typically
// abstract the retrieval of the named object from a remote server.
type Describer interface {
Describe(namespace, name string, describerSettings DescriberSettings) (output string, err error)
}
// DescriberSettings holds display configuration for each object
// describer to control what is printed.
type DescriberSettings struct {
ShowEvents bool
}
// ObjectDescriber is an interface for displaying arbitrary objects with extra
// information. Use when an object is in hand (on disk, or already retrieved).
// Implementers may ignore the additional information passed on extra, or use it
// by default. ObjectDescribers may return ErrNoDescriber if no suitable describer
// is found.
type ObjectDescriber interface {
DescribeObject(object interface{}, extra ...interface{}) (output string, err error)
}
// ErrNoDescriber is a structured error indicating the provided object or objects
// cannot be described.
type ErrNoDescriber struct {
Types []string
}
// Error implements the error interface.
func (e ErrNoDescriber) Error() string {
return fmt.Sprintf("no describer has been defined for %v", e.Types)
}
// Each level has 2 spaces for PrefixWriter // Each level has 2 spaces for PrefixWriter
const ( const (
LEVEL_0 = iota LEVEL_0 = iota
@ -122,8 +93,8 @@ func (pw *PrefixWriter) WriteLine(a ...interface{}) {
fmt.Fprintln(pw.out, a...) fmt.Fprintln(pw.out, a...)
} }
func describerMap(c clientset.Interface) map[schema.GroupKind]Describer { func describerMap(c clientset.Interface) map[schema.GroupKind]printers.Describer {
m := map[schema.GroupKind]Describer{ m := map[schema.GroupKind]printers.Describer{
api.Kind("Pod"): &PodDescriber{c}, api.Kind("Pod"): &PodDescriber{c},
api.Kind("ReplicationController"): &ReplicationControllerDescriber{c}, api.Kind("ReplicationController"): &ReplicationControllerDescriber{c},
api.Kind("Secret"): &SecretDescriber{c}, api.Kind("Secret"): &SecretDescriber{c},
@ -155,7 +126,7 @@ func describerMap(c clientset.Interface) map[schema.GroupKind]Describer {
return m return m
} }
// List of all resource types we can describe // DescribableResources lists all resource types we can describe.
func DescribableResources() []string { func DescribableResources() []string {
keys := make([]string, 0) keys := make([]string, 0)
@ -166,16 +137,16 @@ func DescribableResources() []string {
return keys return keys
} }
// Describer returns the default describe functions for each of the standard // DescriberFor returns the default describe functions for each of the standard
// Kubernetes types. // Kubernetes types.
func DescriberFor(kind schema.GroupKind, c clientset.Interface) (Describer, bool) { func DescriberFor(kind schema.GroupKind, c clientset.Interface) (printers.Describer, bool) {
f, ok := describerMap(c)[kind] f, ok := describerMap(c)[kind]
return f, ok return f, ok
} }
// GenericDescriberFor returns a generic describer for the specified mapping // GenericDescriberFor returns a generic describer for the specified mapping
// that uses only information available from runtime.Unstructured // that uses only information available from runtime.Unstructured
func GenericDescriberFor(mapping *meta.RESTMapping, dynamic *dynamic.Client, events coreclient.EventsGetter) Describer { func GenericDescriberFor(mapping *meta.RESTMapping, dynamic *dynamic.Client, events coreclient.EventsGetter) printers.Describer {
return &genericDescriber{mapping, dynamic, events} return &genericDescriber{mapping, dynamic, events}
} }
@ -185,7 +156,7 @@ type genericDescriber struct {
events coreclient.EventsGetter events coreclient.EventsGetter
} }
func (g *genericDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (output string, err error) { func (g *genericDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (output string, err error) {
apiResource := &metav1.APIResource{ apiResource := &metav1.APIResource{
Name: g.mapping.Resource, Name: g.mapping.Resource,
Namespaced: g.mapping.Scope.Name() == meta.RESTScopeNameNamespace, Namespaced: g.mapping.Scope.Name() == meta.RESTScopeNameNamespace,
@ -214,7 +185,7 @@ func (g *genericDescriber) Describe(namespace, name string, describerSettings De
} }
// DefaultObjectDescriber can describe the default Kubernetes objects. // DefaultObjectDescriber can describe the default Kubernetes objects.
var DefaultObjectDescriber ObjectDescriber var DefaultObjectDescriber printers.ObjectDescriber
func init() { func init() {
d := &Describers{} d := &Describers{}
@ -239,7 +210,7 @@ type NamespaceDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *NamespaceDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *NamespaceDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
ns, err := d.Core().Namespaces().Get(name, metav1.GetOptions{}) ns, err := d.Core().Namespaces().Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -411,7 +382,7 @@ type LimitRangeDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *LimitRangeDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *LimitRangeDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
lr := d.Core().LimitRanges(namespace) lr := d.Core().LimitRanges(namespace)
limitRange, err := lr.Get(name, metav1.GetOptions{}) limitRange, err := lr.Get(name, metav1.GetOptions{})
@ -438,7 +409,7 @@ type ResourceQuotaDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *ResourceQuotaDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *ResourceQuotaDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
rq := d.Core().ResourceQuotas(namespace) rq := d.Core().ResourceQuotas(namespace)
resourceQuota, err := rq.Get(name, metav1.GetOptions{}) resourceQuota, err := rq.Get(name, metav1.GetOptions{})
@ -508,7 +479,7 @@ type PodDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *PodDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *PodDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
pod, err := d.Core().Pods(namespace).Get(name, metav1.GetOptions{}) pod, err := d.Core().Pods(namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
if describerSettings.ShowEvents { if describerSettings.ShowEvents {
@ -810,7 +781,7 @@ type PersistentVolumeDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := d.Core().PersistentVolumes() c := d.Core().PersistentVolumes()
pv, err := c.Get(name, metav1.GetOptions{}) pv, err := c.Get(name, metav1.GetOptions{})
@ -881,7 +852,7 @@ type PersistentVolumeClaimDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := d.Core().PersistentVolumeClaims(namespace) c := d.Core().PersistentVolumeClaims(namespace)
pvc, err := c.Get(name, metav1.GetOptions{}) pvc, err := c.Get(name, metav1.GetOptions{})
@ -1214,7 +1185,7 @@ type ReplicationControllerDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *ReplicationControllerDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *ReplicationControllerDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
rc := d.Core().ReplicationControllers(namespace) rc := d.Core().ReplicationControllers(namespace)
pc := d.Core().Pods(namespace) pc := d.Core().Pods(namespace)
@ -1286,7 +1257,7 @@ type ReplicaSetDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *ReplicaSetDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *ReplicaSetDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
rsc := d.Extensions().ReplicaSets(namespace) rsc := d.Extensions().ReplicaSets(namespace)
pc := d.Core().Pods(namespace) pc := d.Core().Pods(namespace)
@ -1338,7 +1309,7 @@ type JobDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *JobDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *JobDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
job, err := d.Batch().Jobs(namespace).Get(name, metav1.GetOptions{}) job, err := d.Batch().Jobs(namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -1387,7 +1358,7 @@ type CronJobDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *CronJobDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *CronJobDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
scheduledJob, err := d.Batch().CronJobs(namespace).Get(name, metav1.GetOptions{}) scheduledJob, err := d.Batch().CronJobs(namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -1474,7 +1445,7 @@ type DaemonSetDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *DaemonSetDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *DaemonSetDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
dc := d.Extensions().DaemonSets(namespace) dc := d.Extensions().DaemonSets(namespace)
pc := d.Core().Pods(namespace) pc := d.Core().Pods(namespace)
@ -1529,7 +1500,7 @@ type SecretDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *SecretDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *SecretDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := d.Core().Secrets(namespace) c := d.Core().Secrets(namespace)
secret, err := c.Get(name, metav1.GetOptions{}) secret, err := c.Get(name, metav1.GetOptions{})
@ -1569,7 +1540,7 @@ type IngressDescriber struct {
clientset.Interface clientset.Interface
} }
func (i *IngressDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (i *IngressDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := i.Extensions().Ingresses(namespace) c := i.Extensions().Ingresses(namespace)
ing, err := c.Get(name, metav1.GetOptions{}) ing, err := c.Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
@ -1598,7 +1569,7 @@ func (i *IngressDescriber) describeBackend(ns string, backend *extensions.Ingres
return formatEndpoints(endpoints, sets.NewString(spName)) return formatEndpoints(endpoints, sets.NewString(spName))
} }
func (i *IngressDescriber) describeIngress(ing *extensions.Ingress, describerSettings DescriberSettings) (string, error) { func (i *IngressDescriber) describeIngress(ing *extensions.Ingress, describerSettings printers.DescriberSettings) (string, error) {
return tabbedString(func(out io.Writer) error { return tabbedString(func(out io.Writer) error {
w := &PrefixWriter{out} w := &PrefixWriter{out}
w.Write(LEVEL_0, "Name:\t%v\n", ing.Name) w.Write(LEVEL_0, "Name:\t%v\n", ing.Name)
@ -1682,7 +1653,7 @@ type ServiceDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *ServiceDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *ServiceDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := d.Core().Services(namespace) c := d.Core().Services(namespace)
service, err := c.Get(name, metav1.GetOptions{}) service, err := c.Get(name, metav1.GetOptions{})
@ -1762,7 +1733,7 @@ type EndpointsDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *EndpointsDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *EndpointsDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := d.Core().Endpoints(namespace) c := d.Core().Endpoints(namespace)
ep, err := c.Get(name, metav1.GetOptions{}) ep, err := c.Get(name, metav1.GetOptions{})
@ -1836,7 +1807,7 @@ type ServiceAccountDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *ServiceAccountDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *ServiceAccountDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := d.Core().ServiceAccounts(namespace) c := d.Core().ServiceAccounts(namespace)
serviceAccount, err := c.Get(name, metav1.GetOptions{}) serviceAccount, err := c.Get(name, metav1.GetOptions{})
@ -1944,7 +1915,7 @@ type NodeDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *NodeDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *NodeDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
mc := d.Core().Nodes() mc := d.Core().Nodes()
node, err := mc.Get(name, metav1.GetOptions{}) node, err := mc.Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
@ -2065,7 +2036,7 @@ type StatefulSetDescriber struct {
client clientset.Interface client clientset.Interface
} }
func (p *StatefulSetDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (p *StatefulSetDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
ps, err := p.client.Apps().StatefulSets(namespace).Get(name, metav1.GetOptions{}) ps, err := p.client.Apps().StatefulSets(namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -2108,7 +2079,7 @@ type CertificateSigningRequestDescriber struct {
client clientset.Interface client clientset.Interface
} }
func (p *CertificateSigningRequestDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (p *CertificateSigningRequestDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
csr, err := p.client.Certificates().CertificateSigningRequests().Get(name, metav1.GetOptions{}) csr, err := p.client.Certificates().CertificateSigningRequests().Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -2178,7 +2149,7 @@ type HorizontalPodAutoscalerDescriber struct {
client clientset.Interface client clientset.Interface
} }
func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
hpa, err := d.client.Autoscaling().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{}) hpa, err := d.client.Autoscaling().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -2369,7 +2340,7 @@ type DeploymentDescriber struct {
versionedClient versionedclientset.Interface versionedClient versionedclientset.Interface
} }
func (dd *DeploymentDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (dd *DeploymentDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
d, err := dd.versionedClient.Extensions().Deployments(namespace).Get(name, metav1.GetOptions{}) d, err := dd.versionedClient.Extensions().Deployments(namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -2504,7 +2475,7 @@ type ConfigMapDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *ConfigMapDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *ConfigMapDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := d.Core().ConfigMaps(namespace) c := d.Core().ConfigMaps(namespace)
configMap, err := c.Get(name, metav1.GetOptions{}) configMap, err := c.Get(name, metav1.GetOptions{})
@ -2537,7 +2508,7 @@ type ClusterDescriber struct {
fedclientset.Interface fedclientset.Interface
} }
func (d *ClusterDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *ClusterDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
cluster, err := d.Federation().Clusters().Get(name, metav1.GetOptions{}) cluster, err := d.Federation().Clusters().Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -2579,7 +2550,7 @@ type NetworkPolicyDescriber struct {
clientset.Interface clientset.Interface
} }
func (d *NetworkPolicyDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (d *NetworkPolicyDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
c := d.Extensions().NetworkPolicies(namespace) c := d.Extensions().NetworkPolicies(namespace)
networkPolicy, err := c.Get(name, metav1.GetOptions{}) networkPolicy, err := c.Get(name, metav1.GetOptions{})
@ -2606,7 +2577,7 @@ type StorageClassDescriber struct {
clientset.Interface clientset.Interface
} }
func (s *StorageClassDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (s *StorageClassDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
sc, err := s.Storage().StorageClasses().Get(name, metav1.GetOptions{}) sc, err := s.Storage().StorageClasses().Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -2635,7 +2606,7 @@ type PodDisruptionBudgetDescriber struct {
clientset.Interface clientset.Interface
} }
func (p *PodDisruptionBudgetDescriber) Describe(namespace, name string, describerSettings DescriberSettings) (string, error) { func (p *PodDisruptionBudgetDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
pdb, err := p.Policy().PodDisruptionBudgets(namespace).Get(name, metav1.GetOptions{}) pdb, err := p.Policy().PodDisruptionBudgets(namespace).Get(name, metav1.GetOptions{})
if err != nil { if err != nil {
return "", err return "", err
@ -2673,7 +2644,7 @@ func newErrNoDescriber(types ...reflect.Type) error {
for _, t := range types { for _, t := range types {
names = append(names, t.String()) names = append(names, t.String())
} }
return ErrNoDescriber{Types: names} return printers.ErrNoDescriber{Types: names}
} }
// Describers implements ObjectDescriber against functions registered via Add. Those functions can // Describers implements ObjectDescriber against functions registered via Add. Those functions can
@ -2720,7 +2691,7 @@ func (d *Describers) DescribeObject(exact interface{}, extra ...interface{}) (st
return "", newErrNoDescriber(append([]reflect.Type{exactType}, types...)...) return "", newErrNoDescriber(append([]reflect.Type{exactType}, types...)...)
} }
// Add adds one or more describer functions to the Describer. The passed function must // Add adds one or more describer functions to the printers.Describer. The passed function must
// match the signature: // match the signature:
// //
// func(...) (string, error) // func(...) (string, error)
@ -2928,3 +2899,102 @@ func printTolerationsMultilineWithIndent(w *PrefixWriter, initialIndent, title,
} }
} }
} }
func tabbedString(f func(io.Writer) error) (string, error) {
out := new(tabwriter.Writer)
buf := &bytes.Buffer{}
out.Init(buf, 0, 8, 1, '\t', 0)
err := f(out)
if err != nil {
return "", err
}
out.Flush()
str := string(buf.String())
return str, nil
}
type SortableResourceNames []api.ResourceName
func (list SortableResourceNames) Len() int {
return len(list)
}
func (list SortableResourceNames) Swap(i, j int) {
list[i], list[j] = list[j], list[i]
}
func (list SortableResourceNames) Less(i, j int) bool {
return list[i] < list[j]
}
// SortedResourceNames returns the sorted resource names of a resource list.
func SortedResourceNames(list api.ResourceList) []api.ResourceName {
resources := make([]api.ResourceName, 0, len(list))
for res := range list {
resources = append(resources, res)
}
sort.Sort(SortableResourceNames(resources))
return resources
}
type SortableResourceQuotas []api.ResourceQuota
func (list SortableResourceQuotas) Len() int {
return len(list)
}
func (list SortableResourceQuotas) Swap(i, j int) {
list[i], list[j] = list[j], list[i]
}
func (list SortableResourceQuotas) Less(i, j int) bool {
return list[i].Name < list[j].Name
}
type SortableVolumeMounts []api.VolumeMount
func (list SortableVolumeMounts) Len() int {
return len(list)
}
func (list SortableVolumeMounts) Swap(i, j int) {
list[i], list[j] = list[j], list[i]
}
func (list SortableVolumeMounts) Less(i, j int) bool {
return list[i].MountPath < list[j].MountPath
}
// SortedQoSResourceNames returns the sorted resource names of a QoS list.
func SortedQoSResourceNames(list qos.QOSList) []api.ResourceName {
resources := make([]api.ResourceName, 0, len(list))
for res := range list {
resources = append(resources, api.ResourceName(res))
}
sort.Sort(SortableResourceNames(resources))
return resources
}
func listOfImages(spec *api.PodSpec) []string {
images := make([]string, 0, len(spec.Containers))
for _, container := range spec.Containers {
images = append(images, container.Image)
}
return images
}
func makeImageList(spec *api.PodSpec) string {
return strings.Join(listOfImages(spec), ",")
}
func versionedClientsetForDeployment(internalClient clientset.Interface) versionedclientset.Interface {
if internalClient == nil {
return &versionedclientset.Clientset{}
}
return &versionedclientset.Clientset{
CoreV1Client: coreclientset.New(internalClient.Core().RESTClient()),
ExtensionsV1beta1Client: extensionsclientset.New(internalClient.Extensions().RESTClient()),
}
}

View File

@ -40,6 +40,7 @@ import (
versionedfake "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake" versionedfake "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/printers"
"k8s.io/kubernetes/pkg/util" "k8s.io/kubernetes/pkg/util"
) )
@ -59,7 +60,7 @@ func TestDescribePod(t *testing.T) {
}) })
c := &describeClient{T: t, Namespace: "foo", Interface: fake} c := &describeClient{T: t, Namespace: "foo", Interface: fake}
d := PodDescriber{c} d := PodDescriber{c}
out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -83,7 +84,7 @@ func TestDescribePodTolerations(t *testing.T) {
}) })
c := &describeClient{T: t, Namespace: "foo", Interface: fake} c := &describeClient{T: t, Namespace: "foo", Interface: fake}
d := PodDescriber{c} d := PodDescriber{c}
out, err := d.Describe("foo", "bar", DescriberSettings{}) out, err := d.Describe("foo", "bar", printers.DescriberSettings{})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -100,7 +101,7 @@ func TestDescribeNamespace(t *testing.T) {
}) })
c := &describeClient{T: t, Namespace: "", Interface: fake} c := &describeClient{T: t, Namespace: "", Interface: fake}
d := NamespaceDescriber{c} d := NamespaceDescriber{c}
out, err := d.Describe("", "myns", DescriberSettings{ShowEvents: true}) out, err := d.Describe("", "myns", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -118,7 +119,7 @@ func TestDescribeService(t *testing.T) {
}) })
c := &describeClient{T: t, Namespace: "foo", Interface: fake} c := &describeClient{T: t, Namespace: "foo", Interface: fake}
d := ServiceDescriber{c} d := ServiceDescriber{c}
out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -167,7 +168,7 @@ func TestPodDescribeResultsSorted(t *testing.T) {
d := PodDescriber{c} d := PodDescriber{c}
// Act // Act
out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
// Assert // Assert
if err != nil { if err != nil {
@ -436,7 +437,7 @@ func TestDescribers(t *testing.T) {
if out, err := d.DescribeObject(first, second, third); out != "" || err == nil { if out, err := d.DescribeObject(first, second, third); out != "" || err == nil {
t.Errorf("unexpected result: %s %v", out, err) t.Errorf("unexpected result: %s %v", out, err)
} else { } else {
if noDescriber, ok := err.(ErrNoDescriber); ok { if noDescriber, ok := err.(printers.ErrNoDescriber); ok {
if !reflect.DeepEqual(noDescriber.Types, []string{"*api.Event", "*api.Pod", "*api.Pod"}) { if !reflect.DeepEqual(noDescriber.Types, []string{"*api.Event", "*api.Pod", "*api.Pod"}) {
t.Errorf("unexpected describer: %v", err) t.Errorf("unexpected describer: %v", err)
} }
@ -649,7 +650,7 @@ func TestPersistentVolumeDescriber(t *testing.T) {
for name, pv := range tests { for name, pv := range tests {
fake := fake.NewSimpleClientset(pv) fake := fake.NewSimpleClientset(pv)
c := PersistentVolumeDescriber{fake} c := PersistentVolumeDescriber{fake}
str, err := c.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) str, err := c.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("Unexpected error for test %s: %v", name, err) t.Errorf("Unexpected error for test %s: %v", name, err)
} }
@ -673,7 +674,7 @@ func TestDescribeDeployment(t *testing.T) {
}, },
}) })
d := DeploymentDescriber{fake, versionedFake} d := DeploymentDescriber{fake, versionedFake}
out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -707,7 +708,7 @@ func TestDescribeCluster(t *testing.T) {
} }
fake := fedfake.NewSimpleClientset(&cluster) fake := fedfake.NewSimpleClientset(&cluster)
d := ClusterDescriber{Interface: fake} d := ClusterDescriber{Interface: fake}
out, err := d.Describe("any", "foo", DescriberSettings{ShowEvents: true}) out, err := d.Describe("any", "foo", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -732,7 +733,7 @@ func TestDescribeStorageClass(t *testing.T) {
}, },
}) })
s := StorageClassDescriber{f} s := StorageClassDescriber{f}
out, err := s.Describe("", "foo", DescriberSettings{ShowEvents: true}) out, err := s.Describe("", "foo", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -756,7 +757,7 @@ func TestDescribePodDisruptionBudget(t *testing.T) {
}, },
}) })
s := PodDisruptionBudgetDescriber{f} s := PodDisruptionBudgetDescriber{f}
out, err := s.Describe("ns1", "pdb1", DescriberSettings{ShowEvents: true}) out, err := s.Describe("ns1", "pdb1", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
@ -1112,7 +1113,7 @@ func TestDescribeHorizontalPodAutoscaler(t *testing.T) {
} }
fake := fake.NewSimpleClientset(&test.hpa) fake := fake.NewSimpleClientset(&test.hpa)
desc := HorizontalPodAutoscalerDescriber{fake} desc := HorizontalPodAutoscalerDescriber{fake}
str, err := desc.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) str, err := desc.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("Unexpected error for test %s: %v", test.name, err) t.Errorf("Unexpected error for test %s: %v", test.name, err)
} }
@ -1141,7 +1142,7 @@ func TestDescribeEvents(t *testing.T) {
}, },
} }
m := map[string]Describer{ m := map[string]printers.Describer{
"DaemonSetDescriber": &DaemonSetDescriber{ "DaemonSetDescriber": &DaemonSetDescriber{
fake.NewSimpleClientset(&extensions.DaemonSet{ fake.NewSimpleClientset(&extensions.DaemonSet{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -1241,7 +1242,7 @@ func TestDescribeEvents(t *testing.T) {
} }
for name, d := range m { for name, d := range m {
out, err := d.Describe("foo", "bar", DescriberSettings{ShowEvents: true}) out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: true})
if err != nil { if err != nil {
t.Errorf("unexpected error for %q: %v", name, err) t.Errorf("unexpected error for %q: %v", name, err)
} }
@ -1252,7 +1253,7 @@ func TestDescribeEvents(t *testing.T) {
t.Errorf("events not found for %q when ShowEvents=true: %s", name, out) t.Errorf("events not found for %q when ShowEvents=true: %s", name, out)
} }
out, err = d.Describe("foo", "bar", DescriberSettings{ShowEvents: false}) out, err = d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: false})
if err != nil { if err != nil {
t.Errorf("unexpected error for %q: %s", name, err) t.Errorf("unexpected error for %q: %s", name, err)
} }

View File

@ -20,19 +20,12 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os"
"reflect"
"sort" "sort"
"strings" "strings"
"text/tabwriter"
"time" "time"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/federation/apis/federation" "k8s.io/kubernetes/federation/apis/federation"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
@ -46,98 +39,11 @@ import (
"k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac"
"k8s.io/kubernetes/pkg/apis/storage" "k8s.io/kubernetes/pkg/apis/storage"
storageutil "k8s.io/kubernetes/pkg/apis/storage/util" storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
"k8s.io/kubernetes/pkg/printers"
"k8s.io/kubernetes/pkg/util/node" "k8s.io/kubernetes/pkg/util/node"
) )
// GetPrinter takes a format type, an optional format argument. It will return true const loadBalancerWidth = 16
// if the format is generic (untyped), otherwise it will return false. The printer
// is agnostic to schema versions, so you must send arguments to PrintObj in the
// version you wish them to be shown using a VersionedPrinter (typically when
// generic is true).
func GetPrinter(format, formatArgument string, noHeaders, allowMissingTemplateKeys bool) (ResourcePrinter, bool, error) {
var printer ResourcePrinter
switch format {
case "json":
printer = &JSONPrinter{}
case "yaml":
printer = &YAMLPrinter{}
case "name":
printer = &NamePrinter{
// TODO: this is wrong, these should be provided as an argument to GetPrinter
Typer: api.Scheme,
Decoder: api.Codecs.UniversalDecoder(),
}
case "template", "go-template":
if len(formatArgument) == 0 {
return nil, false, fmt.Errorf("template format specified but no template given")
}
templatePrinter, err := NewTemplatePrinter([]byte(formatArgument))
if err != nil {
return nil, false, fmt.Errorf("error parsing template %s, %v\n", formatArgument, err)
}
templatePrinter.AllowMissingKeys(allowMissingTemplateKeys)
printer = templatePrinter
case "templatefile", "go-template-file":
if len(formatArgument) == 0 {
return nil, false, fmt.Errorf("templatefile format specified but no template file given")
}
data, err := ioutil.ReadFile(formatArgument)
if err != nil {
return nil, false, fmt.Errorf("error reading template %s, %v\n", formatArgument, err)
}
templatePrinter, err := NewTemplatePrinter(data)
if err != nil {
return nil, false, fmt.Errorf("error parsing template %s, %v\n", string(data), err)
}
templatePrinter.AllowMissingKeys(allowMissingTemplateKeys)
printer = templatePrinter
case "jsonpath":
if len(formatArgument) == 0 {
return nil, false, fmt.Errorf("jsonpath template format specified but no template given")
}
jsonpathPrinter, err := NewJSONPathPrinter(formatArgument)
if err != nil {
return nil, false, fmt.Errorf("error parsing jsonpath %s, %v\n", formatArgument, err)
}
jsonpathPrinter.AllowMissingKeys(allowMissingTemplateKeys)
printer = jsonpathPrinter
case "jsonpath-file":
if len(formatArgument) == 0 {
return nil, false, fmt.Errorf("jsonpath file format specified but no template file file given")
}
data, err := ioutil.ReadFile(formatArgument)
if err != nil {
return nil, false, fmt.Errorf("error reading template %s, %v\n", formatArgument, err)
}
jsonpathPrinter, err := NewJSONPathPrinter(string(data))
if err != nil {
return nil, false, fmt.Errorf("error parsing template %s, %v\n", string(data), err)
}
jsonpathPrinter.AllowMissingKeys(allowMissingTemplateKeys)
printer = jsonpathPrinter
case "custom-columns":
var err error
if printer, err = NewCustomColumnsPrinterFromSpec(formatArgument, api.Codecs.UniversalDecoder(), noHeaders); err != nil {
return nil, false, err
}
case "custom-columns-file":
file, err := os.Open(formatArgument)
if err != nil {
return nil, false, fmt.Errorf("error reading template %s, %v\n", formatArgument, err)
}
defer file.Close()
if printer, err = NewCustomColumnsPrinterFromTemplate(file, api.Codecs.UniversalDecoder()); err != nil {
return nil, false, err
}
case "wide":
fallthrough
case "":
return nil, false, nil
default:
return nil, false, fmt.Errorf("output format %q not recognized", format)
}
return printer, true, nil
}
// NOTE: When adding a new resource type here, please update the list // NOTE: When adding a new resource type here, please update the list
// pkg/kubectl/cmd/get.go to reflect the new resource type. // pkg/kubectl/cmd/get.go to reflect the new resource type.
@ -184,7 +90,6 @@ var (
// TODO: consider having 'KIND' for third party resource data // TODO: consider having 'KIND' for third party resource data
thirdPartyResourceDataColumns = []string{"NAME", "LABELS", "DATA"} thirdPartyResourceDataColumns = []string{"NAME", "LABELS", "DATA"}
horizontalPodAutoscalerColumns = []string{"NAME", "REFERENCE", "TARGETS", "MINPODS", "MAXPODS", "REPLICAS", "AGE"} horizontalPodAutoscalerColumns = []string{"NAME", "REFERENCE", "TARGETS", "MINPODS", "MAXPODS", "REPLICAS", "AGE"}
withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print cluster name too.
deploymentColumns = []string{"NAME", "DESIRED", "CURRENT", "UP-TO-DATE", "AVAILABLE", "AGE"} deploymentColumns = []string{"NAME", "DESIRED", "CURRENT", "UP-TO-DATE", "AVAILABLE", "AGE"}
deploymentWideColumns = []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"} deploymentWideColumns = []string{"CONTAINER(S)", "IMAGE(S)", "SELECTOR"}
configMapColumns = []string{"NAME", "DATA", "AGE"} configMapColumns = []string{"NAME", "DATA", "AGE"}
@ -194,7 +99,7 @@ var (
certificateSigningRequestColumns = []string{"NAME", "AGE", "REQUESTOR", "CONDITION"} certificateSigningRequestColumns = []string{"NAME", "AGE", "REQUESTOR", "CONDITION"}
) )
func printPod(pod *api.Pod, w io.Writer, options PrintOptions) error { func printPod(pod *api.Pod, w io.Writer, options printers.PrintOptions) error {
if err := printPodBase(pod, w, options); err != nil { if err := printPodBase(pod, w, options); err != nil {
return err return err
} }
@ -202,7 +107,7 @@ func printPod(pod *api.Pod, w io.Writer, options PrintOptions) error {
return nil return nil
} }
func printPodList(podList *api.PodList, w io.Writer, options PrintOptions) error { func printPodList(podList *api.PodList, w io.Writer, options printers.PrintOptions) error {
for _, pod := range podList.Items { for _, pod := range podList.Items {
if err := printPodBase(&pod, w, options); err != nil { if err := printPodBase(&pod, w, options); err != nil {
return err return err
@ -211,10 +116,10 @@ func printPodList(podList *api.PodList, w io.Writer, options PrintOptions) error
return nil return nil
} }
// addDefaultHandlers adds print handlers for default Kubernetes types. // AddHandlers adds print handlers for default Kubernetes types dealing with internal versions.
func (h *HumanReadablePrinter) addDefaultHandlers() { func AddHandlers(h *printers.HumanReadablePrinter) {
h.Handler(podColumns, podWideColumns, h.printPodList) h.Handler(podColumns, podWideColumns, printPodList)
h.Handler(podColumns, podWideColumns, h.printPod) h.Handler(podColumns, podWideColumns, printPod)
h.Handler(podTemplateColumns, nil, printPodTemplate) h.Handler(podTemplateColumns, nil, printPodTemplate)
h.Handler(podTemplateColumns, nil, printPodTemplateList) h.Handler(podTemplateColumns, nil, printPodTemplateList)
h.Handler(podDisruptionBudgetColumns, nil, printPodDisruptionBudget) h.Handler(podDisruptionBudgetColumns, nil, printPodDisruptionBudget)
@ -288,6 +193,16 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
h.Handler(statusColumns, nil, printStatus) h.Handler(statusColumns, nil, printStatus)
} }
// formatResourceName receives a resource kind, name, and boolean specifying
// whether or not to update the current name to "kind/name"
func formatResourceName(kind, name string, withKind bool) string {
if !withKind || kind == "" {
return name
}
return kind + "/" + name
}
// Pass ports=nil for all ports. // Pass ports=nil for all ports.
func formatEndpoints(endpoints *api.Endpoints, ports sets.String) string { func formatEndpoints(endpoints *api.Endpoints, ports sets.String) string {
if len(endpoints.Subsets) == 0 { if len(endpoints.Subsets) == 0 {
@ -322,35 +237,16 @@ func formatEndpoints(endpoints *api.Endpoints, ports sets.String) string {
return ret return ret
} }
func ShortHumanDuration(d time.Duration) string {
// Allow deviation no more than 2 seconds(excluded) to tolerate machine time
// inconsistence, it can be considered as almost now.
if seconds := int(d.Seconds()); seconds < -1 {
return fmt.Sprintf("<invalid>")
} else if seconds < 0 {
return fmt.Sprintf("0s")
} else if seconds < 60 {
return fmt.Sprintf("%ds", seconds)
} else if minutes := int(d.Minutes()); minutes < 60 {
return fmt.Sprintf("%dm", minutes)
} else if hours := int(d.Hours()); hours < 24 {
return fmt.Sprintf("%dh", hours)
} else if hours < 24*364 {
return fmt.Sprintf("%dd", hours/24)
}
return fmt.Sprintf("%dy", int(d.Hours()/24/365))
}
// translateTimestamp returns the elapsed time since timestamp in // translateTimestamp returns the elapsed time since timestamp in
// human-readable approximation. // human-readable approximation.
func translateTimestamp(timestamp metav1.Time) string { func translateTimestamp(timestamp metav1.Time) string {
if timestamp.IsZero() { if timestamp.IsZero() {
return "<unknown>" return "<unknown>"
} }
return ShortHumanDuration(time.Now().Sub(timestamp.Time)) return printers.ShortHumanDuration(time.Now().Sub(timestamp.Time))
} }
func printPodBase(pod *api.Pod, w io.Writer, options PrintOptions) error { func printPodBase(pod *api.Pod, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, pod.Name, options.WithKind) name := formatResourceName(options.Kind, pod.Name, options.WithKind)
namespace := pod.Namespace namespace := pod.Namespace
@ -459,7 +355,7 @@ func printPodBase(pod *api.Pod, w io.Writer, options PrintOptions) error {
return nil return nil
} }
func printPodTemplate(pod *api.PodTemplate, w io.Writer, options PrintOptions) error { func printPodTemplate(pod *api.PodTemplate, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, pod.Name, options.WithKind) name := formatResourceName(options.Kind, pod.Name, options.WithKind)
namespace := pod.Namespace namespace := pod.Namespace
@ -490,7 +386,7 @@ func printPodTemplate(pod *api.PodTemplate, w io.Writer, options PrintOptions) e
return nil return nil
} }
func printPodTemplateList(podList *api.PodTemplateList, w io.Writer, options PrintOptions) error { func printPodTemplateList(podList *api.PodTemplateList, w io.Writer, options printers.PrintOptions) error {
for _, pod := range podList.Items { for _, pod := range podList.Items {
if err := printPodTemplate(&pod, w, options); err != nil { if err := printPodTemplate(&pod, w, options); err != nil {
return err return err
@ -499,7 +395,7 @@ func printPodTemplateList(podList *api.PodTemplateList, w io.Writer, options Pri
return nil return nil
} }
func printPodDisruptionBudget(pdb *policy.PodDisruptionBudget, w io.Writer, options PrintOptions) error { func printPodDisruptionBudget(pdb *policy.PodDisruptionBudget, w io.Writer, options printers.PrintOptions) error {
// name, minavailable, selector // name, minavailable, selector
name := formatResourceName(options.Kind, pdb.Name, options.WithKind) name := formatResourceName(options.Kind, pdb.Name, options.WithKind)
namespace := pdb.Namespace namespace := pdb.Namespace
@ -521,7 +417,7 @@ func printPodDisruptionBudget(pdb *policy.PodDisruptionBudget, w io.Writer, opti
return nil return nil
} }
func printPodDisruptionBudgetList(pdbList *policy.PodDisruptionBudgetList, w io.Writer, options PrintOptions) error { func printPodDisruptionBudgetList(pdbList *policy.PodDisruptionBudgetList, w io.Writer, options printers.PrintOptions) error {
for _, pdb := range pdbList.Items { for _, pdb := range pdbList.Items {
if err := printPodDisruptionBudget(&pdb, w, options); err != nil { if err := printPodDisruptionBudget(&pdb, w, options); err != nil {
return err return err
@ -531,7 +427,7 @@ func printPodDisruptionBudgetList(pdbList *policy.PodDisruptionBudgetList, w io.
} }
// TODO(AdoHe): try to put wide output in a single method // TODO(AdoHe): try to put wide output in a single method
func printReplicationController(controller *api.ReplicationController, w io.Writer, options PrintOptions) error { func printReplicationController(controller *api.ReplicationController, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, controller.Name, options.WithKind) name := formatResourceName(options.Kind, controller.Name, options.WithKind)
namespace := controller.Namespace namespace := controller.Namespace
@ -574,7 +470,7 @@ func printReplicationController(controller *api.ReplicationController, w io.Writ
return nil return nil
} }
func printReplicationControllerList(list *api.ReplicationControllerList, w io.Writer, options PrintOptions) error { func printReplicationControllerList(list *api.ReplicationControllerList, w io.Writer, options printers.PrintOptions) error {
for _, controller := range list.Items { for _, controller := range list.Items {
if err := printReplicationController(&controller, w, options); err != nil { if err := printReplicationController(&controller, w, options); err != nil {
return err return err
@ -583,7 +479,7 @@ func printReplicationControllerList(list *api.ReplicationControllerList, w io.Wr
return nil return nil
} }
func printReplicaSet(rs *extensions.ReplicaSet, w io.Writer, options PrintOptions) error { func printReplicaSet(rs *extensions.ReplicaSet, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, rs.Name, options.WithKind) name := formatResourceName(options.Kind, rs.Name, options.WithKind)
namespace := rs.Namespace namespace := rs.Namespace
@ -625,7 +521,7 @@ func printReplicaSet(rs *extensions.ReplicaSet, w io.Writer, options PrintOption
return nil return nil
} }
func printReplicaSetList(list *extensions.ReplicaSetList, w io.Writer, options PrintOptions) error { func printReplicaSetList(list *extensions.ReplicaSetList, w io.Writer, options printers.PrintOptions) error {
for _, rs := range list.Items { for _, rs := range list.Items {
if err := printReplicaSet(&rs, w, options); err != nil { if err := printReplicaSet(&rs, w, options); err != nil {
return err return err
@ -634,7 +530,7 @@ func printReplicaSetList(list *extensions.ReplicaSetList, w io.Writer, options P
return nil return nil
} }
func printCluster(c *federation.Cluster, w io.Writer, options PrintOptions) error { func printCluster(c *federation.Cluster, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, c.Name, options.WithKind) name := formatResourceName(options.Kind, c.Name, options.WithKind)
var statuses []string var statuses []string
@ -658,7 +554,7 @@ func printCluster(c *federation.Cluster, w io.Writer, options PrintOptions) erro
} }
return nil return nil
} }
func printClusterList(list *federation.ClusterList, w io.Writer, options PrintOptions) error { func printClusterList(list *federation.ClusterList, w io.Writer, options printers.PrintOptions) error {
for _, rs := range list.Items { for _, rs := range list.Items {
if err := printCluster(&rs, w, options); err != nil { if err := printCluster(&rs, w, options); err != nil {
return err return err
@ -667,7 +563,7 @@ func printClusterList(list *federation.ClusterList, w io.Writer, options PrintOp
return nil return nil
} }
func printJob(job *batch.Job, w io.Writer, options PrintOptions) error { func printJob(job *batch.Job, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, job.Name, options.WithKind) name := formatResourceName(options.Kind, job.Name, options.WithKind)
namespace := job.Namespace namespace := job.Namespace
@ -721,7 +617,7 @@ func printJob(job *batch.Job, w io.Writer, options PrintOptions) error {
return nil return nil
} }
func printJobList(list *batch.JobList, w io.Writer, options PrintOptions) error { func printJobList(list *batch.JobList, w io.Writer, options printers.PrintOptions) error {
for _, job := range list.Items { for _, job := range list.Items {
if err := printJob(&job, w, options); err != nil { if err := printJob(&job, w, options); err != nil {
return err return err
@ -730,7 +626,7 @@ func printJobList(list *batch.JobList, w io.Writer, options PrintOptions) error
return nil return nil
} }
func printCronJob(cronJob *batch.CronJob, w io.Writer, options PrintOptions) error { func printCronJob(cronJob *batch.CronJob, w io.Writer, options printers.PrintOptions) error {
name := cronJob.Name name := cronJob.Name
namespace := cronJob.Namespace namespace := cronJob.Namespace
@ -757,7 +653,7 @@ func printCronJob(cronJob *batch.CronJob, w io.Writer, options PrintOptions) err
return nil return nil
} }
func printCronJobList(list *batch.CronJobList, w io.Writer, options PrintOptions) error { func printCronJobList(list *batch.CronJobList, w io.Writer, options printers.PrintOptions) error {
for _, cronJob := range list.Items { for _, cronJob := range list.Items {
if err := printCronJob(&cronJob, w, options); err != nil { if err := printCronJob(&cronJob, w, options); err != nil {
return err return err
@ -825,7 +721,7 @@ func makePortString(ports []api.ServicePort) string {
return strings.Join(pieces, ",") return strings.Join(pieces, ",")
} }
func printService(svc *api.Service, w io.Writer, options PrintOptions) error { func printService(svc *api.Service, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, svc.Name, options.WithKind) name := formatResourceName(options.Kind, svc.Name, options.WithKind)
namespace := svc.Namespace namespace := svc.Namespace
@ -859,7 +755,7 @@ func printService(svc *api.Service, w io.Writer, options PrintOptions) error {
return err return err
} }
func printServiceList(list *api.ServiceList, w io.Writer, options PrintOptions) error { func printServiceList(list *api.ServiceList, w io.Writer, options printers.PrintOptions) error {
for _, svc := range list.Items { for _, svc := range list.Items {
if err := printService(&svc, w, options); err != nil { if err := printService(&svc, w, options); err != nil {
return err return err
@ -905,7 +801,7 @@ func formatPorts(tls []extensions.IngressTLS) string {
return "80" return "80"
} }
func printIngress(ingress *extensions.Ingress, w io.Writer, options PrintOptions) error { func printIngress(ingress *extensions.Ingress, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, ingress.Name, options.WithKind) name := formatResourceName(options.Kind, ingress.Name, options.WithKind)
namespace := ingress.Namespace namespace := ingress.Namespace
@ -935,7 +831,7 @@ func printIngress(ingress *extensions.Ingress, w io.Writer, options PrintOptions
return nil return nil
} }
func printIngressList(ingressList *extensions.IngressList, w io.Writer, options PrintOptions) error { func printIngressList(ingressList *extensions.IngressList, w io.Writer, options printers.PrintOptions) error {
for _, ingress := range ingressList.Items { for _, ingress := range ingressList.Items {
if err := printIngress(&ingress, w, options); err != nil { if err := printIngress(&ingress, w, options); err != nil {
return err return err
@ -944,7 +840,7 @@ func printIngressList(ingressList *extensions.IngressList, w io.Writer, options
return nil return nil
} }
func printStatefulSet(ps *apps.StatefulSet, w io.Writer, options PrintOptions) error { func printStatefulSet(ps *apps.StatefulSet, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, ps.Name, options.WithKind) name := formatResourceName(options.Kind, ps.Name, options.WithKind)
namespace := ps.Namespace namespace := ps.Namespace
@ -983,7 +879,7 @@ func printStatefulSet(ps *apps.StatefulSet, w io.Writer, options PrintOptions) e
return nil return nil
} }
func printStatefulSetList(statefulSetList *apps.StatefulSetList, w io.Writer, options PrintOptions) error { func printStatefulSetList(statefulSetList *apps.StatefulSetList, w io.Writer, options printers.PrintOptions) error {
for _, ps := range statefulSetList.Items { for _, ps := range statefulSetList.Items {
if err := printStatefulSet(&ps, w, options); err != nil { if err := printStatefulSet(&ps, w, options); err != nil {
return err return err
@ -992,7 +888,7 @@ func printStatefulSetList(statefulSetList *apps.StatefulSetList, w io.Writer, op
return nil return nil
} }
func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, options PrintOptions) error { func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, ds.Name, options.WithKind) name := formatResourceName(options.Kind, ds.Name, options.WithKind)
namespace := ds.Namespace namespace := ds.Namespace
@ -1041,7 +937,7 @@ func printDaemonSet(ds *extensions.DaemonSet, w io.Writer, options PrintOptions)
return nil return nil
} }
func printDaemonSetList(list *extensions.DaemonSetList, w io.Writer, options PrintOptions) error { func printDaemonSetList(list *extensions.DaemonSetList, w io.Writer, options printers.PrintOptions) error {
for _, ds := range list.Items { for _, ds := range list.Items {
if err := printDaemonSet(&ds, w, options); err != nil { if err := printDaemonSet(&ds, w, options); err != nil {
return err return err
@ -1050,7 +946,7 @@ func printDaemonSetList(list *extensions.DaemonSetList, w io.Writer, options Pri
return nil return nil
} }
func printEndpoints(endpoints *api.Endpoints, w io.Writer, options PrintOptions) error { func printEndpoints(endpoints *api.Endpoints, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, endpoints.Name, options.WithKind) name := formatResourceName(options.Kind, endpoints.Name, options.WithKind)
namespace := endpoints.Namespace namespace := endpoints.Namespace
@ -1070,7 +966,7 @@ func printEndpoints(endpoints *api.Endpoints, w io.Writer, options PrintOptions)
return err return err
} }
func printEndpointsList(list *api.EndpointsList, w io.Writer, options PrintOptions) error { func printEndpointsList(list *api.EndpointsList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printEndpoints(&item, w, options); err != nil { if err := printEndpoints(&item, w, options); err != nil {
return err return err
@ -1079,7 +975,7 @@ func printEndpointsList(list *api.EndpointsList, w io.Writer, options PrintOptio
return nil return nil
} }
func printNamespace(item *api.Namespace, w io.Writer, options PrintOptions) error { func printNamespace(item *api.Namespace, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, item.Name, options.WithKind) name := formatResourceName(options.Kind, item.Name, options.WithKind)
if options.WithNamespace { if options.WithNamespace {
@ -1096,7 +992,7 @@ func printNamespace(item *api.Namespace, w io.Writer, options PrintOptions) erro
return err return err
} }
func printNamespaceList(list *api.NamespaceList, w io.Writer, options PrintOptions) error { func printNamespaceList(list *api.NamespaceList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printNamespace(&item, w, options); err != nil { if err := printNamespace(&item, w, options); err != nil {
return err return err
@ -1105,7 +1001,7 @@ func printNamespaceList(list *api.NamespaceList, w io.Writer, options PrintOptio
return nil return nil
} }
func printSecret(item *api.Secret, w io.Writer, options PrintOptions) error { func printSecret(item *api.Secret, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, item.Name, options.WithKind) name := formatResourceName(options.Kind, item.Name, options.WithKind)
namespace := item.Namespace namespace := item.Namespace
@ -1125,7 +1021,7 @@ func printSecret(item *api.Secret, w io.Writer, options PrintOptions) error {
return err return err
} }
func printSecretList(list *api.SecretList, w io.Writer, options PrintOptions) error { func printSecretList(list *api.SecretList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printSecret(&item, w, options); err != nil { if err := printSecret(&item, w, options); err != nil {
return err return err
@ -1135,7 +1031,7 @@ func printSecretList(list *api.SecretList, w io.Writer, options PrintOptions) er
return nil return nil
} }
func printServiceAccount(item *api.ServiceAccount, w io.Writer, options PrintOptions) error { func printServiceAccount(item *api.ServiceAccount, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, item.Name, options.WithKind) name := formatResourceName(options.Kind, item.Name, options.WithKind)
namespace := item.Namespace namespace := item.Namespace
@ -1155,7 +1051,7 @@ func printServiceAccount(item *api.ServiceAccount, w io.Writer, options PrintOpt
return err return err
} }
func printServiceAccountList(list *api.ServiceAccountList, w io.Writer, options PrintOptions) error { func printServiceAccountList(list *api.ServiceAccountList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printServiceAccount(&item, w, options); err != nil { if err := printServiceAccount(&item, w, options); err != nil {
return err return err
@ -1165,7 +1061,7 @@ func printServiceAccountList(list *api.ServiceAccountList, w io.Writer, options
return nil return nil
} }
func printNode(node *api.Node, w io.Writer, options PrintOptions) error { func printNode(node *api.Node, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, node.Name, options.WithKind) name := formatResourceName(options.Kind, node.Name, options.WithKind)
if options.WithNamespace { if options.WithNamespace {
@ -1249,7 +1145,7 @@ func findNodeRole(node *api.Node) string {
return "" return ""
} }
func printNodeList(list *api.NodeList, w io.Writer, options PrintOptions) error { func printNodeList(list *api.NodeList, w io.Writer, options printers.PrintOptions) error {
for _, node := range list.Items { for _, node := range list.Items {
if err := printNode(&node, w, options); err != nil { if err := printNode(&node, w, options); err != nil {
return err return err
@ -1258,7 +1154,7 @@ func printNodeList(list *api.NodeList, w io.Writer, options PrintOptions) error
return nil return nil
} }
func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, options PrintOptions) error { func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, pv.Name, options.WithKind) name := formatResourceName(options.Kind, pv.Name, options.WithKind)
if options.WithNamespace { if options.WithNamespace {
@ -1296,7 +1192,7 @@ func printPersistentVolume(pv *api.PersistentVolume, w io.Writer, options PrintO
return err return err
} }
func printPersistentVolumeList(list *api.PersistentVolumeList, w io.Writer, options PrintOptions) error { func printPersistentVolumeList(list *api.PersistentVolumeList, w io.Writer, options printers.PrintOptions) error {
for _, pv := range list.Items { for _, pv := range list.Items {
if err := printPersistentVolume(&pv, w, options); err != nil { if err := printPersistentVolume(&pv, w, options); err != nil {
return err return err
@ -1305,7 +1201,7 @@ func printPersistentVolumeList(list *api.PersistentVolumeList, w io.Writer, opti
return nil return nil
} }
func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer, options PrintOptions) error { func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, pvc.Name, options.WithKind) name := formatResourceName(options.Kind, pvc.Name, options.WithKind)
namespace := pvc.Namespace namespace := pvc.Namespace
@ -1336,7 +1232,7 @@ func printPersistentVolumeClaim(pvc *api.PersistentVolumeClaim, w io.Writer, opt
return err return err
} }
func printPersistentVolumeClaimList(list *api.PersistentVolumeClaimList, w io.Writer, options PrintOptions) error { func printPersistentVolumeClaimList(list *api.PersistentVolumeClaimList, w io.Writer, options printers.PrintOptions) error {
for _, psd := range list.Items { for _, psd := range list.Items {
if err := printPersistentVolumeClaim(&psd, w, options); err != nil { if err := printPersistentVolumeClaim(&psd, w, options); err != nil {
return err return err
@ -1345,7 +1241,7 @@ func printPersistentVolumeClaimList(list *api.PersistentVolumeClaimList, w io.Wr
return nil return nil
} }
func printEvent(event *api.Event, w io.Writer, options PrintOptions) error { func printEvent(event *api.Event, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, event.InvolvedObject.Name, options.WithKind) name := formatResourceName(options.Kind, event.InvolvedObject.Name, options.WithKind)
namespace := event.Namespace namespace := event.Namespace
@ -1388,7 +1284,7 @@ func printEvent(event *api.Event, w io.Writer, options PrintOptions) error {
} }
// Sorts and prints the EventList in a human-friendly format. // Sorts and prints the EventList in a human-friendly format.
func printEventList(list *api.EventList, w io.Writer, options PrintOptions) error { func printEventList(list *api.EventList, w io.Writer, options printers.PrintOptions) error {
sort.Sort(events.SortableEvents(list.Items)) sort.Sort(events.SortableEvents(list.Items))
for i := range list.Items { for i := range list.Items {
if err := printEvent(&list.Items[i], w, options); err != nil { if err := printEvent(&list.Items[i], w, options); err != nil {
@ -1398,12 +1294,12 @@ func printEventList(list *api.EventList, w io.Writer, options PrintOptions) erro
return nil return nil
} }
func printLimitRange(limitRange *api.LimitRange, w io.Writer, options PrintOptions) error { func printLimitRange(limitRange *api.LimitRange, w io.Writer, options printers.PrintOptions) error {
return printObjectMeta(limitRange.ObjectMeta, w, options, true) return printObjectMeta(limitRange.ObjectMeta, w, options, true)
} }
// Prints the LimitRangeList in a human-friendly format. // Prints the LimitRangeList in a human-friendly format.
func printLimitRangeList(list *api.LimitRangeList, w io.Writer, options PrintOptions) error { func printLimitRangeList(list *api.LimitRangeList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printLimitRange(&list.Items[i], w, options); err != nil { if err := printLimitRange(&list.Items[i], w, options); err != nil {
return err return err
@ -1413,7 +1309,7 @@ func printLimitRangeList(list *api.LimitRangeList, w io.Writer, options PrintOpt
} }
// printObjectMeta prints the object metadata of a given resource. // printObjectMeta prints the object metadata of a given resource.
func printObjectMeta(meta metav1.ObjectMeta, w io.Writer, options PrintOptions, namespaced bool) error { func printObjectMeta(meta metav1.ObjectMeta, w io.Writer, options printers.PrintOptions, namespaced bool) error {
name := formatResourceName(options.Kind, meta.Name, options.WithKind) name := formatResourceName(options.Kind, meta.Name, options.WithKind)
if namespaced && options.WithNamespace { if namespaced && options.WithNamespace {
@ -1436,12 +1332,12 @@ func printObjectMeta(meta metav1.ObjectMeta, w io.Writer, options PrintOptions,
return err return err
} }
func printResourceQuota(resourceQuota *api.ResourceQuota, w io.Writer, options PrintOptions) error { func printResourceQuota(resourceQuota *api.ResourceQuota, w io.Writer, options printers.PrintOptions) error {
return printObjectMeta(resourceQuota.ObjectMeta, w, options, true) return printObjectMeta(resourceQuota.ObjectMeta, w, options, true)
} }
// Prints the ResourceQuotaList in a human-friendly format. // Prints the ResourceQuotaList in a human-friendly format.
func printResourceQuotaList(list *api.ResourceQuotaList, w io.Writer, options PrintOptions) error { func printResourceQuotaList(list *api.ResourceQuotaList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printResourceQuota(&list.Items[i], w, options); err != nil { if err := printResourceQuota(&list.Items[i], w, options); err != nil {
return err return err
@ -1450,12 +1346,12 @@ func printResourceQuotaList(list *api.ResourceQuotaList, w io.Writer, options Pr
return nil return nil
} }
func printRole(role *rbac.Role, w io.Writer, options PrintOptions) error { func printRole(role *rbac.Role, w io.Writer, options printers.PrintOptions) error {
return printObjectMeta(role.ObjectMeta, w, options, true) return printObjectMeta(role.ObjectMeta, w, options, true)
} }
// Prints the Role in a human-friendly format. // Prints the Role in a human-friendly format.
func printRoleList(list *rbac.RoleList, w io.Writer, options PrintOptions) error { func printRoleList(list *rbac.RoleList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printRole(&list.Items[i], w, options); err != nil { if err := printRole(&list.Items[i], w, options); err != nil {
return err return err
@ -1464,7 +1360,7 @@ func printRoleList(list *rbac.RoleList, w io.Writer, options PrintOptions) error
return nil return nil
} }
func printRoleBinding(roleBinding *rbac.RoleBinding, w io.Writer, options PrintOptions) error { func printRoleBinding(roleBinding *rbac.RoleBinding, w io.Writer, options printers.PrintOptions) error {
meta := roleBinding.ObjectMeta meta := roleBinding.ObjectMeta
name := formatResourceName(options.Kind, meta.Name, options.WithKind) name := formatResourceName(options.Kind, meta.Name, options.WithKind)
@ -1503,7 +1399,7 @@ func printRoleBinding(roleBinding *rbac.RoleBinding, w io.Writer, options PrintO
} }
// Prints the RoleBinding in a human-friendly format. // Prints the RoleBinding in a human-friendly format.
func printRoleBindingList(list *rbac.RoleBindingList, w io.Writer, options PrintOptions) error { func printRoleBindingList(list *rbac.RoleBindingList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printRoleBinding(&list.Items[i], w, options); err != nil { if err := printRoleBinding(&list.Items[i], w, options); err != nil {
return err return err
@ -1512,7 +1408,7 @@ func printRoleBindingList(list *rbac.RoleBindingList, w io.Writer, options Print
return nil return nil
} }
func printClusterRole(clusterRole *rbac.ClusterRole, w io.Writer, options PrintOptions) error { func printClusterRole(clusterRole *rbac.ClusterRole, w io.Writer, options printers.PrintOptions) error {
if options.WithNamespace { if options.WithNamespace {
return fmt.Errorf("clusterRole is not namespaced") return fmt.Errorf("clusterRole is not namespaced")
} }
@ -1520,7 +1416,7 @@ func printClusterRole(clusterRole *rbac.ClusterRole, w io.Writer, options PrintO
} }
// Prints the ClusterRole in a human-friendly format. // Prints the ClusterRole in a human-friendly format.
func printClusterRoleList(list *rbac.ClusterRoleList, w io.Writer, options PrintOptions) error { func printClusterRoleList(list *rbac.ClusterRoleList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printClusterRole(&list.Items[i], w, options); err != nil { if err := printClusterRole(&list.Items[i], w, options); err != nil {
return err return err
@ -1529,7 +1425,7 @@ func printClusterRoleList(list *rbac.ClusterRoleList, w io.Writer, options Print
return nil return nil
} }
func printClusterRoleBinding(clusterRoleBinding *rbac.ClusterRoleBinding, w io.Writer, options PrintOptions) error { func printClusterRoleBinding(clusterRoleBinding *rbac.ClusterRoleBinding, w io.Writer, options printers.PrintOptions) error {
meta := clusterRoleBinding.ObjectMeta meta := clusterRoleBinding.ObjectMeta
name := formatResourceName(options.Kind, meta.Name, options.WithKind) name := formatResourceName(options.Kind, meta.Name, options.WithKind)
@ -1566,7 +1462,7 @@ func printClusterRoleBinding(clusterRoleBinding *rbac.ClusterRoleBinding, w io.W
} }
// Prints the ClusterRoleBinding in a human-friendly format. // Prints the ClusterRoleBinding in a human-friendly format.
func printClusterRoleBindingList(list *rbac.ClusterRoleBindingList, w io.Writer, options PrintOptions) error { func printClusterRoleBindingList(list *rbac.ClusterRoleBindingList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printClusterRoleBinding(&list.Items[i], w, options); err != nil { if err := printClusterRoleBinding(&list.Items[i], w, options); err != nil {
return err return err
@ -1575,7 +1471,7 @@ func printClusterRoleBindingList(list *rbac.ClusterRoleBindingList, w io.Writer,
return nil return nil
} }
func printCertificateSigningRequest(csr *certificates.CertificateSigningRequest, w io.Writer, options PrintOptions) error { func printCertificateSigningRequest(csr *certificates.CertificateSigningRequest, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, csr.Name, options.WithKind) name := formatResourceName(options.Kind, csr.Name, options.WithKind)
meta := csr.ObjectMeta meta := csr.ObjectMeta
@ -1627,7 +1523,7 @@ func extractCSRStatus(csr *certificates.CertificateSigningRequest) (string, erro
return status, nil return status, nil
} }
func printCertificateSigningRequestList(list *certificates.CertificateSigningRequestList, w io.Writer, options PrintOptions) error { func printCertificateSigningRequestList(list *certificates.CertificateSigningRequestList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printCertificateSigningRequest(&list.Items[i], w, options); err != nil { if err := printCertificateSigningRequest(&list.Items[i], w, options); err != nil {
return err return err
@ -1636,7 +1532,7 @@ func printCertificateSigningRequestList(list *certificates.CertificateSigningReq
return nil return nil
} }
func printComponentStatus(item *api.ComponentStatus, w io.Writer, options PrintOptions) error { func printComponentStatus(item *api.ComponentStatus, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, item.Name, options.WithKind) name := formatResourceName(options.Kind, item.Name, options.WithKind)
if options.WithNamespace { if options.WithNamespace {
@ -1668,7 +1564,7 @@ func printComponentStatus(item *api.ComponentStatus, w io.Writer, options PrintO
return err return err
} }
func printComponentStatusList(list *api.ComponentStatusList, w io.Writer, options PrintOptions) error { func printComponentStatusList(list *api.ComponentStatusList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printComponentStatus(&item, w, options); err != nil { if err := printComponentStatus(&item, w, options); err != nil {
return err return err
@ -1678,7 +1574,7 @@ func printComponentStatusList(list *api.ComponentStatusList, w io.Writer, option
return nil return nil
} }
func printThirdPartyResource(rsrc *extensions.ThirdPartyResource, w io.Writer, options PrintOptions) error { func printThirdPartyResource(rsrc *extensions.ThirdPartyResource, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, rsrc.Name, options.WithKind) name := formatResourceName(options.Kind, rsrc.Name, options.WithKind)
versions := make([]string, len(rsrc.Versions)) versions := make([]string, len(rsrc.Versions))
@ -1693,7 +1589,7 @@ func printThirdPartyResource(rsrc *extensions.ThirdPartyResource, w io.Writer, o
return nil return nil
} }
func printThirdPartyResourceList(list *extensions.ThirdPartyResourceList, w io.Writer, options PrintOptions) error { func printThirdPartyResourceList(list *extensions.ThirdPartyResourceList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printThirdPartyResource(&item, w, options); err != nil { if err := printThirdPartyResource(&item, w, options); err != nil {
return err return err
@ -1710,7 +1606,7 @@ func truncate(str string, maxLen int) string {
return str return str
} }
func printThirdPartyResourceData(rsrc *extensions.ThirdPartyResourceData, w io.Writer, options PrintOptions) error { func printThirdPartyResourceData(rsrc *extensions.ThirdPartyResourceData, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, rsrc.Name, options.WithKind) name := formatResourceName(options.Kind, rsrc.Name, options.WithKind)
l := labels.FormatLabels(rsrc.Labels) l := labels.FormatLabels(rsrc.Labels)
@ -1724,7 +1620,7 @@ func printThirdPartyResourceData(rsrc *extensions.ThirdPartyResourceData, w io.W
return nil return nil
} }
func printThirdPartyResourceDataList(list *extensions.ThirdPartyResourceDataList, w io.Writer, options PrintOptions) error { func printThirdPartyResourceDataList(list *extensions.ThirdPartyResourceDataList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printThirdPartyResourceData(&item, w, options); err != nil { if err := printThirdPartyResourceData(&item, w, options); err != nil {
return err return err
@ -1734,7 +1630,7 @@ func printThirdPartyResourceDataList(list *extensions.ThirdPartyResourceDataList
return nil return nil
} }
func printDeployment(deployment *extensions.Deployment, w io.Writer, options PrintOptions) error { func printDeployment(deployment *extensions.Deployment, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, deployment.Name, options.WithKind) name := formatResourceName(options.Kind, deployment.Name, options.WithKind)
if options.WithNamespace { if options.WithNamespace {
@ -1774,7 +1670,7 @@ func printDeployment(deployment *extensions.Deployment, w io.Writer, options Pri
return err return err
} }
func printDeploymentList(list *extensions.DeploymentList, w io.Writer, options PrintOptions) error { func printDeploymentList(list *extensions.DeploymentList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printDeployment(&item, w, options); err != nil { if err := printDeployment(&item, w, options); err != nil {
return err return err
@ -1843,7 +1739,7 @@ func formatHPAMetrics(specs []autoscaling.MetricSpec, statuses []autoscaling.Met
return ret return ret
} }
func printHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, w io.Writer, options PrintOptions) error { func printHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, w io.Writer, options printers.PrintOptions) error {
namespace := hpa.Namespace namespace := hpa.Namespace
name := formatResourceName(options.Kind, hpa.Name, options.WithKind) name := formatResourceName(options.Kind, hpa.Name, options.WithKind)
@ -1882,7 +1778,7 @@ func printHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, w io
return err return err
} }
func printHorizontalPodAutoscalerList(list *autoscaling.HorizontalPodAutoscalerList, w io.Writer, options PrintOptions) error { func printHorizontalPodAutoscalerList(list *autoscaling.HorizontalPodAutoscalerList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printHorizontalPodAutoscaler(&list.Items[i], w, options); err != nil { if err := printHorizontalPodAutoscaler(&list.Items[i], w, options); err != nil {
return err return err
@ -1891,7 +1787,7 @@ func printHorizontalPodAutoscalerList(list *autoscaling.HorizontalPodAutoscalerL
return nil return nil
} }
func printConfigMap(configMap *api.ConfigMap, w io.Writer, options PrintOptions) error { func printConfigMap(configMap *api.ConfigMap, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, configMap.Name, options.WithKind) name := formatResourceName(options.Kind, configMap.Name, options.WithKind)
namespace := configMap.Namespace namespace := configMap.Namespace
@ -1911,7 +1807,7 @@ func printConfigMap(configMap *api.ConfigMap, w io.Writer, options PrintOptions)
return err return err
} }
func printConfigMapList(list *api.ConfigMapList, w io.Writer, options PrintOptions) error { func printConfigMapList(list *api.ConfigMapList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printConfigMap(&list.Items[i], w, options); err != nil { if err := printConfigMap(&list.Items[i], w, options); err != nil {
return err return err
@ -1920,7 +1816,7 @@ func printConfigMapList(list *api.ConfigMapList, w io.Writer, options PrintOptio
return nil return nil
} }
func printPodSecurityPolicy(item *extensions.PodSecurityPolicy, w io.Writer, options PrintOptions) error { func printPodSecurityPolicy(item *extensions.PodSecurityPolicy, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, item.Name, options.WithKind) name := formatResourceName(options.Kind, item.Name, options.WithKind)
_, err := fmt.Fprintf(w, "%s\t%t\t%v\t%s\t%s\t%s\t%s\t%t\t%v\n", name, item.Spec.Privileged, _, err := fmt.Fprintf(w, "%s\t%t\t%v\t%s\t%s\t%s\t%s\t%t\t%v\n", name, item.Spec.Privileged,
@ -1929,7 +1825,7 @@ func printPodSecurityPolicy(item *extensions.PodSecurityPolicy, w io.Writer, opt
return err return err
} }
func printPodSecurityPolicyList(list *extensions.PodSecurityPolicyList, w io.Writer, options PrintOptions) error { func printPodSecurityPolicyList(list *extensions.PodSecurityPolicyList, w io.Writer, options printers.PrintOptions) error {
for _, item := range list.Items { for _, item := range list.Items {
if err := printPodSecurityPolicy(&item, w, options); err != nil { if err := printPodSecurityPolicy(&item, w, options); err != nil {
return err return err
@ -1939,7 +1835,7 @@ func printPodSecurityPolicyList(list *extensions.PodSecurityPolicyList, w io.Wri
return nil return nil
} }
func printNetworkPolicy(networkPolicy *extensions.NetworkPolicy, w io.Writer, options PrintOptions) error { func printNetworkPolicy(networkPolicy *extensions.NetworkPolicy, w io.Writer, options printers.PrintOptions) error {
name := formatResourceName(options.Kind, networkPolicy.Name, options.WithKind) name := formatResourceName(options.Kind, networkPolicy.Name, options.WithKind)
namespace := networkPolicy.Namespace namespace := networkPolicy.Namespace
@ -1959,7 +1855,7 @@ func printNetworkPolicy(networkPolicy *extensions.NetworkPolicy, w io.Writer, op
return err return err
} }
func printNetworkPolicyList(list *extensions.NetworkPolicyList, w io.Writer, options PrintOptions) error { func printNetworkPolicyList(list *extensions.NetworkPolicyList, w io.Writer, options printers.PrintOptions) error {
for i := range list.Items { for i := range list.Items {
if err := printNetworkPolicy(&list.Items[i], w, options); err != nil { if err := printNetworkPolicy(&list.Items[i], w, options); err != nil {
return err return err
@ -1968,7 +1864,7 @@ func printNetworkPolicyList(list *extensions.NetworkPolicyList, w io.Writer, opt
return nil return nil
} }
func printStorageClass(sc *storage.StorageClass, w io.Writer, options PrintOptions) error { func printStorageClass(sc *storage.StorageClass, w io.Writer, options printers.PrintOptions) error {
name := sc.Name name := sc.Name
if storageutil.IsDefaultAnnotation(sc.ObjectMeta) { if storageutil.IsDefaultAnnotation(sc.ObjectMeta) {
@ -1989,7 +1885,7 @@ func printStorageClass(sc *storage.StorageClass, w io.Writer, options PrintOptio
return nil return nil
} }
func printStorageClassList(scList *storage.StorageClassList, w io.Writer, options PrintOptions) error { func printStorageClassList(scList *storage.StorageClassList, w io.Writer, options printers.PrintOptions) error {
for _, sc := range scList.Items { for _, sc := range scList.Items {
if err := printStorageClass(&sc, w, options); err != nil { if err := printStorageClass(&sc, w, options); err != nil {
return err return err
@ -1998,7 +1894,7 @@ func printStorageClassList(scList *storage.StorageClassList, w io.Writer, option
return nil return nil
} }
func printStatus(status *metav1.Status, w io.Writer, options PrintOptions) error { func printStatus(status *metav1.Status, w io.Writer, options printers.PrintOptions) error {
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", status.Status, status.Reason, status.Message); err != nil { if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", status.Status, status.Reason, status.Message); err != nil {
return err return err
} }
@ -2068,149 +1964,6 @@ func layoutContainers(containers []api.Container, w io.Writer) error {
return nil return nil
} }
func formatLabelHeaders(columnLabels []string) []string {
formHead := make([]string, len(columnLabels))
for i, l := range columnLabels {
p := strings.Split(l, "/")
formHead[i] = strings.ToUpper((p[len(p)-1]))
}
return formHead
}
// headers for --show-labels=true
func formatShowLabelsHeader(showLabels bool, t reflect.Type) []string {
if showLabels {
if t.String() != "*api.ThirdPartyResource" && t.String() != "*api.ThirdPartyResourceList" {
return []string{"LABELS"}
}
}
return nil
}
// PrintObj prints the obj in a human-friendly format according to the type of the obj.
func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) error {
// if output is a tabwriter (when it's called by kubectl get), we use it; create a new tabwriter otherwise
w, found := output.(*tabwriter.Writer)
if !found {
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.
obj, _ = DecodeUnknownObject(obj)
t := reflect.TypeOf(obj)
if handler := h.handlerMap[t]; handler != nil {
if !h.options.NoHeaders && t != h.lastType {
headers := handler.columns
if h.options.Wide {
headers = append(headers, handler.columnsWithWide...)
}
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
}
args := []reflect.Value{reflect.ValueOf(obj), reflect.ValueOf(w), reflect.ValueOf(h.options)}
resultValue := handler.printFunc.Call(args)[0]
if resultValue.IsNil() {
return nil
}
return resultValue.Interface().(error)
}
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
}
// 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 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
}
}
content := unstructured.UnstructuredContent()
kind := "<missing>"
if objKind, ok := content["kind"]; ok {
if str, ok := objKind.(string); ok {
kind = str
}
}
if objAPIVersion, ok := content["apiVersion"]; ok {
if str, ok := objAPIVersion.(string); ok {
version, err := schema.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
}
func tabbedString(f func(io.Writer) error) (string, error) {
out := new(tabwriter.Writer)
buf := &bytes.Buffer{}
out.Init(buf, 0, 8, 1, '\t', 0)
err := f(out)
if err != nil {
return "", err
}
out.Flush()
str := string(buf.String())
return str, nil
}
// formatEventSource formats EventSource as a comma separated string excluding Host when empty // formatEventSource formats EventSource as a comma separated string excluding Host when empty
func formatEventSource(es api.EventSource) string { func formatEventSource(es api.EventSource) string {
EventSourceString := []string{es.Component} EventSourceString := []string{es.Component}

View File

@ -26,8 +26,11 @@ import (
"testing" "testing"
"time" "time"
"github.com/ghodss/yaml"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
yamlserializer "k8s.io/apimachinery/pkg/runtime/serializer/yaml" yamlserializer "k8s.io/apimachinery/pkg/runtime/serializer/yaml"
@ -42,8 +45,7 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/policy"
kubectltesting "k8s.io/kubernetes/pkg/kubectl/testing" kubectltesting "k8s.io/kubernetes/pkg/kubectl/testing"
"k8s.io/kubernetes/pkg/printers"
"github.com/ghodss/yaml"
) )
func init() { func init() {
@ -60,8 +62,8 @@ var testData = kubectltesting.TestStruct{
func TestVersionedPrinter(t *testing.T) { func TestVersionedPrinter(t *testing.T) {
original := &kubectltesting.TestStruct{Key: "value"} original := &kubectltesting.TestStruct{Key: "value"}
p := NewVersionedPrinter( p := printers.NewVersionedPrinter(
ResourcePrinterFunc(func(obj runtime.Object, w io.Writer) error { printers.ResourcePrinterFunc(func(obj runtime.Object, w io.Writer) error {
if obj == original { if obj == original {
t.Fatalf("object should not be identical: %#v", obj) t.Fatalf("object should not be identical: %#v", obj)
} }
@ -79,7 +81,7 @@ func TestVersionedPrinter(t *testing.T) {
} }
func TestPrintDefault(t *testing.T) { func TestPrintDefault(t *testing.T) {
printer, found, err := GetPrinter("", "", false, false) printer, found, err := printers.GetStandardPrinter("", "", false, false, nil, nil, nil)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %#v", err) t.Fatalf("unexpected error: %#v", err)
} }
@ -134,12 +136,12 @@ func TestPrinter(t *testing.T) {
} }
for _, test := range printerTests { for _, test := range printerTests {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
printer, generic, err := GetPrinter(test.Format, test.FormatArgument, false, true) printer, generic, err := printers.GetStandardPrinter(test.Format, test.FormatArgument, false, true, api.Registry.RESTMapper(api.Registry.EnabledVersions()...), api.Scheme, []runtime.Decoder{api.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme})
if err != nil { if err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err) t.Errorf("in %s, unexpected error: %#v", test.Name, err)
} }
if generic && len(test.OutputVersions) > 0 { if generic && len(test.OutputVersions) > 0 {
printer = NewVersionedPrinter(printer, api.Scheme, test.OutputVersions...) printer = printers.NewVersionedPrinter(printer, api.Scheme, test.OutputVersions...)
} }
if err := printer.PrintObj(test.Input, buf); err != nil { if err := printer.PrintObj(test.Input, buf); err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err) t.Errorf("in %s, unexpected error: %#v", test.Name, err)
@ -164,14 +166,14 @@ func TestBadPrinter(t *testing.T) {
{"bad jsonpath", "jsonpath", "{.Name", fmt.Errorf("error parsing jsonpath {.Name, unclosed action\n")}, {"bad jsonpath", "jsonpath", "{.Name", fmt.Errorf("error parsing jsonpath {.Name, unclosed action\n")},
} }
for _, test := range badPrinterTests { for _, test := range badPrinterTests {
_, _, err := GetPrinter(test.Format, test.FormatArgument, false, false) _, _, err := printers.GetStandardPrinter(test.Format, test.FormatArgument, false, false, api.Registry.RESTMapper(api.Registry.EnabledVersions()...), api.Scheme, []runtime.Decoder{api.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme})
if err == nil || err.Error() != test.Error.Error() { if err == nil || err.Error() != test.Error.Error() {
t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err) t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err)
} }
} }
} }
func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data []byte, v interface{}) error) { func testPrinter(t *testing.T, printer printers.ResourcePrinter, unmarshalFunc func(data []byte, v interface{}) error) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
err := printer.PrintObj(&testData, buf) err := printer.PrintObj(&testData, buf)
@ -216,11 +218,11 @@ func testPrinter(t *testing.T, printer ResourcePrinter, unmarshalFunc func(data
} }
func TestYAMLPrinter(t *testing.T) { func TestYAMLPrinter(t *testing.T) {
testPrinter(t, &YAMLPrinter{}, yaml.Unmarshal) testPrinter(t, &printers.YAMLPrinter{}, yaml.Unmarshal)
} }
func TestJSONPrinter(t *testing.T) { func TestJSONPrinter(t *testing.T) {
testPrinter(t, &JSONPrinter{}, json.Unmarshal) testPrinter(t, &printers.JSONPrinter{}, json.Unmarshal)
} }
func TestFormatResourceName(t *testing.T) { func TestFormatResourceName(t *testing.T) {
@ -240,7 +242,7 @@ func TestFormatResourceName(t *testing.T) {
} }
} }
func PrintCustomType(obj *TestPrintType, w io.Writer, options PrintOptions) error { func PrintCustomType(obj *TestPrintType, w io.Writer, options printers.PrintOptions) error {
data := obj.Data data := obj.Data
kind := options.Kind kind := options.Kind
if options.WithKind { if options.WithKind {
@ -250,13 +252,13 @@ func PrintCustomType(obj *TestPrintType, w io.Writer, options PrintOptions) erro
return err return err
} }
func ErrorPrintHandler(obj *TestPrintType, w io.Writer, options PrintOptions) error { func ErrorPrintHandler(obj *TestPrintType, w io.Writer, options printers.PrintOptions) error {
return fmt.Errorf("ErrorPrintHandler error") return fmt.Errorf("ErrorPrintHandler error")
} }
func TestCustomTypePrinting(t *testing.T) { func TestCustomTypePrinting(t *testing.T) {
columns := []string{"Data"} columns := []string{"Data"}
printer := NewHumanReadablePrinter(PrintOptions{}) printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer.Handler(columns, nil, PrintCustomType) printer.Handler(columns, nil, PrintCustomType)
obj := TestPrintType{"test object"} obj := TestPrintType{"test object"}
@ -273,7 +275,7 @@ func TestCustomTypePrinting(t *testing.T) {
func TestCustomTypePrintingWithKind(t *testing.T) { func TestCustomTypePrintingWithKind(t *testing.T) {
columns := []string{"Data"} columns := []string{"Data"}
printer := NewHumanReadablePrinter(PrintOptions{}) printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer.Handler(columns, nil, PrintCustomType) printer.Handler(columns, nil, PrintCustomType)
printer.EnsurePrintWithKind("test") printer.EnsurePrintWithKind("test")
@ -291,7 +293,7 @@ func TestCustomTypePrintingWithKind(t *testing.T) {
func TestPrintHandlerError(t *testing.T) { func TestPrintHandlerError(t *testing.T) {
columns := []string{"Data"} columns := []string{"Data"}
printer := NewHumanReadablePrinter(PrintOptions{}) printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer.Handler(columns, nil, ErrorPrintHandler) printer.Handler(columns, nil, ErrorPrintHandler)
obj := TestPrintType{"test object"} obj := TestPrintType{"test object"}
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
@ -302,7 +304,7 @@ func TestPrintHandlerError(t *testing.T) {
} }
func TestUnknownTypePrinting(t *testing.T) { func TestUnknownTypePrinting(t *testing.T) {
printer := NewHumanReadablePrinter(PrintOptions{}) printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
err := printer.PrintObj(&TestUnknownType{}, buffer) err := printer.PrintObj(&TestUnknownType{}, buffer)
if err == nil { if err == nil {
@ -312,7 +314,7 @@ func TestUnknownTypePrinting(t *testing.T) {
func TestTemplatePanic(t *testing.T) { func TestTemplatePanic(t *testing.T) {
tmpl := `{{and ((index .currentState.info "foo").state.running.startedAt) .currentState.info.net.state.running.startedAt}}` tmpl := `{{and ((index .currentState.info "foo").state.running.startedAt) .currentState.info.net.state.running.startedAt}}`
printer, err := NewTemplatePrinter([]byte(tmpl)) printer, err := printers.NewTemplatePrinter([]byte(tmpl))
if err != nil { if err != nil {
t.Fatalf("tmpl fail: %v", err) t.Fatalf("tmpl fail: %v", err)
} }
@ -357,7 +359,7 @@ func TestNamePrinter(t *testing.T) {
}, },
"pod/foo\npod/bar\n"}, "pod/foo\npod/bar\n"},
} }
printer, _, _ := GetPrinter("name", "", false, false) printer, _, _ := printers.GetStandardPrinter("name", "", false, false, api.Registry.RESTMapper(api.Registry.EnabledVersions()...), api.Scheme, []runtime.Decoder{api.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme})
for name, item := range tests { for name, item := range tests {
buff := &bytes.Buffer{} buff := &bytes.Buffer{}
err := printer.PrintObj(item.obj, buff) err := printer.PrintObj(item.obj, buff)
@ -467,12 +469,12 @@ func TestTemplateStrings(t *testing.T) {
} }
// The point of this test is to verify that the below template works. // The point of this test is to verify that the below template works.
tmpl := `{{if (exists . "status" "containerStatuses")}}{{range .status.containerStatuses}}{{if (and (eq .name "foo") (exists . "state" "running"))}}true{{end}}{{end}}{{end}}` tmpl := `{{if (exists . "status" "containerStatuses")}}{{range .status.containerStatuses}}{{if (and (eq .name "foo") (exists . "state" "running"))}}true{{end}}{{end}}{{end}}`
p, err := NewTemplatePrinter([]byte(tmpl)) p, err := printers.NewTemplatePrinter([]byte(tmpl))
if err != nil { if err != nil {
t.Fatalf("tmpl fail: %v", err) t.Fatalf("tmpl fail: %v", err)
} }
printer := NewVersionedPrinter(p, api.Scheme, api.Registry.GroupOrDie(api.GroupName).GroupVersion) printer := printers.NewVersionedPrinter(p, api.Scheme, api.Registry.GroupOrDie(api.GroupName).GroupVersion)
for name, item := range table { for name, item := range table {
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
@ -496,44 +498,47 @@ func TestPrinters(t *testing.T) {
var ( var (
err error err error
templatePrinter ResourcePrinter templatePrinter printers.ResourcePrinter
templatePrinter2 ResourcePrinter templatePrinter2 printers.ResourcePrinter
jsonpathPrinter ResourcePrinter jsonpathPrinter printers.ResourcePrinter
) )
templatePrinter, err = NewTemplatePrinter([]byte("{{.name}}")) templatePrinter, err = printers.NewTemplatePrinter([]byte("{{.name}}"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
templatePrinter = NewVersionedPrinter(templatePrinter, api.Scheme, v1.SchemeGroupVersion) templatePrinter = printers.NewVersionedPrinter(templatePrinter, api.Scheme, v1.SchemeGroupVersion)
templatePrinter2, err = NewTemplatePrinter([]byte("{{len .items}}")) templatePrinter2, err = printers.NewTemplatePrinter([]byte("{{len .items}}"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
templatePrinter2 = NewVersionedPrinter(templatePrinter2, api.Scheme, v1.SchemeGroupVersion) templatePrinter2 = printers.NewVersionedPrinter(templatePrinter2, api.Scheme, v1.SchemeGroupVersion)
jsonpathPrinter, err = NewJSONPathPrinter("{.metadata.name}") jsonpathPrinter, err = printers.NewJSONPathPrinter("{.metadata.name}")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
jsonpathPrinter = NewVersionedPrinter(jsonpathPrinter, api.Scheme, v1.SchemeGroupVersion) jsonpathPrinter = printers.NewVersionedPrinter(jsonpathPrinter, api.Scheme, v1.SchemeGroupVersion)
printers := map[string]ResourcePrinter{ allPrinters := map[string]printers.ResourcePrinter{
"humanReadable": NewHumanReadablePrinter(PrintOptions{ "humanReadable": printers.NewHumanReadablePrinter(printers.PrintOptions{
NoHeaders: true, NoHeaders: true,
}), }),
"humanReadableHeaders": NewHumanReadablePrinter(PrintOptions{}), "humanReadableHeaders": printers.NewHumanReadablePrinter(printers.PrintOptions{}),
"json": &JSONPrinter{}, "json": &printers.JSONPrinter{},
"yaml": &YAMLPrinter{}, "yaml": &printers.YAMLPrinter{},
"template": templatePrinter, "template": templatePrinter,
"template2": templatePrinter2, "template2": templatePrinter2,
"jsonpath": jsonpathPrinter, "jsonpath": jsonpathPrinter,
"name": &NamePrinter{ "name": &printers.NamePrinter{
Typer: api.Scheme, Typer: api.Scheme,
Decoder: api.Codecs.UniversalDecoder(), Decoders: []runtime.Decoder{api.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme},
Mapper: api.Registry.RESTMapper(api.Registry.EnabledVersions()...),
}, },
} }
AddHandlers((allPrinters["humanReadable"]).(*printers.HumanReadablePrinter))
AddHandlers((allPrinters["humanReadableHeaders"]).(*printers.HumanReadablePrinter))
objects := map[string]runtime.Object{ objects := map[string]runtime.Object{
"pod": &api.Pod{ObjectMeta: om("pod")}, "pod": &api.Pod{ObjectMeta: om("pod")},
"emptyPodList": &api.PodList{}, "emptyPodList": &api.PodList{},
@ -550,7 +555,7 @@ func TestPrinters(t *testing.T) {
"jsonpath": sets.NewString("emptyPodList", "nonEmptyPodList", "endpoints"), "jsonpath": sets.NewString("emptyPodList", "nonEmptyPodList", "endpoints"),
} }
for pName, p := range printers { for pName, p := range allPrinters {
for oName, obj := range objects { for oName, obj := range objects {
b := &bytes.Buffer{} b := &bytes.Buffer{}
if err := p.PrintObj(obj, b); err != nil { if err := p.PrintObj(obj, b); err != nil {
@ -566,7 +571,8 @@ func TestPrinters(t *testing.T) {
func TestPrintEventsResultSorted(t *testing.T) { func TestPrintEventsResultSorted(t *testing.T) {
// Arrange // Arrange
printer := NewHumanReadablePrinter(PrintOptions{}) printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
AddHandlers(printer)
obj := api.EventList{ obj := api.EventList{
Items: []api.Event{ Items: []api.Event{
@ -610,7 +616,8 @@ func TestPrintEventsResultSorted(t *testing.T) {
} }
func TestPrintNodeStatus(t *testing.T) { func TestPrintNodeStatus(t *testing.T) {
printer := NewHumanReadablePrinter(PrintOptions{}) printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
AddHandlers(printer)
table := []struct { table := []struct {
node api.Node node api.Node
status string status string
@ -729,10 +736,11 @@ func TestPrintNodeStatus(t *testing.T) {
} }
func TestPrintNodeOSImage(t *testing.T) { func TestPrintNodeOSImage(t *testing.T) {
printer := NewHumanReadablePrinter(PrintOptions{ printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
ColumnLabels: []string{}, ColumnLabels: []string{},
Wide: true, Wide: true,
}) })
AddHandlers(printer)
table := []struct { table := []struct {
node api.Node node api.Node
@ -773,10 +781,11 @@ func TestPrintNodeOSImage(t *testing.T) {
} }
func TestPrintNodeKernelVersion(t *testing.T) { func TestPrintNodeKernelVersion(t *testing.T) {
printer := NewHumanReadablePrinter(PrintOptions{ printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
ColumnLabels: []string{}, ColumnLabels: []string{},
Wide: true, Wide: true,
}) })
AddHandlers(printer)
table := []struct { table := []struct {
node api.Node node api.Node
@ -817,9 +826,10 @@ func TestPrintNodeKernelVersion(t *testing.T) {
} }
func TestPrintNodeExternalIP(t *testing.T) { func TestPrintNodeExternalIP(t *testing.T) {
printer := NewHumanReadablePrinter(PrintOptions{ printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
Wide: true, Wide: true,
}) })
AddHandlers(printer)
table := []struct { table := []struct {
node api.Node node api.Node
externalIP string externalIP string
@ -900,7 +910,7 @@ func TestPrintHunmanReadableIngressWithColumnLabels(t *testing.T) {
}, },
} }
buff := bytes.Buffer{} buff := bytes.Buffer{}
printIngress(&ingress, &buff, PrintOptions{ printIngress(&ingress, &buff, printers.PrintOptions{
ColumnLabels: []string{"app_name"}, ColumnLabels: []string{"app_name"},
}) })
output := string(buff.Bytes()) output := string(buff.Bytes())
@ -1025,7 +1035,7 @@ func TestPrintHumanReadableService(t *testing.T) {
for _, svc := range tests { for _, svc := range tests {
for _, wide := range []bool{false, true} { for _, wide := range []bool{false, true} {
buff := bytes.Buffer{} buff := bytes.Buffer{}
printService(&svc, &buff, PrintOptions{Wide: wide}) printService(&svc, &buff, printers.PrintOptions{Wide: wide})
output := string(buff.Bytes()) output := string(buff.Bytes())
ip := svc.Spec.ClusterIP ip := svc.Spec.ClusterIP
if !strings.Contains(output, ip) { if !strings.Contains(output, ip) {
@ -1209,9 +1219,10 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) {
for _, test := range table { for _, test := range table {
if test.isNamespaced { if test.isNamespaced {
// Expect output to include namespace when requested. // Expect output to include namespace when requested.
printer := NewHumanReadablePrinter(PrintOptions{ printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
WithNamespace: true, WithNamespace: true,
}) })
AddHandlers(printer)
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
err := printer.PrintObj(test.obj, buffer) err := printer.PrintObj(test.obj, buffer)
if err != nil { if err != nil {
@ -1223,7 +1234,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) {
} }
} else { } else {
// Expect error when trying to get all namespaces for un-namespaced object. // Expect error when trying to get all namespaces for un-namespaced object.
printer := NewHumanReadablePrinter(PrintOptions{ printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
WithNamespace: true, WithNamespace: true,
}) })
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
@ -1319,9 +1330,8 @@ func TestPrintPod(t *testing.T) {
} }
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
printer := HumanReadablePrinter{}
for _, test := range tests { for _, test := range tests {
printer.printPod(&test.pod, buf, PrintOptions{ShowAll: true}) printPod(&test.pod, buf, printers.PrintOptions{ShowAll: true})
// We ignore time // We ignore time
if !strings.HasPrefix(buf.String(), test.expect) { if !strings.HasPrefix(buf.String(), test.expect) {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
@ -1413,9 +1423,8 @@ func TestPrintNonTerminatedPod(t *testing.T) {
} }
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
printer := HumanReadablePrinter{}
for _, test := range tests { for _, test := range tests {
printer.printPod(&test.pod, buf, PrintOptions{}) printPod(&test.pod, buf, printers.PrintOptions{})
// We ignore time // We ignore time
if !strings.HasPrefix(buf.String(), test.expect) { if !strings.HasPrefix(buf.String(), test.expect) {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
@ -1474,9 +1483,8 @@ func TestPrintPodWithLabels(t *testing.T) {
} }
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
printer := HumanReadablePrinter{}
for _, test := range tests { for _, test := range tests {
printer.printPod(&test.pod, buf, PrintOptions{ColumnLabels: test.labelColumns}) printPod(&test.pod, buf, printers.PrintOptions{ColumnLabels: test.labelColumns})
// We ignore time // We ignore time
if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) { if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) {
t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String()) t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String())
@ -1554,13 +1562,13 @@ func TestPrintDeployment(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printDeployment(&test.deployment, buf, PrintOptions{}) printDeployment(&test.deployment, buf, printers.PrintOptions{})
if buf.String() != test.expect { if buf.String() != test.expect {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
} }
buf.Reset() buf.Reset()
// print deployment with '-o wide' option // print deployment with '-o wide' option
printDeployment(&test.deployment, buf, PrintOptions{Wide: true}) printDeployment(&test.deployment, buf, printers.PrintOptions{Wide: true})
if buf.String() != test.wideExpect { if buf.String() != test.wideExpect {
t.Fatalf("Expected: %s, got: %s", test.wideExpect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.wideExpect, buf.String())
} }
@ -1596,7 +1604,7 @@ func TestPrintDaemonSet(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printDaemonSet(&test.ds, buf, PrintOptions{}) printDaemonSet(&test.ds, buf, printers.PrintOptions{})
if !strings.HasPrefix(buf.String(), test.startsWith) { if !strings.HasPrefix(buf.String(), test.startsWith) {
t.Fatalf("Expected to start with %s but got %s", test.startsWith, buf.String()) t.Fatalf("Expected to start with %s but got %s", test.startsWith, buf.String())
} }
@ -1644,7 +1652,7 @@ func TestPrintJob(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printJob(&test.job, buf, PrintOptions{}) printJob(&test.job, buf, printers.PrintOptions{})
if buf.String() != test.expect { if buf.String() != test.expect {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
} }
@ -2014,7 +2022,7 @@ func TestPrintHPA(t *testing.T) {
buff := bytes.NewBuffer([]byte{}) buff := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
err := printHorizontalPodAutoscaler(&test.hpa, buff, PrintOptions{}) err := printHorizontalPodAutoscaler(&test.hpa, buff, printers.PrintOptions{})
if err != nil { if err != nil {
t.Errorf("expected %q, got error: %v", test.expected, err) t.Errorf("expected %q, got error: %v", test.expected, err)
buff.Reset() buff.Reset()
@ -2079,10 +2087,8 @@ func TestPrintPodShowLabels(t *testing.T) {
} }
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
printer := HumanReadablePrinter{}
for _, test := range tests { for _, test := range tests {
printer.printPod(&test.pod, buf, PrintOptions{ShowLabels: test.showLabels}) printPod(&test.pod, buf, printers.PrintOptions{ShowLabels: test.showLabels})
// We ignore time // We ignore time
if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) { if !strings.HasPrefix(buf.String(), test.startsWith) || !strings.HasSuffix(buf.String(), test.endsWith) {
t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String()) t.Fatalf("Expected to start with: %s and end with: %s, but got: %s", test.startsWith, test.endsWith, buf.String())
@ -2132,7 +2138,7 @@ func TestPrintService(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printService(&test.service, buf, PrintOptions{}) printService(&test.service, buf, printers.PrintOptions{})
// We ignore time // We ignore time
if buf.String() != test.expect { if buf.String() != test.expect {
t.Fatalf("Expected: %s, got: %s %d", test.expect, buf.String(), strings.Compare(test.expect, buf.String())) t.Fatalf("Expected: %s, got: %s %d", test.expect, buf.String(), strings.Compare(test.expect, buf.String()))
@ -2165,7 +2171,7 @@ func TestPrintPodDisruptionBudget(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
for _, test := range tests { for _, test := range tests {
printPodDisruptionBudget(&test.pdb, buf, PrintOptions{}) printPodDisruptionBudget(&test.pdb, buf, printers.PrintOptions{})
if buf.String() != test.expect { if buf.String() != test.expect {
t.Fatalf("Expected: %s, got: %s", test.expect, buf.String()) t.Fatalf("Expected: %s, got: %s", test.expect, buf.String())
} }
@ -2190,7 +2196,7 @@ func TestAllowMissingKeys(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
printer, _, err := GetPrinter(test.Format, test.Template, false, test.AllowMissingTemplateKeys) printer, _, err := printers.GetStandardPrinter(test.Format, test.Template, false, test.AllowMissingTemplateKeys, api.Registry.RESTMapper(api.Registry.EnabledVersions()...), api.Scheme, []runtime.Decoder{api.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme})
if err != nil { if err != nil {
t.Errorf("in %s, unexpected error: %#v", test.Name, err) t.Errorf("in %s, unexpected error: %#v", test.Name, err)
} }

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package kubectl package internalversion
import ( import (
"reflect" "reflect"

View File

@ -27,7 +27,6 @@ const (
tabwriterPadding = 3 tabwriterPadding = 3
tabwriterPadChar = ' ' tabwriterPadChar = ' '
tabwriterFlags = 0 tabwriterFlags = 0
loadBalancerWidth = 16
) )
// GetNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text. // GetNewTabWriter returns a tabwriter that translates tabbed columns in input into properly aligned text.