-
Notifications
You must be signed in to change notification settings - Fork 254
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
[protoc-gen-openapi] Support google.protobuf.Any and google.rpc.Status #327
Conversation
@timburks here is another one for you |
@jeffsawatzky could you merge the main branch (now containing #324) and resolve any conflicts? I'm not expecting any problems, but that would clarify what's new here. |
… qualified naming of google.protobuf.Value
f55cc29
to
9db6849
Compare
@timburks done (rebased everything) |
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.
Just a few initial questions while I'm reading this...
@@ -246,7 +246,7 @@ components: | |||
- type: array | |||
items: | |||
$ref: '#/components/schemas/AnyJSONValue' |
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.
On my first read-through, I'm wondering why this didn't change to google.protobuf.Value
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 file was generated with fq_schema_naming=false
(the default) so it uses the older AnyJSONValue
schema name for backwards compatibility.
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.
There was a bug in my previous PR with google.protobuf.Value
not getting converted to the fully qualified name, which I didn't catch until I added support for google.protobuf.Any
. This is why you see the schema name change in the openapi_fq_schema_naming.yaml
file (which uses fully qualified naming) since I have fixed the issue in this 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.
I was wondering the same thing.
The library is at < v1.0.0, isn't it better to be consistent/correct rather than backwards compatible at this point?
@@ -246,7 +246,7 @@ components: | |||
- type: array | |||
items: | |||
$ref: '#/components/schemas/AnyJSONValue' |
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.
also here, why isn't this google.protobuf.Value?
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.
Same with this file, it was generated with fq_schema_naming=false
(the default) so it uses the older AnyJSONValue
schema name for backwards compatibility.
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.
Just a thought regarding the description of google.protobuf.Value
:
Isn't the description a bit wrong? The value can never be null
, right?
OpenAPI (v3.0.x) doesn't support null
as type and the schema says oneOf
, so it must be one of the types - therefore it can not be null
.
@@ -246,7 +246,7 @@ components: | |||
- type: array | |||
items: | |||
$ref: '#/components/schemas/AnyJSONValue' |
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 was wondering the same thing.
The library is at < v1.0.0, isn't it better to be consistent/correct rather than backwards compatible at this point?
@@ -246,7 +246,7 @@ components: | |||
- type: array | |||
items: | |||
$ref: '#/components/schemas/AnyJSONValue' | |||
description: AnyJSONValue is a "catch all" type that can hold any JSON value, except null as this is not allowed in OpenAPI | |||
description: '`Value` represents a dynamically typed value which can be either null, a number, a string, a boolean, a recursive struct value, or a list of values. A producer of value is expected to set one of that variants, absence of any variant indicates an error. The JSON representation for `Value` is JSON value.' |
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.
If AnyJSONValue is kept, this description should also be kept.
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 description is coming straight off of the google.protobuf.Value message here:
https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/struct.proto#L56L61
Which followed the pattern of using the message comments for the schema descriptions.
I can switch it back to a hard coded value though if that is preferred.
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.
When running the schema through a JSON validator, you will get an error, if the value is null
, but not if the property is not set at all.
So basically: it can not be null
- it is our definition that is wrong, since it does not have null
as a possible type, but we can not have null
as a type, because OpenAPI v3.0.x does not allow that.
It will be doable in OpenAPI v3.1.0 as full JSON Schema is supported.
@jeffsawatzky and @timburks what is your opinions 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'm not actually a big fan of the comment for the Any
message...it's way too long. So I might hard code that to something smaller anyway. If you want me to change the comment here for Value
too I can do that.
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.
As it is actually incorrect, due to the need of breaking that definition, I think it would make sense to use something like the original AnyJSONValue is a "catch all" type that can hold any JSON value, except null as this is not allowed in OpenAPI
.
Maybe borrow some from the protobuf comment:
Value represents a dynamically typed value which can be any JSON value, except null
.
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 both AnyJSONValue
and Value
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.
@morphar I was referring to this big long comment for the Any
message. It's way too huge.
https://github.com/google/gnostic/pull/327/files#diff-190e6a851c89c364cd83e2bd05fc44555cdb0d940341e5c531a4eae9c0c66308R29
I'm going to fix that up along with the one for the Value
message.
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.
Aaahh... Gotcha :) 👍
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.
Also, while the "null" type is not allowed, we could make the schema nullable which would allow null values.
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.
Nice catch!
That would also allow for proper handling of google.protobuf.Value
, as it can then also be set to required
:
... absence of any variant indicates an error ...
👍
@@ -246,7 +246,7 @@ components: | |||
- type: array | |||
items: | |||
$ref: '#/components/schemas/AnyJSONValue' | |||
description: AnyJSONValue is a "catch all" type that can hold any JSON value, except null as this is not allowed in OpenAPI | |||
description: '`Value` represents a dynamically typed value which can be either null, a number, a string, a boolean, a recursive struct value, or a list of values. A producer of value is expected to set one of that variants, absence of any variant indicates an error. The JSON representation for `Value` is JSON value.' |
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.
Also keep, if AnyJSONValue is kept.
@@ -246,7 +246,7 @@ components: | |||
- type: array | |||
items: | |||
$ref: '#/components/schemas/AnyJSONValue' | |||
description: AnyJSONValue is a "catch all" type that can hold any JSON value, except null as this is not allowed in OpenAPI | |||
description: '`Value` represents a dynamically typed value which can be either null, a number, a string, a boolean, a recursive struct value, or a list of values. A producer of value is expected to set one of that variants, absence of any variant indicates an error. The JSON representation for `Value` is JSON value.' |
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.
One more, if keep AnyJSONValue, then keep this as well
name := getMessageName(message.Desc) | ||
if !*g.conf.FQSchemaNaming { |
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 is also a question of: should we be consistent or backwards compatible.
I would personally prefer that types are the same, regardless of the naming.
I would be surprised if I changed the naming option and got different types.
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'm not sure about the history of the naming here, but without it being fully qualified with the package prefix then the name of the schema would just be Value
which seems a little too general perhaps. Same with Any
. I am happy to switch them both to just be Value
and Any
in the case non-fully-qualified names if that is what you prefer. I personally will always use the fully qualified names so it doesn't matter to me. :)
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.
Aahh... Good point! You're absolutely right 👍 It would easily risk conflicting with a user's naming, which is why the AnyJSONValue
name was chosen in the first place, if I remember correctly.
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.
Would it make more sense to have GoogleProtobufValue
instead of AnyJSONValue
?
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.
If you are ok with a possibly breaking change, that is fine with me. I'll do what the repo owners here want. :)
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.
:) It makes sense to me, as one of the overall goals is to be able to convert both ways, so to have the "full" name, is probably more sane, than AnyJSONValue
. What are your thoughts @timburks?
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.
No strong opinion, but GoogleProtobufValue
sounds more specific. I'm fine with whatever you two work out.
I just checked a whole bunch of scenarios and validators. |
…ed their descriptions, and added nullable to Value
@morphar I updated the name and descriptions of the |
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.
Only the 1 comment. Otherwise it looks good to me 👍
@@ -951,9 +951,9 @@ func (g *OpenAPIv3Generator) addSchemasToDocumentV3(d *v3.Document, messages []* | |||
Value: &v3.SchemaOrReference{ | |||
Oneof: &v3.SchemaOrReference_Schema{ | |||
Schema: &v3.Schema{ | |||
Description: messageDescription, | |||
Description: "Represents a dynamically typed value which can be either null, a number, a string, a boolean, a recursive struct value, or a list of values.", | |||
Nullable: true, // this only works with OpenAPI 3.0.x |
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.
Is it possible to set this to required
as well?
Then it would adhere to both OpenAPI v3.0.x and the protobuf description, right?
I agree. We define 3.0.3, so we should adhere to that spec, ignoring 3.1.x in this code. |
I don't think I need to add "required" to the |
Great! 👍 Regarding
|
Yes, required would have to be set on the property of whatever parent schema defines a Value property. |
I'm just trying to understand if this is actually 100% compatible now. Is the |
@morphar I'm not sure if it is possible or even needed to tell you the truth. From what I can tell, it isn't possible for a schema to require itself to be present in a parent schema. For example, if a With that said, I don't think it is needed anyway. According to the Protocol Buffer Language Guide:
Furthermore, I think what we have for FWIW, the protoc-gen-openapiv2 generator just uses "object" for
|
@jeffsawatzky sorry, I was unclear. I meant if we should set the OpenAPI property as required. |
@morphar I read the following:
As: However, when it comes to JSON I don't think it matters since the JSON transcoding will treat a missing value as an implicit null value. The docs say:
So I think we can represent So, to answer your question, I don't think a property in OpenAPI needs to be defined as |
@morphar seeing as how I have a few PRs queuing up, can we keep this PR focused on the Status and Any schemas? We can discuss the Value schema in another issue perhaps? |
@jeffsawatzky Sorry, just did a test against Envoy. You're completely right, it is not required to be set, when the protobuf type is |
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.
Everything looks good to me 👍
It's fully up to you, if you want the schemaless / typeless to be in another 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.
I thought I approved the last review :)
Maybe @timburks needs to approve, for the merging to be unblocked? |
@morphar since you confirmed we can go typeless I have made that change to make the openapi doc smaller. |
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.
👍 Beautiful! Thank you @jeffsawatzky :)
And sorry for the long discussion back and forth @jeffsawatzky! But nice that it resulted in a way better solution 👍 |
@morphar No worries. I'm glad we were able to work out a solution together! |
@morphar @jeffsawatzky thanks for all this! merging now |
Great! Thanks @timburks 👍 |
Note that this PR is based off of my previous PR #324 which is not yet merged. So while the changes here look big, here are the actual changes relevant to this PR:
jeffsawatzky/gnostic@fq-names...jeffsawatzky:grpc-status
Purpose
Envoy and grpc-gateway use the
google.rpc.Status
message to report error messages back as can be seen here:https://github.com/envoyproxy/envoy/blob/9dd8ae3c69a9917d97a886ed03e1c010dcd9b098/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc#L827L860
google.rpc.Status
provides a way to report additional error details in thedetails
property, which is a list ofgoogle.protobuf.Any
which has special JSON encoding as can be seen here:https://developers.google.com/protocol-buffers/docs/proto3#json
Note that
google.protobuf.Any
andgoogle.protobuf.Value
are different.google.protobuf.Value
can be any JSON value, whereasgoogle.protobuf.Any
can be any protobuf message type and has a special@type
property when transcoded so that you can determine which protobuf message definition to use.We don't have control over the value of
@type
and it will always be the fully qualified name of the protobuf message. So if people what to be able to use this to map back to an OpenAPI schema definition then they will need to use fully qualified names (which I added in PR #324)