Skip to content

Commit

Permalink
feat(ec2): add vpn metrics
Browse files Browse the repository at this point in the history
Add VPN metrics (TunnelState, TunnelDataIn, TunnelDataOut) across all tunnels
and per connection by adding a new augmentation.

Adapt AugmentationGenerator to support name overrides for class, interface
and module when these cannot be directly derived from the CloudFormation
resource name: no base class, resource name not really Pascal case,
resource module is Kebab case.
  • Loading branch information
jogold committed Mar 8, 2019
1 parent 85a1840 commit ef8c568
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 8 deletions.
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ export * from './vpn';

// AWS::EC2 CloudFormation Resources:
export * from './ec2.generated';

import './ec2-augmentations.generated';
39 changes: 39 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/vpn.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import cloudwatch = require('@aws-cdk/aws-cloudwatch');
import cdk = require('@aws-cdk/cdk');
import net = require('net');
import { CfnCustomerGateway, CfnVPNConnection, CfnVPNConnectionRoute } from './ec2.generated';
Expand Down Expand Up @@ -98,6 +99,44 @@ export enum VpnConnectionType {
}

export class VpnConnection extends cdk.Construct implements IVpnConnection {
/**
* Return the given named metric for all VPN connections.
*/
public static metricAll(metricName: string, props?: cloudwatch.MetricCustomization): cloudwatch.Metric {
return new cloudwatch.Metric({
namespace: 'AWS/VPN',
metricName,
...props
});
}

/**
* Metric for the tunnel state of all VPN connections.
*
* @default average over 5 minutes
*/
public static metricAllTunnelState(props?: cloudwatch.MetricCustomization): cloudwatch.Metric {
return this.metricAll('TunnelSate', { statistic: 'avg', ...props });
}

/**
* Metric for the tunnel data in of all VPN connections.
*
* @default sum over 5 minutes
*/
public static metricAllTunnelDataIn(props?: cloudwatch.MetricCustomization): cloudwatch.Metric {
return this.metricAll('TunnelDataIn', { statistic: 'sum', ...props });
}

/**
* Metric for the tunnel data out of all VPN connections.
*
* @default sum over 5 minutes
*/
public static metricAllTunnelDataOut(props?: cloudwatch.MetricCustomization): cloudwatch.Metric {
return this.metricAll('TunnelDataOut', { statistic: 'sum', ...props });
}

public readonly vpnId: string;
public readonly customerGatewayId: string;
public readonly customerGatewayIp: string;
Expand Down
4 changes: 3 additions & 1 deletion packages/@aws-cdk/aws-ec2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@
},
"dependencies": {
"@aws-cdk/aws-iam": "^0.25.2",
"@aws-cdk/aws-cloudwatch": "^0.25.2",
"@aws-cdk/cdk": "^0.25.2",
"@aws-cdk/cx-api": "^0.25.2"
},
"homepage": "https://github.com/awslabs/aws-cdk",
"peerDependencies": {
"@aws-cdk/aws-cloudwatch": "^0.25.2",
"@aws-cdk/cdk": "^0.25.2",
"@aws-cdk/cx-api": "^0.25.2"
},
Expand All @@ -78,4 +80,4 @@
"resource-attribute:@aws-cdk/aws-ec2.ISecurityGroup.securityGroupVpcId"
]
}
}
}
41 changes: 40 additions & 1 deletion packages/@aws-cdk/aws-ec2/test/test.vpn.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, haveResource, } from '@aws-cdk/assert';
import { Stack } from '@aws-cdk/cdk';
import { Test } from 'nodeunit';
import { VpcNetwork } from '../lib';
import { VpcNetwork, VpnConnection } from '../lib';

export = {
'can add a vpn connection to a vpc with a vpn gateway'(test: Test) {
Expand Down Expand Up @@ -258,6 +258,45 @@ export = {
}
}), /`tunnelInsideCidr`.+size/);

test.done();
},

