-
Notifications
You must be signed in to change notification settings - Fork 40k
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
have basic kubectl crud agnostic of registered types #36085
have basic kubectl crud agnostic of registered types #36085
Conversation
@@ -39,6 +39,14 @@ func GetItemsPtr(list runtime.Object) (interface{}, error) { | |||
if err != nil { | |||
return nil, err | |||
} | |||
|
|||
// if we're a runtime.Unstructured, check to see if we have an `items` key | |||
if unstructured, ok := list.(*runtime.Unstructured); ok { |
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.
@smarterclayton api/meta
changes to more cleanly handle the way the unstructured decoder works. It doesn't make an UnstructuredList
by default, which is annoying.
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.
This needs a test.
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.
fixing
@@ -117,6 +125,13 @@ func SetList(list runtime.Object, objects []runtime.Object) error { | |||
slice := reflect.MakeSlice(items.Type(), len(objects), len(objects)) | |||
for i := range objects { | |||
dest := slice.Index(i) | |||
|
|||
// check to see if you're directly assignable | |||
if reflect.TypeOf(objects[i]).AssignableTo(dest.Type()) { |
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.
When you pass an UnstructuredList
into this method, you don't want to dereference the items like you do in EnforcePtr
below.
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.
This needs a test.
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.
easier: if dest.Kind() == reflect.Ptr
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.
easier: if dest.Kind() == reflect.Ptr
I prefer this express and I think this check is slightly different.
return err | ||
// take the filtered items and create a new list for display | ||
list := &runtime.UnstructuredList{ | ||
Object: map[string]interface{}{ |
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.
This looks nasty, but it serializes correctly and v1.List
does not serialize correctly. :(
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.
Doesn't this lose resourceVersion?
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.
Doesn't this lose resourceVersion?
Will fix.
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.
Actually, turns out HEAD doesn't preserve the resourceversion.
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.
or selflink
@@ -48,28 +48,6 @@ func makeImageList(spec *api.PodSpec) string { | |||
return strings.Join(listOfImages(spec), ",") | |||
} | |||
|
|||
func NewThirdPartyResourceMapper(gvs []unversioned.GroupVersion, gvks []unversioned.GroupVersionKind) (meta.RESTMapper, error) { |
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.
@sttts @smarterclayton so happy!
|
||
// check if the object is unstructured. If so, let's attempt to convert it to a type we can understand before | ||
// trying to print, since the printers are keyed by type. This is extremely expensive. | ||
if objBytes, err := runtime.Encode(api.Codecs.LegacyCodec(), obj); err == 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.
@smarterclayton will you let me get away with this to have the capability? It only hurts kubectl
.
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.
can you not check whether this is unstructured first? Or is it now always unstructured coming in to here? Not sure why you have to blanket encode?
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.
can you not check whether this is unstructured first? Or is it now always unstructured coming in to here? Not sure why you have to blanket encode?
I think its almost always unstructured, but I'm not certain enough to assume it.
I will gate on unstructured and unknown to start.
case reflect.Interface: | ||
switch itype := i.Interface().(type) { | ||
case uint8: | ||
if jtype, ok := j.Interface().(uint8); ok { |
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.
Check precedence carefully through here.
Jenkins GCE Node e2e failed for commit 90d9fa4. Full PR test history. The magic incantation to run this job again is |
90d9fa4
to
29d2a1d
Compare
This gets pretty deep into scheme/codec stuff. Moving to @smarterclayton. This is ready for review. |
// 2. if the specified output-version is a recognized, valid Scheme, then the list should use that scheme, and otherwise it will default to the client version, registered.GroupOrDie(api.GroupName).GroupVersion.String() in this test; | ||
// 3a. if the specified output-version is a recognized, valid Scheme, in which the requested object (replicationcontroller) can be represented, then the object should be returned using that version; | ||
// 3b. otherwise if the specified output-version is unrecognized, but the requested object (replicationcontroller) is recognized by the client's codec, then it will be converted to the client version, registered.GroupOrDie(api.GroupName).GroupVersion.String() in this test. | ||
func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { |
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.
We no longer do anything with --output-version
. I'd like to leave disconnecting/doc-ing that to a followup, but this this makes us generic for basic CRUD.
t.Fatal(actual) | ||
} | ||
for i, obj := range actual { | ||
actualObj, err := runtime.Decode( |
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.
encodes the unstructured (or whatever) and then decodes that back into internal for the comparison which this package is using.
@@ -2447,6 +2533,20 @@ func (j *JSONPathPrinter) PrintObj(obj runtime.Object, w io.Writer) error { | |||
} | |||
} | |||
|
|||
if unknown, ok := obj.(*runtime.Unknown); ok { |
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.
twitch
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.
twitch
Found inside a list somewhere I think. Given the way this code works, the change here is actually correct. Well, more correct than it was before. The whole thing needs some rethinking.
@@ -2256,9 +2265,78 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er | |||
} | |||
return resultValue.Interface().(error) | |||
} | |||
|
|||
// we don't recognize this type, but we can still attempt to print some reasonable information about. | |||
unstructured, ok := obj.(*runtime.Unstructured) |
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.
Keep in mind unstructured really is "generic API v1" when used this way (with accessors). So this code only works until someone changes metadata and then is horribly broken again. Which is not inconsistent with what we've said up till now, that we won't change v1 metadata until we have server side transformation (we can't, effectively).
Jenkins GCE etcd3 e2e failed for commit 29d2a1d. Full PR test history. The magic incantation to run this job again is |
Jenkins GCE e2e failed for commit 29d2a1d. Full PR test history. The magic incantation to run this job again is |
Jenkins GCI GCE e2e failed for commit 29d2a1d. Full PR test history. The magic incantation to run this job again is |
29d2a1d
to
e667fb3
Compare
comments addressed. |
a6d8fe9
to
61673c4
Compare
Much better now without the patch to |
@k8s-bot test this [submit-queue is verifying that this PR is safe to merge] |
Automatic merge from submit-queue |
Fixing the failures? |
which failures on what? |
@deads2k I'm working on isssue #36007, which is forked from #35791. Why we only do that for |
As I recall, there's something wrong with the implementation of |
It looks like this changed the kubectl -o jsonpath behavior to now fail if it cannot find the field. We should make sure the release notes are clear about this as it could cause scripts that were depending on the old behavior to fail (e.g. if the script checks if the field exists by querying for it and looks for an empty value) |
Hrm - that may have been something even older that I did in 1.4. |
@smarterclayton I suspect it is this PR. 1.4 has the "return empty" behavior, and the new behavior actually breaks version skew tests. This PR updated a kubectl.go e2e test to work around the change in behavior, but it is failing when running the old tests against a new client/server. We could potentially revert to the old behavior by using the work you implemented in #31714 |
@bgrant0607 FYI I am not sure if we consider this a api compatibility breaking change. The json path doc does explicitly state what the behavior is when the field is not present. 1.4 behavior:
1.5 behavior:
I have not been able to find a record of the original intention when the field is missing from the JSON. It would probably be best to support either behavior by exposing a flag to control the knobs introduced in #31714. I am not sure it is worth the risk introduced to get that into 1.5 though. |
@pwittrock @smarterclayton Is there a reason why we wouldn't make the 1.4 behavior the default? |
Making the 1.4 behavior the default makes the most sense to me. My biggest concern would be around getting the change cherrypicked and tested in time for the 1.5 release. Today I will look into if this can be done as a simple change. |
Created issue #37991 for tracking |
@smarterclayton Looking more closely at the PR, you are right that it doesn't seem like this should have caused the change in behavior we are seeing. Still investigating the root cause. |
According to JSONPath the quasi spec, no expression that has no field
should return errors. We insert that extra logic ourselves.
On Dec 2, 2016, at 5:56 PM, Phillip Wittrock <notifications@github.com> wrote:
@smarterclayton <https://github.com/smarterclayton> Looking more closely at
the PR, you are right that it doesn't seem like this should have caused the
change in behavior we are seeing. Still investigating the root cause.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#36085 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABG_p9WOApkxGKw3UVW25xteSrgeZYfJks5rEKI4gaJpZM4KnplK>
.
|
Makes
kubectl get
agnostic to scheme (baked in API types). This means that it will now work against generic API servers that are "kube shaped".This is similar to the work done for
kubectl create
last release. I'll split out the smaller command.kubectl get
looks a lot different, but this eliminates all special casing for TPR in those cases.@fabianofranz
This change is