Last active
November 18, 2020 14:22
-
-
Save pulumipus/61edcdd8ab3f50a42b4bd34a7e1f789b to your computer and use it in GitHub Desktop.
Extended Pulumi Automation API workflow orchestration example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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