Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(appconfig): support for CfnMonitorsProperty in environments #27680

Merged
merged 4 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/@aws-cdk/aws-appconfig-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,13 @@ declare const alarm: cloudwatch.Alarm;
new appconfig.Environment(this, 'MyEnvironment', {
application,
monitors: [
{alarm},
]
appconfig.Monitor.fromCloudWatchAlarm(alarm),
],
});
```

scanlonp marked this conversation as resolved.
Show resolved Hide resolved
Environment monitors also support L1 CfnEnvironment.MonitorsProperty constructs. However, this is not the recommended approach for CloudWatch alarms because a role will not be auto-generated if not provided.

## Extension

An extension augments your ability to inject logic or behavior at different points during the AWS AppConfig workflow of creating or deploying a configuration.
Expand Down
8 changes: 8 additions & 0 deletions packages/@aws-cdk/aws-appconfig-alpha/lib/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,11 +335,15 @@ export interface HostedConfigurationOptions extends ConfigurationOptions {

/**
* The latest version number of the hosted configuration.
*
* @default - None.
*/
readonly latestVersionNumber?: number;

/**
* The version label of the hosted configuration.
*
* @default - None.
*/
readonly versionLabel?: string;
}
Expand All @@ -352,11 +356,15 @@ export interface HostedConfigurationProps extends ConfigurationProps {

/**
* The latest version number of the hosted configuration.
*
* @default - None.
*/
readonly latestVersionNumber?: number;

/**
* The version label of the hosted configuration.
*
* @default - None.
*/
readonly versionLabel?: string;
}
Expand Down
62 changes: 53 additions & 9 deletions packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,22 @@ export interface EnvironmentAttributes {

/**
* The name of the environment.
*
* @default - None.
*/
readonly name?: string;

/**
* The description of the environment.
*
* @default - None.
*/
readonly description?: string;

/**
* The monitors for the environment.
*
* @default - None.
*/
readonly monitors?: Monitor[];
}
Expand Down Expand Up @@ -238,8 +244,10 @@ export class Environment extends EnvironmentBase {
description: this.description,
monitors: this.monitors?.map((monitor, index) => {
return {
alarmArn: monitor.alarm.alarmArn,
alarmRoleArn: monitor.alarmRole?.roleArn || this.createAlarmRole(monitor.alarm.alarmArn, index).roleArn,
alarmArn: monitor.alarmArn,
...(monitor.monitorType === MonitorType.CLOUDWATCH
? { alarmRoleArn: monitor.alarmRoleArn || this.createAlarmRole(monitor.alarmArn, index).roleArn }
: { alarmRoleArn: monitor.alarmRoleArn }),
};
}),
});
Expand Down Expand Up @@ -276,21 +284,57 @@ export class Environment extends EnvironmentBase {
}
}

export enum MonitorType {
CLOUDWATCH,
CFN_MONITORS_PROPERTY,
}

/**
* Defines monitors that will be associated with an AWS AppConfig environment.
*/
export interface Monitor {
export abstract class Monitor {
/**
* The Amazon CloudWatch alarm.
*/
readonly alarm: cloudwatch.IAlarm;
* Creates a Monitor from a CloudWatch alarm. If the alarm role is not specified, a role will
* be generated.
*
* @param alarm The Amazon CloudWatch alarm.
* @param alarmRole The IAM role for AWS AppConfig to view the alarm state.
*/
public static fromCloudWatchAlarm(alarm: cloudwatch.IAlarm, alarmRole?: iam.IRole): Monitor {
return {
alarmArn: alarm.alarmArn,
alarmRoleArn: alarmRole?.roleArn,
monitorType: MonitorType.CLOUDWATCH,
};
}

/**
* The IAM role for AWS AppConfig to view the alarm state.
* Creates a Monitor from a CfnEnvironment.MonitorsProperty construct.
*
* @default - A role is generated.
* @param monitorsProperty The monitors property.
*/
public static fromCfnMonitorsProperty(monitorsProperty: CfnEnvironment.MonitorsProperty): Monitor {
return {
alarmArn: monitorsProperty.alarmArn!,
alarmRoleArn: monitorsProperty.alarmRoleArn,
monitorType: MonitorType.CFN_MONITORS_PROPERTY,
};
}

/**
* The alarm ARN for AWS AppConfig to monitor.
*/
public abstract readonly alarmArn: string;

/**
* The type of monitor.
*/
public abstract readonly monitorType: MonitorType;

/**
* The IAM role ARN for AWS AppConfig to view the alarm state.
*/
readonly alarmRole?: iam.IRole;
public abstract readonly alarmRoleArn?: string;
}

export interface IEnvironment extends IResource {
Expand Down
8 changes: 8 additions & 0 deletions packages/@aws-cdk/aws-appconfig-alpha/lib/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,21 +290,29 @@ export interface ExtensionAttributes {

/**
* The Amazon Resource Name (ARN) of the extension.
*
* @default - The extension ARN is generated.
*/
readonly extensionArn?: string;

/**
* The actions of the extension.
*
* @default - None.
*/
readonly actions?: Action[];

/**
* The name of the extension.
*
* @default - None.
*/
readonly name?: string;

/**
* The description of the extension.
*
* @default - None.
*/
readonly description?: string;
}
Expand Down
141 changes: 96 additions & 45 deletions packages/@aws-cdk/aws-appconfig-alpha/test/environment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { App } from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { Alarm, Metric } from 'aws-cdk-lib/aws-cloudwatch';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Application, Environment } from '../lib';
import { Application, Environment, Monitor } from '../lib';

describe('environment', () => {
test('default environment', () => {
Expand Down Expand Up @@ -58,26 +58,23 @@ describe('environment', () => {
test('environment with monitors with alarm and alarmRole', () => {
const stack = new cdk.Stack();
const app = new Application(stack, 'MyAppConfig');
const alarm = new Alarm(stack, 'Alarm', {
threshold: 5,
evaluationPeriods: 5,
metric: new Metric(
{
namespace: 'aws',
metricName: 'myMetric',
},
),
});
const alarmRole = new iam.Role(stack, 'Role', {
assumedBy: new iam.ServicePrincipal('appconfig.amazonaws.com'),
});
const env = new Environment(stack, 'MyEnvironment', {
name: 'TestEnv',
application: app,
monitors: [
{
alarm: new Alarm(stack, 'Alarm', {
threshold: 5,
evaluationPeriods: 5,
metric: new Metric(
{
namespace: 'aws',
metricName: 'myMetric',
},
),
}),
alarmRole: new iam.Role(stack, 'Role', {
assumedBy: new iam.ServicePrincipal('appconfig.amazonaws.com'),
}),
},
],
monitors: [Monitor.fromCloudWatchAlarm(alarm, alarmRole)],
});

Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 1);
Expand Down Expand Up @@ -123,11 +120,7 @@ describe('environment', () => {
const env = new Environment(stack, 'MyEnvironment', {
name: 'TestEnv',
application: app,
monitors: [
{
alarm,
},
],
monitors: [Monitor.fromCloudWatchAlarm(alarm)],
});

expect(env).toBeDefined();
Expand Down Expand Up @@ -177,39 +170,97 @@ describe('environment', () => {
});
});

test('environment with monitors with two alarms', () => {
test('environment with CfnMonitorsProperty monitor', () => {
const stack = new cdk.Stack();
const app = new Application(stack, 'MyAppConfig');
new Environment(stack, 'MyEnvironment', {
const env = new Environment(stack, 'MyEnvironment', {
name: 'TestEnv',
application: app,
monitors: [
Monitor.fromCfnMonitorsProperty({
alarmArn: 'thisismyalarm',
}),
],
});

expect(env).toBeDefined();
Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 0);
Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 0);
Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::Environment', {
Name: 'TestEnv',
ApplicationId: {
Ref: 'MyAppConfigB4B63E75',
},
Monitors: [
{
alarm: new Alarm(stack, 'Alarm1', {
threshold: 5,
evaluationPeriods: 5,
metric: new Metric(
{
namespace: 'aws',
metricName: 'myMetric',
},
),
}),
AlarmArn: 'thisismyalarm',
},
],
});
});

test('environment with CfnMonitorsProperty monitor with roleArn', () => {
const stack = new cdk.Stack();
const app = new Application(stack, 'MyAppConfig');
const env = new Environment(stack, 'MyEnvironment', {
name: 'TestEnv',
application: app,
monitors: [
Monitor.fromCfnMonitorsProperty({
alarmArn: 'thisismyalarm',
alarmRoleArn: 'thisismyalarmrolearn',
}),
],
});

expect(env).toBeDefined();
Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 0);
Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 0);
Template.fromStack(stack).hasResourceProperties('AWS::AppConfig::Environment', {
Name: 'TestEnv',
ApplicationId: {
Ref: 'MyAppConfigB4B63E75',
},
Monitors: [
{
alarm: new Alarm(stack, 'Alarm2', {
threshold: 5,
evaluationPeriods: 5,
metric: new Metric(
{
namespace: 'aws',
metricName: 'myMetric',
},
),
}),
AlarmArn: 'thisismyalarm',
AlarmRoleArn: 'thisismyalarmrolearn',
},
],
});
});

test('environment with monitors with two alarms', () => {
const stack = new cdk.Stack();
const app = new Application(stack, 'MyAppConfig');
const alarm1 = new Alarm(stack, 'Alarm1', {
threshold: 5,
evaluationPeriods: 5,
metric: new Metric(
{
namespace: 'aws',
metricName: 'myMetric',
},
),
});
const alarm2 = new Alarm(stack, 'Alarm2', {
threshold: 5,
evaluationPeriods: 5,
metric: new Metric(
{
namespace: 'aws',
metricName: 'myMetric',
},
),
});
new Environment(stack, 'MyEnvironment', {
name: 'TestEnv',
application: app,
monitors: [
Monitor.fromCloudWatchAlarm(alarm1),
Monitor.fromCloudWatchAlarm(alarm2),
],
});

Template.fromStack(stack).resourceCountIs('AWS::CloudWatch::Alarm', 2);
Template.fromStack(stack).resourceCountIs('AWS::IAM::Role', 2);
Expand Down

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

Loading