CloudFunctionを使って他のPJのCloudStorageにあるCSVデータをCloudSQLに入れる方法

## アーキテクチャ図
![CF2SQL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/fd55e2d6-7afb-5d38-b0b0-3cb09a8dc1f5.png)
ちなみにステップ数は約20ステップ。こんなの楽勝だと思ってたら何日もハマってしまった。

## ソース
ソースも簡単。StackOverflowにあるまんま書けば良い。

```python:MAIN.PY
def importDs(request):
    import googleapiclient.discovery
    from oauth2client.client import GoogleCredentials

    credentials = GoogleCredentials.get_application_default()
    service = googleapiclient.discovery.build('sqladmin', 'v1beta4', credentials=credentials)

    # Project ID of the project that contains the instance.
    project = '[プロジェクト名]'  # TODO: Update placeholder value.
    # Cloud SQL instance ID. This does not include the project ID.
    instance = '[CloudSQLのインスタンス名]'  # TODO: Update placeholder value.
    instances_import_request_body = {
        "importContext": {
            "uri": "[GCSの場所]",
            "database": '[database名]',
            "fileType": "CSV",
            "csvImportOptions": {
                "table": "[テーブル名]"
            }
        }
    }

    request = service.instances().import_(project=project, instance=instance, body=instances_import_request_body)
    response = request.execute()
```

```text:REQUIREMENTS.TXT
google-api-python-client==1.9.3
google-auth-httplib2==0.0.3
google-auth==1.17.2
oauth2client==4.1.3
```

## The service account does not have the required permissions for the bucket.にハマる。

参照するCloudStorageにあるCSVファイルが他のPJなので、Cloud Funtionの権限をCloudStorageにつけてもアクセスが出来ない。
え？なんで？普通これで動くんじゃないのか？？PJすべてのサービスアカウントやIAMで定義されているものすべて付けても動かない。これで何日もハマる。

## 正解は、CloudSQLインスタンスのサービスアカウントをCloudStrageに付与
「CloudFuntionはCloudSQLのAPIからimportするから、CloudSQLインスタンスのサービスアカウントをCloudStrageに付与すれば動くんじゃないのか？」と思いついてやったら、アッサリ動きました。

![CloudSQLサービスアカウント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/e0b19c7e-e2de-b569-02e6-190a2189a7fa.png)
ここのサービスアカウントをCloudStoregeのバケットに付与する。

![gcs_権限.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/d04fd0a9-6b64-1353-fdfe-f791c57f60a0.png)
CloudStorageの該当バケットの三点リーダーを押して、権限を追加します。

![gcs権限追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/025febcb-f828-211c-d7c4-31382df7d093.png)
「項目を追加」から、
 エンティティ: 「ユーザー」 
 名前      : CloudSQLインスタンスのサービスアカウント
 アクセス権: 「読み取り」 （読み取りしか使わないため）
上記で追加する。


## backetでやる場合
ファイルでやるのではなくて、backetでやる場合
![bucket_permission.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/3cec68b3-2293-0943-12c7-682aa28e1c49.png)

バケットの編集権限を付与します。
![bucket_add_member.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/27077885-4e20-5476-6be4-f4aad7f7dc39.png)
メンバーを追加します。
![bucket_add_member2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17419/07652ac3-8165-cac2-0776-005fde2a5357.png)
Storageオブジェクトを閲覧にして追加します。

わかってしまえば１日もかからない作業に何日もかかってしまった。

## ちょっと気になる
oauth2clientはもうdescriptionなので、google-authを使う形に変えたほうがいい。 

## 参考URL

参考1:[Import GCS CSV into Cloud SQL from Cloud Function](https://stackoverflow.com/questions/57843016/import-gcs-csv-into-cloud-sql-from-cloud-function)
参考2:[Google Cloud ドキュメント Method: instances.import](https://cloud.google.com/sql/docs/mysql/admin-api/rest/v1beta4/instances/import)
参考3:[Google Cloud ドキュメント Cloud SQL にデータをインポートする](https://cloud.google.com/sql/docs/mysql/import-export/importing?hl=ja#rest)
参考4:[Google Cloud ドキュメント Cloud Functions から Cloud SQL に接続する](https://cloud.google.com/sql/docs/mysql/connect-functions?hl=ja#python)