Cloud9にAWS CDK (Python3) をインストールする方法

#AWS CDKがGA！
2019年7月11日に、AWS Cloud Development Kit (AWS CDK)がGAしました。
Infrastructure as Codeの観点では、CloudFormationを使うよりも開発が楽になるとかなんとか言われていますが、実際に試さねば分からないだろうと思い、早速手を動かしてみることにしました。

本記事では、Cloud9を使ってAWS CDKを開始する方法をまとめてみました。
Python3でCDKを使って開発する前提での覚書となります。

#AWS CDKとは
公式「[What Is the AWS CDK?](https://docs.aws.amazon.com/ja_jp/cdk/latest/guide/home.html)」の解説を紐解いていきます。

* AWS CDKは、クラウドインフラストラクチャをコードで定義するためのソフトウェア開発フレームワークです。
* AWS CDKを使ってコードを書き、実行すると、AWS CloudFormationを通じてインフラストラクチャがプロビジョニングされます。
* CloudFormationとの違いとして、TypeScript、JavaScript、Pythonといった、開発者が慣れ親しんだプログラミング言語でインフラストラクチャを定義できます。
* if分岐やforループを活用できることから、CloudFormationに比べて記述量も減らせそう。

既に、PythonでAWSのインフラストラクチャをプロビジョニングする[troposphere](https://github.com/cloudtools/troposphere)もありますが、AWSが公式でCDKを出してきたことで、サポート面で安心できるCDKの利用が増えていくのかなと思ったりしています。

# AWS CDKをCloud9にインストール
AWS CDK (Python3) を利用して開発するための準備をします。
## 必要条件
・Node.js 8.11.x 以降のバージョンが必要です。
・Python3.6 以降のバージョンが必要です。
・AWS CDK CLIを利用するため、CredentialsとAWSリージョンを特定する必要があります。

## インストール
Cloud9でターミナルを開き `npm install -g aws-cdk` を実行します。

```text:install
$ npm install -g aws-cdk
/home/ec2-user/.nvm/versions/node/v8.16.0/bin/cdk -> /home/ec2-user/.nvm/versions/node/v8.16.0/lib/node_modules/aws-cdk/bin/cdk

> core-js@2.6.9 postinstall /home/ec2-user/.nvm/versions/node/v8.16.0/lib/node_modules/aws-cdk/node_modules/core-js
> node scripts/postinstall || echo "ignore"

Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!

The project needs your help! Please consider supporting of core-js on Open Collective or Patreon: 
> https://opencollective.com/core-js 
> https://www.patreon.com/zloirock 

Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)

+ aws-cdk@1.0.0
added 267 packages from 249 contributors in 12.069s
```

インストールが成功していれば `cdk --version` でバージョンを確認できます。

```text:version
$ cdk --version
1.0.0 (build d89592e)
```

ここで、Cloud9で通常使用するPythonが3.6に設定されていることを ```python --version``` で改めて確認しておきます。

```text
(master) $ python --version
Python 3.6.8
```

もし2.7.xだった場合は、こちらの[リンク先](https://qiita.com/acecrc/items/fb34a12b265122816d4b)の手順で、Python3を使えるように設定を切り替えましょう。
[AWS Cloud9 でPython3を使うための設定
](https://qiita.com/acecrc/items/fb34a12b265122816d4b)

# アプリを作る
次に、**空のディレクトリ**を作って、ディレクトリに移動した後 `cdk init --language python` コマンドで、アプリを初期化します。(Gitリポジトリができます)
今回は分かりやすいように `CDK` というディレクトリ名にしていますが、名前は何でも良いです。
**言語を指定するのは、この `cdk init` を実行する時です。**

```text:init
$ mkdir CDK
$ cd CDK
$ cdk init --language python
Applying project template app for python
Initializing a new git repository...

(略)

Enjoy!
```

結果を確認してみます。 `cdk init` の結果、いろいろできています。

``` 
(master) $ ls -al
total 40
drwxr-xr-x  5 ec2-user ec2-user 4096 Jul 13 07:05 .
drwxr-xr-x 11 ec2-user ec2-user 4096 Jul 13 05:49 ..
-rw-rw-r--  1 ec2-user ec2-user  138 Jul 13 07:05 app.py
drwxrwxr-x  2 ec2-user ec2-user 4096 Jul 13 07:05 cdk
-rw-rw-r--  1 ec2-user ec2-user   32 Jul 13 07:05 cdk.json
drwxrwxr-x  5 ec2-user ec2-user 4096 Jul 13 07:05 .env
drwxrwxr-x  7 ec2-user ec2-user 4096 Jul 13 07:05 .git
-rw-rw-r--  1 ec2-user ec2-user 1651 Jul 13 07:05 README.md
-rw-rw-r--  1 ec2-user ec2-user    5 Jul 13 07:05 requirements.txt
-rw-rw-r--  1 ec2-user ec2-user 1008 Jul 13 07:05 setup.py
```

次に、CDKが依存するパッケージをインストールします。

```text
(master) $ sudo pip install -r requirements.txt                                                   
Obtaining file:///home/ec2-user/environment/CDK (from -r requirements.txt (line 1))
Collecting aws-cdk.core (from cdk==0.0.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/60/99/6b1bc6e1059d0d97050550cfb7aee7ca154cf69ef4afd85e516340b8fd6d/aws_cdk.core-1.0.0-py3-none-any.whl (508kB)
    100% |████████████████████████████████| 512kB 2.4MB/s 
Collecting jsii~=0.14.0 (from aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/fc/30/0954b455242b6b9a01f614db21d8a1707d62c7d302420a6c72c93faeb80e/jsii-0.14.0-py3-none-any.whl (236kB)
    100% |████████████████████████████████| 245kB 4.6MB/s 
Collecting aws-cdk.cx-api>=1.0.0,~=1.0 (from aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/98/be/53a9bb48df0bd066fe1a227a93df70a957b717ce741d6746085bdb49e1ef/aws_cdk.cx_api-1.0.0-py3-none-any.whl (78kB)
    100% |████████████████████████████████| 81kB 6.1MB/s 
Collecting publication>=0.0.3 (from aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/f8/d3/6308debad7afcdb3ea5f50b4b3d852f41eb566a311fbcb4da23755a28155/publication-0.0.3-py2.py3-none-any.whl
Collecting attrs>=18.2 (from jsii~=0.14.0->aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/23/96/d828354fa2dbdf216eaa7b7de0db692f12c234f7ef888cc14980ef40d1d2/attrs-19.1.0-py2.py3-none-any.whl
Collecting cattrs (from jsii~=0.14.0->aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/4a/4e/f8bfec0990a2d4f9f79d4417336b761c58c849672cd3b81637a22f02bb20/cattrs-0.9.0-py2.py3-none-any.whl (54kB)
    100% |████████████████████████████████| 61kB 8.0MB/s 
Collecting typing-extensions>=3.6.4 (from jsii~=0.14.0->aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/27/aa/bd1442cfb0224da1b671ab334d3b0a4302e4161ea916e28904ff9618d471/typing_extensions-3.7.4-py3-none-any.whl
Collecting python-dateutil (from jsii~=0.14.0->aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
  Using cached https://files.pythonhosted.org/packages/41/17/c62faccbfbd163c7f57f3844689e3a78bae1f403648a6afb1d0866d87fbb/python_dateutil-2.8.0-py2.py3-none-any.whl
Collecting importlib-resources; python_version < "3.7" (from jsii~=0.14.0->aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/2f/f7/b4aa02cdd3ee7ebba375969d77c00826aa15c5db84247d23c89522dccbfa/importlib_resources-1.0.2-py2.py3-none-any.whl
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/site-packages (from python-dateutil->jsii~=0.14.0->aws-cdk.core->cdk==0.0.1->-r requirements.txt (line 1))
Installing collected packages: attrs, cattrs, typing-extensions, python-dateutil, importlib-resources, jsii, publication, aws-cdk.cx-api, aws-cdk.core, cdk
  Running setup.py develop for cdk
Successfully installed attrs-19.1.0 aws-cdk.core-1.0.0 aws-cdk.cx-api-1.0.0 cattrs-0.9.0 cdk importlib-resources-1.0.2 jsii-0.14.0 publication-0.0.3 python-dateutil-2.8.0 typing-extensions-3.7.4
```

# Hello World!
app.pyを開いて、テストコードを書き換えます。

```python:app.py
#!/usr/bin/env python3

from aws_cdk import core
from cdk.cdk_stack import CdkStack

app = core.App()

CdkStack(app, "HelloWorldStack")

app.synth()
```

`cdk ls` で、スタックの一覧を列挙できます。

```
(master) $ cdk ls
HelloWorldStack
```

この時、内部的にはapp.pyの中の`app.synth()`が呼ばれて、cdk.outの下にHelloWorldStack.template.jsonができて、その結果をリストしているようです。
※ `app.synth()` を消して実行したら `cdk ls` の実行に失敗しました。

```text
(master) $ ls cdk.out/
cdk.out  HelloWorldStack.template.json  manifest.json
```

`XXX.template.json` はCloudFormationのテンプレートになります。
CDKでコードを書き、内部的にCloudFormationを使ってインフラストラクチャをデプロイしていくという流れが想像できます。

ここまでの手順で、Cloud9上でAWS CDKをインストールし、Python3を使って開発を進める準備が整いました。

# 参考文献
[What Is the AWS CDK?](https://docs.aws.amazon.com/ja_jp/cdk/latest/guide/home.html)
[Getting Started With the AWS CDK](https://docs.aws.amazon.com/ja_jp/cdk/latest/guide/getting_started.html)