google / gnostic-grpc

A gnostic plugin that converts an OpenAPI API description into a description of a gRPC service that can be used to implement that API using gRPC-JSON Transcoding.
Apache License 2.0
297 stars 53 forks source link

File included an unresolvable reference #84

Open nomad-software opened 2 years ago

nomad-software commented 2 years ago

I'm trying to convert the following Json file: https://github.com/oracle/hospitality-api-docs/blob/main/rest-api-specs/property/lov.json

Using this command:

gnostic --grpc-out=api ../hospitality-api-docs/rest-api-specs/property/lov.json

and i'm getting this error:

Errors reading ../hospitality-api-docs/rest-api-specs/property/lov.json
Plugin error: [file "lov.proto" included an unresolvable reference to "GetChannelParametersLOVResponses"]

If I then try the --resolve-refs option like this:

gnostic --grpc-out=api --resolve-refs ../hospitality-api-docs/rest-api-specs/property/lov.json

I get another slightly different error:

Errors reading ../hospitality-api-docs/rest-api-specs/property/lov.json
Plugin error: [file "lov.proto" included an unresolvable reference to "lov.GetChannelParametersLOVOK"]

There's another file that has problems too: https://github.com/oracle/hospitality-api-docs/blob/main/rest-api-specs/property/fofcfg.json

but the rest convert correctly. Any ideas on what is happening here as the Json files seem to be valid?

Thanks.

nielthiart commented 9 months ago

@nomad-software Were you able to resolve this issue for your use case, or do you know what caused this error?

nomad-software commented 9 months ago

Nope, it was never resolved. I had to remove the offending parts by had from the Json file before conversion. Luckily I didn't need those particular endpoints.

nielthiart commented 9 months ago

Thanks! I found that if I use a recent version of gnostic to create a .pb binary, I can get the .proto output by running gnostic-grpc -input petstore.pb, for example.

nomad-software commented 9 months ago

Thanks for the suggestion but that doesn't work on the original file mentioned.

iliakonnov commented 7 months ago

I believe to have found source of this issue.

Definition like this:

"DataResult": {
  "properties": {
    "object": {
      "additionalProperties": {
        "$ref": "#/definitions/DataResult"
      },
      "description": "Object value",
      "example": "",
      "type": "object"
    },
    "string": {
      "type": "string"
    },
  },
  "type": "object"
}

Is represented by gnostic-grpc like that:

message Object {
    map<string, DataResult> additional_properties = 1;
}

message DataResult {
    string string = 1;
    Object object = 2;
}

To do that, gnostic internally generates a type to store object field data.

https://github.com/google/gnostic/blob/ad271d568b713ad381ad6751cd8b950eade78d98/surface/model_openapiv2.go#L388-L393

Note that it uses namedSchema.Name as a name for a new type. In this case it happens to be an object (look at field name).

Later, gnostic-rpc begins processing a field with name object and type object:

https://github.com/google/gnostic-grpc/blob/c8bc7e1d29fa90542c0e50c5f1c207f2d16b4970/generator/language.go#L36-L38

Since type object is reserved it is not resolved there.

https://github.com/google/gnostic-grpc/blob/c8bc7e1d29fa90542c0e50c5f1c207f2d16b4970/generator/language.go#L81-L82

But later on NativeType of a field is used as a name of a referenced proto message (resulting in api_package.object):

https://github.com/google/gnostic-grpc/blob/c8bc7e1d29fa90542c0e50c5f1c207f2d16b4970/generator/generator_messages.go#L162-L164

Obviously, this results in an invalid proto file since it does not contains a definition for a api_package.object message.

I've fixed the issue for me by changing the first snippet to prefix generated type name with it's containing type name.

    fieldTypeName := fmt.Sprintf("%s_%s", name, namedSchema.Name)
    fieldInfo := b.buildFromSchemaOrReference(fieldTypeName, namedSchema.Value)
    makeFieldAndAppendToType(fieldInfo, schemaType, namedSchema.Name)
wkrige commented 3 months ago

Thanks! I found that if I use a recent version of gnostic to create a .pb binary, I can get the .proto output by running gnostic-grpc -input petstore.pb, for example.

Same issue. This path worked for me. Thanks for the help! Strange that the invocation of gnostic-grpc as plugin gives different results.