From e031c97c3e18c32ba87b31c82d6c75ee17dd4860 Mon Sep 17 00:00:00 2001 From: charles shin Date: Mon, 9 Oct 2023 07:58:11 -0700 Subject: [PATCH] fix: populate custom resources CDK stacks with region and account (#12575) --- .../utils/generate-cfn-from-cdk.test.ts | 26 ++++++++++++++ .../src/utils/generate-cfn-from-cdk.ts | 15 +++++++- .../custom-resources/barebone-cdk-stack.ts | 35 +++++++++++++++++++ .../src/__tests__/custom_resources.test.ts | 20 +++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 packages/amplify-category-custom/src/__tests__/utils/generate-cfn-from-cdk.test.ts create mode 100644 packages/amplify-e2e-tests/custom-resources/barebone-cdk-stack.ts diff --git a/packages/amplify-category-custom/src/__tests__/utils/generate-cfn-from-cdk.test.ts b/packages/amplify-category-custom/src/__tests__/utils/generate-cfn-from-cdk.test.ts new file mode 100644 index 00000000000..d4777fe90a0 --- /dev/null +++ b/packages/amplify-category-custom/src/__tests__/utils/generate-cfn-from-cdk.test.ts @@ -0,0 +1,26 @@ +import { getCDKProps } from '../../utils/generate-cfn-from-cdk'; + +describe('generate-cfn-from-cdk', () => { + describe('getCDKProps', () => { + beforeEach(() => { + process.env = {}; + }); + + test('should return undefined if CDK env vars are not set', () => { + const actual = getCDKProps(); + expect(actual).toBeUndefined(); + }); + + test('should return cdk props with env set', () => { + process.env = { + CDK_DEFAULT_ACCOUNT: 'some_account_id', + CDK_DEFAULT_REGION: 'us-east-1', + }; + + const actual = getCDKProps(); + + expect(actual.env?.account).toEqual('some_account_id'); + expect(actual.env?.region).toEqual('us-east-1'); + }); + }); +}); diff --git a/packages/amplify-category-custom/src/utils/generate-cfn-from-cdk.ts b/packages/amplify-category-custom/src/utils/generate-cfn-from-cdk.ts index c68bedce15c..8dfa2b04504 100644 --- a/packages/amplify-category-custom/src/utils/generate-cfn-from-cdk.ts +++ b/packages/amplify-category-custom/src/utils/generate-cfn-from-cdk.ts @@ -2,19 +2,32 @@ import * as cdk from 'aws-cdk-lib'; import { JSONUtilities, pathManager } from '@aws-amplify/amplify-cli-core'; import * as path from 'path'; import { categoryName } from './constants'; +import { StackProps } from '@aws-cdk/core'; export type AmplifyResourceProps = { category: string; resourceName: string; }; +export function getCDKProps(): StackProps { + if (process.env.CDK_DEFAULT_ACCOUNT || process.env.CDK_DEFAULT_REGION) { + return { + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, + }, + }; + } + return {}; +} + export async function generateCloudFormationFromCDK(resourceName: string) { const targetDir = pathManager.getResourceDirectoryPath(undefined, categoryName, resourceName); const { cdkStack } = await import(path.resolve(path.join(targetDir, 'build', 'cdk-stack.js'))); const amplifyResourceProps: AmplifyResourceProps = { category: categoryName, resourceName }; - const customStack: cdk.Stack = new cdkStack(undefined, undefined, undefined, amplifyResourceProps); + const customStack: cdk.Stack = new cdkStack(undefined, undefined, getCDKProps(), amplifyResourceProps); // @ts-ignore JSONUtilities.writeJson(path.join(targetDir, 'build', `${resourceName}-cloudformation-template.json`), customStack._toCloudFormation()); diff --git a/packages/amplify-e2e-tests/custom-resources/barebone-cdk-stack.ts b/packages/amplify-e2e-tests/custom-resources/barebone-cdk-stack.ts new file mode 100644 index 00000000000..d524e4af6d3 --- /dev/null +++ b/packages/amplify-e2e-tests/custom-resources/barebone-cdk-stack.ts @@ -0,0 +1,35 @@ +import * as cdk from 'aws-cdk-lib'; +import * as sqs from 'aws-cdk-lib/aws-sqs'; +import * as sns from 'aws-cdk-lib/aws-sns'; +import * as subs from 'aws-cdk-lib/aws-sns-subscriptions'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import { Construct } from 'constructs'; + +// eslint-disable-next-line import/no-extraneous-dependencies +import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper'; + +export class cdkStack extends cdk.Stack { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + constructor(scope: Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) { + super(scope, id, props); + /* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */ + new cdk.CfnParameter(this, 'env', { + type: 'String', + description: 'Current Amplify CLI env name', + }); + /* AWS CDK code goes here - learn more: https://docs.aws.amazon.com/cdk/latest/guide/home.html */ + + ec2.Vpc.fromLookup(this, 'VPC', { + isDefault: true, + }); + + const queue = new sqs.Queue(this, 'sqs-queue'); + // 👇 create sns topic + const topic = new sns.Topic(this, 'sns-topic'); + + // 👇 subscribe queue to topic + topic.addSubscription(new subs.SqsSubscription(queue)); + + // creation of resources inside the VPC + } +} diff --git a/packages/amplify-e2e-tests/src/__tests__/custom_resources.test.ts b/packages/amplify-e2e-tests/src/__tests__/custom_resources.test.ts index e669fa0c459..c1f52300fcc 100644 --- a/packages/amplify-e2e-tests/src/__tests__/custom_resources.test.ts +++ b/packages/amplify-e2e-tests/src/__tests__/custom_resources.test.ts @@ -18,6 +18,7 @@ import { v4 as uuid } from 'uuid'; describe('adding custom resources test', () => { let projRoot: string; + beforeEach(async () => { projRoot = await createNewProjectDir('custom-resources'); }); @@ -130,4 +131,23 @@ describe('adding custom resources test', () => { }, }); }); + + it('should use default cdk env var if set', async () => { + const cdkResourceName = `custom${uuid().split('-')[0]}`; + const destCustomResourceFilePath = path.join(projRoot, 'amplify', 'backend', 'custom', cdkResourceName, 'cdk-stack.ts'); + const srcCustomResourceFilePath = path.join(__dirname, '..', '..', 'custom-resources', 'barebone-cdk-stack.ts'); + + await initJSProjectWithProfile(projRoot, {}); + await addCDKCustomResource(projRoot, { name: cdkResourceName }); + + fs.copyFileSync(srcCustomResourceFilePath, destCustomResourceFilePath); + + // no aws account & region set, should throw error, + await expect(amplifyPushAuth(projRoot)).rejects.toThrowError(); + + // should pickup to default cdk env vars and build cfn stack. + process.env.CDK_DEFAULT_ACCOUNT = 'some_id'; + process.env.CDK_DEFAULT_REGION = process.env.CLI_REGION; + await amplifyPushAuth(projRoot); + }); });