UNPKG

serverless-vpc-discovery

Version:
175 lines (174 loc) 8.79 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; const lambda_function_1 = require("./common/lambda-function"); const globals_1 = __importDefault(require("./globals")); const validation_1 = require("./validation"); const schema_1 = require("./schema"); const logging_1 = __importDefault(require("./logging")); const node_config_provider_1 = require("@smithy/node-config-provider"); const config_resolver_1 = require("@smithy/config-resolver"); class VPCPlugin { constructor(serverless, options, v3Utils) { this.serverless = serverless; globals_1.default.serverless = serverless; globals_1.default.options = options; if (v3Utils === null || v3Utils === void 0 ? void 0 : v3Utils.log) { globals_1.default.v3Utils = v3Utils; } /* hooks are the actual code that will run when called */ this.hooks = { "before:package:initialize": this.hookWrapper.bind(this, this.updateFunctionsVpcConfig) }; serverless.configSchemaHandler.defineCustomProperties(schema_1.customProperties); serverless.configSchemaHandler.defineFunctionProperties("aws", schema_1.functionProperties); } /** * Wrapper for lifecycle function, initializes variables and checks if enabled. * @param lifecycleFunc lifecycle function that actually does desired action */ hookWrapper(lifecycleFunc) { return __awaiter(this, void 0, void 0, function* () { this.validateCustomVPCDiscoveryConfig(); yield this.initResources(); return yield lifecycleFunc.call(this); }); } /** * Validate if the plugin config exists */ validateCustomVPCDiscoveryConfig() { const config = this.serverless.service.custom; const vpcDiscovery = config && config.vpcDiscovery; if (vpcDiscovery) { // support backward compatibility this.updateVPCDiscoveryConfigCompatibility(vpcDiscovery); // validate config try { // the validateVPCDiscoveryConfig is general for custom and func configs // so try catch for extend error message with `custom.vpcDiscovery` as a source (0, validation_1.validateVPCDiscoveryConfig)(vpcDiscovery); } catch (e) { throw new Error(`The \`custom.vpcDiscovery\` is not configured correctly: \n${e} ` + " Please see README for proper setup."); } } } /** * This function update VPC Discovery config to support version 2.x config structure and show warning errors */ updateVPCDiscoveryConfigCompatibility(vpcDiscovery) { // support backward compatibility if (vpcDiscovery && (vpcDiscovery.subnetNames || vpcDiscovery.securityGroupNames)) { // convert `vpcDiscovery.subnetNames` or `vpcDiscovery.securityGroupNames` to the new config structure if (!vpcDiscovery.subnets && !vpcDiscovery.securityGroups) { if (vpcDiscovery.subnetNames) { vpcDiscovery.subnets = [{ tagKey: "Name", tagValues: vpcDiscovery.subnetNames }]; } if (vpcDiscovery.securityGroupNames) { vpcDiscovery.securityGroups = [{ names: vpcDiscovery.securityGroupNames }]; } logging_1.default.logWarning("The `vpcDiscovery.subnetNames` and `vpcDiscovery.securityGroupNames` options are deprecated " + "and will be removed in the future. Please see README for proper setup."); } } } /** * Setup AWS resources */ initResources() { return __awaiter(this, void 0, void 0, function* () { // setup AWS resources yield this.initSLSCredentials(); yield this.initAWSRegion(); const baseVPCDiscovery = this.serverless.service.custom ? this.serverless.service.custom.vpcDiscovery : null; this.lambdaFunction = new lambda_function_1.LambdaFunction(globals_1.default.credentials, baseVPCDiscovery); // start of the legacy AWS SDK V2 creds support // TODO: remove it in case serverless will add V3 support try { yield this.lambdaFunction.ec2Wrapper.getVpcs(); } catch (error) { if (error.message.includes("Could not load credentials from any providers")) { globals_1.default.credentials = this.serverless.providers.aws.getCredentials(); this.lambdaFunction = new lambda_function_1.LambdaFunction(globals_1.default.credentials, baseVPCDiscovery); } } }); } /** * Init AWS credentials based on sls `provider.profile` */ initSLSCredentials() { return __awaiter(this, void 0, void 0, function* () { const slsProfile = globals_1.default.options["aws-profile"] || globals_1.default.serverless.service.provider.profile; globals_1.default.credentials = slsProfile ? yield globals_1.default.getProfileCreds(slsProfile) : null; }); } /** * Init AWS current region based on Node options */ initAWSRegion() { return __awaiter(this, void 0, void 0, function* () { try { 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)(); } catch (err) { logging_1.default.logInfo("Node region was not found."); } }); } /** * Updates functions vpc config * @returns {Promise<object>} */ updateFunctionsVpcConfig() { return __awaiter(this, void 0, void 0, function* () { logging_1.default.logInfo("Updating VPC config..."); const service = this.serverless.service; const functions = service.functions || {}; // Sets the serverless's vpc config // loop through the functions and update VPC config for (const funcName of Object.keys(functions)) { const func = service.functions[funcName]; this.updateVPCDiscoveryConfigCompatibility(func.vpcDiscovery); const funcVPC = yield this.lambdaFunction.getFuncVPC(funcName, func.vpcDiscovery); if (!funcVPC) { continue; } // init vpc empty config in case not exists func.vpc = func.vpc || {}; // log warning in case vpc.subnetIds and vpcDiscovery.subnetNames are specified. if (func.vpc.subnetIds && func.vpcDiscovery && func.vpcDiscovery.subnets) { logging_1.default.logWarning(`vpc.subnetIds' are specified for the function '${funcName}' ` + "and overrides 'vpcDiscovery.subnets' discovery config."); } // log warning in case vpc.securityGroupIds and vpcDiscovery.securityGroupNames are specified. if (func.vpc.securityGroupIds && func.vpcDiscovery && func.vpcDiscovery.securityGroups) { logging_1.default.logWarning(`vpc.securityGroupIds' are specified for the function '${funcName}' ` + "and overrides 'vpcDiscovery.securityGroups' discovery config."); } // set vpc.subnetIds if it does not exists if (!func.vpc.subnetIds && funcVPC.subnetIds) { func.vpc.subnetIds = funcVPC.subnetIds; } // set vpc.securityGroupIds if it does not exists if (!func.vpc.securityGroupIds && funcVPC.securityGroupIds) { func.vpc.securityGroupIds = funcVPC.securityGroupIds; } } return service.functions; }); } } module.exports = VPCPlugin;