|
| 1 | +import type { Group, AtlasOrganization } from "../src/common/atlas/openapi.js"; |
| 2 | +import { ApiClient } from "../src/common/atlas/apiClient.js"; |
| 3 | +import { ConsoleLogger } from "../src/common/logger.js"; |
| 4 | +import { Keychain } from "../src/lib.js"; |
| 5 | +import { describe, it } from "vitest"; |
| 6 | + |
| 7 | +function isOlderThanADay(date: string): boolean { |
| 8 | + const oneDayInMs = 24 * 60 * 60 * 1000; |
| 9 | + const projectDate = new Date(date); |
| 10 | + const currentDate = new Date(); |
| 11 | + return currentDate.getTime() - projectDate.getTime() > oneDayInMs; |
| 12 | +} |
| 13 | + |
| 14 | +async function findTestOrganization(client: ApiClient): Promise<AtlasOrganization> { |
| 15 | + const orgs = await client.listOrganizations(); |
| 16 | + const testOrg = orgs?.results?.find((org) => org.name === "MongoDB MCP Test"); |
| 17 | + |
| 18 | + if (!testOrg) { |
| 19 | + throw new Error('Test organization "MongoDB MCP Test" not found.'); |
| 20 | + } |
| 21 | + |
| 22 | + return testOrg; |
| 23 | +} |
| 24 | + |
| 25 | +async function findAllTestProjects(client: ApiClient, orgId: string): Promise<Group[]> { |
| 26 | + const projects = await client.listOrganizationProjects({ |
| 27 | + params: { |
| 28 | + path: { |
| 29 | + orgId, |
| 30 | + }, |
| 31 | + }, |
| 32 | + }); |
| 33 | + |
| 34 | + const testProjects = projects?.results?.filter((proj) => proj.name.startsWith("testProj-")) || []; |
| 35 | + return testProjects.filter((proj) => isOlderThanADay(proj.created)); |
| 36 | +} |
| 37 | + |
| 38 | +async function deleteAllClustersOnStaleProject(client: ApiClient, projectId: string): Promise<void> { |
| 39 | + const allClusters = await client |
| 40 | + .listClusters({ |
| 41 | + params: { |
| 42 | + path: { |
| 43 | + groupId: projectId || "", |
| 44 | + }, |
| 45 | + }, |
| 46 | + }) |
| 47 | + .then((res) => res.results || []); |
| 48 | + |
| 49 | + await Promise.allSettled( |
| 50 | + allClusters.map((cluster) => |
| 51 | + client.deleteCluster({ params: { path: { groupId: projectId || "", clusterName: cluster.name || "" } } }) |
| 52 | + ) |
| 53 | + ); |
| 54 | +} |
| 55 | + |
| 56 | +async function main(): Promise<void> { |
| 57 | + const apiClient = new ApiClient( |
| 58 | + { |
| 59 | + baseUrl: process.env.MDB_MCP_API_BASE_URL || "https://cloud-dev.mongodb.com", |
| 60 | + credentials: { |
| 61 | + clientId: process.env.MDB_MCP_API_CLIENT_ID || "", |
| 62 | + clientSecret: process.env.MDB_MCP_API_CLIENT_SECRET || "", |
| 63 | + }, |
| 64 | + }, |
| 65 | + new ConsoleLogger(Keychain.root) |
| 66 | + ); |
| 67 | + |
| 68 | + const testOrg = await findTestOrganization(apiClient); |
| 69 | + const testProjects = await findAllTestProjects(apiClient, testOrg.id || ""); |
| 70 | + |
| 71 | + if (testProjects.length === 0) { |
| 72 | + console.log("No stale test projects found for cleanup."); |
| 73 | + } |
| 74 | + |
| 75 | + for (const project of testProjects) { |
| 76 | + console.log(`Cleaning up project: ${project.name} (${project.id})`); |
| 77 | + if (!project.id) { |
| 78 | + console.warn(`Skipping project with missing ID: ${project.name}`); |
| 79 | + continue; |
| 80 | + } |
| 81 | + |
| 82 | + await deleteAllClustersOnStaleProject(apiClient, project.id); |
| 83 | + await apiClient.deleteProject({ |
| 84 | + params: { |
| 85 | + path: { |
| 86 | + groupId: project.id, |
| 87 | + }, |
| 88 | + }, |
| 89 | + }); |
| 90 | + console.log(`Deleted project: ${project.name} (${project.id})`); |
| 91 | + } |
| 92 | + |
| 93 | + return; |
| 94 | +} |
| 95 | + |
| 96 | +describe("Cleanup Atlas Test Leftovers", () => { |
| 97 | + it("should clean up stale test projects", async () => { |
| 98 | + await main(); |
| 99 | + }); |
| 100 | +}); |
0 commit comments