-
Notifications
You must be signed in to change notification settings - Fork 808
Adds declarative-friendly state transition guidance #1079
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
base: master
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -123,6 +123,44 @@ message PublishBookRequest { | |
| - The comment for the field **should** document the resource pattern. | ||
| - Other fields **may** be included. | ||
|
|
||
| ### Declarative-friendly state transitions | ||
|
|
||
| If a resource's state can be modified by [declarative tooling][aip-128], it | ||
| **should** expose a separate `desired_state` field taking the same enum type. | ||
|
|
||
| ```proto | ||
| message Book { | ||
| enum State { | ||
| STATE_UNSPECIFIED = 0; | ||
| UNPUBLISHED = 1; | ||
| PUBLISHING = 2; | ||
| PUBLISHED = 3; | ||
| } | ||
|
|
||
| State state = 1 [(google.api.field_behaviopr = OUTPUT_ONLY)]; | ||
|
Contributor
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. Typo |
||
| State desired_state = 2; | ||
|
Contributor
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. Issues with this:
Separate attributes are often better. For instance, Kubernetes Deployment has a "paused" field:
Contributor
Author
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.
Contributor
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.
@bgrant0607 I feel like we should just update google.aip.dev/180 to explain this one. One reason is that clients unaware of the new enum value will receive the unspecified value, and send that over the wire potentially erasing the currently set parameter.
I'm not sure if it's that strong of a case, but we do need updated guidance that enables known gaps like cross-service lifecycle management. I definitely agree guidance needs be updated, but it's on a longer backlog. At minimum I think anything that removes guidance from AIP-128 and reduces the gap between declarative-friendly and non-declarative-friendly APIs is an improvement. Thanks for authoring this!
Contributor
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. To clarify I think Brian is arguing for more granular switches on fields ( 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. I'd suggest this actually isn't a recommendation we should make. It may even be an anti-pattern, although it's understandable why it comes up as an idea every so often.
So it seems like there's a connection between the two. But having an assignable field of the output-only enum is very rarely the best way to design the new hand-free resource control feature. A different question to ask is "What config-feature on this resource would I add that, when optionally configured by the customer, would tell the backend when these custom methods should be called automatically?" Looking at VM instance, some custom methods that can't be reached are start/stop/reset/suspend/resume... A quick hypothetical of those... ... just a gist, but you get the idea.
|
||
| } | ||
| ``` | ||
|
|
||
| - The `state` field's output **may** change to more granular | ||
| [active states](#common-states) to indicate progress toward the `desired_state`. | ||
| - The `desired_state` field **must** only allow [resting state](#common-states) | ||
|
Contributor
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. As discussed above, the best way to enforce this is to use a separate enum entirely. Doing so eliminates the need to require the runtime behavior outlined below (preconditions, invalid_argument) |
||
| enum values. | ||
| - Attempting to set `desired_state` to an [active state](#common-states) **must** | ||
| error with `INVALID_ARGUMENT` (HTTP 400). | ||
| - Attempting to set `desired_state` to a state that cannot be transitioned to | ||
| from the current state **must** error with `FAILED_PRECONDITION` (HTTP 400). | ||
| - A [long-running][] operation **must not** complete until the `state` has | ||
|
mbleigh marked this conversation as resolved.
Contributor
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. would this apply for custom methods, or for updates? In either case I kind of feel like this shouldn't be the case - the client can poll the resource state if desired, and if the operation takes hours, have a several-hour-long LRO just to see if your parameter was accepted feels like it'll limit it's utility for local clients like gcloud and Terraform. |
||
| reached the `desired_state` (or **must** error if it cannot). | ||
| - If a resource supports both declarative `desired_state` and imperative | ||
| [state transition methods](#state-transition-methods), executing a state | ||
| transition method **should** modify the desired state appropriately. | ||
|
Contributor
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. This will create drift in declarative clients. It would be better to not have the desired state field in that case.
Contributor
Author
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. Yes, it will create drift - but I'm trying to consider:
Declarative tooling expects to be the only manager of a given resource, so out of band updates of any kind create drift problems. This is something that API consumers have to manage for themselves.
Contributor
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. maybe this is why it's best to not have e.g. Or maybe have a way to clear desired state (unspecified) that allows custom methods to mutate the state? effectively a lock. |
||
| - If a resource is created without `desired_state`, the field **must** default | ||
|
Contributor
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're working on guidance around how to handle default values. When services change values set by clients, it causes problems for declarative and other state-driven clients. It would be better to leave the value unspecified.
Contributor
Author
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. I can buy an argument for leaving it unspecified.
Contributor
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. +1 to unspecified. unspecified IMO means "I'm managing this state outside of the resource". If i saw a resting value I'd read that to be "keep this resource in the resting state". |
||
| to the same resting value as `state`. | ||
| - If an out-of-band event causes the resting `state` of the resource to change, | ||
| the `desired_state` **must** be changed to match. This does not apply to | ||
| a temporary condition that will return to the same resting state. | ||
|
|
||
| ## Additional Guidance | ||
|
|
||
| ### Default value | ||
|
|
@@ -239,4 +277,5 @@ necessary. | |
| - **2019-07-18**: Added explicit guidance on the unspecified value. | ||
|
|
||
| [aip-126]: ./0126.md | ||
| [aip-128]: ./0128.md | ||
| [long-running]: ./0151.md | ||
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 shouldn't call this "declarative-friendly": there really shouldn't be a different between declarative-friendly APIs and non-declarative friendly APIs.
Is there a way to make the guidance more generic?
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.
I'd say this guidance is more "managing state with resource fields" than declarative.