Skip to content

Commit a5c36ce

Browse files
authored
Merge pull request #363 from smarterclayton/serverside_get
Proposal: Server-side `kubectl get`
2 parents 0e8f17d + 550ae37 commit a5c36ce

File tree

1 file changed

+183
-0
lines changed

1 file changed

+183
-0
lines changed
+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Expose `get` output from the server
2+
3+
Today, all clients must reproduce the tabular and describe output implemented in `kubectl` to perform simple lists
4+
of objects. This logic in many cases is non-trivial and condenses multiple fields into succinct output. It also requires
5+
that every client provide rendering logic for every possible type, including those provided by API aggregation or third
6+
party resources which may not be known at compile time.
7+
8+
This proposal covers moving `get` and `describe` to the server to reduce total work for all clients and centralize these
9+
core display options for better reuse and extension.
10+
11+
12+
## Background
13+
14+
`kubectl get` is a simple tabular representation of one or more instances of a particular resource type. It is the primary
15+
listing mechanism and so must be implemented for each type. Today, we have a single generic implementation for unrecognized
16+
types that attempts to load information from the `metadata` field (assuming the object follows the metav1 Kubernetes API
17+
schema). `get` supports a `wide` mode that includes additional columns. Users can add additional columns for labels via a
18+
flag. Headers corresponding to the columns are optionally displayed.
19+
20+
`kubectl describe` shows a textual representation of individual objects that describes individual fields as subsequent
21+
lines and uses indendation and nested tables to convey deeper structure on the resource (such as events for a pod or
22+
each container). It sometimes retrieves related objects like events, pods for a replication controller, or autoscalers
23+
for a deployment. It supports no significant flags.
24+
25+
The implementation of both is modeled as a registered function that takes an object or list of objects and outputs
26+
semi-structured text.
27+
28+
## Goals
29+
30+
* Make it easy for a simple client to get a list of resources for a web UI or CLI output
31+
* Support all existing options, leave open the door for future extension and experimentation
32+
* Allow new API extensions and third party resources to be implemented server side, removing the need to version
33+
schemes for retrieving data from the server
34+
* Keep implementation of `get` and `describe` simple
35+
* Ease internationalization of `get` and `describe` output for all clients
36+
37+
## Non-Goals
38+
39+
* Deep customization of the returned output by the client
40+
41+
42+
## Specification of server-side `get`
43+
44+
The server would return a `Table` object (working-name) that contains metadata for columns and one or more
45+
rows composed of cells for each column. Some additional data may be relevant for each row and returned by the
46+
server. Since every object should have a `Table` representation, treat this as part of content negotiation
47+
as described in [the alternative representations of objects proposal](alternate-api-representations.md).
48+
49+
Example request:
50+
51+
```
52+
$ curl https://localhost:8443/api/v1/pods -H "Accept: application/json+vnd.kubernetes.as+meta.k8s.io+v1alpha1+Table"
53+
{
54+
"kind": "Table",
55+
"apiVersion": "meta.k8s.io/v1alpha1",
56+
"headers": [
57+
{"name": "Name", "type": "string", "description": "The name of the pod, must be unique ..."},
58+
{"name": "Status", "type": "string", "description": "Describes the current state of the pod"},
59+
...
60+
],
61+
"items": [
62+
{"cells": ["pod1", "Failed - unable to start", ...]},
63+
{"cells": ["pod2", "Init 0/2", ...]},
64+
...
65+
]
66+
}
67+
```
68+
69+
This representation is also possible to return from a watch. The watch can omit headers on subsequent queries.
70+
71+
```
72+
$ curl https://localhost:8443/api/v1/pods?watch=1 -H "Accept: application/json+vnd.kubernetes.as+meta.k8s.io+v1alpha1+Table"
73+
{
74+
"kind": "Table",
75+
"apiVersion": "meta.k8s.io/v1alpha1",
76+
// headers are printed first, in case the watch holds
77+
"headers": [
78+
{"name": "Name", "type": "string", "description": "The name of the pod, must be unique ..."},
79+
{"name": "Status", "type": "string", "description": "Describes the current state of the pod"},
80+
...
81+
]
82+
}
83+
{
84+
"kind": "Table",
85+
"apiVersion": "meta.k8s.io/v1alpha1",
86+
// headers are not returned here
87+
"items": [
88+
{"cells": ["pod1", "Failed - unable to start", ...]},
89+
...
90+
]
91+
}
92+
```
93+
94+
It can also be returned in CSV form:
95+
96+
```
97+
$ curl https://localhost:8443/api/v1/pods -H "Accept: text/csv+vnd.kubernetes.as+meta.k8s.io+v1alpha1+Table"
98+
Name,Status,...
99+
pod1,"Failed - unable to start",...
100+
pod2,"Init 0/2",...
101+
...
102+
```
103+
104+
To support "wide" format, columns may be marked with an optional priority field of increasing integers (default
105+
priority 0):
106+
107+
```
108+
{
109+
"kind": "Table",
110+
"apiVersion": "meta.k8s.io/v1alpha1",
111+
"headers": [
112+
...
113+
{"name": "Node Name", "type": "string", "description": "The node the pod is scheduled on, empty if the pod is not yet scheduled", "priority": 1},
114+
...
115+
],
116+
...
117+
}
118+
```
119+
120+
To allow label columns, and to enable integrators to build effective UIs, each row may contain an `object` field that
121+
is either `PartialObjectMetadata` (a standard object containing only ObjectMeta) or the object itself. Clients may request
122+
this field be set by specifying `?includeObject=None|Metadata|Self` on the query parameter.
123+
124+
```
125+
GET ...?includeObject=Metadata
126+
{
127+
"kind": "Table",
128+
"apiVersion": "meta.k8s.io/v1alpha1",
129+
"items": [
130+
...
131+
{"cells": [...], "object": {"kind": "PartialObjectMetadata", "apiVersion":"meta.k8s.io/v1alpha1", "metadata": {"name": "pod1", "namespace": "pod2", "labels": {"a": "1"}, ...}},
132+
...
133+
]
134+
}
135+
```
136+
137+
The `Metadata` value would be the default. Clients that wish to print in an advanced manner may use `Self` to get the full
138+
object and perform arbitrary transformations.
139+
140+
All fields on the server side are candidates for translation and localization changes can be delivered more
141+
quickly and to all clients.
142+
143+
Third-party resources can more easily implement `get` in this fashion - instead of web dashboards and
144+
`kubectl` both implementing their own logic to parse a particular version of Swagger or OpenAPI, the server
145+
component performs the transformation. The server encapsulates the details of printing. Aggregated resources
146+
automatically provide this behavior when possible.
147+
148+
149+
### Specific features in `kubectl get`
150+
151+
Feature | Implementation
152+
--- | ---
153+
sort-by | Continue to implement client-side (no server side sort planned)
154+
custom-column (jsonpath) | Implement client-side by requesting object `?includeObject=Self` and parsing
155+
custom-column (label) | Implement client-side by getting labels from metadata returned with each row
156+
show-kind | Implement client-side by using the discovery info associated with the object (rather than being returned by server)
157+
template | Implement client-side, bypass receiving table output and get raw objects
158+
watch | Request Table output via the watch endpoint
159+
export | Implement client-side, bypass receiving table output and get exported object
160+
wide | Server should indicate which columns are "additional" via a field on on the header column - client then shows those columns if it wants to
161+
color (proposed) | Rows which should be highlighted should have a semantic field on the row - e.g. `alert: [{type: Warning, message: "This pod has been deleted"}]`. Cells could be selected by adding an additional field `alert: [{type: Warning, ..., cells: [0, 1]}]`.
162+
163+
164+
## Future considerations
165+
166+
* When we introduce server side paging, Table would be paged similar to how PodList or other types are paged. https://issues.k8s.io/2349
167+
* More advanced output could in the future be provided by an external call-out or an aggregation API on the server side.
168+
* `describe` could be managed on the server as well, with a similar generic format, and external outbound links used to reference other objects.
169+
170+
171+
## Migration
172+
173+
Old clients will continue retrieving the primary representation. Clients can begin using the optional `Accept`
174+
header to indicate they want the simpler version, and if they receive a Table perform the new path, otherwise
175+
fall back to client side functions.
176+
177+
Server side code would reuse the existing display functions but replace TabWriter with either a structured writer
178+
or the tabular form.
179+
180+
181+
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
182+
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/proposals/server-get.md?pixel)]()
183+
<!-- END MUNGE: GENERATED_ANALYTICS -->

0 commit comments

Comments
 (0)