-
Notifications
You must be signed in to change notification settings - Fork 39.8k
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
Smarter generic getters and describers #44222
Smarter generic getters and describers #44222
Conversation
Also @liggitt since you wrote the previous version. |
29b6665
to
8bfe8d3
Compare
@k8s-bot gci gce e2e test this |
I'm extremely interested in this PR for service-catalog, just for the record |
fyi @jwforres |
I'm assigned but pretty unfamiliar with this code. Maybe someone else would be a better reviewer? |
@fabianofranz Does this print all the fields, or how does it decide which ones to print? |
@pwittrock Current rules are
|
8bfe8d3
to
c34168f
Compare
What are top-level fields? Are those the first leaf nodes encountered in a breadth-first search? Does it include both spec and status, or just spec? |
@pwittrock Sorry, yeah I meant leaf nodes at the tree root (so in a BFS), taken in lexical order. Meaning, in the yam below it would print:
If This is the current state, but I could improve if it makes sense, like trying to take something from the children of |
@fabianofranz I agree keeping it as simple as possible for as long as possible is best. Spec and Status are relatively standard, so it is too bad this won't work well for them, but I think that is ok for now. |
if events != nil { | ||
DescribeEvents(events, w) | ||
} | ||
return nil | ||
}) | ||
} | ||
|
||
func printUnstructuredContent(w PrefixWriter, level int, content map[string]interface{}, skipPrefix string, skip ...string) { | ||
for field, value := range content { |
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.
Do the values always appear in the same order? If not, can we make them consistent?
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.
Not in describe, but if we want it consistent I can use the same strategy used in get (an ordered slice of the map keys).
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.
If you don't mind, lets do that. I think it would be frustrating if you run the same describe command 2x and the output is reordered. Esp if you are trying to debug - e.g. describe, look for field, do something, describe, look for field (where did it go?)
expected: "\n Creation Timestamp:\t2017-04-01T00:00:00Z\n", | ||
}, | ||
{ | ||
expected: "\nItems:\n Item Bool:\ttrue\n", |
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.
why is itemInt missing?
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.
It's not missing, I just didn't care to test it. I'll add.
var discoveredFieldNames []string // we want it predictable so this will be used to sort | ||
ignoreIfDiscovered := []string{"kind", "apiVersion"} // these are already covered | ||
for field, value := range content { | ||
if slice.ContainsString(ignoreIfDiscovered, field, nil) { |
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.
Does this always discover the same fields? Is the order always the same?
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.
Yes, here in get the order is always the same so it will always discover the same fields.
c34168f
to
5062f1f
Compare
@pwittrock thanks for the review, comments addressed. |
@@ -201,8 +204,51 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er | |||
} | |||
|
|||
if _, err := meta.Accessor(obj); err == nil { | |||
// we don't recognize this type, but we can still attempt to print some reasonable information about. |
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.
Is there a test for this?
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.
Added some in humanreadable_test.go
.
printUnstructuredContent(w, LEVEL_0, obj.UnstructuredContent(), "", ".dummy1", ".metadata.dummy3") | ||
output := out.String() | ||
|
||
for _, test := range testCases { |
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.
Now that the order is consistent, we should make sure we test the ordering. Doing so should simplify this check.
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.
Done.
5062f1f
to
ccf8e6a
Compare
@pwittrock comments addressed. |
ccf8e6a
to
b276f17
Compare
@@ -49,6 +49,20 @@ func ShuffleStrings(s []string) []string { | |||
return shuffled | |||
} | |||
|
|||
// ContainsString checks if a given slice of strings contains the provided string. | |||
// If a modifier func is provided, it is called with the slice item before the comparation. | |||
func ContainsString(slice []string, s string, modifier func(s string) string) bool { |
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.
Is this still used?
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.
Yes, still in a few other places.
/lgtm |
Needs approval, @smarterclayton mind taking a look? |
Or @bgrant0607 |
Approve but one minor nit. If you want to do in a follow up that's fine /approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: fabianofranz, pwittrock, smarterclayton
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
@k8s-bot cvm gce e2e test this |
Automatic merge from submit-queue (batch tested with PRs 44222, 44614, 44292, 44638) |
In 1.8 we'll have most of the generic printing on the server in place. Any objections to taking this specific part out and relying on that? In general, any object will return name and age, CRD can return based on their openapi extensions, and extension APIs can return full structured fields. |
Makes printers and describers smarter for generic resources.
This traverses unstructured objects and prints their attributes for generic resources (TPR, federated API, etc) in
kubectl get
andkubectl describe
. Makes use of the object's field names to come up with a best guess for describer labels and get headers, and field value types to understand how to better print it, indent, etc.A nice intermediate solution while we don't have get and describe extensions.
Examples:
Release note:
PTAL @pmorie @pwittrock @kubernetes/sig-cli-pr-reviews