Skip to content

Instantly share code, notes, and snippets.

@dontlaugh
Last active August 6, 2020 16:57
Show Gist options
  • Save dontlaugh/1ccf92015d2e990b95b6ebeaa32cdc13 to your computer and use it in GitHub Desktop.
Save dontlaugh/1ccf92015d2e990b95b6ebeaa32cdc13 to your computer and use it in GitHub Desktop.
Deno AWS cli example
#!/usr/bin/env -S deno run --allow-read --allow-net --allow-run
/*
This script prints out a list of VPCs, subnets, and route tables.
The output will be different depending on which AWS account you are
connected to.
*/
const {stdout, copy} = Deno;
import iro, {
bold, red, dim, yellow, white, blue, cyan, green
} from "https://cdn.jsdelivr.net/npm/node-iro@1.0.1/src/iro.ts";
async function main() {
let networks = new Array<Network>();
let vpcs: Vpc[] = await getVpcs();
for (let vpc of vpcs) {
let n = await buildNetwork(vpc);
networks.push(n);
}
for (let [vpc, subnets, routeTables] of networks) {
let vpcName = iro(vpc.name, bold, yellow);
let vpcId = iro(vpc.id, dim, yellow);
let vpcLabel = iro("vpc:", dim, white);
let vpcCidr = iro(vpc.cidrBlock, dim, yellow)
console.log(`${vpcLabel} ${vpcName} ${vpcId} ${vpcCidr}`);
let numSubnets = iro(`number of subnets: ${subnets.length}`, dim, cyan);
console.log(numSubnets);
for (let sn of subnets) {
let subnetName = iro(sn.name, bold, blue);
let subnetId = iro(sn.id, dim, blue);
console.log(` ${subnetId} ${subnetName}`)
}
for (let rt of routeTables) {
let rtId = iro(`${rt.id}`, green)
let mainRt = iro(rt.main ? "main" : "", bold, red)
let routeTableLabel = iro("route table", green, dim);
let routes = iro(rt.routes.join(" "), bold, green)
let routesLabel = iro("routes: ", dim, green)
let assocLabel = iro("associations: ", dim, green)
let assoc = iro(rt.assocations.join(" "), dim, green)
console.log(` ${routeTableLabel} ${rtId} ${mainRt}`)
console.log(` ${routesLabel} ${routes}`)
console.log(` ${assocLabel} ${assoc}`)
}
console.log("");
}
}
async function buildNetwork(vpc: Vpc): Promise<Network> {
let subnets = await getSubnets(vpc.id);
let routeTables = await getRouteTables(vpc.id);
return [vpc, subnets, routeTables];
}
async function getVpcs(withDefaultVpc: boolean = false): Promise<Vpc[]> {
let [success, output] = await commandWithOutput(
["aws", "ec2", "describe-vpcs", "--filter", `Name=isDefault,Values=${withDefaultVpc}`]);
if (!success) throw Error("getVpcs failed")
const decoder = new TextDecoder('utf-8');
let response: Array<{[key: string]: any}> = JSON.parse(decoder.decode(output))["Vpcs"];
let vpcs = new Array<Vpc>();
for (let obj of response) {
let vpc: Vpc = {
cidrBlock: obj["CidrBlock"],
name: getAWSTag("Name", obj["Tags"]),
id: obj["VpcId"],
};
vpcs.push(vpc);
}
return vpcs;
}
async function getRouteTables(vpcId: string): Promise<RouteTable[]> {
let [success, output] = await commandWithOutput(
["aws", "ec2", "describe-route-tables", "--filters", `Name=vpc-id,Values=${vpcId}`]);
if (!success) {
throw Error("getRouteTables failed")
}
const decoder = new TextDecoder('utf-8');
let rts: Array<{[key: string]: any}> = JSON.parse(decoder.decode(output))["RouteTables"];
let routeTables = new Array<RouteTable>();
for (let obj of rts) {
let isMain: boolean = obj["Associations"].filter((assoc: {[key: string]: any}) => {
if (assoc.hasOwnProperty("Main")) {
return assoc["Main"];
}
}).length == 1;
let associations: string[] = obj["Associations"]
.filter((assoc: {[key: string]: any}) => assoc.hasOwnProperty("SubnetId"))
.map((assoc: {[key: string]: any}) => {
return assoc["SubnetId"]
});
let routes: string[] = obj["Routes"].map((r: {[key: string]: any})=> {
return r["DestinationCidrBlock"]
});
let rt: RouteTable = {
id: obj["RouteTableId"],
main: isMain,
assocations: associations,
routes: routes,
};
routeTables.push(rt);
}
return routeTables;
}
async function getSubnets(vpcId: string): Promise<Subnet[]> {
let [success, output] = await commandWithOutput(
["aws", "ec2", "describe-subnets", "--filters", `Name=vpc-id,Values=${vpcId}`]);
if (!success) {
throw Error("getSubnets failed")
}
const decoder = new TextDecoder('utf-8');
let response: Array<{[key: string]: any}> = JSON.parse(decoder.decode(output))["Subnets"];
let subnets = new Array<Subnet>();
for (let obj of response) {
let s: Subnet = {
id: obj["SubnetId"],
name: getAWSTag("Name", obj["Tags"]),
};
subnets.push(s);
}
return subnets;
}
async function commandWithOutput(cmd: string[]): Promise<[boolean, ArrayBuffer]> {
let result = Deno.run({
cmd: cmd,
stdout: "piped",
});
let status = await result.status();
let output = await result.output();
return [status.success, output];
}
function getAWSTag(key: string, tags: Array<{[key: string]: string}>): string {
let filtered = tags.filter((o) => o["Key"] == key);
if (filtered.length < 1) {
return `(${key} MISSING)`
}
return filtered[0]["Value"];
}
interface Vpc {
id: string,
name: string,
cidrBlock: string,
}
interface Subnet {
id: string,
name: string,
}
interface RouteTable {
id: string
main: boolean,
routes: string[],
assocations: string[],
}
type Network = [Vpc, Subnet[], RouteTable[]];
await main();
/*
TODO: More aws ec2 subecommands:
describe-local-gateway-route-tables
describe-local-gateways
describe-nat-gateways
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment