serverless-vpc-discovery 5.0.2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.mocharc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "require": ["tsx"],
3
+ "extensions": ["ts"],
4
+ "spec": ["test/unit-tests/**/*.test.ts"]
5
+ }
package/README.md CHANGED
@@ -183,10 +183,11 @@ All tests should pass.
183
183
  To run integration tests, set an environment variable TEST\_VPC\_NAME to the VPC you will be testing for. Then,
184
184
 
185
185
  ```
186
+ export SERVERLESS_LICENSE_KEY=<license_key>
186
187
  export AWS_PROFILE=your_profile
187
188
  export TEST_VPC_NAME=vpc_name
188
- npm run build
189
- npm run integration-test
189
+ npx npm run build
190
+ npx npm run integration-test
190
191
  ```
191
192
 
192
193
  If there is an error build and install the node\_module inside the serverless-vpc-discovery folder:
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -17,6 +8,7 @@ const utils_1 = require("../utils");
17
8
  const client_ec2_1 = require("@aws-sdk/client-ec2");
18
9
  const globals_1 = __importDefault(require("../globals"));
19
10
  class EC2Wrapper {
11
+ ec2;
20
12
  constructor(credentials) {
21
13
  this.ec2 = new client_ec2_1.EC2Client({
22
14
  credentials,
@@ -28,29 +20,25 @@ class EC2Wrapper {
28
20
  * Returns the promise that contains the vpc list
29
21
  * @returns {Promise.<Vpc[]>}
30
22
  */
31
- getVpcs() {
32
- return __awaiter(this, void 0, void 0, function* () {
33
- return yield (0, utils_1.getAWSPagedResults)(this.ec2, "Vpcs", "NextToken", "NextToken", new client_ec2_1.DescribeVpcsCommand({}));
34
- });
23
+ async getVpcs() {
24
+ return await (0, utils_1.getAWSPagedResults)(this.ec2, "Vpcs", "NextToken", "NextToken", new client_ec2_1.DescribeVpcsCommand({}));
35
25
  }
36
26
  /**
37
27
  * Returns the promise that contains the vpc-id
38
28
  * @param {string} vpcName
39
29
  * @returns {Promise.<string>}
40
30
  */
41
- getVpcId(vpcName) {
42
- return __awaiter(this, void 0, void 0, function* () {
43
- const vpcItems = yield (0, utils_1.getAWSPagedResults)(this.ec2, "Vpcs", "NextToken", "NextToken", new client_ec2_1.DescribeVpcsCommand({
44
- Filters: [{
45
- Name: "tag:Name",
46
- Values: [vpcName]
47
- }]
48
- }));
49
- if (vpcItems.length === 0) {
50
- throw new Error(`VPC with tag key 'Name' and tag value '${vpcName}' does not exist.`);
51
- }
52
- return vpcItems[0].VpcId;
53
- });
31
+ async getVpcId(vpcName) {
32
+ const vpcItems = await (0, utils_1.getAWSPagedResults)(this.ec2, "Vpcs", "NextToken", "NextToken", new client_ec2_1.DescribeVpcsCommand({
33
+ Filters: [{
34
+ Name: "tag:Name",
35
+ Values: [vpcName]
36
+ }]
37
+ }));
38
+ if (vpcItems.length === 0) {
39
+ throw new Error(`VPC with tag key 'Name' and tag value '${vpcName}' does not exist.`);
40
+ }
41
+ return vpcItems[0].VpcId;
54
42
  }
55
43
  /**
56
44
  * Returns the promise that contains the subnet IDs
@@ -60,30 +48,28 @@ class EC2Wrapper {
60
48
  * @param {string[]} tagValues
61
49
  * @returns {Promise.<string[]>}
62
50
  */
63
- getSubnetIds(vpcId, tagKey, tagValues) {
64
- return __awaiter(this, void 0, void 0, function* () {
65
- const subnets = yield (0, utils_1.getAWSPagedResults)(this.ec2, "Subnets", "NextToken", "NextToken", new client_ec2_1.DescribeSubnetsCommand({
66
- Filters: [{
67
- Name: "vpc-id",
68
- Values: [vpcId]
69
- }, {
70
- Name: `tag:${tagKey}`,
71
- Values: tagValues
72
- }]
73
- }));
74
- const missingSubnetValues = tagValues.filter((tagValue) => {
75
- // collect subnets by name
76
- const subnetsByName = subnets.filter((subnet) => {
77
- return (0, utils_1.wildcardMatches)(tagValue, (0, utils_1.getValueFromTags)(subnet.Tags, tagKey));
78
- });
79
- return subnetsByName.length === 0;
51
+ async getSubnetIds(vpcId, tagKey, tagValues) {
52
+ const subnets = await (0, utils_1.getAWSPagedResults)(this.ec2, "Subnets", "NextToken", "NextToken", new client_ec2_1.DescribeSubnetsCommand({
53
+ Filters: [{
54
+ Name: "vpc-id",
55
+ Values: [vpcId]
56
+ }, {
57
+ Name: `tag:${tagKey}`,
58
+ Values: tagValues
59
+ }]
60
+ }));
61
+ const missingSubnetValues = tagValues.filter((tagValue) => {
62
+ // collect subnets by name
63
+ const subnetsByName = subnets.filter((subnet) => {
64
+ return (0, utils_1.wildcardMatches)(tagValue, (0, utils_1.getValueFromTags)(subnet.Tags, tagKey));
80
65
  });
81
- if (!subnets.length || missingSubnetValues.length) {
82
- throw new Error(`Subnets with vpc id '${vpcId}', tag key '${tagKey}' and tag values '${missingSubnetValues}' do not exist. ` +
83
- "Please check the `tagKey` and `tagValues` are correct or remove it.");
84
- }
85
- return subnets.map((subnet) => subnet.SubnetId);
66
+ return subnetsByName.length === 0;
86
67
  });
68
+ if (!subnets.length || missingSubnetValues.length) {
69
+ throw new Error(`Subnets with vpc id '${vpcId}', tag key '${tagKey}' and tag values '${missingSubnetValues}' do not exist. ` +
70
+ "Please check the `tagKey` and `tagValues` are correct or remove it.");
71
+ }
72
+ return subnets.map((subnet) => subnet.SubnetId);
87
73
  }
88
74
  /**
89
75
  * Returns the promise that contains the security group IDs
@@ -93,54 +79,52 @@ class EC2Wrapper {
93
79
  * @param {string[]} tagValues
94
80
  * @returns {Promise.<string[]>}
95
81
  */
96
- getSecurityGroupIds(vpcId, names, tagKey, tagValues) {
97
- return __awaiter(this, void 0, void 0, function* () {
98
- // init filter by vpc id
99
- const input = { Filters: [{ Name: "vpc-id", Values: [vpcId] }] };
100
- // update filters with names if specified
101
- if (names) {
102
- input.Filters.push({ Name: "group-name", Values: names });
103
- }
104
- // update filters with tag and values if specified
105
- if (tagKey && tagValues) {
106
- input.Filters.push({ Name: `tag:${tagKey}`, Values: tagValues });
107
- }
108
- const securityGroups = yield (0, utils_1.getAWSPagedResults)(this.ec2, "SecurityGroups", "NextToken", "NextToken", new client_ec2_1.DescribeSecurityGroupsCommand(input));
109
- if (securityGroups.length === 0) {
110
- const namesErrorText = names ? `, names '${names}'` : "";
111
- const tagErrorText = tagKey && tagValues ? `, tag key '${tagKey}' and tag values '${tagValues}'` : "";
112
- throw new Error(`Security groups with vpc id '${vpcId}'${namesErrorText}${tagErrorText} do not exist`);
113
- }
114
- if (names) {
115
- const missingGroupsNames = names.filter((groupName) => {
116
- // collect security groups by name
117
- const securityGroupsByName = securityGroups.filter((securityGroup) => {
118
- return (0, utils_1.wildcardMatches)(groupName, securityGroup.GroupName);
119
- });
120
- return securityGroupsByName.length === 0;
82
+ async getSecurityGroupIds(vpcId, names, tagKey, tagValues) {
83
+ // init filter by vpc id
84
+ const input = { Filters: [{ Name: "vpc-id", Values: [vpcId] }] };
85
+ // update filters with names if specified
86
+ if (names) {
87
+ input.Filters.push({ Name: "group-name", Values: names });
88
+ }
89
+ // update filters with tag and values if specified
90
+ if (tagKey && tagValues) {
91
+ input.Filters.push({ Name: `tag:${tagKey}`, Values: tagValues });
92
+ }
93
+ const securityGroups = await (0, utils_1.getAWSPagedResults)(this.ec2, "SecurityGroups", "NextToken", "NextToken", new client_ec2_1.DescribeSecurityGroupsCommand(input));
94
+ if (securityGroups.length === 0) {
95
+ const namesErrorText = names ? `, names '${names}'` : "";
96
+ const tagErrorText = tagKey && tagValues ? `, tag key '${tagKey}' and tag values '${tagValues}'` : "";
97
+ throw new Error(`Security groups with vpc id '${vpcId}'${namesErrorText}${tagErrorText} do not exist`);
98
+ }
99
+ if (names) {
100
+ const missingGroupsNames = names.filter((groupName) => {
101
+ // collect security groups by name
102
+ const securityGroupsByName = securityGroups.filter((securityGroup) => {
103
+ return (0, utils_1.wildcardMatches)(groupName, securityGroup.GroupName);
121
104
  });
122
- if (missingGroupsNames.length) {
123
- throw new Error(`Security groups do not exist for the names: ${missingGroupsNames}. ` +
124
- "Please check the 'names' are correct or remove it.");
125
- }
105
+ return securityGroupsByName.length === 0;
106
+ });
107
+ if (missingGroupsNames.length) {
108
+ throw new Error(`Security groups do not exist for the names: ${missingGroupsNames}. ` +
109
+ "Please check the 'names' are correct or remove it.");
126
110
  }
127
- if (tagKey && tagValues) {
128
- tagValues = tagValues || [];
129
- const missingGroupsTagNames = tagValues.filter((tagValue) => {
130
- // collect subnets by name
131
- const groupsByName = securityGroups.filter((securityGroup) => {
132
- const groupTagValue = (0, utils_1.getValueFromTags)(securityGroup.Tags, tagKey);
133
- return groupTagValue === tagValue;
134
- });
135
- return groupsByName.length === 0;
111
+ }
112
+ if (tagKey && tagValues) {
113
+ tagValues = tagValues || [];
114
+ const missingGroupsTagNames = tagValues.filter((tagValue) => {
115
+ // collect subnets by name
116
+ const groupsByName = securityGroups.filter((securityGroup) => {
117
+ const groupTagValue = (0, utils_1.getValueFromTags)(securityGroup.Tags, tagKey);
118
+ return groupTagValue === tagValue;
136
119
  });
137
- if (missingGroupsTagNames.length) {
138
- throw new Error(`Security groups do not exist for the tag '${tagKey}' and tag values: '${missingGroupsTagNames}'. ` +
139
- "Please check the 'tagKey' and 'tagValues' are correct or remove it.");
140
- }
120
+ return groupsByName.length === 0;
121
+ });
122
+ if (missingGroupsTagNames.length) {
123
+ throw new Error(`Security groups do not exist for the tag '${tagKey}' and tag values: '${missingGroupsTagNames}'. ` +
124
+ "Please check the 'tagKey' and 'tagValues' are correct or remove it.");
141
125
  }
142
- return securityGroups.map((group) => group.GroupId);
143
- });
126
+ }
127
+ return securityGroups.map((group) => group.GroupId);
144
128
  }
145
129
  }
146
130
  exports.EC2Wrapper = EC2Wrapper;
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -19,10 +10,12 @@ const validation_1 = require("../validation");
19
10
  const logging_1 = __importDefault(require("../logging"));
20
11
  const ts_md5_1 = require("ts-md5");
21
12
  class LambdaFunction {
13
+ ec2Wrapper;
14
+ basicVPCDiscovery;
15
+ vpcIdsCache = {};
16
+ subnetsIdsCache = {};
17
+ SGIdsCache = {};
22
18
  constructor(credentials, basicVPCDiscovery) {
23
- this.vpcIdsCache = {};
24
- this.subnetsIdsCache = {};
25
- this.SGIdsCache = {};
26
19
  this.ec2Wrapper = new ec2_wrapper_1.EC2Wrapper(credentials);
27
20
  this.basicVPCDiscovery = basicVPCDiscovery;
28
21
  }
@@ -30,105 +23,95 @@ class LambdaFunction {
30
23
  * Validate and return VPC config for the given function
31
24
  * @returns {Promise<VPC>}
32
25
  */
33
- getFuncVPC(funcName, funcVPCDiscovery) {
34
- return __awaiter(this, void 0, void 0, function* () {
35
- if (typeof funcVPCDiscovery === "boolean" && !funcVPCDiscovery) {
36
- // skip vpc setup for `vpcDiscovery=false` option
37
- logging_1.default.logInfo(`Skipping VPC config for the function '${funcName}'`);
38
- return null;
39
- }
40
- // inherit the `custom.vpcDiscovery`
41
- const vpcDiscovery = Object.assign({}, this.basicVPCDiscovery, funcVPCDiscovery);
42
- // return null in case vpcDiscovery not setup
43
- if ((0, utils_1.isObjectEmpty)(vpcDiscovery)) {
44
- return null;
45
- }
46
- // validate func vpcDiscovery config
47
- try {
48
- (0, validation_1.validateVPCDiscoveryConfig)(vpcDiscovery);
49
- }
50
- catch (e) {
51
- throw new Error(`Function '${funcName}' is not configured correctly: ${e} VPC not configured. ` +
52
- "Please see the README for the proper setup.");
53
- }
54
- try {
55
- logging_1.default.logInfo(`Getting VPC config for the function: '${funcName}'\n`);
56
- return yield this.getVpcConfig(vpcDiscovery);
57
- }
58
- catch (e) {
59
- logging_1.default.logError(`Function '${funcName}' VPC not configured based on the error: ${e}`);
60
- }
26
+ async getFuncVPC(funcName, funcVPCDiscovery) {
27
+ if (typeof funcVPCDiscovery === "boolean" && !funcVPCDiscovery) {
28
+ // skip vpc setup for `vpcDiscovery=false` option
29
+ logging_1.default.logInfo(`Skipping VPC config for the function '${funcName}'`);
30
+ return null;
31
+ }
32
+ // inherit the `custom.vpcDiscovery`
33
+ const vpcDiscovery = Object.assign({}, this.basicVPCDiscovery, funcVPCDiscovery);
34
+ // return null in case vpcDiscovery not setup
35
+ if ((0, utils_1.isObjectEmpty)(vpcDiscovery)) {
61
36
  return null;
62
- });
37
+ }
38
+ // validate func vpcDiscovery config
39
+ try {
40
+ (0, validation_1.validateVPCDiscoveryConfig)(vpcDiscovery);
41
+ }
42
+ catch (e) {
43
+ throw new Error(`Function '${funcName}' is not configured correctly: ${e} VPC not configured. ` +
44
+ "Please see the README for the proper setup.");
45
+ }
46
+ try {
47
+ logging_1.default.logInfo(`Getting VPC config for the function: '${funcName}'\n`);
48
+ return await this.getVpcConfig(vpcDiscovery);
49
+ }
50
+ catch (e) {
51
+ logging_1.default.logError(`Function '${funcName}' VPC not configured based on the error: ${e}`);
52
+ }
53
+ return null;
63
54
  }
64
55
  /**
65
56
  * Gets the desired vpc with the designated subnets and security groups
66
57
  * that were set in serverless config file
67
58
  * @returns {Promise<object>}
68
59
  */
69
- getVpcConfig(vpcDiscovery) {
70
- return __awaiter(this, void 0, void 0, function* () {
71
- const vpc = {};
72
- const vpcId = yield this.getVPCId(vpcDiscovery.vpcName);
73
- logging_1.default.logInfo(`Found VPC with id '${vpcId}'`);
74
- if (vpcDiscovery.subnets) {
75
- vpc.subnetIds = [];
76
- for (const subnet of vpcDiscovery.subnets) {
77
- const subnetIds = yield this.getVPCSubnets(vpcId, subnet.tagKey, subnet.tagValues);
78
- vpc.subnetIds = vpc.subnetIds.concat(subnetIds);
79
- }
80
- // remove duplicate elements from the array
81
- vpc.subnetIds = [...new Set(vpc.subnetIds)];
60
+ async getVpcConfig(vpcDiscovery) {
61
+ const vpc = {};
62
+ const vpcId = await this.getVPCId(vpcDiscovery.vpcName);
63
+ logging_1.default.logInfo(`Found VPC with id '${vpcId}'`);
64
+ if (vpcDiscovery.subnets) {
65
+ vpc.subnetIds = [];
66
+ for (const subnet of vpcDiscovery.subnets) {
67
+ const subnetIds = await this.getVPCSubnets(vpcId, subnet.tagKey, subnet.tagValues);
68
+ vpc.subnetIds = vpc.subnetIds.concat(subnetIds);
82
69
  }
83
- if (vpcDiscovery.securityGroups) {
84
- vpc.securityGroupIds = [];
85
- for (const group of vpcDiscovery.securityGroups) {
86
- const groupIds = yield this.getVPCSecurityGroups(vpcId, group.names, group.tagKey, group.tagValues);
87
- vpc.securityGroupIds = vpc.securityGroupIds.concat(groupIds);
88
- }
89
- // remove duplicate elements from the array
90
- vpc.securityGroupIds = [...new Set(vpc.securityGroupIds)];
70
+ // remove duplicate elements from the array
71
+ vpc.subnetIds = [...new Set(vpc.subnetIds)];
72
+ }
73
+ if (vpcDiscovery.securityGroups) {
74
+ vpc.securityGroupIds = [];
75
+ for (const group of vpcDiscovery.securityGroups) {
76
+ const groupIds = await this.getVPCSecurityGroups(vpcId, group.names, group.tagKey, group.tagValues);
77
+ vpc.securityGroupIds = vpc.securityGroupIds.concat(groupIds);
91
78
  }
92
- return vpc;
93
- });
79
+ // remove duplicate elements from the array
80
+ vpc.securityGroupIds = [...new Set(vpc.securityGroupIds)];
81
+ }
82
+ return vpc;
94
83
  }
95
84
  /**
96
85
  * Get the VPC id from cache or read from AWS
97
86
  * @returns {Promise<object>}
98
87
  */
99
- getVPCId(vpcName) {
100
- return __awaiter(this, void 0, void 0, function* () {
101
- if (this.vpcIdsCache[vpcName] === undefined) {
102
- this.vpcIdsCache[vpcName] = yield this.ec2Wrapper.getVpcId(vpcName);
103
- }
104
- return this.vpcIdsCache[vpcName];
105
- });
88
+ async getVPCId(vpcName) {
89
+ if (this.vpcIdsCache[vpcName] === undefined) {
90
+ this.vpcIdsCache[vpcName] = await this.ec2Wrapper.getVpcId(vpcName);
91
+ }
92
+ return this.vpcIdsCache[vpcName];
106
93
  }
107
94
  /**
108
95
  * Get the subnet ids from cache or read from AWS
109
96
  * @returns {Promise<object>}
110
97
  */
111
- getVPCSubnets(vpcId, tagKey, tagValues) {
112
- return __awaiter(this, void 0, void 0, function* () {
113
- const hash = ts_md5_1.Md5.hashStr(vpcId + tagKey + tagValues.join());
114
- if (!this.subnetsIdsCache[hash]) {
115
- this.subnetsIdsCache[hash] = yield this.ec2Wrapper.getSubnetIds(vpcId, tagKey, tagValues);
116
- }
117
- return this.subnetsIdsCache[hash];
118
- });
98
+ async getVPCSubnets(vpcId, tagKey, tagValues) {
99
+ const hash = ts_md5_1.Md5.hashStr(vpcId + tagKey + tagValues.join());
100
+ if (!this.subnetsIdsCache[hash]) {
101
+ this.subnetsIdsCache[hash] = await this.ec2Wrapper.getSubnetIds(vpcId, tagKey, tagValues);
102
+ }
103
+ return this.subnetsIdsCache[hash];
119
104
  }
120
105
  /**
121
106
  * Get the security group ids from cache or read from AWS
122
107
  * @returns {Promise<object>}
123
108
  */
124
- getVPCSecurityGroups(vpcId, names, tagKey, tagValues) {
125
- return __awaiter(this, void 0, void 0, function* () {
126
- const hash = ts_md5_1.Md5.hashStr(vpcId + (names || []).join() + tagKey + (tagValues || []).join());
127
- if (!this.SGIdsCache[hash]) {
128
- this.SGIdsCache[hash] = yield this.ec2Wrapper.getSecurityGroupIds(vpcId, names, tagKey, tagValues);
129
- }
130
- return this.SGIdsCache[hash];
131
- });
109
+ async getVPCSecurityGroups(vpcId, names, tagKey, tagValues) {
110
+ const hash = ts_md5_1.Md5.hashStr(vpcId + (names || []).join() + tagKey + (tagValues || []).join());
111
+ if (!this.SGIdsCache[hash]) {
112
+ this.SGIdsCache[hash] = await this.ec2Wrapper.getSecurityGroupIds(vpcId, names, tagKey, tagValues);
113
+ }
114
+ return this.SGIdsCache[hash];
132
115
  }
133
116
  }
134
117
  exports.LambdaFunction = LambdaFunction;
@@ -1,25 +1,21 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  const util_retry_1 = require("@smithy/util-retry");
13
4
  const credential_providers_1 = require("@aws-sdk/credential-providers");
14
5
  class Globals {
6
+ static pluginName = "Serverless VPC Discovery";
7
+ static serverless;
8
+ static options;
9
+ static v3Utils;
10
+ static currentRegion;
11
+ static credentials;
12
+ static defaultRegion = "us-east-1";
15
13
  static getRegion() {
16
14
  const slsRegion = Globals.options.region || Globals.serverless.service.provider.region;
17
15
  return slsRegion || Globals.currentRegion || Globals.defaultRegion;
18
16
  }
19
- static getProfileCreds(profile) {
20
- return __awaiter(this, void 0, void 0, function* () {
21
- return yield (0, credential_providers_1.fromIni)({ profile })();
22
- });
17
+ static async getProfileCreds(profile) {
18
+ return await (0, credential_providers_1.fromIni)({ profile })();
23
19
  }
24
20
  static getRetryStrategy(attempts = 3, delay = 3000, backoff = 500) {
25
21
  return new util_retry_1.ConfiguredRetryStrategy(attempts, // max attempts.
@@ -29,6 +25,4 @@ class Globals {
29
25
  );
30
26
  }
31
27
  }
32
- Globals.pluginName = "Serverless VPC Discovery";
33
- Globals.defaultRegion = "us-east-1";
34
28
  exports.default = Globals;
package/dist/src/index.js CHANGED
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
12
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
4
  };
@@ -19,11 +10,14 @@ const logging_1 = __importDefault(require("./logging"));
19
10
  const node_config_provider_1 = require("@smithy/node-config-provider");
20
11
  const config_resolver_1 = require("@smithy/config-resolver");
21
12
  class VPCPlugin {
13
+ serverless;
14
+ hooks;
15
+ lambdaFunction;
22
16
  constructor(serverless, options, v3Utils) {
23
17
  this.serverless = serverless;
24
18
  globals_1.default.serverless = serverless;
25
19
  globals_1.default.options = options;
26
- if (v3Utils === null || v3Utils === void 0 ? void 0 : v3Utils.log) {
20
+ if (v3Utils?.log) {
27
21
  globals_1.default.v3Utils = v3Utils;
28
22
  }
29
23
  /* hooks are the actual code that will run when called */
@@ -37,12 +31,10 @@ class VPCPlugin {
37
31
  * Wrapper for lifecycle function, initializes variables and checks if enabled.
38
32
  * @param lifecycleFunc lifecycle function that actually does desired action
39
33
  */
40
- hookWrapper(lifecycleFunc) {
41
- return __awaiter(this, void 0, void 0, function* () {
42
- this.validateCustomVPCDiscoveryConfig();
43
- yield this.initResources();
44
- return yield lifecycleFunc.call(this);
45
- });
34
+ async hookWrapper(lifecycleFunc) {
35
+ this.validateCustomVPCDiscoveryConfig();
36
+ await this.initResources();
37
+ return await lifecycleFunc.call(this);
46
38
  }
47
39
  /**
48
40
  * Validate if the plugin config exists
@@ -86,89 +78,81 @@ class VPCPlugin {
86
78
  /**
87
79
  * Setup AWS resources
88
80
  */
89
- initResources() {
90
- return __awaiter(this, void 0, void 0, function* () {
91
- // setup AWS resources
92
- yield this.initSLSCredentials();
93
- yield this.initAWSRegion();
94
- const baseVPCDiscovery = this.serverless.service.custom ? this.serverless.service.custom.vpcDiscovery : null;
95
- this.lambdaFunction = new lambda_function_1.LambdaFunction(globals_1.default.credentials, baseVPCDiscovery);
96
- // start of the legacy AWS SDK V2 creds support
97
- // TODO: remove it in case serverless will add V3 support
98
- try {
99
- yield this.lambdaFunction.ec2Wrapper.getVpcs();
100
- }
101
- catch (error) {
102
- if (error.message.includes("Could not load credentials from any providers")) {
103
- globals_1.default.credentials = this.serverless.providers.aws.getCredentials();
104
- this.lambdaFunction = new lambda_function_1.LambdaFunction(globals_1.default.credentials, baseVPCDiscovery);
105
- }
81
+ async initResources() {
82
+ // setup AWS resources
83
+ await this.initSLSCredentials();
84
+ await this.initAWSRegion();
85
+ const baseVPCDiscovery = this.serverless.service.custom ? this.serverless.service.custom.vpcDiscovery : null;
86
+ this.lambdaFunction = new lambda_function_1.LambdaFunction(globals_1.default.credentials, baseVPCDiscovery);
87
+ // start of the legacy AWS SDK V2 creds support
88
+ // TODO: remove it in case serverless will add V3 support
89
+ try {
90
+ await this.lambdaFunction.ec2Wrapper.getVpcs();
91
+ }
92
+ catch (error) {
93
+ if (error.message.includes("Could not load credentials from any providers")) {
94
+ globals_1.default.credentials = this.serverless.providers.aws.getCredentials();
95
+ this.lambdaFunction = new lambda_function_1.LambdaFunction(globals_1.default.credentials, baseVPCDiscovery);
106
96
  }
107
- });
97
+ }
108
98
  }
109
99
  /**
110
100
  * Init AWS credentials based on sls `provider.profile`
111
101
  */
112
- initSLSCredentials() {
113
- return __awaiter(this, void 0, void 0, function* () {
114
- const slsProfile = globals_1.default.options["aws-profile"] || globals_1.default.serverless.service.provider.profile;
115
- globals_1.default.credentials = slsProfile ? yield globals_1.default.getProfileCreds(slsProfile) : null;
116
- });
102
+ async initSLSCredentials() {
103
+ const slsProfile = globals_1.default.options["aws-profile"] || globals_1.default.serverless.service.provider.profile;
104
+ globals_1.default.credentials = slsProfile ? await globals_1.default.getProfileCreds(slsProfile) : null;
117
105
  }
118
106
  /**
119
107
  * Init AWS current region based on Node options
120
108
  */
121
- initAWSRegion() {
122
- return __awaiter(this, void 0, void 0, function* () {
123
- try {
124
- globals_1.default.currentRegion = yield (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS)();
125
- }
126
- catch (err) {
127
- logging_1.default.logInfo("Node region was not found.");
128
- }
129
- });
109
+ async initAWSRegion() {
110
+ try {
111
+ globals_1.default.currentRegion = await (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS)();
112
+ }
113
+ catch (err) {
114
+ logging_1.default.logInfo("Node region was not found.");
115
+ }
130
116
  }
131
117
  /**
132
118
  * Updates functions vpc config
133
119
  * @returns {Promise<object>}
134
120
  */
135
- updateFunctionsVpcConfig() {
136
- return __awaiter(this, void 0, void 0, function* () {
137
- logging_1.default.logInfo("Updating VPC config...");
138
- const service = this.serverless.service;
139
- const functions = service.functions || {};
140
- // Sets the serverless's vpc config
141
- // loop through the functions and update VPC config
142
- for (const funcName of Object.keys(functions)) {
143
- const func = service.functions[funcName];
144
- this.updateVPCDiscoveryConfigCompatibility(func.vpcDiscovery);
145
- const funcVPC = yield this.lambdaFunction.getFuncVPC(funcName, func.vpcDiscovery);
146
- if (!funcVPC) {
147
- continue;
148
- }
149
- // init vpc empty config in case not exists
150
- func.vpc = func.vpc || {};
151
- // log warning in case vpc.subnetIds and vpcDiscovery.subnetNames are specified.
152
- if (func.vpc.subnetIds && func.vpcDiscovery && func.vpcDiscovery.subnets) {
153
- logging_1.default.logWarning(`vpc.subnetIds' are specified for the function '${funcName}' ` +
154
- "and overrides 'vpcDiscovery.subnets' discovery config.");
155
- }
156
- // log warning in case vpc.securityGroupIds and vpcDiscovery.securityGroupNames are specified.
157
- if (func.vpc.securityGroupIds && func.vpcDiscovery && func.vpcDiscovery.securityGroups) {
158
- logging_1.default.logWarning(`vpc.securityGroupIds' are specified for the function '${funcName}' ` +
159
- "and overrides 'vpcDiscovery.securityGroups' discovery config.");
160
- }
161
- // set vpc.subnetIds if it does not exists
162
- if (!func.vpc.subnetIds && funcVPC.subnetIds) {
163
- func.vpc.subnetIds = funcVPC.subnetIds;
164
- }
165
- // set vpc.securityGroupIds if it does not exists
166
- if (!func.vpc.securityGroupIds && funcVPC.securityGroupIds) {
167
- func.vpc.securityGroupIds = funcVPC.securityGroupIds;
168
- }
121
+ async updateFunctionsVpcConfig() {
122
+ logging_1.default.logInfo("Updating VPC config...");
123
+ const service = this.serverless.service;
124
+ const functions = service.functions || {};
125
+ // Sets the serverless's vpc config
126
+ // loop through the functions and update VPC config
127
+ for (const funcName of Object.keys(functions)) {
128
+ const func = service.functions[funcName];
129
+ this.updateVPCDiscoveryConfigCompatibility(func.vpcDiscovery);
130
+ const funcVPC = await this.lambdaFunction.getFuncVPC(funcName, func.vpcDiscovery);
131
+ if (!funcVPC) {
132
+ continue;
169
133
  }
170
- return service.functions;
171
- });
134
+ // init vpc empty config in case not exists
135
+ func.vpc = func.vpc || {};
136
+ // log warning in case vpc.subnetIds and vpcDiscovery.subnetNames are specified.
137
+ if (func.vpc.subnetIds && func.vpcDiscovery && func.vpcDiscovery.subnets) {
138
+ logging_1.default.logWarning(`vpc.subnetIds' are specified for the function '${funcName}' ` +
139
+ "and overrides 'vpcDiscovery.subnets' discovery config.");
140
+ }
141
+ // log warning in case vpc.securityGroupIds and vpcDiscovery.securityGroupNames are specified.
142
+ if (func.vpc.securityGroupIds && func.vpcDiscovery && func.vpcDiscovery.securityGroups) {
143
+ logging_1.default.logWarning(`vpc.securityGroupIds' are specified for the function '${funcName}' ` +
144
+ "and overrides 'vpcDiscovery.securityGroups' discovery config.");
145
+ }
146
+ // set vpc.subnetIds if it does not exists
147
+ if (!func.vpc.subnetIds && funcVPC.subnetIds) {
148
+ func.vpc.subnetIds = funcVPC.subnetIds;
149
+ }
150
+ // set vpc.securityGroupIds if it does not exists
151
+ if (!func.vpc.securityGroupIds && funcVPC.securityGroupIds) {
152
+ func.vpc.securityGroupIds = funcVPC.securityGroupIds;
153
+ }
154
+ }
155
+ return service.functions;
172
156
  }
173
157
  }
174
158
  module.exports = VPCPlugin;
package/dist/src/utils.js CHANGED
@@ -1,15 +1,10 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.getValueFromTags = exports.wildcardMatches = exports.isObjectEmpty = exports.getAWSPagedResults = exports.sleep = void 0;
3
+ exports.sleep = sleep;
4
+ exports.getAWSPagedResults = getAWSPagedResults;
5
+ exports.isObjectEmpty = isObjectEmpty;
6
+ exports.wildcardMatches = wildcardMatches;
7
+ exports.getValueFromTags = getValueFromTags;
13
8
  /**
14
9
  * Iterate through the pages of a AWS SDK response and collect them into a single array
15
10
  *
@@ -19,35 +14,28 @@ exports.getValueFromTags = exports.wildcardMatches = exports.isObjectEmpty = exp
19
14
  * @param nextRequestTokenKey - The response key name that has the next paging token value
20
15
  * @param params - Parameters to send in the request
21
16
  */
22
- function getAWSPagedResults(client, resultsKey, nextTokenKey, nextRequestTokenKey, params) {
23
- return __awaiter(this, void 0, void 0, function* () {
24
- let results = [];
25
- let response = yield client.send(params);
26
- results = results.concat(response[resultsKey] || results);
27
- while (nextRequestTokenKey in response && response[nextRequestTokenKey]) {
28
- params.input[nextTokenKey] = response[nextRequestTokenKey];
29
- response = yield client.send(params);
30
- results = results.concat(response[resultsKey]);
31
- }
32
- return results;
33
- });
17
+ async function getAWSPagedResults(client, resultsKey, nextTokenKey, nextRequestTokenKey, params) {
18
+ let results = [];
19
+ let response = await client.send(params);
20
+ results = results.concat(response[resultsKey] || results);
21
+ while (nextRequestTokenKey in response && response[nextRequestTokenKey]) {
22
+ params.input[nextTokenKey] = response[nextRequestTokenKey];
23
+ response = await client.send(params);
24
+ results = results.concat(response[resultsKey]);
25
+ }
26
+ return results;
34
27
  }
35
- exports.getAWSPagedResults = getAWSPagedResults;
36
28
  /**
37
29
  * Stops event thread execution for given number of seconds.
38
30
  * @param seconds
39
31
  * @returns {Promise<void>} Resolves after given number of seconds.
40
32
  */
41
- function sleep(seconds) {
42
- return __awaiter(this, void 0, void 0, function* () {
43
- return new Promise((resolve) => setTimeout(resolve, 1000 * seconds));
44
- });
33
+ async function sleep(seconds) {
34
+ return new Promise((resolve) => setTimeout(resolve, 1000 * seconds));
45
35
  }
46
- exports.sleep = sleep;
47
36
  function isObjectEmpty(value) {
48
37
  return Object.keys(value).length === 0;
49
38
  }
50
- exports.isObjectEmpty = isObjectEmpty;
51
39
  function replaceAll(input, search, replace) {
52
40
  return input.split(search).join(replace);
53
41
  }
@@ -57,7 +45,6 @@ function wildcardMatches(inputArn, actualArn) {
57
45
  const inputArnRegex = new RegExp(`^${inputArnRegexStr}$`);
58
46
  return inputArnRegex.test(actualArn);
59
47
  }
60
- exports.wildcardMatches = wildcardMatches;
61
48
  function getValueFromTags(tags, tagKey) {
62
49
  const tagItem = tags.find((tag) => tag.Key === tagKey);
63
50
  if (tagItem) {
@@ -65,4 +52,3 @@ function getValueFromTags(tags, tagKey) {
65
52
  }
66
53
  return null;
67
54
  }
68
- exports.getValueFromTags = getValueFromTags;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateVPCDiscoveryConfig = void 0;
3
+ exports.validateVPCDiscoveryConfig = validateVPCDiscoveryConfig;
4
4
  /**
5
5
  * Validate vpc discovery subnets config
6
6
  * @param subnets - the `SubnetItem` options
@@ -61,4 +61,3 @@ function validateVPCDiscoveryConfig(vpcDiscovery) {
61
61
  validateVPCSecurityGroups(vpcDiscovery.securityGroups);
62
62
  }
63
63
  }
64
- exports.validateVPCDiscoveryConfig = validateVPCDiscoveryConfig;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "serverless-vpc-discovery",
3
- "version": "5.0.2",
3
+ "version": "7.0.0",
4
4
  "engines": {
5
- "node": ">=14"
5
+ "node": ">=18"
6
6
  },
7
7
  "description": "Serverless Plugin to modify VPC values",
8
8
  "author": "Amplify Education Inc",
@@ -30,9 +30,9 @@
30
30
  "main": "dist/src/index.js",
31
31
  "bin": {},
32
32
  "scripts": {
33
- "test": "nyc mocha -r ts-node/register --project tsconfig.json test/unit-tests/index.test.ts && nyc report --reporter=text-summary",
34
- "integration-test": "nyc mocha -r ts-node/register --project tsconfig.json test/integration-tests/*.test.ts && nyc report --reporter=text-summary",
35
- "lint": "eslint src --ext .ts",
33
+ "test": "c8 mocha -r tsx test/unit-tests/index.test.ts",
34
+ "integration-test": "mocha -r tsx test/integration-tests/*.test.ts",
35
+ "lint": "eslint src",
36
36
  "lint:fix": "npm run lint -- --fix",
37
37
  "build": "tsc --project .",
38
38
  "prepare": "npm run build"
@@ -43,45 +43,41 @@
43
43
  "*.json",
44
44
  "dist/**/*.js"
45
45
  ],
46
- "nyc": {
47
- "extension": [
48
- ".ts"
49
- ]
50
- },
51
46
  "devDependencies": {
52
- "@aws-sdk/client-lambda": "^3.465.0",
47
+ "@aws-sdk/client-lambda": "~3.967.0",
48
+ "@types/chai": "^5.0.1",
49
+ "@types/chai-spies": "^1.0.6",
53
50
  "@types/js-yaml": "^4.0.9",
54
- "@types/mocha": "^10.0.6",
55
- "@types/node": "^20.10.3",
56
- "@types/randomstring": "^1.1.11",
51
+ "@types/mocha": "^10.0.10",
52
+ "@types/node": "^18.0.0",
53
+ "@types/randomstring": "^1.3.0",
57
54
  "@types/shelljs": "^0.8.15",
58
- "@typescript-eslint/eslint-plugin": "^5.62.0",
59
- "@typescript-eslint/parser": "^5.62.0",
60
- "aws-sdk-client-mock": "^3.0.0",
61
- "chai": "^4.3.10",
55
+ "@typescript-eslint/eslint-plugin": "^8.56.0",
56
+ "aws-sdk-client-mock": "^4.1.0",
57
+ "chai": "^6.2.2",
62
58
  "chai-spies": "^1.1.0",
63
- "eslint": "^7.32.0",
64
- "eslint-config-standard": "^16.0.3",
65
- "eslint-plugin-import": "^2.29.0",
66
- "eslint-plugin-node": "^11.1.0",
67
- "eslint-plugin-promise": "^5.2.0",
68
- "js-yaml": "^4.1.0",
69
- "mocha": "^10.2.0",
59
+ "eslint": "^9.0.0",
60
+ "neostandard": "^0.12.0",
61
+ "js-yaml": "^4.1.1",
62
+ "mocha": "^11.0.0",
70
63
  "mocha-param": "^2.0.1",
71
- "nyc": "^15.1.0",
72
- "randomstring": "^1.3.0",
73
- "serverless": "^3.38.0",
64
+ "c8": "^10.0.0",
65
+ "randomstring": "^1.3.1",
66
+ "serverless": "^4.32.0",
74
67
  "shelljs": "^0.8.5",
75
- "ts-node": "^10.9.1",
76
- "typescript": "5.1.6"
68
+ "tsx": "^4.21.0",
69
+ "typescript": "^5.9.3"
77
70
  },
78
71
  "dependencies": {
79
- "@aws-sdk/client-ec2": "^3.467.0",
80
- "@aws-sdk/credential-providers": "^3.495.0",
81
- "@smithy/config-resolver": "^2.1.0",
82
- "@smithy/node-config-provider": "^2.2.0",
83
- "@smithy/smithy-client": "^2.1.18",
84
- "@smithy/util-retry": "^2.0.8",
72
+ "@aws-sdk/client-ec2": "~3.967.0",
73
+ "@aws-sdk/credential-providers": "~3.967.0",
74
+ "@smithy/config-resolver": "~4.4.5",
75
+ "@smithy/node-config-provider": "~4.3.7",
76
+ "@smithy/smithy-client": "~4.10.4",
77
+ "@smithy/util-retry": "~4.2.7",
85
78
  "ts-md5": "^1.3.1"
79
+ },
80
+ "overrides": {
81
+ "fast-xml-parser": "^5.3.6"
86
82
  }
87
83
  }
package/tsconfig.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "module": "commonjs",
4
4
  "moduleResolution": "node",
5
5
  "rootDir": ".",
6
- "target": "es6",
6
+ "target": "ES2022",
7
7
  "sourceMap": false,
8
8
  "outDir": "dist",
9
9
  "types": [
package/.eslintrc.json DELETED
@@ -1,41 +0,0 @@
1
- {
2
- "env": {
3
- "browser": true,
4
- "es2021": true,
5
- "commonjs": true,
6
- "node": true,
7
- "mocha": true
8
- },
9
- "extends": [
10
- "standard",
11
- "eslint:recommended",
12
- "plugin:@typescript-eslint/eslint-recommended"
13
- ],
14
- "parser": "@typescript-eslint/parser",
15
- "parserOptions": {
16
- "ecmaVersion": 2020,
17
- "sourceType": "module"
18
- },
19
- "plugins": [
20
- "@typescript-eslint"
21
- ],
22
- "rules": {
23
- "quotes": [
24
- "error",
25
- "double"
26
- ],
27
- "semi": [
28
- "error",
29
- "always"
30
- ],
31
- "arrow-parens": [
32
- "error",
33
- "always"
34
- ],
35
- "complexity": [
36
- "error",
37
- 15
38
- ],
39
- "guard-for-in": "error"
40
- }
41
- }