From 9c1bbcdca7eba0e98bc5687edf03520ee167356b Mon Sep 17 00:00:00 2001 From: amitjoshi Date: Wed, 20 Nov 2024 15:47:59 +0530 Subject: [PATCH 1/4] Add environment list retrieval and refactor BAP endpoint logic --- src/common/services/BAPService.ts | 29 ++------- src/common/services/Constants.ts | 1 + src/common/services/TelemetryConstants.ts | 2 + src/common/utilities/Utils.ts | 73 +++++++++++++++++++++++ 4 files changed, 81 insertions(+), 24 deletions(-) diff --git a/src/common/services/BAPService.ts b/src/common/services/BAPService.ts index fb26251aa..bcfb51310 100644 --- a/src/common/services/BAPService.ts +++ b/src/common/services/BAPService.ts @@ -5,9 +5,10 @@ import { ITelemetry } from "../OneDSLoggerTelemetry/telemetry/ITelemetry"; import { bapServiceAuthentication, getCommonHeaders } from "./AuthenticationProvider"; -import { VSCODE_EXTENSION_GET_BAP_ENDPOINT_UNSUPPORTED_REGION, VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_COMPLETED, VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED } from "./TelemetryConstants"; +import { VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_COMPLETED, VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED } from "./TelemetryConstants"; import { ServiceEndpointCategory, BAP_API_VERSION, BAP_SERVICE_COPILOT_CROSS_GEO_FLAG_RELATIVE_URL, BAP_SERVICE_ENDPOINT } from "./Constants"; import { sendTelemetryEvent } from "../copilot/telemetry/copilotTelemetry"; +import { getBAPEndpoint } from "../utilities/Utils"; export class BAPService { public static async getCrossGeoCopilotDataMovementEnabledFlag(serviceEndpointStamp: ServiceEndpointCategory, telemetry: ITelemetry, environmentId: string): Promise { @@ -15,7 +16,7 @@ export class BAPService { try { const accessToken = await bapServiceAuthentication(telemetry, true); - const response = await fetch(await BAPService.getBAPEndpoint(serviceEndpointStamp, telemetry, environmentId), { + const response = await fetch(await BAPService.getBAPCopilotCrossGeoFlagEndpoint(serviceEndpointStamp, telemetry, environmentId), { method: 'GET', headers: getCommonHeaders(accessToken) }); @@ -33,29 +34,9 @@ export class BAPService { return false; } - static async getBAPEndpoint(serviceEndpointStamp: ServiceEndpointCategory, telemetry: ITelemetry, environmentId: string): Promise { + static async getBAPCopilotCrossGeoFlagEndpoint(serviceEndpointStamp: ServiceEndpointCategory, telemetry: ITelemetry, environmentId: string): Promise { - let bapEndpoint = ""; - - switch (serviceEndpointStamp) { - case ServiceEndpointCategory.TEST: - bapEndpoint = "https://test.api.bap.microsoft.com"; - break; - case ServiceEndpointCategory.PREPROD: - bapEndpoint = "https://preprod.api.bap.microsoft.com"; - break; - case ServiceEndpointCategory.PROD: - bapEndpoint = "https://api.bap.microsoft.com"; - break; - // All below endpoints are not supported yet - case ServiceEndpointCategory.DOD: - case ServiceEndpointCategory.GCC: - case ServiceEndpointCategory.HIGH: - case ServiceEndpointCategory.MOONCAKE: - default: - sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_GET_BAP_ENDPOINT_UNSUPPORTED_REGION, data: serviceEndpointStamp }); - break; - } + const bapEndpoint = await getBAPEndpoint(serviceEndpointStamp, telemetry); return BAP_SERVICE_ENDPOINT.replace('{rootURL}', bapEndpoint) + BAP_SERVICE_COPILOT_CROSS_GEO_FLAG_RELATIVE_URL.replace('{environmentID}', environmentId).replace('{apiVersion}', BAP_API_VERSION); diff --git a/src/common/services/Constants.ts b/src/common/services/Constants.ts index d41c586b4..791e3cc1c 100644 --- a/src/common/services/Constants.ts +++ b/src/common/services/Constants.ts @@ -17,6 +17,7 @@ export const BAP_API_VERSION = '2021-04-01'; export const BAP_SERVICE_SCOPE_DEFAULT = "https://api.bap.microsoft.com/.default"; export const BAP_SERVICE_ENDPOINT = `{rootURL}/providers/Microsoft.BusinessAppPlatform/`; export const BAP_SERVICE_COPILOT_CROSS_GEO_FLAG_RELATIVE_URL = `scopes/admin/environments/{environmentID}?$expand=properties/copilotPolicies&api-version={apiVersion}`; +export const BAP_ENVIRONMENT_LIST_URL = `scopes/admin/environments?api-version=2021-04-01&select=name,properties.displayName,properties.linkedEnvironmentMetadata`; // PPAPI constants export const PPAPI_WEBSITES_API_VERSION = '2022-03-01-preview'; diff --git a/src/common/services/TelemetryConstants.ts b/src/common/services/TelemetryConstants.ts index 4d4d26404..18615c9b2 100644 --- a/src/common/services/TelemetryConstants.ts +++ b/src/common/services/TelemetryConstants.ts @@ -24,3 +24,5 @@ export const VSCODE_EXTENSION_GET_PPAPI_WEBSITES_ENDPOINT_UNSUPPORTED_REGION = " export const VSCODE_EXTENSION_DECODE_JWT_TOKEN_FAILED = "VSCodeExtensionDecodeJWTTokenFailed"; export const VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_COMPLETED = "VSCodeExtensionPPAPIGetWebsiteByIdCompleted"; export const VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_FAILED = "VSCodeExtensionPPAPIGetWebsiteByIdFailed"; +export const VSCODE_EXTENSION_GET_ENV_LIST_SUCCESS = "VSCodeExtensionGetEnvListSuccess"; +export const VSCODE_EXTENSION_GET_ENV_LIST_FAILED = "VSCodeExtensionGetEnvListFailed"; diff --git a/src/common/utilities/Utils.ts b/src/common/utilities/Utils.ts index 853f97433..f5cd76c0d 100644 --- a/src/common/utilities/Utils.ts +++ b/src/common/utilities/Utils.ts @@ -14,6 +14,9 @@ import { getDisabledOrgList, getDisabledTenantList } from "../copilot/utils/copi import { CopilotNotAvailable, CopilotNotAvailableECSConfig } from "../copilot/telemetry/telemetryConstants"; import path from "path"; import { oneDSLoggerWrapper } from "../OneDSLoggerTelemetry/oneDSLoggerWrapper"; +import { bapServiceAuthentication } from "../services/AuthenticationProvider"; +import { BAP_ENVIRONMENT_LIST_URL, BAP_SERVICE_ENDPOINT, ServiceEndpointCategory } from "../services/Constants"; +import { VSCODE_EXTENSION_GET_ENV_LIST_SUCCESS, VSCODE_EXTENSION_GET_ENV_LIST_FAILED, VSCODE_EXTENSION_GET_BAP_ENDPOINT_UNSUPPORTED_REGION } from "../services/TelemetryConstants"; export function getSelectedCode(editor: vscode.TextEditor): string { if (!editor) { @@ -320,3 +323,73 @@ export function getECSOrgLocationValue(clusterName: string, clusterNumber: strin return extractedSubstring; } + +//API call to get env list for a org +export async function getEnvList(telemetry: ITelemetry, endpointStamp: ServiceEndpointCategory): Promise<{ envId: string, envDisplayName: string }[]> { + const envInfo: { envId: string, envDisplayName: string }[] = []; + try { + const bapAuthToken = await bapServiceAuthentication(telemetry, true); + const bapEndpoint = getBAPEndpoint(endpointStamp, telemetry); + const envListEndpoint = `${bapEndpoint}${BAP_ENVIRONMENT_LIST_URL}`; + + const envListResponse = await fetch(envListEndpoint, { + method: "GET", + headers: { + "Authorization": `Bearer ${bapAuthToken}` + } + }); + + if (envListResponse.ok) { + const envListJson = await envListResponse.json(); + envListJson.value.forEach((env: any) => { + envInfo.push({ + envId: env.properties.linkedEnvironmentMetadata.instanceUrl, + envDisplayName: env.properties.displayName + }); + }); + sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_GET_ENV_LIST_SUCCESS }); + oneDSLoggerWrapper.getLogger().traceInfo(VSCODE_EXTENSION_GET_ENV_LIST_SUCCESS); + } else { + sendTelemetryEvent(telemetry, { + eventName: VSCODE_EXTENSION_GET_ENV_LIST_FAILED, + errorMsg: envListResponse.statusText + }); + oneDSLoggerWrapper.getLogger().traceError(VSCODE_EXTENSION_GET_ENV_LIST_FAILED, VSCODE_EXTENSION_GET_ENV_LIST_FAILED, new Error(envListResponse.statusText)); + } + } catch (error) { + sendTelemetryEvent(telemetry, { + eventName: VSCODE_EXTENSION_GET_ENV_LIST_FAILED, + errorMsg: (error as Error).message + }); + oneDSLoggerWrapper.getLogger().traceError(VSCODE_EXTENSION_GET_ENV_LIST_FAILED, VSCODE_EXTENSION_GET_ENV_LIST_FAILED, error as Error); + } + return envInfo; +} + + +export function getBAPEndpoint(serviceEndpointStamp: ServiceEndpointCategory, telemetry: ITelemetry): string { + let bapEndpoint = ""; + + switch (serviceEndpointStamp) { + case ServiceEndpointCategory.TEST: + bapEndpoint = "https://test.api.bap.microsoft.com"; + break; + case ServiceEndpointCategory.PREPROD: + bapEndpoint = "https://preprod.api.bap.microsoft.com"; + break; + case ServiceEndpointCategory.PROD: + bapEndpoint = "https://api.bap.microsoft.com"; + break; + // All below endpoints are not supported yet + case ServiceEndpointCategory.DOD: + case ServiceEndpointCategory.GCC: + case ServiceEndpointCategory.HIGH: + case ServiceEndpointCategory.MOONCAKE: + default: + sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_GET_BAP_ENDPOINT_UNSUPPORTED_REGION, data: serviceEndpointStamp }); + oneDSLoggerWrapper.getLogger().traceInfo(VSCODE_EXTENSION_GET_BAP_ENDPOINT_UNSUPPORTED_REGION, { data: serviceEndpointStamp }); + break; + } + + return BAP_SERVICE_ENDPOINT.replace('{rootURL}', bapEndpoint) +} From d245756132bcddd83945e3ae4951e1e3bc00f4ec Mon Sep 17 00:00:00 2001 From: amitjoshi Date: Wed, 20 Nov 2024 16:04:26 +0530 Subject: [PATCH 2/4] Add type annotation for environment list retrieval in Utils.ts --- src/common/utilities/Utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/utilities/Utils.ts b/src/common/utilities/Utils.ts index f5cd76c0d..7d0bf2c33 100644 --- a/src/common/utilities/Utils.ts +++ b/src/common/utilities/Utils.ts @@ -341,6 +341,7 @@ export async function getEnvList(telemetry: ITelemetry, endpointStamp: ServiceEn if (envListResponse.ok) { const envListJson = await envListResponse.json(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any envListJson.value.forEach((env: any) => { envInfo.push({ envId: env.properties.linkedEnvironmentMetadata.instanceUrl, From db1f3ada1e8e5b01394d0208bfcafbcee4e3079c Mon Sep 17 00:00:00 2001 From: amitjoshi438 <54068463+amitjoshi438@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:19:01 +0530 Subject: [PATCH 3/4] Update src/common/utilities/Utils.ts Co-authored-by: Priyanshu Agrawal --- src/common/utilities/Utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/utilities/Utils.ts b/src/common/utilities/Utils.ts index 7d0bf2c33..7a4d322a8 100644 --- a/src/common/utilities/Utils.ts +++ b/src/common/utilities/Utils.ts @@ -324,7 +324,7 @@ export function getECSOrgLocationValue(clusterName: string, clusterNumber: strin return extractedSubstring; } -//API call to get env list for a org +//API call to get env list for an org export async function getEnvList(telemetry: ITelemetry, endpointStamp: ServiceEndpointCategory): Promise<{ envId: string, envDisplayName: string }[]> { const envInfo: { envId: string, envDisplayName: string }[] = []; try { From 70fa79426f281ad15925e75283c56a5650c71211 Mon Sep 17 00:00:00 2001 From: amitjoshi Date: Thu, 21 Nov 2024 18:30:26 +0530 Subject: [PATCH 4/4] Refactor BAP environment list URL to use a variable for API version and update imports in Utils.ts --- src/common/services/Constants.ts | 2 +- src/common/utilities/Utils.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/services/Constants.ts b/src/common/services/Constants.ts index 791e3cc1c..a77791abd 100644 --- a/src/common/services/Constants.ts +++ b/src/common/services/Constants.ts @@ -17,7 +17,7 @@ export const BAP_API_VERSION = '2021-04-01'; export const BAP_SERVICE_SCOPE_DEFAULT = "https://api.bap.microsoft.com/.default"; export const BAP_SERVICE_ENDPOINT = `{rootURL}/providers/Microsoft.BusinessAppPlatform/`; export const BAP_SERVICE_COPILOT_CROSS_GEO_FLAG_RELATIVE_URL = `scopes/admin/environments/{environmentID}?$expand=properties/copilotPolicies&api-version={apiVersion}`; -export const BAP_ENVIRONMENT_LIST_URL = `scopes/admin/environments?api-version=2021-04-01&select=name,properties.displayName,properties.linkedEnvironmentMetadata`; +export const BAP_ENVIRONMENT_LIST_URL = `scopes/admin/environments?api-version={apiVersion}&select=name,properties.displayName,properties.linkedEnvironmentMetadata`; // PPAPI constants export const PPAPI_WEBSITES_API_VERSION = '2022-03-01-preview'; diff --git a/src/common/utilities/Utils.ts b/src/common/utilities/Utils.ts index 7d0bf2c33..ca12cd5a7 100644 --- a/src/common/utilities/Utils.ts +++ b/src/common/utilities/Utils.ts @@ -15,7 +15,7 @@ import { CopilotNotAvailable, CopilotNotAvailableECSConfig } from "../copilot/te import path from "path"; import { oneDSLoggerWrapper } from "../OneDSLoggerTelemetry/oneDSLoggerWrapper"; import { bapServiceAuthentication } from "../services/AuthenticationProvider"; -import { BAP_ENVIRONMENT_LIST_URL, BAP_SERVICE_ENDPOINT, ServiceEndpointCategory } from "../services/Constants"; +import { BAP_API_VERSION, BAP_ENVIRONMENT_LIST_URL, BAP_SERVICE_ENDPOINT, ServiceEndpointCategory } from "../services/Constants"; import { VSCODE_EXTENSION_GET_ENV_LIST_SUCCESS, VSCODE_EXTENSION_GET_ENV_LIST_FAILED, VSCODE_EXTENSION_GET_BAP_ENDPOINT_UNSUPPORTED_REGION } from "../services/TelemetryConstants"; export function getSelectedCode(editor: vscode.TextEditor): string { @@ -330,7 +330,7 @@ export async function getEnvList(telemetry: ITelemetry, endpointStamp: ServiceEn try { const bapAuthToken = await bapServiceAuthentication(telemetry, true); const bapEndpoint = getBAPEndpoint(endpointStamp, telemetry); - const envListEndpoint = `${bapEndpoint}${BAP_ENVIRONMENT_LIST_URL}`; + const envListEndpoint = `${bapEndpoint}${BAP_ENVIRONMENT_LIST_URL.replace('{apiVersion}', BAP_API_VERSION)}`; const envListResponse = await fetch(envListEndpoint, { method: "GET",