cdk-cost-analyzer 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,35 +2,35 @@
2
2
  "entries": {
3
3
  "AmazonS3:US East (N. Virginia):storageClass:General Purpose|volumeType:Standard": {
4
4
  "price": 0.023,
5
- "timestamp": 1769022317313
5
+ "timestamp": 1769681855367
6
6
  },
7
7
  "AmazonDynamoDB:US East (N. Virginia):group:DDB-ReadUnits|groupDescription:OnDemand ReadRequestUnits": {
8
8
  "price": 0.023,
9
- "timestamp": 1769022317321
9
+ "timestamp": 1769681855373
10
10
  },
11
11
  "AmazonDynamoDB:US East (N. Virginia):group:DDB-WriteUnits|groupDescription:OnDemand WriteRequestUnits": {
12
12
  "price": 0.023,
13
- "timestamp": 1769022317321
13
+ "timestamp": 1769681855374
14
14
  },
15
15
  "AmazonEC2:US East (N. Virginia):capacitystatus:Used|instanceType:t3.micro|operatingSystem:Linux|preInstalledSw:NA|tenancy:Shared": {
16
16
  "price": 0.023,
17
- "timestamp": 1769022317333
17
+ "timestamp": 1769681855389
18
18
  },
19
19
  "AWSLambda:US East (N. Virginia):group:AWS-Lambda-Requests": {
20
20
  "price": 0.023,
21
- "timestamp": 1769022317342
21
+ "timestamp": 1769681855394
22
22
  },
23
23
  "AWSLambda:US East (N. Virginia):group:AWS-Lambda-Duration": {
24
24
  "price": 0.023,
25
- "timestamp": 1769022317343
25
+ "timestamp": 1769681855394
26
26
  },
27
27
  "AmazonS3:EU (Frankfurt):storageClass:General Purpose|volumeType:Standard": {
28
28
  "price": 0.023,
29
- "timestamp": 1769022329590
29
+ "timestamp": 1769681867552
30
30
  },
31
31
  "AmazonS3:invalid-region-123:storageClass:General Purpose|volumeType:Standard": {
32
32
  "price": 0.023,
33
- "timestamp": 1769022329639
33
+ "timestamp": 1769681867598
34
34
  }
35
35
  }
36
36
  }
@@ -5,4 +5,5 @@ export declare class ECSCalculator implements ResourceCostCalculator {
5
5
  calculateCost(resource: ResourceWithId, region: string, pricingClient: PricingClient): Promise<MonthlyCost>;
6
6
  private calculateFargateCost;
7
7
  private calculateEC2Cost;
8
+ private getRegionPrefix;
8
9
  }
@@ -29,20 +29,31 @@ class ECSCalculator {
29
29
  // Default assumptions for Fargate task
30
30
  const assumedVCpu = 0.25; // 0.25 vCPU
31
31
  const assumedMemoryGB = 0.5; // 0.5 GB
32
+ const regionPrefix = this.getRegionPrefix(region);
33
+ if (!regionPrefix) {
34
+ return {
35
+ amount: 0,
36
+ currency: 'USD',
37
+ confidence: 'unknown',
38
+ assumptions: [
39
+ `Region prefix not found for ${region}`,
40
+ 'Unable to query Fargate pricing',
41
+ ],
42
+ };
43
+ }
32
44
  const vCpuCostPerHour = await pricingClient.getPrice({
33
45
  serviceCode: 'AmazonECS',
34
46
  region: (0, RegionMapper_1.normalizeRegion)(region),
35
47
  filters: [
36
48
  { field: 'productFamily', value: 'Compute' },
37
- { field: 'usagetype', value: `${region}-Fargate-vCPU-Hours:perCPU` },
49
+ { field: 'usagetype', value: `${regionPrefix}-Fargate-vCPU-Hours:perCPU` },
38
50
  ],
39
51
  });
40
52
  const memoryCostPerHour = await pricingClient.getPrice({
41
53
  serviceCode: 'AmazonECS',
42
54
  region: (0, RegionMapper_1.normalizeRegion)(region),
43
55
  filters: [
44
- { field: 'productFamily', value: 'Compute' },
45
- { field: 'usagetype', value: `${region}-Fargate-GB-Hours:perGB` },
56
+ { field: 'usagetype', value: `${regionPrefix}-Fargate-GB-Hours` },
46
57
  ],
47
58
  });
48
59
  if (vCpuCostPerHour === null || memoryCostPerHour === null) {
@@ -93,6 +104,54 @@ class ECSCalculator {
93
104
  ],
94
105
  };
95
106
  }
107
+ getRegionPrefix(region) {
108
+ // AWS uses region prefixes in usage types for ECS Fargate
109
+ // Format: {PREFIX}-Fargate-vCPU-Hours:perCPU or {PREFIX}-Fargate-GB-Hours
110
+ const prefixMap = {
111
+ // US Regions
112
+ 'us-east-1': 'USE1',
113
+ 'us-east-2': 'USE2',
114
+ 'us-west-1': 'USW1',
115
+ 'us-west-2': 'USW2',
116
+ // EU Regions
117
+ 'eu-west-1': 'EUW1',
118
+ 'eu-west-2': 'EUW2',
119
+ 'eu-west-3': 'EUW3',
120
+ 'eu-central-1': 'EUC1',
121
+ 'eu-central-2': 'EUC2',
122
+ 'eu-north-1': 'EUN1',
123
+ 'eu-south-1': 'EUS1',
124
+ 'eu-south-2': 'EUS2',
125
+ // Asia Pacific Regions
126
+ 'ap-south-1': 'APS1',
127
+ 'ap-south-2': 'APS2',
128
+ 'ap-southeast-1': 'APS3',
129
+ 'ap-southeast-2': 'APS4',
130
+ 'ap-southeast-3': 'APS5',
131
+ 'ap-southeast-4': 'APS6',
132
+ 'ap-northeast-1': 'APN1',
133
+ 'ap-northeast-2': 'APN2',
134
+ 'ap-northeast-3': 'APN3',
135
+ 'ap-east-1': 'APE1',
136
+ // Canada Regions
137
+ 'ca-central-1': 'CAN1',
138
+ 'ca-west-1': 'CAW1',
139
+ // South America Regions
140
+ 'sa-east-1': 'SAE1',
141
+ // Middle East Regions
142
+ 'me-south-1': 'MES1',
143
+ 'me-central-1': 'MEC1',
144
+ // Africa Regions
145
+ 'af-south-1': 'AFS1',
146
+ // Israel Regions
147
+ 'il-central-1': 'ILC1',
148
+ // Other Regions
149
+ 'ap-southeast-5': 'APS7',
150
+ 'us-gov-west-1': 'UGW1',
151
+ 'us-gov-east-1': 'UGE1',
152
+ };
153
+ return prefixMap[region] || '';
154
+ }
96
155
  }
