【学習メモ】CDKのチュートリアルをためす

## はじめに
Pythonを書いたことのない初心者が、テキストで書いていたCloudformationをCDKでやってねと言われたときの話。

## 注意
この記事はAWSの公式を感想を交えてなぞ(って検証す)るだけの記録です。
英語の記事はGoogle翻訳を使います。

## CDK
ぐぐったらすぐに見つかりました。
[既存のCloudFormationテンプレートファイルをAWS CDKに移行してみた(dev.classmethod.jp)](https://dev.classmethod.jp/articles/cdk-cfn-include/)

すぐに記事のマネをしたい気になりましたが一呼吸。
「[ググるのをやめるとプログラムの生産性が上がるかもしれない(simplearchitect.hatenablog.com)](https://simplearchitect.hatenablog.com/entry/2018/09/18/080347)」を思い出して、まず公式ドキュメントを探します。

こちらもすぐに見つかりましたが、イングリッシュ！
[Getting started with the AWS CDK](https://docs.aws.amazon.com/ja_jp/cdk/latest/guide/getting_started.html)
ですが諦めてガイドをいちから取り組みます。

## 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

GoかPythonで書いてねと聞いていましたが、5つの言語(TypeScript, JavaScript, Python, Java, or C#)から選べるようです。
あれ？Goがない？
「Finally, you should be proficient in the programming language you intend to use with the AWS CDK.」
スクリプト書きますがBashとコマンドプロンプトしか書きません。
習熟が必要なんて最初に言って欲しいですね。
とはいえ、5つから選び放題というのも贅沢な悩みです。

出てきた用語。
アップ、スタック(Cloudformationと同じ単語だけど指しているものは違う？)、コンストラクト。
アップ内にスタックがあって、スタック内にコンストラクトがあって、コンストラクトの中にAWSリソースが定義される。

コンストラクトは3つにわかれる。(L1 ... Level 1)
・AWS CloudFormation-only or L1→Cfnに直接対応。
・Curated or L2→L1をカプセル化？
・Patterns or L3→コンストラクトライブラリではL1/L2とは別…（意味不）

Node.jsが必要？ Javascriptの実行環境くらいの知識で、完全に異国のツール状態です。
なんとなく ```brew install node.js```と打ってみたら入りました。

```
% which -a node
/usr/local/bin/node
% node -v
v15.4.0
```

awsのクレデンシャルを入力します。

```
aws configure --profile cdktest
```

```
% npm install -g aws-cdk

added 192 packages, and audited 192 packages in 6s

found 0 vulnerabilities
npm notice
npm notice New minor version of npm available! 7.0.15 -> 7.1.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v7.1.1
npm notice Run npm install -g npm@7.1.1 to update!
npm notice

% cdk --version
1.77.0 (build a941c53)
```

次に進みます。

## Your first AWS CDK app

プロジェクト用のフォルダを作ります。

```
% mkdir hello-cdk
% cd hello-cdk
```

```pythonを選択
% cdk init app --language python
```

ドキュメントと実行する内容が少し違いました。

```
% source .venv/bin/activate
```

入力の際に```(.venv)```と付くようになりました。

```
(.venv)% python -m pip install -r requirements.txt
```
2行目を見るとpipで警告が出ていたのでアップデートします。

```
WARNING: You are using pip version 20.2.1; however, version 20.3.1 is available.
You should consider upgrading via the '/Users/myname/hello-cdk/.venv/bin/python -m pip install --upgrade pip' command.
```
```
(.venv)% /Users/myname/hello-cdk/.venv/bin/python -m pip install --upgrade pip
Collecting pip
  Downloading pip-20.3.1-py2.py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 5.8 MB/s
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 20.2.1
    Uninstalling pip-20.2.1:
      Successfully uninstalled pip-20.2.1
Successfully installed pip-20.3.1
```
スタック一覧を見ます。

```
(.venv)% cdk ls
hello-cdk
```
S3バケットのリソースが入ったスタックをまず作るようです。
コンストラクトライブラリから、AmazonS3パッケージをインストールします。
必要なサービスはこの「コンストラクトライブラリ」からDLすつ必要があるようです。

```:s3Packageのインストール
(.venv)% pip install aws-cdk.aws-s3
Collecting aws-cdk.aws-s3
(中略)
Installing collected packages: aws-cdk.aws-iam, aws-cdk.aws-kms, aws-cdk.aws-events, aws-cdk.aws-s3
Successfully installed aws-cdk.aws-events-1.77.0 aws-cdk.aws-iam-1.77.0 aws-cdk.aws-kms-1.77.0 aws-cdk.aws-s3-1.77.0
```

hello_cdk/hello_cdk_stack.pyを2箇所書き換えよと出ています。
変更前の中身をみてみます。

```:変更前
(.venv)% cat -n hello_cdk/hello_cdk_stack.py
     1	from aws_cdk import core
     2
     3
     4	class HelloCdkStack(core.Stack):
     5
     6	    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
     7	        super().__init__(scope, construct_id, **kwargs)
     8
     9	        # The code that defines your stack goes here
```

指示が曖昧ですが書き換えてみます。
pythonもコメントアウトは#でできる模様。インデントが意味を持つ言語と聞いていたので、とりあえず行頭、行頭でないを守ってコピペしてみます。

```:変更後
(.venv)% cat -n hello_cdk/hello_cdk_stack.py
     1	#from aws_cdk import core
     2	from aws_cdk import (
     3	    aws_s3 as s3,
     4	    core as cdk
     5	)
     6
     7	class HelloCdkStack(core.Stack):
     8
     9	    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
    10	        super().__init__(scope, construct_id, **kwargs)
    11
    12	        # The code that defines your stack goes here
    13	bucket = s3.Bucket(self,
    14	    "MyFirstBucket",
    15	    versioned=True,)
```
こんな理解でしょうか。

|パラメーター|内容|
|:--:|:--:|
|scope|```self```|
|Id|```"MyFirstBucket"```|
|props|```versioned=True```|

検索するとCDKのクラスが出てきました。
[class Bucket (construct)(docs.aws.amazon.com)](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.Bucket.html)

シンセサイズしてみます。

```
(.venv)% cdk synth
Traceback (most recent call last):
  File "app.py", line 5, in <module>
    from hello_cdk.hello_cdk_stack import HelloCdkStack
  File "/Users/myname/hello-cdk/hello_cdk/hello_cdk_stack.py", line 7, in <module>
    class HelloCdkStack(core.Stack):
NameError: name 'core' is not defined
Subprocess exited with error 1
```
coreがないと怒られます。
1行目はコメントアウトしてはいけなかったんでしょうか。
1行目のコメントアウトを外してみます。

```
(.venv)% cat -n hello_cdk/hello_cdk_stack.py | head -n 2
     1	from aws_cdk import core
     2	from aws_cdk import (
```
```
(.venv)% cdk synth
Traceback (most recent call last):
  File "app.py", line 5, in <module>
    from hello_cdk.hello_cdk_stack import HelloCdkStack
  File "/Users/myname/hello-cdk/hello_cdk/hello_cdk_stack.py", line 13, in <module>
    bucket = s3.Bucket(self,
NameError: name 'self' is not defined
Subprocess exited with error 1
```
今度はselfが無いと…

詰んだ感じので、README.mdを見ます。
見ると、いくつかコマンドがあるようです。

```
 * `cdk ls`          list all stacks in the app
 * `cdk synth`       emits the synthesized CloudFormation template
 * `cdk deploy`      deploy this stack to your default AWS account/region
 * `cdk diff`        compare deployed stack with current state
 * `cdk docs`        open CDK documentation
```
Diffができるようです。

```
(.venv)% cdk diff
Traceback (most recent call last):
  File "app.py", line 5, in <module>
    from hello_cdk.hello_cdk_stack import HelloCdkStack
  File "/Users/myname/hello-cdk/hello_cdk/hello_cdk_stack.py", line 13, in <module>
    bucket = s3.Bucket(self,
NameError: name 'self' is not defined
Subprocess exited with error 1
```
同じように出てしまいます。
ぐぐると、インデントの可能性が高そうです。
def __init__ と同じところにbucketがくるようにします。

```
(.venv)% cat -n  hello_cdk/hello_cdk_stack.py
     1	from aws_cdk import core
     2	from aws_cdk import (
     3	    aws_s3 as s3,
     4	    core as cdk
     5	)
     6
     7	class HelloCdkStack(core.Stack):
     8
     9	    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
    10	        super().__init__(scope, construct_id, **kwargs)
    11
    12	        # The code that defines your stack goes here
    13	    bucket = s3.Bucket(self,
    14	        "MyFirstBucket",
    15	        versioned=True,)
```
なしてdiffを…

```
(.venv)% cdk diff
Traceback (most recent call last):
  File "app.py", line 5, in <module>
    from hello_cdk.hello_cdk_stack import HelloCdkStack
  File "/Users/myname/hello-cdk/hello_cdk/hello_cdk_stack.py", line 7, in <module>
    class HelloCdkStack(core.Stack):
  File "/Users/myname/hello-cdk/hello_cdk/hello_cdk_stack.py", line 13, in HelloCdkStack
    bucket = s3.Bucket(self,
NameError: name 'self' is not defined
Subprocess exited with error 1
```
またエラーが出ました。ううむ…

コメントと同じインデントにしてみます。

```
(.venv)% cat -n  hello_cdk/hello_cdk_stack.py
     1	from aws_cdk import core
     2	from aws_cdk import (
     3	    aws_s3 as s3,
     4	    core as cdk
     5	)
     6
     7	class HelloCdkStack(core.Stack):
     8
     9	    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
    10	        super().__init__(scope, construct_id, **kwargs)
    11
    12	        # The code that defines your stack goes here
    13	        bucket = s3.Bucket(self,
    14	            "MyFirstBucket",
    15	            versioned=True,)
```

```
(.venv)% cdk diff
Stack hello-cdk
Conditions
[+] Condition CDKMetadata/Condition CDKMetadataAvailable: {"Fn::Or":[{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ca-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-northwest-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-central-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-3"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"sa-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-2"]}]}]}

Resources
[+] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501
```
おお、通りました。

```def __init__ ```のところでselfが定義されていて、そのインデントよりも下（深い？）にないと、selfが使えなかったのかもしれません。

synthしてみます。

```
(.venv)% cdk synth
Resources:
  MyFirstBucketB8884501:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Metadata:
      aws:cdk:path: hello-cdk/MyFirstBucket/Resource
  CDKMetadata:
    Type: AWS::CDK::Metadata
    Properties:
      Modules: aws-cdk=1.77.0,@aws-cdk/aws-events=1.77.0,@aws-cdk/aws-iam=1.77.0,@aws-cdk/aws-kms=1.77.0,@aws-cdk/aws-s3=1.77.0,@aws-cdk/cloud-assembly-schema=1.77.0,@aws-cdk/core=1.77.0,@aws-cdk/cx-api=1.77.0,@aws-cdk/region-info=1.77.0,jsii-runtime=Python/3.8.6
    Metadata:
      aws:cdk:path: hello-cdk/CDKMetadata/Default
    Condition: CDKMetadataAvailable
Conditions:
  CDKMetadataAvailable:
    Fn::Or:
      - Fn::Or:
          - Fn::Equals:
              - Ref: AWS::Region
              - ap-east-1
          - Fn::Equals:
              - Ref: AWS::Region
              - ap-northeast-1
          - Fn::Equals:
              - Ref: AWS::Region
              - ap-northeast-2
          - Fn::Equals:
              - Ref: AWS::Region
              - ap-south-1
          - Fn::Equals:
              - Ref: AWS::Region
              - ap-southeast-1
          - Fn::Equals:
              - Ref: AWS::Region
              - ap-southeast-2
          - Fn::Equals:
              - Ref: AWS::Region
              - ca-central-1
          - Fn::Equals:
              - Ref: AWS::Region
              - cn-north-1
          - Fn::Equals:
              - Ref: AWS::Region
              - cn-northwest-1
          - Fn::Equals:
              - Ref: AWS::Region
              - eu-central-1
      - Fn::Or:
          - Fn::Equals:
              - Ref: AWS::Region
              - eu-north-1
          - Fn::Equals:
              - Ref: AWS::Region
              - eu-west-1
          - Fn::Equals:
              - Ref: AWS::Region
              - eu-west-2
          - Fn::Equals:
              - Ref: AWS::Region
              - eu-west-3
          - Fn::Equals:
              - Ref: AWS::Region
              - me-south-1
          - Fn::Equals:
              - Ref: AWS::Region
              - sa-east-1
          - Fn::Equals:
              - Ref: AWS::Region
              - us-east-1
          - Fn::Equals:
              - Ref: AWS::Region
              - us-east-2
          - Fn::Equals:
              - Ref: AWS::Region
              - us-west-1
          - Fn::Equals:
              - Ref: AWS::Region
              - us-west-2
```
めちゃくちゃ長いファイルができました。多少見慣れたファイルで安心します。
S3のMyFirstBucketB8884501の数字はどこから出てきたんでしょう。

```cdk synth```というコマンドが、アプリ実行のようです。
先程指定したリソースが、テンプレートとして出力されるようです。
スタックを.pyファイルで作成すれば良いのでしょうか。

デプロイしてみます。

```
(.venv)% cdk deploy
hello-cdk: deploying...
hello-cdk: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (3/3)





 ✅  hello-cdk

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/hello-cdk/f75ee690-3ba0-11eb-b1cf-0611461e9ae4
```
デプロイされました。

今度はバケットに変更を加えるようです。
パブリック読み取り→有効
スタック削除でバケットの自動削除→有効

```:変更後
(.venv)% cat -n  hello_cdk/hello_cdk_stack.py
     1	from aws_cdk import core
     2	from aws_cdk import (
     3	    aws_s3 as s3,
     4	    core as cdk
     5	)
     6
     7	class HelloCdkStack(core.Stack):
     8
     9	    def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None:
    10	        super().__init__(scope, construct_id, **kwargs)
    11
    12	        # The code that defines your stack goes here
    13	        bucket = s3.Bucket(self,
    14	            "MyFirstBucket",
    15	            versioned=True,
    16	            public_read_access=True,
    17	            removal_policy=cdk.RemovalPolicy.DESTROY)
```
せっかくなのでdiffしてみます。

```
(.venv)% cdk diff
Stack hello-cdk
IAM Statement Changes
┌───┬────────────────────────┬────────┬──────────────┬───────────┬───────────┐
│   │ Resource               │ Effect │ Action       │ Principal │ Condition │
├───┼────────────────────────┼────────┼──────────────┼───────────┼───────────┤
│ + │ ${MyFirstBucket.Arn}/* │ Allow  │ s3:GetObject │ *         │           │
└───┴────────────────────────┴────────┴──────────────┴───────────┴───────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Resources
[+] AWS::S3::BucketPolicy MyFirstBucket/Policy MyFirstBucketPolicy3243DEFD
[~] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501
 ├─ [~] DeletionPolicy
 │   ├─ [-] Retain
 │   └─ [+] Delete
 └─ [~] UpdateReplacePolicy
     ├─ [-] Retain
     └─ [+] Delete

```
めっちゃ見やすい…
deployしてみます。
diffではリソースの変化も出ましたが、deployではリソースの変化は表示されず、IAMポリシーの表示だけでした。

```
(.venv)% cdk deploy
This deployment will make potentially sensitive changes according to your current security approval level (--require-approval broadening).
Please confirm you intend to make the following modifications:

IAM Statement Changes
┌───┬────────────────────────┬────────┬──────────────┬───────────┬───────────┐
│   │ Resource               │ Effect │ Action       │ Principal │ Condition │
├───┼────────────────────────┼────────┼──────────────┼───────────┼───────────┤
│ + │ ${MyFirstBucket.Arn}/* │ Allow  │ s3:GetObject │ *         │           │
└───┴────────────────────────┴────────┴──────────────┴───────────┴───────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Do you wish to deploy these changes (y/n)? y
hello-cdk: deploying...
hello-cdk: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (3/2)




 ✅  hello-cdk

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/hello-cdk/f75ee690-3ba0-11eb-b1cf-0611461e9ae4
```
大きなスタックの差分としては2つ

1つ目は「UpdateReplacePolicy」と「DeletionPolicy」がRetain（残す）から、Deleteに変わっていました。

```
    UpdateReplacePolicy: Delete
    DeletionPolicy: Delete
```
```removal_policy=cdk.RemovalPolicy.DESTROY``` という行に当たるようです。
cdk.RemovalPolicy.DESTROYはどこで定義されているんでしょうか…

宣言のところで```core as cdk```とあり、cdkをcoreと読み替えるようなので、
coreというクラスがありそうです。

[enum RemovalPolicy(docs.aws.amazon.com)](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.RemovalPolicy.html)にありました。

2つ目はポリシーの追加。

```
  MyFirstBucketPolicy3243DEFD:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket:
        Ref: MyFirstBucketB8884501
      PolicyDocument:
        Statement:
          - Action: s3:GetObject
            Effect: Allow
            Principal: "*"
            Resource:
              Fn::Join:
                - ""
                - - Fn::GetAtt:
                      - MyFirstBucketB8884501
                      - Arn
                  - /*
        Version: "2012-10-17"
    Metadata:
      aws:cdk:path: hello-cdk/MyFirstBucket/Policy/Resource
```

最後にクイックツアーを終了するのにスタックリソースを削除します。
何が消えるか・・・はわかりません。



```
(.venv)% cdk destroy
Are you sure you want to delete: hello-cdk (y/n)? y
hello-cdk: destroying...
9:32:47 PM | DELETE_IN_PROGRESS   | AWS::CloudFormation::Stack | hello-cdk
9:32:50 PM | DELETE_IN_PROGRESS   | AWS::CDK::Metadata    | CDKMetadata/Default

 ✅  hello-cdk: destroyed
```

スタックが削除されました。

terminalを開き直して、cdk diffを実施しても環境変数がない状態だとエラーが出ます。

```
% cdk diff
Traceback (most recent call last):
  File "app.py", line 3, in <module>
    from aws_cdk import core
ModuleNotFoundError: No module named 'aws_cdk'
Subprocess exited with error 1
```

README.mdのとおりに環境変数を設定するときちんと差分が見えます。

```
% source .venv/bin/activate
(.venv)% cdk diff
Stack hello-cdk
IAM Statement Changes
┌───┬────────────────────────┬────────┬──────────────┬───────────┬───────────┐
│   │ Resource               │ Effect │ Action       │ Principal │ Condition │
├───┼────────────────────────┼────────┼──────────────┼───────────┼───────────┤
│ + │ ${MyFirstBucket.Arn}/* │ Allow  │ s3:GetObject │ *         │           │
└───┴────────────────────────┴────────┴──────────────┴───────────┴───────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Conditions
[+] Condition CDKMetadata/Condition CDKMetadataAvailable: {"Fn::Or":[{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ca-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-northwest-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-central-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-3"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"sa-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-2"]}]}]}

Resources
[+] AWS::S3::Bucket MyFirstBucket MyFirstBucketB8884501
[+] AWS::S3::BucketPolicy MyFirstBucket/Policy MyFirstBucketPolicy3243DEFD
```

環境変数をみてみます。

```
(.venv)% cat .venv/bin/activate
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly

deactivate () {
    # reset old environment variables
    if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
        PATH="${_OLD_VIRTUAL_PATH:-}"
        export PATH
        unset _OLD_VIRTUAL_PATH
    fi
    if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
        PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
        export PYTHONHOME
        unset _OLD_VIRTUAL_PYTHONHOME
    fi

    # This should detect bash and zsh, which have a hash command that must
    # be called to get it to forget past commands.  Without forgetting
    # past commands the $PATH changes we made may not be respected
    if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
        hash -r
    fi

    if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
        PS1="${_OLD_VIRTUAL_PS1:-}"
        export PS1
        unset _OLD_VIRTUAL_PS1
    fi

    unset VIRTUAL_ENV
    if [ ! "${1:-}" = "nondestructive" ] ; then
    # Self destruct!
        unset -f deactivate
    fi
}

# unset irrelevant variables
deactivate nondestructive

VIRTUAL_ENV="/Users/myname/hello-cdk/.venv"
export VIRTUAL_ENV

_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH

# unset PYTHONHOME if set
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
# could use `if (set -u; : $PYTHONHOME) ;` in bash
if [ -n "${PYTHONHOME:-}" ] ; then
    _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
    unset PYTHONHOME
fi

if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
    _OLD_VIRTUAL_PS1="${PS1:-}"
    if [ "x(.venv) " != x ] ; then
	PS1="(.venv) ${PS1:-}"
    else
    if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
        # special case for Aspen magic directories
        # see https://aspen.io/
        PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
    else
        PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
    fi
    fi
    export PS1
fi

# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands.  Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
    hash -r
fi
```
意外と長い。

VIRTUAL_ENV、PYTHONHOME、PS1、というあたりをセットしているようです。

スタックの作成、削除ができたのでチュートリアルは終了します。

## リファレンス
https://docs.aws.amazon.com/cdk/api/latest/python/