'can use metricTunnelState on a vpn connection'(test: Test) {
// GIVEN
const stack = new Stack();

const vpc = new VpcNetwork(stack, 'VpcNetwork', {
vpnGateway: true
});

const vpn = vpc.addVpnConnection('Vpn', {
ip: '192.0.2.1'
});

// THEN
test.deepEqual(stack.node.resolve(vpn.metricTunnelState()), {
dimensions: { VpnId: { Ref: 'VpcNetworkVpnA476C58D' } },
namespace: 'AWS/VPN',
metricName: 'TunnelState',
periodSec: 300,
statistic: 'Average'
});

test.done();
},

'can use metricAllTunnelDataOut'(test: Test) {
// GIVEN
const stack = new Stack();

// THEN
test.deepEqual(stack.node.resolve(VpnConnection.metricAllTunnelDataOut()), {
namespace: 'AWS/VPN',
metricName: 'TunnelDataOut',
periodSec: 300,
statistic: 'Sum'
});

test.done();
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"overrides": {
"interface": "IVpnConnection",
"class": "VpnConnection",
"module": "vpn"
},
"metrics": {
"namespace": "AWS/VPN",
"dimensions": { "VpnId": "this.vpnId" },
"metrics": [
{
"name": "TunnelState",
"documentation": "The state of the tunnel. 0 indicates DOWN and 1 indicates UP."
},
{
"name": "TunnelDataIn",
"documentation": "The bytes received through the VPN tunnel.",
"type": "count"
},
{
"name": "TunnelDataOut",
"documentation": "The bytes sent through the VPN tunnel.",
"type": "count"
}
]
}
}
24 changes: 23 additions & 1 deletion packages/@aws-cdk/cfnspec/lib/schema/augmentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,28 @@ export interface ResourceAugmentation {
* Metric augmentations for this resource type
*/
metrics?: ResourceMetricAugmentations;

/**
* Overrides for this resource augmentation
*/
overrides?: ResourceOverrides;
}

export interface ResourceOverrides {
/**
* The name of the resource class
*/
class?: string;

/**
* The name of the resource interface
*/
interface?: string;

/**
* The name of the module
*/
module?: string;
}

export interface ResourceMetricAugmentations {
Expand Down Expand Up @@ -57,4 +79,4 @@ export enum MetricType {
* property. The most useful aggregate of this type of metric is "Max".
*/
Gauge = 'gauge'
}
}
10 changes: 5 additions & 5 deletions tools/cfn2ts/lib/augmentation-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class AugmentationGenerator {

if (aug.metrics) {
this.code.line('import cloudwatch = require("@aws-cdk/aws-cloudwatch");');
this.emitMetricAugmentations(resourceTypeName, aug.metrics);
this.emitMetricAugmentations(resourceTypeName, aug.metrics, aug.overrides);
hadAugmentations = true;
}
}
Expand All @@ -39,14 +39,14 @@ export class AugmentationGenerator {
return await this.code.save(dir);
}

private emitMetricAugmentations(resourceTypeName: string, metrics: schema.ResourceMetricAugmentations) {
private emitMetricAugmentations(resourceTypeName: string, metrics: schema.ResourceMetricAugmentations, overrides?: schema.ResourceOverrides) {
const cfnName = SpecName.parse(resourceTypeName);
const resourceName = genspec.CodeName.forCfnResource(cfnName, this.affix);
const l2ClassName = resourceName.className.replace(/^Cfn/, '');

const baseClassName = l2ClassName + 'Base';
const interfaceName = 'I' + l2ClassName;
const baseClassModule = `./${l2ClassName.toLowerCase()}-base`;
const baseClassName = (overrides && overrides.class) || l2ClassName + 'Base';
const interfaceName = (overrides && overrides.interface) || 'I' + l2ClassName;
const baseClassModule = `./${(overrides && overrides.module) || `${l2ClassName.toLowerCase()}-base`}`;

this.code.line(`import { ${baseClassName} } from "${baseClassModule}";`);

Expand Down

0 comments on commit ef8c568

Please sign in to comment.