Skip to content

Commit 993cac1

Browse files
Merge pull request #67747 from smarterclayton/fix_apiservice
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here: https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md. 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 ``` @liggitt @deads2k helps to debug why controllers block (aggregate api is down) ```release-note `kubectl get apiservice` now shows the target service and whether the service is available ``` Kubernetes-commit: 72ef97a1411293f39b918f7eca9f95324c6d46e9
2 parents 4f01d79 + 2dc3713 commit 993cac1

File tree

29 files changed

+2049
-1441
lines changed

29 files changed

+2049
-1441
lines changed

Godeps/Godeps.json

Lines changed: 318 additions & 310 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/registry/apiservice/etcd/etcd.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ package etcd
1818

1919
import (
2020
"context"
21+
"fmt"
2122

23+
"k8s.io/apimachinery/pkg/api/meta"
24+
metatable "k8s.io/apimachinery/pkg/api/meta/table"
2225
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
2327
"k8s.io/apimachinery/pkg/runtime"
2428
"k8s.io/apiserver/pkg/registry/generic"
2529
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
@@ -53,6 +57,60 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST
5357
return &REST{store}
5458
}
5559

60+
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
61+
62+
func (c *REST) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) {
63+
table := &metav1beta1.Table{
64+
ColumnDefinitions: []metav1beta1.TableColumnDefinition{
65+
{Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]},
66+
{Name: "Service", Type: "string", Description: "The reference to the service that hosts this API endpoint."},
67+
{Name: "Available", Type: "string", Description: "Whether this service is available."},
68+
{Name: "Age", Type: "string", Description: swaggerMetadataDescriptions["creationTimestamp"]},
69+
},
70+
}
71+
if m, err := meta.ListAccessor(obj); err == nil {
72+
table.ResourceVersion = m.GetResourceVersion()
73+
table.SelfLink = m.GetSelfLink()
74+
table.Continue = m.GetContinue()
75+
} else {
76+
if m, err := meta.CommonAccessor(obj); err == nil {
77+
table.ResourceVersion = m.GetResourceVersion()
78+
table.SelfLink = m.GetSelfLink()
79+
}
80+
}
81+
82+
var err error
83+
table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) {
84+
svc := obj.(*apiregistration.APIService)
85+
service := "Local"
86+
if svc.Spec.Service != nil {
87+
service = fmt.Sprintf("%s/%s", svc.Spec.Service.Namespace, svc.Spec.Service.Name)
88+
}
89+
status := string(apiregistration.ConditionUnknown)
90+
if condition := getCondition(svc.Status.Conditions, "Available"); condition != nil {
91+
switch {
92+
case condition.Status == apiregistration.ConditionTrue:
93+
status = string(condition.Status)
94+
case len(condition.Reason) > 0:
95+
status = fmt.Sprintf("%s (%s)", condition.Status, condition.Reason)
96+
default:
97+
status = string(condition.Status)
98+
}
99+
}
100+
return []interface{}{name, service, status, age}, nil
101+
})
102+
return table, err
103+
}
104+
105+
func getCondition(conditions []apiregistration.APIServiceCondition, conditionType apiregistration.APIServiceConditionType) *apiregistration.APIServiceCondition {
106+
for i, condition := range conditions {
107+
if condition.Type == conditionType {
108+
return &conditions[i]
109+
}
110+
}
111+
return nil
112+
}
113+
56114
// NewStatusREST makes a RESTStorage for status that has more limited options.
57115
// It is based on the original REST so that we can share the same underlying store
58116
func NewStatusREST(scheme *runtime.Scheme, rest *REST) *StatusREST {

0 commit comments

Comments
 (0)