Skip to content

Commit 9098381

Browse files
committed
Add list quotas with limit one script
1 parent f0b61d2 commit 9098381

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed

scripts/listQuotasWithLimitOne.ts

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
/*
5+
How to run this script:
6+
7+
If running as part of the Quota Monitor for AWS solution code:
8+
1. Ensure you have AWS CLI installed and configured with appropriate credentials.
9+
Run 'aws configure' to set up your AWS environment.
10+
11+
2. Navigate to the root directory of the Quota Monitor for AWS solution.
12+
13+
3. Install dependencies (if not already done or if there have been updates):
14+
npm install
15+
16+
4. Compile and run the script:
17+
- Compile TypeScript to JavaScript:
18+
npx tsc scripts/listQuotasWithLimitOne.ts
19+
- Run the compiled JavaScript:
20+
node scripts/listQuotasWithLimitOne.js
21+
22+
If running as a standalone script:
23+
24+
Prerequisites:
25+
1. Ensure you have AWS CLI installed and configured with appropriate credentials.
26+
Run 'aws configure' to set up your AWS environment.
27+
28+
2. Install Node.js and npm (Node Package Manager) on your system.
29+
Download from: https://nodejs.org/ if not already installed.
30+
31+
3. Install required dependencies:
32+
- Create a package.json file in the same directory as this script (if not exists):
33+
npm init -y
34+
- Install required packages:
35+
npm install @aws-sdk/client-service-quotas
36+
- Install dev dependencies for TypeScript:
37+
npm install --save-dev typescript @types/node
38+
39+
4. Compile and run the script:
40+
- Compile TypeScript to JavaScript:
41+
npx tsc script_name.ts
42+
- Run the compiled JavaScript:
43+
node script_name.js
44+
45+
Note: Replace 'script_name' with the actual name of this file.
46+
47+
*/
48+
49+
import { ServiceQuotasClient, paginateListServiceQuotas, paginateListServices } from "@aws-sdk/client-service-quotas";
50+
import * as fs from "fs";
51+
import * as path from "path";
52+
53+
const CONFIG = {
54+
MAX_RETRIES: 5,
55+
BATCH_SIZE: 5,
56+
BATCH_DELAY_MS: 1500,
57+
};
58+
59+
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
60+
61+
async function retryWithExponentialBackoff<T>(operation: () => Promise<T>, retryCount: number = 0): Promise<T> {
62+
try {
63+
return await operation();
64+
} catch (error: any) {
65+
if (error.name === "TooManyRequestsException" && retryCount < CONFIG.MAX_RETRIES) {
66+
const delay = Math.pow(2, retryCount) * 1000 + Math.random() * 1000;
67+
console.log(`Rate limited. Retrying in ${delay}ms...`);
68+
await sleep(delay);
69+
return retryWithExponentialBackoff(operation, retryCount + 1);
70+
}
71+
throw error;
72+
}
73+
}
74+
75+
async function getServiceCodes(client: ServiceQuotasClient): Promise<string[]> {
76+
const codes: string[] = [];
77+
const servicesPaginator = paginateListServices({ client }, {});
78+
for await (const page of servicesPaginator) {
79+
if (page.Services) {
80+
codes.push(
81+
...page.Services.map((service) => service.ServiceCode).filter((code): code is string => code !== undefined)
82+
);
83+
}
84+
}
85+
return codes;
86+
}
87+
88+
interface QuotaInfo {
89+
quotaCode: string;
90+
quotaName: string;
91+
}
92+
93+
async function getQuotasForService(client: ServiceQuotasClient, serviceCode: string): Promise<QuotaInfo[]> {
94+
try {
95+
const quotaInfo: QuotaInfo[] = [];
96+
const quotasPaginator = paginateListServiceQuotas({ client }, { ServiceCode: serviceCode });
97+
for await (const page of quotasPaginator) {
98+
if (page.Quotas) {
99+
const filteredQuotas = page.Quotas.filter(
100+
(quota) =>
101+
quota.Value === 1 &&
102+
quota.UsageMetric?.MetricNamespace === "AWS/Usage" &&
103+
quota.QuotaCode !== undefined &&
104+
quota.QuotaName !== undefined
105+
);
106+
quotaInfo.push(
107+
...filteredQuotas.map((quota) => ({
108+
quotaCode: quota.QuotaCode as string,
109+
quotaName: quota.QuotaName as string,
110+
}))
111+
);
112+
}
113+
}
114+
return quotaInfo;
115+
} catch (error: any) {
116+
if (error.name === "TooManyRequestsException") {
117+
throw error;
118+
}
119+
console.error(`Error processing service ${serviceCode}:`, error);
120+
return [];
121+
}
122+
}
123+
124+
async function getAllServicesQuotasWithLimitOne() {
125+
const client = new ServiceQuotasClient({});
126+
const result: { [serviceCode: string]: QuotaInfo[] } = {};
127+
128+
try {
129+
const serviceCodes = await retryWithExponentialBackoff(() => getServiceCodes(client));
130+
console.log(`Total services found: ${serviceCodes.length}`);
131+
132+
for (let i = 0; i < serviceCodes.length; i += CONFIG.BATCH_SIZE) {
133+
const batch = serviceCodes.slice(i, i + CONFIG.BATCH_SIZE);
134+
const batchResults = await Promise.all(
135+
batch.map(async (serviceCode) => {
136+
try {
137+
const quotaInfo = await retryWithExponentialBackoff(() => getQuotasForService(client, serviceCode));
138+
return { serviceCode, quotaInfo };
139+
} catch (error) {
140+
console.error(`Error processing service ${serviceCode}:`, error);
141+
return { serviceCode, quotaInfo: [] };
142+
}
143+
})
144+
);
145+
146+
batchResults.forEach(({ serviceCode, quotaInfo }) => {
147+
if (quotaInfo.length > 0) {
148+
result[serviceCode] = quotaInfo;
149+
}
150+
console.log(` Quotas with limit 1 and metrics for ${serviceCode}: ${quotaInfo.length}`);
151+
});
152+
153+
await sleep(CONFIG.BATCH_DELAY_MS);
154+
}
155+
156+
return result;
157+
} catch (error) {
158+
console.error("Error fetching quotas:", error);
159+
return result;
160+
}
161+
}
162+
163+
async function main() {
164+
console.time("Execution Time");
165+
const quotasWithLimitOne = await getAllServicesQuotasWithLimitOne();
166+
167+
const outputPath = path.join(__dirname, "quotasWithLimitOne.json");
168+
fs.writeFileSync(outputPath, JSON.stringify(quotasWithLimitOne, null, 2));
169+
170+
const totalQuotas = Object.values(quotasWithLimitOne).reduce((sum, quotaInfo) => sum + quotaInfo.length, 0);
171+
console.log(`Total quotas with limit 1 and usage metrics across all services: ${totalQuotas}`);
172+
console.log(`Results have been written to: ${outputPath}`);
173+
console.timeEnd("Execution Time");
174+
}
175+
176+
main();

0 commit comments

Comments
 (0)