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

Mark Conditions in CustomResourceDefinitionStatus as optional #64996

Merged

Conversation

roycaihw
Copy link
Member

@roycaihw roycaihw commented Jun 12, 2018

What this PR does / why we need it:
Apiserver may respond null for required property Conditions in metav1.CustomResourceDefinitionStatus (e.g. create a crd with kubectl --v=9 and check the response), which fails the validation in generated python client kubernetes-client/python#415. This PR marks the field as optional.

Release note:

Property `conditions` in `apiextensions.v1beta1.CustomResourceDefinitionStatus` and `apiextensions.v1.CustomResourceDefinitionStatus` is now optional instead of required.

/sig api-machinery
/area custom-resources

@k8s-ci-robot k8s-ci-robot added 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. area/custom-resources size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jun 12, 2018
@roycaihw
Copy link
Member Author

/assign @mbohlool @sttts

@sttts
Copy link
Contributor

sttts commented Jun 13, 2018

Seeing this being inconsistent for a number of types (when searching for Conditions [] in kube). Can we fix this everywhere?

@roycaihw
Copy link
Member Author

@sttts Did a search under staging/src/k8s.io/api. 20 out of 21 Conditions fields have the omitempty json tag. 16 have the +optional tag. The openapi generator considers a field "optional" if either tag exists.

The problem is that we don't (and probably cannot?) have API conventions to reason about if an arbitrary API field should be optional, so we have to fix them one by one.

