Skip to content

Commit

Permalink
Merge branch 'master' into bump/14.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored May 6, 2020
2 parents 376f7e6 + ada0de1 commit bd5a09e
Show file tree
Hide file tree
Showing 19 changed files with 487 additions and 70 deletions.
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
"graceful-fs": "^4.2.4",
"typescript": "~3.8.3"
},
"resolutions-comment": "should be removed or reviewed when nodeunit dependency is dropped or adjusted",
"resolutions": {
"tap-mocha-reporter": "^5.0.1"
},
"repository": {
"type": "git",
"url": "git://github.com/aws/aws-cdk"
Expand Down
3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-batch/lib/job-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,9 @@ export class JobDefinition extends Resource implements IJobDefinition {
memory: container.memoryLimitMiB || 4,
mountPoints: container.mountPoints,
privileged: container.privileged || false,
resourceRequirements: container.gpuCount
? [{ type: 'GPU', value: String(container.gpuCount) }]
: undefined,
readonlyRootFilesystem: container.readOnly || false,
ulimits: container.ulimits,
user: container.user,
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-batch/test/job-definition.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ describe('Batch Job Definition', () => {
MountPoints: [],
Privileged: jobDefProps.container.privileged,
ReadonlyRootFilesystem: jobDefProps.container.readOnly,
ResourceRequirements: [{ Type: 'GPU', Value: String(jobDefProps.container.gpuCount)}],
Ulimits: [],
User: jobDefProps.container.user,
Vcpus: jobDefProps.container.vcpus,
Expand Down
11 changes: 11 additions & 0 deletions packages/@aws-cdk/aws-cloudwatch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,17 @@ dashboard.addWidgets(new GraphWidget({
}));
```

The graph legend can be adjusted from the default position at bottom of the widget.

```ts
dashboard.addWidgets(new GraphWidget({
// ...
// ...

legendPosition: LegendPosition.RIGHT,
}));
```

### Alarm widget

An alarm widget shows the graph and the alarm line of a single alarm:
Expand Down
28 changes: 28 additions & 0 deletions packages/@aws-cdk/aws-cloudwatch/lib/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,13 @@ export interface GraphWidgetProps extends MetricWidgetProps {
* @default - None
*/
readonly rightYAxis?: YAxisProps;

/**
* Position of the legend
*
* @default - bottom
*/
readonly legendPosition?: LegendPosition;
}

/**
Expand Down Expand Up @@ -210,6 +217,7 @@ export class GraphWidget extends ConcreteWidget {
left: this.props.leftYAxis !== undefined ? this.props.leftYAxis : undefined,
right: this.props.rightYAxis !== undefined ? this.props.rightYAxis : undefined,
},
legend: this.props.legendPosition !== undefined ? { position: this.props.legendPosition } : undefined,
},
}];
}
Expand Down Expand Up @@ -349,6 +357,26 @@ export class Color {
public static readonly RED = '#d62728';
}

/**
* The position of the legend on a GraphWidget.
*/
export enum LegendPosition {
/**
* Legend appears below the graph (default).
*/
BOTTOM = 'bottom',

/**
* Add shading above the annotation
*/
RIGHT = 'right',

/**
* Add shading below the annotation
*/
HIDDEN = 'hidden'
}

function mapAnnotation(yAxis: string): ((x: HorizontalAnnotation) => any) {
return (a: HorizontalAnnotation) => {
return { ...a, yAxis };
Expand Down
31 changes: 30 additions & 1 deletion packages/@aws-cdk/aws-cloudwatch/test/test.graphs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Stack } from '@aws-cdk/core';
import { Test } from 'nodeunit';
import { Alarm, AlarmWidget, Color, GraphWidget, LogQueryWidget, Metric, Shading, SingleValueWidget } from '../lib';
import { Alarm, AlarmWidget, Color, GraphWidget, LegendPosition, LogQueryWidget, Metric, Shading, SingleValueWidget } from '../lib';

export = {
'add stacked property to graphs'(test: Test) {
Expand Down Expand Up @@ -393,4 +393,33 @@ export = {
test.deepEqual(stack.resolve(widget.toJson())[0].properties.annotations.horizontal[0], { yAxis: 'left', value: 100, color: '#d62728' });
test.done();
},

'legend position is respected in constructor'(test: Test) {
// WHEN
const stack = new Stack();
const widget = new GraphWidget({
left: [new Metric({ namespace: 'CDK', metricName: 'Test' }) ],
legendPosition: LegendPosition.RIGHT,
});

// THEN
test.deepEqual(stack.resolve(widget.toJson()), [{
type: 'metric',
width: 6,
height: 6,
properties: {
view: 'timeSeries',
region: { Ref: 'AWS::Region' },
metrics: [
['CDK', 'Test'],
],
yAxis: {},
legend: {
position: 'right',
},
},
}]);

test.done();
},
};
13 changes: 13 additions & 0 deletions packages/@aws-cdk/aws-ec2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,19 @@ host.allowSshAccessFrom(ec2.Peer.ipv4('1.2.3.4/32'));
As there are no SSH public keys deployed on this machine, you need to use [EC2 Instance Connect](https://aws.amazon.com/de/blogs/compute/new-using-amazon-ec2-instance-connect-for-ssh-access-to-your-ec2-instances/)
with the command `aws ec2-instance-connect send-ssh-public-key` to provide your SSH public key.

EBS volume for the bastion host can be encrypted like:
```ts
const host = new ec2.BastionHostLinux(stack, 'BastionHost', {
vpc,
blockDevices: [{
deviceName: 'EBSBastionHost',
volume: BlockDeviceVolume.ebs(10, {
encrypted: true,
}),
}],
});
```


## Block Devices

Expand Down
17 changes: 17 additions & 0 deletions packages/@aws-cdk/aws-ec2/lib/bastion-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IMachineImage, MachineImage } from './machine-image';
import { IPeer } from './peer';
import { Port } from './port';
import { ISecurityGroup } from './security-group';
import { BlockDevice } from './volume';
import { IVpc, SubnetSelection } from './vpc';

/**
Expand Down Expand Up @@ -64,6 +65,20 @@ export interface BastionHostLinuxProps {
* may be replaced on every deployment).
*/
readonly machineImage?: IMachineImage;

/**
* Specifies how block devices are exposed to the instance. You can specify virtual devices and EBS volumes.
*
* Each instance that is launched has an associated root device volume,
* either an Amazon EBS volume or an instance store volume.
* You can use block device mappings to specify additional EBS volumes or
* instance store volumes to attach to an instance when it is launched.
*
* @see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html
*
* @default - Uses the block device mapping of the AMI
*/
readonly blockDevices?: BlockDevice[];
}

/**
Expand Down Expand Up @@ -129,6 +144,7 @@ export class BastionHostLinux extends Construct implements IInstance {
constructor(scope: Construct, id: string, props: BastionHostLinuxProps) {
super(scope, id);
this.stack = Stack.of(scope);

this.instance = new Instance(this, 'Resource', {
vpc: props.vpc,
availabilityZone: props.availabilityZone,
Expand All @@ -137,6 +153,7 @@ export class BastionHostLinux extends Construct implements IInstance {
instanceType: props.instanceType ?? InstanceType.of(InstanceClass.T3, InstanceSize.NANO),
machineImage: props.machineImage ?? MachineImage.latestAmazonLinux({ generation: AmazonLinuxGeneration.AMAZON_LINUX_2 }),
vpcSubnets: props.subnetSelection ?? {},
blockDevices: props.blockDevices ?? undefined,
});
this.instance.addToRolePolicy(new PolicyStatement({
actions: [
Expand Down
40 changes: 39 additions & 1 deletion packages/@aws-cdk/aws-ec2/test/test.bastion-host.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/core';
import { Test } from 'nodeunit';
import { BastionHostLinux, SubnetType, Vpc } from '../lib';
import { BastionHostLinux, BlockDeviceVolume, SubnetType, Vpc } from '../lib';

export = {
'default instance is created in basic'(test: Test) {
Expand Down Expand Up @@ -45,6 +45,44 @@ export = {
SubnetId: {Ref: 'VPCIsolatedSubnet1SubnetEBD00FC6'},
}));

test.done();
},
'ebs volume is encrypted'(test: Test) {
// GIVEN
const stack = new Stack();
const vpc = new Vpc(stack, 'VPC', {
subnetConfiguration: [
{
subnetType: SubnetType.ISOLATED,
name: 'Isolated',
},
],
});

// WHEN
new BastionHostLinux(stack, 'Bastion', {
vpc,
blockDevices: [{
deviceName: 'EBSBastionHost',
volume: BlockDeviceVolume.ebs(10, {
encrypted: true,
}),
}],
});

// THEN
expect(stack).to(haveResource('AWS::EC2::Instance', {
BlockDeviceMappings: [
{
DeviceName: 'EBSBastionHost',
Ebs: {
Encrypted: true,
VolumeSize: 10,
},
},
],
}));

test.done();
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ export = {
],
},
'SourceBucketNames': [{
'Ref': 'AssetParameterse9b696b2a8a1f93ea8b8a9ce1e4dd4727f9243eba984e50411ca95c6b03d26b6S3Bucket1A1EC3E9',
'Ref': 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3BucketB41AE64D',
}],
'SourceObjectKeys': [{
'Fn::Join': [
Expand All @@ -241,7 +241,7 @@ export = {
'Fn::Split': [
'||',
{
'Ref': 'AssetParameterse9b696b2a8a1f93ea8b8a9ce1e4dd4727f9243eba984e50411ca95c6b03d26b6S3VersionKeyE46A4824',
'Ref': 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3VersionKeyF3CBA38F',
},
],
},
Expand All @@ -254,7 +254,7 @@ export = {
'Fn::Split': [
'||',
{
'Ref': 'AssetParameterse9b696b2a8a1f93ea8b8a9ce1e4dd4727f9243eba984e50411ca95c6b03d26b6S3VersionKeyE46A4824',
'Ref': 'AssetParameters86f8bca4f28a0bcafef0a98fe4cea25c0071aca27401e35cfaecd06313373bcaS3VersionKeyF3CBA38F',
},
],
},
Expand Down
28 changes: 13 additions & 15 deletions packages/@aws-cdk/aws-stepfunctions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,27 @@ example](https://docs.aws.amazon.com/step-functions/latest/dg/job-status-poller-
```ts
import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as tasks from '@aws-cdk/aws-stepfunctions-tasks';
import * as lambda from '@aws-cdk/aws-lambda';

const submitLambda = new lambda.Function(this, 'SubmitLambda', { ... });
const getStatusLambda = new lambda.Function(this, 'CheckLambda', { ... });

const submitJob = new sfn.Task(this, 'Submit Job', {
task: new tasks.RunLambdaTask(submitLambda, {
integrationPattern: sfn.ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN,
}),
// Put Lambda's result here in the execution's state object
resultPath: '$.guid',
task: new tasks.RunLambdaTask(submitLambda),
// Lambda's result is in the attribute `Payload`
outputPath: '$.Payload',
});

const waitX = new sfn.Wait(this, 'Wait X Seconds', {
time: sfn.WaitTime.secondsPath('$.waitSeconds'),
});

const getStatus = new sfn.Task(this, 'Get Job Status', {
task: new tasks.RunLambdaTask(getStatusLambda, {
integrationPattern: sfn.ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN,
}),
task: new tasks.RunLambdaTask(getStatusLambda),
// Pass just the field named "guid" into the Lambda, put the
// Lambda's result in a field called "status"
// Lambda's result in a field called "status" in the response
inputPath: '$.guid',
resultPath: '$.status',
outputPath: '$.Payload',
});

const jobFailed = new sfn.Fail(this, 'Job Failed', {
Expand All @@ -58,12 +55,10 @@ const jobFailed = new sfn.Fail(this, 'Job Failed', {
});

const finalStatus = new sfn.Task(this, 'Get Final Job Status', {
task: new tasks.RunLambdaTask(getStatusLambda, {
integrationPattern: sfn.ServiceIntegrationPattern.WAIT_FOR_TASK_TOKEN,
}),
// Use "guid" field as input, output of the Lambda becomes the
// entire state machine output.
task: new tasks.RunLambdaTask(getStatusLambda),
// Use "guid" field as input
inputPath: '$.guid',
outputPath: '$.Payload',
});

const definition = submitJob
Expand All @@ -81,6 +76,9 @@ new sfn.StateMachine(this, 'StateMachine', {
});
```

You can find more sample snippets and learn more about the service integrations
in the `@aws-cdk/aws-stepfunctions-tasks` package.

## State Machine

A `stepfunctions.StateMachine` is a resource that takes a state machine
Expand Down
11 changes: 6 additions & 5 deletions packages/@aws-cdk/core/lib/fs/fingerprint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ export function fingerprint(fileOrDirectory: string, options: FingerprintOptions
if (exclude.length) {
_hashField(hash, 'options.exclude', JSON.stringify(exclude));
}
_processFileOrDirectory(fileOrDirectory);
const isDir = fs.statSync(fileOrDirectory).isDirectory();
_processFileOrDirectory(fileOrDirectory, isDir);

return hash.digest('hex');

function _processFileOrDirectory(symbolicPath: string, realPath = symbolicPath) {
if (shouldExclude(exclude, symbolicPath)) {
function _processFileOrDirectory(symbolicPath: string, isRootDir: boolean = false, realPath = symbolicPath) {
if (!isRootDir && shouldExclude(exclude, symbolicPath)) {
return;
}

Expand All @@ -49,15 +50,15 @@ export function fingerprint(fileOrDirectory: string, options: FingerprintOptions
const linkTarget = fs.readlinkSync(realPath);
const resolvedLinkTarget = path.resolve(path.dirname(realPath), linkTarget);
if (shouldFollow(follow, rootDirectory, resolvedLinkTarget)) {
_processFileOrDirectory(symbolicPath, resolvedLinkTarget);
_processFileOrDirectory(symbolicPath, false, resolvedLinkTarget);
} else {
_hashField(hash, `link:${relativePath}`, linkTarget);
}
} else if (stat.isFile()) {
_hashField(hash, `file:${relativePath}`, _contentFingerprint(realPath, stat));
} else if (stat.isDirectory()) {
for (const item of fs.readdirSync(realPath).sort()) {
_processFileOrDirectory(path.join(symbolicPath, item), path.join(realPath, item));
_processFileOrDirectory(path.join(symbolicPath, item), false, path.join(realPath, item));
}
} else {
throw new Error(`Unable to hash ${symbolicPath}: it is neither a file nor a directory`);
Expand Down
Loading

0 comments on commit bd5a09e

Please sign in to comment.