0
2

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.

別スタックで作成したAWSリソースの情報を取得する

Last updated at Posted at 2022-11-24

概要

CloudFormationまたはCDKでのAWS環境構築は、スタックと呼ばれるAWSリソースの集合を作成することによって行われます。

スタック作成の粒度は開発者によって様々ですが、別スタックで作成したリソースの情報を利用したい場合があります。

例:
・スタックAでS3バケットを作成
・スタックBで作成するLambdaの環境変数に、スタックAで作成したバケット名を設定

この場合、スタックAで作成したバケット名をスタックBで使用するためには以下のような方法が考えられます。

  1. エクスポート値を使用しない-1
    CloudFormationのAWSコンソールで、スタックAのリソース名を確認。取得したバケット名をスタックB作成のテンプレートにべた書きしてデプロイ

  2. エクスポート値を使用しない-2
    CloudFormationのAWSコンソールで、スタックAのリソース名を確認。取得したバケット名をスタックB作成時に外から注入してデプロイ

  3. エクスポート値を使用する
    スタックA作成時にエクスポート値としてS3バケット名を出力。スタックB作成時にエクスポート値をインポート(クロススタック参照)してデプロイ

  4. パラメータストアを利用する
    スタックA作成時パラメータストアにS3バケット名を登録。スタックB作成時にパラメータストアからバケット名を取得してデプロイ

今回はこれらを実際に試していきます。

試してみた

では、それぞれCDKで試してみます。

エクスポート値を使用しない-1

Stack APPのCDKは以下になります。

bin/cdk.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { StackA } from '../lib/stack_a';
import { StackB } from '../lib/stack_b';

const app = new cdk.App();

new StackA(app, 'StackA', {
});
new StackB(app, 'StackB', {
});

まず、スタックAでS3バケットを作成します。
CDKは以下になります。

lib/stack_a.ts
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';

export class StackA extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bucket = new s3.CfnBucket(this, 'CreateBucketA', {
      bucketName: 'bucket-export-test'
    });
  }
}

スタックAをデプロイします。

cdk deploy StackA

スタックが作成されたので、リソース名をAWSコンソールで確認します。
1-1.PNG

次に、確認したS3バケット名をスタックBに入力してLambdaを作成します。
CDKは以下になります。

lib/stack_b.ts
import * as cdk from '@aws-cdk/core';
import { Role, ServicePrincipal, ManagedPolicy } from '@aws-cdk/aws-iam';
import { Function, AssetCode, Runtime } from '@aws-cdk/aws-lambda';

export class StackB extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const executionLambdaRole = new Role(this, 'LambdaRole', {
      roleName: 'lambdaRole',
      assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
      managedPolicies: [
      ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
      ]
    });
    new Function(this, 'ExportTestFunction', {
      functionName: 'export-test-function',
      runtime: Runtime.NODEJS_14_X,
      code: AssetCode.fromAsset('src'),
      handler: 'index.handler',
      role: executionLambdaRole,
      environment: {
        BUCKET_NAME: "bucket-export-test"
      }
    });
  }
}

スタックBをデプロイします。

cdk deploy StackB

AWSコンソールでLambdaを確認すると、環境変数が設定されていることが確認できます。
1-2.PNG

エクスポート値を使用しない-2

次に、バケット名をデプロイ時に外から注入する方法を紹介します。
※スタックAのCDKは先ほどと同様なため省略します。

Stack APPのCDKの変更点は以下になります。

bin/cdk.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { StackA } from '../lib/stack_a';
import { StackB } from '../lib/stack_b';

const app = new cdk.App();

new StackA(app, 'StackA', {
});
new StackB(app, 'StackB', {
+  bucket: app.node.tryGetContext(`bucket`)
});

Lambdaを作成するCDKの変更点は以下になります。

lib/stack_b.ts
import * as cdk from '@aws-cdk/core';
import { Role, ServicePrincipal, ManagedPolicy } from '@aws-cdk/aws-iam';
import { Function, AssetCode, Runtime } from '@aws-cdk/aws-lambda';

export class StackB extends cdk.Stack {
-  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
+  constructor(scope: cdk.Construct, id: string, props: StackBProps) {
    super(scope, id, props);

    const executionLambdaRole = new Role(this, 'LambdaRole', {
      roleName: 'lambdaRole',
      assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
      managedPolicies: [
      ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
      ]
    });
    new Function(this, 'ExportTestFunction', {
      functionName: 'export-test-function',
      runtime: Runtime.NODEJS_14_X,
      code: AssetCode.fromAsset('src'),
      handler: 'index.handler',
      role: executionLambdaRole,
      environment: {
-        BUCKET_NAME: "bucket-export-test"
+        BUCKET_NAME: props.bucket
      }
    });
  }
}

+export interface StackBProps extends cdk.StackProps {
+  readonly bucket: string;
+}

スタックAをデプロイします。

cdk deploy StackA

スタックBをデプロイします。
引数で渡したバケット名が環境変数に設定されます。

