🩴

Cloud Functions で、Cloud Storage にある CSV を Cloud SQL にインポートする

2023/09/16に公開

ドキュメントはあるにはあるんだが、まとまった手順がそろってなかったので書いておく。細かいところが未テストなのであとで追記するかも。

前提

  • Cloud Functions は python で書く
  • Cloud SQL instance, Cloud Storage bucket は作成済みとする

overview

必要なリソースはこんな感じ。

service account の作成

Cloud Functions

まず、Cloud Functions の service account を用意する。

手順は、

  • service account を作成
  • Cloud SQL Admin ロールをつける
  • import したい CSV がある Cloud Storage bucket に Storage Legacy Object Reader ロールをつける

ソース

The Cloud SQL Admin role and the roles/storage.legacyObjectReader IAM role

https://cloud.google.com/sql/docs/postgres/import-export/import-export-csv#required_roles_and_permissions_for_importing_to

Cloud SQL

つぎに、 Cloud SQL の service account に対象の Cloud Storage bucket への Storage Object Viewer ロールをつける。この service account のメールアドレスは Cloud SQL の画面から見れる。

ソース

Provide your instance with the storage.objectAdmin IAM role for your bucket. For help with setting IAM permissions, see Using IAM permissions.

https://cloud.google.com/sql/docs/postgres/import-export/import-export-csv#required_roles_and_permissions_for_importing_to

Cloud Functions から discovery API を呼び出す

調べたかぎり python 用の Cloud SQL client はないので、 discovery API を使うしかない。

まずパッケージを入れる。

$ pip install google-api-python-client

次に、service account key をダウンロードして、環境変数にセットする。なおこの環境変数は GCP 上で動かすときは不要で、あくまでローカルでテストするときのみ必要。

$ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json

コードはこんな感じ。 TODO のところは各自直してください。

import google.auth
from googleapiclient import discovery

creds, project_id = google.auth.default()
service = discovery.build("sqladmin", "v1beta4", credentials=creds)
req_body = {
    "importContext": {
        "fileType": "CSV",
        "uri": "gs://path/to/file.csv",
        "database": "my-db", # TODO
        "csvImportOptions": {
            "table": "my-table" # TODO
            # TODO: uncomment according to csv file format
            # "escapeCharacter": "escape_character",
            # "quoteCharacter": "quote_character",
            # "fieldsTerminatedBy": "fields_terminated_by",
            # "linesTerminatedBy": "lines_terminated_by",
        },
    }
}
req = service.instances().import_(
    # TODO: set instance ID
    project=project_id, instance="my-cloud-sql-instance", body=req_body
)
resp = req.execute()
import json

print(json.dumps(resp, indent=2))

ポイント1: discovery API のドキュメントはここ
https://cloud.google.com/sql/docs/mysql/admin-api/rest/v1beta4/instances/import

service.instances().import ではなく import_ なところに注意かも。

ポイント2:
google.auth.default() を使うことで、GCP の Application Default Credentials を使える。
https://google-auth.readthedocs.io/en/master/reference/google.auth.html#google.auth.default

ポイント3: インポートする CSV はカラムの列に注意。table schema と列の順番を揃えるか、 request body の中で columns を指定するかのどちらかが必要。

Note: The default behavior for Cloud SQL is to import columns in your CSV file in the same order as the table schema. If the order is different in your CSV file or if some columns are skipped, use importContext.csvImportOptions.columns[] to import data from the CSV file.

https://cloud.google.com/sql/docs/postgres/import-export/import-export-csv#required_roles_and_permissions_for_importing_to

実行結果を確認

Cloud SQL の Operations 画面から、インポート結果を見て成功してればおーけー。

Discussion