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

Commit

Permalink
feat: add option for creating nat via fck-nat
Browse files Browse the repository at this point in the history
  • Loading branch information
mwillbanks committed Oct 23, 2023
1 parent eac5364 commit 3af1088
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 9 deletions.
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
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

0 comments on commit 3af1088

Please sign in to comment.