diff --git a/packages/@aws-cdk/aws-appconfig-alpha/README.md b/packages/@aws-cdk/aws-appconfig-alpha/README.md index f75f7b9c32471..b29fa5707a26d 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/README.md +++ b/packages/@aws-cdk/aws-appconfig-alpha/README.md @@ -176,6 +176,20 @@ new appconfig.HostedConfiguration(this, 'MyHostedConfiguration', { }); ``` +To deploy a configuration to an environment after initialization use the `deploy` method: + +```ts +declare const application: appconfig.Application; +declare const env: appconfig.Environment; + +const config = new appconfig.HostedConfiguration(this, 'MyHostedConfiguration', { + application, + content: appconfig.ConfigurationContent.fromInlineText('This is my configuration content.'), +}); + +config.deploy(env); +``` + ### SourcedConfiguration A sourced configuration represents configuration stored in an Amazon S3 bucket, AWS Secrets Manager secret, Systems Manager diff --git a/packages/@aws-cdk/aws-appconfig-alpha/lib/configuration.ts b/packages/@aws-cdk/aws-appconfig-alpha/lib/configuration.ts index e6ecb903feb92..3d141089cd637 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/lib/configuration.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/lib/configuration.ts @@ -303,6 +303,24 @@ abstract class ConfigurationBase extends Construct implements IConfiguration, IE this.extensible.addExtension(extension); } + /** + * Deploys the configuration to the specified environment. + * + * @param environment The environment to deploy the configuration to + */ + public deploy(environment: IEnvironment) { + const logicalId = `Deployment${this.getDeploymentHash(environment)}`; + new CfnDeployment(this, logicalId, { + applicationId: this.application.applicationId, + configurationProfileId: this.configurationProfileId, + deploymentStrategyId: this.deploymentStrategy!.deploymentStrategyId, + environmentId: environment.environmentId, + configurationVersion: this.versionNumber!, + description: this.description, + kmsKeyIdentifier: this.deploymentKey?.keyArn, + }); + } + protected addExistingEnvironmentsToApplication() { this.deployTo?.forEach((environment) => { if (!this.application.environments.includes(environment)) { @@ -320,16 +338,7 @@ abstract class ConfigurationBase extends Construct implements IConfiguration, IE if ((this.deployTo && !this.deployTo.includes(environment))) { return; } - const logicalId = `Deployment${this.getDeploymentHash(environment)}`; - new CfnDeployment(this, logicalId, { - applicationId: this.application.applicationId, - configurationProfileId: this.configurationProfileId, - deploymentStrategyId: this.deploymentStrategy!.deploymentStrategyId, - environmentId: environment.environmentId, - configurationVersion: this.versionNumber!, - description: this.description, - kmsKeyIdentifier: this.deploymentKey?.keyArn, - }); + this.deploy(environment); }); } } diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/configuration.test.ts b/packages/@aws-cdk/aws-appconfig-alpha/test/configuration.test.ts index 8beb61a83d5b9..489c95dfd818e 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/configuration.test.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/configuration.test.ts @@ -149,6 +149,121 @@ describe('configuration', () => { Template.fromStack(stack).resourceCountIs('AWS::AppConfig::Deployment', 1); }); + test('configuration using deploy method and no environment associated', () => { + const stack = new cdk.Stack(); + const app = new Application(stack, 'MyAppConfig', { + name: 'MyApplication', + }); + app.addEnvironment('MyEnv1'); + const env = app.addEnvironment('MyEnv2'); + const config = new HostedConfiguration(stack, 'MyHostedConfig', { + content: ConfigurationContent.fromInlineText('This is my content'), + application: app, + deploymentStrategy: new DeploymentStrategy(stack, 'MyDeploymentStrategy', { + rolloutStrategy: RolloutStrategy.linear({ + growthFactor: 15, + deploymentDuration: cdk.Duration.minutes(30), + }), + }), + }); + config.deploy(env); + + Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::Deployment', { + ApplicationId: { + Ref: 'MyAppConfigB4B63E75', + }, + EnvironmentId: { + Ref: 'MyAppConfigMyEnv2350437D6', + }, + ConfigurationVersion: { + Ref: 'MyHostedConfig51D3877D', + }, + ConfigurationProfileId: { + Ref: 'MyHostedConfigConfigurationProfile2E1A2BBC', + }, + DeploymentStrategyId: { + Ref: 'MyDeploymentStrategy60D31FB0', + }, + }); + Template.fromStack(stack).resourceCountIs('AWS::AppConfig::Deployment', 1); + }); + + test('configuration using deploy method with environment associated', () => { + const stack = new cdk.Stack(); + const app = new Application(stack, 'MyAppConfig', { + name: 'MyApplication', + }); + const env1 = app.addEnvironment('MyEnv1'); + const env2 = app.addEnvironment('MyEnv2'); + const config = new HostedConfiguration(stack, 'MyHostedConfig', { + content: ConfigurationContent.fromInlineText('This is my content'), + application: app, + deploymentStrategy: new DeploymentStrategy(stack, 'MyDeploymentStrategy', { + rolloutStrategy: RolloutStrategy.linear({ + growthFactor: 15, + deploymentDuration: cdk.Duration.minutes(30), + }), + }), + deployTo: [env1], + }); + config.deploy(env2); + + Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::Deployment', { + ApplicationId: { + Ref: 'MyAppConfigB4B63E75', + }, + EnvironmentId: { + Ref: 'MyAppConfigMyEnv1B9120FA1', + }, + ConfigurationVersion: { + Ref: 'MyHostedConfig51D3877D', + }, + ConfigurationProfileId: { + Ref: 'MyHostedConfigConfigurationProfile2E1A2BBC', + }, + DeploymentStrategyId: { + Ref: 'MyDeploymentStrategy60D31FB0', + }, + }); + Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::Deployment', { + ApplicationId: { + Ref: 'MyAppConfigB4B63E75', + }, + EnvironmentId: { + Ref: 'MyAppConfigMyEnv2350437D6', + }, + ConfigurationVersion: { + Ref: 'MyHostedConfig51D3877D', + }, + ConfigurationProfileId: { + Ref: 'MyHostedConfigConfigurationProfile2E1A2BBC', + }, + DeploymentStrategyId: { + Ref: 'MyDeploymentStrategy60D31FB0', + }, + }); + Template.fromStack(stack).resourceCountIs('AWS::AppConfig::Deployment', 2); + }); + + test('configuration with no environment associated and no deploy method used', () => { + const stack = new cdk.Stack(); + const app = new Application(stack, 'MyAppConfig', { + name: 'MyApplication', + }); + new HostedConfiguration(stack, 'MyHostedConfig', { + content: ConfigurationContent.fromInlineText('This is my content'), + application: app, + deploymentStrategy: new DeploymentStrategy(stack, 'MyDeploymentStrategy', { + rolloutStrategy: RolloutStrategy.linear({ + growthFactor: 15, + deploymentDuration: cdk.Duration.minutes(30), + }), + }), + }); + + Template.fromStack(stack).resourceCountIs('AWS::AppConfig::Deployment', 0); + }); + test('configuration with two configurations specified', () => { const stack = new cdk.Stack(); const app = new Application(stack, 'MyAppConfig', { diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/.cache/e976a796f036a5efbf44b99e44cfb5a961df08d8dbf7cd37e60bf216fb982a00.zip b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/.cache/e976a796f036a5efbf44b99e44cfb5a961df08d8dbf7cd37e60bf216fb982a00.zip new file mode 100644 index 0000000000000..ed9129d5ece9c Binary files /dev/null and b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/.cache/e976a796f036a5efbf44b99e44cfb5a961df08d8dbf7cd37e60bf216fb982a00.zip differ diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/aws-appconfig-configuration.assets.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/aws-appconfig-configuration.assets.json index b7b538ae455f2..f860e3b4a8908 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/aws-appconfig-configuration.assets.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/aws-appconfig-configuration.assets.json @@ -53,7 +53,7 @@ } } }, - "6ee0190db59f43253bdcd852c99b5c2229188185876571206fbdcab150ea4786": { + "df33d9dc000fae6b4ae1252e22f268275eac602b701d0e4c4aa8c463411bb15e": { "source": { "path": "aws-appconfig-configuration.template.json", "packaging": "file" @@ -61,7 +61,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "6ee0190db59f43253bdcd852c99b5c2229188185876571206fbdcab150ea4786.json", + "objectKey": "df33d9dc000fae6b4ae1252e22f268275eac602b701d0e4c4aa8c463411bb15e.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/aws-appconfig-configuration.template.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/aws-appconfig-configuration.template.json index 96b60551aaf98..9b57163a553d7 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/aws-appconfig-configuration.template.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/aws-appconfig-configuration.template.json @@ -33,6 +33,15 @@ "Name": "awsappconfigconfiguration-MyAppConfig-HostedEnvFromYaml-BB2C802A" } }, + "MyAppConfigEnvDeployLater26FA1032": { + "Type": "AWS::AppConfig::Environment", + "Properties": { + "ApplicationId": { + "Ref": "MyAppConfigB4B63E75" + }, + "Name": "awsappconfigconfiguration-MyAppConfig-EnvDeployLater-91038922" + } + }, "MyAppConfigParameterEnvD769FB19": { "Type": "AWS::AppConfig::Environment", "Properties": { @@ -224,6 +233,26 @@ } } }, + "MyHostedConfigFromJsonDeploymentEFECDBC4087F1": { + "Type": "AWS::AppConfig::Deployment", + "Properties": { + "ApplicationId": { + "Ref": "MyAppConfigB4B63E75" + }, + "ConfigurationProfileId": { + "Ref": "MyHostedConfigFromJsonConfigurationProfile863E1E42" + }, + "ConfigurationVersion": { + "Ref": "MyHostedConfigFromJsonD8CF9BE4" + }, + "DeploymentStrategyId": { + "Ref": "MyDeployStrategy062CAEA2" + }, + "EnvironmentId": { + "Ref": "MyAppConfigEnvDeployLater26FA1032" + } + } + }, "MyHostedConfigFromYamlConfigurationProfile7C77A435": { "Type": "AWS::AppConfig::ConfigurationProfile", "Properties": { diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/manifest.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/manifest.json index d8c09b629a540..0a4c2ed473aae 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/6ee0190db59f43253bdcd852c99b5c2229188185876571206fbdcab150ea4786.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/df33d9dc000fae6b4ae1252e22f268275eac602b701d0e4c4aa8c463411bb15e.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -58,6 +58,12 @@ "data": "MyAppConfigHostedEnvFromYaml82D3D1B2" } ], + "/aws-appconfig-configuration/MyAppConfig/EnvDeployLater/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyAppConfigEnvDeployLater26FA1032" + } + ], "/aws-appconfig-configuration/MyAppConfig/ParameterEnv/Resource": [ { "type": "aws:cdk:logicalId", @@ -148,6 +154,12 @@ "data": "MyHostedConfigFromJsonDeploymentCD82E3049E374" } ], + "/aws-appconfig-configuration/MyHostedConfigFromJson/DeploymentEFECD": [ + { + "type": "aws:cdk:logicalId", + "data": "MyHostedConfigFromJsonDeploymentEFECDBC4087F1" + } + ], "/aws-appconfig-configuration/MyHostedConfigFromYaml/ConfigurationProfile": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/tree.json b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/tree.json index 2be11468cdab5..eaf7cfc6ce8e9 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.js.snapshot/tree.json @@ -107,6 +107,33 @@ "version": "0.0.0" } }, + "EnvDeployLater": { + "id": "EnvDeployLater", + "path": "aws-appconfig-configuration/MyAppConfig/EnvDeployLater", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-appconfig-configuration/MyAppConfig/EnvDeployLater/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppConfig::Environment", + "aws:cdk:cloudformation:props": { + "applicationId": { + "Ref": "MyAppConfigB4B63E75" + }, + "name": "awsappconfigconfiguration-MyAppConfig-EnvDeployLater-91038922" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appconfig.CfnEnvironment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-appconfig-alpha.Environment", + "version": "0.0.0" + } + }, "ParameterEnv": { "id": "ParameterEnv", "path": "aws-appconfig-configuration/MyAppConfig/ParameterEnv", @@ -511,6 +538,34 @@ "fqn": "aws-cdk-lib.aws_appconfig.CfnDeployment", "version": "0.0.0" } + }, + "DeploymentEFECD": { + "id": "DeploymentEFECD", + "path": "aws-appconfig-configuration/MyHostedConfigFromJson/DeploymentEFECD", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::AppConfig::Deployment", + "aws:cdk:cloudformation:props": { + "applicationId": { + "Ref": "MyAppConfigB4B63E75" + }, + "configurationProfileId": { + "Ref": "MyHostedConfigFromJsonConfigurationProfile863E1E42" + }, + "configurationVersion": { + "Ref": "MyHostedConfigFromJsonD8CF9BE4" + }, + "deploymentStrategyId": { + "Ref": "MyDeployStrategy062CAEA2" + }, + "environmentId": { + "Ref": "MyAppConfigEnvDeployLater26FA1032" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_appconfig.CfnDeployment", + "version": "0.0.0" + } } }, "constructInfo": { diff --git a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.ts b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.ts index e606a2b63644e..bf6e396bc8f51 100644 --- a/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.ts +++ b/packages/@aws-cdk/aws-appconfig-alpha/test/integ.configuration.ts @@ -69,7 +69,7 @@ new HostedConfiguration(stack, 'MyHostedConfig', { // create basic config profile from add config version from file const hostedEnvFromJson = appConfigApp.addEnvironment('HostedEnvFromJson'); -new HostedConfiguration(stack, 'MyHostedConfigFromJson', { +const config = new HostedConfiguration(stack, 'MyHostedConfigFromJson', { application: appConfigApp, content: ConfigurationContent.fromInlineText('This is the configuration content'), deployTo: [hostedEnvFromJson], @@ -84,6 +84,10 @@ new HostedConfiguration(stack, 'MyHostedConfigFromYaml', { deploymentStrategy, }); +// verify a configuration can be deployed through the deploy method +const envToDeployLater = appConfigApp.addEnvironment('EnvDeployLater'); +config.deploy(envToDeployLater); + // ssm paramter as configuration source const func = new Function(stack, 'MyValidatorFunction', { runtime: Runtime.PYTHON_3_8,