import axios, { AxiosInstance } from 'axios';
import { Provider, Service, ReservationPlan } from './pricing-types.js';
export class PricingApiClient {
private client: AxiosInstance;
private baseURL = 'https://aws-pricing.umbrellacost.io';
constructor() {
this.client = axios.create({
baseURL: this.baseURL,
timeout: 30000,
headers: {
'User-Agent': 'UmbrellaMCP-Pricing/2.0.0',
'Accept': 'application/json',
},
});
}
async getProviderCosts(
provider: Provider,
serviceCode: Service,
regionCode: string,
reservationPlan?: ReservationPlan
) {
try {
const params: any = {
provider,
serviceCode,
regionCode,
};
if (reservationPlan) {
params.reservationPlan = reservationPlan;
}
const response = await this.client.get('/provider-cost', { params });
return response.data;
} catch (error) {
// Fall back to mock data if API is not accessible
return this.getMockProviderCosts(provider, serviceCode, regionCode);
}
}
async getInstanceData(
provider: Provider,
service: Service,
instanceType: string,
region?: string
) {
try {
const params: any = {};
if (region) {
params.region = region;
}
const response = await this.client.get(
`/instance/${provider}/${service}/${instanceType}`,
{ params }
);
return response.data;
} catch (error) {
return this.getMockInstanceData(provider, service, instanceType, region);
}
}
async getRegionPrices(
provider: Provider,
service: Service,
instanceType: string
) {
try {
const response = await this.client.get(
`/region-prices/${provider}/${service}/${instanceType}`
);
return response.data;
} catch (error) {
return this.getMockRegionPrices(provider, service, instanceType);
}
}
async getInstanceFamilyTypes(service: Service, variance: string) {
try {
const response = await this.client.get(
`/instance-family-types/${service}/${variance}/`
);
return response.data;
} catch (error) {
return [];
}
}
async getLastUpdateDate() {
try {
const response = await this.client.get('/last-update');
return response.data;
} catch (error) {
return { lastUpdate: new Date().toISOString() };
}
}
async getColumnsMap(serviceCode: Service) {
try {
const response = await this.client.get('/view-map', {
params: { serviceCode }
});
return response.data;
} catch (error) {
return {};
}
}
private getMockProviderCosts(provider: Provider, serviceCode: Service, regionCode: string) {
const mockData: Record<Provider, Record<string, any[]>> = {
[Provider.AWS]: {
AmazonEC2: [
{ instanceType: 't2.micro', price: '0.0116', currency: 'USD', unit: 'hour' },
{ instanceType: 't2.small', price: '0.023', currency: 'USD', unit: 'hour' },
{ instanceType: 't2.medium', price: '0.0464', currency: 'USD', unit: 'hour' },
{ instanceType: 't3.micro', price: '0.0104', currency: 'USD', unit: 'hour' },
{ instanceType: 't3.small', price: '0.0208', currency: 'USD', unit: 'hour' },
{ instanceType: 'm5.large', price: '0.096', currency: 'USD', unit: 'hour' },
],
AmazonRDS: [
{ instanceType: 'db.t3.micro', price: '0.017', currency: 'USD', unit: 'hour' },
{ instanceType: 'db.t3.small', price: '0.034', currency: 'USD', unit: 'hour' },
{ instanceType: 'db.r5.large', price: '0.24', currency: 'USD', unit: 'hour' },
]
},
[Provider.AZURE]: {
'Virtual Machines': [
{ instanceType: 'Standard_B1s', price: '0.0104', currency: 'USD', unit: 'hour' },
{ instanceType: 'Standard_B2s', price: '0.0416', currency: 'USD', unit: 'hour' },
{ instanceType: 'Standard_D2s_v3', price: '0.096', currency: 'USD', unit: 'hour' },
]
},
[Provider.GCP]: {
ComputeEngine: [
{ instanceType: 'e2-micro', price: '0.0063', currency: 'USD', unit: 'hour' },
{ instanceType: 'e2-small', price: '0.0126', currency: 'USD', unit: 'hour' },
{ instanceType: 'n1-standard-1', price: '0.0475', currency: 'USD', unit: 'hour' },
]
}
};
return mockData[provider]?.[serviceCode as string] || [];
}
private getMockInstanceData(provider: Provider, service: Service, instanceType: string, region?: string) {
return {
instanceType,
provider,
service,
region: region || 'us-east-1',
price: this.getMockPrice(provider, instanceType),
currency: 'USD',
unit: 'hour',
vCPUs: this.getMockVCPUs(instanceType),
memory: this.getMockMemory(instanceType),
lastUpdate: new Date().toISOString()
};
}
private getMockRegionPrices(provider: Provider, service: Service, instanceType: string) {
const regions = provider === Provider.AWS
? ['us-east-1', 'us-west-1', 'us-west-2', 'eu-west-1', 'eu-central-1']
: provider === Provider.AZURE
? ['eastus', 'westus', 'westeurope', 'northeurope', 'southeastasia']
: ['us-central1', 'europe-west1', 'asia-southeast1', 'us-east1', 'us-west1'];
const basePrice = parseFloat(this.getMockPrice(provider, instanceType));
return regions.map((region, index) => ({
region,
OnDemandHour: (basePrice * (0.9 + index * 0.05)).toFixed(4),
currency: 'USD'
}));
}
private getMockPrice(provider: Provider, instanceType: string): string {
const priceMap: Record<string, string> = {
't2.micro': '0.0116',
't2.small': '0.023',
't2.medium': '0.0464',
't3.micro': '0.0104',
't3.small': '0.0208',
'm5.large': '0.096',
'Standard_B1s': '0.0104',
'Standard_B2s': '0.0416',
'Standard_D2s_v3': '0.096',
'e2-micro': '0.0063',
'e2-small': '0.0126',
'n1-standard-1': '0.0475'
};
return priceMap[instanceType] || '0.10';
}
private getMockVCPUs(instanceType: string): number {
const vcpuMap: Record<string, number> = {
't2.micro': 1, 't2.small': 1, 't2.medium': 2,
't3.micro': 2, 't3.small': 2, 'm5.large': 2,
'Standard_B1s': 1, 'Standard_B2s': 2, 'Standard_D2s_v3': 2,
'e2-micro': 2, 'e2-small': 2, 'n1-standard-1': 1
};
return vcpuMap[instanceType] || 2;
}
private getMockMemory(instanceType: string): string {
const memoryMap: Record<string, string> = {
't2.micro': '1 GiB', 't2.small': '2 GiB', 't2.medium': '4 GiB',
't3.micro': '1 GiB', 't3.small': '2 GiB', 'm5.large': '8 GiB',
'Standard_B1s': '1 GiB', 'Standard_B2s': '4 GiB', 'Standard_D2s_v3': '8 GiB',
'e2-micro': '1 GiB', 'e2-small': '2 GiB', 'n1-standard-1': '3.75 GiB'
};
return memoryMap[instanceType] || '4 GiB';
}
}