97
156
  exports.ECSCalculator = ECSCalculator;
98
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRUNTQ2FsY3VsYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wcmljaW5nL2NhbGN1bGF0b3JzL0VDU0NhbGN1bGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsa0RBQWtEO0FBRWxELE1BQWEsYUFBYTtJQUN4QixRQUFRLENBQUMsWUFBb0I7UUFDM0IsT0FBTyxZQUFZLEtBQUssbUJBQW1CLENBQUM7SUFDOUMsQ0FBQztJQUVELEtBQUssQ0FBQyxhQUFhLENBQ2pCLFFBQXdCLEVBQ3hCLE1BQWMsRUFDZCxhQUE0QjtRQUU1QixNQUFNLFlBQVksR0FBSSxRQUFRLENBQUMsVUFBVSxDQUFDLFlBQXVCLElBQUksQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sVUFBVSxHQUFJLFFBQVEsQ0FBQyxVQUFVLENBQUMsVUFBcUIsSUFBSSxTQUFTLENBQUM7UUFFM0UsSUFBSSxVQUFVLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsUUFBUSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDbEYsQ0FBQzthQUFNLElBQUksVUFBVSxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQ2hDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzdDLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTztnQkFDTCxNQUFNLEVBQUUsQ0FBQztnQkFDVCxRQUFRLEVBQUUsS0FBSztnQkFDZixVQUFVLEVBQUUsU0FBUztnQkFDckIsV0FBVyxFQUFFLENBQUMsNEJBQTRCLFVBQVUsRUFBRSxDQUFDO2FBQ3hELENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxvQkFBb0IsQ0FDaEMsU0FBeUIsRUFDekIsWUFBb0IsRUFDcEIsTUFBYyxFQUNkLGFBQTRCO1FBRTVCLElBQUksQ0FBQztZQUNILHVDQUF1QztZQUN2QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsQ0FBQyxZQUFZO1lBQ3RDLE1BQU0sZUFBZSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVM7WUFFdEMsTUFBTSxlQUFlLEdBQUcsTUFBTSxhQUFhLENBQUMsUUFBUSxDQUFDO2dCQUNuRCxXQUFXLEVBQUUsV0FBVztnQkFDeEIsTUFBTSxFQUFFLElBQUEsOEJBQWUsRUFBQyxNQUFNLENBQUM7Z0JBQy9CLE9BQU8sRUFBRTtvQkFDUCxFQUFFLEtBQUssRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRTtvQkFDNUMsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sNEJBQTRCLEVBQUU7aUJBQ3JFO2FBQ0YsQ0FBQyxDQUFDO1lBRUgsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLGFBQWEsQ0FBQyxRQUFRLENBQUM7Z0JBQ3JELFdBQVcsRUFBRSxXQUFXO2dCQUN4QixNQUFNLEVBQUUsSUFBQSw4QkFBZSxFQUFDLE1BQU0sQ0FBQztnQkFDL0IsT0FBTyxFQUFFO29CQUNQLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFO29CQUM1QyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLEdBQUcsTUFBTSx5QkFBeUIsRUFBRTtpQkFDbEU7YUFDRixDQUFDLENBQUM7WUFFSCxJQUFJLGVBQWUsS0FBSyxJQUFJLElBQUksaUJBQWlCLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQzNELE9BQU87b0JBQ0wsTUFBTSxFQUFFLENBQUM7b0JBQ1QsUUFBUSxFQUFFLEtBQUs7b0JBQ2YsVUFBVSxFQUFFLFNBQVM7b0JBQ3JCLFdBQVcsRUFBRSxDQUFDLDRDQUE0QyxDQUFDO2lCQUM1RCxDQUFDO1lBQ0osQ0FBQztZQUVELE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQztZQUMxQixNQUFNLFFBQVEsR0FBRyxXQUFXLEdBQUcsZUFBZSxHQUFHLGFBQWEsR0FBRyxZQUFZLENBQUM7WUFDOUUsTUFBTSxVQUFVLEdBQUcsZUFBZSxHQUFHLGlCQUFpQixHQUFHLGFBQWEsR0FBRyxZQUFZLENBQUM7WUFDdEYsTUFBTSxXQUFXLEdBQUcsUUFBUSxHQUFHLFVBQVUsQ0FBQztZQUUxQyxPQUFPO2dCQUNMLE1BQU0sRUFBRSxXQUFXO2dCQUNuQixRQUFRLEVBQUUsS0FBSztnQkFDZixVQUFVLEVBQUUsUUFBUTtnQkFDcEIsV0FBVyxFQUFFO29CQUNYLEdBQUcsWUFBWSxrQkFBa0I7b0JBQ2pDLFdBQVcsV0FBVyxnQkFBZ0I7b0JBQ3RDLFdBQVcsZUFBZSxxQkFBcUI7b0JBQy9DLFdBQVcsYUFBYSxtQ0FBbUM7b0JBQzNELHFCQUFxQjtvQkFDckIsaURBQWlEO2lCQUNsRDthQUNGLENBQUM7UUFDSixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU87Z0JBQ0wsTUFBTSxFQUFFLENBQUM7Z0JBQ1QsUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsVUFBVSxFQUFFLFNBQVM7Z0JBQ3JCLFdBQVcsRUFBRSxDQUFDLDRCQUE0QixLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQzthQUNwRyxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxZQUFvQjtRQUMzQyxPQUFPO1lBQ0wsTUFBTSxFQUFFLENBQUM7WUFDVCxRQUFRLEVBQUUsS0FBSztZQUNmLFVBQVUsRUFBRSxLQUFLO1lBQ2pCLFdBQVcsRUFBRTtnQkFDWCxHQUFHLFlBQVkscUNBQXFDO2dCQUNwRCwwREFBMEQ7Z0JBQzFELGdEQUFnRDtnQkFDaEQsd0VBQXdFO2FBQ3pFO1NBQ0YsQ0FBQztJQUNKLENBQUM7Q0FFRjtBQTNHRCxzQ0EyR0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBSZXNvdXJjZVdpdGhJZCB9IGZyb20gJy4uLy4uL2RpZmYvdHlwZXMnO1xuaW1wb3J0IHsgUmVzb3VyY2VDb3N0Q2FsY3VsYXRvciwgTW9udGhseUNvc3QsIFByaWNpbmdDbGllbnQgfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBub3JtYWxpemVSZWdpb24gfSBmcm9tICcuLi9SZWdpb25NYXBwZXInO1xuXG5leHBvcnQgY2xhc3MgRUNTQ2FsY3VsYXRvciBpbXBsZW1lbnRzIFJlc291cmNlQ29zdENhbGN1bGF0b3Ige1xuICBzdXBwb3J0cyhyZXNvdXJjZVR5cGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiByZXNvdXJjZVR5cGUgPT09ICdBV1M6OkVDUzo6U2VydmljZSc7XG4gIH1cblxuICBhc3luYyBjYWxjdWxhdGVDb3N0KFxuICAgIHJlc291cmNlOiBSZXNvdXJjZVdpdGhJZCxcbiAgICByZWdpb246IHN0cmluZyxcbiAgICBwcmljaW5nQ2xpZW50OiBQcmljaW5nQ2xpZW50LFxuICApOiBQcm9taXNlPE1vbnRobHlDb3N0PiB7XG4gICAgY29uc3QgZGVzaXJlZENvdW50ID0gKHJlc291cmNlLnByb3BlcnRpZXMuRGVzaXJlZENvdW50IGFzIG51bWJlcikgfHwgMTtcbiAgICBjb25zdCBsYXVuY2hUeXBlID0gKHJlc291cmNlLnByb3BlcnRpZXMuTGF1bmNoVHlwZSBhcyBzdHJpbmcpIHx8ICdGQVJHQVRFJztcblxuICAgIGlmIChsYXVuY2hUeXBlID09PSAnRkFSR0FURScpIHtcbiAgICAgIHJldHVybiB0aGlzLmNhbGN1bGF0ZUZhcmdhdGVDb3N0KHJlc291cmNlLCBkZXNpcmVkQ291bnQsIHJlZ2lvbiwgcHJpY2luZ0NsaWVudCk7XG4gICAgfSBlbHNlIGlmIChsYXVuY2hUeXBlID09PSAnRUMyJykge1xuICAgICAgcmV0dXJuIHRoaXMuY2FsY3VsYXRlRUMyQ29zdChkZXNpcmVkQ291bnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgY29uZmlkZW5jZTogJ3Vua25vd24nLFxuICAgICAgICBhc3N1bXB0aW9uczogW2BVbnN1cHBvcnRlZCBsYXVuY2ggdHlwZTogJHtsYXVuY2hUeXBlfWBdLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNhbGN1bGF0ZUZhcmdhdGVDb3N0KFxuICAgIF9yZXNvdXJjZTogUmVzb3VyY2VXaXRoSWQsXG4gICAgZGVzaXJlZENvdW50OiBudW1iZXIsXG4gICAgcmVnaW9uOiBzdHJpbmcsXG4gICAgcHJpY2luZ0NsaWVudDogUHJpY2luZ0NsaWVudCxcbiAgKTogUHJvbWlzZTxNb250aGx5Q29zdD4ge1xuICAgIHRyeSB7XG4gICAgICAvLyBEZWZhdWx0IGFzc3VtcHRpb25zIGZvciBGYXJnYXRlIHRhc2tcbiAgICAgIGNvbnN0IGFzc3VtZWRWQ3B1ID0gMC4yNTsgLy8gMC4yNSB2Q1BVXG4gICAgICBjb25zdCBhc3N1bWVkTWVtb3J5R0IgPSAwLjU7IC8vIDAuNSBHQlxuXG4gICAgICBjb25zdCB2Q3B1Q29zdFBlckhvdXIgPSBhd2FpdCBwcmljaW5nQ2xpZW50LmdldFByaWNlKHtcbiAgICAgICAgc2VydmljZUNvZGU6ICdBbWF6b25FQ1MnLFxuICAgICAgICByZWdpb246IG5vcm1hbGl6ZVJlZ2lvbihyZWdpb24pLFxuICAgICAgICBmaWx0ZXJzOiBbXG4gICAgICAgICAgeyBmaWVsZDogJ3Byb2R1Y3RGYW1pbHknLCB2YWx1ZTogJ0NvbXB1dGUnIH0sXG4gICAgICAgICAgeyBmaWVsZDogJ3VzYWdldHlwZScsIHZhbHVlOiBgJHtyZWdpb259LUZhcmdhdGUtdkNQVS1Ib3VyczpwZXJDUFVgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgbWVtb3J5Q29zdFBlckhvdXIgPSBhd2FpdCBwcmljaW5nQ2xpZW50LmdldFByaWNlKHtcbiAgICAgICAgc2VydmljZUNvZGU6ICdBbWF6b25FQ1MnLFxuICAgICAgICByZWdpb246IG5vcm1hbGl6ZVJlZ2lvbihyZWdpb24pLFxuICAgICAgICBmaWx0ZXJzOiBbXG4gICAgICAgICAgeyBmaWVsZDogJ3Byb2R1Y3RGYW1pbHknLCB2YWx1ZTogJ0NvbXB1dGUnIH0sXG4gICAgICAgICAgeyBmaWVsZDogJ3VzYWdldHlwZScsIHZhbHVlOiBgJHtyZWdpb259LUZhcmdhdGUtR0ItSG91cnM6cGVyR0JgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgaWYgKHZDcHVDb3N0UGVySG91ciA9PT0gbnVsbCB8fCBtZW1vcnlDb3N0UGVySG91ciA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGFtb3VudDogMCxcbiAgICAgICAgICBjdXJyZW5jeTogJ1VTRCcsXG4gICAgICAgICAgY29uZmlkZW5jZTogJ3Vua25vd24nLFxuICAgICAgICAgIGFzc3VtcHRpb25zOiBbJ1ByaWNpbmcgZGF0YSBub3QgYXZhaWxhYmxlIGZvciBFQ1MgRmFyZ2F0ZSddLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBob3Vyc1Blck1vbnRoID0gNzMwO1xuICAgICAgY29uc3QgdkNwdUNvc3QgPSBhc3N1bWVkVkNwdSAqIHZDcHVDb3N0UGVySG91ciAqIGhvdXJzUGVyTW9udGggKiBkZXNpcmVkQ291bnQ7XG4gICAgICBjb25zdCBtZW1vcnlDb3N0ID0gYXNzdW1lZE1lbW9yeUdCICogbWVtb3J5Q29zdFBlckhvdXIgKiBob3Vyc1Blck1vbnRoICogZGVzaXJlZENvdW50O1xuICAgICAgY29uc3QgbW9udGhseUNvc3QgPSB2Q3B1Q29zdCArIG1lbW9yeUNvc3Q7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGFtb3VudDogbW9udGhseUNvc3QsXG4gICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgY29uZmlkZW5jZTogJ21lZGl1bScsXG4gICAgICAgIGFzc3VtcHRpb25zOiBbXG4gICAgICAgICAgYCR7ZGVzaXJlZENvdW50fSB0YXNrKHMpIHJ1bm5pbmdgLFxuICAgICAgICAgIGBBc3N1bWVzICR7YXNzdW1lZFZDcHV9IHZDUFUgcGVyIHRhc2tgLFxuICAgICAgICAgIGBBc3N1bWVzICR7YXNzdW1lZE1lbW9yeUdCfSBHQiBtZW1vcnkgcGVyIHRhc2tgLFxuICAgICAgICAgIGBBc3N1bWVzICR7aG91cnNQZXJNb250aH0gaG91cnMgcGVyIG1vbnRoICgyNC83IG9wZXJhdGlvbilgLFxuICAgICAgICAgICdGYXJnYXRlIGxhdW5jaCB0eXBlJyxcbiAgICAgICAgICAnRG9lcyBub3QgaW5jbHVkZSBkYXRhIHRyYW5zZmVyIG9yIHN0b3JhZ2UgY29zdHMnLFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICBjdXJyZW5jeTogJ1VTRCcsXG4gICAgICAgIGNvbmZpZGVuY2U6ICd1bmtub3duJyxcbiAgICAgICAgYXNzdW1wdGlvbnM6IFtgRmFpbGVkIHRvIGZldGNoIHByaWNpbmc6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWBdLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNhbGN1bGF0ZUVDMkNvc3QoZGVzaXJlZENvdW50OiBudW1iZXIpOiBNb250aGx5Q29zdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFtb3VudDogMCxcbiAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgIGNvbmZpZGVuY2U6ICdsb3cnLFxuICAgICAgYXNzdW1wdGlvbnM6IFtcbiAgICAgICAgYCR7ZGVzaXJlZENvdW50fSB0YXNrKHMpIHJ1bm5pbmcgb24gRUMyIGxhdW5jaCB0eXBlYCxcbiAgICAgICAgJ0VDMiBsYXVuY2ggdHlwZSBjb3N0cyBkZXBlbmQgb24gdW5kZXJseWluZyBFQzIgaW5zdGFuY2VzJyxcbiAgICAgICAgJ1JlZmVyIHRvIEVDMiBpbnN0YW5jZSBjb3N0cyBmb3IgYWN0dWFsIHByaWNpbmcnLFxuICAgICAgICAnRG9lcyBub3QgaW5jbHVkZSBFQ1MgdGFzay1zcGVjaWZpYyBjb3N0cyAobWluaW1hbCBmb3IgRUMyIGxhdW5jaCB0eXBlKScsXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxufVxuIl19
157
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRUNTQ2FsY3VsYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wcmljaW5nL2NhbGN1bGF0b3JzL0VDU0NhbGN1bGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsa0RBQWtEO0FBRWxELE1BQWEsYUFBYTtJQUN4QixRQUFRLENBQUMsWUFBb0I7UUFDM0IsT0FBTyxZQUFZLEtBQUssbUJBQW1CLENBQUM7SUFDOUMsQ0FBQztJQUVELEtBQUssQ0FBQyxhQUFhLENBQ2pCLFFBQXdCLEVBQ3hCLE1BQWMsRUFDZCxhQUE0QjtRQUU1QixNQUFNLFlBQVksR0FBSSxRQUFRLENBQUMsVUFBVSxDQUFDLFlBQXVCLElBQUksQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sVUFBVSxHQUFJLFFBQVEsQ0FBQyxVQUFVLENBQUMsVUFBcUIsSUFBSSxTQUFTLENBQUM7UUFFM0UsSUFBSSxVQUFVLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsb0JBQW9CLENBQUMsUUFBUSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFDbEYsQ0FBQzthQUFNLElBQUksVUFBVSxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQ2hDLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzdDLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTztnQkFDTCxNQUFNLEVBQUUsQ0FBQztnQkFDVCxRQUFRLEVBQUUsS0FBSztnQkFDZixVQUFVLEVBQUUsU0FBUztnQkFDckIsV0FBVyxFQUFFLENBQUMsNEJBQTRCLFVBQVUsRUFBRSxDQUFDO2FBQ3hELENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxvQkFBb0IsQ0FDaEMsU0FBeUIsRUFDekIsWUFBb0IsRUFDcEIsTUFBYyxFQUNkLGFBQTRCO1FBRTVCLElBQUksQ0FBQztZQUNILHVDQUF1QztZQUN2QyxNQUFN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QUFlLEVBQUUsTUFBTTtZQUN2QixlQUFlLEVBQUUsTUFBTTtTQUN4QixDQUFDO1FBRUYsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ2pDLENBQUM7Q0FDRjtBQXhLRCxzQ0F3S0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBSZXNvdXJjZVdpdGhJZCB9IGZyb20gJy4uLy4uL2RpZmYvdHlwZXMnO1xuaW1wb3J0IHsgUmVzb3VyY2VDb3N0Q2FsY3VsYXRvciwgTW9udGhseUNvc3QsIFByaWNpbmdDbGllbnQgfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBub3JtYWxpemVSZWdpb24gfSBmcm9tICcuLi9SZWdpb25NYXBwZXInO1xuXG5leHBvcnQgY2xhc3MgRUNTQ2FsY3VsYXRvciBpbXBsZW1lbnRzIFJlc291cmNlQ29zdENhbGN1bGF0b3Ige1xuICBzdXBwb3J0cyhyZXNvdXJjZVR5cGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiByZXNvdXJjZVR5cGUgPT09ICdBV1M6OkVDUzo6U2VydmljZSc7XG4gIH1cblxuICBhc3luYyBjYWxjdWxhdGVDb3N0KFxuICAgIHJlc291cmNlOiBSZXNvdXJjZVdpdGhJZCxcbiAgICByZWdpb246IHN0cmluZyxcbiAgICBwcmljaW5nQ2xpZW50OiBQcmljaW5nQ2xpZW50LFxuICApOiBQcm9taXNlPE1vbnRobHlDb3N0PiB7XG4gICAgY29uc3QgZGVzaXJlZENvdW50ID0gKHJlc291cmNlLnByb3BlcnRpZXMuRGVzaXJlZENvdW50IGFzIG51bWJlcikgfHwgMTtcbiAgICBjb25zdCBsYXVuY2hUeXBlID0gKHJlc291cmNlLnByb3BlcnRpZXMuTGF1bmNoVHlwZSBhcyBzdHJpbmcpIHx8ICdGQVJHQVRFJztcblxuICAgIGlmIChsYXVuY2hUeXBlID09PSAnRkFSR0FURScpIHtcbiAgICAgIHJldHVybiB0aGlzLmNhbGN1bGF0ZUZhcmdhdGVDb3N0KHJlc291cmNlLCBkZXNpcmVkQ291bnQsIHJlZ2lvbiwgcHJpY2luZ0NsaWVudCk7XG4gICAgfSBlbHNlIGlmIChsYXVuY2hUeXBlID09PSAnRUMyJykge1xuICAgICAgcmV0dXJuIHRoaXMuY2FsY3VsYXRlRUMyQ29zdChkZXNpcmVkQ291bnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgY29uZmlkZW5jZTogJ3Vua25vd24nLFxuICAgICAgICBhc3N1bXB0aW9uczogW2BVbnN1cHBvcnRlZCBsYXVuY2ggdHlwZTogJHtsYXVuY2hUeXBlfWBdLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNhbGN1bGF0ZUZhcmdhdGVDb3N0KFxuICAgIF9yZXNvdXJjZTogUmVzb3VyY2VXaXRoSWQsXG4gICAgZGVzaXJlZENvdW50OiBudW1iZXIsXG4gICAgcmVnaW9uOiBzdHJpbmcsXG4gICAgcHJpY2luZ0NsaWVudDogUHJpY2luZ0NsaWVudCxcbiAgKTogUHJvbWlzZTxNb250aGx5Q29zdD4ge1xuICAgIHRyeSB7XG4gICAgICAvLyBEZWZhdWx0IGFzc3VtcHRpb25zIGZvciBGYXJnYXRlIHRhc2tcbiAgICAgIGNvbnN0IGFzc3VtZWRWQ3B1ID0gMC4yNTsgLy8gMC4yNSB2Q1BVXG4gICAgICBjb25zdCBhc3N1bWVkTWVtb3J5R0IgPSAwLjU7IC8vIDAuNSBHQlxuXG4gICAgICBjb25zdCByZWdpb25QcmVmaXggPSB0aGlzLmdldFJlZ2lvblByZWZpeChyZWdpb24pO1xuICAgICAgaWYgKCFyZWdpb25QcmVmaXgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgICAgY3VycmVuY3k6ICdVU0QnLFxuICAgICAgICAgIGNvbmZpZGVuY2U6ICd1bmtub3duJyxcbiAgICAgICAgICBhc3N1bXB0aW9uczogW1xuICAgICAgICAgICAgYFJlZ2lvbiBwcmVmaXggbm90IGZvdW5kIGZvciAke3JlZ2lvbn1gLFxuICAgICAgICAgICAgJ1VuYWJsZSB0byBxdWVyeSBGYXJnYXRlIHByaWNpbmcnLFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHZDcHVDb3N0UGVySG91ciA9IGF3YWl0IHByaWNpbmdDbGllbnQuZ2V0UHJpY2Uoe1xuICAgICAgICBzZXJ2aWNlQ29kZTogJ0FtYXpvbkVDUycsXG4gICAgICAgIHJlZ2lvbjogbm9ybWFsaXplUmVnaW9uKHJlZ2lvbiksXG4gICAgICAgIGZpbHRlcnM6IFtcbiAgICAgICAgICB7IGZpZWxkOiAncHJvZHVjdEZhbWlseScsIHZhbHVlOiAnQ29tcHV0ZScgfSxcbiAgICAgICAgICB7IGZpZWxkOiAndXNhZ2V0eXBlJywgdmFsdWU6IGAke3JlZ2lvblByZWZpeH0tRmFyZ2F0ZS12Q1BVLUhvdXJzOnBlckNQVWAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBtZW1vcnlDb3N0UGVySG91ciA9IGF3YWl0IHByaWNpbmdDbGllbnQuZ2V0UHJpY2Uoe1xuICAgICAgICBzZXJ2aWNlQ29kZTogJ0FtYXpvbkVDUycsXG4gICAgICAgIHJlZ2lvbjogbm9ybWFsaXplUmVnaW9uKHJlZ2lvbiksXG4gICAgICAgIGZpbHRlcnM6IFtcbiAgICAgICAgICB7IGZpZWxkOiAndXNhZ2V0eXBlJywgdmFsdWU6IGAke3JlZ2lvblByZWZpeH0tRmFyZ2F0ZS1HQi1Ib3Vyc2AgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAodkNwdUNvc3RQZXJIb3VyID09PSBudWxsIHx8IG1lbW9yeUNvc3RQZXJIb3VyID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgICBjb25maWRlbmNlOiAndW5rbm93bicsXG4gICAgICAgICAgYXNzdW1wdGlvbnM6IFsnUHJpY2luZyBkYXRhIG5vdCBhdmFpbGFibGUgZm9yIEVDUyBGYXJnYXRlJ10sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGhvdXJzUGVyTW9udGggPSA3MzA7XG4gICAgICBjb25zdCB2Q3B1Q29zdCA9IGFzc3VtZWRWQ3B1ICogdkNwdUNvc3RQZXJIb3VyICogaG91cnNQZXJNb250aCAqIGRlc2lyZWRDb3VudDtcbiAgICAgIGNvbnN0IG1lbW9yeUNvc3QgPSBhc3N1bWVkTWVtb3J5R0IgKiBtZW1vcnlDb3N0UGVySG91ciAqIGhvdXJzUGVyTW9udGggKiBkZXNpcmVkQ291bnQ7XG4gICAgICBjb25zdCBtb250aGx5Q29zdCA9IHZDcHVDb3N0ICsgbWVtb3J5Q29zdDtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYW1vdW50OiBtb250aGx5Q29zdCxcbiAgICAgICAgY3VycmVuY3k6ICdVU0QnLFxuICAgICAgICBjb25maWRlbmNlOiAnbWVkaXVtJyxcbiAgICAgICAgYXNzdW1wdGlvbnM6IFtcbiAgICAgICAgICBgJHtkZXNpcmVkQ291bnR9IHRhc2socykgcnVubmluZ2AsXG4gICAgICAgICAgYEFzc3VtZXMgJHthc3N1bWVkVkNwdX0gdkNQVSBwZXIgdGFza2AsXG4gICAgICAgICAgYEFzc3VtZXMgJHthc3N1bWVkTWVtb3J5R0J9IEdCIG1lbW9yeSBwZXIgdGFza2AsXG4gICAgICAgICAgYEFzc3VtZXMgJHtob3Vyc1Blck1vbnRofSBob3VycyBwZXIgbW9udGggKDI0Lzcgb3BlcmF0aW9uKWAsXG4gICAgICAgICAgJ0ZhcmdhdGUgbGF1bmNoIHR5cGUnLFxuICAgICAgICAgICdEb2VzIG5vdCBpbmNsdWRlIGRhdGEgdHJhbnNmZXIgb3Igc3RvcmFnZSBjb3N0cycsXG4gICAgICAgIF0sXG4gICAgICB9O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgY29uZmlkZW5jZTogJ3Vua25vd24nLFxuICAgICAgICBhc3N1bXB0aW9uczogW2BGYWlsZWQgdG8gZmV0Y2ggcHJpY2luZzogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YF0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2FsY3VsYXRlRUMyQ29zdChkZXNpcmVkQ291bnQ6IG51bWJlcik6IE1vbnRobHlDb3N0IHtcbiAgICByZXR1cm4ge1xuICAgICAgYW1vdW50OiAwLFxuICAgICAgY3VycmVuY3k6ICdVU0QnLFxuICAgICAgY29uZmlkZW5jZTogJ2xvdycsXG4gICAgICBhc3N1bXB0aW9uczogW1xuICAgICAgICBgJHtkZXNpcmVkQ291bnR9IHRhc2socykgcnVubmluZyBvbiBFQzIgbGF1bmNoIHR5cGVgLFxuICAgICAgICAnRUMyIGxhdW5jaCB0eXBlIGNvc3RzIGRlcGVuZCBvbiB1bmRlcmx5aW5nIEVDMiBpbnN0YW5jZXMnLFxuICAgICAgICAnUmVmZXIgdG8gRUMyIGluc3RhbmNlIGNvc3RzIGZvciBhY3R1YWwgcHJpY2luZycsXG4gICAgICAgICdEb2VzIG5vdCBpbmNsdWRlIEVDUyB0YXNrLXNwZWNpZmljIGNvc3RzIChtaW5pbWFsIGZvciBFQzIgbGF1bmNoIHR5cGUpJyxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UmVnaW9uUHJlZml4KHJlZ2lvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAvLyBBV1MgdXNlcyByZWdpb24gcHJlZml4ZXMgaW4gdXNhZ2UgdHlwZXMgZm9yIEVDUyBGYXJnYXRlXG4gICAgLy8gRm9ybWF0OiB7UFJFRklYfS1GYXJnYXRlLXZDUFUtSG91cnM6cGVyQ1BVIG9yIHtQUkVGSVh9LUZhcmdhdGUtR0ItSG91cnNcbiAgICBjb25zdCBwcmVmaXhNYXA6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICAvLyBVUyBSZWdpb25zXG4gICAgICAndXMtZWFzdC0xJzogJ1VTRTEnLFxuICAgICAgJ3VzLWVhc3QtMic6ICdVU0UyJyxcbiAgICAgICd1cy13ZXN0LTEnOiAnVVNXMScsXG4gICAgICAndXMtd2VzdC0yJzogJ1VTVzInLFxuICAgICAgLy8gRVUgUmVnaW9uc1xuICAgICAgJ2V1LXdlc3QtMSc6ICdFVVcxJyxcbiAgICAgICdldS13ZXN0LTInOiAnRVVXMicsXG4gICAgICAnZXUtd2VzdC0zJzogJ0VVVzMnLFxuICAgICAgJ2V1LWNlbnRyYWwtMSc6ICdFVUMxJyxcbiAgICAgICdldS1jZW50cmFsLTInOiAnRVVDMicsXG4gICAgICAnZXUtbm9ydGgtMSc6ICdFVU4xJyxcbiAgICAgICdldS1zb3V0aC0xJzogJ0VVUzEnLFxuICAgICAgJ2V1LXNvdXRoLTInOiAnRVVTMicsXG4gICAgICAvLyBBc2lhIFBhY2lmaWMgUmVnaW9uc1xuICAgICAgJ2FwLXNvdXRoLTEnOiAnQVBTMScsXG4gICAgICAnYXAtc291dGgtMic6ICdBUFMyJyxcbiAgICAgICdhcC1zb3V0aGVhc3QtMSc6ICdBUFMzJyxcbiAgICAgICdhcC1zb3V0aGVhc3QtMic6ICdBUFM0JyxcbiAgICAgICdhcC1zb3V0aGVhc3QtMyc6ICdBUFM1JyxcbiAgICAgICdhcC1zb3V0aGVhc3QtNCc6ICdBUFM2JyxcbiAgICAgICdhcC1ub3J0aGVhc3QtMSc6ICdBUE4xJyxcbiAgICAgICdhcC1ub3J0aGVhc3QtMic6ICdBUE4yJyxcbiAgICAgICdhcC1ub3J0aGVhc3QtMyc6ICdBUE4zJyxcbiAgICAgICdhcC1lYXN0LTEnOiAnQVBFMScsXG4gICAgICAvLyBDYW5hZGEgUmVnaW9uc1xuICAgICAgJ2NhLWNlbnRyYWwtMSc6ICdDQU4xJyxcbiAgICAgICdjYS13ZXN0LTEnOiAnQ0FXMScsXG4gICAgICAvLyBTb3V0aCBBbWVyaWNhIFJlZ2lvbnNcbiAgICAgICdzYS1lYXN0LTEnOiAnU0FFMScsXG4gICAgICAvLyBNaWRkbGUgRWFzdCBSZWdpb25zXG4gICAgICAnbWUtc291dGgtMSc6ICdNRVMxJyxcbiAgICAgICdtZS1jZW50cmFsLTEnOiAnTUVDMScsXG4gICAgICAvLyBBZnJpY2EgUmVnaW9uc1xuICAgICAgJ2FmLXNvdXRoLTEnOiAnQUZTMScsXG4gICAgICAvLyBJc3JhZWwgUmVnaW9uc1xuICAgICAgJ2lsLWNlbnRyYWwtMSc6ICdJTEMxJyxcbiAgICAgIC8vIE90aGVyIFJlZ2lvbnNcbiAgICAgICdhcC1zb3V0aGVhc3QtNSc6ICdBUFM3JyxcbiAgICAgICd1cy1nb3Ytd2VzdC0xJzogJ1VHVzEnLFxuICAgICAgJ3VzLWdvdi1lYXN0LTEnOiAnVUdFMScsXG4gICAgfTtcblxuICAgIHJldHVybiBwcmVmaXhNYXBbcmVnaW9uXSB8fCAnJztcbiAgfVxufVxuIl19
@@ -1 +1 @@
1
- v0.1.11
1
+ v0.1.13
package/package.json CHANGED
@@ -56,7 +56,7 @@
56
56
  "jest": "^30.2.0",
