はじめに
こんにちは、TIG DXチームの真野です。Go Cloud記事の第6弾です。
- Go Cloud#1 概要とBlobへの活用方法
- Go Cloud#2 Pub/Subの概要紹介
- Go Cloud#3 Go CloudのDocStoreを使う
- Go Cloud#4 URLを編集するパッケージ
- Go Cloud#5 AWSのローカルモック環境であるLocalStackを活用する
- Go Cloud#6 GCPのローカルエミュレータを活用する(この記事です)
- Go Cloud#7 PubSubドライバー(pubだけ)を実装してみる
本記事では、Go CloudでGCPのエミュレータに接続してみます。同様の企画であるAWS LocalStack版は第5弾でまとめていますので、詳細はそちらを確認ください
GCPのローカルエミュレータとは
GCPのリソースを管理するためのコマンドラインインタフェースとして gcloud があり、このgcloudコマンド経由で各種エミュレータを実行できます。
gcloudはAWSでいうAWS CLIに相当しますが、AWS CLIにはもちろんそのような仕組みは備わっていません。代わりにLocalStackというツールを利用することが多いです。それとは異なりGCPは標準コマンドに組み込まれているということで、思想の違いのようなものを感じられ興味深いですね。
エミューレータ種類について
gcloud alpha emulators --help
で確認すると、2019年11月時点でエミュレートできるサービスは4つです。
- bigtable
- pubsub
- datastore
- firestore
現時点ではGo CloudのBlobに相当するCloud Storageのエミュレータは存在しないようです 1。
存在しない理由は注釈1のStackOverflowの回答にもありますが、各Cloud StorageのSDKに、ローカルストレージに書き込むオプションが存在するため、エミュレータレベルでは存在しないのでは? と推測します。純製ではないですが fsouza/fake-gcs-serverというツールもあるので、こちらを利用することも検討に値するかもしれません。
本記事では、gcloud emulator で実行できる、 pubsubとfirestoreに対してGo Cloudでアクセスしていきます。
Cloud Pub/Sub
Cloud Pub/Sub は送信者と受信者を切り離す多対多の非同期メッセージングを提供することによって、別々に開発されたアプリケーションの間で安全かつ高可用な通信を実現するGCPのプロダクトです。送信側がPublisher、受信側がSubscriberと呼ばれ、1:Nのメッセージのやり取りを行えます。
https://cloud.google.com/pubsub/docs/overview
ドキュメントに従いgcloud pubsubエミュレータをインストールします。
gcloud components install pubsub-emulator |
インストールが終わったら、以下のコマンドでエミュレータを起動します。
gcloud beta emulators pubsub start --project=dummy |
--project
で指定するPJは実際に存在しないダミー値でOKです。ポートはデフォルト 8085
で起動します。 --port
オプションで変更も可能です。
アプリケーションにエミュレータを認識させるためには、PUBSUB_EMULATOR_HOST
と PUBSUB_PROJECT_ID
という2つの環境変数を設定する必要があるので設定します。
export PUBSUB_EMULATOR_HOST=localhost:8085 |
このまま、gcloudコマンドで起動したpub/subのエミュレータに対してトピックを作成します。…と言いたいところですが、 実はgcloudはエミュレータに非対応です。
The emulator does not support GCP Console or gcloud pubsub commands.
(エミュレータはGCPコンソールやgcloud pubsubコマンドに対応していません)
https://cloud.google.com/pubsub/docs/emulator#using_the_emulator
え、どうやってトピック作るの? って疑問に思いましたが、GCPのSDK経由であれば操作できるようです(そうでないと意味無いので当然ですが)。ドキュメントにPython製のツールがいくつかおいてあるので、そちらをgcloudコマンドの代わりに利用してトピックを作成します。
# ツールの取得 |
Topic created: name: "projects/dummy/topics/future-example"
といったメッセージが出力されれば成功です。
ではGo Cloudでさきほど作成した future-example
というトピックに対してPublishしてみます。
package main |
実は上記のコードは2019/11時点のGo CDK 0.1.0では上手く動かないようです。理由は、PUBSUB_EMULATOR_HOST
の環境変数は読んでくれているようです が、gRPCのトランスポートがCredentialsがついたたままで、 Insecureオプションへの切り替えが無いからだと思います。PullRequstチャンスだと思いますが、現時点のコードベースだと、gcppubsubパッケージでガンバってInsecureオプションを付ける処理を入れる必要がある気がします。
ということで、例えば以下のようなコードでWithInsecureで切り替えが必要すれば一応動かすことができます。ちょっと長いですがGCPのCredentailsを環境変数ではなく 自前で設定する場合のコード に、エミュレータの切り替えを追加しただけです。
var endPoint = "pubsub.googleapis.com:443" |
続いて、Subscribeです。先程のPython製ツールでSubscriptionのエンドポイントを作成します。ProjectID, トピック名を指定し、gocdk-example1
としたエンドポイントを指定しました。
python subscriber.py dummy create future-example gocdk-example1 |
この gocdk-example1
に対してGo Cloudでアクセスします。
func main() { |
Subscribeのテストをしたい場合は、先程のPythonライブラリにサンプルでPublishするツールも付いているのでそちらで検証すると良いと思います。
python publisher.py dummy publish future-example |
上記は、1から10までpublishする簡単なツールですが、検証用途ととしてはお手軽なのでオススメです。実行すると、Subscription側に標準出力されることが確認できると思います。
Cloud Firestore
Cloud Firestore は、高速でサーバーレスなフルマネージドのクラウド ネイティブ NoSQL ドキュメント データベースです。
https://cloud.google.com/firestore/
エミュレータのインストールはこちら を参考にできますが、今回はgcloudコマンドを直接叩いて起動させます。
gcloud components install cloud-firestore-emulator |
インストールが終わったら、以下のコマンドでエミュレータを起動します。オプションはこちら を参考ください。
gcloud beta emulators firestore start --project dummy --host-port=localhost:8080 |
--host-port
オプションでポートを固定できます(指定しないと起動のたびに違うポートが用いられました)。localhost:8080
でアクセスすると Ok
が返ってくれば起動成功です。
これをGo Cloudでアクセスします。その前にCloud Pub/Subの場合と同様に、エミュレータの環境変数を設定します。
export FIRESTORE_EMULATOR_HOST=localhost:8080 |
続いてコードはこちらです。FirestoreもPub/Subと同様に、エミュレータ対応する関数を用意してスイッチさせています。
type Record struct { |
コードの中でCreate(登録)とGet(取得)ができました。後はエミュレータを意識すること無く操作できます。
まとめ
GCPのローカルエミュレータのFirestore, PubSubに対して多少前処理が必要ですがGo Cloudから十分アクセスができます。同時にまだ実装が枯れきっていないので色々PullRequestチャンスだと思います。
エミュレータを使っていてよかったなと思うポイントは、gcloudこそ利用できませんでしたが、PubSubで登場したPythonツールのように、既存のエコシステムを活用出来る点で、コードの動作確認ではとてもお世話になると思います。
Go Cloud自体の file
や mem
のような機能と合わせてエミュレータも上手く使い分けて、より生産性と品質を高められるようにしていきたいですね。