Commit 79126825 authored by k8s-merge-robot's avatar k8s-merge-robot

Merge pull request #20226 from smarterclayton/fix_extract_list

Auto commit by PR queue bot
parents e24ea121 71a13f7f
...@@ -844,6 +844,12 @@ __EOF__ ...@@ -844,6 +844,12 @@ __EOF__
# Post-condition: redis-master and redis-slave services are created # Post-condition: redis-master and redis-slave services are created
kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:' kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:'
### Custom columns can be specified
# Pre-condition: generate output using custom columns
output_message=$(kubectl get services -o=custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion 2>&1 "${kube_flags[@]}")
# Post-condition: should contain name column
kube::test::if_has_string "${output_message}" 'redis-master'
### Delete multiple services at once ### Delete multiple services at once
# Pre-condition: redis-master and redis-slave services exist # Pre-condition: redis-master and redis-slave services exist
kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:' kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:'
......
...@@ -72,12 +72,17 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) { ...@@ -72,12 +72,17 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
for i := range list { for i := range list {
raw := items.Index(i) raw := items.Index(i)
switch item := raw.Interface().(type) { switch item := raw.Interface().(type) {
case runtime.Object:
list[i] = item
case runtime.RawExtension: case runtime.RawExtension:
list[i] = &runtime.Unknown{ switch {
RawJSON: item.RawJSON, case item.Object != nil:
list[i] = item.Object
case item.RawJSON != nil:
list[i] = &runtime.Unknown{RawJSON: item.RawJSON}
default:
list[i] = nil
} }
case runtime.Object:
list[i] = item
default: default:
var found bool var found bool
if list[i], found = raw.Addr().Interface().(runtime.Object); !found { if list[i], found = raw.Addr().Interface().(runtime.Object); !found {
......
...@@ -67,6 +67,28 @@ func TestExtractList(t *testing.T) { ...@@ -67,6 +67,28 @@ func TestExtractList(t *testing.T) {
} }
} }
func TestExtractListV1(t *testing.T) {
pl := &v1.PodList{
Items: []v1.Pod{
{ObjectMeta: v1.ObjectMeta{Name: "1"}},
{ObjectMeta: v1.ObjectMeta{Name: "2"}},
{ObjectMeta: v1.ObjectMeta{Name: "3"}},
},
}
list, err := meta.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i].(*v1.Pod).Name, pl.Items[i].Name; e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
}
}
func TestExtractListGeneric(t *testing.T) { func TestExtractListGeneric(t *testing.T) {
pl := &api.List{ pl := &api.List{
Items: []runtime.Object{ Items: []runtime.Object{
...@@ -94,6 +116,7 @@ func TestExtractListGenericV1(t *testing.T) { ...@@ -94,6 +116,7 @@ func TestExtractListGenericV1(t *testing.T) {
Items: []runtime.RawExtension{ Items: []runtime.RawExtension{
{RawJSON: []byte("foo")}, {RawJSON: []byte("foo")},
{RawJSON: []byte("bar")}, {RawJSON: []byte("bar")},
{Object: &v1.Pod{ObjectMeta: v1.ObjectMeta{Name: "other"}}},
}, },
} }
list, err := meta.ExtractList(pl) list, err := meta.ExtractList(pl)
...@@ -109,6 +132,9 @@ func TestExtractListGenericV1(t *testing.T) { ...@@ -109,6 +132,9 @@ func TestExtractListGenericV1(t *testing.T) {
if obj, ok := list[1].(*runtime.Unknown); !ok { if obj, ok := list[1].(*runtime.Unknown); !ok {
t.Fatalf("Expected list[1] to be *runtime.Unknown, it is %#v", obj) t.Fatalf("Expected list[1] to be *runtime.Unknown, it is %#v", obj)
} }
if obj, ok := list[2].(*v1.Pod); !ok {
t.Fatalf("Expected list[2] to be *runtime.Unknown, it is %#v", obj)
}
} }
type fakePtrInterfaceList struct { type fakePtrInterfaceList struct {
......
...@@ -73,7 +73,7 @@ func massageJSONPath(pathExpression string) (string, error) { ...@@ -73,7 +73,7 @@ func massageJSONPath(pathExpression string) (string, error) {
// //
// NAME API_VERSION // NAME API_VERSION
// foo bar // foo bar
func NewCustomColumnsPrinterFromSpec(spec string) (*CustomColumnsPrinter, error) { func NewCustomColumnsPrinterFromSpec(spec string, decoder runtime.Decoder) (*CustomColumnsPrinter, error) {
if len(spec) == 0 { if len(spec) == 0 {
return nil, fmt.Errorf("custom-columns format specified but no custom columns given") return nil, fmt.Errorf("custom-columns format specified but no custom columns given")
} }
...@@ -90,7 +90,7 @@ func NewCustomColumnsPrinterFromSpec(spec string) (*CustomColumnsPrinter, error) ...@@ -90,7 +90,7 @@ func NewCustomColumnsPrinterFromSpec(spec string) (*CustomColumnsPrinter, error)
} }
columns[ix] = Column{Header: colSpec[0], FieldSpec: spec} columns[ix] = Column{Header: colSpec[0], FieldSpec: spec}
} }
return &CustomColumnsPrinter{Columns: columns}, nil return &CustomColumnsPrinter{Columns: columns, Decoder: decoder}, nil
} }
func splitOnWhitespace(line string) []string { func splitOnWhitespace(line string) []string {
...@@ -108,7 +108,7 @@ func splitOnWhitespace(line string) []string { ...@@ -108,7 +108,7 @@ func splitOnWhitespace(line string) []string {
// For example the template below: // For example the template below:
// NAME API_VERSION // NAME API_VERSION
// {metadata.name} {apiVersion} // {metadata.name} {apiVersion}
func NewCustomColumnsPrinterFromTemplate(templateReader io.Reader) (*CustomColumnsPrinter, error) { func NewCustomColumnsPrinterFromTemplate(templateReader io.Reader, decoder runtime.Decoder) (*CustomColumnsPrinter, error) {
scanner := bufio.NewScanner(templateReader) scanner := bufio.NewScanner(templateReader)
if !scanner.Scan() { if !scanner.Scan() {
return nil, fmt.Errorf("invalid template, missing header line. Expected format is one line of space separated headers, one line of space separated column specs.") return nil, fmt.Errorf("invalid template, missing header line. Expected format is one line of space separated headers, one line of space separated column specs.")
...@@ -135,7 +135,7 @@ func NewCustomColumnsPrinterFromTemplate(templateReader io.Reader) (*CustomColum ...@@ -135,7 +135,7 @@ func NewCustomColumnsPrinterFromTemplate(templateReader io.Reader) (*CustomColum
FieldSpec: spec, FieldSpec: spec,
} }
} }
return &CustomColumnsPrinter{Columns: columns}, nil return &CustomColumnsPrinter{Columns: columns, Decoder: decoder}, nil
} }
// Column represents a user specified column // Column represents a user specified column
...@@ -191,9 +191,11 @@ func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jso ...@@ -191,9 +191,11 @@ func (s *CustomColumnsPrinter) printOneObject(obj runtime.Object, parsers []*jso
columns := make([]string, len(parsers)) columns := make([]string, len(parsers))
switch u := obj.(type) { switch u := obj.(type) {
case *runtime.Unknown: case *runtime.Unknown:
var err error if len(u.RawJSON) > 0 {
if obj, _, err = s.Decoder.Decode(u.RawJSON, nil, nil); err != nil { var err error
return err if obj, err = runtime.Decode(s.Decoder, u.RawJSON); err != nil {
return fmt.Errorf("can't decode object for printing: %v (%s)", err, u.RawJSON)
}
} }
} }
for ix := range parsers { for ix := range parsers {
......
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/runtime"
...@@ -103,7 +104,7 @@ func TestNewColumnPrinterFromSpec(t *testing.T) { ...@@ -103,7 +104,7 @@ func TestNewColumnPrinterFromSpec(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
printer, err := NewCustomColumnsPrinterFromSpec(test.spec) printer, err := NewCustomColumnsPrinterFromSpec(test.spec, 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)
...@@ -186,7 +187,7 @@ func TestNewColumnPrinterFromTemplate(t *testing.T) { ...@@ -186,7 +187,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) printer, err := 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)
...@@ -262,6 +263,7 @@ foo baz ...@@ -262,6 +263,7 @@ foo baz
for _, test := range tests { for _, test := range tests {
printer := &CustomColumnsPrinter{ printer := &CustomColumnsPrinter{
Columns: test.columns, Columns: test.columns,
Decoder: api.Codecs.UniversalDecoder(),
} }
buffer := &bytes.Buffer{} buffer := &bytes.Buffer{}
if err := printer.PrintObj(test.obj, buffer); err != nil { if err := printer.PrintObj(test.obj, buffer); err != nil {
......
...@@ -113,7 +113,7 @@ func GetPrinter(format, formatArgument string) (ResourcePrinter, bool, error) { ...@@ -113,7 +113,7 @@ func GetPrinter(format, formatArgument string) (ResourcePrinter, bool, error) {
} }
case "custom-columns": case "custom-columns":
var err error var err error
if printer, err = NewCustomColumnsPrinterFromSpec(formatArgument); err != nil { if printer, err = NewCustomColumnsPrinterFromSpec(formatArgument, api.Codecs.UniversalDecoder()); err != nil {
return nil, false, err return nil, false, err
} }
case "custom-columns-file": case "custom-columns-file":
...@@ -121,7 +121,7 @@ func GetPrinter(format, formatArgument string) (ResourcePrinter, bool, error) { ...@@ -121,7 +121,7 @@ func GetPrinter(format, formatArgument string) (ResourcePrinter, bool, error) {
if err != nil { if err != nil {
return nil, false, fmt.Errorf("error reading template %s, %v\n", formatArgument, err) return nil, false, fmt.Errorf("error reading template %s, %v\n", formatArgument, err)
} }
if printer, err = NewCustomColumnsPrinterFromTemplate(file); err != nil { if printer, err = NewCustomColumnsPrinterFromTemplate(file, api.Codecs.UniversalDecoder()); err != nil {
return nil, false, err return nil, false, err
} }
case "wide": case "wide":
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment