Skip to content
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

Fix Unstructured field accessor #48065

Merged

Conversation

ironcladlou
Copy link
Contributor

@ironcladlou ironcladlou commented Jun 26, 2017

Fix the Unstructured GetDeletionGracePeriodSeconds accessor which was
always returning nil regardless of the underlying stored value. The
field value always appearing nil prevents Custom Resource instances
from being deleted when garbage collection is enabled for CRs and
when DeletePropagationOrphan is used. More generally, this fix means that
delete-on-update now works for CR instances.

Add some test coverage for Unstructured metadata deserialization.

The Unstructured DeletionGracePeriodSeconds field marshals as a value
type from JSON and as a pointer type via SetDeletionGracePeriodSeconds.
The GetDeletionGracePeriodSeconds method now supports handling both
int64 and *int64 values so that either underlying value can be returned.

Add a reflection-based unit test which attempts to exercise all the
Object Get/Set methods for nil handling.

Registries backed by the generic Store's `Update` implementation support delete-on-update, which allows resources to be automatically deleted during an update provided:

* Garbage collection is enabled for the Store
* The resource being updated has no finalizers
* The resource being updated has a non-nil DeletionGracePeriodSeconds equal to 0

With this fix, Custom Resource instances now also support delete-on-update behavior under the same circumstances.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jun 26, 2017
@k8s-github-robot k8s-github-robot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. release-note-none Denotes a PR that doesn't merit a release note. labels Jun 26, 2017
@@ -136,8 +136,8 @@ func getNestedInt64(obj map[string]interface{}, fields ...string) int64 {
}

