Skip to content
This repository has been archived by the owner on Dec 20, 2023. It is now read-only.

Provide option for using non-deprecated amazon instances with fck-nat #1195

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ custom:

# Whether to create a NAT instance
createNatInstance: false
# When enabled with the above, it will utilize the
# [fck-nat](https://fck-nat.dev/) AMI vs. the Amazon AMI's with arm64
# t4g.nano instances
createNatInstanceFckNat: false

# Whether to create AWS Systems Manager (SSM) Parameters
createParameters: false
Expand Down
2 changes: 1 addition & 1 deletion __tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ describe('ServerlessVpcPlugin', () => {

mockHelper('EC2', 'describeImages', mockCallback);

const actual = await plugin.getImagesByName('test');
const actual = await plugin.getImagesByName('test', 'test', 'test');
expect(actual).toEqual(['ami-test']);
expect(mockCallback).toHaveBeenCalled();
expect.assertions(3);
Expand Down
63 changes: 62 additions & 1 deletion __tests__/nat_instance.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,68 @@ describe('nat_instance', () => {

const imageId = 'ami-00a9d4a05375b2763';

const actual = buildNatInstance(imageId, ['us-east-1a', 'us-east-1b']);
const actual = buildNatInstance(imageId, 't2.micro', ['us-east-1a', 'us-east-1b']);
expect(actual).toEqual(expected);
expect.assertions(1);
});
});

describe('#buildNatInstance createNatInstanceFckNat', () => {
it('builds an EC2 instance', () => {
const expected = {
NatInstance: {
Type: 'AWS::EC2::Instance',
DependsOn: 'InternetGatewayAttachment',
Properties: {
AvailabilityZone: {
'Fn::Select': ['0', ['us-east-1a', 'us-east-1b']],
},
BlockDeviceMappings: [
{
DeviceName: '/dev/xvda',
Ebs: {
VolumeSize: 10,
VolumeType: 'gp2',
DeleteOnTermination: true,
},
},
],
ImageId: 'ami-0d30a34832b46dcae',
InstanceType: 't4g.nano',
Monitoring: false,
NetworkInterfaces: [
{
AssociatePublicIpAddress: true,
DeleteOnTermination: true,
Description: 'eth0',
DeviceIndex: '0',
GroupSet: [
{
Ref: 'NatSecurityGroup',
},
],
SubnetId: {
Ref: 'PublicSubnet1',
},
},
],
SourceDestCheck: false,
Tags: [
{
Key: 'Name',
Value: {
// eslint-disable-next-line no-template-curly-in-string
'Fn::Sub': '${AWS::StackName}-nat',
},
},
],
},
},
};

const imageId = 'ami-0d30a34832b46dcae';

const actual = buildNatInstance(imageId, 't4g.nano', ['us-east-1a', 'us-east-1b']);
expect(actual).toEqual(expected);
expect.assertions(1);
});
Expand Down
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@
},
"devDependencies": {
"aws-sdk-mock": "5.8.0",
"eslint": "8.51.0",
"eslint": "^8.51.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "8.8.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-jest": "27.2.3",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jest": "^27.2.3",
"eslint-plugin-prettier": "5.0.1",
"jest": "29.6.2",
"nock": "13.3.4",
"prettier": "3.0.1",
"serverless": "3.34.0"
"jest": "^29.6.2",
"nock": "^13.3.4",
"prettier": "^3.0.1",
"serverless": "^3.34.0"
}
}
28 changes: 23 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ServerlessVpcPlugin {
let createDbSubnet = true;
let createFlowLogs = false;
let createNatInstance = false;
let createNatInstanceFckNat = false;
let createBastionHost = false;
let createParameters = false;
let bastionHostKeyName = null;
Expand Down Expand Up @@ -103,6 +104,12 @@ class ServerlessVpcPlugin {

if ('createNatInstance' in vpcConfig && typeof vpcConfig.createNatInstance === 'boolean') {
({ createNatInstance } = vpcConfig);
if (
'createNatInstanceFckNat' in vpcConfig &&
typeof vpcConfig.createNatInstanceFckNat === 'boolean'
) {
({ createNatInstanceFckNat } = vpcConfig);
}
}

if (createNatGateway && createNatInstance) {
Expand Down Expand Up @@ -162,10 +169,15 @@ class ServerlessVpcPlugin {
const resources = providerObj.compiledCloudFormationTemplate.Resources;

let vpcNatAmi = null;
let instanceType = null;
if (createNatInstance) {
this.serverless.cli.log('Finding latest VPC NAT Instance AMI...');

const images = await this.getImagesByName('amzn-ami-vpc-nat*');
instanceType = createNatInstanceFckNat ? 't4g.nano' : 't2.micro';
const images = createNatInstanceFckNat
? await this.getImagesByName('568608671756', 'fck-nat-amzn2-*', 'arm64')
: await this.getImagesByName('amazon', 'amzn-ami-vpc-nat*', 'x86_64');

if (Array.isArray(images) && images.length > 0) {
[vpcNatAmi] = images;
} else {
Expand Down Expand Up @@ -204,7 +216,11 @@ class ServerlessVpcPlugin {

if (createNatInstance && vpcNatAmi) {
this.serverless.cli.log(`Provisioning NAT Instance using AMI ${vpcNatAmi}`);
Object.assign(resources, buildNatSecurityGroup(), buildNatInstance(vpcNatAmi, zones));
Object.assign(
resources,
buildNatSecurityGroup(),
buildNatInstance(vpcNatAmi, instanceType, zones),
);
}

if (createBastionHost) {
Expand Down Expand Up @@ -374,16 +390,18 @@ class ServerlessVpcPlugin {
/**
* Return an array of AMI images which match the VPC NAT Instance image
*
* @param {String} owner AMI id to search for
* @param {String} name AMI name to search for
* @param {String} arch AMI architecture to search for
* @return {Array}
*/
async getImagesByName(name) {
async getImagesByName(owner, name, arch) {
const params = {
Owners: ['amazon'],
Owners: [owner],
Filters: [
{
Name: 'architecture',
Values: ['x86_64'],
Values: [arch],
},
{
Name: 'image-type',
Expand Down
5 changes: 3 additions & 2 deletions src/nat_instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,12 @@ function buildNatSecurityGroup() {
* Build the NAT instance
*
* @param {Object} imageId AMI image ID
* @param {String} instance type
* @param {Array} zones Array of availability zones
* @param {Object} params
* @return {Object}
*/
function buildNatInstance(imageId, zones = [], { name = 'NatInstance' } = {}) {
function buildNatInstance(imageId, instanceType, zones = [], { name = 'NatInstance' } = {}) {
if (!imageId) {
return {};
}
Expand All @@ -99,7 +100,7 @@ function buildNatInstance(imageId, zones = [], { name = 'NatInstance' } = {}) {
},
],
ImageId: imageId, // amzn-ami-vpc-nat-hvm-2018.03.0.20181116-x86_64-ebs
InstanceType: 't2.micro',
InstanceType: instanceType,
Monitoring: false,
NetworkInterfaces: [
{
Expand Down
Loading