kubernetes/staging/src/k8s.io/api$ grep -r "Conditions \[\]" -B 4
extensions/v1beta1/types.go-
extensions/v1beta1/types.go-	// Represents the latest available observations of a deployment's current state.
extensions/v1beta1/types.go-	// +patchMergeKey=type
extensions/v1beta1/types.go-	// +patchStrategy=merge
extensions/v1beta1/types.go:	Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
--
extensions/v1beta1/types.go-	// Represents the latest available observations of a DaemonSet's current state.
extensions/v1beta1/types.go-	// +optional
extensions/v1beta1/types.go-	// +patchMergeKey=type
extensions/v1beta1/types.go-	// +patchStrategy=merge
extensions/v1beta1/types.go:	Conditions []DaemonSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,10,rep,name=conditions"`
--
extensions/v1beta1/types.go-	// Represents the latest available observations of a replica set's current state.
extensions/v1beta1/types.go-	// +optional
extensions/v1beta1/types.go-	// +patchMergeKey=type
extensions/v1beta1/types.go-	// +patchStrategy=merge
extensions/v1beta1/types.go:	Conditions []ReplicaSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
--
batch/v1/types.go-	// More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/
batch/v1/types.go-	// +optional
batch/v1/types.go-	// +patchMergeKey=type
batch/v1/types.go-	// +patchStrategy=merge
batch/v1/types.go:	Conditions []JobCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
--
certificates/v1beta1/types.go-
certificates/v1beta1/types.go-type CertificateSigningRequestStatus struct {
certificates/v1beta1/types.go-	// Conditions applied to the request, such as approval or denial.
certificates/v1beta1/types.go-	// +optional
certificates/v1beta1/types.go:	Conditions []CertificateSigningRequestCondition `json:"conditions,omitempty" protobuf:"bytes,1,rep,name=conditions"`
--
apps/v1/types.go-	// Represents the latest available observations of a statefulset's current state.
apps/v1/types.go-	// +optional
apps/v1/types.go-	// +patchMergeKey=type
apps/v1/types.go-	// +patchStrategy=merge
apps/v1/types.go:	Conditions []StatefulSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,10,rep,name=conditions"`
--
apps/v1/types.go-
apps/v1/types.go-	// Represents the latest available observations of a deployment's current state.
apps/v1/types.go-	// +patchMergeKey=type
apps/v1/types.go-	// +patchStrategy=merge
apps/v1/types.go:	Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
--
apps/v1/types.go-	// Represents the latest available observations of a DaemonSet's current state.
apps/v1/types.go-	// +optional
apps/v1/types.go-	// +patchMergeKey=type
apps/v1/types.go-	// +patchStrategy=merge
apps/v1/types.go:	Conditions []DaemonSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,10,rep,name=conditions"`
--
apps/v1/types.go-	// Represents the latest available observations of a replica set's current state.
apps/v1/types.go-	// +optional
apps/v1/types.go-	// +patchMergeKey=type
apps/v1/types.go-	// +patchStrategy=merge
apps/v1/types.go:	Conditions []ReplicaSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
--
apps/v1beta1/types.go-	// Represents the latest available observations of a statefulset's current state.
apps/v1beta1/types.go-	// +optional
apps/v1beta1/types.go-	// +patchMergeKey=type
apps/v1beta1/types.go-	// +patchStrategy=merge
apps/v1beta1/types.go:	Conditions []StatefulSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,10,rep,name=conditions"`
--
apps/v1beta1/types.go-
apps/v1beta1/types.go-	// Represents the latest available observations of a deployment's current state.
apps/v1beta1/types.go-	// +patchMergeKey=type
apps/v1beta1/types.go-	// +patchStrategy=merge
apps/v1beta1/types.go:	Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
--
apps/v1beta2/types.go-	// Represents the latest available observations of a statefulset's current state.
apps/v1beta2/types.go-	// +optional
apps/v1beta2/types.go-	// +patchMergeKey=type
apps/v1beta2/types.go-	// +patchStrategy=merge
apps/v1beta2/types.go:	Conditions []StatefulSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,10,rep,name=conditions"`
--
apps/v1beta2/types.go-
apps/v1beta2/types.go-	// Represents the latest available observations of a deployment's current state.
apps/v1beta2/types.go-	// +patchMergeKey=type
apps/v1beta2/types.go-	// +patchStrategy=merge
apps/v1beta2/types.go:	Conditions []DeploymentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
--
apps/v1beta2/types.go-	// Represents the latest available observations of a DaemonSet's current state.
apps/v1beta2/types.go-	// +optional
apps/v1beta2/types.go-	// +patchMergeKey=type
apps/v1beta2/types.go-	// +patchStrategy=merge
apps/v1beta2/types.go:	Conditions []DaemonSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,10,rep,name=conditions"`
--
apps/v1beta2/types.go-	// Represents the latest available observations of a replica set's current state.
apps/v1beta2/types.go-	// +optional
apps/v1beta2/types.go-	// +patchMergeKey=type
apps/v1beta2/types.go-	// +patchStrategy=merge
apps/v1beta2/types.go:	Conditions []ReplicaSetCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
--
autoscaling/v2beta1/types.go-	CurrentMetrics []MetricStatus `json:"currentMetrics" protobuf:"bytes,5,rep,name=currentMetrics"`
autoscaling/v2beta1/types.go-
autoscaling/v2beta1/types.go-	// conditions is the set of conditions required for this autoscaler to scale its target,
autoscaling/v2beta1/types.go-	// and indicates whether or not those conditions are met.
autoscaling/v2beta1/types.go:	Conditions []HorizontalPodAutoscalerCondition `json:"conditions" protobuf:"bytes,6,rep,name=conditions"`
--
core/v1/types.go-	// resized then the Condition will be set to 'ResizeStarted'.
core/v1/types.go-	// +optional
core/v1/types.go-	// +patchMergeKey=type
core/v1/types.go-	// +patchStrategy=merge
core/v1/types.go:	Conditions []PersistentVolumeClaimCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,4,rep,name=conditions"`
--
core/v1/types.go-	// More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
core/v1/types.go-	// +optional
core/v1/types.go-	// +patchMergeKey=type
core/v1/types.go-	// +patchStrategy=merge
core/v1/types.go:	Conditions []PodCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,2,rep,name=conditions"`
--
core/v1/types.go-	// Represents the latest available observations of a replication controller's current state.
core/v1/types.go-	// +optional
core/v1/types.go-	// +patchMergeKey=type
core/v1/types.go-	// +patchStrategy=merge
core/v1/types.go:	Conditions []ReplicationControllerCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,6,rep,name=conditions"`
--
core/v1/types.go-	// More info: https://kubernetes.io/docs/concepts/nodes/node/#condition
core/v1/types.go-	// +optional
core/v1/types.go-	// +patchMergeKey=type
core/v1/types.go-	// +patchStrategy=merge
core/v1/types.go:	Conditions []NodeCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,4,rep,name=conditions"`
--
core/v1/types.go-	// List of component conditions observed
core/v1/types.go-	// +optional
core/v1/types.go-	// +patchMergeKey=type
core/v1/types.go-	// +patchStrategy=merge
core/v1/types.go:	Conditions []ComponentCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,2,rep,name=conditions"`

@sttts
Copy link
Contributor

sttts commented Jun 20, 2018

The problem is that we don't (and probably cannot?) have API conventions to reason about if an arbitrary API field should be optional, so we have to fix them one by one.

Which means a number of follow-ups?

@sttts
Copy link
Contributor

sttts commented Jun 20, 2018

@roycaihw can you formulate the release-note in JSON terms to be understandable by users?

Otherwise, lgtm.

@sttts
Copy link
Contributor

sttts commented Jun 20, 2018

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 20, 2018
@lavalamp
Copy link
Member

/approve

I edited the release note.

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 21, 2018
@roycaihw
Copy link
Member Author

I edited the release note.

@lavalamp Thanks. I was thinking about the point that @smarterclayton made in #65041 (comment). Marking these beta fields omitempty does look backwards incompatible to me if client expects to see the key in the json response from apiserver (even if the value used to be null). Any thought?

/hold

Which means a number of follow-ups?

@sttts Yes I can file an issue for those Conditions [] but I would like more inputs on the convention that we want to enforce (e.g. every Conditions in <RESOURCE>Status should be +optional and omitempty?). Some other API fields tracked in kubernetes-client/gen#52

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jun 22, 2018
@lavalamp
Copy link
Member

I understand apiserver already omits the key completely if the list is empty, and is therefore violating the spec, correct? (per kubernetes-client/gen#52) Is this true for json, proto, both, or neither? Please confirm this before we proceed onto the next step :)

Assuming we are in violation of the spec, we can either fix the spec or fix our behavior. I think fixing the spec is less disruptive overall. Therefore, I agree with this change and think it is allowable, pending double-checking today's behavior.

@smarterclayton
Copy link
Contributor

When you say fixing spec, you mean "tell people to just set +optional in their Godoc without setting omitempty, document that existing fields should never be marked omitempty once they hit beta, and new fields can continue to be created as omitempty"? That would still mark the field optional in OpenAPI, and would preserve the semantics for users.

@k8s-github-robot
Copy link

/test all

Tests are more than 96 hours old. Re-running tests.

@fejta-bot
Copy link

Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Oct 12, 2018
@fejta-bot
Copy link

Stale issues rot after 30d of inactivity.
Mark the issue as fresh with /remove-lifecycle rotten.
Rotten issues close after an additional 30d of inactivity.

If this issue is safe to close now please do so with /close.

Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle rotten

@k8s-ci-robot k8s-ci-robot added lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Nov 11, 2018
@k8s-ci-robot k8s-ci-robot added priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. and removed needs-priority Indicates a PR lacks a `priority/foo` label and requires one. labels Aug 13, 2019
@fejta-bot
Copy link

This PR may require API review.

If so, when the changes are ready, complete the pre-review checklist and request an API review.

Status of requested reviews is tracked in the API Review project.

@liggitt
Copy link
Member

liggitt commented Aug 19, 2019

needs update to include v1 API type as well

@roycaihw roycaihw force-pushed the optional-crdstatus-conditions branch from 2c6fba8 to b614879 Compare August 20, 2019 21:33
@roycaihw
Copy link
Member Author

needs update to include v1 API type as well

thanks. Updated

@roycaihw
Copy link
Member Author

roycaihw commented Aug 20, 2019

/retest

flake:

subresources_test.go:689: unable to update status: Operation cannot be fulfilled on noxus.mygroup.example.com "foo": StorageError: invalid object, Code: 4, Key: /6ce03995-b641-4b07-b305-99a9a6878ed0/mygroup.example.com/noxus/not-the-default/foo, ResourceVersion: 0, AdditionalErrorMsg: Precondition failed: UID in precondition: ee04977e-9768-4062-87e8-f1000a00570e, UID in object meta: 613ac225-6e00-478a-aae7-b6b3828820c9

quite rare according to: https://storage.googleapis.com/k8s-gubernator/triage/index.html?pr=1&text=Precondition%20failed%3A%20UID%20in%20precondition

@roycaihw
Copy link
Member Author

roycaihw commented Aug 21, 2019

/retest

missed / in my previous comment

@liggitt
Copy link
Member

liggitt commented Aug 21, 2019

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 21, 2019
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: lavalamp, liggitt, roycaihw, sttts

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

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@fejta-bot
Copy link

/retest
This bot automatically retries jobs that failed/flaked on approved PRs (send feedback to fejta).

Review the full test history for this PR.

Silence the bot with an /lgtm cancel or /hold comment for consistent failures.

1 similar comment
@fejta-bot
Copy link

/retest
This bot automatically retries jobs that failed/flaked on approved PRs (send feedback to fejta).

Review the full test history for this PR.

Silence the bot with an /lgtm cancel or /hold comment for consistent failures.

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. area/custom-resources cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API lgtm "Looks good to me", indicates that a PR is ready to be merged. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. 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/XS Denotes a PR that changes 0-9 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants