Switch TableGenerator/TableConvertor interfaces to metav1

This commit is contained in:
Jordan Liggitt 2019-11-26 13:13:25 -05:00
parent 2e57e54fa6
commit 36eb250cbb
42 changed files with 818 additions and 683 deletions

View File

@ -12,7 +12,6 @@ go_library(
deps = [ deps = [
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
], ],

View File

@ -30,7 +30,6 @@ go_test(
"//pkg/printers:go_default_library", "//pkg/printers:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
@ -93,7 +92,6 @@ go_library(
"//staging/src/k8s.io/api/scheduling/v1:go_default_library", "//staging/src/k8s.io/api/scheduling/v1:go_default_library",
"//staging/src/k8s.io/api/storage/v1:go_default_library", "//staging/src/k8s.io/api/storage/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/printers/storage", importpath = "k8s.io/kubernetes/pkg/printers/storage",
deps = [ deps = [
"//pkg/printers:go_default_library", "//pkg/printers:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
], ],
) )

View File

@ -20,22 +20,22 @@ import (
"context" "context"
"fmt" "fmt"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/printers"
) )
// TableConvertor struct - converts objects to metav1beta1.Table using printers.TableGenerator // TableConvertor struct - converts objects to metav1.Table using printers.TableGenerator
type TableConvertor struct { type TableConvertor struct {
printers.TableGenerator printers.TableGenerator
} }
// ConvertToTable method - converts objects to metav1beta1.Table objects using TableGenerator // ConvertToTable method - converts objects to metav1.Table objects using TableGenerator
func (c TableConvertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (c TableConvertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
noHeaders := false noHeaders := false
if tableOptions != nil { if tableOptions != nil {
switch t := tableOptions.(type) { switch t := tableOptions.(type) {
case *metav1beta1.TableOptions: case *metav1.TableOptions:
if t != nil { if t != nil {
noHeaders = t.NoHeaders noHeaders = t.NoHeaders
} }

View File

@ -22,7 +22,6 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
) )
@ -33,18 +32,18 @@ type GenerateOptions struct {
Wide bool Wide bool
} }
// TableGenerator - an interface for generating metav1beta1.Table provided a runtime.Object // TableGenerator - an interface for generating metav1.Table provided a runtime.Object
type TableGenerator interface { type TableGenerator interface {
GenerateTable(obj runtime.Object, options GenerateOptions) (*metav1beta1.Table, error) GenerateTable(obj runtime.Object, options GenerateOptions) (*metav1.Table, error)
} }
// PrintHandler - interface to handle printing provided an array of metav1beta1.TableColumnDefinition // PrintHandler - interface to handle printing provided an array of metav1.TableColumnDefinition
type PrintHandler interface { type PrintHandler interface {
TableHandler(columns []metav1beta1.TableColumnDefinition, printFunc interface{}) error TableHandler(columns []metav1.TableColumnDefinition, printFunc interface{}) error
} }
type handlerEntry struct { type handlerEntry struct {
columnDefinitions []metav1beta1.TableColumnDefinition columnDefinitions []metav1.TableColumnDefinition
printFunc reflect.Value printFunc reflect.Value
args []reflect.Value args []reflect.Value
} }
@ -77,7 +76,7 @@ func (h *HumanReadableGenerator) With(fns ...func(PrintHandler)) *HumanReadableG
// GenerateTable returns a table for the provided object, using the printer registered for that type. It returns // GenerateTable returns a table for the provided object, using the printer registered for that type. It returns
// a table that includes all of the information requested by options, but will not remove rows or columns. The // a table that includes all of the information requested by options, but will not remove rows or columns. The
// caller is responsible for applying rules related to filtering rows or columns. // caller is responsible for applying rules related to filtering rows or columns.
func (h *HumanReadableGenerator) GenerateTable(obj runtime.Object, options GenerateOptions) (*metav1beta1.Table, error) { func (h *HumanReadableGenerator) GenerateTable(obj runtime.Object, options GenerateOptions) (*metav1.Table, error) {
t := reflect.TypeOf(obj) t := reflect.TypeOf(obj)
handler, ok := h.handlerMap[t] handler, ok := h.handlerMap[t]
if !ok { if !ok {
@ -90,11 +89,11 @@ func (h *HumanReadableGenerator) GenerateTable(obj runtime.Object, options Gener
return nil, results[1].Interface().(error) return nil, results[1].Interface().(error)
} }
var columns []metav1beta1.TableColumnDefinition var columns []metav1.TableColumnDefinition
if !options.NoHeaders { if !options.NoHeaders {
columns = handler.columnDefinitions columns = handler.columnDefinitions
if !options.Wide { if !options.Wide {
columns = make([]metav1beta1.TableColumnDefinition, 0, len(handler.columnDefinitions)) columns = make([]metav1.TableColumnDefinition, 0, len(handler.columnDefinitions))
for i := range handler.columnDefinitions { for i := range handler.columnDefinitions {
if handler.columnDefinitions[i].Priority != 0 { if handler.columnDefinitions[i].Priority != 0 {
continue continue
@ -103,12 +102,12 @@ func (h *HumanReadableGenerator) GenerateTable(obj runtime.Object, options Gener
} }
} }
} }
table := &metav1beta1.Table{ table := &metav1.Table{
ListMeta: metav1.ListMeta{ ListMeta: metav1.ListMeta{
ResourceVersion: "", ResourceVersion: "",
}, },
ColumnDefinitions: columns, ColumnDefinitions: columns,
Rows: results[0].Interface().([]metav1beta1.TableRow), Rows: results[0].Interface().([]metav1.TableRow),
} }
if m, err := meta.ListAccessor(obj); err == nil { if m, err := meta.ListAccessor(obj); err == nil {
table.ResourceVersion = m.GetResourceVersion() table.ResourceVersion = m.GetResourceVersion()
@ -126,7 +125,7 @@ func (h *HumanReadableGenerator) GenerateTable(obj runtime.Object, options Gener
// TableHandler adds a print handler with a given set of columns to HumanReadableGenerator instance. // TableHandler adds a print handler with a given set of columns to HumanReadableGenerator instance.
// See ValidateRowPrintHandlerFunc for required method signature. // See ValidateRowPrintHandlerFunc for required method signature.
func (h *HumanReadableGenerator) TableHandler(columnDefinitions []metav1beta1.TableColumnDefinition, printFunc interface{}) error { func (h *HumanReadableGenerator) TableHandler(columnDefinitions []metav1.TableColumnDefinition, printFunc interface{}) error {
printFuncValue := reflect.ValueOf(printFunc) printFuncValue := reflect.ValueOf(printFunc)
if err := ValidateRowPrintHandlerFunc(printFuncValue); err != nil { if err := ValidateRowPrintHandlerFunc(printFuncValue); err != nil {
utilruntime.HandleError(fmt.Errorf("unable to register print function: %v", err)) utilruntime.HandleError(fmt.Errorf("unable to register print function: %v", err))
@ -150,7 +149,7 @@ func (h *HumanReadableGenerator) TableHandler(columnDefinitions []metav1beta1.Ta
// ValidateRowPrintHandlerFunc validates print handler signature. // ValidateRowPrintHandlerFunc validates print handler signature.
// printFunc is the function that will be called to print an object. // printFunc is the function that will be called to print an object.
// It must be of the following type: // It must be of the following type:
// func printFunc(object ObjectType, options GenerateOptions) ([]metav1beta1.TableRow, error) // func printFunc(object ObjectType, options GenerateOptions) ([]metav1.TableRow, error)
// where ObjectType is the type of the object that will be printed, and the first // where ObjectType is the type of the object that will be printed, and the first
// return value is an array of rows, with each row containing a number of cells that // return value is an array of rows, with each row containing a number of cells that
// match the number of columns defined for that printer function. // match the number of columns defined for that printer function.
@ -164,10 +163,10 @@ func ValidateRowPrintHandlerFunc(printFunc reflect.Value) error {
"Must accept 2 parameters and return 2 value.") "Must accept 2 parameters and return 2 value.")
} }
if funcType.In(1) != reflect.TypeOf((*GenerateOptions)(nil)).Elem() || if funcType.In(1) != reflect.TypeOf((*GenerateOptions)(nil)).Elem() ||
funcType.Out(0) != reflect.TypeOf((*[]metav1beta1.TableRow)(nil)).Elem() || funcType.Out(0) != reflect.TypeOf((*[]metav1.TableRow)(nil)).Elem() ||
funcType.Out(1) != reflect.TypeOf((*error)(nil)).Elem() { funcType.Out(1) != reflect.TypeOf((*error)(nil)).Elem() {
return fmt.Errorf("invalid print handler. The expected signature is: "+ return fmt.Errorf("invalid print handler. The expected signature is: "+
"func handler(obj %v, options GenerateOptions) ([]metav1beta1.TableRow, error)", funcType.In(0)) "func handler(obj %v, options GenerateOptions) ([]metav1.TableRow, error)", funcType.In(0))
} }
return nil return nil
} }

View File

@ -39,7 +39,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",

View File

@ -23,7 +23,6 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
"k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/generic"
@ -273,7 +272,7 @@ func shouldHaveDeleteDependentsFinalizer(options *metav1.DeleteOptions, haveDele
return haveDeleteDependentsFinalizer return haveDeleteDependentsFinalizer
} }
func (e *REST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (e *REST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
return e.store.ConvertToTable(ctx, object, tableOptions) return e.store.ConvertToTable(ctx, object, tableOptions)
} }

View File

@ -24,7 +24,6 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -22,11 +22,10 @@ import (
"testing" "testing"
"time" "time"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -430,7 +429,7 @@ func TestConvertToTableList(t *testing.T) {
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
columns := []metav1beta1.TableColumnDefinition{ columns := []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
{Name: "Ready", Type: "string", Description: "The aggregate readiness state of this pod for accepting traffic."}, {Name: "Ready", Type: "string", Description: "The aggregate readiness state of this pod for accepting traffic."},
{Name: "Status", Type: "string", Description: "The aggregate status of the containers in this pod."}, {Name: "Status", Type: "string", Description: "The aggregate status of the containers in this pod."},
@ -522,7 +521,7 @@ func TestConvertToTableList(t *testing.T) {
testCases := []struct { testCases := []struct {
in runtime.Object in runtime.Object
out *metav1beta1.Table out *metav1.Table
err bool err bool
}{ }{
{ {
@ -531,31 +530,31 @@ func TestConvertToTableList(t *testing.T) {
}, },
{ {
in: &api.Pod{}, in: &api.Pod{},
out: &metav1beta1.Table{ out: &metav1.Table{
ColumnDefinitions: columns, ColumnDefinitions: columns,
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"", "0/0", "", int64(0), "<unknown>", "<none>", "<none>", "<none>", "<none>"}, Object: runtime.RawExtension{Object: &api.Pod{}}}, {Cells: []interface{}{"", "0/0", "", int64(0), "<unknown>", "<none>", "<none>", "<none>", "<none>"}, Object: runtime.RawExtension{Object: &api.Pod{}}},
}, },
}, },
}, },
{ {
in: pod1, in: pod1,
out: &metav1beta1.Table{ out: &metav1.Table{
ColumnDefinitions: columns, ColumnDefinitions: columns,
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo", "1/2", "Pending", int64(10), "370d", "10.1.2.3", "test-node", "nominated-node", "1/2"}, Object: runtime.RawExtension{Object: pod1}}, {Cells: []interface{}{"foo", "1/2", "Pending", int64(10), "370d", "10.1.2.3", "test-node", "nominated-node", "1/2"}, Object: runtime.RawExtension{Object: pod1}},
}, },
}, },
}, },
{ {
in: &api.PodList{}, in: &api.PodList{},
out: &metav1beta1.Table{ColumnDefinitions: columns}, out: &metav1.Table{ColumnDefinitions: columns},
}, },
{ {
in: multiIPsPod, in: multiIPsPod,
out: &metav1beta1.Table{ out: &metav1.Table{
ColumnDefinitions: columns, ColumnDefinitions: columns,
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo", "1/2", "Pending", int64(10), "370d", "10.1.2.3", "test-node", "nominated-node", "1/2"}, Object: runtime.RawExtension{Object: multiIPsPod}}, {Cells: []interface{}{"foo", "1/2", "Pending", int64(10), "370d", "10.1.2.3", "test-node", "nominated-node", "1/2"}, Object: runtime.RawExtension{Object: multiIPsPod}},
}, },
}, },

View File

@ -26,7 +26,6 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
@ -67,7 +66,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",

View File

@ -28,7 +28,6 @@ import (
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@ -81,7 +80,6 @@ type ServiceStorage interface {
rest.CreaterUpdater rest.CreaterUpdater
rest.GracefulDeleter rest.GracefulDeleter
rest.Watcher rest.Watcher
rest.TableConvertor
rest.Exporter rest.Exporter
rest.StorageVersionProvider rest.StorageVersionProvider
} }
@ -550,7 +548,7 @@ func (rs *REST) ResourceLocation(ctx context.Context, id string) (*url.URL, http
return nil, nil, errors.NewServiceUnavailable(fmt.Sprintf("no endpoints available for service %q", id)) return nil, nil, errors.NewServiceUnavailable(fmt.Sprintf("no endpoints available for service %q", id))
} }
func (r *REST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (r *REST) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
return r.services.ConvertToTable(ctx, object, tableOptions) return r.services.ConvertToTable(ctx, object, tableOptions)
} }

View File

@ -28,7 +28,6 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
@ -155,7 +154,7 @@ func (s *serviceStorage) Watch(ctx context.Context, options *metainternalversion
panic("not implemented") panic("not implemented")
} }
func (s *serviceStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (s *serviceStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
panic("not implemented") panic("not implemented")
} }

View File

@ -80,7 +80,6 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",

View File

@ -30,7 +30,6 @@ import (
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion" metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
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/apis/meta/v1/unstructured"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
@ -266,7 +265,7 @@ func TestColumns(t *testing.T) {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
tbl, err := storage.CustomResource.ConvertToTable(ctx, gottenList, &metav1beta1.TableOptions{}) tbl, err := storage.CustomResource.ConvertToTable(ctx, gottenList, &metav1.TableOptions{})
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }

View File

@ -11,7 +11,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta/table:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta/table:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/client-go/util/jsonpath:go_default_library", "//staging/src/k8s.io/client-go/util/jsonpath:go_default_library",

View File

@ -27,7 +27,6 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metatable "k8s.io/apimachinery/pkg/api/meta/table" metatable "k8s.io/apimachinery/pkg/api/meta/table"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
"k8s.io/client-go/util/jsonpath" "k8s.io/client-go/util/jsonpath"
@ -38,7 +37,7 @@ var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
// New creates a new table convertor for the provided CRD column definition. If the printer definition cannot be parsed, // New creates a new table convertor for the provided CRD column definition. If the printer definition cannot be parsed,
// error will be returned along with a default table convertor. // error will be returned along with a default table convertor.
func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableConvertor, error) { func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableConvertor, error) {
headers := []metav1beta1.TableColumnDefinition{ headers := []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]}, {Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]},
} }
c := &convertor{ c := &convertor{
@ -58,7 +57,7 @@ func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableC
} }
c.additionalColumns = append(c.additionalColumns, path) c.additionalColumns = append(c.additionalColumns, path)
c.headers = append(c.headers, metav1beta1.TableColumnDefinition{ c.headers = append(c.headers, metav1.TableColumnDefinition{
Name: col.Name, Name: col.Name,
Type: col.Type, Type: col.Type,
Format: col.Format, Format: col.Format,
@ -71,13 +70,13 @@ func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableC
} }
type convertor struct { type convertor struct {
headers []metav1beta1.TableColumnDefinition headers []metav1.TableColumnDefinition
additionalColumns []*jsonpath.JSONPath additionalColumns []*jsonpath.JSONPath
} }
func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
table := &metav1beta1.Table{} table := &metav1.Table{}
opt, ok := tableOptions.(*metav1beta1.TableOptions) opt, ok := tableOptions.(*metav1.TableOptions)
noHeaders := ok && opt != nil && opt.NoHeaders noHeaders := ok && opt != nil && opt.NoHeaders
if !noHeaders { if !noHeaders {
table.ColumnDefinitions = c.headers table.ColumnDefinitions = c.headers

View File

@ -76,7 +76,7 @@ func Test_cellForJSONValue(t *testing.T) {
func Test_convertor_ConvertToTable(t *testing.T) { func Test_convertor_ConvertToTable(t *testing.T) {
type fields struct { type fields struct {
headers []metav1beta1.TableColumnDefinition headers []metav1.TableColumnDefinition
additionalColumns []*jsonpath.JSONPath additionalColumns []*jsonpath.JSONPath
} }
type args struct { type args struct {
@ -88,13 +88,13 @@ func Test_convertor_ConvertToTable(t *testing.T) {
name string name string
fields fields fields fields
args args args args
want *metav1beta1.Table want *metav1.Table
wantErr bool wantErr bool
}{ }{
{ {
name: "Return table for object", name: "Return table for object",
fields: fields{ fields: fields{
headers: []metav1beta1.TableColumnDefinition{{Name: "name", Type: "string"}}, headers: []metav1.TableColumnDefinition{{Name: "name", Type: "string"}},
}, },
args: args{ args: args{
obj: &metav1beta1.PartialObjectMetadata{ obj: &metav1beta1.PartialObjectMetadata{
@ -102,9 +102,9 @@ func Test_convertor_ConvertToTable(t *testing.T) {
}, },
tableOptions: nil, tableOptions: nil,
}, },
want: &metav1beta1.Table{ want: &metav1.Table{
ColumnDefinitions: []metav1beta1.TableColumnDefinition{{Name: "name", Type: "string"}}, ColumnDefinitions: []metav1.TableColumnDefinition{{Name: "name", Type: "string"}},
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{ {
Cells: []interface{}{"blah"}, Cells: []interface{}{"blah"},
Object: runtime.RawExtension{ Object: runtime.RawExtension{
@ -119,7 +119,7 @@ func Test_convertor_ConvertToTable(t *testing.T) {
{ {
name: "Return table for list", name: "Return table for list",
fields: fields{ fields: fields{
headers: []metav1beta1.TableColumnDefinition{{Name: "name", Type: "string"}}, headers: []metav1.TableColumnDefinition{{Name: "name", Type: "string"}},
}, },
args: args{ args: args{
obj: &metav1beta1.PartialObjectMetadataList{ obj: &metav1beta1.PartialObjectMetadataList{
@ -130,9 +130,9 @@ func Test_convertor_ConvertToTable(t *testing.T) {
}, },
tableOptions: nil, tableOptions: nil,
}, },
want: &metav1beta1.Table{ want: &metav1.Table{
ColumnDefinitions: []metav1beta1.TableColumnDefinition{{Name: "name", Type: "string"}}, ColumnDefinitions: []metav1.TableColumnDefinition{{Name: "name", Type: "string"}},
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{ {
Cells: []interface{}{"blah"}, Cells: []interface{}{"blah"},
Object: runtime.RawExtension{ Object: runtime.RawExtension{
@ -155,17 +155,17 @@ func Test_convertor_ConvertToTable(t *testing.T) {
{ {
name: "Accept TableOptions", name: "Accept TableOptions",
fields: fields{ fields: fields{
headers: []metav1beta1.TableColumnDefinition{{Name: "name", Type: "string"}}, headers: []metav1.TableColumnDefinition{{Name: "name", Type: "string"}},
}, },
args: args{ args: args{
obj: &metav1beta1.PartialObjectMetadata{ obj: &metav1beta1.PartialObjectMetadata{
ObjectMeta: metav1.ObjectMeta{Name: "blah", CreationTimestamp: metav1.NewTime(time.Unix(1, 0))}, ObjectMeta: metav1.ObjectMeta{Name: "blah", CreationTimestamp: metav1.NewTime(time.Unix(1, 0))},
}, },
tableOptions: &metav1beta1.TableOptions{}, tableOptions: &metav1.TableOptions{},
}, },
want: &metav1beta1.Table{ want: &metav1.Table{
ColumnDefinitions: []metav1beta1.TableColumnDefinition{{Name: "name", Type: "string"}}, ColumnDefinitions: []metav1.TableColumnDefinition{{Name: "name", Type: "string"}},
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{ {
Cells: []interface{}{"blah"}, Cells: []interface{}{"blah"},
Object: runtime.RawExtension{ Object: runtime.RawExtension{
@ -180,16 +180,16 @@ func Test_convertor_ConvertToTable(t *testing.T) {
{ {
name: "Omit headers from TableOptions", name: "Omit headers from TableOptions",
fields: fields{ fields: fields{
headers: []metav1beta1.TableColumnDefinition{{Name: "name", Type: "string"}}, headers: []metav1.TableColumnDefinition{{Name: "name", Type: "string"}},
}, },
args: args{ args: args{
obj: &metav1beta1.PartialObjectMetadata{ obj: &metav1beta1.PartialObjectMetadata{
ObjectMeta: metav1.ObjectMeta{Name: "blah", CreationTimestamp: metav1.NewTime(time.Unix(1, 0))}, ObjectMeta: metav1.ObjectMeta{Name: "blah", CreationTimestamp: metav1.NewTime(time.Unix(1, 0))},
}, },
tableOptions: &metav1beta1.TableOptions{NoHeaders: true}, tableOptions: &metav1.TableOptions{NoHeaders: true},
}, },
want: &metav1beta1.Table{ want: &metav1.Table{
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{ {
Cells: []interface{}{"blah"}, Cells: []interface{}{"blah"},
Object: runtime.RawExtension{ Object: runtime.RawExtension{

View File

@ -158,97 +158,198 @@ func TestTableGet(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
ret, err := crRestClient.Get(). // metav1beta1 table
Resource(crd.Spec.Names.Plural). {
SetHeader("Accept", fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName)). ret, err := crRestClient.Get().
VersionedParams(&metav1beta1.TableOptions{}, parameterCodec). Resource(crd.Spec.Names.Plural).
Do(). SetHeader("Accept", fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName)).
Get() VersionedParams(&metav1beta1.TableOptions{}, parameterCodec).
if err != nil { Do().
t.Fatalf("failed to list %v resources: %v", gvk, err) Get()
} if err != nil {
t.Fatalf("failed to list %v resources: %v", gvk, err)
tbl, ok := ret.(*metav1beta1.Table)
if !ok {
t.Fatalf("expected metav1beta1.Table, got %T", ret)
}
t.Logf("%v table list: %#v", gvk, tbl)
columns, err := getColumnsForVersion(crd, v.Name)
if err != nil {
t.Fatal(err)
}
expectColumnNum := len(columns) + 1
if got, expected := len(tbl.ColumnDefinitions), expectColumnNum; got != expected {
t.Errorf("expected %d headers, got %d", expected, got)
} else {
age := metav1beta1.TableColumnDefinition{Name: "Age", Type: "date", Format: "", Description: "Custom resource definition column (in JSONPath format): .metadata.creationTimestamp", Priority: 0}
if got, expected := tbl.ColumnDefinitions[1], age; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
} }
alpha := metav1beta1.TableColumnDefinition{Name: "Alpha", Type: "string", Format: "", Description: "Custom resource definition column (in JSONPath format): .spec.alpha", Priority: 0} tbl, ok := ret.(*metav1beta1.Table)
if got, expected := tbl.ColumnDefinitions[2], alpha; got != expected { if !ok {
t.Errorf("expected column definition %#v, got %#v", expected, got) t.Fatalf("expected metav1beta1.Table, got %T", ret)
} }
t.Logf("%v table list: %#v", gvk, tbl)
beta := metav1beta1.TableColumnDefinition{Name: "Beta", Type: "integer", Format: "int64", Description: "the beta field", Priority: 42} columns, err := getColumnsForVersion(crd, v.Name)
if got, expected := tbl.ColumnDefinitions[3], beta; got != expected { if err != nil {
t.Errorf("expected column definition %#v, got %#v", expected, got) t.Fatal(err)
} }
expectColumnNum := len(columns) + 1
gamma := metav1beta1.TableColumnDefinition{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values"} if got, expected := len(tbl.ColumnDefinitions), expectColumnNum; got != expected {
if got, expected := tbl.ColumnDefinitions[4], gamma; got != expected { t.Errorf("expected %d headers, got %d", expected, got)
t.Errorf("expected column definition %#v, got %#v", expected, got) } else {
} age := metav1beta1.TableColumnDefinition{Name: "Age", Type: "date", Format: "", Description: "Custom resource definition column (in JSONPath format): .metadata.creationTimestamp", Priority: 0}
if got, expected := tbl.ColumnDefinitions[1], age; got != expected {
epsilon := metav1beta1.TableColumnDefinition{Name: "Epsilon", Type: "string", Description: "an array of integers as string"}
if got, expected := tbl.ColumnDefinitions[5], epsilon; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
// Validate extra column for v1
if i == 1 {
zeta := metav1beta1.TableColumnDefinition{Name: "Zeta", Type: "integer", Format: "int64", Description: "the zeta field", Priority: 42}
if got, expected := tbl.ColumnDefinitions[6], zeta; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got) t.Errorf("expected column definition %#v, got %#v", expected, got)
} }
}
} alpha := metav1beta1.TableColumnDefinition{Name: "Alpha", Type: "string", Format: "", Description: "Custom resource definition column (in JSONPath format): .spec.alpha", Priority: 0}
if got, expected := len(tbl.Rows), 1; got != expected { if got, expected := tbl.ColumnDefinitions[2], alpha; got != expected {
t.Errorf("expected %d rows, got %d", expected, got) t.Errorf("expected column definition %#v, got %#v", expected, got)
} else if got, expected := len(tbl.Rows[0].Cells), expectColumnNum; got != expected { }
t.Errorf("expected %d cells, got %d", expected, got)
} else { beta := metav1beta1.TableColumnDefinition{Name: "Beta", Type: "integer", Format: "int64", Description: "the beta field", Priority: 42}
if got, expected := tbl.Rows[0].Cells[0], "foo"; got != expected { if got, expected := tbl.ColumnDefinitions[3], beta; got != expected {
t.Errorf("expected cell[0] to equal %q, got %q", expected, got) t.Errorf("expected column definition %#v, got %#v", expected, got)
} }
if s, ok := tbl.Rows[0].Cells[1].(string); !ok {
t.Errorf("expected cell[1] to be a string, got: %#v", tbl.Rows[0].Cells[1]) gamma := metav1beta1.TableColumnDefinition{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values"}
} else { if got, expected := tbl.ColumnDefinitions[4], gamma; got != expected {
dur, err := time.ParseDuration(s) t.Errorf("expected column definition %#v, got %#v", expected, got)
if err != nil { }
t.Errorf("expected cell[1] to be a duration: %v", err)
} else if abs(dur.Seconds()) > 30.0 { epsilon := metav1beta1.TableColumnDefinition{Name: "Epsilon", Type: "string", Description: "an array of integers as string"}
t.Errorf("expected cell[1] to be a small age, but got: %v", dur) if got, expected := tbl.ColumnDefinitions[5], epsilon; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
// Validate extra column for v1
if i == 1 {
zeta := metav1beta1.TableColumnDefinition{Name: "Zeta", Type: "integer", Format: "int64", Description: "the zeta field", Priority: 42}
if got, expected := tbl.ColumnDefinitions[6], zeta; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
} }
} }
if got, expected := tbl.Rows[0].Cells[2], "foo_123"; got != expected { if got, expected := len(tbl.Rows), 1; got != expected {
t.Errorf("expected cell[2] to equal %q, got %q", expected, got) t.Errorf("expected %d rows, got %d", expected, got)
} else if got, expected := len(tbl.Rows[0].Cells), expectColumnNum; got != expected {
t.Errorf("expected %d cells, got %d", expected, got)
} else {
if got, expected := tbl.Rows[0].Cells[0], "foo"; got != expected {
t.Errorf("expected cell[0] to equal %q, got %q", expected, got)
}
if s, ok := tbl.Rows[0].Cells[1].(string); !ok {
t.Errorf("expected cell[1] to be a string, got: %#v", tbl.Rows[0].Cells[1])
} else {
dur, err := time.ParseDuration(s)
if err != nil {
t.Errorf("expected cell[1] to be a duration: %v", err)
} else if abs(dur.Seconds()) > 30.0 {
t.Errorf("expected cell[1] to be a small age, but got: %v", dur)
}
}
if got, expected := tbl.Rows[0].Cells[2], "foo_123"; got != expected {
t.Errorf("expected cell[2] to equal %q, got %q", expected, got)
}
if got, expected := tbl.Rows[0].Cells[3], int64(10); got != expected {
t.Errorf("expected cell[3] to equal %#v, got %#v", expected, got)
}
if got, expected := tbl.Rows[0].Cells[4], interface{}(nil); got != expected {
t.Errorf("expected cell[4] to equal %#v although the type does not match the column, got %#v", expected, got)
}
if got, expected := tbl.Rows[0].Cells[5], "[1 2 3]"; got != expected {
t.Errorf("expected cell[5] to equal %q, got %q", expected, got)
}
// Validate extra column for v1
if i == 1 {
if got, expected := tbl.Rows[0].Cells[6], int64(5); got != expected {
t.Errorf("expected cell[6] to equal %q, got %q", expected, got)
}
}
} }
if got, expected := tbl.Rows[0].Cells[3], int64(10); got != expected { }
t.Errorf("expected cell[3] to equal %#v, got %#v", expected, got)
// metav1 table
{
ret, err := crRestClient.Get().
Resource(crd.Spec.Names.Plural).
SetHeader("Accept", fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", metav1.SchemeGroupVersion.Version, metav1.GroupName)).
VersionedParams(&metav1.TableOptions{}, parameterCodec).
Do().
Get()
if err != nil {
t.Fatalf("failed to list %v resources: %v", gvk, err)
} }
if got, expected := tbl.Rows[0].Cells[4], interface{}(nil); got != expected {
t.Errorf("expected cell[4] to equal %#v although the type does not match the column, got %#v", expected, got) tbl, ok := ret.(*metav1.Table)
if !ok {
t.Fatalf("expected metav1.Table, got %T", ret)
} }
if got, expected := tbl.Rows[0].Cells[5], "[1 2 3]"; got != expected { t.Logf("%v table list: %#v", gvk, tbl)
t.Errorf("expected cell[5] to equal %q, got %q", expected, got)
columns, err := getColumnsForVersion(crd, v.Name)
if err != nil {
t.Fatal(err)
} }
// Validate extra column for v1 expectColumnNum := len(columns) + 1
if i == 1 { if got, expected := len(tbl.ColumnDefinitions), expectColumnNum; got != expected {
if got, expected := tbl.Rows[0].Cells[6], int64(5); got != expected { t.Errorf("expected %d headers, got %d", expected, got)
t.Errorf("expected cell[6] to equal %q, got %q", expected, got) } else {
age := metav1.TableColumnDefinition{Name: "Age", Type: "date", Format: "", Description: "Custom resource definition column (in JSONPath format): .metadata.creationTimestamp", Priority: 0}
if got, expected := tbl.ColumnDefinitions[1], age; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
alpha := metav1.TableColumnDefinition{Name: "Alpha", Type: "string", Format: "", Description: "Custom resource definition column (in JSONPath format): .spec.alpha", Priority: 0}
if got, expected := tbl.ColumnDefinitions[2], alpha; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
beta := metav1.TableColumnDefinition{Name: "Beta", Type: "integer", Format: "int64", Description: "the beta field", Priority: 42}
if got, expected := tbl.ColumnDefinitions[3], beta; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
gamma := metav1.TableColumnDefinition{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values"}
if got, expected := tbl.ColumnDefinitions[4], gamma; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
epsilon := metav1.TableColumnDefinition{Name: "Epsilon", Type: "string", Description: "an array of integers as string"}
if got, expected := tbl.ColumnDefinitions[5], epsilon; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
// Validate extra column for v1
if i == 1 {
zeta := metav1.TableColumnDefinition{Name: "Zeta", Type: "integer", Format: "int64", Description: "the zeta field", Priority: 42}
if got, expected := tbl.ColumnDefinitions[6], zeta; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
}
}
if got, expected := len(tbl.Rows), 1; got != expected {
t.Errorf("expected %d rows, got %d", expected, got)
} else if got, expected := len(tbl.Rows[0].Cells), expectColumnNum; got != expected {
t.Errorf("expected %d cells, got %d", expected, got)
} else {
if got, expected := tbl.Rows[0].Cells[0], "foo"; got != expected {
t.Errorf("expected cell[0] to equal %q, got %q", expected, got)
}
if s, ok := tbl.Rows[0].Cells[1].(string); !ok {
t.Errorf("expected cell[1] to be a string, got: %#v", tbl.Rows[0].Cells[1])
} else {
dur, err := time.ParseDuration(s)
if err != nil {
t.Errorf("expected cell[1] to be a duration: %v", err)
} else if abs(dur.Seconds()) > 30.0 {
t.Errorf("expected cell[1] to be a small age, but got: %v", dur)
}
}
if got, expected := tbl.Rows[0].Cells[2], "foo_123"; got != expected {
t.Errorf("expected cell[2] to equal %q, got %q", expected, got)
}
if got, expected := tbl.Rows[0].Cells[3], int64(10); got != expected {
t.Errorf("expected cell[3] to equal %#v, got %#v", expected, got)
}
if got, expected := tbl.Rows[0].Cells[4], interface{}(nil); got != expected {
t.Errorf("expected cell[4] to equal %#v although the type does not match the column, got %#v", expected, got)
}
if got, expected := tbl.Rows[0].Cells[5], "[1 2 3]"; got != expected {
t.Errorf("expected cell[5] to equal %q, got %q", expected, got)
}
// Validate extra column for v1
if i == 1 {
if got, expected := tbl.Rows[0].Cells[6], int64(5); got != expected {
t.Errorf("expected cell[6] to equal %q, got %q", expected, got)
}
} }
} }
} }

View File

@ -9,7 +9,6 @@ go_library(
deps = [ deps = [
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/duration:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/duration:go_default_library",
], ],

View File

@ -21,16 +21,15 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/duration" "k8s.io/apimachinery/pkg/util/duration"
) )
// MetaToTableRow converts a list or object into one or more table rows. The provided rowFn is invoked for // MetaToTableRow converts a list or object into one or more table rows. The provided rowFn is invoked for
// each accessed item, with name and age being passed to each. // each accessed item, with name and age being passed to each.
func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error)) ([]metav1beta1.TableRow, error) { func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error)) ([]metav1.TableRow, error) {
if meta.IsListType(obj) { if meta.IsListType(obj) {
rows := make([]metav1beta1.TableRow, 0, 16) rows := make([]metav1.TableRow, 0, 16)
err := meta.EachListItem(obj, func(obj runtime.Object) error { err := meta.EachListItem(obj, func(obj runtime.Object) error {
nestedRows, err := MetaToTableRow(obj, rowFn) nestedRows, err := MetaToTableRow(obj, rowFn)
if err != nil { if err != nil {
@ -45,12 +44,12 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1.
return rows, nil return rows, nil
} }
rows := make([]metav1beta1.TableRow, 0, 1) rows := make([]metav1.TableRow, 0, 1)
m, err := meta.Accessor(obj) m, err := meta.Accessor(obj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
row := metav1beta1.TableRow{ row := metav1.TableRow{
Object: runtime.RawExtension{Object: obj}, Object: runtime.RawExtension{Object: obj},
} }
row.Cells, err = rowFn(obj, m, m.GetName(), ConvertToHumanReadableDateType(m.GetCreationTimestamp())) row.Cells, err = rowFn(obj, m, m.GetName(), ConvertToHumanReadableDateType(m.GetCreationTimestamp()))

View File

@ -71,8 +71,8 @@ func addToGroupVersion(scheme *runtime.Scheme) error {
&metav1.UpdateOptions{}, &metav1.UpdateOptions{},
) )
scheme.AddKnownTypes(SchemeGroupVersion, scheme.AddKnownTypes(SchemeGroupVersion,
&metav1beta1.Table{}, &metav1.Table{},
&metav1beta1.TableOptions{}, &metav1.TableOptions{},
&metav1beta1.PartialObjectMetadata{}, &metav1beta1.PartialObjectMetadata{},
&metav1beta1.PartialObjectMetadataList{}, &metav1beta1.PartialObjectMetadataList{},
) )

View File

@ -8,7 +8,6 @@ go_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
], ],
) )

View File

@ -18,12 +18,11 @@ package validation
import ( import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
) )
// ValidateTableOptions returns any invalid flags on TableOptions. // ValidateTableOptions returns any invalid flags on TableOptions.
func ValidateTableOptions(opts *metav1beta1.TableOptions) field.ErrorList { func ValidateTableOptions(opts *metav1.TableOptions) field.ErrorList {
var allErrs field.ErrorList var allErrs field.ErrorList
switch opts.IncludeObject { switch opts.IncludeObject {
case metav1.IncludeMetadata, metav1.IncludeNone, metav1.IncludeObject, "": case metav1.IncludeMetadata, metav1.IncludeNone, metav1.IncludeObject, "":

View File

@ -377,7 +377,7 @@ func (storage *SimpleRESTStorage) Export(ctx context.Context, name string, opts
return obj, storage.errors["export"] return obj, storage.errors["export"]
} }
func (storage *SimpleRESTStorage) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (storage *SimpleRESTStorage) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
return rest.NewDefaultTableConvertor(schema.GroupResource{Resource: "simple"}).ConvertToTable(ctx, obj, tableOptions) return rest.NewDefaultTableConvertor(schema.GroupResource{Resource: "simple"}).ConvertToTable(ctx, obj, tableOptions)
} }
@ -895,6 +895,10 @@ func (OnlyGetRESTStorage) List(ctx context.Context, options *metainternalversion
return nil, nil return nil, nil
} }
func (OnlyGetRESTStorage) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
return nil, nil
}
// TestSomeUnimplementedRESTStorage ensures that if a rest.Storage does // TestSomeUnimplementedRESTStorage ensures that if a rest.Storage does
// not implement a given method, that it is literally not registered // not implement a given method, that it is literally not registered
// with the server. We need to have at least one verb supported inorder // with the server. We need to have at least one verb supported inorder
@ -1900,7 +1904,7 @@ func TestGetTable(t *testing.T) {
accept string accept string
params url.Values params url.Values
pretty bool pretty bool
expected *metav1beta1.Table expected *metav1.Table
statusCode int statusCode int
item bool item bool
}{ }{
@ -1935,14 +1939,14 @@ func TestGetTable(t *testing.T) {
{ {
item: true, item: true,
accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io", accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
expected: &metav1beta1.Table{ expected: &metav1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"}, TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"}, ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
ColumnDefinitions: []metav1beta1.TableColumnDefinition{ ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]}, {Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
}, },
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}}, {Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}},
}, },
}, },
@ -1953,14 +1957,14 @@ func TestGetTable(t *testing.T) {
runtime.ContentTypeProtobuf + ";as=Table;v=v1beta1;g=meta.k8s.io", runtime.ContentTypeProtobuf + ";as=Table;v=v1beta1;g=meta.k8s.io",
"application/json;as=Table;v=v1beta1;g=meta.k8s.io", "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
}, ","), }, ","),
expected: &metav1beta1.Table{ expected: &metav1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"}, TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"}, ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
ColumnDefinitions: []metav1beta1.TableColumnDefinition{ ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]}, {Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
}, },
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}}, {Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}},
}, },
}, },
@ -1969,14 +1973,14 @@ func TestGetTable(t *testing.T) {
item: true, item: true,
accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io", accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
params: url.Values{"includeObject": []string{"Metadata"}}, params: url.Values{"includeObject": []string{"Metadata"}},
expected: &metav1beta1.Table{ expected: &metav1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"}, TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"}, ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
ColumnDefinitions: []metav1beta1.TableColumnDefinition{ ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]}, {Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
}, },
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}}, {Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}},
}, },
}, },
@ -1984,14 +1988,14 @@ func TestGetTable(t *testing.T) {
{ {
accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io", accept: "application/json;as=Table;v=v1beta1;g=meta.k8s.io",
params: url.Values{"includeObject": []string{"Metadata"}}, params: url.Values{"includeObject": []string{"Metadata"}},
expected: &metav1beta1.Table{ expected: &metav1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"}, TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/test/link"}, ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/test/link"},
ColumnDefinitions: []metav1beta1.TableColumnDefinition{ ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]}, {Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
}, },
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}}, {Cells: []interface{}{"foo1", now.Time.UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedV1Beta1Body}},
}, },
}, },
@ -2051,7 +2055,7 @@ func TestGetTable(t *testing.T) {
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
t.Errorf("%d: unexpected response: %#v", i, resp) t.Errorf("%d: unexpected response: %#v", i, resp)
} }
var itemOut metav1beta1.Table var itemOut metav1.Table
body, err := extractBody(resp, &itemOut) body, err := extractBody(resp, &itemOut)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -2117,14 +2121,14 @@ func TestWatchTable(t *testing.T) {
{ {
Type: "ADDED", Type: "ADDED",
Object: runtime.RawExtension{ Object: runtime.RawExtension{
Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1beta1.Table{ Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"}, TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"}, ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
ColumnDefinitions: []metav1beta1.TableColumnDefinition{ ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]}, {Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
}, },
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo1", time.Unix(1, 0).UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}}, {Cells: []interface{}{"foo1", time.Unix(1, 0).UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}},
}, },
}))), }))),
@ -2142,14 +2146,14 @@ func TestWatchTable(t *testing.T) {
{ {
Type: "ADDED", Type: "ADDED",
Object: runtime.RawExtension{ Object: runtime.RawExtension{
Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1beta1.Table{ Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"}, TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"}, ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
ColumnDefinitions: []metav1beta1.TableColumnDefinition{ ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]}, {Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
}, },
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo1", time.Unix(1, 0).UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}}, {Cells: []interface{}{"foo1", time.Unix(1, 0).UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}},
}, },
}))), }))),
@ -2158,10 +2162,10 @@ func TestWatchTable(t *testing.T) {
{ {
Type: "MODIFIED", Type: "MODIFIED",
Object: runtime.RawExtension{ Object: runtime.RawExtension{
Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1beta1.Table{ Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"}, TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1beta1"},
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"}, ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
Rows: []metav1beta1.TableRow{ Rows: []metav1.TableRow{
{Cells: []interface{}{"foo1", time.Unix(1, 0).UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}}, {Cells: []interface{}{"foo1", time.Unix(1, 0).UTC().Format(time.RFC3339)}, Object: runtime.RawExtension{Raw: encodedBody}},
}, },
}))), }))),
@ -2182,7 +2186,7 @@ func TestWatchTable(t *testing.T) {
Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1.Table{ Raw: []byte(strings.TrimSpace(runtime.EncodeOrDie(s, &metav1.Table{
TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1"}, TypeMeta: metav1.TypeMeta{Kind: "Table", APIVersion: "meta.k8s.io/v1"},
ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"}, ListMeta: metav1.ListMeta{ResourceVersion: "10", SelfLink: "/blah"},
ColumnDefinitions: []metav1beta1.TableColumnDefinition{ ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metaDoc["name"]},
{Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]}, {Name: "Created At", Type: "date", Description: metaDoc["creationTimestamp"]},
}, },

View File

@ -74,7 +74,7 @@ func doTransformObject(ctx context.Context, obj runtime.Object, opts interface{}
return asPartialObjectMetadataList(obj, target.GroupVersion()) return asPartialObjectMetadataList(obj, target.GroupVersion())
case target.Kind == "Table": case target.Kind == "Table":
options, ok := opts.(*metav1beta1.TableOptions) options, ok := opts.(*metav1.TableOptions)
if !ok { if !ok {
return nil, fmt.Errorf("unexpected TableOptions, got %T", opts) return nil, fmt.Errorf("unexpected TableOptions, got %T", opts)
} }
@ -93,8 +93,8 @@ func optionsForTransform(mediaType negotiation.MediaTypeOptions, req *http.Reque
switch target := mediaType.Convert; { switch target := mediaType.Convert; {
case target == nil: case target == nil:
case target.Kind == "Table" && (target.GroupVersion() == metav1beta1.SchemeGroupVersion || target.GroupVersion() == metav1.SchemeGroupVersion): case target.Kind == "Table" && (target.GroupVersion() == metav1beta1.SchemeGroupVersion || target.GroupVersion() == metav1.SchemeGroupVersion):
opts := &metav1beta1.TableOptions{} opts := &metav1.TableOptions{}
if err := metainternalversionscheme.ParameterCodec.DecodeParameters(req.URL.Query(), metav1beta1.SchemeGroupVersion, opts); err != nil { if err := metainternalversionscheme.ParameterCodec.DecodeParameters(req.URL.Query(), metav1.SchemeGroupVersion, opts); err != nil {
return nil, err return nil, err
} }
switch errs := validation.ValidateTableOptions(opts); len(errs) { switch errs := validation.ValidateTableOptions(opts); len(errs) {
@ -159,7 +159,7 @@ func (e errNotAcceptable) Status() metav1.Status {
} }
} }
func asTable(ctx context.Context, result runtime.Object, opts *metav1beta1.TableOptions, scope *RequestScope, groupVersion schema.GroupVersion) (runtime.Object, error) { func asTable(ctx context.Context, result runtime.Object, opts *metav1.TableOptions, scope *RequestScope, groupVersion schema.GroupVersion) (runtime.Object, error) {
switch groupVersion { switch groupVersion {
case metav1beta1.SchemeGroupVersion, metav1.SchemeGroupVersion: case metav1beta1.SchemeGroupVersion, metav1.SchemeGroupVersion:
default: default:

View File

@ -25,7 +25,6 @@ import (
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer/streaming" "k8s.io/apimachinery/pkg/runtime/serializer/streaming"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@ -125,7 +124,7 @@ func serveWatch(watcher watch.Interface, scope *RequestScope, mediaTypeOptions n
// When we are transformed to a table, use the table options as the state for whether we // When we are transformed to a table, use the table options as the state for whether we
// should print headers - on watch, we only want to print table headers on the first object // should print headers - on watch, we only want to print table headers on the first object
// and omit them on subsequent events. // and omit them on subsequent events.
if tableOptions, ok := options.(*metav1beta1.TableOptions); ok { if tableOptions, ok := options.(*metav1.TableOptions); ok {
tableOptions.NoHeaders = true tableOptions.NoHeaders = true
} }
return result return result

View File

@ -65,7 +65,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/validation/path:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/validation/path:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -29,7 +29,6 @@ import (
"k8s.io/apimachinery/pkg/api/validation/path" "k8s.io/apimachinery/pkg/api/validation/path"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -1353,7 +1352,7 @@ func (e *Store) startObservingCount(period time.Duration) func() {
return func() { close(stopCh) } return func() { close(stopCh) }
} }
func (e *Store) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (e *Store) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
if e.TableConvertor != nil { if e.TableConvertor != nil {
return e.TableConvertor.ConvertToTable(ctx, object, tableOptions) return e.TableConvertor.ConvertToTable(ctx, object, tableOptions)
} }

View File

@ -41,7 +41,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",

View File

@ -24,7 +24,6 @@ import (
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion" metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
@ -99,6 +98,8 @@ type Lister interface {
NewList() runtime.Object NewList() runtime.Object
// List selects resources in the storage which match to the selector. 'options' can be nil. // List selects resources in the storage which match to the selector. 'options' can be nil.
List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error)
// TableConvertor ensures all list implementers also implement table conversion
TableConvertor
} }
// Exporter is an object that knows how to strip a RESTful resource for export. A store should implement this interface // Exporter is an object that knows how to strip a RESTful resource for export. A store should implement this interface
@ -141,7 +142,7 @@ type GetterWithOptions interface {
} }
type TableConvertor interface { type TableConvertor interface {
ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error)
} }
// GracefulDeleter knows how to pass deletion options to allow delayed deletion of a // GracefulDeleter knows how to pass deletion options to allow delayed deletion of a

View File

@ -24,7 +24,6 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
) )
@ -40,14 +39,14 @@ func NewDefaultTableConvertor(resource schema.GroupResource) TableConvertor {
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
func (c defaultTableConvertor) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (c defaultTableConvertor) ConvertToTable(ctx context.Context, object runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
var table metav1beta1.Table var table metav1.Table
fn := func(obj runtime.Object) error { fn := func(obj runtime.Object) error {
m, err := meta.Accessor(obj) m, err := meta.Accessor(obj)
if err != nil { if err != nil {
return errNotAcceptable{resource: c.qualifiedResource} return errNotAcceptable{resource: c.qualifiedResource}
} }
table.Rows = append(table.Rows, metav1beta1.TableRow{ table.Rows = append(table.Rows, metav1.TableRow{
Cells: []interface{}{m.GetName(), m.GetCreationTimestamp().Time.UTC().Format(time.RFC3339)}, Cells: []interface{}{m.GetName(), m.GetCreationTimestamp().Time.UTC().Format(time.RFC3339)},
Object: runtime.RawExtension{Object: obj}, Object: runtime.RawExtension{Object: obj},
}) })
@ -74,8 +73,8 @@ func (c defaultTableConvertor) ConvertToTable(ctx context.Context, object runtim
table.SelfLink = m.GetSelfLink() table.SelfLink = m.GetSelfLink()
} }
} }
if opt, ok := tableOptions.(*metav1beta1.TableOptions); !ok || !opt.NoHeaders { if opt, ok := tableOptions.(*metav1.TableOptions); !ok || !opt.NoHeaders {
table.ColumnDefinitions = []metav1beta1.TableColumnDefinition{ table.ColumnDefinitions = []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]}, {Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]},
{Name: "Created At", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"]}, {Name: "Created At", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"]},
} }

View File

@ -22,7 +22,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",

View File

@ -26,7 +26,6 @@ import (
"github.com/liggitt/tabwriter" "github.com/liggitt/tabwriter"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/duration" "k8s.io/apimachinery/pkg/util/duration"
@ -36,7 +35,7 @@ import (
var _ ResourcePrinter = &HumanReadablePrinter{} var _ ResourcePrinter = &HumanReadablePrinter{}
type printHandler struct { type printHandler struct {
columnDefinitions []metav1beta1.TableColumnDefinition columnDefinitions []metav1.TableColumnDefinition
printFunc reflect.Value printFunc reflect.Value
} }
@ -46,7 +45,7 @@ var (
printFunc: reflect.ValueOf(printStatus), printFunc: reflect.ValueOf(printStatus),
} }
statusColumnDefinitions = []metav1beta1.TableColumnDefinition{ statusColumnDefinitions = []metav1.TableColumnDefinition{
{Name: "Status", Type: "string"}, {Name: "Status", Type: "string"},
{Name: "Reason", Type: "string"}, {Name: "Reason", Type: "string"},
{Name: "Message", Type: "string"}, {Name: "Message", Type: "string"},
@ -57,7 +56,7 @@ var (
printFunc: reflect.ValueOf(printObjectMeta), printFunc: reflect.ValueOf(printObjectMeta),
} }
objectMetaColumnDefinitions = []metav1beta1.TableColumnDefinition{ objectMetaColumnDefinitions = []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
{Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
} }
@ -73,7 +72,7 @@ var (
type HumanReadablePrinter struct { type HumanReadablePrinter struct {
options PrintOptions options PrintOptions
lastType interface{} lastType interface{}
lastColumns []metav1beta1.TableColumnDefinition lastColumns []metav1.TableColumnDefinition
printedHeaders bool printedHeaders bool
} }
@ -110,7 +109,7 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
// Parameter "obj" is a table from server; print it. // Parameter "obj" is a table from server; print it.
// display tables following the rules of options // display tables following the rules of options
if table, ok := obj.(*metav1beta1.Table); ok { if table, ok := obj.(*metav1.Table); ok {
// Do not print headers if this table has no column definitions, or they are the same as the last ones we printed // Do not print headers if this table has no column definitions, or they are the same as the last ones we printed
localOptions := h.options localOptions := h.options
if h.printedHeaders && (len(table.ColumnDefinitions) == 0 || reflect.DeepEqual(table.ColumnDefinitions, h.lastColumns)) { if h.printedHeaders && (len(table.ColumnDefinitions) == 0 || reflect.DeepEqual(table.ColumnDefinitions, h.lastColumns)) {
@ -136,8 +135,8 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
} }
if len(eventType) > 0 { if len(eventType) > 0 {
if err := addColumns(beginning, table, if err := addColumns(beginning, table,
[]metav1beta1.TableColumnDefinition{{Name: "Event", Type: "string"}}, []metav1.TableColumnDefinition{{Name: "Event", Type: "string"}},
[]cellValueFunc{func(metav1beta1.TableRow) (interface{}, error) { return formatEventType(eventType), nil }}, []cellValueFunc{func(metav1.TableRow) (interface{}, error) { return formatEventType(eventType), nil }},
); err != nil { ); err != nil {
return err return err
} }
@ -171,7 +170,7 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
// printTable prints a table to the provided output respecting the filtering rules for options // printTable prints a table to the provided output respecting the filtering rules for options
// for wide columns and filtered rows. It filters out rows that are Completed. You should call // for wide columns and filtered rows. It filters out rows that are Completed. You should call
// decorateTable if you receive a table from a remote server before calling printTable. // decorateTable if you receive a table from a remote server before calling printTable.
func printTable(table *metav1beta1.Table, output io.Writer, options PrintOptions) error { func printTable(table *metav1.Table, output io.Writer, options PrintOptions) error {
if !options.NoHeaders { if !options.NoHeaders {
// avoid printing headers if we have no rows to display // avoid printing headers if we have no rows to display
if len(table.Rows) == 0 { if len(table.Rows) == 0 {
@ -218,7 +217,7 @@ func printTable(table *metav1beta1.Table, output io.Writer, options PrintOptions
return nil return nil
} }
type cellValueFunc func(metav1beta1.TableRow) (interface{}, error) type cellValueFunc func(metav1.TableRow) (interface{}, error)
type columnAddPosition int type columnAddPosition int
@ -227,7 +226,7 @@ const (
end columnAddPosition = 2 end columnAddPosition = 2
) )
func addColumns(pos columnAddPosition, table *metav1beta1.Table, columns []metav1beta1.TableColumnDefinition, valueFuncs []cellValueFunc) error { func addColumns(pos columnAddPosition, table *metav1.Table, columns []metav1.TableColumnDefinition, valueFuncs []cellValueFunc) error {
if len(columns) != len(valueFuncs) { if len(columns) != len(valueFuncs) {
return fmt.Errorf("cannot prepend columns, unmatched value functions") return fmt.Errorf("cannot prepend columns, unmatched value functions")
} }
@ -268,7 +267,7 @@ func addColumns(pos columnAddPosition, table *metav1beta1.Table, columns []metav
} }
// All cells successfully computed, now replace columns and rows // All cells successfully computed, now replace columns and rows
newColumns := make([]metav1beta1.TableColumnDefinition, 0, len(columns)+len(table.ColumnDefinitions)) newColumns := make([]metav1.TableColumnDefinition, 0, len(columns)+len(table.ColumnDefinitions))
switch pos { switch pos {
case beginning: case beginning:
newColumns = append(newColumns, columns...) newColumns = append(newColumns, columns...)
@ -291,7 +290,7 @@ func addColumns(pos columnAddPosition, table *metav1beta1.Table, columns []metav
// namespace column. It will fill empty columns with nil (if the object // namespace column. It will fill empty columns with nil (if the object
// does not expose metadata). It returns an error if the table cannot // does not expose metadata). It returns an error if the table cannot
// be decorated. // be decorated.
func decorateTable(table *metav1beta1.Table, options PrintOptions) error { func decorateTable(table *metav1.Table, options PrintOptions) error {
width := len(table.ColumnDefinitions) + len(options.ColumnLabels) width := len(table.ColumnDefinitions) + len(options.ColumnLabels)
if options.WithNamespace { if options.WithNamespace {
width++ width++
@ -313,22 +312,22 @@ func decorateTable(table *metav1beta1.Table, options PrintOptions) error {
} }
if width != len(table.ColumnDefinitions) { if width != len(table.ColumnDefinitions) {
columns = make([]metav1beta1.TableColumnDefinition, 0, width) columns = make([]metav1.TableColumnDefinition, 0, width)
if options.WithNamespace { if options.WithNamespace {
columns = append(columns, metav1beta1.TableColumnDefinition{ columns = append(columns, metav1.TableColumnDefinition{
Name: "Namespace", Name: "Namespace",
Type: "string", Type: "string",
}) })
} }
columns = append(columns, table.ColumnDefinitions...) columns = append(columns, table.ColumnDefinitions...)
for _, label := range formatLabelHeaders(options.ColumnLabels) { for _, label := range formatLabelHeaders(options.ColumnLabels) {
columns = append(columns, metav1beta1.TableColumnDefinition{ columns = append(columns, metav1.TableColumnDefinition{
Name: label, Name: label,
Type: "string", Type: "string",
}) })
} }
if options.ShowLabels { if options.ShowLabels {
columns = append(columns, metav1beta1.TableColumnDefinition{ columns = append(columns, metav1.TableColumnDefinition{
Name: "Labels", Name: "Labels",
Type: "string", Type: "string",
}) })
@ -417,7 +416,7 @@ func printRowsForHandlerEntry(output io.Writer, handler *printHandler, eventType
} }
if results[1].IsNil() { if results[1].IsNil() {
rows := results[0].Interface().([]metav1beta1.TableRow) rows := results[0].Interface().([]metav1.TableRow)
printRows(output, eventType, rows, options) printRows(output, eventType, rows, options)
return nil return nil
} }
@ -439,7 +438,7 @@ func formatEventType(eventType string) string {
} }
// printRows writes the provided rows to output. // printRows writes the provided rows to output.
func printRows(output io.Writer, eventType string, rows []metav1beta1.TableRow, options PrintOptions) { func printRows(output io.Writer, eventType string, rows []metav1.TableRow, options PrintOptions) {
for _, row := range rows { for _, row := range rows {
if len(eventType) > 0 { if len(eventType) > 0 {
fmt.Fprint(output, formatEventType(eventType)) fmt.Fprint(output, formatEventType(eventType))
@ -522,20 +521,20 @@ func appendLabelCells(values []interface{}, itemLabels map[string]string, opts P
return values return values
} }
func printStatus(obj runtime.Object, options PrintOptions) ([]metav1beta1.TableRow, error) { func printStatus(obj runtime.Object, options PrintOptions) ([]metav1.TableRow, error) {
status, ok := obj.(*metav1.Status) status, ok := obj.(*metav1.Status)
if !ok { if !ok {
return nil, fmt.Errorf("expected *v1.Status, got %T", obj) return nil, fmt.Errorf("expected *v1.Status, got %T", obj)
} }
return []metav1beta1.TableRow{{ return []metav1.TableRow{{
Object: runtime.RawExtension{Object: obj}, Object: runtime.RawExtension{Object: obj},
Cells: []interface{}{status.Status, status.Reason, status.Message}, Cells: []interface{}{status.Status, status.Reason, status.Message},
}}, nil }}, nil
} }
func printObjectMeta(obj runtime.Object, options PrintOptions) ([]metav1beta1.TableRow, error) { func printObjectMeta(obj runtime.Object, options PrintOptions) ([]metav1.TableRow, error) {
if meta.IsListType(obj) { if meta.IsListType(obj) {
rows := make([]metav1beta1.TableRow, 0, 16) rows := make([]metav1.TableRow, 0, 16)
err := meta.EachListItem(obj, func(obj runtime.Object) error { err := meta.EachListItem(obj, func(obj runtime.Object) error {
nestedRows, err := printObjectMeta(obj, options) nestedRows, err := printObjectMeta(obj, options)
if err != nil { if err != nil {
@ -550,12 +549,12 @@ func printObjectMeta(obj runtime.Object, options PrintOptions) ([]metav1beta1.Ta
return rows, nil return rows, nil
} }
rows := make([]metav1beta1.TableRow, 0, 1) rows := make([]metav1.TableRow, 0, 1)
m, err := meta.Accessor(obj) m, err := meta.Accessor(obj)
if err != nil { if err != nil {
return nil, err return nil, err
} }
row := metav1beta1.TableRow{ row := metav1.TableRow{
Object: runtime.RawExtension{Object: obj}, Object: runtime.RawExtension{Object: obj},
} }
row.Cells = append(row.Cells, m.GetName(), translateTimestampSince(m.GetCreationTimestamp())) row.Cells = append(row.Cells, m.GetName(), translateTimestampSince(m.GetCreationTimestamp()))

View File

@ -14,7 +14,6 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta/table:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/meta/table:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",

View File

@ -23,7 +23,6 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metatable "k8s.io/apimachinery/pkg/api/meta/table" metatable "k8s.io/apimachinery/pkg/api/meta/table"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
@ -60,9 +59,9 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
// ConvertToTable implements the TableConvertor interface for REST. // ConvertToTable implements the TableConvertor interface for REST.
func (c *REST) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (c *REST) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1.Table, error) {
table := &metav1beta1.Table{ table := &metav1.Table{
ColumnDefinitions: []metav1beta1.TableColumnDefinition{ ColumnDefinitions: []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]}, {Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]},
{Name: "Service", Type: "string", Description: "The reference to the service that hosts this API endpoint."}, {Name: "Service", Type: "string", Description: "The reference to the service that hosts this API endpoint."},
{Name: "Available", Type: "string", Description: "Whether this service is available."}, {Name: "Available", Type: "string", Description: "Whether this service is available."},

View File

@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"io" "io"
"net/url" "net/url"
"strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -351,7 +352,7 @@ func (r *RuntimeSorter) Sort() error {
return nil return nil
} }
if len(r.objects) == 1 { if len(r.objects) == 1 {
_, isTable := r.objects[0].(*metav1beta1.Table) _, isTable := r.objects[0].(*metav1.Table)
if !isTable { if !isTable {
return nil return nil
} }
@ -362,7 +363,7 @@ func (r *RuntimeSorter) Sort() error {
for _, obj := range r.objects { for _, obj := range r.objects {
switch t := obj.(type) { switch t := obj.(type) {
case *metav1beta1.Table: case *metav1.Table:
includesTable = true includesTable = true
if sorter, err := NewTableSorter(t, r.field); err != nil { if sorter, err := NewTableSorter(t, r.field); err != nil {
@ -433,11 +434,11 @@ func (o *GetOptions) transformRequests(req *rest.Request) {
return return
} }
group := metav1beta1.GroupName req.SetHeader("Accept", strings.Join([]string{
version := metav1beta1.SchemeGroupVersion.Version fmt.Sprintf("application/json;as=Table;v=%s;g=%s", metav1.SchemeGroupVersion.Version, metav1.GroupName),
fmt.Sprintf("application/json;as=Table;v=%s;g=%s", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName),
tableParam := fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", version, group) "application/json",
req.SetHeader("Accept", tableParam) }, ","))
// if sorting, ensure we receive the full object in order to introspect its fields via jsonpath // if sorting, ensure we receive the full object in order to introspect its fields via jsonpath
if o.Sort { if o.Sort {

View File

@ -18,6 +18,7 @@ package get
import ( import (
"bytes" "bytes"
"encoding/json"
encjson "encoding/json" encjson "encoding/json"
"fmt" "fmt"
"io" "io"
@ -267,6 +268,31 @@ foo 0/0 0 <unknown>
} }
} }
func TestGetV1TableObjects(t *testing.T) {
pods, _, _ := cmdtesting.TestData()
tf := cmdtesting.NewTestFactory().WithNamespace("test")
defer tf.Cleanup()
codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
tf.UnstructuredClient = &fake.RESTClient{
NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
Resp: &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: podV1TableObjBody(codec, pods.Items[0])},
}
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdGet("kubectl", tf, streams)
cmd.SetOutput(buf)
cmd.Run(cmd, []string{"pods", "foo"})
expected := `NAME READY STATUS RESTARTS AGE
foo 0/0 0 <unknown>
`
if e, a := expected, buf.String(); e != a {
t.Errorf("expected\n%v\ngot\n%v", e, a)
}
}
func TestGetObjectsShowKind(t *testing.T) { func TestGetObjectsShowKind(t *testing.T) {
pods, _, _ := cmdtesting.TestData() pods, _, _ := cmdtesting.TestData()
@ -2706,7 +2732,32 @@ var podColumns = []metav1.TableColumnDefinition{
// build a meta table response from a pod list // build a meta table response from a pod list
func podTableObjBody(codec runtime.Codec, pods ...corev1.Pod) io.ReadCloser { func podTableObjBody(codec runtime.Codec, pods ...corev1.Pod) io.ReadCloser {
table := &metav1beta1.Table{
TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1beta1", Kind: "Table"},
ColumnDefinitions: podColumns,
}
for i := range pods {
b := bytes.NewBuffer(nil)
codec.Encode(&pods[i], b)
table.Rows = append(table.Rows, metav1beta1.TableRow{
Object: runtime.RawExtension{Raw: b.Bytes()},
Cells: []interface{}{pods[i].Name, "0/0", "", int64(0), "<unknown>", "<none>", "<none>", "<none>", "<none>"},
})
}
data, err := json.Marshal(table)
if err != nil {
panic(err)
}
if !strings.Contains(string(data), `"meta.k8s.io/v1beta1"`) {
panic("expected v1beta1, got " + string(data))
}
return cmdtesting.BytesBody(data)
}
// build a meta table response from a pod list
func podV1TableObjBody(codec runtime.Codec, pods ...corev1.Pod) io.ReadCloser {
table := &metav1.Table{ table := &metav1.Table{
TypeMeta: metav1.TypeMeta{APIVersion: "meta.k8s.io/v1", Kind: "Table"},
ColumnDefinitions: podColumns, ColumnDefinitions: podColumns,
} }
for i := range pods { for i := range pods {
@ -2717,7 +2768,14 @@ func podTableObjBody(codec runtime.Codec, pods ...corev1.Pod) io.ReadCloser {
Cells: []interface{}{pods[i].Name, "0/0", "", int64(0), "<unknown>", "<none>", "<none>", "<none>", "<none>"}, Cells: []interface{}{pods[i].Name, "0/0", "", int64(0), "<unknown>", "<none>", "<none>", "<none>", "<none>"},
}) })
} }
return cmdtesting.ObjBody(codec, table) data, err := json.Marshal(table)
if err != nil {
panic(err)
}
if !strings.Contains(string(data), `"meta.k8s.io/v1"`) {
panic("expected v1, got " + string(data))
}
return cmdtesting.BytesBody(data)
} }
// build meta table watch events from pod watch events // build meta table watch events from pod watch events

View File

@ -19,7 +19,7 @@ package get
import ( import (
"io" "io"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/printers"
) )
@ -37,7 +37,7 @@ func (p *skipPrinter) PrintObj(obj runtime.Object, writer io.Writer) error {
return p.delegate.PrintObj(obj, writer) return p.delegate.PrintObj(obj, writer)
} }
table, isTable := obj.(*metav1beta1.Table) table, isTable := obj.(*metav1.Table)
if !isTable { if !isTable {
return nil return nil
} }

View File

@ -28,7 +28,6 @@ import (
"k8s.io/apimachinery/pkg/api/meta" "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/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/printers"
"k8s.io/client-go/util/jsonpath" "k8s.io/client-go/util/jsonpath"
@ -46,7 +45,7 @@ type SortingPrinter struct {
} }
func (s *SortingPrinter) PrintObj(obj runtime.Object, out io.Writer) error { func (s *SortingPrinter) PrintObj(obj runtime.Object, out io.Writer) error {
if table, isTable := obj.(*metav1beta1.Table); isTable && len(table.Rows) > 1 { if table, isTable := obj.(*metav1.Table); isTable && len(table.Rows) > 1 {
parsedField, err := RelaxedJSONPathExpression(s.SortField) parsedField, err := RelaxedJSONPathExpression(s.SortField)
if err != nil { if err != nil {
parsedField = s.SortField parsedField = s.SortField
@ -322,7 +321,7 @@ func (r *RuntimeSort) OriginalPosition(ix int) int {
type TableSorter struct { type TableSorter struct {
field string field string
obj *metav1beta1.Table obj *metav1.Table
parsedRows [][][]reflect.Value parsedRows [][][]reflect.Value
} }
@ -361,7 +360,7 @@ func (t *TableSorter) Sort() error {
return nil return nil
} }
func NewTableSorter(table *metav1beta1.Table, field string) (*TableSorter, error) { func NewTableSorter(table *metav1.Table, field string) (*TableSorter, error) {
var parsedRows [][][]reflect.Value var parsedRows [][][]reflect.Value
parser := jsonpath.New("sorting").AllowMissingKeys(true) parser := jsonpath.New("sorting").AllowMissingKeys(true)

View File

@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/printers"
"k8s.io/klog" "k8s.io/klog"
) )
@ -45,24 +46,26 @@ func (t *TablePrinter) PrintObj(obj runtime.Object, writer io.Writer) error {
return t.Delegate.PrintObj(obj, writer) return t.Delegate.PrintObj(obj, writer)
} }
var recognizedTableVersions = map[schema.GroupVersionKind]bool{
metav1beta1.SchemeGroupVersion.WithKind("Table"): true,
metav1.SchemeGroupVersion.WithKind("Table"): true,
}
func decodeIntoTable(obj runtime.Object) (runtime.Object, error) { func decodeIntoTable(obj runtime.Object) (runtime.Object, error) {
event, isEvent := obj.(*metav1.WatchEvent) event, isEvent := obj.(*metav1.WatchEvent)
if isEvent { if isEvent {
obj = event.Object.Object obj = event.Object.Object
} }
if obj.GetObjectKind().GroupVersionKind().Group != metav1beta1.GroupName { if !recognizedTableVersions[obj.GetObjectKind().GroupVersionKind()] {
return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table") return nil, fmt.Errorf("attempt to decode non-Table object")
}
if obj.GetObjectKind().GroupVersionKind().Kind != "Table" {
return nil, fmt.Errorf("attempt to decode non-Table object into a v1beta1.Table")
} }
unstr, ok := obj.(*unstructured.Unstructured) unstr, ok := obj.(*unstructured.Unstructured)
if !ok { if !ok {
return nil, fmt.Errorf("attempt to decode non-Unstructured object") return nil, fmt.Errorf("attempt to decode non-Unstructured object")
} }
table := &metav1beta1.Table{} table := &metav1.Table{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstr.Object, table); err != nil { if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstr.Object, table); err != nil {
return nil, err return nil, err
} }