Skip to content

Commit ceba258

Browse files
committed
feat: support flex clusters to atlas tools
1 parent 4a0db37 commit ceba258

File tree

8 files changed

+528
-93
lines changed

8 files changed

+528
-93
lines changed

scripts/filter.ts

+4
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ function filterOpenapi(openapi: OpenAPIV3_1.Document): OpenAPIV3_1.Document {
2525
"createProject",
2626
"deleteProject",
2727
"listClusters",
28+
"listFlexClusters",
2829
"getCluster",
30+
"getFlexCluster",
2931
"createCluster",
32+
"createFlexCluster",
3033
"deleteCluster",
34+
"deleteFlexCluster",
3135
"listClustersForAllProjects",
3236
"createDatabaseUser",
3337
"deleteDatabaseUser",

src/common/atlas/apiClient.ts

+40
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,46 @@ export class ApiClient {
275275
}
276276
}
277277

278+
async listFlexClusters(options: FetchOptions<operations["listFlexClusters"]>) {
279+
const { data, error, response } = await this.client.GET("/api/atlas/v2/groups/{groupId}/flexClusters", options);
280+
if (error) {
281+
throw ApiClientError.fromError(response, error);
282+
}
283+
return data;
284+
}
285+
286+
async createFlexCluster(options: FetchOptions<operations["createFlexCluster"]>) {
287+
const { data, error, response } = await this.client.POST(
288+
"/api/atlas/v2/groups/{groupId}/flexClusters",
289+
options
290+
);
291+
if (error) {
292+
throw ApiClientError.fromError(response, error);
293+
}
294+
return data;
295+
}
296+
297+
async deleteFlexCluster(options: FetchOptions<operations["deleteFlexCluster"]>) {
298+
const { error, response } = await this.client.DELETE(
299+
"/api/atlas/v2/groups/{groupId}/flexClusters/{name}",
300+
options
301+
);
302+
if (error) {
303+
throw ApiClientError.fromError(response, error);
304+
}
305+
}
306+
307+
async getFlexCluster(options: FetchOptions<operations["getFlexCluster"]>) {
308+
const { data, error, response } = await this.client.GET(
309+
"/api/atlas/v2/groups/{groupId}/flexClusters/{name}",
310+
options
311+
);
312+
if (error) {
313+
throw ApiClientError.fromError(response, error);
314+
}
315+
return data;
316+
}
317+
278318
async listOrganizations(options?: FetchOptions<operations["listOrganizations"]>) {
279319
const { data, error, response } = await this.client.GET("/api/atlas/v2/orgs", options);
280320
if (error) {

src/common/atlas/cluster.ts

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { ClusterDescription20240805, FlexClusterDescription20241113 } from "./openapi.js";
2+
import { ApiClient } from "./apiClient.js";
3+
4+
export interface Cluster {
5+
name?: string;
6+
instanceType: "FREE" | "DEDICATED" | "FLEX";
7+
instanceSize?: string;
8+
state?: "IDLE" | "CREATING" | "UPDATING" | "DELETING" | "REPAIRING" | "UNKNOWN";
9+
mongoDBVersion?: string;
10+
connectionString?: string;
11+
}
12+
13+
export function formatFlexCluster(cluster: FlexClusterDescription20241113): Cluster {
14+
return {
15+
name: cluster.name,
16+
instanceType: "FLEX",
17+
instanceSize: undefined,
18+
state: cluster.stateName,
19+
mongoDBVersion: cluster.mongoDBVersion,
20+
connectionString: cluster.connectionStrings?.standardSrv || cluster.connectionStrings?.standard,
21+
};
22+
}
23+
24+
export function formatCluster(cluster: ClusterDescription20240805): Cluster {
25+
const regionConfigs = (cluster.replicationSpecs || [])
26+
.map(
27+
(replicationSpec) =>
28+
(replicationSpec.regionConfigs || []) as {
29+
providerName: string;
30+
electableSpecs?: {
31+
instanceSize: string;
32+
};
33+
readOnlySpecs?: {
34+
instanceSize: string;
35+
};
36+
analyticsSpecs?: {
37+
instanceSize: string;
38+
};
39+
}[]
40+
)
41+
.flat()
42+
.map((regionConfig) => {
43+
return {
44+
providerName: regionConfig.providerName,
45+
instanceSize:
46+
regionConfig.electableSpecs?.instanceSize ||
47+
regionConfig.readOnlySpecs?.instanceSize ||
48+
regionConfig.analyticsSpecs?.instanceSize,
49+
};
50+
});
51+
52+
const instanceSize = (regionConfigs.length <= 0 ? undefined : regionConfigs[0].instanceSize) || "UNKNOWN";
53+
54+
const clusterInstanceType = instanceSize == "M0" ? "FREE" : "DEDICATED";
55+
56+
return {
57+
name: cluster.name,
58+
instanceType: clusterInstanceType,
59+
instanceSize: clusterInstanceType == "DEDICATED" ? instanceSize : undefined,
60+
state: cluster.stateName,
61+
mongoDBVersion: cluster.mongoDBVersion,
62+
connectionString: cluster.connectionStrings?.standardSrv || cluster.connectionStrings?.standard,
63+
};
64+
}
65+
66+
export async function inspectCluster(apiClient: ApiClient, projectId: string, clusterName: string): Promise<Cluster> {
67+
try {
68+
const cluster = await apiClient.getCluster({
69+
params: {
70+
path: {
71+
groupId: projectId,
72+
clusterName,
73+
},
74+
},
75+
});
76+
return formatCluster(cluster);
77+
} catch (error) {
78+
try {
79+
const cluster = await apiClient.getFlexCluster({
80+
params: {
81+
path: {
82+
groupId: projectId,
83+
name: clusterName,
84+
},
85+
},
86+
});
87+
return formatFlexCluster(cluster);
88+
} catch {
89+
throw error;
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)