19
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Japan AWS Jr. ChampionsAdvent Calendar 2023

Day 5

cdk importとcdk migrateについて

Last updated at Posted at 2023-12-04

はじめに

Japan AWS Jr. Champions Advent Calendar 5日目の投稿です。
今回は、AWS CDKのコマンドであるcdk importと 10 月に AWS CDK v2.100.0となりリリースされたcdk migrateコマンドについて紹介します。
v2.100.0 では、cdk importコマンドが stable となり、cdk migrateコマンドが新しく追加されました。

AWS Cloud Development Kit(AWS CDK)

AWS Cloud Development Kit(AWS CDK)とは、AWS リソースをプログラミング言語で定義できるツールです。
AWS CDK では、AWS リソース定義の抽象化レイヤーが提供されているため、簡潔にリソースを定義できることが特徴です。

AWS CDK の開始方法については公式ドキュメントを参照してください。

cdk import

cdk importは、v2.20.0以上で使用できる機能となっています。

cdk import は CDK 以外の手段で作成した AWS リソースをAWS CDKの管理下に置くことができる機能です。cdk importコマンドを実行することで、既存のAWSリソースをAWS CDKのスタックにインポートできます。

cdk importを使用して既存のAmazon S3バケットをCDKスタックにインポートする例を紹介します。

cdk importはS3バケット以外のリソースにも対応しています。
cdk importでサポートされているリソースについてはこちらを参照してください。

ここでは、AWS CDKプロジェクトがデプロイ済みで、既存のS3バケットをAWS CDKで管理したいケースを想定しています。

AWSマネージドコンソールからS3バケットを新規に作成し、S3バケットを追加したいスタックに以下のように記述します。


const bucket = new s3.Bucket(this,'SampleBucket')

以下のdiffコマンドで変更が発生することを確認します。

$ npx cdk diff
Resources
[+] AWS::S3::Bucket Sample-Bucket SampleBucket<ランダムな文字列>

次に、cdk importコマンドを実行し、作成したS3のバケット名を入力するとインポートが実行されます。

$ npx cdk import 
The 'cdk import' feature is currently in preview.
SampleEc2Stack
SampleEc2StackSample-Bucket/Resource (AWS::S3::Bucket): enter BucketName to import (empty to skip): [作成したバケット名を入力]
SampleEc2Stack: importing resources into stack...
SampleEc2Stack: creating CloudFormation changeset...

再度diffコマンドを入力し、no differencesとなっていれば取り込みが完了しています。
このようにAWS CDKの利便性を活用しながら、既存のリソースを再利用することができます。
また、AWS CDKで管理されているリソースと一緒に、既存のリソースも同じコードベースで管理することができるため、管理が簡単になります。

cdk migrate

cdk migrateは既存のCloudFormationテンプレートもしくは既存のスタックをAWS CDKプロジェクトに変換する機能です。

cdk migrate は現在実験的なものであり、将来的に変更される可能性があります。

CloudFormationテンプレートファイルでのcdk migrate

ローカルにCloudFormationテンプレートファイルを作成します。

今回はEC2インスタンスのテンプレートを作成しました。実際のコードは下記の通りです。

コードを見る
AWSTemplateFormatVersion: "2010-09-09"
Metadata:
  License: Apache-2.0
Description:
  "AWS CloudFormation Sample Template EC2InstanceWithSecurityGroupSample:
  Create an Amazon EC2 instance running the Amazon Linux AMI. The AMI is chosen based
  on the region in which the stack is run. This example creates an EC2 security group
  for the instance to give you SSH access. **WARNING** This template creates an Amazon
  EC2 instance. You will be billed for the AWS resources used if you create a stack
  from this template."
