Skip to content

Instantly share code, notes, and snippets.

@pulumipus
Last active November 18, 2020 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pulumipus/61edcdd8ab3f50a42b4bd34a7e1f789b to your computer and use it in GitHub Desktop.
Save pulumipus/61edcdd8ab3f50a42b4bd34a7e1f789b to your computer and use it in GitHub Desktop.
Extended Pulumi Automation API workflow orchestration example
import { InlineProgramArgs, LocalWorkspace } from "@pulumi/pulumi/x/automation";
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
import * as pulumi from "@pulumi/pulumi";
import * as mysql from "mysql";
const process = require('process');
const args = process.argv.slice(2);
let destroy = false;
let createdb =false;
let checktable = false;
let optimize = false;
let analyze = false;
if (args.length > 0 && args[0]) {
destroy = args[0] === "destroy";
createdb = args[0] === "createdb";
checktable = args[0] === "checktable";
optimize = args[0] === "optimize";
analyze = args[0] === "analyze";
}
let tableName = args[1];
const run = async () => {
// This is our pulumi program in "inline function" form
const pulumiProgram = async () => {
// set database properties
const dbName = "hellosql";
const dbUser = "hellosql";
const dbPass = "dbpass";
async function getSecret(name: string) {
const secret = await aws.secretsmanager.getSecret({name: name});
const sm = aws.secretsmanager.getSecretVersion( {secretId: secret.arn});
return (await sm).secretString;
}
// setup infrastructure
const vpc = awsx.ec2.Vpc.getDefault();
const subnetGroup = new aws.rds.SubnetGroup("dbsubnet", {
subnetIds: vpc.publicSubnetIds,
});
// make a public SG for our cluster for the migration
const securityGroup = new awsx.ec2.SecurityGroup("publicGroup", {
egress: [
{
protocol: "-1",
fromPort: 0,
toPort: 0,
cidrBlocks: ["0.0.0.0/0"],
}
],
ingress: [
{
protocol: "-1",
fromPort: 0,
toPort: 0,
cidrBlocks: ["0.0.0.0/0"],
}
]
});
// provision our db
const cluster = new aws.rds.Cluster("db", {
engine: "aurora-mysql",
engineVersion: "5.7.mysql_aurora.2.03.2",
databaseName: dbUser,
masterUsername: dbName,
masterPassword: getSecret("dbpass"),
skipFinalSnapshot: true,
dbSubnetGroupName: subnetGroup.name,
vpcSecurityGroupIds: [securityGroup.id],
});
const clusterInstance = new aws.rds.ClusterInstance("dbInstance", {
clusterIdentifier: cluster.clusterIdentifier,
instanceClass: "db.t3.small",
engine: "aurora-mysql",
engineVersion: "5.7.mysql_aurora.2.03.2",
publiclyAccessible: true,
dbSubnetGroupName: subnetGroup.name,
});
return {
host: pulumi.interpolate`${cluster.endpoint}`,
dbName,
dbUser,
dbPass: getSecret("dbpass"),
dbBucket: bucket
};
};
// Create our stack
const args: InlineProgramArgs = {
stackName: "dev",
projectName: "databaseMigration",
program: pulumiProgram
};
// create (or select if one already exists) a stack that uses our inline program
const stack = await LocalWorkspace.createOrSelectStack(args);
console.info("successfully initialized stack");
console.info("installing plugins...");
await stack.workspace.installPlugin("aws", "v3.6.1");
console.info("plugins installed");
console.info("setting up config");
await stack.setConfig("aws:region", { value: "us-west-2" });
console.info("config set");
console.info("refreshing stack...");
await stack.refresh({ onOutput: console.info });
console.info("refresh complete");
if (destroy) {
console.info("destroying stack...");
await stack.destroy({ onOutput: console.info });
console.info("stack destroy complete");
process.exit(0);
}
console.info("updating stack...");
const upRes = await stack.up({ onOutput: console.info });
console.log(`update summary: \n${JSON.stringify(upRes.summary.resourceChanges, null, 4)}`);
console.log(`db host url: ${upRes.outputs.host.value}`);
console.info("configuring db...");
// establish mysql client
const connection = mysql.createConnection({
host: upRes.outputs.host.value,
user: upRes.outputs.dbUser.value,
password: upRes.outputs.dbPass.value,
database: upRes.outputs.dbName.value
});
// create table and populate it
if (createdb) {
connection.connect();
console.log("creating table...")
// make sure the table exists
connection.query(`
CREATE TABLE IF NOT EXISTS hello_pulumi(
id int(9) NOT NULL,
color varchar(14) NOT NULL,
PRIMARY KEY(id)
);
`, function (error, results, fields) {
if (error) throw error;
console.log("table created!")
console.log('Result: ', JSON.stringify(results));
console.log("seeding initial data...")
});
// seed the table with some data to start
connection.query(`
INSERT IGNORE INTO hello_pulumi (id, color)
VALUES
(1, 'Purple'),
(2, 'Violet'),
(3, 'Plum');
`, function (error, results, fields) {
if (error) throw error;
console.log("rows inserted!")
console.log('Result: ', JSON.stringify(results));
console.log("querying to veryify data...")
});
// read the data back
connection.query(`SELECT COUNT(*) FROM hello_pulumi;`, function (error, results, fields) {
if (error) throw error;
console.log('Result: ', JSON.stringify(results));
console.log("database, tables, and rows successfuly configured!")
});
connection.end();
}
// MySQL command to check tables for integrity errors
if (checktable) {
connection.connect();
console.log("checking table...")
if (tableName) {
connection.query(`CHECK TABLE ${tableName};`, function (error, results, fields) {
if (error) throw error;
console.log('Result: ', JSON.stringify(results));
console.log("table checked for integrity errors!")});
} else {
console.log("Error: Table not specified.");
console.log("Try: yarn start checktable {table name}");
}
connection.end();
}
// MySQL command to rebuild index for slow database response
if (analyze) {
connection.connect();
console.log(" analyze table...")
if (tableName) {
connection.query(`ANALYZE TABLE ${tableName};`, function (error, results, fields) {
if (error) throw error;
console.log('Result: ', JSON.stringify(results));
console.log("table index rebuilt!")});
} else {
console.log("Error: Table not specified.");
console.log("Try: yarn start analyze {table name}");
}
connection.end();
}
// MySQL command to reclaim space and rebuild tables and indices
if (optimize) {
connection.connect();
console.log(" optimize table...")
if (tableName) {
connection.query(`OPTIMIZE TABLE ${tableName};`, function (error, results, fields) {
if (error) throw error;
console.log('Result: ', JSON.stringify(results));
console.log("table space reclaimed, table and index rebuilt!")});
} else {
console.log("Error: Table not specified.");
console.log("Try: yarn start analyze {table name}");
}
connection.end();
}
};
run().catch(err => console.log(err));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment