DeploymentManagerを利用したCloud SQLの作成

# DeploymentManagerを利用したCloud SQLの作成 #

## サマリー ##
### やりたいこと ###
- GCPのDeploymentManager を使ってCloudSQLも一連の自動化の処理として作成したい。（別にgcloudコマンドやRESTでも別にいいんですが）

### 結論 ###
- DeploymentManagerを利用してCloudSQLの作成/削除ができるようになった

### ハマったこと ###
- YAMLの例が少ない
- ユーザの権限情報を作成しないとdeploymentManagerで削除できない
- インスタンス名がすぐには使いまわせない

## 手順 ##
### 前提 ###
CloudSQLとしての対象は
1. [Cloud SQL for MySQL][cloudsql-mysql-url] : MySQLベース
2. [Cloud SQL for PostgreSQL][cloudsql-postgre-url] : PostgreSQLベース
がありますが、前者のMySQLベースを対象とします。

また、Cloud SQL for MySQL内でも第1世代と第2世代の違いがあります。
基本的に性能がよいとされる第2世代を対象とします。

また以下の条件を満たしているものとします。

- GCP上にプロジェクトがある
- プロジェクトでCloudSQLが作成できる権限がある（課金設定など）  
まだの場合は公式の[クイックスタート][quick-start-url]の手順に従って構築します。
- 操作端末には`gcloud`コマンドが導入されている


### GCPコンソールからのインスタンスの作成方法（確認） ###
ここでは事前準備がきちんとされているかをGCPコンソールからCloudSQLを作成することで確認します。確認ができているのであれば飛ばして構いません。
1. [インスタンス作成ページ](https://console.cloud.google.com/projectselector/sql/instances?hl=ja&_ga=2.168220321.-1098436370.1497935559&supportedpurview=project)へ移動
2. プロジェクトを選択し、`続行`をクリックします。
3. `インスタンスを作成`をクリックします。
4. エンジンの選択で、MySQLの`第 2 世代`を選択された状態で`MySQLを選択`をクリックします。
5. ユースケースの選択で（検証目的なので）`MySQLの開発の設定`をクリックします。
6. MySQLの設定を実施します。
  - インスタンスID※
  - rootパスワード
  - リージョン
      - asia-northeast1（なんとなく日本）
  - マシンタイプとストレージ
      - SSD -> HDD（貧乏性なので…）
  - `作成`をクリック

※簡単に作れて、簡単に消せますが、なぜかインスタンス名は**最長1週間は使いまわせない**とのことなので、本番用の名前は最後まで取っておきましょう。

### DeploymentManageでのインスタンスの作成方法 ###
ここから本題。deployment-managerでも作れます。

まず下記の`cloudsql.yml`と`cloudsql.jinja`を作成し、同一ディレクトリに保存します。 　
念のために書いておきますが、ファイル名は任意です。ただし、jinjaはymlが参照するのでそこは注意しましょう。

```yml
#cloudsql.yml
imports:
- path: cloudsql.jinja

resources:
- name: mysql5-6
  type: cloudsql.jinja
  properties:
    instanceName: mysql5-6
    region: asia-northeast1
    tier: db-n1-standard-1
    databaseVersion: MYSQL_5_6
    dataDiskType: PD_HDD
    dataDiskSizeGb: 70
    userName: <DB接続ユーザ名>
    password: <DB接続パスワード>
```

```yml
#cloudsql.jinja
resources:
- name: {{ properties["instanceName"] }}
  type: sqladmin.v1beta4.instance
  properties:
    backendType: SECOND_GEN
    region: {{ properties["region"] }}
    databaseVersion: {{ properties["databaseVersion"] }}
    instanceType: CLOUD_SQL_INSTANCE
    settings:
      tier: {{ properties["tier"] }}
      dataDiskType: {{ properties["dataDiskType"] }}
      dataDiskSizeGb: {{ properties["dataDiskSizeGb"] }}
- name: {{ properties["userName"] }}
  type: sqladmin.v1beta4.user
  properties:
    instance: $(ref.{{ properties["instanceName"] }}.name)
    password: {{ properties["password"] }}
    host: "cloudsqlproxy~%"
```

設定ファイルの準備ができたら下記のようにDeploymentManagerを実行します。

```shell
$ gcloud deployment-manager deployments create <deploymentManager上の名前> --config cloudsql.yml
```
以上！

ちなみに削除したい場合は以下。コンソールからも削除できます。

```shell
$ gcloud deployment-manager deployments delete <deploymentManager上の名前> -q 
```

最後の`-q`オプションは削除確認しないためのものです。

## ハマったこと ##
### YAMLの例が見つからない ###
探し方が悪いのだろうけど見つけられなかった。  
[GoogleのResourceの例](https://cloud.google.com/deployment-manager/docs/configuration/supported-resource-types?hl=ja)を参照しながら試行錯誤。 　
あれ、REST用のJSONの例なので試行錯誤。

できたのが↑のYAML。他にも色々パラメータはあるので必要に応じて設定しましょう。

### ユーザの権限情報を作成しないとdeploymentManagerで削除できない ###
どうもdeploymentManagerでの操作時に必要なパラメータが揃っているかをチェックされるみたいなのですが、ユーザの権限情報についてなしでも作成できるのに**削除時にはユーザの権限情報が必須**と怒られる。 　
ここでのユーザはあくまでdeploymentManagerの構成情報としてのものなので、**後からCloudSQLのコンソールから追加しても関係ない**。~~バグじゃないのか~~　 
ということで


```yaml
    host: "cloudsqlproxy~%"
```
を忘れないようにしましょう。

### インスタンス名がすぐには使いまわせない ###
試行錯誤のために作っては削除し、ってやりたかったんですがインスタンス名がそのままだと既に使われている旨のエラーが出ます。

[公式ページ](https://cloud.google.com/sql/docs/mysql/delete-instance?hl=ja)によると
```
削除したインスタンスのインスタンス名は、削除してから最大 1 週間は再利用できません。
```
とのことで、即座に使える保証はないとのことです。 　
「本番はこの名前で！」とか決まっているのであればちゃんと動作検証終わるまでは使わないようにした方がいいかもです。

[cloudsql-url]:https://cloud.google.com/sql/docs/?hl=ja
[cloudsql-mysql-url]:https://cloud.google.com/sql/docs/mysql/?hl=ja
[cloudsql-postgre-url]:https://cloud.google.com/sql/docs/postgres/?hl=ja
[quick-start-url]:https://cloud.google.com/sql/docs/mysql/quickstarts?hl=ja
[quick-3-url]:https://console.cloud.google.com/flows/enableapi?apiid=sqladmin&hl=ja