-
Notifications
You must be signed in to change notification settings - Fork 517
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(AIP-4231): include type and child_type ref compat guidance #1332
Conversation
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 correct to me, but I'll need to take a bit of time to check that we actually comply with it in C#...
SGTM! Holding, no real rush. |
Tested for C# with Cloud Functions v2. In ListFunctionsRequest:
I changed the |
Wonderful. Thanks for checking. Do you want to check the |
Hmm... I think this shows it works when we go from type to a child type that only has a single parent. It would definitely be a semantic breaking change, in that you'd be going from saying "this value is always in format X" to "this value is always in format X, Y or Z" (so anyone assuming X would be broken). Hmm. (This may also depend on the name of the field, at least in C#. I'm not sure how far we want to go with this.) |
I think my perspective is a bit skewed towards request message resource_references, where the user sets the value, and as long as what they were setting previously is still supported then adding new supported patterns isn't breaking. I think you are right that it would be risky in the response case, where user assumes it is always X, but suddenly it's Y...that said I don't know what level of support we have for references in responses since we don't typically control the response message (protobuf codegen does), whereas with request fields, we control the generated function signature at the very least. |
Yes, it's definitely simpler for request messages. I'll try to work out a way of testing the "specific type to child_type with extra parents" situation. It may be a matter of making a breaking change in one commit (that never gets published) and then checking whether going back again is not breaking... |
Okay, testing with https://github.com/googleapis/googleapis/blob/master/google/cloud/accessapproval/v1/accessapproval.proto First, change ListApprovalsRequestMessage.parent to: string parent = 1 [(google.api.resource_reference) = {
type: "cloudresourcemanager.googleapis.com/Project"
}]; Regenerate and commit. This commit is effectively the reverse of what we want to do, but it's expected to be breaking. The interesting bit is when we revert the change in the proto, so converting it to: string parent = 1 [(google.api.resource_reference) = {
child_type: "accessapproval.googleapis.com/ApprovalRequest"
}]; Regenerate and commit. The commit can be seen here (for now - I'll delete the branch in a bit). Changes are:
So that particular example looks compatible. Maybe we should be slightly more coy about this and say that changes to request message resource reference fields should be compatible? |
Thank you for testing all of this!
I'm fine with that :) PTAL I only changed that second case of |
Yup, that looks good :) |
aip/client-libraries/4231.md
Outdated
@@ -219,6 +219,13 @@ to the following backwards-compatibility expectations: | |||
libraries. | |||
- The addition of a `google.api.resource_reference` annotation on an existing | |||
field **must** be a backwards-compatible change. | |||
- Changing a `google.api.resource_reference` from `child_type` to `type` | |||
**must** be a backwards-compatible change when the `child_type` referenced | |||
is single-parented and the newly referenced `type` is that exact parent. |
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 wonder if we could provide examples regarding what single-parented
means, or links to other AIPs if it is already explained? They may seem straightforward to people that are familiar with the concept of resources, but could take a while for people to figure it out by themselves if they are not.
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.
Fair point, the distinction is actually described earlier in this AIP under the heading Multi-pattern resources
. Would you still like to see some reference here?
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've updated the language to be a little more specific regarding the parts of the resource definition that are pertinent to evaluation, as well as references to the relevant sections for more examples.
@blakeli0 thanks for reviewing, I was about to ask for your thoughts :D |
@@ -219,6 +219,19 @@ to the following backwards-compatibility expectations: | |||
libraries. | |||
- The addition of a `google.api.resource_reference` annotation on an existing | |||
field **must** be a backwards-compatible change. | |||
- Changing a `google.api.resource_reference` from `child_type` to `type` | |||
**must** be a backwards-compatible change when the `child_type` referenced | |||
has a single `pattern` and the newly referenced `type` is the matching |
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.
Maybe is the only matching parent
? Because if a child has multiple parents, it would not be backwards-compatible.
If I'm understanding correctly, if the child type is
option (google.api.resource) = {
type: "recaptchaenterprise.googleapis.com/RelatedAccountGroupMembership"
pattern: "projects/{project}/relatedaccountgroups/{relatedaccountgroup}/memberships/{membership}"
}
It has a single pattern
and Project
is actually one of the matching parent, but changing the child_type to Project
would still be breaking because it is not the only parent.
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.
Project
isn't the parent (though I guess you could call it a grandparent) because that's not longest matching pattern
sans child resource's segments - /memberships/{membership}
It sounds like you want more clarity on such definitions, but I don't think this is the right section to do that in - this language needs to be concise and succinct regarding compatibility.
Can we instead improve such documentation in a separate PR?
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.
SGTM. I definitely want to understand more about how the parent of child_type
is resolved, it would be great if we have examples for it. Back to my question though, is it possible for a child_type
to have multiple parents if it only has one pattern
?
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.
For sure, you got it!
Back to my question though, is it possible for a
child_type
to have multiple parents if it only has onepattern
?
Nope! I will start by saying that the current google.api.resource
annotation does not express this well, which is why you and I are here and why we need to add some words to fix it :)
The basic form of a resource name pattern is roughly expressed in regex as
(?<parent>([a-z][a-zA-Z0-9]*\/\{[a-z][_a-z0-9]*[a-z0-9]\}\/)*)(?<child>[a-z][a-zA-Z0-9]*\/\{[a-z][_a-z0-9]*[a-z0-9]\})
Plugging that into regex101 you get this: https://regex101.com/r/N9fbQ7/1 - take a look at how the parent and child named groups change as the pattern gets longer.
Basically, a resource name is multiple pairs of pluralCollectionName/{singular_typ_name}
over and over, with the last pair being the "child" resource collection, and the concatenation of all previous pairs being the "parent" resource.
Put differently, if I define a resource Foo
with pattern foos/{foo}
, then a child Bar
with foos/{foo}/bars/{bar}
, and another Baz
with foos/{foo}/bars/{bar}/bazs/{baz}
and I want the parent of Baz
, the resource that defines the name pattern with the summation of all preceding pairs is Bar
This backfills guidance that wasn't written down explicitly, but should've been implemented in all languages that support resource references.
Covers two cases that involve switching between
type
andchild_type
references that should be safe to make as the the field either remains the same or gains additional possible patterns.