概要
- CDK for TerraformをPythonで試そうとしてハマったところのまとめ
- 公式のGet StatedはTypeScriptの手順であり、Pythonの手順が無かったのであれこれ調べながら試した
- コマンド内の一部をマスク(xxxxx)しておりますが、ユーザ名をマスクしているだけです
参考
- https://www.hashicorp.com/blog/cdk-for-terraform-enabling-python-and-typescript-support/
- https://github.com/hashicorp/terraform-cdk/tree/master/examples/python/aws
やろうとしたこと
- CDK for TerraformのPythonでVPC,Subnetを作る
install
- npmでcdktf-cliをインストール
$ npm install -g cdktf-cli
/Users/xxxxx/.anyenv/envs/nodenv/versions/12.13.0/bin/cdktf -> /Users/xxxxx/.anyenv/envs/nodenv/versions/12.13.0/lib/node_modules/cdktf-cli/bin/cdktf
npm WARN eslint-plugin-react@7.20.6 requires a peer of eslint@^3 || ^4 || ^5 || ^6 || ^7 but none is installed. You must install peer dependencies yourself.
+ cdktf-cli@0.0.16
updated 3 packages in 19.656s
╭────────────────────────────────────────────────────────────────╮
│ │
│ New minor version of npm available! 6.13.6 → 6.14.8 │
│ Changelog: https://github.com/npm/cli/releases/tag/v6.14.8 │
│ Run npm install -g npm to update! │
│ │
╰────────────────────────────────────────────────────────────────╯
- バージョン確認
$ cdktf --version
0.0.16
- cdktfコマンド確認
$ cdktf
cdktf [コマンド]
コマンド:
cdktf deploy [OPTIONS] Deploy the given stack
cdktf destroy [OPTIONS] Destroy the given stack
cdktf diff [OPTIONS] Perform a diff (terraform plan) for the given stack
cdktf get [OPTIONS] Generate CDK Constructs for Terraform providers and modules.
cdktf init [OPTIONS] Create a new cdktf project from a template.
cdktf login Retrieves an API token to connect to Terraform Cloud.
cdktf synth [OPTIONS] Synthesizes Terraform code for the given app in a directory. [エイリアス: synthesize]
オプション:
--version バージョンを表示 [真偽]
--disable-logging Dont write log files. Supported using the env CDKTF_DISABLE_LOGGING. [真偽] [デフォルト: true]
--log-level Which log level should be written. Only supported via setting the env CDKTF_LOG_LEVEL [文字列]
-h, --help ヘルプを表示 [真偽]
Options can be specified via environment variables with the "CDKTF_" prefix (e.g. "CDKTF_OUTPUT")
プロジェクト新規作成
- ディレクトリ作成
$ mkdir vpc-example
$ cd vpc-example
- 初期化
- ここで以下を入力する
- Terraform Cloud使うかどうか
- 言語選択(Python/TypeScript)
- プロジェクト名
- プロジェクト説明
$ cdktf init
Welcome to CDK for Terraform!
By default, cdktf allows you to manage the state of your stacks using Terraform Cloud for free.
cdktf will request an API token for app.terraform.io using your browser.
If login is successful, cdktf will store the token in plain text in
the following file for use by subsequent Terraform commands:
/Users/xxxxx/.terraform.d/credentials.tfrc.json
Note: The local storage mode isn't recommended for storing the state of your stacks.
Do you want to continue with Terraform Cloud remote state management (yes/no)? no # Terraform Cloudは今回は利用しないためno
[1] python
[2] typescript
[0] CANCEL
What template you want to use? [1, 2, 0]: 1 # python選択
Initializing a project using the python template.
We will now set up the project. Please enter the details for your project.
If you want to exit, press ^C.
Project Name: (default: 'vpc-example') vpc-example # プロジェクト名入力
Project Description: (default: 'A simple getting started project for cdktf.') # プロジェクト説明入力
Unable to find "pipenv". Install from https://pipenv.kennethreitz.org
エラー① 「Unable to find "pipenv". Install from https://pipenv.kennethreitz.org」
- cdktf initで生成されるファイル(cdktf.json)内を見てみたらpipenvを利用しているので追加する
$ brew install pipenv
(長いので略)
- 再度初期化
$ cdktf init
Welcome to CDK for Terraform!
By default, cdktf allows you to manage the state of your stacks using Terraform Cloud for free.
cdktf will request an API token for app.terraform.io using your browser.
If login is successful, cdktf will store the token in plain text in
the following file for use by subsequent Terraform commands:
/Users/xxxxx/.terraform.d/credentials.tfrc.json
Note: The local storage mode isn't recommended for storing the state of your stacks.
Do you want to continue with Terraform Cloud remote state management (yes/no)? no # Terraform Cloudは今回は利用しないためno
[1] python
[2] typescript
[0] CANCEL
What template you want to use? [1, 2, 0]: 1 # python選択
Initializing a project using the python template.
We will now set up the project. Please enter the details for your project.
If you want to exit, press ^C.
Project Name: (default: 'vpc-example') vpc-example # プロジェクト名入力
Project Description: (default: 'A simple getting started project for cdktf.') # プロジェクト説明入力
Creating a virtualenv for this project…
Pipfile: /Users/xxxxx/workspace/AWS/terraform/cdk/vpc-example/Pipfile
Using /Users/xxxxx/.anyenv/envs/pyenv/versions/3.7.0/bin/python3.7m (3.7.0) to create virtualenv…
⠦ Creating virtual environment...created virtual environment CPython3.7.0.final.0-64 in 1887ms
creator CPython3Posix(dest=/Users/xxxxx/.local/share/virtualenvs/vpc-example-krFy7qQn, clear=False, global=False)
seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/Users/xxxxx/Library/Application Support/virtualenv)
added seed packages: pip==20.2.1, setuptools==49.2.1, wheel==0.34.2
activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator
✔ Successfully created virtual environment!
Virtualenv location: /Users/xxxxx/.local/share/virtualenvs/vpc-example-krFy7qQn
Pipfile.lock not found, creating…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Updated Pipfile.lock (a65489)!
Installing dependencies from Pipfile.lock (a65489)…
🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 00:00:00
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Installing cdktf~=0.0.16…
Adding cdktf to Pipfile's [packages]…
✔ Installation Succeeded
Pipfile.lock (a65489) out of date, updating to (c2187c)…
Locking [dev-packages] dependencies…
Locking [packages] dependencies…
Building requirements...
Resolving dependencies...
✔ Success!
Updated Pipfile.lock (c2187c)!
Installing dependencies from Pipfile.lock (c2187c)…
🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 00:00:00
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.
Generated python constructs in the output directory: imports
========================================================================================================
Your cdktf Python project is ready!
cat help Prints this message
Compile:
pipenv run ./main.py Compile and run the python code.
Synthesize:
cdktf synth Synthesize Terraform resources to cdktf.out/
Diff:
cdktf diff Perform a diff (terraform plan) for the given stack
Deploy:
cdktf deploy Deploy the given stack
Destroy:
cdktf destroy Destroy the given stack
========================================================================================================
VPCを追加してみる
- main.pyを編集
- AWS provider追加
- VPC(10.0.0.0/16)追加
- Subnet x3 追加
main.py
# !/usr/bin/env python
from constructs import Construct
from cdktf import App, TerraformStack
+ from imports.aws import AwsProvider # 追加
+ from imports.terraform_aws_modules.vpc.aws import Vpc # 追加
class MyStack(TerraformStack):
def __init__(self, scope: Construct, ns: str):
super().__init__(scope, ns)
# define resources here
+ AwsProvider(self, 'Aws', region='ap-northeast-1') # 追加
+ Vpc(self, 'vpc-from-cdk-for-terraform',
+ name='vpc-from-cdk-for-terraform',
+ cidr='10.0.0.0/16',
+ azs=["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"],
+ public_subnets=["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
+ ) # 追加
app = App()
MyStack(app, "vpc-example")
app.synth()
- deployしてみる
$ cdktf deploy
⠇ synthesizing ...
Traceback (most recent call last):
File "./main.py", line 5, in <module>
from imports.terraform_aws_modules.vpc.aws import Vpc
⠙ synthesizing ...
non-zero exit code 1
エラー② 「terraform_aws_modulesが見つからない」
- cdktf.jsonにmoduleの設定がされていなかった
cdktf.json
{
"language": "python",
"app": "pipenv run ./main.py",
"terraformProviders": ["aws@~> 2.0"],
+ "terraformModules": ["terraform-aws-modules/vpc/aws"], # 追加
"codeMakerOutput": "imports"
}
- moduleをゲット
$ cdktf get
Generated python constructs in the output directory: imports
- module確認
$ ll imports
total 0
drwxr-xr-x 5 xxxxx 1896053708 160 8 23 22:51 aws
drwxr-xr-x 3 xxxxx 1896053708 96 8 23 22:51 terraform_aws_modules
- 再deploy
$ cdktf deploy
Stack: vpc-example
Resources
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_internet_gateway.this[0]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route.public_internet_gateway[0]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table.public[0]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table_association.public[0]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table_association.public[1]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table_association.public[2]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_subnet.public[0]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_subnet.public[1]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_subnet.public[2]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_vpc.this[0]
Diff: 10 to create, 0 to update, 0 to delete.
Do you want to perform these actions?
CDK for Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes # yesを入力
- terraformでおなじみの「Enter a value:」で
yes
を入力
deploy中となり
⠼ Deploying Stack: vpc-example
完了
Summary: 0 created, 0 updated, 0 destroyed.
なぜか全部0
AWSコンソール確認
- できていたもの
- VPC
- Internet Gateway
- Public Subnet x3
- Route Table
上記のcdk deploy
実行中に表示されていたリソースができていた
terraform plan的なものができるか確認
- subnetを3 -> 2に減らしてみる
main.py
# !/usr/bin/env python
from constructs import Construct
from cdktf import App, TerraformStack
from imports.aws import AwsProvider
from imports.terraform_aws_modules.vpc.aws import Vpc
class MyStack(TerraformStack):
def __init__(self, scope: Construct, ns: str):
super().__init__(scope, ns)
# define resources here
AwsProvider(self, 'Aws', region='ap-northeast-1')
Vpc(self, 'vpc-from-cdk-for-terraform',
name='vpc-from-cdk-for-terraform',
cidr='10.0.0.0/16',
- azs=["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"],
+ azs=["ap-northeast-1a", "ap-northeast-1c"],
- public_subnets=["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
+ public_subnets=["10.0.1.0/24", "10.0.2.0/24"]
)
app = App()
MyStack(app, "vpc-example")
app.synth()
- 差分確認
$ cdktf diff
Stack: vpc-example
Resources
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table_association.public[2]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_subnet.public[2]
Diff: 0 to create, 0 to update, 2 to delete.
- subnetを3 -> 4に増やしてみる
main.py
# !/usr/bin/env python
from constructs import Construct
from cdktf import App, TerraformStack
from imports.aws import AwsProvider
from imports.terraform_aws_modules.vpc.aws import Vpc
class MyStack(TerraformStack):
def __init__(self, scope: Construct, ns: str):
super().__init__(scope, ns)
# define resources here
AwsProvider(self, 'Aws', region='ap-northeast-1')
Vpc(self, 'vpc-from-cdk-for-terraform',
name='vpc-from-cdk-for-terraform',
cidr='10.0.0.0/16',
- azs=["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"],
+ azs=["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d", "ap-northeast-1a"],
- public_subnets=["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
+ public_subnets=["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
)
app = App()
MyStack(app, "vpc-example")
app.synth()
- 差分確認
$ cdktf diff
Stack: vpc-example
Resources
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table_association.public[3]
+ module.vpcexample_vpcfromcdkforterraform_660852D9.aws_subnet.public[3]
Diff: 2 to create, 0 to update, 0 to delete.
削除
$ cdktf destroy
⠋ planning vpc-example...
Stack: vpc-example
Resources
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_internet_gateway.this[0]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route.public_internet_gateway[0]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table.public[0]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table_association.public[0]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table_association.public[1]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_route_table_association.public[2]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_subnet.public[0]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_subnet.public[1]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_subnet.public[2]
- module.vpcexample_vpcfromcdkforterraform_660852D9.aws_vpc.this[0]
Diff: 0 to create, 0 to update, 10 to delete.
Do you want to perform these actions?
CDK for Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
- Enter a value: は
yes
を入力
⠼ Destroying Stack: vpc-example
Summary: 0 destroyed.
こちらも何故か 0 destoryed
まとめ
- pipenvインストールが必要
- 依存moduleなどは
cdktf.json
に書いてね - deploy/destroyの結果がまだ不安定っぽい
- そしてdeploy/destroyを間違えそう・・・
- importとかいろいろためしてみよう