Refactor printers to support rendering as a Table

Return tables from the server.

Kubernetes-commit: 7ce63eb608cdf95df429d6138ccf8dbf8b47a740
This commit is contained in:
Clayton Coleman 2017-05-26 19:00:01 -04:00 committed by Kubernetes Publisher
parent e1228ec319
commit afe291fde8
6 changed files with 31 additions and 16 deletions

View File

@ -34,7 +34,7 @@ import (
// transformResponseObject takes an object loaded from storage and performs any necessary transformations.
// Will write the complete response object.
func transformResponseObject(ctx request.Context, scope RequestScope, req *http.Request, w http.ResponseWriter, statusCode int, result runtime.Object) {
// TODO: use returned serializer
// TODO: fetch the media type much earlier in request processing and pass it into this method.
mediaType, _, err := negotiation.NegotiateOutputMediaType(req, scope.Serializer, &scope)
if err != nil {
status := responsewriters.ErrorToAPIStatus(err)
@ -169,7 +169,7 @@ func transformResponseObject(ctx request.Context, scope RequestScope, req *http.
}
}
responsewriters.WriteObject(statusCode, scope.Kind.GroupVersion(), scope.Serializer, result, w, req)
responsewriters.WriteObject(ctx, statusCode, scope.Kind.GroupVersion(), scope.Serializer, result, w, req)
}
// errNotAcceptable indicates Accept negotiation has failed

View File

@ -62,6 +62,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/api/validation/path:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/api/validation/path"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1alpha1 "k8s.io/apimachinery/pkg/apis/meta/v1alpha1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
@ -154,6 +155,9 @@ type Store struct {
// ExportStrategy implements resource-specific behavior during export,
// optional. Exported objects are not decorated.
ExportStrategy rest.RESTExportStrategy
// TableConvertor is an optional interface for transforming items or lists
// of items into tabular output. If unset, the default will be used.
TableConvertor rest.TableConvertor
// Storage is the interface for the underlying storage for the resource.
Storage storage.Interface
@ -168,6 +172,7 @@ type Store struct {
// Note: the rest.StandardStorage interface aggregates the common REST verbs
var _ rest.StandardStorage = &Store{}
var _ rest.Exporter = &Store{}
var _ rest.TableConvertor = &Store{}
const OptimisticLockErrorMsg = "the object has been modified; please apply your changes to the latest version and try again"
@ -1233,3 +1238,10 @@ func (e *Store) CompleteWithOptions(options *generic.StoreOptions) error {
return nil
}
func (e *Store) ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1alpha1.Table, error) {
if e.TableConvertor != nil {
return e.TableConvertor.ConvertToTable(ctx, object, tableOptions)
}
return rest.DefaultTableConvertor.ConvertToTable(ctx, object, tableOptions)
}

View File

@ -31,6 +31,7 @@ go_library(
"export.go",
"meta.go",
"rest.go",
"table.go",
"update.go",
],
tags = ["automanaged"],
@ -42,6 +43,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library",

View File

@ -118,7 +118,7 @@ type GetterWithOptions interface {
}
type TableConvertor interface {
ConvertToTableList(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1alpha1.TableList, error)
ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1alpha1.Table, error)
}
// Deleter is an object that can delete a named RESTful resource.

View File

@ -32,15 +32,15 @@ type defaultTableConvertor struct{}
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
func (defaultTableConvertor) ConvertToTableList(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1alpha1.TableList, error) {
var table metav1alpha1.TableList
func (defaultTableConvertor) ConvertToTable(ctx genericapirequest.Context, object runtime.Object, tableOptions runtime.Object) (*metav1alpha1.Table, error) {
var table metav1alpha1.Table
fn := func(obj runtime.Object) error {
m, err := meta.Accessor(obj)
if err != nil {
// TODO: skip objects we don't recognize
return nil
}
table.Items = append(table.Items, metav1alpha1.TableListItem{
table.Rows = append(table.Rows, metav1alpha1.TableRow{
Cells: []interface{}{m.GetClusterName(), m.GetNamespace(), m.GetName(), m.GetCreationTimestamp().Time.UTC().Format(time.RFC3339)},
Object: runtime.RawExtension{Object: obj},
})
@ -56,7 +56,7 @@ func (defaultTableConvertor) ConvertToTableList(ctx genericapirequest.Context, o
return nil, err
}
}
table.Headers = []metav1alpha1.TableListHeader{
table.ColumnDefinitions = []metav1alpha1.TableColumnDefinition{
{Name: "Cluster Name", Type: "string", Description: swaggerMetadataDescriptions["clusterName"]},
{Name: "Namespace", Type: "string", Description: swaggerMetadataDescriptions["namespace"]},
{Name: "Name", Type: "string", Description: swaggerMetadataDescriptions["name"]},
@ -71,8 +71,8 @@ func (defaultTableConvertor) ConvertToTableList(ctx genericapirequest.Context, o
return &table, nil
}
func trimColumn(column int, table *metav1alpha1.TableList) bool {
for _, item := range table.Items {
func trimColumn(column int, table *metav1alpha1.Table) bool {
for _, item := range table.Rows {
switch t := item.Cells[column].(type) {
case string:
if len(t) > 0 {
@ -85,22 +85,22 @@ func trimColumn(column int, table *metav1alpha1.TableList) bool {
}
}
if column == 0 {
table.Headers = table.Headers[1:]
table.ColumnDefinitions = table.ColumnDefinitions[1:]
} else {
for j := column; j < len(table.Headers); j++ {
table.Headers[j] = table.Headers[j+1]
for j := column; j < len(table.ColumnDefinitions); j++ {
table.ColumnDefinitions[j] = table.ColumnDefinitions[j+1]
}
}
for i := range table.Items {
cells := table.Items[i].Cells
for i := range table.Rows {
cells := table.Rows[i].Cells
if column == 0 {
table.Items[i].Cells = cells[1:]
table.Rows[i].Cells = cells[1:]
continue
}
for j := column; j < len(cells); j++ {
cells[j] = cells[j+1]
}
table.Items[i].Cells = cells[:len(cells)-1]
table.Rows[i].Cells = cells[:len(cells)-1]
}
return true
}