Skip to content

Commit

Permalink
feat(appconfig-alpha): add deploy method to configuration constructs (#…
Browse files Browse the repository at this point in the history
…28269)

Adding a deploy method to the configuration construct to allow deployments on a config at any time after creation.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
chenjane-dev committed Dec 6, 2023
1 parent 2d9de18 commit c723ef9
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 14 deletions.
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-appconfig-alpha/README.md
Expand Up @@ -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
Expand Down
29 changes: 19 additions & 10 deletions packages/@aws-cdk/aws-appconfig-alpha/lib/configuration.ts
Expand Up @@ -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)) {
Expand All @@ -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);
});
}
}
Expand Down
115 changes: 115 additions & 0 deletions packages/@aws-cdk/aws-appconfig-alpha/test/configuration.test.ts
Expand Up @@ -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', {
Expand Down
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -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": {
Expand Down Expand Up @@ -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": {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -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],
Expand All @@ -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,
Expand Down

0 comments on commit c723ef9

Please sign in to comment.