Parameters:
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: must be the name of an existing EC2 KeyPair.
  InstanceType:
    Description: WebServer EC2 instance type
    Type: String
    Default: t3.small
    AllowedValues:
      [
        t2.nano,
        t2.micro,
        t2.small,
        t2.medium,
        t2.large,
        t2.xlarge,
        t2.2xlarge,
        t3.nano,
        t3.micro,
        t3.small,
        t3.medium,
        t3.large,
        t3.xlarge,
        t3.2xlarge,
        m4.large,
        m4.xlarge,
        m4.2xlarge,
        m4.4xlarge,
        m4.10xlarge,
        m5.large,
        m5.xlarge,
        m5.2xlarge,
        m5.4xlarge,
        c5.large,
        c5.xlarge,
        c5.2xlarge,
        c5.4xlarge,
        c5.9xlarge,
        g3.8xlarge,
        r5.large,
        r5.xlarge,
        r5.2xlarge,
        r5.4xlarge,
        r3.12xlarge,
        i3.xlarge,
        i3.2xlarge,
        i3.4xlarge,
        i3.8xlarge,
        d2.xlarge,
        d2.2xlarge,
        d2.4xlarge,
        d2.8xlarge,
      ]
    ConstraintDescription: must be a valid EC2 instance type.
  SSHLocation:
    Description: The IP address range that can be used to SSH to the EC2 instances
    Type: String
    MinLength: 9
    MaxLength: 18
    Default: 0.0.0.0/0
    AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
    ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x.
  LatestAmiId:
    Type: "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>"
    Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: !Ref "InstanceType"
      SecurityGroups: [!Ref "InstanceSecurityGroup"]
      KeyName: !Ref "KeyName"
      ImageId: !Ref "LatestAmiId"
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable SSH access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref "SSHLocation"
Outputs:
  InstanceId:
    Description: InstanceId of the newly created EC2 instance
    Value: !Ref "EC2Instance"
  AZ:
    Description: Availability Zone of the newly created EC2 instance
    Value: !GetAtt [EC2Instance, AvailabilityZone]
  PublicDNS:
    Description: Public DNSName of the newly created EC2 instance
    Value: !GetAtt [EC2Instance, PublicDnsName]
  PublicIP:
    Description: Public IP address of the newly created EC2 instance
    Value: !GetAtt [EC2Instance, PublicIp]

cdk migrateコマンド実行

