mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Rewrite Spark UI link when using unified connection (#4362)
* Rewrite Spark UI link when using unified connection * Add more robust error checking
This commit is contained in:
@@ -11,6 +11,7 @@ import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
|||||||
import { AppContext } from './appContext';
|
import { AppContext } from './appContext';
|
||||||
import { SqlClusterConnection } from './objectExplorerNodeProvider/connection';
|
import { SqlClusterConnection } from './objectExplorerNodeProvider/connection';
|
||||||
import { ICommandObjectExplorerContext } from './objectExplorerNodeProvider/command';
|
import { ICommandObjectExplorerContext } from './objectExplorerNodeProvider/command';
|
||||||
|
import { IEndpoint } from './utils';
|
||||||
import { MssqlObjectExplorerNodeProvider } from './objectExplorerNodeProvider/objectExplorerNodeProvider';
|
import { MssqlObjectExplorerNodeProvider } from './objectExplorerNodeProvider/objectExplorerNodeProvider';
|
||||||
|
|
||||||
|
|
||||||
@@ -118,12 +119,6 @@ function connToConnectionParam(connection: azdata.connection.Connection): Connec
|
|||||||
return <ConnectionParam>result;
|
return <ConnectionParam>result;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IEndpoint {
|
|
||||||
serviceName: string;
|
|
||||||
ipAddress: string;
|
|
||||||
port: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConnectionParam implements azdata.connection.Connection, azdata.IConnectionProfile, azdata.ConnectionInfo
|
class ConnectionParam implements azdata.connection.Connection, azdata.IConnectionProfile, azdata.ConnectionInfo
|
||||||
{
|
{
|
||||||
public connectionName: string;
|
public connectionName: string;
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ export async function getClusterEndpoint(profileId: string, serviceName: string)
|
|||||||
return clusterEndpoint;
|
return clusterEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IEndpoint {
|
export interface IEndpoint {
|
||||||
serviceName: string;
|
serviceName: string;
|
||||||
ipAddress: string;
|
ipAddress: string;
|
||||||
port: number;
|
port: number;
|
||||||
|
|||||||
@@ -88,6 +88,12 @@ export enum Platform {
|
|||||||
Others
|
Others
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IEndpoint {
|
||||||
|
serviceName: string;
|
||||||
|
ipAddress: string;
|
||||||
|
port: number;
|
||||||
|
}
|
||||||
|
|
||||||
export function getOSPlatform(): Platform {
|
export function getOSPlatform(): Platform {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case 'win32':
|
case 'win32':
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ export class JupyterSession implements nb.ISession {
|
|||||||
|
|
||||||
//Update server info with bigdata endpoint - Unified Connection
|
//Update server info with bigdata endpoint - Unified Connection
|
||||||
if (connection.providerName === SQL_PROVIDER) {
|
if (connection.providerName === SQL_PROVIDER) {
|
||||||
let clusterEndpoint: IEndpoint = await this.getClusterEndpoint(connection.id, KNOX_ENDPOINT);
|
let clusterEndpoint: utils.IEndpoint = await this.getClusterEndpoint(connection.id, KNOX_ENDPOINT);
|
||||||
if (!clusterEndpoint) {
|
if (!clusterEndpoint) {
|
||||||
let kernelDisplayName: string = await this.getKernelDisplayName();
|
let kernelDisplayName: string = await this.getKernelDisplayName();
|
||||||
return Promise.reject(new Error(localize('connectionNotValid', 'Spark kernels require a connection to a SQL Server big data cluster master instance.')));
|
return Promise.reject(new Error(localize('connectionNotValid', 'Spark kernels require a connection to a SQL Server big data cluster master instance.')));
|
||||||
@@ -303,12 +303,12 @@ export class JupyterSession implements nb.ISession {
|
|||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getClusterEndpoint(profileId: string, serviceName: string): Promise<IEndpoint> {
|
private async getClusterEndpoint(profileId: string, serviceName: string): Promise<utils.IEndpoint> {
|
||||||
let serverInfo: ServerInfo = await connection.getServerInfo(profileId);
|
let serverInfo: ServerInfo = await connection.getServerInfo(profileId);
|
||||||
if (!serverInfo || !serverInfo.options) {
|
if (!serverInfo || !serverInfo.options) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
let endpoints: IEndpoint[] = serverInfo.options['clusterEndpoints'];
|
let endpoints: utils.IEndpoint[] = serverInfo.options['clusterEndpoints'];
|
||||||
if (!endpoints || endpoints.length === 0) {
|
if (!endpoints || endpoints.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -320,12 +320,6 @@ interface ICredentials {
|
|||||||
'url': string;
|
'url': string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IEndpoint {
|
|
||||||
serviceName: string;
|
|
||||||
ipAddress: string;
|
|
||||||
port: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ISparkMagicConfig {
|
interface ISparkMagicConfig {
|
||||||
kernel_python_credentials: ICredentials;
|
kernel_python_credentials: ICredentials;
|
||||||
kernel_scala_credentials: ICredentials;
|
kernel_scala_credentials: ICredentials;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { INotificationService, Severity } from 'vs/platform/notification/common/
|
|||||||
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
|
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
|
||||||
import { getErrorMessage } from 'sql/parts/notebook/notebookUtils';
|
import { getErrorMessage } from 'sql/parts/notebook/notebookUtils';
|
||||||
import { ICellModel, CellExecutionState } from 'sql/parts/notebook/models/modelInterfaces';
|
import { ICellModel, CellExecutionState } from 'sql/parts/notebook/models/modelInterfaces';
|
||||||
|
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||||
import { MultiStateAction, IMultiStateData, IActionStateData } from 'sql/parts/notebook/notebookActions';
|
import { MultiStateAction, IMultiStateData, IActionStateData } from 'sql/parts/notebook/notebookActions';
|
||||||
|
|
||||||
let notebookMoreActionMsg = localize('notebook.failed', "Please select active cell and try again");
|
let notebookMoreActionMsg = localize('notebook.failed', "Please select active cell and try again");
|
||||||
@@ -68,7 +69,8 @@ export class RunCellAction extends MultiStateAction<CellExecutionState> {
|
|||||||
public static LABEL = 'Run cell';
|
public static LABEL = 'Run cell';
|
||||||
private _executionChangedDisposable: IDisposable;
|
private _executionChangedDisposable: IDisposable;
|
||||||
private _context: CellContext;
|
private _context: CellContext;
|
||||||
constructor(context: CellContext, @INotificationService private notificationService: INotificationService) {
|
constructor(context: CellContext, @INotificationService private notificationService: INotificationService,
|
||||||
|
@IConnectionManagementService private connectionManagementService: IConnectionManagementService) {
|
||||||
super(RunCellAction.ID, new IMultiStateData<CellExecutionState>([
|
super(RunCellAction.ID, new IMultiStateData<CellExecutionState>([
|
||||||
{ key: CellExecutionState.Hidden, value: { label: emptyExecutionCountLabel, className: '', tooltip: '', hideIcon: true }},
|
{ key: CellExecutionState.Hidden, value: { label: emptyExecutionCountLabel, className: '', tooltip: '', hideIcon: true }},
|
||||||
{ key: CellExecutionState.Stopped, value: { label: '', className: 'toolbarIconRun', tooltip: localize('runCell', 'Run cell') }},
|
{ key: CellExecutionState.Stopped, value: { label: '', className: 'toolbarIconRun', tooltip: localize('runCell', 'Run cell') }},
|
||||||
@@ -89,7 +91,7 @@ export class RunCellAction extends MultiStateAction<CellExecutionState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await this._context.cell.runCell(this.notificationService);
|
await this._context.cell.runCell(this.notificationService, this.connectionManagementService);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
let message = getErrorMessage(error);
|
let message = getErrorMessage(error);
|
||||||
this.notificationService.error(message);
|
this.notificationService.error(message);
|
||||||
|
|||||||
@@ -6,18 +6,21 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { nb } from 'azdata';
|
import { nb, ServerInfo } from 'azdata';
|
||||||
|
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
|
|
||||||
import { ICellModelOptions, IModelFactory, FutureInternal, CellExecutionState } from './modelInterfaces';
|
|
||||||
import * as notebookUtils from '../notebookUtils';
|
import * as notebookUtils from '../notebookUtils';
|
||||||
import { CellTypes, CellType, NotebookChangeType } from 'sql/parts/notebook/models/contracts';
|
import { CellTypes, CellType, NotebookChangeType } from 'sql/parts/notebook/models/contracts';
|
||||||
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
|
|
||||||
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
|
import { NotebookModel } from 'sql/parts/notebook/models/notebookModel';
|
||||||
|
import { ICellModel } from 'sql/parts/notebook/models/modelInterfaces';
|
||||||
|
import { ICellModelOptions, IModelFactory, FutureInternal, CellExecutionState } from './modelInterfaces';
|
||||||
|
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||||
|
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
||||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||||
|
import { MssqlProviderId } from 'sql/common/constants';
|
||||||
import { Schemas } from 'vs/base/common/network';
|
import { Schemas } from 'vs/base/common/network';
|
||||||
let modelId = 0;
|
let modelId = 0;
|
||||||
|
|
||||||
@@ -38,6 +41,7 @@ export class CellModel implements ICellModel {
|
|||||||
private _executionCount: number | undefined;
|
private _executionCount: number | undefined;
|
||||||
private _cellUri: URI;
|
private _cellUri: URI;
|
||||||
public id: string;
|
public id: string;
|
||||||
|
private _connectionManagementService: IConnectionManagementService;
|
||||||
|
|
||||||
constructor(private factory: IModelFactory, cellData?: nb.ICellContents, private _options?: ICellModelOptions) {
|
constructor(private factory: IModelFactory, cellData?: nb.ICellContents, private _options?: ICellModelOptions) {
|
||||||
this.id = `${modelId++}`;
|
this.id = `${modelId++}`;
|
||||||
@@ -181,8 +185,11 @@ export class CellModel implements ICellModel {
|
|||||||
return CellExecutionState.Hidden;
|
return CellExecutionState.Hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async runCell(notificationService?: INotificationService): Promise<boolean> {
|
public async runCell(notificationService?: INotificationService, connectionManagementService?: IConnectionManagementService): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
|
if (connectionManagementService) {
|
||||||
|
this._connectionManagementService = connectionManagementService;
|
||||||
|
}
|
||||||
if (this.cellType !== CellTypes.Code) {
|
if (this.cellType !== CellTypes.Code) {
|
||||||
// TODO should change hidden state to false if we add support
|
// TODO should change hidden state to false if we add support
|
||||||
// for this property
|
// for this property
|
||||||
@@ -371,7 +378,8 @@ export class CellModel implements ICellModel {
|
|||||||
if (result && result.data && result.data['text/html']) {
|
if (result && result.data && result.data['text/html']) {
|
||||||
let model = (this as CellModel).options.notebook as NotebookModel;
|
let model = (this as CellModel).options.notebook as NotebookModel;
|
||||||
if (model.activeConnection) {
|
if (model.activeConnection) {
|
||||||
let host = model.activeConnection.serverName;
|
let endpoint = this.getKnoxEndpoint(model.activeConnection);
|
||||||
|
let host = endpoint && endpoint.ipAddress ? endpoint.ipAddress : model.activeConnection.serverName;
|
||||||
let html = result.data['text/html'];
|
let html = result.data['text/html'];
|
||||||
html = html.replace(/(https?:\/\/mssql-master.*\/proxy)(.*)/g, function (a, b, c) {
|
html = html.replace(/(https?:\/\/mssql-master.*\/proxy)(.*)/g, function (a, b, c) {
|
||||||
let ret = '';
|
let ret = '';
|
||||||
@@ -458,4 +466,20 @@ export class CellModel implements ICellModel {
|
|||||||
// Use this to set the internal (immutable) and public (shared with extension) uri properties
|
// Use this to set the internal (immutable) and public (shared with extension) uri properties
|
||||||
this.cellUri = uri;
|
this.cellUri = uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Knox endpoint from IConnectionProfile
|
||||||
|
// TODO: this will be refactored out into the notebooks extension as a contribution point
|
||||||
|
private getKnoxEndpoint(activeConnection: IConnectionProfile): notebookUtils.IEndpoint {
|
||||||
|
let endpoint;
|
||||||
|
if (this._connectionManagementService && activeConnection && activeConnection.providerName === MssqlProviderId) {
|
||||||
|
let serverInfo: ServerInfo = this._connectionManagementService.getServerInfo(activeConnection.id);
|
||||||
|
if (serverInfo && serverInfo.options && serverInfo.options['clusterEndpoints']) {
|
||||||
|
let endpoints: notebookUtils.IEndpoint[] = serverInfo.options['clusterEndpoints'];
|
||||||
|
if (endpoints && endpoints.length > 0) {
|
||||||
|
endpoint = endpoints.find(ep => ep.serviceName.toLowerCase() === 'knox');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return endpoint;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ export interface ICellModel {
|
|||||||
readonly onExecutionStateChange: Event<CellExecutionState>;
|
readonly onExecutionStateChange: Event<CellExecutionState>;
|
||||||
setFuture(future: FutureInternal): void;
|
setFuture(future: FutureInternal): void;
|
||||||
readonly executionState: CellExecutionState;
|
readonly executionState: CellExecutionState;
|
||||||
runCell(notificationService?: INotificationService): Promise<boolean>;
|
runCell(notificationService?: INotificationService, connectionManagementService?: IConnectionManagementService): Promise<boolean>;
|
||||||
setOverrideLanguage(language: string);
|
setOverrideLanguage(language: string);
|
||||||
equals(cellModel: ICellModel): boolean;
|
equals(cellModel: ICellModel): boolean;
|
||||||
toJSON(): nb.ICellContents;
|
toJSON(): nb.ICellContents;
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
await this.modelReady;
|
await this.modelReady;
|
||||||
let uriString = cell.cellUri.toString();
|
let uriString = cell.cellUri.toString();
|
||||||
if (this._model.cells.findIndex(c => c.cellUri.toString() === uriString) > -1) {
|
if (this._model.cells.findIndex(c => c.cellUri.toString() === uriString) > -1) {
|
||||||
return cell.runCell(this.notificationService);
|
return cell.runCell(this.notificationService, this.connectionManagementService);
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(new Error(localize('cellNotFound', 'cell with URI {0} was not found in this model', uriString)));
|
return Promise.reject(new Error(localize('cellNotFound', 'cell with URI {0} was not found in this model', uriString)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,12 @@ export interface IStandardKernelWithProvider {
|
|||||||
readonly notebookProvider: string;
|
readonly notebookProvider: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IEndpoint {
|
||||||
|
serviceName: string;
|
||||||
|
ipAddress: string;
|
||||||
|
port: number;
|
||||||
|
}
|
||||||
|
|
||||||
export function tryMatchCellMagic(input: string): string {
|
export function tryMatchCellMagic(input: string): string {
|
||||||
if (!input) {
|
if (!input) {
|
||||||
return input;
|
return input;
|
||||||
|
|||||||
Reference in New Issue
Block a user