@aws-amplify/graphql-schema-generator
Version:
Amplify GraphQL schema generator
242 lines • 10.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.invokeSchemaInspectorLambda = exports.sleep = exports.provisionSchemaInspectorLambda = exports.getHostVpc = void 0;
const client_iam_1 = require("@aws-sdk/client-iam");
const client_lambda_1 = require("@aws-sdk/client-lambda");
const fs = __importStar(require("fs-extra"));
const ora_1 = __importDefault(require("ora"));
const vpc_helper_cluster_1 = require("./vpc-helper-cluster");
const vpc_helper_proxy_1 = require("./vpc-helper-proxy");
const vpc_helper_instance_1 = require("./vpc-helper-instance");
const spinner = (0, ora_1.default)('');
const getHostVpc = async (hostname, region) => {
const proxyResult = await (0, vpc_helper_proxy_1.checkHostInDBProxies)(hostname, region);
if (proxyResult) {
return proxyResult;
}
const warning = (clusterOrInstance) => {
return (`The host you provided is for an RDS ${clusterOrInstance}. Consider using an RDS Proxy as your data source instead.\n` +
'See the documentation for a discussion of how an RDS proxy can help you scale your application more effectively.');
};
const clusterResult = await (0, vpc_helper_cluster_1.checkHostInDBClusters)(hostname, region);
if (clusterResult) {
console.warn(warning('cluster'));
return clusterResult;
}
const instanceResult = await (0, vpc_helper_instance_1.checkHostInDBInstances)(hostname, region);
if (instanceResult) {
console.warn(warning('instance'));
return instanceResult;
}
return undefined;
};
exports.getHostVpc = getHostVpc;
const provisionSchemaInspectorLambda = async (lambdaName, vpc, region) => {
var _a, _b, _c, _d;
const roleName = `${lambdaName}-execution-role`;
let createLambda = true;
const iamRole = await createRoleIfNotExists(roleName, region);
const existingLambda = await getSchemaInspectorLambda(lambdaName, region);
spinner.start('Provisioning a function to introspect the database schema...');
try {
if (existingLambda) {
const subnetIds = vpc.subnetAvailabilityZoneConfig.map((sn) => sn.subnetId);
const vpcConfigMismatch = ((_b = (_a = existingLambda.VpcConfig) === null || _a === void 0 ? void 0 : _a.SecurityGroupIds) === null || _b === void 0 ? void 0 : _b.sort().join()) !== vpc.securityGroupIds.sort().join() ||
((_d = (_c = existingLambda.VpcConfig) === null || _c === void 0 ? void 0 : _c.SubnetIds) === null || _d === void 0 ? void 0 : _d.sort().join()) !== subnetIds.sort().join();
if (vpcConfigMismatch) {
await deleteSchemaInspectorLambdaRole(lambdaName, region);
createLambda = true;
}
else {
await updateSchemaInspectorLambda(lambdaName, region);
createLambda = false;
}
}
if (createLambda) {
await createSchemaInspectorLambda(lambdaName, iamRole, vpc, region);
}
}
catch (err) {
spinner.fail('Failed to provision a function to introspect the database schema.');
console.debug(`Error provisioning a function to introspect the database schema: ${err}`);
throw err;
}
spinner.succeed('Successfully provisioned a function to introspect the database schema.');
};
exports.provisionSchemaInspectorLambda = provisionSchemaInspectorLambda;
const getSchemaInspectorLambda = async (lambdaName, region) => {
const lambdaClient = new client_lambda_1.LambdaClient({ region });
const params = {
FunctionName: lambdaName,
};
try {
const response = await lambdaClient.send(new client_lambda_1.GetFunctionCommand(params));
return response.Configuration;
}
catch (err) {
return undefined;
}
};
const deleteSchemaInspectorLambdaRole = async (lambdaName, region) => {
const lambdaClient = new client_lambda_1.LambdaClient({ region });
const params = {
FunctionName: lambdaName,
};
const FUNCTION_DELETE_DELAY = 10000;
await lambdaClient.send(new client_lambda_1.DeleteFunctionCommand(params));
await (0, exports.sleep)(FUNCTION_DELETE_DELAY);
};
const createSchemaInspectorLambda = async (lambdaName, iamRole, vpc, region) => {
const lambdaClient = new client_lambda_1.LambdaClient({ region });
const subnetIds = vpc.subnetAvailabilityZoneConfig.map((sn) => sn.subnetId);
const params = {
Code: {
ZipFile: await fs.readFile(`${__dirname}/../rds-schema-inspector.zip`),
},
PackageType: 'Zip',
FunctionName: lambdaName,
Handler: 'index.handler',
Role: iamRole.Arn,
Runtime: 'nodejs20.x',
VpcConfig: {
SecurityGroupIds: vpc.securityGroupIds,
SubnetIds: subnetIds,
},
Timeout: 30,
};
const response = await lambdaClient.send(new client_lambda_1.CreateFunctionCommand(params));
await (0, client_lambda_1.waitUntilFunctionActive)({ client: lambdaClient, maxWaitTime: 600 }, { FunctionName: response.FunctionName });
};
const updateSchemaInspectorLambda = async (lambdaName, region) => {
const lambdaClient = new client_lambda_1.LambdaClient({ region });
const params = {
FunctionName: lambdaName,
ZipFile: await fs.readFile(`${__dirname}/../rds-schema-inspector.zip`),
};
await lambdaClient.send(new client_lambda_1.UpdateFunctionCodeCommand(params));
};
const createRoleIfNotExists = async (roleName, region) => {
let role = await getRole(roleName, region);
const ROLE_PROPAGATION_DELAY = 10000;
if (!role) {
role = await createRole(roleName, region);
await (0, exports.sleep)(ROLE_PROPAGATION_DELAY);
}
return role;
};
const sleep = async (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
exports.sleep = sleep;
const createPolicy = async (policyName, region) => {
const client = new client_iam_1.IAMClient({ region });
const command = new client_iam_1.CreatePolicyCommand({
PolicyName: policyName,
PolicyDocument: JSON.stringify({
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Resource: '*',
Action: ['ec2:CreateNetworkInterface', 'ec2:DescribeNetworkInterfaces', 'ec2:DeleteNetworkInterface'],
},
{
Effect: 'Allow',
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
Resource: ['arn:aws:logs:*:*:*'],
},
],
}),
});
const result = await client.send(command);
await (0, client_iam_1.waitUntilPolicyExists)({ client, maxWaitTime: 30 }, { PolicyArn: result.Policy.Arn });
return result.Policy;
};
const createRole = async (roleName, region) => {
const client = new client_iam_1.IAMClient({ region });
const policy = await createPolicy(`${roleName}-policy`, region);
const command = new client_iam_1.CreateRoleCommand({
AssumeRolePolicyDocument: JSON.stringify({
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: 'lambda.amazonaws.com',
},
Action: 'sts:AssumeRole',
},
],
}),
RoleName: roleName,
});
const result = await client.send(command);
const attachPolicyCommand = new client_iam_1.AttachRolePolicyCommand({
PolicyArn: policy.Arn,
RoleName: roleName,
});
await client.send(attachPolicyCommand);
await (0, client_iam_1.waitUntilRoleExists)({ client, maxWaitTime: 30 }, { RoleName: roleName });
return result.Role;
};
const getRole = async (roleName, region) => {
const client = new client_iam_1.IAMClient({ region });
const command = new client_iam_1.GetRoleCommand({
RoleName: roleName,
});
try {
const response = await client.send(command);
return response.Role;
}
catch (err) {
if (err.name == 'NoSuchEntityException') {
return undefined;
}
throw err;
}
};
const invokeSchemaInspectorLambda = async (funcName, dbConfig, query, region) => {
const client = new client_lambda_1.LambdaClient({ region });
const encoder = new TextEncoder();
const command = new client_lambda_1.InvokeCommand({
FunctionName: funcName,
Payload: encoder.encode(JSON.stringify({
config: dbConfig,
query,
})),
LogType: client_lambda_1.LogType.Tail,
});
const { Payload } = await client.send(command);
const result = Buffer.from(Payload).toString();
const resultJson = JSON.parse(result);
if (resultJson.errorMessage) {
throw new Error(`Error occurred while fetching the database metadata: ${resultJson.errorMessage}`);
}
return resultJson;
};
exports.invokeSchemaInspectorLambda = invokeSchemaInspectorLambda;
//# sourceMappingURL=vpc-helper.js.map