-
Notifications
You must be signed in to change notification settings - Fork 515
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
Change AIP-149 guidance from "should" to "should not" for proto3 optional on primitives #863
Comments
I'm strongly supportive of this. In addition to @SirGitsalot's points:
|
For a concrete example of the danger of This was a real bug that happened to us in Terraform! hashicorp/terraform-provider-google#1608 |
Just playing devil's advocate here. The way @SirGitsalot worded the proposed AIPs, it sounds to me like the recommendation is never to use I don't know if there are other implementations similar to the proto3 JSON mapping mentioned, but it sounds to me like the proposed change is specifically meant to cater to that implementation. Are there other, similar tools that fall victim to the same problem? To that end, is there another alternative where the proto3 JSON mapping implementation processes the proto messages differently as not to cause this problem. It also sounds like part of the problem is that this isn't documented correctly since
I would think that, at a minimum, that updating that documentation to correctly reflect the behavior with optional fields would help mitigate the issue. Finally, regarding the comment of @rileykarson - I'm not familiar with Terraform, but in reading through the real-world case you brought up, it seems like the request in question was intended to target objects in the bucket that were live ( Just some food for thought, but the TLDR is - does making the proposed change simply solve a problem with one implementation at the expense of creating a problem in another? And if so, is there a way we can word this to explain why we should ever use |
It's a little messier than that! The field can be unset meaning match both live and noncurrent objects, true meaning match only live objects, and false meaning match only noncurrent objects. However, if a bucket doesn't have versioning turned on, all objects are live so unset and true are equivalent. The user thought they'd specified nothing, our client didn't know the field was
I suspect we have to consider how users are using these APIs. I believe it to be the case that the majority of GCP users interact with the REST API indirectly (gcloud, Terraform, Config Connector, and other orchestration tools are all REST-based) and some advanced users will interact with the API directly (i.e. through REST client libraries). That may not be as true for other Google APIs, though. That may mean a Cloud-specific AIP would be appropriate, for example, or a relatively strong
I want to stress that all Cloud APIs (and other public Google APIs, the most accessible list I know is https://github.com/googleapis/google-api-go-client's service list) are using this proto-to-JSON mapping to create REST APIs. |
Re: user cannot figure out optional: There was no interest from the OnePlatform team to fix the autogenerated documentation to show that a field was optional (either in the REST or the grpc documentation). You cannot figure out this information from the discovery JSON. So this is not new to Terraform. |
I guess in some sense this is a problem with FieldMask being a poorly designed feature. Today, the user has to do:
This gets increasingly worse when Book has a dozen fields to update. I mean, the user just set a dozen fields on Now, you could say that you should Which is why we have a FieldMasks class to examine a proto object / do a proto diff to figure out what the user's FieldMask should be.
But then, we can't distinguish between
And
Now, if |
To elaborate on the point that @AnashOommen made, the FieldMask design is an issue in the Ads API because its resources have many fields that are frequently updated, so it is important that users only perform partial updates on the fields they actually want to change. Generally speaking, if APIs have similar characteristics (resources with many fields that are frequently updated), I would suspect those APIs will encounter similar issues, and as a result, similar issues with removing the |
This sounds like what we've done clientside in DCL and KCC, who represent all types as indirect types (i.e. Representing API types as |
A lot of the discussion on this issue seems to be based on the public proto3 documentation, which has not been updated for
... where proto3 optional fields do have explicit presence. How much does that change the objection to using |
Ping on this, @SirGitsalot, @rileykarson, @AnashOommen, @devchas |
Most of my thoughts are based on the difficulty wrt. implementing clients- lack of metadata in GCP specs (c.g.c. docs, discovery docs), lack of pointer types (needed to represent fyi @toumorokoshi @slevenick in case you're interested! |
@rileykarson: Thanks for the extra detail. (I think the choice of whether If there are concrete aspects (like Discovery, docs and the Go implementation) that can be improved, and additional rules (like considering it to be a breaking change), that feels like a more constructive set of things to look at than a blanket ban based on initially-incorrect expectations around JSON representations. |
AIP-149 says:
I propose changing this to "Services defined in protocol buffers should not use the optional keyword". While it's easy for a service that's built using protocol buffers and gRPC to use
optional
for field presence detection, it's difficult (and sometimes impossible) for clients using other encodings and transports (e.g., JSON over HTTP). As a concrete example, most GCP APIs use proto3 JSON mapping to convert protos to and from JSON. That mapping explicitly says that omitting a field entirely, setting it tonull
, and setting the field to its default value are equivalent. That's not true foroptional
fields, and in turn that means that JSON-comsuming clients must create special case code to support APIs that useoptional
.Instead of using
optional
APIs should:Following this new guidance the AIP-149 example would look like:
The text was updated successfully, but these errors were encountered: