mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +00:00
ExtractList should handle v1.RawExtension correctly
Also fixes CustomColumnPrinter to pass decoder in, and ensures a test case tests the combined path.
This commit is contained in:
parent
738eae88f8
commit
71a13f7f4b
@ -848,6 +848,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) {
|
|||||||
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.RawExtension:
|
||||||
|
switch {
|
||||||
|
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:
|
case runtime.Object:
|
||||||
list[i] = item
|
list[i] = item
|
||||||
case runtime.RawExtension:
|
|
||||||
list[i] = &runtime.Unknown{
|
|
||||||
RawJSON: item.RawJSON,
|
|
||||||
}
|
|
||||||
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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
|||||||
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) {
|
|||||||
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) {
|
|||||||
//
|
//
|
||||||
// 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)
|
|||||||
}
|
}
|
||||||
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 {
|
|||||||
// 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
|
|||||||
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
|
|||||||
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 (
|
|||||||
"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) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
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) {
|
|||||||
}
|
}
|
||||||
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
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
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) {
|
|||||||
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":
|
||||||
|
Loading…
Reference in New Issue
Block a user