From 51b2014234089ee7442362effaa9a7437d0a9f61 Mon Sep 17 00:00:00 2001 From: Peter Nied Date: Wed, 20 Nov 2024 14:26:06 -0600 Subject: [PATCH] Hardcode AMIs for use in the bootstrap machine (#1153) * With the current latest AL2023 image al2023-ami-2023.6.20241111.0-kernel-6.1-x86_64 npm install hangs indefinately. We are switching back to an older version that works and providing a way to incrementially update to AMIs that we have tested. * Add govcloud images * Update to 2023.6.20241031 source Signed-off-by: Peter Nied --- .../migration-assistant-solution/README.md | 4 ++ .../create-ami-map.sh | 38 ++++++++++++++++ .../lib/solutions-stack.ts | 43 ++++++++++++------- .../test/solutions-stack.test.ts | 10 ++++- 4 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 deployment/migration-assistant-solution/create-ami-map.sh diff --git a/deployment/migration-assistant-solution/README.md b/deployment/migration-assistant-solution/README.md index bad9fb666..12c044e30 100644 --- a/deployment/migration-assistant-solution/README.md +++ b/deployment/migration-assistant-solution/README.md @@ -36,6 +36,10 @@ The full range of functionality offered by the migration assistant deployed thro This project is writen in TypeScript and uses the cloud developer tookit (CDK) to produce its build artifacts, cloud formation templates that can be used to deploy onto Amazon Web Services. +### Hardcoded AMIs + +While using EC2 we have run into issues with AMI's being released that broken our functionality so we are hardcoding all AMIs to ensure the solution will work. Setup your AWS credentials in the command line and run the script `create-ami-map.sh` in this directory to find the matching AMI in all regions, then update the map inside the solutions stack, [ref](./create-ami-map.sh). + ### Quick Start Guide * Install Node 18+ & Npm 10+ https://docs.npmjs.com/downloading-and-installing-node-js-and-npm diff --git a/deployment/migration-assistant-solution/create-ami-map.sh b/deployment/migration-assistant-solution/create-ami-map.sh new file mode 100644 index 000000000..ea001d9cc --- /dev/null +++ b/deployment/migration-assistant-solution/create-ami-map.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# AMI name to look up +AMI_NAME="al2023-ami-2023.6.20241031.0-kernel-6.1-x86_64" +OWNER="amazon" + +# Get the list of all available AWS regions +REGIONS=$(aws ec2 describe-regions --query "Regions[].RegionName" --output text) + +declare -A amiMap + +echo "Looking up AMI IDs for '$AMI_NAME' owned by '$OWNER' in all regions..." + +for region in $REGIONS; do + echo "Searching in region: $region" + ami_id=$(aws ec2 describe-images \ + --region $region \ + --owners $OWNER \ + --filters "Name=name,Values=$AMI_NAME" \ + --query "Images[0].ImageId" \ + --output text) + + if [ "$ami_id" != "None" ]; then + amiMap[$region]=$ami_id + echo "Found AMI ID: $ami_id in region $region" + else + echo "No AMI found in region $region" + fi +done + +# Generate the AMI map as typescript +echo "" +echo "AMI Map:" +echo "const amiMap = {" +for region in "${!amiMap[@]}"; do + echo " '$region': '${amiMap[$region]}'," +done +echo "};" diff --git a/deployment/migration-assistant-solution/lib/solutions-stack.ts b/deployment/migration-assistant-solution/lib/solutions-stack.ts index 5ef3ed83d..1ef51f550 100644 --- a/deployment/migration-assistant-solution/lib/solutions-stack.ts +++ b/deployment/migration-assistant-solution/lib/solutions-stack.ts @@ -11,6 +11,7 @@ import {Construct} from 'constructs'; import { BlockDeviceVolume, CloudFormationInit, + GenericLinuxImage, InitCommand, InitElement, InitFile, @@ -18,7 +19,6 @@ import { InstanceClass, InstanceSize, InstanceType, - MachineImage, Vpc } from "aws-cdk-lib/aws-ec2"; import {InstanceProfile, ManagedPolicy, Role, ServicePrincipal} from "aws-cdk-lib/aws-iam"; @@ -201,6 +201,31 @@ export class SolutionsInfrastructureStack extends Stack { }), ] + // Generated with ../create-ami-map.sh + const amiMap: Record = { + 'us-east-2': 'ami-0fae88c1e6794aa17', + 'us-east-1': 'ami-063d43db0594b521b', + 'us-west-1': 'ami-05c65d8bb2e35991a', + 'us-west-2': 'ami-066a7fbea5161f451', + 'ca-central-1': 'ami-0d13170a36bc1b384', + 'ap-south-1': 'ami-08bf489a05e916bbd', + 'sa-east-1': 'ami-065c72b3f381dab73', + 'eu-north-1': 'ami-04b54ebf295fe01d7', + 'ap-northeast-1': 'ami-08ce76bae392de7dc', + 'ap-northeast-2': 'ami-03d31e4041396b53c', + 'ap-northeast-3': 'ami-0403e868508046e73', + 'eu-central-1': 'ami-0eddb4a4e7d846d6f', + 'eu-west-2': 'ami-02f617729751b375a', + 'eu-west-3': 'ami-0db5e28c1b3823bb7', + 'eu-west-1': 'ami-03ca36368dbc9cfa1', + 'ap-southeast-2': 'ami-037a2314eeca55594', + 'ap-southeast-1': 'ami-08f49baa317796afd', + }; + + // Manually looked up with https://us-gov-east-1.console.amazonaws-us-gov.com/ec2/home?region=us-gov-east-1#AMICatalog: + amiMap['us-gov-west-1'] = 'ami-0e46a6a8d36d6f1f2'; + amiMap['us-gov-east-1'] = 'ami-0016d10ace091da71'; + new Instance(this, 'BootstrapEC2Instance', { vpc: vpc, vpcSubnets: { @@ -208,7 +233,7 @@ export class SolutionsInfrastructureStack extends Stack { }, instanceName: `bootstrap-instance-${stackMarker}`, instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.LARGE), - machineImage: MachineImage.latestAmazonLinux2023(), + machineImage: new GenericLinuxImage(amiMap), role: bootstrapRole, blockDevices: [ { @@ -222,16 +247,6 @@ export class SolutionsInfrastructureStack extends Stack { }, }); - const dynamicEc2ImageParameter = this.node.findAll() - .filter(c => c instanceof CfnParameter) - .filter(c => (c as CfnParameter).type === "AWS::SSM::Parameter::Value") - .pop() as CfnParameter; - if (dynamicEc2ImageParameter) { - dynamicEc2ImageParameter.description = "Latest Amazon Linux Image Id for the build machine"; - dynamicEc2ImageParameter.overrideLogicalId("LastedAmazonLinuxImageId"); - dynamicEc2ImageParameter.noEcho = true; - } - const parameterGroups = []; if (importedVPCParameters.length > 0) { parameterGroups.push({ @@ -243,10 +258,6 @@ export class SolutionsInfrastructureStack extends Stack { Label: { default: "Additional parameters" }, Parameters: additionalParameters }); - parameterGroups.push({ - Label: { default: "System parameters" }, - Parameters: [dynamicEc2ImageParameter?.logicalId] - }); this.templateOptions.metadata = { 'AWS::CloudFormation::Interface': { diff --git a/deployment/migration-assistant-solution/test/solutions-stack.test.ts b/deployment/migration-assistant-solution/test/solutions-stack.test.ts index 60001911f..e14594e83 100644 --- a/deployment/migration-assistant-solution/test/solutions-stack.test.ts +++ b/deployment/migration-assistant-solution/test/solutions-stack.test.ts @@ -11,7 +11,10 @@ describe('Solutions stack', () => { solutionName: 'test-solution', solutionVersion: '0.0.1', codeBucket: 'test-bucket', - createVPC: true + createVPC: true, + env: { + region: 'us-west-1' + } }); const template = Template.fromStack(stack); template.resourceCountIs('AWS::EC2::VPC', 1) @@ -27,7 +30,10 @@ describe('Solutions stack', () => { solutionName: 'test-solution', solutionVersion: '0.0.1', codeBucket: 'test-bucket', - createVPC: false + createVPC: false, + env: { + region: 'us-west-1' + } }); const template = Template.fromStack(stack); template.resourceCountIs('AWS::EC2::VPC', 0)