57
57
  "jest-junit": "^16",
58
58
  "lint-staged": "^15.0.0",
59
- "projen": "^0.99.4",
59
+ "projen": "^0.99.8",
60
60
  "ts-jest": "^29.4.6",
61
61
  "ts-node": "^10.9.2",
62
62
  "typescript": "^5.9.3"
@@ -82,7 +82,7 @@
82
82
  "publishConfig": {
83
83
  "access": "public"
84
84
  },
85
- "version": "0.1.11",
85
+ "version": "0.1.13",
86
86
  "bugs": {
87
87
  "url": "https://github.com/buildinginthecloud/cdk-cost-analyzer/issues"
88
88
  },
@@ -91,6 +91,12 @@
91
91
  "testTimeout": 30000,
92
92
  "forceExit": true,
93
93
  "detectOpenHandles": true,
94
+ "testEnvironmentOptions": {
95
+ "customExportConditions": [
96
+ "node",
97
+ "node-addons"
98
+ ]
99
+ },
94
100
  "testMatch": [
95
101
  "<rootDir>/@(src|test)/**/*(*.)@(spec|test).ts?(x)",
96
102
  "<rootDir>/@(src|test)/**/__tests__/**/*.ts?(x)",
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env ts-node
2
+ /**
3
+ * Discovery script for ECS Fargate pricing filters
4
+ *
5
+ * This script helps identify the correct filters for querying
6
+ * AWS Pricing API for ECS Fargate vCPU and memory pricing.
7
+ *
8
+ * Usage:
9
+ * npx ts-node tools/discover-ecs-fargate-pricing.ts
10
+ */
11
+
12
+ import { PricingClient as AWSPricingClient, GetProductsCommand } from '@aws-sdk/client-pricing';
13
+
14
+ async function discoverECSFargatePricing(): Promise<void> {
15
+ const client = new AWSPricingClient({
16
+ region: 'us-east-1',
17
+ credentials: undefined, // Will use AWS_PROFILE from environment
18
+ });
19
+
20
+ console.log('='.repeat(80));
21
+ console.log('ECS Fargate Pricing Discovery');
22
+ console.log('='.repeat(80));
23
+ console.log();
24
+
25
+ // Test 1: Find all ECS products
26
+ console.log('Test 1: Searching for ECS products...');
27
+ try {
28
+ const command1 = new GetProductsCommand({
29
+ ServiceCode: 'AmazonECS',
30
+ MaxResults: 10,
31
+ });
32
+ const response1 = await client.send(command1);
33
+
34
+ if (response1.PriceList && response1.PriceList.length > 0) {
35
+ console.log(`Found ${response1.PriceList.length} ECS products`);
36
+ console.log('\nSample product attributes:');
37
+ const sample = JSON.parse(response1.PriceList[0]);
38
+ console.log(JSON.stringify(sample.product?.attributes, null, 2));
39
+ }
40
+ } catch (error) {
41
+ console.error('Error:', error);
42
+ }
43
+ console.log();
44
+
45
+ // Test 2: Search for Fargate-specific products
46
+ console.log('Test 2: Searching for Fargate products...');
47
+ try {
48
+ const command2 = new GetProductsCommand({
49
+ ServiceCode: 'AmazonECS',
50
+ Filters: [
51
+ { Type: 'TERM_MATCH', Field: 'productFamily', Value: 'Compute' },
52
+ ],
53
+ MaxResults: 10,
54
+ });
55
+ const response2 = await client.send(command2);
56
+
57
+ if (response2.PriceList && response2.PriceList.length > 0) {
58
+ console.log(`Found ${response2.PriceList.length} Compute products`);
59
+ response2.PriceList.forEach((item: string, idx: number) => {
60
+ const product = JSON.parse(item);
61
+ const attrs = product.product?.attributes;
62
+ console.log(`\nProduct ${idx + 1}:`);
63
+ console.log(` usagetype: ${attrs?.usagetype}`);
64
+ console.log(` operation: ${attrs?.operation}`);
65
+ console.log(` productFamily: ${attrs?.productFamily}`);
66
+ console.log(` group: ${attrs?.group}`);
67
+ console.log(` groupDescription: ${attrs?.groupDescription}`);
68
+ });
69
+ }
70
+ } catch (error) {
71
+ console.error('Error:', error);
72
+ }
73
+ console.log();
74
+
75
+ // Test 3: Search for vCPU pricing
76
+ console.log('Test 3: Searching for Fargate vCPU pricing...');
77
+ const vCpuFilters = [
78
+ [
79
+ { Type: 'TERM_MATCH', Field: 'productFamily', Value: 'Compute' },
80
+ { Type: 'TERM_MATCH', Field: 'usagetype', Value: `EUC1-Fargate-vCPU-Hours:perCPU` },
81
+ ],
82
+ [
83
+ { Type: 'TERM_MATCH', Field: 'productFamily', Value: 'Compute' },
84
+ { Type: 'TERM_MATCH', Field: 'usagetype', Value: `Fargate-vCPU-Hours:perCPU` },
85
+ ],
86
+ [
87
+ { Type: 'TERM_MATCH', Field: 'group', Value: 'Fargate-vCPU-Hours:perCPU' },
88
+ ],
89
+ ];
90
+
91
+ for (let i = 0; i < vCpuFilters.length; i++) {
92
+ console.log(`\nAttempt ${i + 1}:`, JSON.stringify(vCpuFilters[i]));
93
+ try {
94
+ const command = new GetProductsCommand({
95
+ ServiceCode: 'AmazonECS',
96
+ Filters: vCpuFilters[i] as any,
97
+ MaxResults: 1,
98
+ });
99
+ const response = await client.send(command);
100
+
101
+ if (response.PriceList && response.PriceList.length > 0) {
102
+ const product = JSON.parse(response.PriceList[0]);
103
+ console.log('✓ SUCCESS! Found vCPU pricing');
104
+ console.log(' Attributes:', JSON.stringify(product.product?.attributes, null, 2));
105
+
106
+ const onDemand = product.terms?.OnDemand;
107
+ if (onDemand) {
108
+ const termKey = Object.keys(onDemand)[0];
109
+ const priceDimensions = onDemand[termKey]?.priceDimensions;
110
+ const dimensionKey = Object.keys(priceDimensions)[0];
111
+ const price = priceDimensions[dimensionKey]?.pricePerUnit?.USD;
112
+ console.log(` Price: $${price} per vCPU-hour`);
113
+ }
114
+ } else {
115
+ console.log('✗ No results');
116
+ }
117
+ } catch (error) {
118
+ console.error('✗ Error:', error instanceof Error ? error.message : error);
119
+ }
120
+ }
121
+ console.log();
122
+
123
+ // Test 4: Search for memory pricing
124
+ console.log('Test 4: Searching for Fargate memory pricing...');
125
+ const memoryFilters = [
126
+ [
127
+ { Type: 'TERM_MATCH', Field: 'productFamily', Value: 'Compute' },
128
+ { Type: 'TERM_MATCH', Field: 'usagetype', Value: `EUC1-Fargate-GB-Hours:perGB` },
129
+ ],
130
+ [
131
+ { Type: 'TERM_MATCH', Field: 'productFamily', Value: 'Compute' },
132
+ { Type: 'TERM_MATCH', Field: 'usagetype', Value: `EUC1-Fargate-Memory-Hours:perGB` },
133
+ ],
134
+ [
135
+ { Type: 'TERM_MATCH', Field: 'usagetype', Value: `EUC1-Fargate-GB-Hours` },
136
+ ],
137
+ [
138
+ { Type: 'TERM_MATCH', Field: 'cputype', Value: 'perGB' },
139
+ ],
140
+ ];
141
+
142
+ for (let i = 0; i < memoryFilters.length; i++) {
143
+ console.log(`\nAttempt ${i + 1}:`, JSON.stringify(memoryFilters[i]));
144
+ try {
145
+ const command = new GetProductsCommand({
146
+ ServiceCode: 'AmazonECS',
147
+ Filters: memoryFilters[i] as any,
148
+ MaxResults: 1,
149
+ });
150
+ const response = await client.send(command);
151
+
152
+ if (response.PriceList && response.PriceList.length > 0) {
153
+ const product = JSON.parse(response.PriceList[0]);
154
+ console.log('✓ SUCCESS! Found memory pricing');
155
+ console.log(' Attributes:', JSON.stringify(product.product?.attributes, null, 2));
156
+
157
+ const onDemand = product.terms?.OnDemand;
158
+ if (onDemand) {
159
+ const termKey = Object.keys(onDemand)[0];
160
+ const priceDimensions = onDemand[termKey]?.priceDimensions;
161
+ const dimensionKey = Object.keys(priceDimensions)[0];
162
+ const price = priceDimensions[dimensionKey]?.pricePerUnit?.USD;
163
+ console.log(` Price: $${price} per GB-hour`);
164
+ }
165
+ } else {
166
+ console.log('✗ No results');
167
+ }
168
+ } catch (error) {
169
+ console.error('✗ Error:', error instanceof Error ? error.message : error);
170
+ }
171
+ }
172
+ console.log();
173
+
174
+ console.log('='.repeat(80));
175
+ console.log('Discovery complete');
176
+ console.log('='.repeat(80));
177
+ }
178
+
179
+ discoverECSFargatePricing().catch(console.error);