From 6ab79a9f2f02e57e0c5023b0f4570bcc707b296e Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Wed, 8 Nov 2023 10:59:19 -0800 Subject: [PATCH] K8s: Improve table converter (support non runtime.Object values) (#77816) --- pkg/registry/apis/playlist/register.go | 2 +- .../grafana-apiserver/utils/tableConverter.go | 38 ++++++++++++++++++- .../utils/tableConverter_test.go | 33 ++++++++++++++-- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/pkg/registry/apis/playlist/register.go b/pkg/registry/apis/playlist/register.go index 0934c796237..47ea4a34c23 100644 --- a/pkg/registry/apis/playlist/register.go +++ b/pkg/registry/apis/playlist/register.go @@ -99,7 +99,7 @@ func (b *PlaylistAPIBuilder) GetAPIGroupInfo( {Name: "Interval", Type: "string", Format: "string", Description: "How often the playlist will update"}, {Name: "Created At", Type: "date"}, }, - func(obj runtime.Object) ([]interface{}, error) { + func(obj any) ([]interface{}, error) { m, ok := obj.(*playlist.Playlist) if !ok { return nil, fmt.Errorf("expected playlist") diff --git a/pkg/services/grafana-apiserver/utils/tableConverter.go b/pkg/services/grafana-apiserver/utils/tableConverter.go index e4cc54823a6..755dc8f74f4 100644 --- a/pkg/services/grafana-apiserver/utils/tableConverter.go +++ b/pkg/services/grafana-apiserver/utils/tableConverter.go @@ -4,6 +4,8 @@ import ( "context" "fmt" "net/http" + "reflect" + "time" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -17,10 +19,10 @@ import ( type customTableConvertor struct { gr schema.GroupResource columns []metav1.TableColumnDefinition - reader func(obj runtime.Object) ([]interface{}, error) + reader func(obj any) ([]interface{}, error) } -func NewTableConverter(gr schema.GroupResource, columns []metav1.TableColumnDefinition, reader func(obj runtime.Object) ([]interface{}, error)) rest.TableConvertor { +func NewTableConverter(gr schema.GroupResource, columns []metav1.TableColumnDefinition, reader func(obj any) ([]interface{}, error)) rest.TableConvertor { converter := customTableConvertor{ gr: gr, columns: columns, @@ -40,6 +42,38 @@ func NewTableConverter(gr schema.GroupResource, columns []metav1.TableColumnDefi return converter } +func NewDefaultTableConverter(gr schema.GroupResource) rest.TableConvertor { + return NewTableConverter(gr, + []metav1.TableColumnDefinition{ + {Name: "Name", Type: "string", Format: "name"}, + {Name: "Created At", Type: "date"}, + }, + func(obj any) ([]interface{}, error) { + v, err := meta.Accessor(obj) + if err == nil && v != nil { + return []interface{}{ + v.GetName(), + v.GetCreationTimestamp().UTC().Format(time.RFC3339), + }, nil + } + + r := reflect.ValueOf(obj).Elem() + n := r.FieldByName("Name").String() + if n != "" { + return []interface{}{ + n, + "", + }, nil + } + + return []interface{}{ + fmt.Sprintf("%v", obj), + "", + }, nil + }, + ) +} + var _ rest.TableConvertor = &customTableConvertor{} var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() diff --git a/pkg/services/grafana-apiserver/utils/tableConverter_test.go b/pkg/services/grafana-apiserver/utils/tableConverter_test.go index 13bb62a71d8..ec1310475c9 100644 --- a/pkg/services/grafana-apiserver/utils/tableConverter_test.go +++ b/pkg/services/grafana-apiserver/utils/tableConverter_test.go @@ -7,11 +7,11 @@ import ( "testing" "time" - "github.com/grafana/grafana/pkg/services/grafana-apiserver/utils" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/grafana/grafana/pkg/services/grafana-apiserver/utils" ) func TestTableConverter(t *testing.T) { @@ -23,7 +23,7 @@ func TestTableConverter(t *testing.T) { {Name: "Dummy", Type: "string", Format: "string", Description: "Something here"}, {Name: "Created At", Type: "date"}, }, - func(obj runtime.Object) ([]interface{}, error) { + func(obj any) ([]interface{}, error) { m, ok := obj.(*metav1.APIGroup) if !ok { return nil, fmt.Errorf("expected status") @@ -94,4 +94,31 @@ func TestTableConverter(t *testing.T) { require.Error(t, err) require.Nil(t, table) require.Equal(t, "the resource y.x does not support being converted to a Table", err.Error()) + + // Default table converter + // Convert a single table + converter = utils.NewDefaultTableConverter(schema.GroupResource{Group: "x", Resource: "y"}) + table, err = converter.ConvertToTable(context.Background(), &metav1.APIGroup{ + Name: "hello", + }, nil) + require.NoError(t, err) + out, err = json.MarshalIndent(table.Rows, "", " ") + require.NoError(t, err) + //fmt.Printf("%s", string(out)) + require.JSONEq(t, `[ + { + "cells": [ + "hello", + "" + ], + "object": { + "name": "hello", + "versions": null, + "preferredVersion": { + "groupVersion": "", + "version": "" + } + } + } + ]`, string(out)) }