Skip to content

Commit bbc5687

Browse files
authored
findAvailableRegions implementation + documentation (#111)
* findAvailableRegions implementation + documentation * update AstraFindAvailableRegionsOptions to use CommandOptions instead of WithTimeout * add integration test for findAvailableRegions
1 parent d33c5c4 commit bbc5687

File tree

5 files changed

+254
-2
lines changed

5 files changed

+254
-2
lines changed

src/administration/astra-admin.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import type {
1717
AstraDatabaseConfig,
1818
CreateAstraDatabaseOptions,
1919
ListAstraDatabasesOptions,
20+
AstraAvailableRegionInfo, AstraFindAvailableRegionsOptions,
2021
} from '@/src/administration/types/index.js';
2122
import { AstraDbAdmin } from '@/src/administration/astra-db-admin.js';
2223
import { Db } from '@/src/db/db.js';
@@ -471,6 +472,71 @@ export class AstraAdmin extends HierarchicalLogger<AdminCommandEventMap> {
471472
});
472473
}
473474

475+
/**
476+
* ##### Overview
477+
*
478+
* Finds available regions for Astra database deployments.
479+
*
480+
* The returned information includes details about each region such as its cloud provider,
481+
* classification tier, geographic zone, and availability status.
482+
*
483+
* @example
484+
* ```ts
485+
* // Find all regions enabled for the current organization (default)
486+
* const enabledRegions = await admin.findAvailableRegions();
487+
*
488+
* // Find AWS regions in North America
489+
* const awsNaRegions = allRegions
490+
* .filter(r => r.cloudProvider === 'AWS' && r.zone === 'na');
491+
* ```
492+
*
493+
* ---
494+
*
495+
* ##### Including non-org-enabled regions
496+
*
497+
* By default, it returns only regions that are enabled for the current organization, but this behavior can be controlled with the {@link AstraFindAvailableRegionsOptions.onlyOrgEnabledRegions} option.
498+
*
499+
* @example
500+
* ```ts
501+
* // Find all regions, including those not enabled for the current organization
502+
* const allRegions = await admin.findAvailableRegions({
503+
* onlyOrgEnabledRegions: false,
504+
* });
505+
* ```
506+
*
507+
* @param options - Options for filtering the regions to return
508+
*
509+
* @returns A promise that resolves to an array of the region information
510+
*
511+
* @see AstraAvailableRegionInfo
512+
* @see AstraRegionClassification
513+
*/
514+
public async findAvailableRegions(options?: AstraFindAvailableRegionsOptions): Promise<AstraAvailableRegionInfo[]> {
515+
const tm = this.#httpClient.tm.single('databaseAdminTimeoutMs', options);
516+
517+
const filterByOrg = options?.onlyOrgEnabledRegions !== false ? 'enabled' : 'disabled';
518+
519+
const resp = await this.#httpClient.request({
520+
method: HttpMethods.Get,
521+
path: '/regions/serverless',
522+
params: {
523+
'filter-by-org': filterByOrg,
524+
'region-type': 'vector',
525+
},
526+
methodName: 'admin.findAvailableRegions',
527+
}, tm);
528+
529+
return resp.data!.map((region: any): AstraAvailableRegionInfo => ({
530+
classification: region.classification,
531+
cloudProvider: region.cloudProvider,
532+
displayName: region.displayName,
533+
enabled: region.enabled,
534+
name: region.name,
535+
reservedForQualifiedUsers: region.reservedForQualifiedUsers,
536+
zone: region.zone,
537+
}));
538+
}
539+
474540
public get _httpClient(): OpaqueHttpClient {
475541
return this.#httpClient;
476542
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright DataStax, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import type { AstraDatabaseCloudProvider } from './admin-common.js';
16+
import type { CommandOptions } from '@/src/lib/index.js';
17+
18+
/**
19+
* ##### Overview
20+
*
21+
* The options for {@link AstraAdmin.findAvailableRegions}.
22+
*
23+
* @example
24+
* ```ts
25+
* const regions = await admin.findAvailableRegions({
26+
* onlyOrgEnabledRegions: false,
27+
* });
28+
* ```
29+
*
30+
* @see AstraAdmin.findAvailableRegions
31+
* @see AstraAvailableRegionInfo
32+
*
33+
* @public
34+
*/
35+
export interface AstraFindAvailableRegionsOptions extends CommandOptions<{ timeout: 'databaseAdminTimeoutMs' }> {
36+
/**
37+
* Whether to only return regions that are enabled for the current organization.
38+
*
39+
* - When `true` or unset: only returns regions enabled for the current organization.
40+
* - When `false`: returns all available regions, including those not enabled for the organization.
41+
*
42+
* Note that the organization is determined by the token used to authenticate the request.
43+
*
44+
* Defaults to `true`.
45+
*/
46+
onlyOrgEnabledRegions?: boolean,
47+
}
48+
49+
/**
50+
* ##### Overview
51+
*
52+
* Represents the classification tier of an Astra database region.
53+
*
54+
* Region availability will depend on the user's account level.
55+
*
56+
* @see AstraAvailableRegionInfo
57+
*
58+
* @public
59+
*/
60+
export type AstraRegionClassification = 'standard' | 'premium' | 'premium_plus';
61+
62+
/**
63+
* ##### Overview
64+
*
65+
* Represents the geographic zone where an Astra database region is located.
66+
*
67+
* - `'na'`: North America
68+
* - `'emea'`: Europe, Middle East, and Africa
69+
* - `'apac'`: Asia Pacific
70+
* - `'sa'`: South America
71+
*
72+
* @see AstraAvailableRegionInfo
73+
*
74+
* @public
75+
*/
76+
export type AstraRegionZone = 'na' | 'apac' | 'emea' | 'sa';
77+
78+
/**
79+
* ##### Overview
80+
*
81+
* Information about an available region for Astra database deployments.
82+
*
83+
* This provides details about each available region including classification, cloud provider, display name, and availability status.
84+
*
85+
* @example
86+
* ```ts
87+
* // Basic usage
88+
* const regions = await admin.findAvailableRegions();
89+
* console.log(regions[0].displayName); // 'Moncks Corner, South Carolina'
90+
*
91+
* // Further filterting & transformation may be done using native list methods
92+
* const awsRegions = regions.filter(region => region.cloudProvider === 'AWS');
93+
* ```
94+
*
95+
* @see AstraAdmin.findAvailableRegions
96+
* @see AstraFindAvailableRegionsOptions
97+
*
98+
* @public
99+
*/
100+
export interface AstraAvailableRegionInfo {
101+
/**
102+
* Represents the classification tier of an Astra database region.
103+
*
104+
* Region availability will depend on the user's account level.
105+
*
106+
* @example
107+
* ```ts
108+
* 'standard'
109+
* ```
110+
*/
111+
classification: AstraRegionClassification,
112+
/**
113+
* The cloud provider hosting this region.
114+
*
115+
* @example
116+
* ```ts
117+
* 'GCP'
118+
* ```
119+
*/
120+
cloudProvider: AstraDatabaseCloudProvider,
121+
/**
122+
* A human-readable display name for the region.
123+
*
124+
* @example
125+
* ```ts
126+
* 'Moncks Corner, South Carolina'
127+
* ```
128+
*/
129+
displayName: string,
130+
/**
131+
* Whether this region is currently enabled for use.
132+
*
133+
* > **✏️Note:** If {@link AstraFindAvailableRegionsOptions.onlyOrgEnabledRegions} is `false`, and `enabled` is still `true`, it does not guarantee that the region is usable by the current organization.
134+
*/
135+
enabled: boolean,
136+
/**
137+
* The unique identifier for the region.
138+
*
139+
* @example
140+
* ```ts
141+
* 'us-east1'
142+
* ```
143+
*/
144+
name: string,
145+
/**
146+
* Whether this region is reserved for qualified users only, meaning special access is required to use it.
147+
*/
148+
reservedForQualifiedUsers: boolean,
149+
/**
150+
* The geographic zone where this region is located.
151+
*
152+
* @example
153+
* ```ts
154+
* 'na'
155+
* ```
156+
*/
157+
zone: AstraRegionZone,
158+
}

src/administration/types/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type * from './admin/create-database.js';
1717
export type * from './admin/drop-database.js';
1818
export type * from './admin/database-info.js';
1919
export type * from './admin/list-databases.js';
20+
export type * from './admin/find-available-regions.js';
2021
export type * from './db-admin/astra-create-keyspace.js';
2122
export type * from './db-admin/astra-drop-keyspace.js';
2223
export type * from './db-admin/local-create-keyspace.js';

src/documents/types/common.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ export type Projection = Record<string, 1 | 0 | boolean | ProjectionSlice>;
8585
* Specifies the number of elements in an array to return in the query result.
8686
*
8787
* Has one of the following forms:
88-
* ```
88+
*
89+
* ```ts
8990
* // Return the first two elements
9091
* { $slice: 2 }
9192
*

tests/integration/administration/astra-admin.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,39 @@
1414
// noinspection DuplicatedCode
1515

1616
import { describe, it } from '@/tests/testlib/index.js';
17+
import type { AstraAvailableRegionInfo } from '@/src/index.js';
1718
import { DataAPIClient, DevOpsAPIResponseError } from '@/src/index.js';
1819
import assert from 'assert';
1920

20-
describe('integration.administration.astra-admin', () => {
21+
describe('(ASTRA) integration.administration.astra-admin', ({ admin }) => {
2122
it('should not stop you from creating an AstraAdmin without a token', async () => {
2223
const client = new DataAPIClient();
2324
const admin = client.admin();
2425
await assert.rejects(() => admin.listDatabases(), DevOpsAPIResponseError);
2526
});
27+
28+
describe('findAvailableRegions', () => {
29+
it('should work', async () => {
30+
const verifyStructure = (region: AstraAvailableRegionInfo) => {
31+
assert.ok(region);
32+
assert.ok(['standard', 'premium', 'premium_plus'].includes(region.classification));
33+
assert.ok(['AWS', 'GCP', 'AZURE'].includes(region.cloudProvider));
34+
assert.ok(typeof region.displayName as unknown === 'string');
35+
assert.ok(typeof region.enabled as unknown === 'boolean');
36+
assert.ok(typeof region.name as unknown === 'string');
37+
assert.ok(typeof region.reservedForQualifiedUsers as unknown === 'boolean');
38+
assert.ok(['na', 'apac', 'emea', 'sa'].includes(region.zone));
39+
};
40+
41+
const regions = await admin.findAvailableRegions();
42+
assert.ok(regions.length);
43+
regions.forEach(verifyStructure);
44+
45+
const allRegions = await admin.findAvailableRegions({ onlyOrgEnabledRegions: false });
46+
assert.ok(allRegions.length);
47+
allRegions.forEach(verifyStructure);
48+
49+
assert.ok(regions.length < allRegions.length);
50+
});
51+
});
2652
});

0 commit comments

Comments
 (0)