Skip to content

Commit

Permalink
feat(aws-ec2): Enable/disable EC2 "Detailed Monitoring" (#19437)
Browse files Browse the repository at this point in the history
Closes #19346

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Dzhuneyt authored Mar 29, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 8f9d274 commit 94f9d27
Showing 7 changed files with 123 additions and 21 deletions.
16 changes: 16 additions & 0 deletions packages/@aws-cdk/aws-ec2/README.md
Original file line number Diff line number Diff line change
@@ -1475,3 +1475,19 @@ const template = new ec2.LaunchTemplate(this, 'LaunchTemplate', {
}),
});
```

## Detailed Monitoring

The following demonstrates how to enable [Detailed Monitoring](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html) for an EC2 instance. Keep in mind that Detailed Monitoring results in [additional charges](http://aws.amazon.com/cloudwatch/pricing/).

```ts
declare const vpc: ec2.Vpc;
declare const instanceType: ec2.InstanceType;

new ec2.Instance(this, 'Instance1', {
vpc,
instanceType,
machineImage: new ec2.AmazonLinuxImage(),
detailedMonitoring: true,
});
```
10 changes: 10 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/instance.ts
Original file line number Diff line number Diff line change
@@ -245,6 +245,15 @@ export interface InstanceProps {
* @default - false
*/
readonly requireImdsv2?: boolean;

/**
* Whether "Detailed Monitoring" is enabled for this instance
* Keep in mind that Detailed Monitoring results in extra charges
*
* @see http://aws.amazon.com/cloudwatch/pricing/
* @default - false
*/
readonly detailedMonitoring?: boolean;
}

/**
@@ -381,6 +390,7 @@ export class Instance extends Resource implements IInstance {
blockDeviceMappings: props.blockDevices !== undefined ? instanceBlockDeviceMappings(this, props.blockDevices) : undefined,
privateIpAddress: props.privateIpAddress,
propagateTagsToVolumeOnCreation: props.propagateTagsToVolumeOnCreation,
monitoring: props.detailedMonitoring,
});
this.instance.node.addDependency(this.role);

83 changes: 78 additions & 5 deletions packages/@aws-cdk/aws-ec2/test/instance.test.ts
Original file line number Diff line number Diff line change
@@ -5,8 +5,19 @@ import { Asset } from '@aws-cdk/aws-s3-assets';
import { StringParameter } from '@aws-cdk/aws-ssm';
import { Stack } from '@aws-cdk/core';
import {
AmazonLinuxImage, BlockDeviceVolume, CloudFormationInit,
EbsDeviceVolumeType, InitCommand, Instance, InstanceArchitecture, InstanceClass, InstanceSize, InstanceType, LaunchTemplate, UserData, Vpc,
AmazonLinuxImage,
BlockDeviceVolume,
CloudFormationInit,
EbsDeviceVolumeType,
InitCommand,
Instance,
InstanceArchitecture,
InstanceClass,
InstanceSize,
InstanceType,
LaunchTemplate,
UserData,
Vpc,
} from '../lib';

let stack: Stack;
@@ -144,7 +155,7 @@ describe('instance', () => {

for (const instanceClass of sampleInstanceClassKeys) {
// WHEN
const key = instanceClass.key as keyof(typeof InstanceClass);
const key = instanceClass.key as keyof (typeof InstanceClass);
const instanceType = InstanceClass[key];

// THEN
@@ -432,6 +443,62 @@ describe('instance', () => {
},
});
});

describe('Detailed Monitoring', () => {
test('instance with Detailed Monitoring enabled', () => {
// WHEN
new Instance(stack, 'Instance', {
vpc,
machineImage: new AmazonLinuxImage(),
instanceType: new InstanceType('t2.micro'),
detailedMonitoring: true,
});

// Force stack synth so the Instance is applied
Template.fromStack(stack);

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', {
Monitoring: true,
});
});

test('instance with Detailed Monitoring disabled', () => {
// WHEN
new Instance(stack, 'Instance', {
vpc,
machineImage: new AmazonLinuxImage(),
instanceType: new InstanceType('t2.micro'),
detailedMonitoring: false,
});

// Force stack synth so the Instance is applied
Template.fromStack(stack);

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', {
Monitoring: false,
});
});

test('instance with Detailed Monitoring unset falls back to disabled', () => {
// WHEN
new Instance(stack, 'Instance', {
vpc,
machineImage: new AmazonLinuxImage(),
instanceType: new InstanceType('t2.micro'),
});

// Force stack synth so the Instance is applied
Template.fromStack(stack);

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::EC2::Instance', {
Monitoring: Match.absent(),
});
});
});

});

test('add CloudFormation Init to instance', () => {
@@ -519,8 +586,14 @@ test('cause replacement from s3 asset in userdata', () => {
const hash = 'f88eace39faf39d7';
Template.fromStack(stack).templateMatches(Match.objectLike({
Resources: Match.objectLike({
[`InstanceOne5B821005${hash}`]: Match.objectLike({ Type: 'AWS::EC2::Instance', Properties: Match.anyValue() }),
[`InstanceTwoDC29A7A7${hash}`]: Match.objectLike({ Type: 'AWS::EC2::Instance', Properties: Match.anyValue() }),
[`InstanceOne5B821005${hash}`]: Match.objectLike({
Type: 'AWS::EC2::Instance',
Properties: Match.anyValue(),
}),
[`InstanceTwoDC29A7A7${hash}`]: Match.objectLike({
Type: 'AWS::EC2::Instance',
Properties: Match.anyValue(),
}),
}),
}));
});
31 changes: 16 additions & 15 deletions packages/@aws-cdk/aws-ec2/test/integ.instance.expected.json
Original file line number Diff line number Diff line change
@@ -18,11 +18,11 @@
"VPCPublicSubnet1SubnetB4246D30": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.0.0/19",
"VpcId": {
"Ref": "VPCB9E5F0B4"
},
"AvailabilityZone": "test-region-1a",
"CidrBlock": "10.0.0.0/19",
"MapPublicIpOnLaunch": true,
"Tags": [
{
@@ -95,15 +95,15 @@
"VPCPublicSubnet1NATGatewayE0556630": {
"Type": "AWS::EC2::NatGateway",
"Properties": {
"SubnetId": {
"Ref": "VPCPublicSubnet1SubnetB4246D30"
},
"AllocationId": {
"Fn::GetAtt": [
"VPCPublicSubnet1EIP6AD938E8",
"AllocationId"
]
},
"SubnetId": {
"Ref": "VPCPublicSubnet1SubnetB4246D30"
},
"Tags": [
{
"Key": "Name",
@@ -115,11 +115,11 @@
"VPCPublicSubnet2Subnet74179F39": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.32.0/19",
"VpcId": {
"Ref": "VPCB9E5F0B4"
},
"AvailabilityZone": "test-region-1b",
"CidrBlock": "10.0.32.0/19",
"MapPublicIpOnLaunch": true,
"Tags": [
{
@@ -192,15 +192,15 @@
"VPCPublicSubnet2NATGateway3C070193": {
"Type": "AWS::EC2::NatGateway",
"Properties": {
"SubnetId": {
"Ref": "VPCPublicSubnet2Subnet74179F39"
},
"AllocationId": {
"Fn::GetAtt": [
"VPCPublicSubnet2EIP4947BC00",
"AllocationId"
]
},
"SubnetId": {
"Ref": "VPCPublicSubnet2Subnet74179F39"
},
"Tags": [
{
"Key": "Name",
@@ -212,11 +212,11 @@
"VPCPublicSubnet3Subnet631C5E25": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.64.0/19",
"VpcId": {
"Ref": "VPCB9E5F0B4"
},
"AvailabilityZone": "test-region-1c",
"CidrBlock": "10.0.64.0/19",
"MapPublicIpOnLaunch": true,
"Tags": [
{
@@ -289,15 +289,15 @@
"VPCPublicSubnet3NATGatewayD3048F5C": {
"Type": "AWS::EC2::NatGateway",
"Properties": {
"SubnetId": {
"Ref": "VPCPublicSubnet3Subnet631C5E25"
},
"AllocationId": {
"Fn::GetAtt": [
"VPCPublicSubnet3EIPAD4BC883",
"AllocationId"
]
},
"SubnetId": {
"Ref": "VPCPublicSubnet3Subnet631C5E25"
},
"Tags": [
{
"Key": "Name",
@@ -309,11 +309,11 @@
"VPCPrivateSubnet1Subnet8BCA10E0": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.96.0/19",
"VpcId": {
"Ref": "VPCB9E5F0B4"
},
"AvailabilityZone": "test-region-1a",
"CidrBlock": "10.0.96.0/19",
"MapPublicIpOnLaunch": false,
"Tags": [
{
@@ -371,11 +371,11 @@
"VPCPrivateSubnet2SubnetCFCDAA7A": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.128.0/19",
"VpcId": {
"Ref": "VPCB9E5F0B4"
},
"AvailabilityZone": "test-region-1b",
"CidrBlock": "10.0.128.0/19",
"MapPublicIpOnLaunch": false,
"Tags": [
{
@@ -433,11 +433,11 @@
"VPCPrivateSubnet3Subnet3EDCD457": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"CidrBlock": "10.0.160.0/19",
"VpcId": {
"Ref": "VPCB9E5F0B4"
},
"AvailabilityZone": "test-region-1c",
"CidrBlock": "10.0.160.0/19",
"MapPublicIpOnLaunch": false,
"Tags": [
{
@@ -620,6 +620,7 @@
"Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter"
},
"InstanceType": "t3.nano",
"Monitoring": true,
"SecurityGroupIds": [
{
"Fn::GetAtt": [
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-ec2/test/integ.instance.ts
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ class TestStack extends cdk.Stack {
vpc,
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.NANO),
machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2 }),
detailedMonitoring: true,
});

instance.addToRolePolicy(new PolicyStatement({
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-ec2/test/userdata.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Bucket } from '@aws-cdk/aws-s3';
import { Template, Match } from '@aws-cdk/assertions';
import { Bucket } from '@aws-cdk/aws-s3';
import { Aws, Stack, CfnResource } from '@aws-cdk/core';
import * as ec2 from '../lib';

1 change: 1 addition & 0 deletions packages/aws-cdk-lib/package.json
Original file line number Diff line number Diff line change
@@ -414,6 +414,7 @@
"./aws-autoscalingplans": "./aws-autoscalingplans/index.js",
"./aws-backup": "./aws-backup/index.js",
"./aws-batch": "./aws-batch/index.js",
"./aws-billingconductor": "./aws-billingconductor/index.js",
"./aws-budgets": "./aws-budgets/index.js",
"./aws-cassandra": "./aws-cassandra/index.js",
"./aws-ce": "./aws-ce/index.js",

0 comments on commit 94f9d27

Please sign in to comment.