mirror of https://github.com/k3s-io/k3s
Give APIServer pretty column output
Simple server side render that prints the implementing service (if any) and the available condition. ``` $ kubectl get apiservice NAME SERVICE AVAILABLE AGE v1. Local True 10m v1.apps Local True 10m v1.authentication.k8s.io Local True 10m v2beta1.autoscaling Local True 10m v1beta1.metrics kube-system/metrics-server False (DiscoveryFailed) 10m ```pull/8/head
parent
5a16163c87
commit
b06d4b7884
|
@ -654,6 +654,10 @@
|
|||
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/meta/table",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
@ -754,6 +758,10 @@
|
|||
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/duration",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
|
||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
|
|
@ -11,7 +11,10 @@ go_library(
|
|||
importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd",
|
||||
importpath = "k8s.io/kube-aggregator/pkg/registry/apiservice/etcd",
|
||||
deps = [
|
||||
"//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/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/apiserver/pkg/registry/generic:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
|
||||
|
|
|
@ -18,8 +18,12 @@ package etcd
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metatable "k8s.io/apimachinery/pkg/api/meta/table"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
|
@ -53,6 +57,60 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST
|
|||
return &REST{store}
|
||||
}
|
||||
|
||||
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
|
||||
|
||||
func (c *REST) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) {
|
||||
table := &metav1beta1.Table{
|
||||
ColumnDefinitions: []metav1beta1.TableColumnDefinition{
|
||||
{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: "Available", Type: "string", Description: "Whether this service is available."},
|
||||
{Name: "Age", Type: "string", Description: swaggerMetadataDescriptions["creationTimestamp"]},
|
||||
},
|
||||
}
|
||||
if m, err := meta.ListAccessor(obj); err == nil {
|
||||
table.ResourceVersion = m.GetResourceVersion()
|
||||
table.SelfLink = m.GetSelfLink()
|
||||
table.Continue = m.GetContinue()
|
||||
} else {
|
||||
if m, err := meta.CommonAccessor(obj); err == nil {
|
||||
table.ResourceVersion = m.GetResourceVersion()
|
||||
table.SelfLink = m.GetSelfLink()
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) {
|
||||
svc := obj.(*apiregistration.APIService)
|
||||
service := "Local"
|
||||
if svc.Spec.Service != nil {
|
||||
service = fmt.Sprintf("%s/%s", svc.Spec.Service.Namespace, svc.Spec.Service.Name)
|
||||
}
|
||||
status := string(apiregistration.ConditionUnknown)
|
||||
if condition := getCondition(svc.Status.Conditions, "Available"); condition != nil {
|
||||
switch {
|
||||
case condition.Status == apiregistration.ConditionTrue:
|
||||
status = string(condition.Status)
|
||||
case len(condition.Reason) > 0:
|
||||
status = fmt.Sprintf("%s (%s)", condition.Status, condition.Reason)
|
||||
default:
|
||||
status = string(condition.Status)
|
||||
}
|
||||
}
|
||||
return []interface{}{name, service, status, age}, nil
|
||||
})
|
||||
return table, err
|
||||
}
|
||||
|
||||
func getCondition(conditions []apiregistration.APIServiceCondition, conditionType apiregistration.APIServiceConditionType) *apiregistration.APIServiceCondition {
|
||||
for i, condition := range conditions {
|
||||
if condition.Type == conditionType {
|
||||
return &conditions[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewStatusREST makes a RESTStorage for status that has more limited options.
|
||||
// It is based on the original REST so that we can share the same underlying store
|
||||
func NewStatusREST(scheme *runtime.Scheme, rest *REST) *StatusREST {
|
||||
|
|
Loading…
Reference in New Issue