Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions aws/security-groups/deleteRabbitorySG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import {
DeleteSecurityGroupCommand,
} from "@aws-sdk/client-ec2";

const GROUP_NAME = "RabbitorySG";

const isAwsError = (error: unknown): error is { name: string; message: string } => {
return typeof error === "object" && error !== null && "name" in error && "message" in error;
};

const getSecurityGroupId = async (client: EC2Client): Promise<string | null> => {
const getRabbitorySGIds = async (client: EC2Client): Promise<string[]> => {
try {
const command = new DescribeSecurityGroupsCommand({ GroupNames: [GROUP_NAME] });
const command = new DescribeSecurityGroupsCommand({});
const response = await client.send(command);
return response.SecurityGroups?.[0]?.GroupId ?? null;
const regex = /(^rabbitmq(-[a-z]+){4}$|^rabbitory)/i
return response.SecurityGroups?.reduce<string[]>((ids, sg) => {
const groupName = sg.GroupName?.toLowerCase();
if (sg.GroupId && groupName && regex.test(groupName)) {
ids.push(sg.GroupId);
}
return ids;
}, []) ?? [];
} catch (error: unknown) {
if (isAwsError(error) && error.name === "InvalidGroup.NotFound") return null; // return if SG does not exist
throw new Error(`Error retrieving security group ID for ${GROUP_NAME}\n${error instanceof Error ? error.message : String(error)}`);
throw new Error(`Error retrieving Rabbitory security groups\n${error instanceof Error ? error.message : String(error)}`);
}
};

Expand All @@ -37,10 +37,11 @@ export const deleteRabbitorySG = async (region: string): Promise<void> => {
const client = new EC2Client({ region: region });

try {
const securityGroupId = await getSecurityGroupId(client);
if (!securityGroupId) return; // return if no sg exists
await deleteSecurityGroup(securityGroupId, client);
const securityGroupIds = await getRabbitorySGIds(client);
for (const sgId of securityGroupIds) {
await deleteSecurityGroup(sgId, client);
}
} catch (error: unknown) {
throw new Error(`Failed to delete RabbitorySG\n${error instanceof Error ? error.message : String(error)}`);
throw new Error(`Failed to delete Rabbitory security groups\n${error instanceof Error ? error.message : String(error)}`);
}
};
65 changes: 45 additions & 20 deletions cli/destroy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,80 @@ import { getInstanceIdsByPublisher } from "./getInstanceIdsByPublisher";
import { runWithSpinner } from "./spinner";
import { getRegion } from "./getRegion";
import chalk from "chalk";
import { fetchAllRegions } from "./fetchAllRegions";

const deleteAllBrokerInstances = async (regions: string[]) => {
for (const region of regions) {
const brokerIds = await getInstanceIdsByPublisher("Rabbitory", region);
if (brokerIds !== undefined) {
for (const brokerId of brokerIds) {
await deleteInstance(brokerId, region);
}
}
}
}

const deleteAllSecurityGroups = async (regions: string[]) => {
for (const region of regions) {
await deleteRabbitorySG(region);
}
}

export const destroy = async () => {
try {
const controlPanelName = "RabbitoryControlPanel";
const region: string = await getRegion();
const brokerIds = await getInstanceIdsByPublisher("Rabbitory", region);
const instanceIds: string[] | undefined = await getRunningInstanceIdsByName(
controlPanelName,
region,
);
const instanceId: string | undefined =
instanceIds !== undefined && instanceIds.length > 0
? instanceIds[0]
: undefined;
const primaryRegion: string = await getRegion();

const regions = await fetchAllRegions();

if (!regions || regions.length === 0) {
console.error("Error fetching regions");
process.exit(1);
}

await runWithSpinner(
"Deleting DynamoDB Table...",
() => deleteTable(region),
() => deleteTable(primaryRegion),
"Deleted DynamoDB Table",
);

await runWithSpinner(
"Deleting RabbitMQ Broker Instances...",
() =>
Promise.all(brokerIds?.map((id) => deleteInstance(id, region)) || []),
"Deleted RabbitMQ Broker Instances",
const instanceIds: string[] | undefined = await getRunningInstanceIdsByName(
controlPanelName,
primaryRegion,
);
const instanceId: string | undefined =
instanceIds !== undefined && instanceIds.length > 0
? instanceIds[0]
: undefined;

if (instanceId !== undefined) {
await runWithSpinner(
"Terminating Control Panel EC2 instance...",
() => deleteInstance(instanceId, region),
() => deleteInstance(instanceId, primaryRegion),
"Terminated EC2 instance",
);
}

await runWithSpinner(
"Deleting RabbitMQ Broker Instances...",
() => deleteAllBrokerInstances(regions),
"Deleted RabbitMQ Broker Instances",
);

await runWithSpinner(
"Deleting Rabbitory security group...",
() => deleteRabbitorySG(region),
() => deleteAllSecurityGroups(regions),
"Deleted Rabbitory security group",
);

await runWithSpinner(
"Deleting RMQ Broker IAM role...",
() => deleteBrokerRole(region),
() => deleteBrokerRole(primaryRegion),
"Deleted RMQ Broker IAM role",
);
await runWithSpinner(
"Deleting Rabbitory IAM role...",
() => deleteRabbitoryRole(region),
() => deleteRabbitoryRole(primaryRegion),
"Deleted Rabbitory IAM role",
);
} catch (error) {
Expand Down
15 changes: 15 additions & 0 deletions cli/fetchAllRegions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { EC2Client, DescribeRegionsCommand } from "@aws-sdk/client-ec2";

export const fetchAllRegions = async () => {
const client = new EC2Client({ region: "us-east-1" });

try {
const command = new DescribeRegionsCommand({});
const response = await client.send(command);
const regions = response.Regions?.map(region => region.RegionName);
if (regions === undefined) throw new Error("Error fetching regions");
return regions.filter((region) => region !== undefined);
} catch (error) {
console.error("Error fetching regions:", error);
}
};