cdk deploy StackB --context bucket=bucket-export-test

エクスポート値を使用する

次に、スタックAの作成時にバケット名をエクスポートし、スタックB作成時にインポートする方法を紹介します。
※スタックBのCDKは先ほどと同様なため省略します。

Stack APPのCDKの変更点は以下になります。

bin/cdk.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { StackA } from '../lib/stack_a';
import { StackB } from '../lib/stack_b';

const app = new cdk.App();

new StackA(app, 'StackA', {
});
new StackB(app, 'StackB', {
-  bucket: app.node.tryGetContext(`bucket`)
+  bucket: cdk.Fn.importValue(`bucketName`)
});

S3バケットを作成するCDKの変更点は以下になります。

lib/stack_a.ts
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';

export class StackA extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bucket = new s3.CfnBucket(this, 'CreateBucketA', {
      bucketName: 'bucket-export-test'
    });

+    new cdk.CfnOutput(this, 'BucketName', {
+      value: 'bucket-export-test',
+      exportName: 'bucketName'
+    });
  }
}

スタックAをデプロイします。

cdk deploy StackA

スタックBをデプロイします。

cdk deploy StackB

パラメータストアを利用する

最後に、スタックAの作成時にバケット名をパラメータストアに登録し、スタックB作成時にパラメータストアから取得する方法を紹介します。

Stack APPのCDKファイルは以下になります。

bin/cdk.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { StackA } from '../lib/stack_a';
import { StackB } from '../lib/stack_b';

const app = new cdk.App();

new StackA(app, 'StackA', {
});
new StackB(app, 'StackB', {
-  bucket: cdk.Fn.importValue(`bucketName`)
});

S3バケットを作成するCDKの変更点は以下になります。

lib/stack_a.ts
import * as cdk from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';
+import * as ssm from '@aws-cdk/aws-ssm';

export class StackA extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const bucket = new s3.CfnBucket(this, 'CreateBucketA', {
      bucketName: 'bucket-export-test'
    });

-    new cdk.CfnOutput(this, 'BucketName', {
-      value: 'bucket-export-test',
-      exportName: 'bucketName'
-    });
+    const param = new ssm.StringParameter(this, 'BucketName', {
+      stringValue: 'bucket-export-test',
+      parameterName: '/bucket/test',
+    });
  }
}

Lambdaを作成するCDKの変更点は以下になります。

lib/stack_b.ts
import * as cdk from '@aws-cdk/core';
import { Role, ServicePrincipal, ManagedPolicy } from '@aws-cdk/aws-iam';
import { Function, AssetCode, Runtime } from '@aws-cdk/aws-lambda';
+import * as ssm from '@aws-cdk/aws-ssm';

export class StackB extends cdk.Stack {
-  constructor(scope: cdk.Construct, id: string, props: StackBProps) {
+  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const executionLambdaRole = new Role(this, 'LambdaRole', {
      roleName: 'lambdaSecureExecutionRole',
      assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
      managedPolicies: [
      ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
      ]
    });
    new Function(this, 'ExportTestFunction', {
      functionName: 'export-test-function',
      runtime: Runtime.NODEJS_14_X,
      code: AssetCode.fromAsset('src'),
      handler: 'index.handler',
      role: executionLambdaRole,
      environment: {
-        BUCKET_NAME: props.bucket
+        BUCKET_NAME: ssm.StringParameter.valueForStringParameter(this, '/bucket/test')
      }
    });
  }
}

-export interface StackBProps extends cdk.StackProps {
-  readonly bucket: string;
-}

スタックAをデプロイします。

cdk deploy StackA

スタックBをデプロイします。

cdk deploy StackB

おまけ

AWS CLIコマンドでもエクスポート値を取得することが出来るので、以下に記載します。

  • 対象のスタック名の全てのエクスポート値を取得
# StackAのエクスポート値
aws cloudformation describe-stacks \
  --stack-name StackA \
  --query "Stacks[0].Outputs[]"

[
    {
        "OutputKey": "BucketA",
        "OutputValue": "bucketa",
        "ExportName": "bucketNameA"
    },
    {
        "OutputKey": "BucketB",
        "OutputValue": "bucketb",
        "ExportName": "bucketNameB"
    }
]
  • 対象のスタック名の指定したエクスポート値を取得
# StackAのエクスポート名:bucketNameAを取得
aws cloudformation describe-stacks \
  --stack-name StackA \
  --query "Stacks[0].Outputs[?ExportName=='bucketNameA'].OutputValue" \
  --output text

bucketa
  • 指定したエクスポート値を取得

エクスポート名:bucketNameの値を取得

aws cloudformation list-exports \
  --query "Exports[?Name=='bucketNameA'].Value[]" \
  --output text

bucketa

おわりに

今回はスタック間のAWSリソース情報の受け渡しについて説明させて頂きました。
CloudFormationやCDKを利用する際はよく使うので、ご参考になれば幸いです。

0
2
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?