@matthewbonig/rds-tools
Version:
A construct for working with RDS SQL servers
125 lines (112 loc) • 3.63 kB
text/typescript
// eslint-disable-next-line @typescript-eslint/no-require-imports
import { IProvider } from './provider';
// eslint-disable-next-line @typescript-eslint/no-require-imports
const AWS = require('aws-sdk');
// eslint-disable-next-line @typescript-eslint/no-require-imports
const response = require('./cfn-response');
export const getProvider = (props: {
username: string;
password: string;
host: string;
databaseName?: string;
engine: string;
port?: string;
}): IProvider => {
const commonProps = {
host: props.host,
port: props.port,
username: props.username,
password: props.password,
databaseName: props.databaseName,
};
switch (props.engine) {
case 'sqlserver':
case 'sqlserver-se':
case 'sqlserver-ex':
case 'sqlserver-ee':
case 'sqlserver-web':
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { MsSqlProvider } = require('./mssql-provider');
return new MsSqlProvider(commonProps);
case 'postgres':
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { PostgresSqlProvider } = require('./postgres-provider');
return new PostgresSqlProvider(commonProps);
case 'mysql':
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { MySqlProvider } = require('./mysql-provider');
return new MySqlProvider(commonProps);
default:
throw new Error('Cannot determine the provider to use. Please submit an Issue.');
}
};
export const innerHandler = async ({ script, databaseName }: { script: string; databaseName: string }) => {
const sm = new AWS.SecretsManager({});
const {
SECRET_ARN: powerUserSecretArn,
} = process.env;
console.log('Getting secret...');
const { SecretString: powerUserSecretString } = await sm.getSecretValue({ SecretId: powerUserSecretArn }).promise();
if (!powerUserSecretString) {
throw new Error('Could not determine the username and password. Make sure the provided Secret has a value and is an object with {username, password}');
}
const {
username,
password,
host,
port,
engine,
} = JSON.parse(powerUserSecretString);
const provider = getProvider({
host,
port,
engine,
username,
password,
databaseName,
});
return provider.query(script);
};
/**
* Handler for Custom Resources
*
* @param event
* @param context
*/
export const handler = async (event: any, context: any) => {
console.log('event: ', JSON.stringify(event, null, 2));
try {
if (event.RequestType === 'Delete') {
await response.send(event, context, 'SUCCESS', null, event.PhysicalResourceId);
return;
}
const {
script,
databaseName,
} = event.ResourceProperties;
const results = await innerHandler({ script, databaseName });
await response.send(event, context, response.SUCCESS, null, null);
return results;
} catch (error) {
// ... error checks
console.log(error);
await response.send(event, context, response.FAILED, { err: error });
}
};
/**
* Handler for direct execution
*
* @param event {script: string, databaseName: string}
* @example {script: 'SELECT 1', databaseName: 'mydatabase'}
*/
export const adhocHandler = async (event: any) => {
console.log('event:', JSON.stringify(event, null, 2));
if (!event.script) {
throw new Error('Please provide a script to run. e.g. `SELECT 1`');
}
if (!event.databaseName) {
throw new Error('Please provide a databaseName. e.g. `mydatabase`');
}
const results: any = await innerHandler(event);
return results.rows;
};