cdk migrateコマンドを実行します。
コマンドのオプションの説明は以下になります。

  • --stack-name
    • スタック名
  • --language
    • AWS CDKプロジェクトの言語
    • AWS CDKがサポートしている言語(TypeScript、JavaScript、Python、Java, C#、Go)はすべてサポートしています。
  • --from-path
    • CloudFormationテンプレートファイルのパス
% cdk migrate --stack-name SampleApplication --language typescript --from-path template/ec2.yaml
This is an experimental feature and development on it is still in progress. We make no guarantees about the outcome or stability of the functionality.
 ⏳  Generating CDK app for SampleApplication...
Applying project template app for typescript
Initializing a new git repository...
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:       git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:       git branch -m <name>
Executing npm install...
✅ All done!

コマンドが成功するとコマンドを実行したディレクトリ配下にAWS CDKプロジェクトが作成されます。

sample-application
├── README.md
├── bin
│   └── sample-application.ts
├── cdk.json
├── jest.config.js
├── lib
│   └── sample-application-stack.ts
├── node_modules
├── package-lock.json
├── package.json
├── test
│   └── sample-application.test.ts
└── tsconfig.json

lib/sample-application-stack.tsを見てみると、CloudFormationのParametersSampleApplicationStackPropsとして渡せるようになっています。

lib/sample-application-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

export interface SampleApplicationStackProps extends cdk.StackProps {
  /**
   * Name of an existing EC2 KeyPair to enable SSH access to the instance
   */
  readonly keyName: string;
  /**
   * WebServer EC2 instance type
   * @default 't3.small'
   */
  readonly instanceType?: string;
  /**
   * The IP address range that can be used to SSH to the EC2 instances
   * @default '0.0.0.0/0'
   */
  readonly sshLocation?: string;
  /**
   * @default '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
   */
  readonly latestAmiId?: string;
}

/**
 * AWS CloudFormation Sample Template EC2InstanceWithSecurityGroupSample: Create an Amazon EC2 instance running the Amazon Linux AMI. The AMI is chosen based on the region in which the stack is run. This example creates an EC2 security group for the instance to give you SSH access. **WARNING** This template creates an Amazon EC2 instance. You will be billed for the AWS resources used if you create a stack from this template.
 */
export class SampleApplicationStack extends cdk.Stack {
  /**
   * InstanceId of the newly created EC2 instance
   */
  public readonly instanceId;
  /**
   * Availability Zone of the newly created EC2 instance
   */
  public readonly az;
  /**
   * Public DNSName of the newly created EC2 instance
   */
  public readonly publicDns;
  /**
   * Public IP address of the newly created EC2 instance
   */
  public readonly publicIp;

  public constructor(scope: cdk.App, id: string, props:SampleApplicationStackProps) {
    super(scope, id, props);

    // Applying default props
    props = {
      ...props,
      keyName: new cdk.CfnParameter(this, 'KeyName', {
        type: 'AWS::EC2::KeyPair::KeyName',
        default: props.keyName.toString(),
        description: 'Name of an existing EC2 KeyPair to enable SSH access to the instance',
      }).valueAsString,
      instanceType: props.instanceType ?? 't3.small',
      sshLocation: props.sshLocation ?? '0.0.0.0/0',
      latestAmiId: new cdk.CfnParameter(this, 'LatestAmiId', {
        type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>',
        default: props.latestAmiId?.toString() ?? '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2',
      }).valueAsString,
    };

    // Resources
    const instanceSecurityGroup = new ec2.CfnSecurityGroup(this, 'InstanceSecurityGroup', {
      groupDescription: 'Enable SSH access via port 22',
      securityGroupIngress: [
        {
          ipProtocol: 'tcp',
          fromPort: 22,
          toPort: 22,
          cidrIp: props.sshLocation!,
        },
      ],
    });

    if (instanceSecurityGroup == null) { throw new Error(`A combination of conditions caused 'instanceSecurityGroup' to be undefined. Fixit.`); }
    const ec2Instance = new ec2.CfnInstance(this, 'EC2Instance', {
      instanceType: props.instanceType!,
      securityGroups: [
        instanceSecurityGroup.ref,
      ],
      keyName: props.keyName!,
      imageId: props.latestAmiId!,
    });

    // Outputs
    this.instanceId = ec2Instance.ref;
    new cdk.CfnOutput(this, 'InstanceId', {
      description: 'InstanceId of the newly created EC2 instance',
      value: this.instanceId!.toString(),
    });
    this.az = ec2Instance.attrAvailabilityZone;
    new cdk.CfnOutput(this, 'AZ', {
      description: 'Availability Zone of the newly created EC2 instance',
      value: this.az!.toString(),
    });
    this.publicDns = ec2Instance.attrPublicDnsName;
    new cdk.CfnOutput(this, 'PublicDNS', {
      description: 'Public DNSName of the newly created EC2 instance',
      value: this.publicDns!.toString(),
    });
    this.publicIp = ec2Instance.attrPublicIp;
    new cdk.CfnOutput(this, 'PublicIP', {
      description: 'Public IP address of the newly created EC2 instance',
      value: this.publicIp!.toString(),
    });
  }
}


既存のスタックでのcdk migrate

次は既存のデプロイ済みのCloudFormationのスタックに対し、cdk migrateコマンドを実行します。

CloudFormationのスタックをデプロイ

AWS公式のCloudFormationサンプルをあらかじめデプロイします。

cdk migrateコマンド実行

--stack-nameオプションでAWSのマネージドコンソールで表示されるCloudFormationのスタック名を指定し、コマンドを実行します。

$ cdk migrate --stack-name sample-stack --language typescript --from-stack

生成されたソースコードはコード量が多いので折りたたんでいます。

コードを見る
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

export interface SampleStackStackProps extends cdk.StackProps {
  /**
   * Name of an existing EC2 KeyPair to enable SSH access to the web server
   */
  readonly keyName: string;
  /**
   * WebServer EC2 instance type
   * @default 't2.small'
   */
  readonly instanceType?: string;
  /**
   * Lockdown SSH access to the bastion host (default can be accessed from anywhere)
   * @default '0.0.0.0/0'
   */
  readonly sshLocation?: string;
}

/**
 * AWS CloudFormation Sample Template EC2_Instance_With_Ephemeral_Drives: Example to show how to attach ephemeral drives using EC2 block device mappings. **WARNING** This template creates an Amazon EC2 instance. You will be billed for the AWS resources used if you create a stack from this template.
 */
export class SampleStackStack extends cdk.Stack {
  /**
   * DNS Name of the newly created EC2 instance
   */
  public readonly instance;

  public constructor(scope: cdk.App, id: string, props: SampleStackStackProps) {
    super(scope, id, props);

    // Applying default props
    props = {
      ...props,
      keyName: new cdk.CfnParameter(this, 'KeyName', {
        type: 'AWS::EC2::KeyPair::KeyName',
        default: props.keyName.toString(),
        description: 'Name of an existing EC2 KeyPair to enable SSH access to the web server',
      }).valueAsString,
      instanceType: props.instanceType ?? 't2.small',
      sshLocation: props.sshLocation ?? '0.0.0.0/0',
    };

    // Mappings
    const awsInstanceType2Arch: Record<string, Record<string, string>> = {
      't1.micro': {
        'Arch': 'HVM64',
      },
      't2.nano': {
        'Arch': 'HVM64',
      },
      't2.micro': {
        'Arch': 'HVM64',
      },
      't2.small': {
        'Arch': 'HVM64',
      },
      't2.medium': {
        'Arch': 'HVM64',
      },
      't2.large': {
        'Arch': 'HVM64',
      },
      'm1.small': {
        'Arch': 'HVM64',
      },
      'm1.medium': {
        'Arch': 'HVM64',
      },
      'm1.large': {
        'Arch': 'HVM64',
      },
      'm1.xlarge': {
        'Arch': 'HVM64',
      },
      'm2.xlarge': {
        'Arch': 'HVM64',
      },
      'm2.2xlarge': {
        'Arch': 'HVM64',
      },
      'm2.4xlarge': {
        'Arch': 'HVM64',
      },
      'm3.medium': {
        'Arch': 'HVM64',
      },
      'm3.large': {
        'Arch': 'HVM64',
      },
      'm3.xlarge': {
        'Arch': 'HVM64',
      },
      'm3.2xlarge': {
        'Arch': 'HVM64',
      },
      'm4.large': {
        'Arch': 'HVM64',
      },
      'm4.xlarge': {
        'Arch': 'HVM64',
      },
      'm4.2xlarge': {
        'Arch': 'HVM64',
      },
      'm4.4xlarge': {
        'Arch': 'HVM64',
      },
      'm4.10xlarge': {
        'Arch': 'HVM64',
      },
      'c1.medium': {
        'Arch': 'HVM64',
      },
      'c1.xlarge': {
        'Arch': 'HVM64',
      },
      'c3.large': {
        'Arch': 'HVM64',
      },
      'c3.xlarge': {
        'Arch': 'HVM64',
      },
      'c3.2xlarge': {
        'Arch': 'HVM64',
      },
      'c3.4xlarge': {
        'Arch': 'HVM64',
      },
      'c3.8xlarge': {
        'Arch': 'HVM64',
      },
      'c4.large': {
        'Arch': 'HVM64',
      },
      'c4.xlarge': {
        'Arch': 'HVM64',
      },
      'c4.2xlarge': {
        'Arch': 'HVM64',
      },
      'c4.4xlarge': {
        'Arch': 'HVM64',
      },
      'c4.8xlarge': {
        'Arch': 'HVM64',
      },
      'g2.2xlarge': {
        'Arch': 'HVMG2',
      },
      'g2.8xlarge': {
        'Arch': 'HVMG2',
      },
      'r3.large': {
        'Arch': 'HVM64',
      },
      'r3.xlarge': {
        'Arch': 'HVM64',
      },
      'r3.2xlarge': {
        'Arch': 'HVM64',
      },
      'r3.4xlarge': {
        'Arch': 'HVM64',
      },
      'r3.8xlarge': {
        'Arch': 'HVM64',
      },
      'i2.xlarge': {
        'Arch': 'HVM64',
      },
      'i2.2xlarge': {
        'Arch': 'HVM64',
      },
      'i2.4xlarge': {
        'Arch': 'HVM64',
      },
      'i2.8xlarge': {
        'Arch': 'HVM64',
      },
      'd2.xlarge': {
        'Arch': 'HVM64',
      },
      'd2.2xlarge': {
        'Arch': 'HVM64',
      },
      'd2.4xlarge': {
        'Arch': 'HVM64',
      },
      'd2.8xlarge': {
        'Arch': 'HVM64',
      },
      'hi1.4xlarge': {
        'Arch': 'HVM64',
      },
      'hs1.8xlarge': {
        'Arch': 'HVM64',
      },
      'cr1.8xlarge': {
        'Arch': 'HVM64',
      },
      'cc2.8xlarge': {
        'Arch': 'HVM64',
      },
    };
    const awsInstanceType2NatArch: Record<string, Record<string, string>> = {
      't1.micro': {
        'Arch': 'NATHVM64',
      },
      't2.nano': {
        'Arch': 'NATHVM64',
      },
      't2.micro': {
        'Arch': 'NATHVM64',
      },
      't2.small': {
        'Arch': 'NATHVM64',
      },
      't2.medium': {
        'Arch': 'NATHVM64',
      },
      't2.large': {
        'Arch': 'NATHVM64',
      },
      'm1.small': {
        'Arch': 'NATHVM64',
      },
      'm1.medium': {
        'Arch': 'NATHVM64',
      },
      'm1.large': {
        'Arch': 'NATHVM64',
      },
      'm1.xlarge': {
        'Arch': 'NATHVM64',
      },
      'm2.xlarge': {
        'Arch': 'NATHVM64',
      },
      'm2.2xlarge': {
        'Arch': 'NATHVM64',
      },
      'm2.4xlarge': {
        'Arch': 'NATHVM64',
      },
      'm3.medium': {
        'Arch': 'NATHVM64',
      },
      'm3.large': {
        'Arch': 'NATHVM64',
      },
      'm3.xlarge': {
        'Arch': 'NATHVM64',
      },
      'm3.2xlarge': {
        'Arch': 'NATHVM64',
      },
      'm4.large': {
        'Arch': 'NATHVM64',
      },
      'm4.xlarge': {
        'Arch': 'NATHVM64',
      },
      'm4.2xlarge': {
        'Arch': 'NATHVM64',
      },
      'm4.4xlarge': {
        'Arch': 'NATHVM64',
      },
      'm4.10xlarge': {
        'Arch': 'NATHVM64',
      },
      'c1.medium': {
        'Arch': 'NATHVM64',
      },
      'c1.xlarge': {
        'Arch': 'NATHVM64',
      },
      'c3.large': {
        'Arch': 'NATHVM64',
      },
      'c3.xlarge': {
        'Arch': 'NATHVM64',
      },
      'c3.2xlarge': {
        'Arch': 'NATHVM64',
      },
      'c3.4xlarge': {
        'Arch': 'NATHVM64',
      },
      'c3.8xlarge': {
        'Arch': 'NATHVM64',
      },
      'c4.large': {
        'Arch': 'NATHVM64',
      },
      'c4.xlarge': {
        'Arch': 'NATHVM64',
      },
      'c4.2xlarge': {
        'Arch': 'NATHVM64',
      },
      'c4.4xlarge': {
        'Arch': 'NATHVM64',
      },
      'c4.8xlarge': {
        'Arch': 'NATHVM64',
      },
      'g2.2xlarge': {
        'Arch': 'NATHVMG2',
      },
      'g2.8xlarge': {
        'Arch': 'NATHVMG2',
      },
      'r3.large': {
        'Arch': 'NATHVM64',
      },
      'r3.xlarge': {
        'Arch': 'NATHVM64',
      },
      'r3.2xlarge': {
        'Arch': 'NATHVM64',
      },
      'r3.4xlarge': {
        'Arch': 'NATHVM64',
      },
      'r3.8xlarge': {
        'Arch': 'NATHVM64',
      },
      'i2.xlarge': {
        'Arch': 'NATHVM64',
      },
      'i2.2xlarge': {
        'Arch': 'NATHVM64',
      },
      'i2.4xlarge': {
        'Arch': 'NATHVM64',
      },
      'i2.8xlarge': {
        'Arch': 'NATHVM64',
      },
      'd2.xlarge': {
        'Arch': 'NATHVM64',
      },
      'd2.2xlarge': {
        'Arch': 'NATHVM64',
      },
      'd2.4xlarge': {
        'Arch': 'NATHVM64',
      },
      'd2.8xlarge': {
        'Arch': 'NATHVM64',
      },
      'hi1.4xlarge': {
        'Arch': 'NATHVM64',
      },
      'hs1.8xlarge': {
        'Arch': 'NATHVM64',
      },
      'cr1.8xlarge': {
        'Arch': 'NATHVM64',
      },
      'cc2.8xlarge': {
        'Arch': 'NATHVM64',
      },
    };
    const awsRegionArch2Ami: Record<string, Record<string, string>> = {
      'af-south-1': {
        'HVM64': 'ami-064cc455f8a1ef504',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'ap-east-1': {
        'HVM64': 'ami-f85b1989',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'ap-northeast-1': {
        'HVM64': 'ami-0b2c2a754d5b4da22',
        'HVMG2': 'ami-09d0e0e099ecabba2',
      },
      'ap-northeast-2': {
        'HVM64': 'ami-0493ab99920f410fc',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'ap-northeast-3': {
        'HVM64': 'ami-01344f6f63a4decc1',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'ap-south-1': {
        'HVM64': 'ami-03cfb5e1fb4fac428',
        'HVMG2': 'ami-0244c1d42815af84a',
      },
      'ap-southeast-1': {
        'HVM64': 'ami-0ba35dc9caf73d1c7',
        'HVMG2': 'ami-0e46ce0d6a87dc979',
      },
      'ap-southeast-2': {
        'HVM64': 'ami-0ae99b503e8694028',
        'HVMG2': 'ami-0c0ab057a101d8ff2',
      },
      'ca-central-1': {
        'HVM64': 'ami-0803e21a2ec22f953',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'cn-north-1': {
        'HVM64': 'ami-07a3f215cc90c889c',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'cn-northwest-1': {
        'HVM64': 'ami-0a3b3b10f714a0ff4',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'eu-central-1': {
        'HVM64': 'ami-0474863011a7d1541',
        'HVMG2': 'ami-0aa1822e3eb913a11',
      },
      'eu-north-1': {
        'HVM64': 'ami-0de4b8910494dba0f',
        'HVMG2': 'ami-32d55b4c',
      },
      'eu-south-1': {
        'HVM64': 'ami-08427144fe9ebdef6',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'eu-west-1': {
        'HVM64': 'ami-015232c01a82b847b',
        'HVMG2': 'ami-0d5299b1c6112c3c7',
      },
      'eu-west-2': {
        'HVM64': 'ami-0765d48d7e15beb93',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'eu-west-3': {
        'HVM64': 'ami-0caf07637eda19d9c',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'me-south-1': {
        'HVM64': 'ami-0744743d80915b497',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'sa-east-1': {
        'HVM64': 'ami-0a52e8a6018e92bb0',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'us-east-1': {
        'HVM64': 'ami-032930428bf1abbff',
        'HVMG2': 'ami-0aeb704d503081ea6',
      },
      'us-east-2': {
        'HVM64': 'ami-027cab9a7bf0155df',
        'HVMG2': 'NOT_SUPPORTED',
      },
      'us-west-1': {
        'HVM64': 'ami-088c153f74339f34c',
        'HVMG2': 'ami-0a7fc72dc0e51aa77',
      },
      'us-west-2': {
        'HVM64': 'ami-01fee56b22f308154',
        'HVMG2': 'ami-0fe84a5b4563d8f27',
      },
    };

    // Resources
    const ec2SecurityGroup = new ec2.CfnSecurityGroup(this, 'EC2SecurityGroup', {
      groupDescription: 'SSH access',
      securityGroupIngress: [
        {
          ipProtocol: 'tcp',
          fromPort: 22,
          toPort: 22,
          cidrIp: props.sshLocation!,
        },
      ],
    });

    if (ec2SecurityGroup == null) { throw new Error(`A combination of conditions caused 'ec2SecurityGroup' to be undefined. Fixit.`); }
    const ec2Instance = new ec2.CfnInstance(this, 'EC2Instance', {
      keyName: props.keyName!,
      instanceType: props.instanceType!,
      imageId: awsRegionArch2Ami[this.region][awsInstanceType2Arch[props.instanceType!]['Arch']],
      securityGroups: [
        ec2SecurityGroup.ref,
      ],
      blockDeviceMappings: [
        {
          deviceName: '/dev/sdc',
          virtualName: 'ephemeral0',
        },
      ],
    });

    // Outputs
    this.instance = ec2Instance.attrPublicDnsName;
    new cdk.CfnOutput(this, 'Instance', {
      description: 'DNS Name of the newly created EC2 instance',
      value: this.instance!.toString(),
    });
  }
}

生成されたコードを見るに、各リージョンやインスタンスタイプのマッピングにRecord<string, Record<string, string>> などTypeScriptの型定義されていることがわかります。

cdk migrateの制約と注意点

cdk migrateはまだ実験的なコマンドのため、執筆時点(2023/12/5)では以下の制約があります。

  • cdk migrate はネストされたスタック、カスタムリソース、Fn::ForEach 組み込み関数をサポートしていません。
  • cdk migrateはL1コンストラクトのみを対応し、L2,L3コンストラクトには対応していません。
  • cdk migrateがアプリケーションの生成に成功しても、そのアプリケーションがすぐにデプロイ可能であることを保証するものではありません。

最後に

今回は、cdk importcdk migrateコマンドを紹介しました。cdk importはあるリソースをAWS CDKの管理下にしたい時に使い、cdk migrateはCloudFormationのスタックをAWS CDKのプロジェクトにしたい時に使えます。
cdk migrateは実験的な機能ということやまだL1コンストラクトにしか対応していませんが、今後、L2コンストラクトなどに対応すると便利だなと思いました。

19
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?