From cb1506f090e36a6da78b8a8a1edf9a1256478311 Mon Sep 17 00:00:00 2001
From: Daniel Neilson <53624638+ddneilson@users.noreply.github.com>
Date: Wed, 12 Oct 2022 17:15:31 -0500
Subject: [PATCH] feat(ec2): adds persist option to user data on windows
instances (#21709)
To set the UserData for Windows instances to run on every instance start, rather than only the first startup, requires adding "true" to the end of the user data string. Currently, users must use an escape hatch to hack the userdata of
windows instances to add this string. This PR makes it possible to add this text directly on the UserData without using an escape hatch.
Implements: https://github.com/aws/aws-cdk/issues/21708
----
### All Submissions:
* [X] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md)
### Adding new Unconventional Dependencies:
* [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies)
### New Features
* [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)?
* [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?
*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/README.md | 15 +
packages/@aws-cdk/aws-ec2/lib/user-data.ts | 26 +-
.../@aws-cdk/aws-ec2/test/integ.userdata.ts | 18 +
.../test/userdata.integ.snapshot/cdk.out | 1 +
.../integ-userdata.assets.json | 19 +
.../integ-userdata.template.json | 541 +++++++++++
.../userdata.integ.snapshot/manifest.json | 226 +++++
.../test/userdata.integ.snapshot/tree.json | 857 ++++++++++++++++++
.../@aws-cdk/aws-ec2/test/userdata.test.ts | 8 +
9 files changed, 1707 insertions(+), 4 deletions(-)
create mode 100644 packages/@aws-cdk/aws-ec2/test/integ.userdata.ts
create mode 100644 packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/cdk.out
create mode 100644 packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/integ-userdata.assets.json
create mode 100644 packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/integ-userdata.template.json
create mode 100644 packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/manifest.json
create mode 100644 packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/tree.json
diff --git a/packages/@aws-cdk/aws-ec2/README.md b/packages/@aws-cdk/aws-ec2/README.md
index 4f77528d922e6..9b24604d546ab 100644
--- a/packages/@aws-cdk/aws-ec2/README.md
+++ b/packages/@aws-cdk/aws-ec2/README.md
@@ -1404,6 +1404,21 @@ instance.userData.addExecuteFileCommand({
asset.grantRead(instance.role);
```
+### Persisting user data
+
+By default, EC2 UserData is run once on only the first time that an instance is started. It is possible to make the
+user data script run on every start of the instance.
+
+When creating a Windows UserData you can use the `persist` option to set whether or not to add
+`true` [to the user data script](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-windows-user-data.html#user-data-scripts). it can be used as follows:
+
+```ts
+const windowsUserData = UserData.forWindows({ persist: true });
+```
+
+For a Linux instance, this can be accomplished by using a Multipart user data to configure cloud-config as detailed
+in: https://aws.amazon.com/premiumsupport/knowledge-center/execute-user-data-ec2/
+
### Multipart user data
In addition, to above the `MultipartUserData` can be used to change instance startup behavior. Multipart user data are composed
diff --git a/packages/@aws-cdk/aws-ec2/lib/user-data.ts b/packages/@aws-cdk/aws-ec2/lib/user-data.ts
index 82e256b9a895a..2b59c63138bef 100644
--- a/packages/@aws-cdk/aws-ec2/lib/user-data.ts
+++ b/packages/@aws-cdk/aws-ec2/lib/user-data.ts
@@ -14,6 +14,24 @@ export interface LinuxUserDataOptions {
readonly shebang?: string;
}
+/**
+ * Options when constructing UserData for Windows
+ */
+export interface WindowsUserDataOptions {
+ /**
+ * Set to true to set this userdata to persist through an instance reboot; allowing
+ * it to run on every instance start.
+ * By default, UserData is run only once during the first instance launch.
+ *
+ * For more information, see:
+ * https://aws.amazon.com/premiumsupport/knowledge-center/execute-user-data-ec2/
+ * https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-windows-user-data.html#user-data-scripts
+ *
+ * @default false
+ */
+ readonly persist?: boolean;
+}
+
/**
* Options when downloading files from S3
*/
@@ -78,8 +96,8 @@ export abstract class UserData {
/**
* Create a userdata object for Windows hosts
*/
- public static forWindows(): UserData {
- return new WindowsUserData();
+ public static forWindows(options: WindowsUserDataOptions = {}): UserData {
+ return new WindowsUserData(options);
}
/**
@@ -197,7 +215,7 @@ class WindowsUserData extends UserData {
private readonly lines: string[] = [];
private readonly onExitLines: string[] = [];
- constructor() {
+ constructor(private readonly props: WindowsUserDataOptions = {}) {
super();
}
@@ -214,7 +232,7 @@ class WindowsUserData extends UserData {
[...(this.renderOnExitLines()),
...this.lines,
...( this.onExitLines.length > 0 ? ['throw "Success"'] : [] )].join('\n')
- }`;
+ }${(this.props.persist ?? false) ? 'true' : ''}`;
}
public addS3DownloadCommand(params: S3DownloadOptions): string {
diff --git a/packages/@aws-cdk/aws-ec2/test/integ.userdata.ts b/packages/@aws-cdk/aws-ec2/test/integ.userdata.ts
new file mode 100644
index 0000000000000..002de7bd6cc29
--- /dev/null
+++ b/packages/@aws-cdk/aws-ec2/test/integ.userdata.ts
@@ -0,0 +1,18 @@
+#!/usr/bin/env node
+import * as cdk from '@aws-cdk/core';
+import * as ec2 from '../lib';
+
+const app = new cdk.App();
+const stack = new cdk.Stack(app, 'integ-userdata');
+
+const vpc = new ec2.Vpc(stack, 'IntegUserdataVpc');
+
+new ec2.Instance(stack, 'WindowsInstance', {
+ vpc,
+ vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
+ instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO),
+ machineImage: new ec2.WindowsImage(ec2.WindowsVersion.WINDOWS_SERVER_2022_ENGLISH_FULL_BASE),
+ userData: ec2.UserData.forWindows({ persist: true }),
+});
+
+app.synth();
diff --git a/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/cdk.out
new file mode 100644
index 0000000000000..8ecc185e9dbee
--- /dev/null
+++ b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/cdk.out
@@ -0,0 +1 @@
+{"version":"21.0.0"}
\ No newline at end of file
diff --git a/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/integ-userdata.assets.json b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/integ-userdata.assets.json
new file mode 100644
index 0000000000000..a97d75d14b3b8
--- /dev/null
+++ b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/integ-userdata.assets.json
@@ -0,0 +1,19 @@
+{
+ "version": "21.0.0",
+ "files": {
+ "9f2c5f7def4ad32c13627dff08f2be0273546384a8fe510e265cc6a7083274e1": {
+ "source": {
+ "path": "integ-userdata.template.json",
+ "packaging": "file"
+ },
+ "destinations": {
+ "current_account-current_region": {
+ "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
+ "objectKey": "9f2c5f7def4ad32c13627dff08f2be0273546384a8fe510e265cc6a7083274e1.json",
+ "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
+ }
+ }
+ }
+ },
+ "dockerImages": {}
+}
\ No newline at end of file
diff --git a/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/integ-userdata.template.json b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/integ-userdata.template.json
new file mode 100644
index 0000000000000..8fa5af6d1dd2b
--- /dev/null
+++ b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/integ-userdata.template.json
@@ -0,0 +1,541 @@
+{
+ "Resources": {
+ "IntegUserdataVpcDE2938ED": {
+ "Type": "AWS::EC2::VPC",
+ "Properties": {
+ "CidrBlock": "10.0.0.0/16",
+ "EnableDnsHostnames": true,
+ "EnableDnsSupport": true,
+ "InstanceTenancy": "default",
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPublicSubnet1Subnet9AE7FE85": {
+ "Type": "AWS::EC2::Subnet",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "AvailabilityZone": {
+ "Fn::Select": [
+ 0,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "CidrBlock": "10.0.0.0/18",
+ "MapPublicIpOnLaunch": true,
+ "Tags": [
+ {
+ "Key": "aws-cdk:subnet-name",
+ "Value": "Public"
+ },
+ {
+ "Key": "aws-cdk:subnet-type",
+ "Value": "Public"
+ },
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PublicSubnet1"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPublicSubnet1RouteTable7B342D96": {
+ "Type": "AWS::EC2::RouteTable",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PublicSubnet1"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPublicSubnet1RouteTableAssociation724A6375": {
+ "Type": "AWS::EC2::SubnetRouteTableAssociation",
+ "Properties": {
+ "RouteTableId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1RouteTable7B342D96"
+ },
+ "SubnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1Subnet9AE7FE85"
+ }
+ }
+ },
+ "IntegUserdataVpcPublicSubnet1DefaultRoute8F93CC39": {
+ "Type": "AWS::EC2::Route",
+ "Properties": {
+ "RouteTableId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1RouteTable7B342D96"
+ },
+ "DestinationCidrBlock": "0.0.0.0/0",
+ "GatewayId": {
+ "Ref": "IntegUserdataVpcIGWB657C40E"
+ }
+ },
+ "DependsOn": [
+ "IntegUserdataVpcVPCGWFA86AC6A"
+ ]
+ },
+ "IntegUserdataVpcPublicSubnet1EIP41DE8CA6": {
+ "Type": "AWS::EC2::EIP",
+ "Properties": {
+ "Domain": "vpc",
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PublicSubnet1"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPublicSubnet1NATGatewayC9F60940": {
+ "Type": "AWS::EC2::NatGateway",
+ "Properties": {
+ "SubnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1Subnet9AE7FE85"
+ },
+ "AllocationId": {
+ "Fn::GetAtt": [
+ "IntegUserdataVpcPublicSubnet1EIP41DE8CA6",
+ "AllocationId"
+ ]
+ },
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PublicSubnet1"
+ }
+ ]
+ },
+ "DependsOn": [
+ "IntegUserdataVpcPublicSubnet1DefaultRoute8F93CC39",
+ "IntegUserdataVpcPublicSubnet1RouteTableAssociation724A6375"
+ ]
+ },
+ "IntegUserdataVpcPublicSubnet2Subnet7EC040B5": {
+ "Type": "AWS::EC2::Subnet",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "AvailabilityZone": {
+ "Fn::Select": [
+ 1,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "CidrBlock": "10.0.64.0/18",
+ "MapPublicIpOnLaunch": true,
+ "Tags": [
+ {
+ "Key": "aws-cdk:subnet-name",
+ "Value": "Public"
+ },
+ {
+ "Key": "aws-cdk:subnet-type",
+ "Value": "Public"
+ },
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PublicSubnet2"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPublicSubnet2RouteTable98BA8E97": {
+ "Type": "AWS::EC2::RouteTable",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PublicSubnet2"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPublicSubnet2RouteTableAssociationBA5DC07F": {
+ "Type": "AWS::EC2::SubnetRouteTableAssociation",
+ "Properties": {
+ "RouteTableId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2RouteTable98BA8E97"
+ },
+ "SubnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2Subnet7EC040B5"
+ }
+ }
+ },
+ "IntegUserdataVpcPublicSubnet2DefaultRoute90FCB645": {
+ "Type": "AWS::EC2::Route",
+ "Properties": {
+ "RouteTableId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2RouteTable98BA8E97"
+ },
+ "DestinationCidrBlock": "0.0.0.0/0",
+ "GatewayId": {
+ "Ref": "IntegUserdataVpcIGWB657C40E"
+ }
+ },
+ "DependsOn": [
+ "IntegUserdataVpcVPCGWFA86AC6A"
+ ]
+ },
+ "IntegUserdataVpcPublicSubnet2EIP662D51E3": {
+ "Type": "AWS::EC2::EIP",
+ "Properties": {
+ "Domain": "vpc",
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PublicSubnet2"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPublicSubnet2NATGatewayB25F84D3": {
+ "Type": "AWS::EC2::NatGateway",
+ "Properties": {
+ "SubnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2Subnet7EC040B5"
+ },
+ "AllocationId": {
+ "Fn::GetAtt": [
+ "IntegUserdataVpcPublicSubnet2EIP662D51E3",
+ "AllocationId"
+ ]
+ },
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PublicSubnet2"
+ }
+ ]
+ },
+ "DependsOn": [
+ "IntegUserdataVpcPublicSubnet2DefaultRoute90FCB645",
+ "IntegUserdataVpcPublicSubnet2RouteTableAssociationBA5DC07F"
+ ]
+ },
+ "IntegUserdataVpcPrivateSubnet1Subnet4EFBF430": {
+ "Type": "AWS::EC2::Subnet",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "AvailabilityZone": {
+ "Fn::Select": [
+ 0,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "CidrBlock": "10.0.128.0/18",
+ "MapPublicIpOnLaunch": false,
+ "Tags": [
+ {
+ "Key": "aws-cdk:subnet-name",
+ "Value": "Private"
+ },
+ {
+ "Key": "aws-cdk:subnet-type",
+ "Value": "Private"
+ },
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PrivateSubnet1"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPrivateSubnet1RouteTable63E39754": {
+ "Type": "AWS::EC2::RouteTable",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PrivateSubnet1"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPrivateSubnet1RouteTableAssociation176A5EB9": {
+ "Type": "AWS::EC2::SubnetRouteTableAssociation",
+ "Properties": {
+ "RouteTableId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet1RouteTable63E39754"
+ },
+ "SubnetId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet1Subnet4EFBF430"
+ }
+ }
+ },
+ "IntegUserdataVpcPrivateSubnet1DefaultRoute03370EF2": {
+ "Type": "AWS::EC2::Route",
+ "Properties": {
+ "RouteTableId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet1RouteTable63E39754"
+ },
+ "DestinationCidrBlock": "0.0.0.0/0",
+ "NatGatewayId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1NATGatewayC9F60940"
+ }
+ }
+ },
+ "IntegUserdataVpcPrivateSubnet2SubnetAFD1E5B4": {
+ "Type": "AWS::EC2::Subnet",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "AvailabilityZone": {
+ "Fn::Select": [
+ 1,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "CidrBlock": "10.0.192.0/18",
+ "MapPublicIpOnLaunch": false,
+ "Tags": [
+ {
+ "Key": "aws-cdk:subnet-name",
+ "Value": "Private"
+ },
+ {
+ "Key": "aws-cdk:subnet-type",
+ "Value": "Private"
+ },
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PrivateSubnet2"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPrivateSubnet2RouteTable7944CD08": {
+ "Type": "AWS::EC2::RouteTable",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc/PrivateSubnet2"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcPrivateSubnet2RouteTableAssociation3B0C1389": {
+ "Type": "AWS::EC2::SubnetRouteTableAssociation",
+ "Properties": {
+ "RouteTableId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet2RouteTable7944CD08"
+ },
+ "SubnetId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet2SubnetAFD1E5B4"
+ }
+ }
+ },
+ "IntegUserdataVpcPrivateSubnet2DefaultRouteA120F4F4": {
+ "Type": "AWS::EC2::Route",
+ "Properties": {
+ "RouteTableId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet2RouteTable7944CD08"
+ },
+ "DestinationCidrBlock": "0.0.0.0/0",
+ "NatGatewayId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2NATGatewayB25F84D3"
+ }
+ }
+ },
+ "IntegUserdataVpcIGWB657C40E": {
+ "Type": "AWS::EC2::InternetGateway",
+ "Properties": {
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/IntegUserdataVpc"
+ }
+ ]
+ }
+ },
+ "IntegUserdataVpcVPCGWFA86AC6A": {
+ "Type": "AWS::EC2::VPCGatewayAttachment",
+ "Properties": {
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "InternetGatewayId": {
+ "Ref": "IntegUserdataVpcIGWB657C40E"
+ }
+ }
+ },
+ "WindowsInstanceInstanceSecurityGroup3B6692A8": {
+ "Type": "AWS::EC2::SecurityGroup",
+ "Properties": {
+ "GroupDescription": "integ-userdata/WindowsInstance/InstanceSecurityGroup",
+ "SecurityGroupEgress": [
+ {
+ "CidrIp": "0.0.0.0/0",
+ "Description": "Allow all outbound traffic by default",
+ "IpProtocol": "-1"
+ }
+ ],
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/WindowsInstance"
+ }
+ ],
+ "VpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ }
+ }
+ },
+ "WindowsInstanceInstanceRoleB7D73766": {
+ "Type": "AWS::IAM::Role",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": {
+ "Fn::Join": [
+ "",
+ [
+ "ec2.",
+ {
+ "Ref": "AWS::URLSuffix"
+ }
+ ]
+ ]
+ }
+ }
+ }
+ ],
+ "Version": "2012-10-17"
+ },
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/WindowsInstance"
+ }
+ ]
+ }
+ },
+ "WindowsInstanceInstanceProfile20441977": {
+ "Type": "AWS::IAM::InstanceProfile",
+ "Properties": {
+ "Roles": [
+ {
+ "Ref": "WindowsInstanceInstanceRoleB7D73766"
+ }
+ ]
+ }
+ },
+ "WindowsInstance4ABA347A": {
+ "Type": "AWS::EC2::Instance",
+ "Properties": {
+ "AvailabilityZone": {
+ "Fn::Select": [
+ 0,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "IamInstanceProfile": {
+ "Ref": "WindowsInstanceInstanceProfile20441977"
+ },
+ "ImageId": {
+ "Ref": "SsmParameterValueawsserviceamiwindowslatestWindowsServer2022EnglishFullBaseC96584B6F00A464EAD1953AFF4B05118Parameter"
+ },
+ "InstanceType": "t2.micro",
+ "SecurityGroupIds": [
+ {
+ "Fn::GetAtt": [
+ "WindowsInstanceInstanceSecurityGroup3B6692A8",
+ "GroupId"
+ ]
+ }
+ ],
+ "SubnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1Subnet9AE7FE85"
+ },
+ "Tags": [
+ {
+ "Key": "Name",
+ "Value": "integ-userdata/WindowsInstance"
+ }
+ ],
+ "UserData": {
+ "Fn::Base64": "true"
+ }
+ },
+ "DependsOn": [
+ "WindowsInstanceInstanceRoleB7D73766"
+ ]
+ }
+ },
+ "Parameters": {
+ "SsmParameterValueawsserviceamiwindowslatestWindowsServer2022EnglishFullBaseC96584B6F00A464EAD1953AFF4B05118Parameter": {
+ "Type": "AWS::SSM::Parameter::Value",
+ "Default": "/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base"
+ },
+ "BootstrapVersion": {
+ "Type": "AWS::SSM::Parameter::Value",
+ "Default": "/cdk-bootstrap/hnb659fds/version",
+ "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
+ }
+ },
+ "Rules": {
+ "CheckBootstrapVersion": {
+ "Assertions": [
+ {
+ "Assert": {
+ "Fn::Not": [
+ {
+ "Fn::Contains": [
+ [
+ "1",
+ "2",
+ "3",
+ "4",
+ "5"
+ ],
+ {
+ "Ref": "BootstrapVersion"
+ }
+ ]
+ }
+ ]
+ },
+ "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/manifest.json
new file mode 100644
index 0000000000000..c6246f95e2ec1
--- /dev/null
+++ b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/manifest.json
@@ -0,0 +1,226 @@
+{
+ "version": "21.0.0",
+ "artifacts": {
+ "Tree": {
+ "type": "cdk:tree",
+ "properties": {
+ "file": "tree.json"
+ }
+ },
+ "integ-userdata.assets": {
+ "type": "cdk:asset-manifest",
+ "properties": {
+ "file": "integ-userdata.assets.json",
+ "requiresBootstrapStackVersion": 6,
+ "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version"
+ }
+ },
+ "integ-userdata": {
+ "type": "aws:cloudformation:stack",
+ "environment": "aws://unknown-account/unknown-region",
+ "properties": {
+ "templateFile": "integ-userdata.template.json",
+ "validateOnSynth": false,
+ "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}",
+ "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}",
+ "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9f2c5f7def4ad32c13627dff08f2be0273546384a8fe510e265cc6a7083274e1.json",
+ "requiresBootstrapStackVersion": 6,
+ "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
+ "additionalDependencies": [
+ "integ-userdata.assets"
+ ],
+ "lookupRole": {
+ "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}",
+ "requiresBootstrapStackVersion": 8,
+ "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version"
+ }
+ },
+ "dependencies": [
+ "integ-userdata.assets"
+ ],
+ "metadata": {
+ "/integ-userdata/IntegUserdataVpc/Resource": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcDE2938ED"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet1/Subnet": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet1Subnet9AE7FE85"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet1/RouteTable": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet1RouteTable7B342D96"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet1/RouteTableAssociation": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet1RouteTableAssociation724A6375"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet1/DefaultRoute": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet1DefaultRoute8F93CC39"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet1/EIP": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet1EIP41DE8CA6"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet1/NATGateway": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet1NATGatewayC9F60940"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet2/Subnet": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet2Subnet7EC040B5"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet2/RouteTable": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet2RouteTable98BA8E97"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet2/RouteTableAssociation": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet2RouteTableAssociationBA5DC07F"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet2/DefaultRoute": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet2DefaultRoute90FCB645"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet2/EIP": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet2EIP662D51E3"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PublicSubnet2/NATGateway": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPublicSubnet2NATGatewayB25F84D3"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PrivateSubnet1/Subnet": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPrivateSubnet1Subnet4EFBF430"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PrivateSubnet1/RouteTable": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPrivateSubnet1RouteTable63E39754"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PrivateSubnet1/RouteTableAssociation": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPrivateSubnet1RouteTableAssociation176A5EB9"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PrivateSubnet1/DefaultRoute": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPrivateSubnet1DefaultRoute03370EF2"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PrivateSubnet2/Subnet": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPrivateSubnet2SubnetAFD1E5B4"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PrivateSubnet2/RouteTable": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPrivateSubnet2RouteTable7944CD08"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PrivateSubnet2/RouteTableAssociation": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPrivateSubnet2RouteTableAssociation3B0C1389"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/PrivateSubnet2/DefaultRoute": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcPrivateSubnet2DefaultRouteA120F4F4"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/IGW": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcIGWB657C40E"
+ }
+ ],
+ "/integ-userdata/IntegUserdataVpc/VPCGW": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "IntegUserdataVpcVPCGWFA86AC6A"
+ }
+ ],
+ "/integ-userdata/WindowsInstance/InstanceSecurityGroup/Resource": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "WindowsInstanceInstanceSecurityGroup3B6692A8"
+ }
+ ],
+ "/integ-userdata/WindowsInstance/InstanceRole/Resource": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "WindowsInstanceInstanceRoleB7D73766"
+ }
+ ],
+ "/integ-userdata/WindowsInstance/InstanceProfile": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "WindowsInstanceInstanceProfile20441977"
+ }
+ ],
+ "/integ-userdata/WindowsInstance/Resource": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "WindowsInstance4ABA347A"
+ }
+ ],
+ "/integ-userdata/SsmParameterValue:--aws--service--ami-windows-latest--Windows_Server-2022-English-Full-Base:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "SsmParameterValueawsserviceamiwindowslatestWindowsServer2022EnglishFullBaseC96584B6F00A464EAD1953AFF4B05118Parameter"
+ }
+ ],
+ "/integ-userdata/BootstrapVersion": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "BootstrapVersion"
+ }
+ ],
+ "/integ-userdata/CheckBootstrapVersion": [
+ {
+ "type": "aws:cdk:logicalId",
+ "data": "CheckBootstrapVersion"
+ }
+ ]
+ },
+ "displayName": "integ-userdata"
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/tree.json b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/tree.json
new file mode 100644
index 0000000000000..b4e8cb0d210a0
--- /dev/null
+++ b/packages/@aws-cdk/aws-ec2/test/userdata.integ.snapshot/tree.json
@@ -0,0 +1,857 @@
+{
+ "version": "tree-0.1",
+ "tree": {
+ "id": "App",
+ "path": "",
+ "children": {
+ "Tree": {
+ "id": "Tree",
+ "path": "Tree",
+ "constructInfo": {
+ "fqn": "constructs.Construct",
+ "version": "10.1.108"
+ }
+ },
+ "integ-userdata": {
+ "id": "integ-userdata",
+ "path": "integ-userdata",
+ "children": {
+ "IntegUserdataVpc": {
+ "id": "IntegUserdataVpc",
+ "path": "integ-userdata/IntegUserdataVpc",
+ "children": {
+ "Resource": {
+ "id": "Resource",
+ "path": "integ-userdata/IntegUserdataVpc/Resource",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::VPC",
+ "aws:cdk:cloudformation:props": {
+ "cidrBlock": "10.0.0.0/16",
+ "enableDnsHostnames": true,
+ "enableDnsSupport": true,
+ "instanceTenancy": "default",
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnVPC",
+ "version": "0.0.0"
+ }
+ },
+ "PublicSubnet1": {
+ "id": "PublicSubnet1",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet1",
+ "children": {
+ "Subnet": {
+ "id": "Subnet",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet1/Subnet",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Subnet",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "availabilityZone": {
+ "Fn::Select": [
+ 0,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "cidrBlock": "10.0.0.0/18",
+ "mapPublicIpOnLaunch": true,
+ "tags": [
+ {
+ "key": "aws-cdk:subnet-name",
+ "value": "Public"
+ },
+ {
+ "key": "aws-cdk:subnet-type",
+ "value": "Public"
+ },
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PublicSubnet1"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSubnet",
+ "version": "0.0.0"
+ }
+ },
+ "Acl": {
+ "id": "Acl",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet1/Acl",
+ "constructInfo": {
+ "fqn": "@aws-cdk/core.Resource",
+ "version": "0.0.0"
+ }
+ },
+ "RouteTable": {
+ "id": "RouteTable",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet1/RouteTable",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PublicSubnet1"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnRouteTable",
+ "version": "0.0.0"
+ }
+ },
+ "RouteTableAssociation": {
+ "id": "RouteTableAssociation",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet1/RouteTableAssociation",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation",
+ "aws:cdk:cloudformation:props": {
+ "routeTableId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1RouteTable7B342D96"
+ },
+ "subnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1Subnet9AE7FE85"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation",
+ "version": "0.0.0"
+ }
+ },
+ "DefaultRoute": {
+ "id": "DefaultRoute",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet1/DefaultRoute",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Route",
+ "aws:cdk:cloudformation:props": {
+ "routeTableId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1RouteTable7B342D96"
+ },
+ "destinationCidrBlock": "0.0.0.0/0",
+ "gatewayId": {
+ "Ref": "IntegUserdataVpcIGWB657C40E"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnRoute",
+ "version": "0.0.0"
+ }
+ },
+ "EIP": {
+ "id": "EIP",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet1/EIP",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::EIP",
+ "aws:cdk:cloudformation:props": {
+ "domain": "vpc",
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PublicSubnet1"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnEIP",
+ "version": "0.0.0"
+ }
+ },
+ "NATGateway": {
+ "id": "NATGateway",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet1/NATGateway",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway",
+ "aws:cdk:cloudformation:props": {
+ "subnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1Subnet9AE7FE85"
+ },
+ "allocationId": {
+ "Fn::GetAtt": [
+ "IntegUserdataVpcPublicSubnet1EIP41DE8CA6",
+ "AllocationId"
+ ]
+ },
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PublicSubnet1"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnNatGateway",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.PublicSubnet",
+ "version": "0.0.0"
+ }
+ },
+ "PublicSubnet2": {
+ "id": "PublicSubnet2",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet2",
+ "children": {
+ "Subnet": {
+ "id": "Subnet",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet2/Subnet",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Subnet",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "availabilityZone": {
+ "Fn::Select": [
+ 1,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "cidrBlock": "10.0.64.0/18",
+ "mapPublicIpOnLaunch": true,
+ "tags": [
+ {
+ "key": "aws-cdk:subnet-name",
+ "value": "Public"
+ },
+ {
+ "key": "aws-cdk:subnet-type",
+ "value": "Public"
+ },
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PublicSubnet2"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSubnet",
+ "version": "0.0.0"
+ }
+ },
+ "Acl": {
+ "id": "Acl",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet2/Acl",
+ "constructInfo": {
+ "fqn": "@aws-cdk/core.Resource",
+ "version": "0.0.0"
+ }
+ },
+ "RouteTable": {
+ "id": "RouteTable",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet2/RouteTable",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PublicSubnet2"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnRouteTable",
+ "version": "0.0.0"
+ }
+ },
+ "RouteTableAssociation": {
+ "id": "RouteTableAssociation",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet2/RouteTableAssociation",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation",
+ "aws:cdk:cloudformation:props": {
+ "routeTableId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2RouteTable98BA8E97"
+ },
+ "subnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2Subnet7EC040B5"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation",
+ "version": "0.0.0"
+ }
+ },
+ "DefaultRoute": {
+ "id": "DefaultRoute",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet2/DefaultRoute",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Route",
+ "aws:cdk:cloudformation:props": {
+ "routeTableId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2RouteTable98BA8E97"
+ },
+ "destinationCidrBlock": "0.0.0.0/0",
+ "gatewayId": {
+ "Ref": "IntegUserdataVpcIGWB657C40E"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnRoute",
+ "version": "0.0.0"
+ }
+ },
+ "EIP": {
+ "id": "EIP",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet2/EIP",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::EIP",
+ "aws:cdk:cloudformation:props": {
+ "domain": "vpc",
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PublicSubnet2"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnEIP",
+ "version": "0.0.0"
+ }
+ },
+ "NATGateway": {
+ "id": "NATGateway",
+ "path": "integ-userdata/IntegUserdataVpc/PublicSubnet2/NATGateway",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway",
+ "aws:cdk:cloudformation:props": {
+ "subnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2Subnet7EC040B5"
+ },
+ "allocationId": {
+ "Fn::GetAtt": [
+ "IntegUserdataVpcPublicSubnet2EIP662D51E3",
+ "AllocationId"
+ ]
+ },
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PublicSubnet2"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnNatGateway",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.PublicSubnet",
+ "version": "0.0.0"
+ }
+ },
+ "PrivateSubnet1": {
+ "id": "PrivateSubnet1",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet1",
+ "children": {
+ "Subnet": {
+ "id": "Subnet",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet1/Subnet",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Subnet",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "availabilityZone": {
+ "Fn::Select": [
+ 0,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "cidrBlock": "10.0.128.0/18",
+ "mapPublicIpOnLaunch": false,
+ "tags": [
+ {
+ "key": "aws-cdk:subnet-name",
+ "value": "Private"
+ },
+ {
+ "key": "aws-cdk:subnet-type",
+ "value": "Private"
+ },
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PrivateSubnet1"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSubnet",
+ "version": "0.0.0"
+ }
+ },
+ "Acl": {
+ "id": "Acl",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet1/Acl",
+ "constructInfo": {
+ "fqn": "@aws-cdk/core.Resource",
+ "version": "0.0.0"
+ }
+ },
+ "RouteTable": {
+ "id": "RouteTable",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet1/RouteTable",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PrivateSubnet1"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnRouteTable",
+ "version": "0.0.0"
+ }
+ },
+ "RouteTableAssociation": {
+ "id": "RouteTableAssociation",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet1/RouteTableAssociation",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation",
+ "aws:cdk:cloudformation:props": {
+ "routeTableId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet1RouteTable63E39754"
+ },
+ "subnetId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet1Subnet4EFBF430"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation",
+ "version": "0.0.0"
+ }
+ },
+ "DefaultRoute": {
+ "id": "DefaultRoute",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet1/DefaultRoute",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Route",
+ "aws:cdk:cloudformation:props": {
+ "routeTableId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet1RouteTable63E39754"
+ },
+ "destinationCidrBlock": "0.0.0.0/0",
+ "natGatewayId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1NATGatewayC9F60940"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnRoute",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.PrivateSubnet",
+ "version": "0.0.0"
+ }
+ },
+ "PrivateSubnet2": {
+ "id": "PrivateSubnet2",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet2",
+ "children": {
+ "Subnet": {
+ "id": "Subnet",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet2/Subnet",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Subnet",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "availabilityZone": {
+ "Fn::Select": [
+ 1,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "cidrBlock": "10.0.192.0/18",
+ "mapPublicIpOnLaunch": false,
+ "tags": [
+ {
+ "key": "aws-cdk:subnet-name",
+ "value": "Private"
+ },
+ {
+ "key": "aws-cdk:subnet-type",
+ "value": "Private"
+ },
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PrivateSubnet2"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSubnet",
+ "version": "0.0.0"
+ }
+ },
+ "Acl": {
+ "id": "Acl",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet2/Acl",
+ "constructInfo": {
+ "fqn": "@aws-cdk/core.Resource",
+ "version": "0.0.0"
+ }
+ },
+ "RouteTable": {
+ "id": "RouteTable",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet2/RouteTable",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc/PrivateSubnet2"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnRouteTable",
+ "version": "0.0.0"
+ }
+ },
+ "RouteTableAssociation": {
+ "id": "RouteTableAssociation",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet2/RouteTableAssociation",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation",
+ "aws:cdk:cloudformation:props": {
+ "routeTableId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet2RouteTable7944CD08"
+ },
+ "subnetId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet2SubnetAFD1E5B4"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation",
+ "version": "0.0.0"
+ }
+ },
+ "DefaultRoute": {
+ "id": "DefaultRoute",
+ "path": "integ-userdata/IntegUserdataVpc/PrivateSubnet2/DefaultRoute",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Route",
+ "aws:cdk:cloudformation:props": {
+ "routeTableId": {
+ "Ref": "IntegUserdataVpcPrivateSubnet2RouteTable7944CD08"
+ },
+ "destinationCidrBlock": "0.0.0.0/0",
+ "natGatewayId": {
+ "Ref": "IntegUserdataVpcPublicSubnet2NATGatewayB25F84D3"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnRoute",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.PrivateSubnet",
+ "version": "0.0.0"
+ }
+ },
+ "IGW": {
+ "id": "IGW",
+ "path": "integ-userdata/IntegUserdataVpc/IGW",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway",
+ "aws:cdk:cloudformation:props": {
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/IntegUserdataVpc"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnInternetGateway",
+ "version": "0.0.0"
+ }
+ },
+ "VPCGW": {
+ "id": "VPCGW",
+ "path": "integ-userdata/IntegUserdataVpc/VPCGW",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment",
+ "aws:cdk:cloudformation:props": {
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ },
+ "internetGatewayId": {
+ "Ref": "IntegUserdataVpcIGWB657C40E"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnVPCGatewayAttachment",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.Vpc",
+ "version": "0.0.0"
+ }
+ },
+ "WindowsInstance": {
+ "id": "WindowsInstance",
+ "path": "integ-userdata/WindowsInstance",
+ "children": {
+ "InstanceSecurityGroup": {
+ "id": "InstanceSecurityGroup",
+ "path": "integ-userdata/WindowsInstance/InstanceSecurityGroup",
+ "children": {
+ "Resource": {
+ "id": "Resource",
+ "path": "integ-userdata/WindowsInstance/InstanceSecurityGroup/Resource",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup",
+ "aws:cdk:cloudformation:props": {
+ "groupDescription": "integ-userdata/WindowsInstance/InstanceSecurityGroup",
+ "securityGroupEgress": [
+ {
+ "cidrIp": "0.0.0.0/0",
+ "description": "Allow all outbound traffic by default",
+ "ipProtocol": "-1"
+ }
+ ],
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/WindowsInstance"
+ }
+ ],
+ "vpcId": {
+ "Ref": "IntegUserdataVpcDE2938ED"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.SecurityGroup",
+ "version": "0.0.0"
+ }
+ },
+ "InstanceRole": {
+ "id": "InstanceRole",
+ "path": "integ-userdata/WindowsInstance/InstanceRole",
+ "children": {
+ "Resource": {
+ "id": "Resource",
+ "path": "integ-userdata/WindowsInstance/InstanceRole/Resource",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::IAM::Role",
+ "aws:cdk:cloudformation:props": {
+ "assumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Action": "sts:AssumeRole",
+ "Effect": "Allow",
+ "Principal": {
+ "Service": {
+ "Fn::Join": [
+ "",
+ [
+ "ec2.",
+ {
+ "Ref": "AWS::URLSuffix"
+ }
+ ]
+ ]
+ }
+ }
+ }
+ ],
+ "Version": "2012-10-17"
+ },
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/WindowsInstance"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-iam.CfnRole",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-iam.Role",
+ "version": "0.0.0"
+ }
+ },
+ "InstanceProfile": {
+ "id": "InstanceProfile",
+ "path": "integ-userdata/WindowsInstance/InstanceProfile",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile",
+ "aws:cdk:cloudformation:props": {
+ "roles": [
+ {
+ "Ref": "WindowsInstanceInstanceRoleB7D73766"
+ }
+ ]
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-iam.CfnInstanceProfile",
+ "version": "0.0.0"
+ }
+ },
+ "Resource": {
+ "id": "Resource",
+ "path": "integ-userdata/WindowsInstance/Resource",
+ "attributes": {
+ "aws:cdk:cloudformation:type": "AWS::EC2::Instance",
+ "aws:cdk:cloudformation:props": {
+ "availabilityZone": {
+ "Fn::Select": [
+ 0,
+ {
+ "Fn::GetAZs": ""
+ }
+ ]
+ },
+ "iamInstanceProfile": {
+ "Ref": "WindowsInstanceInstanceProfile20441977"
+ },
+ "imageId": {
+ "Ref": "SsmParameterValueawsserviceamiwindowslatestWindowsServer2022EnglishFullBaseC96584B6F00A464EAD1953AFF4B05118Parameter"
+ },
+ "instanceType": "t2.micro",
+ "securityGroupIds": [
+ {
+ "Fn::GetAtt": [
+ "WindowsInstanceInstanceSecurityGroup3B6692A8",
+ "GroupId"
+ ]
+ }
+ ],
+ "subnetId": {
+ "Ref": "IntegUserdataVpcPublicSubnet1Subnet9AE7FE85"
+ },
+ "tags": [
+ {
+ "key": "Name",
+ "value": "integ-userdata/WindowsInstance"
+ }
+ ],
+ "userData": {
+ "Fn::Base64": "true"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.CfnInstance",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/aws-ec2.Instance",
+ "version": "0.0.0"
+ }
+ },
+ "SsmParameterValue:--aws--service--ami-windows-latest--Windows_Server-2022-English-Full-Base:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": {
+ "id": "SsmParameterValue:--aws--service--ami-windows-latest--Windows_Server-2022-English-Full-Base:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter",
+ "path": "integ-userdata/SsmParameterValue:--aws--service--ami-windows-latest--Windows_Server-2022-English-Full-Base:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter",
+ "constructInfo": {
+ "fqn": "@aws-cdk/core.CfnParameter",
+ "version": "0.0.0"
+ }
+ },
+ "SsmParameterValue:--aws--service--ami-windows-latest--Windows_Server-2022-English-Full-Base:C96584B6-F00A-464E-AD19-53AFF4B05118": {
+ "id": "SsmParameterValue:--aws--service--ami-windows-latest--Windows_Server-2022-English-Full-Base:C96584B6-F00A-464E-AD19-53AFF4B05118",
+ "path": "integ-userdata/SsmParameterValue:--aws--service--ami-windows-latest--Windows_Server-2022-English-Full-Base:C96584B6-F00A-464E-AD19-53AFF4B05118",
+ "constructInfo": {
+ "fqn": "@aws-cdk/core.Resource",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/core.Stack",
+ "version": "0.0.0"
+ }
+ }
+ },
+ "constructInfo": {
+ "fqn": "@aws-cdk/core.App",
+ "version": "0.0.0"
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/@aws-cdk/aws-ec2/test/userdata.test.ts b/packages/@aws-cdk/aws-ec2/test/userdata.test.ts
index fc877cbb2c7c9..4a29db3ea45c9 100644
--- a/packages/@aws-cdk/aws-ec2/test/userdata.test.ts
+++ b/packages/@aws-cdk/aws-ec2/test/userdata.test.ts
@@ -178,6 +178,14 @@ describe('user data', () => {
);
});
+ test('can persist windows userdata', () => {
+ // WHEN
+ const userData = ec2.UserData.forWindows({ persist: true });
+
+ // THEN
+ const rendered = userData.render();
+ expect(rendered).toEqual('true');
+ });
test('can create Linux user data', () => {
// GIVEN