update UPAPI calls

This commit is contained in:
Tara Zou 2024-04-26 14:15:59 -04:00
parent d7718c42da
commit 6ba2ff6000
5 changed files with 48 additions and 31 deletions

View File

@ -97,9 +97,6 @@ const handleMessage = async (event: MessageEvent): Promise<void> => {
} }
const inputs = event.data.data.inputs as SelfServeFrameInputs; const inputs = event.data.data.inputs as SelfServeFrameInputs;
// Test
console.log("catalogAPIKey" + inputs.catalogAPIKey);
// End Test
if (!inputs) { if (!inputs) {
return; return;
} }

View File

@ -1,5 +1,6 @@
import { configContext } from "../../ConfigContext"; import { configContext } from "../../ConfigContext";
import { userContext } from "../../UserContext"; import { userContext } from "../../UserContext";
import { get } from "../../Utils/arm/generatedClients/cosmos/locations";
import { armRequestWithoutPolling, getOfferingIdsRequest } from "../../Utils/arm/request"; import { armRequestWithoutPolling, getOfferingIdsRequest } from "../../Utils/arm/request";
import { selfServeTraceFailure, selfServeTraceStart, selfServeTraceSuccess } from "../SelfServeTelemetryProcessor"; import { selfServeTraceFailure, selfServeTraceStart, selfServeTraceSuccess } from "../SelfServeTelemetryProcessor";
import { RefreshResult } from "../SelfServeTypes"; import { RefreshResult } from "../SelfServeTypes";
@ -169,6 +170,16 @@ export const getRegions = async (): Promise<Array<RegionItem>> => {
} }
}; };
export const getRegionShortName = async (regionDisplayName: string) : Promise<string> => {
const locationsList = await get(userContext.subscriptionId, regionDisplayName);
if ('id' in locationsList) {
const locationId = locationsList.id;
return locationId.substring(locationId.lastIndexOf('/') + 1);
}
return undefined;
}
const getFetchPricesPathForRegion = (subscriptionId: string): string => { const getFetchPricesPathForRegion = (subscriptionId: string): string => {
return `/subscriptions/${subscriptionId}/providers/Microsoft.CostManagement/fetchPrices`; return `/subscriptions/${subscriptionId}/providers/Microsoft.CostManagement/fetchPrices`;
}; };
@ -187,9 +198,10 @@ export const getPriceMapAndCurrencyCode = async (map: OfferingIdMap): Promise<Pr
let pricingCurrency; let pricingCurrency;
for (const region of map.keys()) { for (const region of map.keys()) {
const regionPriceMap = new Map<string, number>(); const regionPriceMap = new Map<string, number>();
const regionShortName = await getRegionShortName(region);
const requestBody: OfferingIdRequest = { const requestBody: OfferingIdRequest = {
location: region, location: regionShortName,
ids: Array.from(map.get(region).values()), ids: Array.from(map.get(region).keys()),
}; };
const response = await armRequestWithoutPolling<FetchPricesResponse>({ const response = await armRequestWithoutPolling<FetchPricesResponse>({
@ -200,16 +212,20 @@ export const getPriceMapAndCurrencyCode = async (map: OfferingIdMap): Promise<Pr
body: requestBody, body: requestBody,
}); });
for (const item of response.result.Items) { for (const item of response.result) {
if (pricingCurrency === undefined) { if (pricingCurrency === undefined) {
pricingCurrency = item.pricingCurrency; pricingCurrency = item.pricingCurrency;
} else if (item.pricingCurrency !== pricingCurrency) { } else if (item.pricingCurrency !== pricingCurrency) {
throw Error("Currency Code Mismatch: Currency code not same for all regions / skus."); throw Error("Currency Code Mismatch: Currency code not same for all regions / skus.");
} }
if (item.error) {
throw Error(`Get price error ${item.error.type} for ${item.id}: ${item.error.description}`);
}
const offeringId = item.id; const offeringId = item.id;
const skuName = map.get(region).get(offeringId); const skuName = map.get(region).get(offeringId);
const unitPrice = item.prices.find(x => x.type == "Consumption").unitPrice; const unitPrice = item.prices.find(x => x.type == "Consumption")?.unitPrice;
regionPriceMap.set(skuName, unitPrice); regionPriceMap.set(skuName, unitPrice);
} }
priceMap.set(region, regionPriceMap); priceMap.set(region, regionPriceMap);
@ -224,6 +240,10 @@ export const getPriceMapAndCurrencyCode = async (map: OfferingIdMap): Promise<Pr
} }
}; };
const getOfferingIdPathForRegion = (): string => {
return `/skus?serviceFamily=Databases&service=Azure Cosmos DB`;
};
export const getOfferingIds = async (regions: Array<RegionItem>): Promise<OfferingIdMap> => { export const getOfferingIds = async (regions: Array<RegionItem>): Promise<OfferingIdMap> => {
const telemetryData = { const telemetryData = {
feature: "Get Offering Ids to calculate approximate cost", feature: "Get Offering Ids to calculate approximate cost",
@ -235,25 +255,27 @@ export const getOfferingIds = async (regions: Array<RegionItem>): Promise<Offeri
try { try {
const offeringIdMap = new Map<string, Map<string, string>>(); const offeringIdMap = new Map<string, Map<string, string>>();
let currencyCode;
for (const regionItem of regions) { for (const regionItem of regions) {
const regionOfferingIdMap = new Map<string, string>(); const regionOfferingIdMap = new Map<string, string>();
const regionShortName = await getRegionShortName(regionItem.locationName);
const response = await getOfferingIdsRequest<GetOfferingIdsResponse>({ const response = await getOfferingIdsRequest<GetOfferingIdsResponse>({
host: configContext.CATALOG_ENDPOINT, host: configContext.CATALOG_ENDPOINT,
path: `/skus`, path: getOfferingIdPathForRegion(),
method: "GET", method: "GET",
apiVersion: "2023-05-01-preview", apiVersion: "2023-05-01-preview",
queryParams: { queryParams: {
filter: filter:
"locationseq '" + "armRegionNameeq '" +
regionItem.locationName + regionShortName +
"'andserviceFamilyeq 'Databases' and service eq 'Azure Cosmos DB'", "'",
}, },
}); });
for (const item of response.result.Items) { for (const item of response.result.items) {
regionOfferingIdMap.set(item.skuName, item.offeringProperties.offeringId); if (item.offeringProperties?.length > 0) {
regionOfferingIdMap.set(item.offeringProperties[0].offeringId, item.skuName);
}
} }
offeringIdMap.set(regionItem.locationName, regionOfferingIdMap); offeringIdMap.set(regionItem.locationName, regionOfferingIdMap);
} }

View File

@ -24,6 +24,7 @@ import { BladeType, generateBladeLink } from "../SelfServeUtils";
import { import {
deleteDedicatedGatewayResource, deleteDedicatedGatewayResource,
getCurrentProvisioningState, getCurrentProvisioningState,
getOfferingIds,
getPriceMapAndCurrencyCode, getPriceMapAndCurrencyCode,
getRegions, getRegions,
refreshDedicatedGatewayProvisioning, refreshDedicatedGatewayProvisioning,
@ -370,9 +371,10 @@ export default class SqlX extends SelfServeBaseClass {
}); });
regions = await getRegions(); regions = await getRegions();
const priceMapAndCurrencyCode = await getPriceMapAndCurrencyCode(regions); const offeringIdMap = await getOfferingIds(regions);
const priceMapAndCurrencyCode = await getPriceMapAndCurrencyCode(offeringIdMap);
priceMap = priceMapAndCurrencyCode.priceMap; priceMap = priceMapAndCurrencyCode.priceMap;
currencyCode = priceMapAndCurrencyCode.currencyCode; currencyCode = priceMapAndCurrencyCode.pricingCurrency;
const response = await getCurrentProvisioningState(); const response = await getCurrentProvisioningState();
if (response.status && response.status !== "Deleting") { if (response.status && response.status !== "Deleting") {

View File

@ -30,16 +30,13 @@ export type UpdateDedicatedGatewayRequestProperties = {
serviceType: string; serviceType: string;
}; };
export type FetchPricesResponse = { export type FetchPricesResponse = Array<PriceItem>;
Items: Array<PriceItem>;
NextPageLink: string | undefined;
Count: number;
};
export type PriceItem = { export type PriceItem = {
prices: Array<PriceType>; prices: Array<PriceType>;
id: string; id: string;
pricingCurrency: string; pricingCurrency: string;
error: PriceError;
}; };
export type PriceType = { export type PriceType = {
@ -47,20 +44,24 @@ export type PriceType = {
unitPrice: number; unitPrice: number;
} }
export type PriceError = {
type: string;
description: string;
}
export type PriceMapAndCurrencyCode = { export type PriceMapAndCurrencyCode = {
priceMap: Map<string, Map<string, number>>; priceMap: Map<string, Map<string, number>>;
pricingCurrency: string; pricingCurrency: string;
}; };
export type GetOfferingIdsResponse = { export type GetOfferingIdsResponse = {
Items: Array<OfferingIdItem>; items: Array<OfferingIdItem>;
NextPageLink: string | undefined; nextPageLink: string | undefined;
Count: number;
}; };
export type OfferingIdItem = { export type OfferingIdItem = {
skuName: string; skuName: string;
offeringProperties: OfferingProperties; offeringProperties: Array<OfferingProperties>;
}; };
export type OfferingProperties = { export type OfferingProperties = {

View File

@ -181,15 +181,10 @@ export async function getOfferingIdsRequest<T>({
throw new Error("No catalog API key provided"); throw new Error("No catalog API key provided");
} }
// TODO: delete after test
// console.log("config CATALOG_API_KEY: " + configContext.CATALOG_API_KEY);
// End Test
const response = await window.fetch(url.href, { const response = await window.fetch(url.href, {
method, method,
headers: { headers: {
// [HttpHeaders.xAPIKey]: configContext.CATALOG_API_KEY, [HttpHeaders.xAPIKey]: configContext.CATALOG_API_KEY,
[HttpHeaders.xAPIKey]: "",
}, },
body: requestBody ? JSON.stringify(requestBody) : undefined, body: requestBody ? JSON.stringify(requestBody) : undefined,
}); });