Merge pull request #42285 from liggitt/get-watch

Automatic merge from submit-queue (batch tested with PRs 41919, 41149, 42350, 42351, 42285)

Fix error printing objects from kubectl get -w

Fixes #42276
This commit is contained in:
Kubernetes Submit Queue 2017-03-03 16:44:45 -08:00 committed by GitHub
commit f7c07a121d
7 changed files with 70 additions and 27 deletions

View File

@ -1160,6 +1160,19 @@ run_kubectl_get_tests() {
output_message=$(! kubectl get pod valid-pod --allow-missing-template-keys=false -o go-template='{{.missing}}' "${kube_flags[@]}")
kube::test::if_has_string "${output_message}" 'map has no entry for key "missing"'
### Test kubectl get watch
output_message=$(kubectl get pods -w --request-timeout=1 "${kube_flags[@]}")
kube::test::if_has_string "${output_message}" 'STATUS' # headers
kube::test::if_has_string "${output_message}" 'valid-pod' # pod details
output_message=$(kubectl get pods/valid-pod -o name -w --request-timeout=1 "${kube_flags[@]}")
kube::test::if_has_not_string "${output_message}" 'STATUS' # no headers
kube::test::if_has_string "${output_message}" 'pods/valid-pod' # resource name
output_message=$(kubectl get pods/valid-pod -o yaml -w --request-timeout=1 "${kube_flags[@]}")
kube::test::if_has_not_string "${output_message}" 'STATUS' # no headers
kube::test::if_has_string "${output_message}" 'name: valid-pod' # yaml
output_message=$(! kubectl get pods/invalid-pod -w --request-timeout=1 "${kube_flags[@]}" 2>&1)
kube::test::if_has_string "${output_message}" '"invalid-pod" not found'
# cleanup
kubectl delete pods valid-pod "${kube_flags[@]}"

View File

@ -147,7 +147,7 @@ func stringBody(body string) io.ReadCloser {
func Example_printReplicationControllerWithNamespace() {
f, tf, _, ns := cmdtesting.NewAPIFactory()
p := printers.NewHumanReadablePrinter(printers.PrintOptions{
p := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
WithNamespace: true,
ColumnLabels: []string{},
})
@ -200,7 +200,7 @@ func Example_printReplicationControllerWithNamespace() {
func Example_printMultiContainersReplicationControllerWithWide() {
f, tf, _, ns := cmdtesting.NewAPIFactory()
p := printers.NewHumanReadablePrinter(printers.PrintOptions{
p := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
Wide: true,
ColumnLabels: []string{},
})
@ -255,7 +255,7 @@ func Example_printMultiContainersReplicationControllerWithWide() {
func Example_printReplicationController() {
f, tf, _, ns := cmdtesting.NewAPIFactory()
p := printers.NewHumanReadablePrinter(printers.PrintOptions{
p := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
ColumnLabels: []string{},
})
printersinternal.AddHandlers(p)
@ -309,7 +309,7 @@ func Example_printReplicationController() {
func Example_printPodWithWideFormat() {
f, tf, _, ns := cmdtesting.NewAPIFactory()
p := printers.NewHumanReadablePrinter(printers.PrintOptions{
p := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
Wide: true,
ColumnLabels: []string{},
})
@ -352,7 +352,7 @@ func Example_printPodWithWideFormat() {
func Example_printPodWithShowLabels() {
f, tf, _, ns := cmdtesting.NewAPIFactory()
p := printers.NewHumanReadablePrinter(printers.PrintOptions{
p := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
ShowLabels: true,
ColumnLabels: []string{},
})
@ -490,7 +490,7 @@ func newAllPhasePodList() *api.PodList {
func Example_printPodHideTerminated() {
f, tf, _, ns := cmdtesting.NewAPIFactory()
p := printers.NewHumanReadablePrinter(printers.PrintOptions{
p := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
ColumnLabels: []string{},
})
printersinternal.AddHandlers(p)
@ -525,7 +525,7 @@ func Example_printPodHideTerminated() {
func Example_printPodShowAll() {
f, tf, _, ns := cmdtesting.NewAPIFactory()
p := printers.NewHumanReadablePrinter(printers.PrintOptions{
p := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
ShowAll: true,
ColumnLabels: []string{},
})
@ -554,7 +554,7 @@ func Example_printPodShowAll() {
func Example_printServiceWithNamespacesAndLabels() {
f, tf, _, ns := cmdtesting.NewAPIFactory()
p := printers.NewHumanReadablePrinter(printers.PrintOptions{
p := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
WithNamespace: true,
ColumnLabels: []string{"l1"},
})

View File

@ -251,8 +251,16 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
// print the current object
filteredResourceCount := 0
if !isWatchOnly {
if err := printer.PrintObj(obj, out); err != nil {
return fmt.Errorf("unable to output the provided object: %v", err)
var objsToPrint []runtime.Object
if isList {
objsToPrint, _ = meta.ExtractList(obj)
} else {
objsToPrint = append(objsToPrint, obj)
}
for _, objToPrint := range objsToPrint {
if err := printer.PrintObj(objToPrint, out); err != nil {
return fmt.Errorf("unable to output the provided object: %v", err)
}
}
filteredResourceCount++
cmdutil.PrintFilterCount(filteredResourceCount, mapping.Resource, filterOpts)

View File

@ -848,7 +848,7 @@ func TestWatchSelector(t *testing.T) {
cmd.Flags().Set("selector", "a=b")
cmd.Run(cmd, []string{"pods"})
expected := []runtime.Object{podList, events[2].Object, events[3].Object}
expected := []runtime.Object{&pods[0], &pods[1], events[2].Object, events[3].Object}
verifyObjects(t, expected, tf.Printer.(*testPrinter).Objects)
if len(buf.String()) == 0 {

View File

@ -416,7 +416,7 @@ func (f *ring0Factory) SuggestedPodTemplateResources() []schema.GroupResource {
}
func (f *ring0Factory) Printer(mapping *meta.RESTMapping, options printers.PrintOptions) (printers.ResourcePrinter, error) {
p := printers.NewHumanReadablePrinter(options)
p := printers.NewHumanReadablePrinter(f.JSONEncoder(), f.Decoder(true), options)
printersinternal.AddHandlers(p)
return p, nil
}

View File

@ -50,13 +50,18 @@ type HumanReadablePrinter struct {
options PrintOptions
lastType reflect.Type
hiddenObjNum int
encoder runtime.Encoder
decoder runtime.Decoder
}
// NewHumanReadablePrinter creates a HumanReadablePrinter.
func NewHumanReadablePrinter(options PrintOptions) *HumanReadablePrinter {
// If encoder and decoder are provided, an attempt to convert unstructured types to internal types is made.
func NewHumanReadablePrinter(encoder runtime.Encoder, decoder runtime.Decoder, options PrintOptions) *HumanReadablePrinter {
printer := &HumanReadablePrinter{
handlerMap: make(map[reflect.Type]*handlerEntry),
options: options,
encoder: encoder,
decoder: decoder,
}
return printer
}
@ -167,7 +172,9 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
// 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)
if h.encoder != nil && h.decoder != nil {
obj, _ = decodeUnknownObject(obj, h.encoder, h.decoder)
}
t := reflect.TypeOf(obj)
if handler := h.handlerMap[t]; handler != nil {
@ -327,3 +334,18 @@ func appendAllLabels(showLabels bool, itemLabels map[string]string) string {
return buffer.String()
}
// check if the object is unstructured. If so, attempt to convert it to a type we can understand.
func decodeUnknownObject(obj runtime.Object, encoder runtime.Encoder, decoder runtime.Decoder) (runtime.Object, error) {
var err error
switch obj.(type) {
case runtime.Unstructured, *runtime.Unknown:
if objBytes, err := runtime.Encode(encoder, obj); err == nil {
if decodedObj, err := runtime.Decode(decoder, objBytes); err == nil {
obj = decodedObj
}
}
}
return obj, err
}

View File

@ -258,7 +258,7 @@ func ErrorPrintHandler(obj *TestPrintType, w io.Writer, options printers.PrintOp
func TestCustomTypePrinting(t *testing.T) {
columns := []string{"Data"}
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{})
printer.Handler(columns, nil, PrintCustomType)
obj := TestPrintType{"test object"}
@ -275,7 +275,7 @@ func TestCustomTypePrinting(t *testing.T) {
func TestCustomTypePrintingWithKind(t *testing.T) {
columns := []string{"Data"}
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{})
printer.Handler(columns, nil, PrintCustomType)
printer.EnsurePrintWithKind("test")
@ -293,7 +293,7 @@ func TestCustomTypePrintingWithKind(t *testing.T) {
func TestPrintHandlerError(t *testing.T) {
columns := []string{"Data"}
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{})
printer.Handler(columns, nil, ErrorPrintHandler)
obj := TestPrintType{"test object"}
buffer := &bytes.Buffer{}
@ -304,7 +304,7 @@ func TestPrintHandlerError(t *testing.T) {
}
func TestUnknownTypePrinting(t *testing.T) {
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{})
buffer := &bytes.Buffer{}
err := printer.PrintObj(&TestUnknownType{}, buffer)
if err == nil {
@ -522,10 +522,10 @@ func TestPrinters(t *testing.T) {
jsonpathPrinter = printers.NewVersionedPrinter(jsonpathPrinter, api.Scheme, v1.SchemeGroupVersion)
allPrinters := map[string]printers.ResourcePrinter{
"humanReadable": printers.NewHumanReadablePrinter(printers.PrintOptions{
"humanReadable": printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
NoHeaders: true,
}),
"humanReadableHeaders": printers.NewHumanReadablePrinter(printers.PrintOptions{}),
"humanReadableHeaders": printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}),
"json": &printers.JSONPrinter{},
"yaml": &printers.YAMLPrinter{},
"template": templatePrinter,
@ -571,7 +571,7 @@ func TestPrinters(t *testing.T) {
func TestPrintEventsResultSorted(t *testing.T) {
// Arrange
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{})
AddHandlers(printer)
obj := api.EventList{
@ -616,7 +616,7 @@ func TestPrintEventsResultSorted(t *testing.T) {
}
func TestPrintNodeStatus(t *testing.T) {
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{})
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{})
AddHandlers(printer)
table := []struct {
node api.Node
@ -736,7 +736,7 @@ func TestPrintNodeStatus(t *testing.T) {
}
func TestPrintNodeOSImage(t *testing.T) {
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
ColumnLabels: []string{},
Wide: true,
})
@ -781,7 +781,7 @@ func TestPrintNodeOSImage(t *testing.T) {
}
func TestPrintNodeKernelVersion(t *testing.T) {
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
ColumnLabels: []string{},
Wide: true,
})
@ -826,7 +826,7 @@ func TestPrintNodeKernelVersion(t *testing.T) {
}
func TestPrintNodeExternalIP(t *testing.T) {
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
Wide: true,
})
AddHandlers(printer)
@ -1219,7 +1219,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) {
for _, test := range table {
if test.isNamespaced {
// Expect output to include namespace when requested.
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
WithNamespace: true,
})
AddHandlers(printer)
@ -1234,7 +1234,7 @@ func TestPrintHumanReadableWithNamespace(t *testing.T) {
}
} else {
// Expect error when trying to get all namespaces for un-namespaced object.
printer := printers.NewHumanReadablePrinter(printers.PrintOptions{
printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{
WithNamespace: true,
})
buffer := &bytes.Buffer{}