diff --git a/configs/mpac.json b/configs/mpac.json index 7c270c6d5..21d8dbebe 100644 --- a/configs/mpac.json +++ b/configs/mpac.json @@ -1,3 +1,4 @@ { - "JUNO_ENDPOINT": "https://tools-staging.cosmos.azure.com" + "JUNO_ENDPOINT": "https://tools-staging.cosmos.azure.com", + "IS_MPAC" : true } \ No newline at end of file diff --git a/configs/prod.json b/configs/prod.json index e2614b018..a994e0636 100644 --- a/configs/prod.json +++ b/configs/prod.json @@ -1,3 +1,4 @@ { - "JUNO_ENDPOINT": "https://tools.cosmos.azure.com" + "JUNO_ENDPOINT": "https://tools.cosmos.azure.com", + "IS_MPAC" : false } diff --git a/src/ConfigContext.ts b/src/ConfigContext.ts index 224d28f8d..89217fbef 100644 --- a/src/ConfigContext.ts +++ b/src/ConfigContext.ts @@ -24,6 +24,7 @@ export interface ConfigContext { JUNO_ENDPOINT: string; GITHUB_CLIENT_ID: string; GITHUB_CLIENT_SECRET?: string; // No need to inject secret for prod. Juno already knows it. + IS_MPAC: boolean; hostedExplorerURL: string; armAPIVersion?: string; allowedJunoOrigins: string[]; @@ -53,6 +54,7 @@ let configContext: Readonly = { ARCADIA_ENDPOINT: "https://workspaceartifacts.projectarcadia.net", ARCADIA_LIVY_ENDPOINT_DNS_ZONE: "dev.azuresynapse.net", GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/settings/applications/1189306 + IS_MPAC: false, JUNO_ENDPOINT: "https://tools.cosmos.azure.com", BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com", allowedJunoOrigins: [ diff --git a/src/Contracts/DataModels.ts b/src/Contracts/DataModels.ts index 2a0d8c6a5..64a9575d3 100644 --- a/src/Contracts/DataModels.ts +++ b/src/Contracts/DataModels.ts @@ -441,13 +441,7 @@ export interface IProvisionData { cosmosEndpoint: string; } -export interface IAccountData { - subscriptionId: string; - resourceGroup: string; - dbAccountName: string; -} - -export interface IContainerData extends IAccountData { +export interface IContainerData { forwardingId: string; } diff --git a/src/Explorer/Explorer.tsx b/src/Explorer/Explorer.tsx index 1a20c68a0..1036dce6d 100644 --- a/src/Explorer/Explorer.tsx +++ b/src/Explorer/Explorer.tsx @@ -16,7 +16,6 @@ import { QueriesClient } from "../Common/QueriesClient"; import * as DataModels from "../Contracts/DataModels"; import { ContainerConnectionInfo, - IAccountData, IContainerData, IPhoenixConnectionInfoResult, IProvisionData, @@ -373,18 +372,13 @@ export default class Explorer { const provisionData: IProvisionData = { cosmosEndpoint: userContext.databaseAccount.properties.documentEndpoint, }; - const accountData: IAccountData = { - subscriptionId: userContext.subscriptionId, - resourceGroup: userContext.resourceGroup, - dbAccountName: userContext.databaseAccount.name, - }; const connectionStatus: ContainerConnectionInfo = { status: ConnectionStatusType.Connecting, }; useNotebook.getState().setConnectionInfo(connectionStatus); try { useNotebook.getState().setIsAllocating(true); - const connectionInfo = await this.phoenixClient.allocateContainer(provisionData, accountData); + const connectionInfo = await this.phoenixClient.allocateContainer(provisionData); await this.setNotebookInfo(connectionInfo, connectionStatus); } catch (error) { connectionStatus.status = ConnectionStatusType.Failed; @@ -404,9 +398,6 @@ export default class Explorer { ) { if (connectionInfo.status === HttpStatusCodes.OK && connectionInfo.data && connectionInfo.data.notebookServerUrl) { const containerData: IContainerData = { - subscriptionId: userContext.subscriptionId, - resourceGroup: userContext.resourceGroup, - dbAccountName: userContext.databaseAccount.name, forwardingId: connectionInfo.data.forwardingId, }; await this.phoenixClient.initiateContainerHeartBeat(containerData); @@ -1285,7 +1276,7 @@ export default class Explorer { await useNotebook.getState().refreshNotebooksEnabledStateForAccount(); //Disable phoenix in case of Vnet or Firewall was enabled. - if (useNotebook.getState().isPhoenix && !isPublicInternetAccessAllowed()) { + if (!isPublicInternetAccessAllowed()) { useNotebook.getState().setIsPhoenix(false); } // TODO: remove reference to isNotebookEnabled and isNotebooksEnabledForAccount @@ -1299,12 +1290,7 @@ export default class Explorer { }); if (useNotebook.getState().isPhoenix) { - if (isNotebookEnabled) { - await this.initNotebooks(userContext.databaseAccount); - } else if (this.notebookToImport) { - // if notebooks is not enabled but the user is trying to do a quickstart setup with notebooks, open the SetupNotebooksPane - this._openSetupNotebooksPaneForQuickstart(); - } + await this.initNotebooks(userContext.databaseAccount); } } } diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx index a322190a2..48e78488c 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.tsx @@ -78,8 +78,9 @@ export function createStaticCommandBarButtons( if (container.notebookManager?.gitHubOAuthService) { notebookButtons.push(createManageGitHubAccountButton(container)); } - - notebookButtons.push(createOpenTerminalButton(container)); + if (useNotebook.getState().isPhoenix && configContext.IS_MPAC) { + notebookButtons.push(createOpenTerminalButton(container)); + } if (selectedNodeState.isConnectedToContainer()) { notebookButtons.push(createNotebookWorkspaceResetButton(container)); } diff --git a/src/Explorer/Notebook/NotebookContainerClient.ts b/src/Explorer/Notebook/NotebookContainerClient.ts index d7bccf04b..13ace69e4 100644 --- a/src/Explorer/Notebook/NotebookContainerClient.ts +++ b/src/Explorer/Notebook/NotebookContainerClient.ts @@ -8,15 +8,8 @@ import { ConnectionStatusType, HttpHeaders, HttpStatusCodes, Notebook } from ".. import { getErrorMessage } from "../../Common/ErrorHandlingUtils"; import * as Logger from "../../Common/Logger"; import * as DataModels from "../../Contracts/DataModels"; -import { - ContainerConnectionInfo, - IAccountData, - IPhoenixConnectionInfoResult, - IProvisionData, - IResponse, -} from "../../Contracts/DataModels"; +import { IPhoenixConnectionInfoResult, IProvisionData, IResponse } from "../../Contracts/DataModels"; import { userContext } from "../../UserContext"; -import { createOrUpdate, destroy } from "../../Utils/arm/generatedClients/cosmosNotebooks/notebookWorkspaces"; import { getAuthorizationHeader } from "../../Utils/AuthorizationUtils"; import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { useNotebook } from "./useNotebook"; @@ -55,21 +48,11 @@ export class NotebookContainerClient { */ private scheduleHeartbeat(delayMs: number): void { setTimeout(async () => { - try { - const memoryUsageInfo = await this.getMemoryUsage(); - useNotebook.getState().setMemoryUsageInfo(memoryUsageInfo); - const notebookServerInfo = useNotebook.getState().notebookServerInfo; - if (notebookServerInfo?.notebookServerEndpoint) { - this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs); - } - } catch (exception) { - if (useNotebook.getState().isPhoenix) { - const connectionStatus: ContainerConnectionInfo = { - status: ConnectionStatusType.Failed, - }; - useNotebook.getState().resetContainerConnection(connectionStatus); - useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed); - } + const memoryUsageInfo = await this.getMemoryUsage(); + useNotebook.getState().setMemoryUsageInfo(memoryUsageInfo); + const notebookServerInfo = useNotebook.getState().notebookServerInfo; + if (notebookServerInfo?.notebookServerEndpoint) { + this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs); } }, delayMs); } @@ -108,7 +91,7 @@ export class NotebookContainerClient { notebookServerEndpoint: string, authToken: string ): Promise { - if (this.checkStatus()) { + if (this.shouldExecuteMemoryCall()) { const response = await fetch(`${notebookServerEndpoint}api/metrics/memory`, { method: "GET", headers: { @@ -137,26 +120,14 @@ export class NotebookContainerClient { } } - private checkStatus(): boolean { - if (useNotebook.getState().isPhoenix) { - if ( - useNotebook.getState().containerStatus?.status === Constants.ContainerStatusType.Disconnected && - useNotebook.getState().connectionInfo?.status === ConnectionStatusType.Connect - ) { - const connectionStatus: ContainerConnectionInfo = { - status: ConnectionStatusType.Reconnect, - }; - useNotebook.getState().resetContainerConnection(connectionStatus); - useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed); - return false; - } else if ( - useNotebook.getState().containerStatus?.status === Constants.ContainerStatusType.Disconnected || - useNotebook.getState().connectionInfo?.status === ConnectionStatusType.Reconnect - ) { - return false; - } + private shouldExecuteMemoryCall(): boolean { + if ( + useNotebook.getState().containerStatus?.status === Constants.ContainerStatusType.Active && + useNotebook.getState().connectionInfo?.status === ConnectionStatusType.Connected + ) { + return true; } - return true; + return false; } public async resetWorkspace(): Promise> { @@ -185,19 +156,11 @@ export class NotebookContainerClient { const provisionData: IProvisionData = { cosmosEndpoint: userContext.databaseAccount.properties.documentEndpoint, }; - const accountData: IAccountData = { - subscriptionId: userContext.subscriptionId, - resourceGroup: userContext.resourceGroup, - dbAccountName: userContext.databaseAccount.name, - }; - return await this.phoenixClient.resetContainer(provisionData, accountData); + return await this.phoenixClient.resetContainer(provisionData); } return null; } catch (error) { Logger.logError(getErrorMessage(error), "NotebookContainerClient/resetWorkspace"); - if (!useNotebook.getState().isPhoenix) { - await this.recreateNotebookWorkspaceAsync(); - } throw error; } } @@ -212,25 +175,6 @@ export class NotebookContainerClient { }; } - private async recreateNotebookWorkspaceAsync(): Promise { - const { databaseAccount } = userContext; - if (!databaseAccount?.id) { - throw new Error("DataExplorer not initialized"); - } - try { - await destroy(userContext.subscriptionId, userContext.resourceGroup, userContext.databaseAccount.name, "default"); - await createOrUpdate( - userContext.subscriptionId, - userContext.resourceGroup, - userContext.databaseAccount.name, - "default" - ); - } catch (error) { - Logger.logError(getErrorMessage(error), "NotebookContainerClient/recreateNotebookWorkspaceAsync"); - return Promise.reject(error); - } - } - private getHeaders(): HeadersInit { const authorizationHeader = getAuthorizationHeader(); return { diff --git a/src/Explorer/Notebook/useNotebook.ts b/src/Explorer/Notebook/useNotebook.ts index 756cbfbdd..72b55b433 100644 --- a/src/Explorer/Notebook/useNotebook.ts +++ b/src/Explorer/Notebook/useNotebook.ts @@ -8,7 +8,7 @@ import { getErrorMessage } from "../../Common/ErrorHandlingUtils"; import * as Logger from "../../Common/Logger"; import { configContext } from "../../ConfigContext"; import * as DataModels from "../../Contracts/DataModels"; -import { ContainerConnectionInfo, ContainerInfo, IAccountData } from "../../Contracts/DataModels"; +import { ContainerConnectionInfo, ContainerInfo } from "../../Contracts/DataModels"; import { useTabs } from "../../hooks/useTabs"; import { IPinnedRepo } from "../../Juno/JunoClient"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; @@ -300,13 +300,7 @@ export const useNotebook: UseStore = create((set, get) => ({ getPhoenixStatus: async () => { if (get().isPhoenix === undefined) { const phoenixClient = new PhoenixClient(); - const accountData: IAccountData = { - subscriptionId: userContext.subscriptionId, - resourceGroup: userContext.resourceGroup, - dbAccountName: userContext.databaseAccount.name, - }; - const isPhoenix = - userContext.features.phoenix === true && (await phoenixClient.IsDbAcountWhitelisted(accountData)); + const isPhoenix = userContext.features.phoenix === true && (await phoenixClient.IsDbAcountWhitelisted()); set({ isPhoenix }); } }, diff --git a/src/Explorer/Tree/ResourceTree.tsx b/src/Explorer/Tree/ResourceTree.tsx index 3b942a2ef..17f532ba9 100644 --- a/src/Explorer/Tree/ResourceTree.tsx +++ b/src/Explorer/Tree/ResourceTree.tsx @@ -121,7 +121,7 @@ export const ResourceTree: React.FC = ({ container }: Resourc children: [], }; - if (useNotebook.getState().isPhoenix === false) { + if (!useNotebook.getState().isPhoenix) { notebooksTree.children.push(buildNotebooksTemporarilyDownTree()); } else { if (galleryContentRoot) { diff --git a/src/Phoenix/PhoenixClient.ts b/src/Phoenix/PhoenixClient.ts index 94bc23922..3c86a529f 100644 --- a/src/Phoenix/PhoenixClient.ts +++ b/src/Phoenix/PhoenixClient.ts @@ -6,7 +6,6 @@ import { configContext } from "../ConfigContext"; import { ContainerConnectionInfo, ContainerInfo, - IAccountData, IContainerData, IPhoenixConnectionInfoResult, IProvisionData, @@ -24,30 +23,21 @@ export class PhoenixClient { minTimeout: Notebook.retryAttemptDelayMs, }; - public async allocateContainer( - provisionData: IProvisionData, - accountData: IAccountData - ): Promise> { - return this.executeContainerAssignmentOperation(provisionData, accountData, "allocate"); + public async allocateContainer(provisionData: IProvisionData): Promise> { + return this.executeContainerAssignmentOperation(provisionData, "allocate"); } - public async resetContainer( - provisionData: IProvisionData, - accountData: IAccountData - ): Promise> { - return this.executeContainerAssignmentOperation(provisionData, accountData, "reset"); + public async resetContainer(provisionData: IProvisionData): Promise> { + return this.executeContainerAssignmentOperation(provisionData, "reset"); } private async executeContainerAssignmentOperation( provisionData: IProvisionData, - accountData: IAccountData, operation: string ): Promise> { try { const response = await fetch( - `${this.getPhoenixContainerPoolingEndPoint()}/subscriptions/${accountData.subscriptionId}/resourceGroups/${ - accountData.resourceGroup - }/providers/Microsoft.DocumentDB/databaseAccounts/${accountData.dbAccountName}/containerconnections`, + `${this.getPhoenixControlPlaneEndpoint()}${userContext.databaseAccount.id}/containerconnections`, { method: operation === "allocate" ? "POST" : "PATCH", headers: PhoenixClient.getHeaders(), @@ -86,11 +76,7 @@ export class PhoenixClient { try { const runContainerStatusAsync = async () => { const response = await window.fetch( - `${this.getPhoenixContainerPoolingEndPoint()}/subscriptions/${containerData.subscriptionId}/resourceGroups/${ - containerData.resourceGroup - }/providers/Microsoft.DocumentDB/databaseAccounts/${containerData.dbAccountName}/${ - containerData.forwardingId - }`, + `${this.getPhoenixControlPlaneEndpoint()}${userContext.databaseAccount.id}/${containerData.forwardingId}`, { method: "GET", headers: PhoenixClient.getHeaders(), @@ -130,37 +116,19 @@ export class PhoenixClient { } private async getContainerHealth(delayMs: number, containerData: IContainerData) { - try { - const containerInfo = await this.getContainerStatusAsync(containerData); - useNotebook.getState().setContainerStatus(containerInfo); - if (useNotebook.getState().containerStatus?.status === ContainerStatusType.Active) { - this.scheduleContainerHeartbeat(delayMs, containerData); - } - } catch (exception) { - const connectionStatus: ContainerConnectionInfo = { - status: ConnectionStatusType.Reconnect, - }; - useNotebook.getState().resetContainerConnection(connectionStatus); - useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed); - useNotebook.getState().setContainerStatus({ - durationLeftInMinutes: undefined, - notebookServerInfo: undefined, - status: ContainerStatusType.Disconnected, - }); + const containerInfo = await this.getContainerStatusAsync(containerData); + useNotebook.getState().setContainerStatus(containerInfo); + if (useNotebook.getState().containerStatus?.status === ContainerStatusType.Active) { + this.scheduleContainerHeartbeat(delayMs, containerData); } } - public async IsDbAcountWhitelisted(accountData: IAccountData) { + public async IsDbAcountWhitelisted() { try { - const response = await window.fetch( - `${this.getPhoenixContainerPoolingEndPoint()}/subscriptions/${accountData.subscriptionId}/resourceGroups/${ - accountData.resourceGroup - }/providers/Microsoft.DocumentDB/databaseAccounts/${accountData.dbAccountName}`, - { - method: "GET", - headers: PhoenixClient.getHeaders(), - } - ); + const response = await window.fetch(`${this.getPhoenixControlPlaneEndpoint()}${userContext.databaseAccount.id}`, { + method: "GET", + headers: PhoenixClient.getHeaders(), + }); return response.status === HttpStatusCodes.OK; } catch (error) { Logger.logError(getErrorMessage(error), "PhoenixClient/IsDbAcountWhitelisted"); @@ -180,7 +148,7 @@ export class PhoenixClient { return phoenixEndpoint; } - public getPhoenixContainerPoolingEndPoint(): string { + public getPhoenixControlPlaneEndpoint(): string { return `${PhoenixClient.getPhoenixEndpoint()}/api/controlplane/toolscontainer/cosmosaccounts`; }