Skip to content

Commit

Permalink
feat(appconfig): add CfnMonitorsProperty as a supported type for moni…
Browse files Browse the repository at this point in the history
…tors
  • Loading branch information
chenjane-dev committed Oct 24, 2023
1 parent 039071d commit afecb88
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 60 deletions.
56 changes: 47 additions & 9 deletions packages/@aws-cdk/aws-appconfig-alpha/lib/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,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 +278,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.
* The alarm ARN for AWS AppConfig to monitor.
*/
readonly alarm: cloudwatch.IAlarm;
public abstract readonly alarmArn: string;

/**
* The IAM role for AWS AppConfig to view the alarm state.
*
* @default - A role is generated.
* The IAM role ARN for AWS AppConfig to view the alarm state.
*/
readonly alarmRole?: iam.IRole;
public abstract readonly alarmRoleArn?: string;

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

/**
* 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,
};
}

/**
* Creates a Monitor from a CfnEnvironment.MonitorsProperty construct.
*
* @param monitorsProperty The monitors property.
*/
public static fromCfnMonitorsProperty(monitorsProperty: CfnEnvironment.MonitorsProperty): Monitor {
return {
alarmArn: monitorsProperty.alarmArn!,
alarmRoleArn: monitorsProperty.alarmRoleArn,
monitorType: MonitorType.CFN_MONITORS_PROPERTY,
};
}
}

export interface IEnvironment extends IResource {
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IntegTest } from '@aws-cdk/integ-tests-alpha';
import { App, Stack } from 'aws-cdk-lib';
import { Application, Environment } from '../lib';
import { Application, Environment, Monitor } from '../lib';
import { Alarm, Metric } from 'aws-cdk-lib/aws-cloudwatch';

const app = new App();
Expand All @@ -24,11 +24,7 @@ const alarm = new Alarm(stack, 'MyAlarm', {
new Environment(stack, 'MyEnvironment', {
application: appForEnv,
description: 'This is the environment for integ testing',
monitors: [
{
alarm,
},
],
monitors: [Monitor.fromCloudWatchAlarm(alarm)],
});

new IntegTest(app, 'appconfig-environment', {
Expand Down

0 comments on commit afecb88

Please sign in to comment.