From b593a185179e6ca529e9d81b6017bb5af29dffd4 Mon Sep 17 00:00:00 2001 From: JoeNonExotic Date: Sun, 19 Feb 2023 01:51:09 -0800 Subject: [PATCH] feat: Initial Release Added a SimpleAppConfig Setup SimpleAppConfig construct/unit test/example --- .gitattributes | 2 +- .github/workflows/release.yml | 2 +- .../{upgrade-main.yml => upgrade-master.yml} | 12 +- .gitignore | 2 +- .projen/deps.json | 4 + .projen/files.json | 2 +- .projen/tasks.json | 2 +- .projenrc.js | 17 +- API.md | 255 ++++++++++++++++++ README.md | 13 +- package.json | 13 +- src/index.ts | 6 +- src/simple-appconfig.ts | 126 +++++++++ .../simple-appconfig.test.ts.snap | 111 ++++++++ test/example-usage/.gitignore | 1 + test/example-usage/index.ts | 42 +++ test/hello.test.ts | 5 - test/simple-appconfig.test.ts | 110 ++++++++ yarn.lock | 90 ++++++- 19 files changed, 776 insertions(+), 39 deletions(-) rename .github/workflows/{upgrade-main.yml => upgrade-master.yml} (94%) create mode 100644 API.md create mode 100644 src/simple-appconfig.ts create mode 100644 test/__snapshots__/simple-appconfig.test.ts.snap create mode 100644 test/example-usage/.gitignore create mode 100644 test/example-usage/index.ts delete mode 100644 test/hello.test.ts create mode 100644 test/simple-appconfig.test.ts diff --git a/.gitattributes b/.gitattributes index 1299013..31cfd93 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,7 +7,7 @@ /.github/workflows/build.yml linguist-generated /.github/workflows/pull-request-lint.yml linguist-generated /.github/workflows/release.yml linguist-generated -/.github/workflows/upgrade-main.yml linguist-generated +/.github/workflows/upgrade-master.yml linguist-generated /.gitignore linguist-generated /.mergify.yml linguist-generated /.npmignore linguist-generated diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0475824..8741dcb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ name: release on: push: branches: - - main + - master workflow_dispatch: {} jobs: release: diff --git a/.github/workflows/upgrade-main.yml b/.github/workflows/upgrade-master.yml similarity index 94% rename from .github/workflows/upgrade-main.yml rename to .github/workflows/upgrade-master.yml index 09e420c..3b91ea0 100644 --- a/.github/workflows/upgrade-main.yml +++ b/.github/workflows/upgrade-master.yml @@ -1,6 +1,6 @@ # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". -name: upgrade-main +name: upgrade-master on: workflow_dispatch: {} schedule: @@ -17,7 +17,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 with: - ref: main + ref: master - name: Install dependencies run: yarn install --check-files --frozen-lockfile - name: Upgrade dependencies @@ -46,7 +46,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 with: - ref: main + ref: master - name: Download patch uses: actions/download-artifact@v3 with: @@ -72,8 +72,8 @@ jobs: ------ - *Automatically created by projen via the "upgrade-main" workflow* - branch: github-actions/upgrade-main + *Automatically created by projen via the "upgrade-master" workflow* + branch: github-actions/upgrade-master title: "chore(deps): upgrade dependencies" body: |- Upgrades project dependencies. See details in [workflow run]. @@ -82,7 +82,7 @@ jobs: ------ - *Automatically created by projen via the "upgrade-main" workflow* + *Automatically created by projen via the "upgrade-master" workflow* author: github-actions committer: github-actions signoff: true diff --git a/.gitignore b/.gitignore index e31dd32..1020acc 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,7 @@ junit.xml /dist/version.txt !/.github/workflows/release.yml !/.mergify.yml -!/.github/workflows/upgrade-main.yml +!/.github/workflows/upgrade-master.yml !/.github/pull_request_template.md !/test/ !/tsconfig.dev.json diff --git a/.projen/deps.json b/.projen/deps.json index 711a77c..e5a8ce0 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -92,6 +92,10 @@ "version": "^27", "type": "build" }, + { + "name": "ts-node", + "type": "build" + }, { "name": "typescript", "type": "build" diff --git a/.projen/files.json b/.projen/files.json index ffcd5fd..feba423 100644 --- a/.projen/files.json +++ b/.projen/files.json @@ -6,7 +6,7 @@ ".github/workflows/build.yml", ".github/workflows/pull-request-lint.yml", ".github/workflows/release.yml", - ".github/workflows/upgrade-main.yml", + ".github/workflows/upgrade-master.yml", ".gitignore", ".mergify.yml", ".projen/deps.json", diff --git a/.projen/tasks.json b/.projen/tasks.json index 57e5a46..4f88db0 100644 --- a/.projen/tasks.json +++ b/.projen/tasks.json @@ -176,7 +176,7 @@ }, "release": { "name": "release", - "description": "Prepare a release from \"main\" branch", + "description": "Prepare a release from \"master\" branch", "env": { "RELEASE": "true" }, diff --git a/.projenrc.js b/.projenrc.js index d5e7483..bf7bbe6 100644 --- a/.projenrc.js +++ b/.projenrc.js @@ -1,15 +1,14 @@ const { awscdk } = require('projen'); const project = new awscdk.AwsCdkConstructLibrary({ - author: 'JoeNonExotic', - authorAddress: 'vijayvikramreddy@gmail.com', + defaultReleaseBranch: 'master', + author: 'JNE', cdkVersion: '2.1.0', - defaultReleaseBranch: 'main', - name: 'appconfig', - repositoryUrl: 'https://github.com/vijayvikramreddy/appconfig.git', + name: 'cdk-appconfig', + description: 'A custom construct for setting up AppConfig using aws-cdk', + repositoryUrl: 'https://github.com/JoeNonExotic/cdk-appconfig.git', - // deps: [], /* Runtime dependencies of this module. */ - // description: undefined, /* The description is just a string that helps people understand the purpose of the package. */ - // devDeps: [], /* Build dependencies for this module. */ - // packageName: undefined, /* The "name" in package.json. */ + devDeps: ['ts-node', 'aws-cdk-lib', 'constructs'], + peerDeps: ['aws-cdk-lib', 'constructs'], }); +project.addKeywords('appconfig', 'constructs'); project.synth(); \ No newline at end of file diff --git a/API.md b/API.md new file mode 100644 index 0000000..62be14e --- /dev/null +++ b/API.md @@ -0,0 +1,255 @@ +# API Reference + +## Constructs + +### SimpleAppConfig + +Custom construct to quickly setup app config resouce based on the passed in {@link SimpleAppConfigProps}. + +This construct does the following: +1. Setup `applicationName/applicationEnvironment/configurationProfileName`. +2. Add/update configurationContent. +3. Apply the add/update immediately. + +#### Initializers + +```typescript +import { SimpleAppConfig } from 'cdk-appconfig' + +new SimpleAppConfig(scope: Construct, id: string, props: SimpleAppConfigProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| scope | constructs.Construct | *No description.* | +| id | string | *No description.* | +| props | SimpleAppConfigProps | *No description.* | + +--- + +##### `scope`Required + +- *Type:* constructs.Construct + +--- + +##### `id`Required + +- *Type:* string + +--- + +##### `props`Required + +- *Type:* SimpleAppConfigProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| toString | Returns a string representation of this construct. | + +--- + +##### `toString` + +```typescript +public toString(): string +``` + +Returns a string representation of this construct. + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| isConstruct | Checks if `x` is a construct. | + +--- + +##### ~~`isConstruct`~~ + +```typescript +import { SimpleAppConfig } from 'cdk-appconfig' + +SimpleAppConfig.isConstruct(x: any) +``` + +Checks if `x` is a construct. + +###### `x`Required + +- *Type:* any + +Any object. + +--- + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| application | aws-cdk-lib.aws_appconfig.CfnApplication | *No description.* | +| configurationProfile | aws-cdk-lib.aws_appconfig.CfnConfigurationProfile | *No description.* | +| deployment | aws-cdk-lib.aws_appconfig.CfnDeployment | *No description.* | +| environment | aws-cdk-lib.aws_appconfig.CfnEnvironment | *No description.* | +| hostedConfigurationVersion | aws-cdk-lib.aws_appconfig.CfnHostedConfigurationVersion | *No description.* | +| immediateDeploymentStrategy | aws-cdk-lib.aws_appconfig.CfnDeploymentStrategy | *No description.* | + +--- + +##### `node`Required + +```typescript +public readonly node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `application`Required + +```typescript +public readonly application: CfnApplication; +``` + +- *Type:* aws-cdk-lib.aws_appconfig.CfnApplication + +--- + +##### `configurationProfile`Required + +```typescript +public readonly configurationProfile: CfnConfigurationProfile; +``` + +- *Type:* aws-cdk-lib.aws_appconfig.CfnConfigurationProfile + +--- + +##### `deployment`Required + +```typescript +public readonly deployment: CfnDeployment; +``` + +- *Type:* aws-cdk-lib.aws_appconfig.CfnDeployment + +--- + +##### `environment`Required + +```typescript +public readonly environment: CfnEnvironment; +``` + +- *Type:* aws-cdk-lib.aws_appconfig.CfnEnvironment + +--- + +##### `hostedConfigurationVersion`Required + +```typescript +public readonly hostedConfigurationVersion: CfnHostedConfigurationVersion; +``` + +- *Type:* aws-cdk-lib.aws_appconfig.CfnHostedConfigurationVersion + +--- + +##### `immediateDeploymentStrategy`Required + +```typescript +public readonly immediateDeploymentStrategy: CfnDeploymentStrategy; +``` + +- *Type:* aws-cdk-lib.aws_appconfig.CfnDeploymentStrategy + +--- + + +## Structs + +### SimpleAppConfigProps + +Props for {@link SimpleAppConfig} construct. + +#### Initializer + +```typescript +import { SimpleAppConfigProps } from 'cdk-appconfig' + +const simpleAppConfigProps: SimpleAppConfigProps = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| applicationEnvironment | string | The name of the environment for deployment. | +| applicationName | string | The name of the app config application. | +| configurationContent | {[ key: string ]: any} | The content within the configuration profile. | +| configurationProfileName | string | The name for the configuration profile within the application. | + +--- + +##### `applicationEnvironment`Required + +```typescript +public readonly applicationEnvironment: string; +``` + +- *Type:* string + +The name of the environment for deployment. + +(Ex: Production) + +--- + +##### `applicationName`Required + +```typescript +public readonly applicationName: string; +``` + +- *Type:* string + +The name of the app config application. + +(Ex: MyApplication) + +--- + +##### `configurationContent`Required + +```typescript +public readonly configurationContent: {[ key: string ]: any}; +``` + +- *Type:* {[ key: string ]: any} + +The content within the configuration profile. + +--- + +##### `configurationProfileName`Required + +```typescript +public readonly configurationProfileName: string; +``` + +- *Type:* string + +The name for the configuration profile within the application. + +--- + + + diff --git a/README.md b/README.md index b3fa7dd..d8cd6a1 100644 --- a/README.md +++ b/README.md @@ -1 +1,12 @@ -# replace this \ No newline at end of file +# cdk-appconfig + +## Hello ! +This simple project was inspired from [this stackoverflow question](https://stackoverflow.com/questions/67579029/aws-cdk-lambda-appconfig-typescript-example-please/74724158#74724158), where I shared [this answer](https://stackoverflow.com/a/74724158). + +When I [read docs on the AppConfig construct library](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appconfig-readme.html), I soon realized that it was ripe for L2 and L3 constructs. Hence this library. + +The library is published under the following names: + +|Language|Repository +|--------|----------- +|JavaScript/TypeScript|[cdk-appconfig](https://www.npmjs.com/package/cdk-appconfig) \ No newline at end of file diff --git a/package.json b/package.json index b60afce..98de5ad 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,9 @@ { - "name": "appconfig", + "name": "cdk-appconfig", + "description": "A custom construct for setting up AppConfig using aws-cdk", "repository": { "type": "git", - "url": "https://github.com/vijayvikramreddy/appconfig.git" + "url": "https://github.com/JoeNonExotic/cdk-appconfig.git" }, "scripts": { "build": "npx projen build", @@ -29,8 +30,7 @@ "projen": "npx projen" }, "author": { - "name": "JoeNonExotic", - "email": "vijayvikramreddy@gmail.com", + "name": "JNE", "organization": false }, "devDependencies": { @@ -54,6 +54,7 @@ "projen": "^0.67.59", "standard-version": "^9", "ts-jest": "^27", + "ts-node": "^10.9.1", "typescript": "^4.9.5" }, "peerDependencies": { @@ -61,7 +62,9 @@ "constructs": "^10.0.5" }, "keywords": [ - "cdk" + "appconfig", + "cdk", + "constructs" ], "main": "lib/index.js", "license": "Apache-2.0", diff --git a/src/index.ts b/src/index.ts index 92c94b8..d465e02 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1 @@ -export class Hello { - public sayHello() { - return 'hello, world!'; - } -} \ No newline at end of file +export * from './simple-appconfig'; \ No newline at end of file diff --git a/src/simple-appconfig.ts b/src/simple-appconfig.ts new file mode 100644 index 0000000..1bd9ae5 --- /dev/null +++ b/src/simple-appconfig.ts @@ -0,0 +1,126 @@ +import { CfnApplication, CfnConfigurationProfile, CfnDeployment, CfnDeploymentStrategy, CfnEnvironment, CfnHostedConfigurationVersion } from 'aws-cdk-lib/aws-appconfig'; +import { Construct } from 'constructs'; + +/** + * A simple type represenation for https://www.rfc-editor.org/rfc/rfc9110.html#name-content-type "application-json" + */ +export type ConfigurationContent = { [x: string]: any }; + +/** + * Props for {@link SimpleAppConfig} construct. + */ +export interface SimpleAppConfigProps { + /** + * The name of the app config application. (Ex: MyApplication) + */ + readonly applicationName: string; + + /** + * The name of the environment for deployment. (Ex: Production) + */ + readonly applicationEnvironment: string; + + /** + * The name for the configuration profile within the application. + */ + readonly configurationProfileName: string; + + /** + * The content within the configuration profile. + */ + readonly configurationContent: ConfigurationContent; +} + +/** + * Custom construct to quickly setup app config resouce based on the passed in {@link SimpleAppConfigProps}. + * This construct does the following: + * 1. Setup `applicationName/applicationEnvironment/configurationProfileName`. + * 2. Add/update configurationContent. + * 3. Apply the add/update immediately. + */ +export class SimpleAppConfig extends Construct { + + public readonly application: CfnApplication; + public readonly immediateDeploymentStrategy: CfnDeploymentStrategy; + public readonly environment: CfnEnvironment; + public readonly configurationProfile: CfnConfigurationProfile; + public readonly hostedConfigurationVersion: CfnHostedConfigurationVersion; + public readonly deployment: CfnDeployment; + + constructor( + scope: Construct, + id: string, + private readonly props: SimpleAppConfigProps, + ) { + super(scope, id); + + // Create a new application + this.application = new CfnApplication( + this, + 'Application', + { + name: this.props.applicationName, + }, + ); + + // setup a deploy strategy to immediately apply config. + this.immediateDeploymentStrategy = new CfnDeploymentStrategy( + this, + 'DeployStrategy', + { + name: 'ImmediateDeployment', + deploymentDurationInMinutes: 0, + growthFactor: 100, + replicateTo: 'NONE', + finalBakeTimeInMinutes: 0, + }, + ); + + // setup an app config env + this.environment = new CfnEnvironment( + this, + 'Environment', + { + applicationId: this.application.ref, + // can be anything that makes sense for your use case. + name: this.props.applicationEnvironment, + }, + ); + + // setup config profile + this.configurationProfile = new CfnConfigurationProfile( + this, + 'ConfigurationProfile', + { + name: this.props.configurationProfileName, + applicationId: this.application.ref, + // we want AppConfig to manage the configuration profile, unless we need from SSM or S3. + locationUri: 'hosted', + // This can also be "AWS.AppConfig.FeatureFlags" + type: 'AWS.Freeform', + }, + ); + + // Update AppConfig + this.hostedConfigurationVersion = new CfnHostedConfigurationVersion( + this, + 'HostedConfigurationVersion', + { + applicationId: this.application.ref, + configurationProfileId: this.configurationProfile.ref, + content: JSON.stringify(this.props.configurationContent), + // https://www.rfc-editor.org/rfc/rfc9110.html#name-content-type + contentType: 'application/json', + }, + ); + + // Perform deployment. + this.deployment = new CfnDeployment(this, 'Deployment', { + applicationId: this.application.ref, + configurationProfileId: this.configurationProfile.ref, + configurationVersion: this.hostedConfigurationVersion.ref, + deploymentStrategyId: this.immediateDeploymentStrategy.ref, + environmentId: this.environment.ref, + }); + } +} \ No newline at end of file diff --git a/test/__snapshots__/simple-appconfig.test.ts.snap b/test/__snapshots__/simple-appconfig.test.ts.snap new file mode 100644 index 0000000..68f8176 --- /dev/null +++ b/test/__snapshots__/simple-appconfig.test.ts.snap @@ -0,0 +1,111 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`simple-appconfig creates expected resources 1`] = ` +Object { + "Parameters": Object { + "BootstrapVersion": Object { + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]", + "Type": "AWS::SSM::Parameter::Value", + }, + }, + "Resources": Object { + "SimpleAppConfigApplication04939DED": Object { + "Properties": Object { + "Name": "MyTestApp", + }, + "Type": "AWS::AppConfig::Application", + }, + "SimpleAppConfigConfigurationProfile78536DC3": Object { + "Properties": Object { + "ApplicationId": Object { + "Ref": "SimpleAppConfigApplication04939DED", + }, + "LocationUri": "hosted", + "Name": "MyConfigurationProfile", + "Type": "AWS.Freeform", + }, + "Type": "AWS::AppConfig::ConfigurationProfile", + }, + "SimpleAppConfigDeployStrategy14D4E4A1": Object { + "Properties": Object { + "DeploymentDurationInMinutes": 0, + "FinalBakeTimeInMinutes": 0, + "GrowthFactor": 100, + "Name": "ImmediateDeployment", + "ReplicateTo": "NONE", + }, + "Type": "AWS::AppConfig::DeploymentStrategy", + }, + "SimpleAppConfigDeploymentB0181BC9": Object { + "Properties": Object { + "ApplicationId": Object { + "Ref": "SimpleAppConfigApplication04939DED", + }, + "ConfigurationProfileId": Object { + "Ref": "SimpleAppConfigConfigurationProfile78536DC3", + }, + "ConfigurationVersion": Object { + "Ref": "SimpleAppConfigHostedConfigurationVersion67E8BB89", + }, + "DeploymentStrategyId": Object { + "Ref": "SimpleAppConfigDeployStrategy14D4E4A1", + }, + "EnvironmentId": Object { + "Ref": "SimpleAppConfigEnvironmentCD8BFB59", + }, + }, + "Type": "AWS::AppConfig::Deployment", + }, + "SimpleAppConfigEnvironmentCD8BFB59": Object { + "Properties": Object { + "ApplicationId": Object { + "Ref": "SimpleAppConfigApplication04939DED", + }, + "Name": "MyTestEnvironment", + }, + "Type": "AWS::AppConfig::Environment", + }, + "SimpleAppConfigHostedConfigurationVersion67E8BB89": Object { + "Properties": Object { + "ApplicationId": Object { + "Ref": "SimpleAppConfigApplication04939DED", + }, + "ConfigurationProfileId": Object { + "Ref": "SimpleAppConfigConfigurationProfile78536DC3", + }, + "Content": "{\\"StringKey\\":\\"StringValue\\",\\"BooleanKey\\":true,\\"NumberKey\\":123,\\"CompositeKey\\":{\\"StringKey\\":\\"StringValue\\",\\"BooleanKey\\":false,\\"NumberKey\\":456},\\"ArrayKey\\":[{\\"StringKey\\":\\"StringValue1\\",\\"BooleanKey\\":true,\\"NumberKey\\":123},{\\"StringKey\\":\\"StringValue2\\",\\"BooleanKey\\":false,\\"NumberKey\\":456}]}", + "ContentType": "application/json", + }, + "Type": "AWS::AppConfig::HostedConfigurationVersion", + }, + }, + "Rules": Object { + "CheckBootstrapVersion": Object { + "Assertions": Array [ + Object { + "Assert": Object { + "Fn::Not": Array [ + Object { + "Fn::Contains": Array [ + Array [ + "1", + "2", + "3", + "4", + "5", + ], + Object { + "Ref": "BootstrapVersion", + }, + ], + }, + ], + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.", + }, + ], + }, + }, +} +`; diff --git a/test/example-usage/.gitignore b/test/example-usage/.gitignore new file mode 100644 index 0000000..b2ef806 --- /dev/null +++ b/test/example-usage/.gitignore @@ -0,0 +1 @@ +cdk.out \ No newline at end of file diff --git a/test/example-usage/index.ts b/test/example-usage/index.ts new file mode 100644 index 0000000..4add5e1 --- /dev/null +++ b/test/example-usage/index.ts @@ -0,0 +1,42 @@ +import { StackProps, Stack, App } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import { SimpleAppConfig } from '../../src'; + + +class MyStack extends Stack { + constructor(scope: Construct, id: string, props: StackProps = {}) { + super(scope, id, props); + new SimpleAppConfig(this, 'SimpleAppConfig', { + applicationName: 'MyAppConfigAppName', + applicationEnvironment: 'MyEnvironment', + configurationProfileName: 'MyConfigProfileName', + // see {@link SimpleAppConfig#ConfigurationContent}, this is pretty generic. + configurationContent: { + MyStringKey: 'MyValue', + MyBooleanKey: true, + MyNumberKey: 123, + MyCompositeKey: { + MyStringKey: 'MyValue', + MyBooleanKey: true, + MyNumberKey: 123, + }, + MyArrayKey: [ + { + MyStringKey: 'MyValue1', + MyBooleanKey: true, + MyNumberKey: 123, + }, + { + MyStringKey: 'MyValue2', + MyBooleanKey: false, + MyNumberKey: 456, + }, + ], + }, + }); + } +} + +const app = new App(); +new MyStack(app, 'my-stack'); +app.synth(); diff --git a/test/hello.test.ts b/test/hello.test.ts deleted file mode 100644 index acbacd4..0000000 --- a/test/hello.test.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Hello } from '../src'; - -test('hello', () => { - expect(new Hello().sayHello()).toBe('hello, world!'); -}); \ No newline at end of file diff --git a/test/simple-appconfig.test.ts b/test/simple-appconfig.test.ts new file mode 100644 index 0000000..28cbb71 --- /dev/null +++ b/test/simple-appconfig.test.ts @@ -0,0 +1,110 @@ +import { App, assertions, Stack } from 'aws-cdk-lib'; +import { SimpleAppConfig } from '../src'; + +/** + * Test configuration content. + */ +const TEST_CONFIGURATION = { + StringKey: 'StringValue', + BooleanKey: true, + NumberKey: 123, + CompositeKey: { + StringKey: 'StringValue', + BooleanKey: false, + NumberKey: 456, + }, + ArrayKey: [ + { + StringKey: 'StringValue1', + BooleanKey: true, + NumberKey: 123, + }, + { + StringKey: 'StringValue2', + BooleanKey: false, + NumberKey: 456, + }, + ], +}; + +const TEST_APP_NAME = 'MyTestApp'; +const TEST_ENV_NAME = 'MyTestEnvironment'; +const TEST_CONFIG_PROFILE_NAME = 'MyConfigurationProfile'; + +describe('simple-appconfig', () => { + it('creates expected resources', () => { + const app = new App(); + const stack = new Stack(app, 'MyTestStack'); + new SimpleAppConfig(stack, 'SimpleAppConfig', { + applicationName: TEST_APP_NAME, + applicationEnvironment: TEST_ENV_NAME, + configurationProfileName: TEST_CONFIG_PROFILE_NAME, + configurationContent: TEST_CONFIGURATION, + }); + + const template = assertions.Template.fromStack(stack); + expect(template).toMatchSnapshot(); + + template.hasResourceProperties('AWS::AppConfig::Application', { + Name: TEST_APP_NAME, + }); + template.resourceCountIs('AWS::AppConfig::Application', 1); + + template.hasResourceProperties('AWS::AppConfig::ConfigurationProfile', { + ApplicationId: { Ref: 'SimpleAppConfigApplication04939DED' }, + LocationUri: 'hosted', + Name: TEST_CONFIG_PROFILE_NAME, + Type: 'AWS.Freeform', + }); + template.resourceCountIs('AWS::AppConfig::ConfigurationProfile', 1); + + + template.hasResourceProperties('AWS::AppConfig::DeploymentStrategy', { + DeploymentDurationInMinutes: 0, + FinalBakeTimeInMinutes: 0, + GrowthFactor: 100, + Name: 'ImmediateDeployment', + ReplicateTo: 'NONE', + }); + template.resourceCountIs('AWS::AppConfig::DeploymentStrategy', 1); + + template.hasResourceProperties('AWS::AppConfig::Deployment', { + ApplicationId: { + Ref: 'SimpleAppConfigApplication04939DED', + }, + ConfigurationProfileId: { + Ref: 'SimpleAppConfigConfigurationProfile78536DC3', + }, + ConfigurationVersion: { + Ref: 'SimpleAppConfigHostedConfigurationVersion67E8BB89', + }, + DeploymentStrategyId: { + Ref: 'SimpleAppConfigDeployStrategy14D4E4A1', + }, + EnvironmentId: { + Ref: 'SimpleAppConfigEnvironmentCD8BFB59', + }, + }); + template.resourceCountIs('AWS::AppConfig::Deployment', 1); + + template.hasResourceProperties('AWS::AppConfig::Environment', { + ApplicationId: { + Ref: 'SimpleAppConfigApplication04939DED', + }, + Name: TEST_ENV_NAME, + }); + template.resourceCountIs('AWS::AppConfig::Environment', 1); + + template.hasResourceProperties('AWS::AppConfig::HostedConfigurationVersion', { + ApplicationId: { + Ref: 'SimpleAppConfigApplication04939DED', + }, + ConfigurationProfileId: { + Ref: 'SimpleAppConfigConfigurationProfile78536DC3', + }, + Content: JSON.stringify(TEST_CONFIGURATION), + ContentType: 'application/json', + }); + template.resourceCountIs('AWS::AppConfig::HostedConfigurationVersion', 1); + }); +}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index a232b67..d909569 100644 --- a/yarn.lock +++ b/yarn.lock @@ -296,6 +296,13 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@eslint/eslintrc@^1.4.1": version "1.4.1" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" @@ -547,7 +554,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0": +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== @@ -562,6 +569,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" @@ -767,6 +782,26 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14": version "7.20.0" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.0.tgz#61bc5a4cae505ce98e1e36c5445e4bee060d8891" @@ -1034,12 +1069,17 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^7.1.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4, acorn@^8.8.0: +acorn@^8.2.4, acorn@^8.4.1, acorn@^8.8.0: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== @@ -1162,6 +1202,11 @@ are-we-there-yet@^3.0.0: delegates "^1.0.0" readable-stream "^3.6.0" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1890,6 +1935,11 @@ core-util-is@^1.0.3, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -2069,6 +2119,11 @@ diff-sequences@^27.5.1: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -4310,7 +4365,7 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" -make-error@1.x: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -6047,6 +6102,25 @@ ts-jest@^27: semver "7.x" yargs-parser "20.x" +ts-node@^10.9.1: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tsconfig-paths@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" @@ -6290,6 +6364,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-to-istanbul@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" @@ -6559,6 +6638,11 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"