mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
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 ```
This commit is contained in:
commit
72ef97a141
@ -658,6 +658,10 @@
|
|||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/apimachinery/pkg/api/meta/table",
|
||||||
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
@ -758,6 +762,10 @@
|
|||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "k8s.io/apimachinery/pkg/util/duration",
|
||||||
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
|
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
|
||||||
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
"Rev": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
@ -11,7 +11,10 @@ go_library(
|
|||||||
importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd",
|
importmap = "k8s.io/kubernetes/vendor/k8s.io/kube-aggregator/pkg/registry/apiservice/etcd",
|
||||||
importpath = "k8s.io/kube-aggregator/pkg/registry/apiservice/etcd",
|
importpath = "k8s.io/kube-aggregator/pkg/registry/apiservice/etcd",
|
||||||
deps = [
|
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/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",
|
||||||
|
@ -18,8 +18,12 @@ package etcd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
|
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"
|
||||||
@ -53,6 +57,60 @@ func NewREST(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) *REST
|
|||||||
return &REST{store}
|
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.
|
// 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
|
// It is based on the original REST so that we can share the same underlying store
|
||||||
func NewStatusREST(scheme *runtime.Scheme, rest *REST) *StatusREST {
|
func NewStatusREST(scheme *runtime.Scheme, rest *REST) *StatusREST {
|
||||||
|
Loading…
Reference in New Issue
Block a user