diff --git a/extensions/arc/src/localizedConstants.ts b/extensions/arc/src/localizedConstants.ts index 394459d9b1..1175f08c39 100644 --- a/extensions/arc/src/localizedConstants.ts +++ b/extensions/arc/src/localizedConstants.ts @@ -141,6 +141,7 @@ export function updated(when: string): string { return localize('arc.updated', " // Errors export const connectionRequired = localize('arc.connectionRequired', "A connection is required to show all properties. Click refresh to re-enter connection information"); +export const couldNotFindControllerRegistration = localize('arc.couldNotFindControllerRegistration', "Could not find controller registration."); export function refreshFailed(error: any): string { return localize('arc.refreshFailed', "Refresh failed. {0}", getErrorMessage(error)); } export function openDashboardFailed(error: any): string { return localize('arc.openDashboardFailed', "Error opening dashboard. {0}", getErrorMessage(error)); } export function resourceDeletionFailed(name: string, error: any): string { return localize('arc.resourceDeletionFailed', "Failed to delete resource {0}. {1}", name, getErrorMessage(error)); } @@ -150,7 +151,6 @@ export function fetchConfigFailed(name: string, error: any): string { return loc export function fetchEndpointsFailed(name: string, error: any): string { return localize('arc.fetchEndpointsFailed', "An unexpected error occurred retrieving the endpoints for '{0}'. {1}", name, getErrorMessage(error)); } export function fetchRegistrationsFailed(name: string, error: any): string { return localize('arc.fetchRegistrationsFailed', "An unexpected error occurred retrieving the registrations for '{0}'. {1}", name, getErrorMessage(error)); } export function fetchDatabasesFailed(name: string, error: any): string { return localize('arc.fetchDatabasesFailed', "An unexpected error occurred retrieving the databases for '{0}'. {1}", name, getErrorMessage(error)); } -export function couldNotFindRegistration(namespace: string, name: string) { return localize('arc.couldNotFindRegistration', "Could not find controller registration for {0} ({1})", name, namespace); } export function resourceDeletionWarning(name: string): string { return localize('arc.resourceDeletionWarning', "Warning! Deleting a resource is permanent and cannot be undone. To delete the resource '{0}' type the name '{0}' below to proceed.", name); } export function invalidResourceDeletionName(name: string): string { return localize('arc.invalidResourceDeletionName', "The value '{0}' does not match the instance name. Try again or press escape to exit", name); } export function couldNotFindAzureResource(name: string): string { return localize('arc.couldNotFindAzureResource', "Could not find Azure resource for {0}", name); } diff --git a/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts b/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts index dbd85d4a93..7ca4087534 100644 --- a/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts +++ b/extensions/arc/src/ui/dashboards/controller/controllerDashboardOverviewPage.ts @@ -5,11 +5,12 @@ import * as azdata from 'azdata'; import * as vscode from 'vscode'; +import * as azurecore from 'azurecore'; import * as loc from '../../../localizedConstants'; import { DashboardPage } from '../../components/dashboardPage'; import { IconPathHelper, cssStyles, iconSize, ResourceType, Endpoints } from '../../../constants'; import { ControllerModel } from '../../../models/controllerModel'; -import { resourceTypeToDisplayName, getResourceTypeIcon, parseInstanceName } from '../../../common/utils'; +import { resourceTypeToDisplayName, getResourceTypeIcon, parseInstanceName, getConnectionModeDisplayText } from '../../../common/utils'; export class ControllerDashboardOverviewPage extends DashboardPage { @@ -19,6 +20,10 @@ export class ControllerDashboardOverviewPage extends DashboardPage { private _arcResourcesTable!: azdata.DeclarativeTableComponent; private _propertiesContainer!: azdata.PropertiesContainerComponent; + private _openInAzurePortalButton!: azdata.ButtonComponent; + + private _azurecoreApi: azurecore.IExtension; + private controllerProperties = { instanceName: '-', resourceGroupName: '-', @@ -32,6 +37,8 @@ export class ControllerDashboardOverviewPage extends DashboardPage { constructor(modelView: azdata.ModelView, private _controllerModel: ControllerModel) { super(modelView); + this._azurecoreApi = vscode.extensions.getExtension(azurecore.extension.name)?.exports; + this.disposables.push( this._controllerModel.onRegistrationsUpdated(() => this.eventuallyRunOnInitialized(() => this.handleRegistrationsUpdated())), this._controllerModel.onEndpointsUpdated(() => this.eventuallyRunOnInitialized(() => this.handleEndpointsUpdated()))); @@ -160,22 +167,20 @@ export class ControllerDashboardOverviewPage extends DashboardPage { } })); - const openInAzurePortalButton = this.modelView.modelBuilder.button().withProperties({ + this._openInAzurePortalButton = this.modelView.modelBuilder.button().withProperties({ label: loc.openInAzurePortal, iconPath: IconPathHelper.openInTab, - enabled: false + enabled: !!this._controllerModel.controllerConfig }).component(); this.disposables.push( - openInAzurePortalButton.onDidClick(async () => { + this._openInAzurePortalButton.onDidClick(async () => { const config = this._controllerModel.controllerConfig; if (config) { - /* TODO CHGAGNON CONFIG vscode.env.openExternal(vscode.Uri.parse( - `https://portal.azure.com/#resource/subscriptions/${config.subscriptionId}/resourceGroups/${config.resourceGroupName}/providers/Microsoft.AzureData/${ResourceType.dataControllers}/${config.instanceName}`)); - */ + `https://portal.azure.com/#resource/subscriptions/${config.spec.settings.azure.subscription}/resourceGroups/${config.spec.settings.azure.resourceGroup}/providers/Microsoft.AzureData/${ResourceType.dataControllers}/${config.metadata.name}`)); } else { - vscode.window.showErrorMessage(loc.couldNotFindRegistration(this._controllerModel.namespace, 'controller')); + vscode.window.showErrorMessage(loc.couldNotFindControllerRegistration); } })); @@ -183,18 +188,21 @@ export class ControllerDashboardOverviewPage extends DashboardPage { [ { component: newInstance }, { component: refreshButton, toolbarSeparatorAfter: true }, - { component: openInAzurePortalButton } + { component: this._openInAzurePortalButton } ] ).component(); } private handleRegistrationsUpdated(): void { const config = this._controllerModel.controllerConfig; + if (this._openInAzurePortalButton) { + this._openInAzurePortalButton.enabled = !!config; + } this.controllerProperties.instanceName = config?.metadata.name || this.controllerProperties.instanceName; - this.controllerProperties.resourceGroupName = /* TODO CHGAGNON RG */ this.controllerProperties.resourceGroupName; - this.controllerProperties.location = /* TODO CHGAGNON LOCATION */ this.controllerProperties.location; - this.controllerProperties.subscriptionId = /* TODO CHGAGNON LOCATION */ this.controllerProperties.subscriptionId; - this.controllerProperties.connectionMode = /* TODO CHGAGNON MODE getConnectionModeDisplayText(config?.connectionMode) || */ this.controllerProperties.connectionMode; + this.controllerProperties.resourceGroupName = config?.spec.settings.azure.resourceGroup || this.controllerProperties.resourceGroupName; + this.controllerProperties.location = this._azurecoreApi.getRegionDisplayName(config?.spec.settings.azure.location) || this.controllerProperties.location; + this.controllerProperties.subscriptionId = config?.spec.settings.azure.subscription || this.controllerProperties.subscriptionId; + this.controllerProperties.connectionMode = getConnectionModeDisplayText(config?.spec.settings.azure.connectionMode) || this.controllerProperties.connectionMode; this.controllerProperties.instanceNamespace = config?.metadata.namespace || this.controllerProperties.instanceNamespace; this.refreshDisplayedProperties(); diff --git a/extensions/arc/src/ui/dashboards/miaa/miaaDashboardOverviewPage.ts b/extensions/arc/src/ui/dashboards/miaa/miaaDashboardOverviewPage.ts index 38c0631aae..8dad524b36 100644 --- a/extensions/arc/src/ui/dashboards/miaa/miaaDashboardOverviewPage.ts +++ b/extensions/arc/src/ui/dashboards/miaa/miaaDashboardOverviewPage.ts @@ -7,8 +7,9 @@ import * as azdata from 'azdata'; import * as azdataExt from 'azdata-ext'; import * as vscode from 'vscode'; import * as loc from '../../../localizedConstants'; +import * as azurecore from 'azurecore'; import { DashboardPage } from '../../components/dashboardPage'; -import { IconPathHelper, cssStyles, Endpoints } from '../../../constants'; +import { IconPathHelper, cssStyles, Endpoints, ResourceType } from '../../../constants'; import { ControllerModel } from '../../../models/controllerModel'; import { getDatabaseStateDisplayText, promptForResourceDeletion } from '../../../common/utils'; import { MiaaModel } from '../../../models/miaaModel'; @@ -25,8 +26,10 @@ export class MiaaDashboardOverviewPage extends DashboardPage { private _grafanaLink!: azdata.HyperlinkComponent; private _databasesTable!: azdata.DeclarativeTableComponent; private _databasesMessage!: azdata.TextComponent; + private _openInAzurePortalButton!: azdata.ButtonComponent; private readonly _azdataApi: azdataExt.IExtension; + private readonly _azurecoreApi: azurecore.IExtension; private _instanceProperties = { resourceGroup: '-', @@ -42,6 +45,7 @@ export class MiaaDashboardOverviewPage extends DashboardPage { constructor(modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _miaaModel: MiaaModel) { super(modelView); this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports; + this._azurecoreApi = vscode.extensions.getExtension(azurecore.extension.name)?.exports; this._instanceProperties.miaaAdmin = this._miaaModel.username || this._instanceProperties.miaaAdmin; this.disposables.push( @@ -226,46 +230,43 @@ export class MiaaDashboardOverviewPage extends DashboardPage { } })); - const openInAzurePortalButton = this.modelView.modelBuilder.button().withProperties({ + this._openInAzurePortalButton = this.modelView.modelBuilder.button().withProperties({ label: loc.openInAzurePortal, - iconPath: IconPathHelper.openInTab + iconPath: IconPathHelper.openInTab, + enabled: !!this._controllerModel.controllerConfig }).component(); this.disposables.push( - openInAzurePortalButton.onDidClick(async () => { - /* TODO chgagnon enable open in Azure - const r = this._controllerModel.getRegistration(ResourceType.sqlManagedInstances, this._miaaModel.info.namespace, this._miaaModel.info.name); - if (r) { + this._openInAzurePortalButton.onDidClick(async () => { + const config = this._controllerModel.controllerConfig; + if (config) { vscode.env.openExternal(vscode.Uri.parse( - `https://portal.azure.com/#resource/subscriptions/${r.subscriptionId}/resourceGroups/${r.resourceGroupName}/providers/Microsoft.AzureData/${ResourceType.sqlManagedInstances}/${r.instanceName}`)); + `https://portal.azure.com/#resource/subscriptions/${config.spec.settings.azure.subscription}/resourceGroups/${config.spec.settings.azure.resourceGroup}/providers/Microsoft.AzureData/${ResourceType.sqlManagedInstances}/${this._miaaModel.info.name}`)); } else { - vscode.window.showErrorMessage(loc.couldNotFindRegistration(this._miaaModel.info.namespace, this._miaaModel.info.name)); + vscode.window.showErrorMessage(loc.couldNotFindControllerRegistration); } - */ })); return this.modelView.modelBuilder.toolbarContainer().withToolbarItems( [ { component: deleteButton }, { component: refreshButton, toolbarSeparatorAfter: true }, - { component: openInAzurePortalButton } + { component: this._openInAzurePortalButton } ] ).component(); } private handleRegistrationsUpdated(): void { - // TODO chgagnon - /* - const reg = this._controllerModel.getRegistration(ResourceType.sqlManagedInstances, this._miaaModel.info.namespace || '', this._miaaModel.info.name); - if (reg) { - this._instanceProperties.resourceGroup = reg.resourceGroupName || '-'; - this._instanceProperties.dataController = this._controllerModel.controllerConfig?.metadata.name || '-'; - this._instanceProperties.region = reg.region || '-'; - this._instanceProperties.subscriptionId = reg.subscriptionId || '-'; - this._instanceProperties.vCores = reg.vCores || ''; - this.refreshDisplayedProperties(); + const config = this._controllerModel.controllerConfig; + if (this._openInAzurePortalButton) { + this._openInAzurePortalButton.enabled = !!config; } - */ + this._instanceProperties.resourceGroup = config?.spec.settings.azure.resourceGroup || this._instanceProperties.resourceGroup; + this._instanceProperties.dataController = config?.metadata.name || this._instanceProperties.dataController; + this._instanceProperties.region = this._azurecoreApi.getRegionDisplayName(config?.spec.settings.azure.location) || this._instanceProperties.region; + this._instanceProperties.subscriptionId = config?.spec.settings.azure.subscription || this._instanceProperties.subscriptionId; + // this._instanceProperties.vCores = reg.vCores || ''; + this.refreshDisplayedProperties(); } private handleMiaaConfigUpdated(): void { diff --git a/extensions/azdata/src/typings/azdata-ext.d.ts b/extensions/azdata/src/typings/azdata-ext.d.ts index 45ea43eb67..2679eb01fd 100644 --- a/extensions/azdata/src/typings/azdata-ext.d.ts +++ b/extensions/azdata/src/typings/azdata-ext.d.ts @@ -75,6 +75,12 @@ declare module 'azdata-ext' { ElasticSearch: { 'vm.max_map_count': string // "-1" }, + azure: { + connectionMode: string, // "indirect", + location: string, // "eastus2euap", + resourceGroup: string, // "my-rg", + subscription: string, // "a5082b29-8c6e-4bc5-8ddd-8ef39dfebc39" + }, controller: { 'enableBilling': string, // "True" 'logs.rotation.days': string, // "7"