-
Notifications
You must be signed in to change notification settings - Fork 5.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
kubectl get
and kubectl describe
extensions
#308
Changes from all commits
a1cf951
1aa9282
39dbe85
f3d5c99
ff39a62
af50771
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
# Provide open-api extensions for kubectl get / kubectl describe columns | ||
|
||
Status: Pending | ||
|
||
Version: Alpha | ||
|
||
## Motivation | ||
|
||
`kubectl get` and `kubectl describe` do not provide a rich experience | ||
for resources retrieved through federated apiservers and types not | ||
compiled into the kubectl binary. Kubectl should support printing | ||
columns configured per-type without having the types compiled in. | ||
|
||
## Proposal | ||
|
||
Allow the apiserver to define the type specific columns that will be | ||
printed using the open-api swagger.json spec already fetched by kubectl. | ||
This provides a limited describe to only print out fields on the object | ||
and related events. | ||
|
||
**Note:** This solution will only work for types compiled into the apiserver | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. include federated apiservers? |
||
providing the open-api swagger.json to kubectl. This solution will | ||
not work for TPR, though TPR could possibly be solved in a similar | ||
way by apply an annotation with the same key / value to the TPR. | ||
|
||
## User Experience | ||
|
||
### Use Cases | ||
|
||
- As a user, when I run `kubectl get` on sig-service-catalog resources | ||
defined in a federated apiserver, I want to see more than just the | ||
name and the type of the resource. | ||
- As a user, when I run `kubectl describe` on sig-service-catalog | ||
resources defined in a federated apiserver, I want the command | ||
to succeed, and to see events for the resource along with important | ||
fields of the resource. | ||
|
||
## Implementation | ||
|
||
Define the open-api extensions `x-kubernetes-kubectl-get-columns` and | ||
`x-kubernetes-kubectl-describe-columns`. These extensions have a | ||
string value containing the columns to be printed by kubectl. The | ||
string format is the same as the `--custom-columns` for `kubectl get`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we don't have openapi schemas for third party resources... do we anticipate adding that in the future? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing that out. I just added some comments about this. The short answer is - Yes I would like to add support for TPR. My initial thought is that this can be done through an annotation on the TPR. If we implement this proposal by hooking into the RestMapper, supporting TPR should be relatively clean. If we hack this proposal in, then it would be less clean. |
||
|
||
### Apiserver | ||
|
||
- Populate the open-api extension value for resource types. | ||
|
||
This is done by hardcoding the extension for types compiled into | ||
the api server. As such this is only a solution for types | ||
implemented using federated apiservers. | ||
|
||
### Kubectl | ||
|
||
Overview: | ||
|
||
- In `kubectl get` use the `x-kubernetes-kubectl-get-columns` value | ||
when printing an object iff 1) it is defined and 2) the output type | ||
is "" (empty string) or "wide". | ||
|
||
- In `kubectl describe` use the `x-kubernetes-kubectl-describe-columns` value | ||
when printing an object iff 1) it is defined | ||
|
||
|
||
#### Option 1: Re-parse the open-api swagger.json in a kubectl library | ||
|
||
Re-parse the open-api swagger.json schema and build a map of group version kind -> columns | ||
parsed from the schema. For this would look similar to validation/schema.go | ||
|
||
In get.go and describe.go: After fetching the "Infos" from the | ||
resource builder, lookup the group version kind from the populated map. | ||
|
||
**Pros:** | ||
- Simple and straightforward solution | ||
- Scope of impacted Kubernetes components is minimal | ||
- Doable in 1.6 | ||
|
||
**Cons:** | ||
- Hacky solution | ||
- Can not be cleanly extended to support TPR | ||
|
||
#### Option 2: Modify api-machinery RestMapper | ||
|
||
Modify the api-machinery RestMapper to parse extensions prefixed | ||
with `x-kubernetes` and include them in the *RestMapping* used by the resource builder. | ||
|
||
```go | ||
type RESTMapping struct { | ||
// Resource is a string representing the name of this resource as a REST client would see it | ||
Resource string | ||
|
||
GroupVersionKind schema.GroupVersionKind | ||
|
||
// Scope contains the information needed to deal with REST Resources that are in a resource hierarchy | ||
Scope RESTScope | ||
|
||
runtime.ObjectConvertor | ||
MetadataAccessor | ||
|
||
// Extensions | ||
ApiExtensions ApiExtensions | ||
} | ||
|
||
type ApiExtensions struct { | ||
Extensions map[string]interface{} | ||
} | ||
``` | ||
|
||
The tags would then be easily accessible from the kubectl get / describe | ||
functions through: `resource.Builder -> Infos -> Mapping -> DisplayOptions` | ||
|
||
**Pros:** | ||
- Clean + generalized solution | ||
- The same strategy can be applied to support TPR | ||
- Can support exposing future extensions such as patchStrategy and mergeKey | ||
- Can be used by other clients / tools | ||
|
||
**Cons:** | ||
- Fields are only loosely tied to rest | ||
- Complicated due to the broad scope and impact | ||
- May not be doable in 1.6 | ||
|
||
#### Considerations | ||
|
||
What should be used for oth an open-api extension columns tag AND a | ||
compiled in printer exist for a type? | ||
|
||
- Apiserver only provides `describe` for types that are never compiled in | ||
- Compiled in `describe` is much more rich - aggregating data across many other types. | ||
e.g. Node describe aggregating Pod data | ||
- kubectl will not be able to provide any `describe` information for new types when version skewed against a newer server | ||
- Always use the extensions if present | ||
- Allows server to control columns. Adds new columns for types on old clients that maybe missing the columns. | ||
- Always use the compiled in commands if present | ||
- The compiled in `describe` is richer and provides aggregated information about many types. | ||
- Always use the `get` extension if present. Always use the `describe` compiled in code if present. | ||
- Inconsistent behavior across how extensions are handled | ||
|
||
### Client/Server Backwards/Forwards compatibility | ||
|
||
#### Newer client | ||
|
||
Client doesn't find the open-api extensions. Fallback on 1.5 behavior. | ||
|
||
In the future, this will provide stronger backwards / forwards compability | ||
as it will allow clients to print objects | ||
|
||
#### Newer server | ||
|
||
Client doesn't respect open-api extensions. Uses 1.5 behavior. | ||
|
||
## Alternatives considered | ||
|
||
### Fork Kubectl and compile in go types | ||
|
||
Fork kubectl and compile in the go types. Implement get / describe | ||
for the new types in the forked version. | ||
|
||
**Pros:** *This is what will happen for sig-service catalog if we take no action in 1.6* | ||
|
||
**Cons:** Bad user experience. No clear solution for patching forked kubectl. | ||
User has to use a separate kubectl binary per-apiserver. Bad president. | ||
|
||
I really don't want this solution to be used. | ||
|
||
### Kubectl describe fully implemented in the server | ||
|
||
Implement a sub-resource "/describe" in the apiserver. This executes | ||
the describe business logic for the object and returns either a string | ||
or json blob for kubectl to print. | ||
|
||
**Pros:** Higher fidelity. Can aggregate data and fetch other objects. | ||
|
||
**Cons:** Higher complexity. Requires more api changes. | ||
|
||
### Write per-type columns to kubectl.config or another local file | ||
|
||
Support checking a local file containing per-type information including | ||
the columns to print. | ||
|
||
**Pros:** Simplest solution. Easy for user to override values. | ||
|
||
**Cons:** Requires manual configuration on user side. Does not provide a consistent experience across clients. | ||
|
||
### Write per-type go templates to kubectl.config or another local file | ||
|
||
Support checking a local file containing per-type information including | ||
the go template. | ||
|
||
**Pros:** Higher fidelity. Easy for user to override values. | ||
|
||
**Cons:** Higher complexity. Requires manual configuration on user side. Does not provide a consistent experience across clients. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do you envision this interacting with kubernetes/kubernetes#33900 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. I guess I don't fully understand how that proposal is intended to interact with the swagger schema. I suspect that this proposal is a much lighter version of the sub-pieces of kubernetes/kubernetes#33900 dealing with getting metadata about objects.