Cloud Endpoints with gRPCで1つのエンドポイントに複数のパッケージ1を使おうとしてちょっと躓いたのでそのメモです。

問題

まず、普通に複数の名前空間を使ってProtocol Buffersの定義ファイルを書くと、2つのファイルを作成することになります。1つのファイルに複数のパッケージを指定するとコンパイルエラーになるためです。

今回はpingechoという2つのパッケージでテストしました。

ping.proto
syntax = "proto3";
package ping;
service PingService {
  rpc Ping (PingRequest) returns (PingResponse) {}
}
message PingRequest {}
message PingResponse {
  string message = 1;
}
echo.proto
syntax = "proto3";
package echo;
service EchoService {
  rpc Echo (EchoRequest) returns (EchoResponse) {}
}
message EchoRequest {
  string message = 1;
}
message EchoResponse {
  string message = 1;
}

そして、これらをデプロイするCloud Endpointsの設定ファイルは次のようになります。

api_config.yaml
type: google.api.Service
config_version: 3

name: api.endpoints.myproject.cloud.goog

title: My APIs
apis:
  - name: echo.EchoService
  - name: ping.PingService

usage:
  rules:
    - selector: "*"
      allow_unregistered_calls: true

このときに別々にコンパイルしてしまうと、デプロイできなくなります。

$ protoc -o echo.pb echo.proto
$ protoc -o ping.pb ping.proto
$ gcloud endpoints services deploy api_config.yaml ping.pb echo.pb
ERROR: (gcloud.endpoints.services.deploy) INVALID_ARGUMENT: Cannot convert to service config.
'ERROR: api_config.yaml:9: Cannot resolve api 'ping.PingService'.'

解決策

これを解決するには出力を1つのファイルにまとめます。

$ protoc -o services.pb echo.proto ping.proto
$ gcloud endpoints services deploy api_config.yaml services.pb

これで問題なくデプロイできました。

ちなみに、既に複数の.pbファイルがある場合は次のように結合してもデプロイできます。

$ cat echo.pb ping.pb > services.pb
$ gcloud endpoints services deploy api_config.yaml services.pb