Cloudformationのインポート機能

次の通りNLBをCloudformationで作成し、Codepipelineで実行していたとします。

```cloudformation.yml
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  ElasticLoadBalancingV2LoadBalancer:
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties:
      Name: "import-nlb"
      Scheme: "internal"
      Type: "network"
      Subnets: 
      - "subnet-XXX"
      - "subnet-XXX"
      IpAddressType: "ipv4"
      LoadBalancerAttributes: 
      - 
        Key: "access_logs.s3.enabled"
        Value: "false"
      - 
        Key: "deletion_protection.enabled"
        Value: "false"
      - 
        Key: "load_balancing.cross_zone.enabled"
        Value: "false"

  ElasticLoadBalancingV2Listener:
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties:
      LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
      Port: 80
      Protocol: "TCP"
      DefaultActions: 
      - 
        Order: 1
        TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup
        Type: "forward"

  ElasticLoadBalancingV2TargetGroup:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      HealthCheckIntervalSeconds: 30
      Port: 80
      Protocol: "TCP"
      HealthCheckPort: "traffic-port"
      HealthCheckProtocol: "TCP"
      HealthCheckTimeoutSeconds: 10
      UnhealthyThresholdCount: 3
      TargetType: "ip"
      HealthyThresholdCount: 3
      VpcId: "vpc-XXX"
      Name: "import-tg"
      HealthCheckEnabled: true
      TargetGroupAttributes: 
      - 
        Key: "proxy_protocol_v2.enabled"
        Value: "false"
      - 
        Key: "preserve_client_ip.enabled"
        Value: "false"
      - 
        Key: "stickiness.enabled"
        Value: "false"
      - 
        Key: "deregistration_delay.timeout_seconds"
        Value: "300"
      - 
        Key: "stickiness.type"
        Value: "source_ip"
      - 
        Key: "deregistration_delay.connection_termination.enabled"
        Value: "false"
```

次に、コンソールからNLBリスナーをわざと削除してから、コンソールで再作成します。
![スクリーンショット 2022-03-12 15.50.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/2212f7df-204a-2803-7780-02c71091b64a.png)

この場合、Cloudformationテンプレートとコンソールから再作成したものに差が出ることとなります。

次にCloudformationテンプレートのNLBリスナーのリソースをコメントアウトし、Codepipelineを実行してみます。

```cloudformation.yml
#   ElasticLoadBalancingV2Listener:
#     Type: "AWS::ElasticLoadBalancingV2::Listener"
#     Properties:
#       LoadBalancerArn: !Ref ElasticLoadBalancingV2LoadBalancer
#       Port: 80
#       Protocol: "TCP"
#       DefaultActions: 
#       - 
#         Order: 1
#         TargetGroupArn: !Ref ElasticLoadBalancingV2TargetGroup
#         Type: "forward"
```

NLBリスナーはコンソールから再作成しているため、当然消えません。

![スクリーンショット 2022-03-12 16.00.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/0d60db65-8093-f9ba-f63c-0cc772a2b810.png)

では、ここからが本題です。

コンソールから再作成したNLBリスナーをCloudformationのインポート機能を利用して、テンプレート化します。

なお、Cloudformationのインポートにリソースがサポートしている必要があるので注意しましょう。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resource-import-supported-resources.html

Cloudformationのコンソールから作業します。
先程コメントアウトした箇所を解除したものと、`DeletionPolicy: Retain` を追加したCloudformationテンプレートを準備しておきます。

「スタックアクション」から、「スタックへのリソースのインポート」をクリック。
![スクリーンショット 2022-03-12 16.11.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/dbb78e48-091b-e780-1324-b7290a164424.png)

「次へ」をクリック。
![スクリーンショット 2022-03-12 16.11.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/7da6e7fe-8f9b-68d6-851b-b754e2286cb7.png)

「cloudformation.yml」をアップロードし、「次へ」をクリック。
![スクリーンショット 2022-03-12 16.11.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/e9060766-8967-683c-762b-ff61db839a3d.png)

コンソールから再作成したNLBリスナーのarnを入力し、「次へ」。
![スクリーンショット 2022-03-12 16.13.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/4cfe7044-cb2c-cb67-4172-c24291a1e711.png)

「次へ」。
![スクリーンショット 2022-03-12 16.13.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/cb1b72ca-afbe-3966-21a1-9f671bc1f58a.png)

　コンソールから再作成したNLBリスナーのarnが指定されていることを確認し、「リソースをインポート」。
![スクリーンショット 2022-03-12 16.13.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/5a70a5de-8bca-13b7-27ef-f538f76112d1.png)

「ドリフトの検出」後「ドリフト結果を表示」からCloudformationテンプレートに差がないか確認してみましょう。
![スクリーンショット 2022-03-12 16.14.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/e8189300-8399-8779-928a-e453ac3f69e5.png)
![スクリーンショット 2022-03-12 16.14.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/fe0ddfbb-f288-b7a9-8f52-d7c02faeb496.png)

NLBリスナーのリソースを確認し、「IN_SYNC」と差がないことが確認できました。
![スクリーンショット 2022-03-12 16.14.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/d538fb4b-c1d6-3994-03d9-9a29e42cc091.png)

次に、コメントアウトした箇所を解除したCloudformationテンプレートをCodepipelineから実行してみます。

ハマりどころ。。。

Cloudformationのイベントを確認すると、「IMPORT_COMPLETE」から変化しません。
![スクリーンショット 2022-03-13 16.03.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/4e937cdd-fb17-7a4d-732b-0b3fe217cee0.png)

Codepipelineを停止して中止後、Cloudformationから直接スタックを更新してみます。
この時同じCloudformationテンプレートでは、次のようなエラーが表示されてしまうため、`DeletionPolicy: Retain`を外した状態でスタックを更新してみます。

`この変更セットの作成中にエラーが発生しました
The submitted information didn't contain changes. Submit different information to create a change set.`

Cloudformationスタックのステータスが、「UPDATE_COMPLETE」となったことを確認します。

![スクリーンショット 2022-03-13 16.14.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/42b689a7-ea6c-7f44-de51-8561d6f5254c.png)

この状態で、Codepipelineを再度実行してみます。今度はCodepipelineが最後まで完了したみたいです。

![スクリーンショット 2022-03-13 16.28.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/2d7e9f6e-61af-35b2-4a65-3e1b49572bad.png)

Cloudformationスタックのステータスが「IMPORT_COMPLETE」では、Codepipelineから実行すると、変化しないということでしょうか？