APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Datastore Import/Exportの紹介(2/2)

始めに

先進サービス開発事業部の山岡です。

前回の記事の続きで、Datastore Import/Exportによる定時バックアップについて書きたいと思います。

旧世代の仕様ではGAEのcronを使い特定のURLを叩くことで起動することができました。新しい方式でも大筋は同じで、cronからURLを叩きその中の動作でDatastoreのAPIを叩くような動作となります。

使い方

権限設定

まずはGAE側からDatastoreのAPIを使うための権限設定を行います。

下記画像のように「IAMと管理」を開きApp Engine default service accountに対しCloud Datastore インポート / エクスポート管理者の権限を付与して下さい。

f:id:ryo-yamaoka:20180531195659p:plain
Cloud Datastore インポート / エクスポート管理者

これを忘れるとAPIのリクエスト時にHTTP403になってしまいます。

Tokenの取得

APIのリクエストにはTokenを含める必要がありますので、以下のようにして取得します。

token, expire, _ := appengine.AccessToken(ctx, "https://www.googleapis.com/auth/datastore", "https://www.googleapis.com/auth/cloud-platform")

取得するTokenの種類はこの2つのURL決め打ちです。2番目の戻り値にはExpireTimeが入っていますので必要に応じて使って下さい。

JSONの作成

リクエスト時にどのKindをバックアップ対象にするか、また出力先のGCSを指定したPOSTを送信する必要があります。

Kindの指定は"entityFilter": { "kinds": ["kind1", "kind2"] }の形で行います。これを省いた場合はCLIと同様に全てのKindがバックアップ対象となり、全てのKindをまとめてリストアすることしかできなくなってしまいますのでdatastore.Kinds(ctx)から取得したものを使うのが良いでしょう。但しこの場合はMapReduceで内部的に使われていたKindも含まれてしまうためアンダースコア始まりのKindは除外してやります。

"outputUrlPrefix"については出力先のGCSパスを指定します。CLIのデフォルトと同じパスを指定したい場合は下記のように指定すると良いでしょう。

outputUrlPrefix := "gs://example-bucket/" + strings.Replace(t.Format("2006-01-02T15:04:05.00000"), ".", "_", 1)

最終的な姿としては以下のようになります。

{
  "entityFilter": {
    "kinds": [
      "kind1",
      "kind2"
    ]
  },
  "outputUrlPrefix": "gs://example-bucket/2018-05-17T09:20:05_80900/"
}

HTTPリクエストの作成と実行

先の工程で得たトークンとJSONをリクエストに含めたhttp.Requestを作成します。JSONは単純にBodyへ入れればOKですが、トークンはAuthorization: Bearer xxxxxの形でリクエストヘッダーに入れます。

これらが出来たらurlfetchから実行してあげればバックアップが始まるはずです。ジョブ作成の成否やその内容はレスポンスに含まれますので、必要ならどこかへ通知したり記録して下さい。

jsonBytes, _ := json.Marshal(payload)
req, _ := http.NewRequest(
    "POST",
    "https://datastore.googleapis.com/v1/projects/"+appengine.AppID(ctx)+":export",
    bytes.NewBuffer(jsonBytes),
)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
resp, _ := urlfetch.Client(ctx).Do(req)

以上でバックアップジョブが動き出すはずなのでgcloud datastore operations list等で確認してみて下さい。