From c62377e14caae677deb7e4eae692eaccb2020c67 Mon Sep 17 00:00:00 2001 From: Mike Vosseller Date: Tue, 30 Nov 2021 10:56:52 -0500 Subject: [PATCH] feat(ec2): extend BastionHostLinux to support CloudFormationInit (#17507) Implements https://github.com/aws/aws-cdk/issues/17161 Extends the `BastionHostLinux` constructor to accept optional `CloudFormationInit` and `ApplyCloudFormationInitOptions` arguments to be passed to the underlying instance. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-ec2/lib/bastion-host.ts | 21 +++++++++- .../aws-ec2/test/bastion-host.test.ts | 42 ++++++++++++++++++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-ec2/lib/bastion-host.ts b/packages/@aws-cdk/aws-ec2/lib/bastion-host.ts index b0345f34b6b98..5f1d7d3c8709f 100644 --- a/packages/@aws-cdk/aws-ec2/lib/bastion-host.ts +++ b/packages/@aws-cdk/aws-ec2/lib/bastion-host.ts @@ -2,8 +2,9 @@ import { IPrincipal, IRole, PolicyStatement } from '@aws-cdk/aws-iam'; import { CfnOutput, Resource, Stack } from '@aws-cdk/core'; import { Construct } from 'constructs'; import { AmazonLinuxGeneration, InstanceArchitecture, InstanceClass, InstanceSize, InstanceType } from '.'; +import { CloudFormationInit } from './cfn-init'; import { Connections } from './connections'; -import { IInstance, Instance } from './instance'; +import { ApplyCloudFormationInitOptions, IInstance, Instance } from './instance'; import { AmazonLinuxCpuType, IMachineImage, MachineImage } from './machine-image'; import { IPeer } from './peer'; import { Port } from './port'; @@ -80,6 +81,22 @@ export interface BastionHostLinuxProps { * @default - Uses the block device mapping of the AMI */ readonly blockDevices?: BlockDevice[]; + + /** + * Apply the given CloudFormation Init configuration to the instance at startup + * + * @default - no CloudFormation init + */ + readonly init?: CloudFormationInit; + + /** + * Use the given options for applying CloudFormation Init + * + * Describes the configsets to use and the timeout to wait + * + * @default - default options + */ + readonly initOptions?: ApplyCloudFormationInitOptions; } /** @@ -159,6 +176,8 @@ export class BastionHostLinux extends Resource implements IInstance { }), vpcSubnets: props.subnetSelection ?? {}, blockDevices: props.blockDevices ?? undefined, + init: props.init, + initOptions: props.initOptions, }); this.instance.addToRolePolicy(new PolicyStatement({ actions: [ diff --git a/packages/@aws-cdk/aws-ec2/test/bastion-host.test.ts b/packages/@aws-cdk/aws-ec2/test/bastion-host.test.ts index 42e2dd8cd7e0a..38570e3306f8a 100644 --- a/packages/@aws-cdk/aws-ec2/test/bastion-host.test.ts +++ b/packages/@aws-cdk/aws-ec2/test/bastion-host.test.ts @@ -1,6 +1,7 @@ import '@aws-cdk/assert-internal/jest'; -import { Stack } from '@aws-cdk/core'; -import { BastionHostLinux, BlockDeviceVolume, InstanceClass, InstanceSize, InstanceType, SubnetType, Vpc } from '../lib'; +import { ResourcePart } from '@aws-cdk/assert-internal'; +import { Duration, Stack } from '@aws-cdk/core'; +import { BastionHostLinux, BlockDeviceVolume, CloudFormationInit, InitCommand, InstanceClass, InstanceSize, InstanceType, SubnetType, Vpc } from '../lib'; describe('bastion host', () => { test('default instance is created in basic', () => { @@ -123,4 +124,41 @@ describe('bastion host', () => { }); + + test('add CloudFormation Init to instance', () => { + // GIVEN + const stack = new Stack(); + const vpc = new Vpc(stack, 'VPC'); + + // WHEN + new BastionHostLinux(stack, 'Bastion', { + vpc, + initOptions: { + timeout: Duration.minutes(30), + }, + init: CloudFormationInit.fromElements( + InitCommand.shellCommand('echo hello'), + ), + }); + + // THEN + expect(stack).toHaveResourceLike('AWS::EC2::Instance', { + CreationPolicy: { + ResourceSignal: { + Timeout: 'PT30M', + }, + }, + Metadata: { + 'AWS::CloudFormation::Init': { + config: { + commands: { + '000': { + command: 'echo hello', + }, + }, + }, + }, + }, + }, ResourcePart.CompleteDefinition); + }); });