func getNestedInt64Pointer(obj map[string]interface{}, fields ...string) *int64 {
if str, ok := getNestedField(obj, fields...).(*int64); ok {
return str
if str, ok := getNestedField(obj, fields...).(int64); ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would correctly handle reading null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -136,8 +136,8 @@ func getNestedInt64(obj map[string]interface{}, fields ...string) int64 {
}

func getNestedInt64Pointer(obj map[string]interface{}, fields ...string) *int64 {
if str, ok := getNestedField(obj, fields...).(*int64); ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this works as long as our number-preserving json unmarshaler is used (stdlib turns numbers into float64)

also, getNestedSlice and getNestedMap assume values are strings and silently drop non-strings... the names should at least be updated so callers know their assumptions

}`,
verify: func(u Unstructured) {
assertEqual("test", u.GetName(), "name")
assertNil(u.GetDeletionGracePeriodSeconds(), "deletionGracePeriodSeconds")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, I see. ok.

@liggitt
Copy link
Member

liggitt commented Jun 26, 2017

what does SetDeletionTimestamp() do? It looks like it stores a string in the unstructured object, which would mean GetDeletionTimestamp() would not be able to read a value set with SetDeletionTimestamp().

Should make sure that the getters/setters work together with both null and present values.

@ironcladlou
Copy link
Contributor Author

@liggitt

what does SetDeletionTimestamp() do? It looks like it stores a string in the unstructured object, which would mean GetDeletionTimestamp() would not be able to read a value set with SetDeletionTimestamp().

Should make sure that the getters/setters work together with both null and present values.

Oh boy, good catch. Hrm.

@ironcladlou
Copy link
Contributor Author

Turns out the problem runs a little deeper: DeletionGracePeriodSeconds is stored as a value type when the Unstructured data is marshalled from JSON, while a pointer type is stored via SetDeletionGracePeriodSeconds. Working on a fix for this as well as reflective unit test coverage for all the Object accessor methods.

@k8s-github-robot k8s-github-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jun 26, 2017
@ash2k
Copy link
Member

ash2k commented Jun 26, 2017

This is similar to #46683.
/sig api-machinery
/kind bug

@k8s-ci-robot k8s-ci-robot added sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. kind/bug Categorizes issue or PR as related to a bug. labels Jun 26, 2017
@ironcladlou
Copy link
Contributor Author

@ash2k

This is similar to #46683.

Thanks, had no idea about that test file. How should I proceed? Should I add coverage to the existing tests? TestUnstructuredGetters and TestUnstructuredSetters are setting and verifying internal state; TestUnstructuredMetadataFromJSON here could be folded into TestUnstructuredGetters to cover the deletionGracePeriodSeconds and generation fields.

TestAccessorMethods here is testing Set/Get opaquely, which is different than any existing test.

cc @deads2k @liggitt

@ironcladlou
Copy link
Contributor Author

I've moved my test code over to the existing suite.

@ash2k
Copy link
Member

ash2k commented Jun 26, 2017

@ironcladlou I have no idea why those tests are in two separate places - I've had the same question :)

@ironcladlou
Copy link
Contributor Author

Looks like this integration test was inadvertently working around the grace period accessor bug. Fixed the test in d5d9c37dea97be5ef3bc2d6f41be6e98dc45ab90.

@ironcladlou
Copy link
Contributor Author

@ash2k mind reviewing this?

@ash2k
Copy link
Member

ash2k commented Jun 28, 2017

@ironcladlou wow, just read the comment from your last commit - this is the behaviour I was actually expecting when I initially wrote this test. See the comment from @deads2k #46439 (comment) - it implies that the final delete is necessary to actually remove the object after all finalizers have been cleared. And I thought it is something else (other controller?) that does this normally, but not during integration tests.

@ash2k
Copy link
Member

ash2k commented Jun 28, 2017

@ironcladlou maybe it is better to remove the field when the pointer is nil? This will be consistent with how unmarshaling works - it does not create a field with nil when the value is not set but just omits it. Also that is how pointers in owner references work (see PR I mentioned above).

@ironcladlou
Copy link
Contributor Author

ironcladlou commented Jun 28, 2017

@ash2k

@ironcladlou wow, just read the comment from your last commit - this is the behaviour I was actually expecting when I initially wrote this test. See the comment from @deads2k #46439 (comment) - it implies that the final delete is necessary to actually remove the object after all finalizers have been cleared. And I thought it is something else (other controller?) that does this normally, but not during integration tests.

In this case I think delete-on-update depends primarily on whether GC is enabled for a given type of registry. In the integration tests right now, GC is definitely enabled for the CRD Store in use. I'm not entirely sure whether GC was enabled during #46439; if GC was enabled, your extra delete would have worked around the accessor bug. If GC was disabled, your extra delete would have been necessary because delete-on-update would have also been implicitly disabled.

I could also be totally wrong and missing something 😁

/cc @deads2k

@ironcladlou
Copy link
Contributor Author

@ash2k

@ironcladlou maybe it is better to remove the field when the pointer is nil? This will be consistent with how unmarshaling works - it does not create a field with nil when the value is not set but just omits it. Also that is how pointers in owner references work (see PR I mentioned above).

I agree with you, but I think we're already dealing with some internal inconsistency in that regard: SetOwnerReferences adheres to your proposed omission behavior, while SetInitializers, SetLabels, SetAnnotations, and SetDeletionTimestamp will retain keys and assign nil values.

If we all agree that nil value keys should be omitted internally, I can get SetDeletionGracePeriodSeconds in line with our desired behavior, and we can address all the other fields in a followup. I'd prefer keep the scope of this PR very narrow.

/cc @deads2k

@deads2k
Copy link
Contributor

deads2k commented Jun 28, 2017

In this case I think delete-on-update depends primarily on whether GC is enabled for a given type of registry.

Hmmm... These have gone through numerous iterations and the original namespace code issued a second delete. I actually can't be sure it wasn't a side-effect of a bug. The rest of this code looks correct, so we'll merge note the bug fix.

@ironcladlou add a release-note for it in this pull please.

@deads2k
Copy link
Contributor

deads2k commented Jun 28, 2017

I think this moves in the right direction. I'm open to changing the nil values for consistency with normal marshalling, but I see that as a followup (open an issue to track, please).

lgtm, squash up a bit for merge.

Fix the Unstructured GetDeletionGracePeriodSeconds accessor which was
always returning nil regardless of the underlying stored value. The
field value always appearing nil prevents Custom Resource instances
from being deleted when garbage collection is enabled for CRs and
when DeletePropagationOrphan is used. More generally, this fix means that
delete-on-update now works for CR instances.

Add some test coverage for Unstructured metadata deserialization.

The Unstructured DeletionGracePeriodSeconds field marshals as a value
type from JSON and as a pointer type via SetDeletionGracePeriodSeconds.
The GetDeletionGracePeriodSeconds method now supports handling both
int64 and *int64 values so that either underlying value can be returned.

Add a reflection-based unit test which attempts to exercise all the
Object Get/Set methods for nil handling.
@deads2k deads2k added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed release-note-none Denotes a PR that doesn't merit a release note. labels Jun 28, 2017
@deads2k
Copy link
Contributor

deads2k commented Jun 28, 2017

/lgtm
/approve no-issue

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 28, 2017
@deads2k
Copy link
Contributor

deads2k commented Jun 28, 2017

/retest

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deads2k, ironcladlou
We suggest the following additional approver: lavalamp

Assign the PR to them by writing /assign @lavalamp in a comment when ready.

Associated issue requirement bypassed by: deads2k

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@ironcladlou
Copy link
Contributor Author

Split out #48211 to track refactoring nil handling for Object related fields.

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deads2k, ironcladlou
We suggest the following additional approver: lavalamp

Assign the PR to them by writing /assign @lavalamp in a comment when ready.

Associated issue requirement bypassed by: deads2k

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

4 similar comments
@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deads2k, ironcladlou
We suggest the following additional approver: lavalamp

Assign the PR to them by writing /assign @lavalamp in a comment when ready.

Associated issue requirement bypassed by: deads2k

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deads2k, ironcladlou
We suggest the following additional approver: lavalamp

Assign the PR to them by writing /assign @lavalamp in a comment when ready.

Associated issue requirement bypassed by: deads2k

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deads2k, ironcladlou
We suggest the following additional approver: lavalamp

Assign the PR to them by writing /assign @lavalamp in a comment when ready.

Associated issue requirement bypassed by: deads2k

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deads2k, ironcladlou
We suggest the following additional approver: lavalamp

Assign the PR to them by writing /assign @lavalamp in a comment when ready.

Associated issue requirement bypassed by: deads2k

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@deads2k deads2k added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 28, 2017
@deads2k
Copy link
Contributor

deads2k commented Jun 28, 2017

@k8s-bot its the old apimachinery tests. Stop freaking out.

@deads2k
Copy link
Contributor

deads2k commented Jun 28, 2017

@ironcladlou that package of old tests exists because we had some tests which relied on kube API types. I think that @sttts gave us an alternative test group in apimachinery since, but I we haven't revisited it.

@shiywang if you're interested in un-cycling those and moving them into apimachinery, let me know.

@k8s-github-robot
Copy link

Automatic merge from submit-queue (batch tested with PRs 48183, 45611, 48065)

@k8s-github-robot k8s-github-robot merged commit d0735b9 into kubernetes:master Jun 28, 2017
@shiywang
Copy link
Contributor

shiywang commented Jun 29, 2017

@deads2k I would like to work on that. checking now : )

@deads2k
Copy link
Contributor

deads2k commented Jun 29, 2017

@deads2k I would like to work on that. checking now : )

opened #48265

k8s-github-robot pushed a commit that referenced this pull request Jul 5, 2017
Automatic merge from submit-queue (batch tested with PRs 47700, 48464, 48502)

Add a refreshing discovery client

Introduce a discovery client (implementing `CachedDiscoveryInterface`) which caches discovery information in memory and which can be actively refreshed by the user.

This implementation fetches from discovery upon refresh and could later be improved to maintain updates from a watch.

Extracted from #47665 and #46000 to help reduce the scope of #48065.

```release-note
NONE
```
k8s-github-robot pushed a commit that referenced this pull request Jul 29, 2017
Automatic merge from submit-queue (batch tested with PRs 49538, 49708, 47665, 49750, 49528)

Enable garbage collection of custom resources

Enhance the garbage collector to periodically refresh the resources it monitors (via discovery) to enable custom resource definition GC (addressing #44507 and reverting #47432).

This is a replacement for #46000.

/cc @lavalamp @deads2k @sttts @caesarxuchao 

/ref #48065

```release-note
The garbage collector now supports custom APIs added via CustomeResourceDefinition or aggregated apiservers. Note that the garbage collector controller refreshes periodically, so there is a latency between when the API is added and when the garbage collector starts to manage it.
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/api-machinery Categorizes an issue or PR as relevant to SIG API Machinery. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants