mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-04-03 02:20:30 -04:00
Renable Strict TSLint (#5018)
* removes more builder references * remove builder from profiler * formatting * fix profiler dailog * remove builder from oatuhdialog * remove the rest of builder references * formatting * add more strict null checks to base * enable strict tslint rules * fix formatting * fix compile error * fix the rest of the hygeny issues and add pipeline step * fix pipeline files
This commit is contained in:
@@ -24,12 +24,27 @@ steps:
|
|||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
yarn
|
yarn
|
||||||
displayName: 'Install'
|
displayName: 'Install'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
node_modules/.bin/gulp electron
|
yarn gulp electron-x64
|
||||||
node_modules/.bin/gulp compile --max_old_space_size=4096
|
displayName: Download Electron
|
||||||
displayName: 'Scripts'
|
|
||||||
|
- script: |
|
||||||
|
yarn gulp hygiene
|
||||||
|
displayName: Run Hygiene Checks
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
yarn tslint
|
||||||
|
displayName: 'Run TSLint'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
yarn strict-null-check
|
||||||
|
displayName: 'Run Strict Null Check'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
yarn compile
|
||||||
|
displayName: 'Compile'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter
|
DISPLAY=:10 ./scripts/test.sh --reporter mocha-junit-reporter
|
||||||
@@ -39,11 +54,3 @@ steps:
|
|||||||
inputs:
|
inputs:
|
||||||
testResultsFiles: '**/test-results.xml'
|
testResultsFiles: '**/test-results.xml'
|
||||||
condition: succeededOrFailed()
|
condition: succeededOrFailed()
|
||||||
|
|
||||||
- script: |
|
|
||||||
yarn tslint
|
|
||||||
displayName: 'Run TSLint'
|
|
||||||
|
|
||||||
- script: |
|
|
||||||
yarn strict-null-check
|
|
||||||
displayName: 'Run Strict Null Check'
|
|
||||||
|
|||||||
@@ -9,11 +9,23 @@ steps:
|
|||||||
displayName: 'Yarn Install'
|
displayName: 'Yarn Install'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
.\node_modules\.bin\gulp electron
|
yarn gulp electron-x64
|
||||||
displayName: 'Electron'
|
displayName: 'Electron'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
npm run compile
|
yarn gulp hygiene
|
||||||
|
displayName: Run Hygiene Checks
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
yarn tslint
|
||||||
|
displayName: 'Run TSLint'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
yarn strict-null-check
|
||||||
|
displayName: 'Run Strict Null Check'
|
||||||
|
|
||||||
|
- script: |
|
||||||
|
yarn compile
|
||||||
displayName: 'Compile'
|
displayName: 'Compile'
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
@@ -24,11 +36,3 @@ steps:
|
|||||||
inputs:
|
inputs:
|
||||||
testResultsFiles: 'test-results.xml'
|
testResultsFiles: 'test-results.xml'
|
||||||
condition: succeededOrFailed()
|
condition: succeededOrFailed()
|
||||||
|
|
||||||
- script: |
|
|
||||||
yarn tslint
|
|
||||||
displayName: 'Run TSLint'
|
|
||||||
|
|
||||||
- script: |
|
|
||||||
yarn strict-null-check
|
|
||||||
displayName: 'Run Strict Null Check'
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|||||||
@@ -90,7 +90,13 @@ const indentationFilter = [
|
|||||||
'!**/Dockerfile.*',
|
'!**/Dockerfile.*',
|
||||||
'!**/*.Dockerfile',
|
'!**/*.Dockerfile',
|
||||||
'!**/*.dockerfile',
|
'!**/*.dockerfile',
|
||||||
'!extensions/markdown-language-features/media/*.js'
|
'!extensions/markdown-language-features/media/*.js',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
'!**/*.xlf',
|
||||||
|
'!**/*.docx',
|
||||||
|
'!**/*.sql',
|
||||||
|
'!extensions/mssql/sqltoolsservice/**',
|
||||||
|
'!extensions/import/flatfileimportservice/**',
|
||||||
];
|
];
|
||||||
|
|
||||||
const copyrightFilter = [
|
const copyrightFilter = [
|
||||||
@@ -119,7 +125,36 @@ const copyrightFilter = [
|
|||||||
'!resources/completions/**',
|
'!resources/completions/**',
|
||||||
'!extensions/markdown-language-features/media/highlight.css',
|
'!extensions/markdown-language-features/media/highlight.css',
|
||||||
'!extensions/html-language-features/server/src/modes/typescript/*',
|
'!extensions/html-language-features/server/src/modes/typescript/*',
|
||||||
'!extensions/*/server/bin/*'
|
'!extensions/*/server/bin/*',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
'!extensions/notebook/src/intellisense/text.ts',
|
||||||
|
'!extensions/mssql/src/objectExplorerNodeProvider/webhdfs.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/tableRenderers.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/common/url.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/common/renderMimeInterfaces.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/common/outputProcessor.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/common/mimemodel.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/cellViews/media/output.css',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/rowSelectionModel.plugin.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/rowDetailView.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/headerFilter.plugin.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/checkboxSelectColumn.plugin.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/cellSelectionModel.plugin.ts',
|
||||||
|
'!src/sql/base/browser/ui/table/plugins/autoSizeColumns.plugin.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/sanitizer.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/renderers.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/registry.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/outputs/factories.ts',
|
||||||
|
'!src/sql/workbench/parts/notebook/models/nbformat.ts',
|
||||||
|
'!extensions/markdown-language-features/media/tomorrow.css',
|
||||||
|
'!src/sql/parts/modelComponents/highlight.css',
|
||||||
|
'!extensions/mssql/sqltoolsservice/**',
|
||||||
|
'!extensions/import/flatfileimportservice/**',
|
||||||
|
'!extensions/notebook/src/prompts/**',
|
||||||
|
'!extensions/mssql/src/prompts/**',
|
||||||
|
'!extensions/notebook/resources/jupyter_config/**',
|
||||||
|
'!**/*.gif',
|
||||||
|
'!**/*.xlf'
|
||||||
];
|
];
|
||||||
|
|
||||||
const eslintFilter = [
|
const eslintFilter = [
|
||||||
@@ -165,8 +200,7 @@ gulp.task('eslint', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('tslint', () => {
|
gulp.task('tslint', () => {
|
||||||
// {{SQL CARBON EDIT}}
|
const options = { emitError: true };
|
||||||
const options = { emitError: false };
|
|
||||||
|
|
||||||
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
|
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
|
||||||
.pipe(filter(tslintFilter))
|
.pipe(filter(tslintFilter))
|
||||||
@@ -264,9 +298,8 @@ function hygiene(some) {
|
|||||||
.pipe(filter(f => !f.stat.isDirectory()))
|
.pipe(filter(f => !f.stat.isDirectory()))
|
||||||
.pipe(filter(indentationFilter))
|
.pipe(filter(indentationFilter))
|
||||||
.pipe(indentation)
|
.pipe(indentation)
|
||||||
.pipe(filter(copyrightFilter));
|
.pipe(filter(copyrightFilter))
|
||||||
// {{SQL CARBON EDIT}}
|
.pipe(copyrights);
|
||||||
// .pipe(copyrights);
|
|
||||||
|
|
||||||
const typescript = result
|
const typescript = result
|
||||||
.pipe(filter(tslintFilter))
|
.pipe(filter(tslintFilter))
|
||||||
@@ -276,15 +309,38 @@ function hygiene(some) {
|
|||||||
const javascript = result
|
const javascript = result
|
||||||
.pipe(filter(eslintFilter))
|
.pipe(filter(eslintFilter))
|
||||||
.pipe(gulpeslint('src/.eslintrc'))
|
.pipe(gulpeslint('src/.eslintrc'))
|
||||||
.pipe(gulpeslint.formatEach('compact'));
|
.pipe(gulpeslint.formatEach('compact'))
|
||||||
// {{SQL CARBON EDIT}}
|
.pipe(gulpeslint.failAfterError());
|
||||||
// .pipe(gulpeslint.failAfterError());
|
|
||||||
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
return es.merge(typescript, javascript)
|
return es.merge(typescript, javascript)
|
||||||
.pipe(es.through(function (data) {
|
.pipe(es.through(function (data) {
|
||||||
// {{SQL CARBON EDIT}}
|
count++;
|
||||||
this.emit('end');
|
if (process.env['TRAVIS'] && count % 10 === 0) {
|
||||||
|
process.stdout.write('.');
|
||||||
|
}
|
||||||
|
this.emit('data', data);
|
||||||
|
}, function () {
|
||||||
|
process.stdout.write('\n');
|
||||||
|
|
||||||
|
const tslintResult = tsLinter.getResult();
|
||||||
|
if (tslintResult.failures.length > 0) {
|
||||||
|
for (const failure of tslintResult.failures) {
|
||||||
|
const name = failure.getFileName();
|
||||||
|
const position = failure.getStartPosition();
|
||||||
|
const line = position.getLineAndCharacter().line;
|
||||||
|
const character = position.getLineAndCharacter().character;
|
||||||
|
|
||||||
|
console.error(`${name}:${line + 1}:${character + 1}:${failure.getFailure()}`);
|
||||||
|
}
|
||||||
|
errorCount += tslintResult.failures.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorCount > 0) {
|
||||||
|
this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.');
|
||||||
|
} else {
|
||||||
|
this.emit('end');
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,21 +6,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
const json = require('gulp-json-editor');
|
|
||||||
const buffer = require('gulp-buffer');
|
|
||||||
const filter = require('gulp-filter');
|
|
||||||
const es = require('event-stream');
|
|
||||||
const vfs = require('vinyl-fs');
|
|
||||||
const pkg = require('../package.json');
|
|
||||||
const cp = require('child_process');
|
|
||||||
const fancyLog = require('fancy-log');
|
|
||||||
const ansiColors = require('ansi-colors');
|
|
||||||
|
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
const jeditor = require('gulp-json-editor');
|
const jeditor = require('gulp-json-editor');
|
||||||
|
|
||||||
gulp.task('mixin', function () {
|
gulp.task('mixin', function () {
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
const updateUrl = process.env['SQLOPS_UPDATEURL'];
|
const updateUrl = process.env['SQLOPS_UPDATEURL'];
|
||||||
if (!updateUrl) {
|
if (!updateUrl) {
|
||||||
console.log('Missing SQLOPS_UPDATEURL, skipping mixin');
|
console.log('Missing SQLOPS_UPDATEURL, skipping mixin');
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ const formatFiles = (some) => {
|
|||||||
console.info('ran formatting on file ' + file.path + ' result: ' + result.message);
|
console.info('ran formatting on file ' + file.path + ' result: ' + result.message);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
console.error(result.message);
|
console.error(result.message);
|
||||||
errorCount++;
|
|
||||||
}
|
}
|
||||||
cb(null, file);
|
cb(null, file);
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ const formatFiles = (some) => {
|
|||||||
.pipe(filter(f => !f.stat.isDirectory()))
|
.pipe(filter(f => !f.stat.isDirectory()))
|
||||||
.pipe(formatting);
|
.pipe(formatting);
|
||||||
|
|
||||||
}
|
};
|
||||||
|
|
||||||
const formatStagedFiles = () => {
|
const formatStagedFiles = () => {
|
||||||
const cp = require('child_process');
|
const cp = require('child_process');
|
||||||
@@ -81,4 +80,4 @@ const formatStagedFiles = () => {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
@@ -27,7 +27,7 @@ function getDebPackageArch(arch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function prepareDebPackage(arch) {
|
function prepareDebPackage(arch) {
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
const binaryDir = '../azuredatastudio-linux-' + arch;
|
const binaryDir = '../azuredatastudio-linux-' + arch;
|
||||||
const debArch = getDebPackageArch(arch);
|
const debArch = getDebPackageArch(arch);
|
||||||
const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch;
|
const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const zipPath = arch => path.join(zipDir(arch), `VSCode-win32-${arch}.zip`);
|
|||||||
const setupDir = (arch, target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`);
|
const setupDir = (arch, target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`);
|
||||||
const issPath = path.join(__dirname, 'win32', 'code.iss');
|
const issPath = path.join(__dirname, 'win32', 'code.iss');
|
||||||
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe');
|
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup-compiler'))), 'bin', 'ISCC.exe');
|
||||||
const signPS1 = path.join(repoPath, 'build', 'azure-pipelines', 'win32', 'sign.ps1');
|
// const signPS1 = path.join(repoPath, 'build', 'azure-pipelines', 'win32', 'sign.ps1');
|
||||||
|
|
||||||
function packageInnoSetup(iss, options, cb) {
|
function packageInnoSetup(iss, options, cb) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"adminToolExtWin.launchSsmsServerPropertiesDialog": "Properties"
|
"adminToolExtWin.launchSsmsServerPropertiesDialog": "Properties"
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://sqlopsextensions.blob.core.windows.net/tools/ssmsmin/{#version#}/{#fileName#}",
|
"downloadUrl": "https://sqlopsextensions.blob.core.windows.net/tools/ssmsmin/{#version#}/{#fileName#}",
|
||||||
"version": "15.0.18092.0",
|
"version": "15.0.18092.0",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_64": "SsmsMin-15.0.18092.0-win-x64.zip",
|
"Windows_64": "SsmsMin-15.0.18092.0-win-x64.zip",
|
||||||
"Windows_86": "SsmsMin-15.0.18092.0-win-x86.zip"
|
"Windows_86": "SsmsMin-15.0.18092.0-win-x86.zip"
|
||||||
},
|
},
|
||||||
"installDirectory": "ssmsmin/{#platform#}/{#version#}",
|
"installDirectory": "ssmsmin/{#platform#}/{#version#}",
|
||||||
"executableFiles": [
|
"executableFiles": [
|
||||||
"SsmsMin.exe"
|
"SsmsMin.exe"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
///
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
@@ -12,8 +10,7 @@ import * as vscode from 'vscode';
|
|||||||
import { IConfig, ServerProvider } from 'service-downloader';
|
import { IConfig, ServerProvider } from 'service-downloader';
|
||||||
import { Telemetry } from './telemetry';
|
import { Telemetry } from './telemetry';
|
||||||
import * as utils from './utils';
|
import * as utils from './utils';
|
||||||
import { ChildProcess, exec, ExecException } from 'child_process';
|
import { ChildProcess, exec } from 'child_process';
|
||||||
import { stringify } from 'querystring';
|
|
||||||
|
|
||||||
const baseConfig = require('./config.json');
|
const baseConfig = require('./config.json');
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
@@ -116,9 +113,9 @@ function launchSsmsDialog(action: string, connectionProfile: azdata.IConnectionP
|
|||||||
let args = buildSsmsMinCommandArgs(params);
|
let args = buildSsmsMinCommandArgs(params);
|
||||||
|
|
||||||
// This will be an async call since we pass in the callback
|
// This will be an async call since we pass in the callback
|
||||||
var proc: ChildProcess = exec(
|
let proc: ChildProcess = exec(
|
||||||
/*command*/`"${exePath}" ${args}`,
|
/*command*/`"${exePath}" ${args}`,
|
||||||
/*options*/undefined,
|
/*options*/undefined,
|
||||||
(execException, stdout, stderr) => {
|
(execException, stdout, stderr) => {
|
||||||
// Process has exited so remove from map of running processes
|
// Process has exited so remove from map of running processes
|
||||||
runningProcesses.delete(proc.pid);
|
runningProcesses.delete(proc.pid);
|
||||||
|
|||||||
@@ -13,123 +13,123 @@ import * as Utils from './utils';
|
|||||||
const packageJson = require('../package.json');
|
const packageJson = require('../package.json');
|
||||||
|
|
||||||
export interface ITelemetryEventProperties {
|
export interface ITelemetryEventProperties {
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITelemetryEventMeasures {
|
export interface ITelemetryEventMeasures {
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters error paths to only include source files. Exported to support testing
|
* Filters error paths to only include source files. Exported to support testing
|
||||||
*/
|
*/
|
||||||
export function filterErrorPath(line: string): string {
|
export function filterErrorPath(line: string): string {
|
||||||
if (line) {
|
if (line) {
|
||||||
let values: string[] = line.split('/out/');
|
let values: string[] = line.split('/out/');
|
||||||
if (values.length <= 1) {
|
if (values.length <= 1) {
|
||||||
// Didn't match expected format
|
// Didn't match expected format
|
||||||
return line;
|
return line;
|
||||||
} else {
|
} else {
|
||||||
return values[1];
|
return values[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Telemetry {
|
export class Telemetry {
|
||||||
private static reporter: TelemetryReporter;
|
private static reporter: TelemetryReporter;
|
||||||
private static userId: string;
|
private static userId: string;
|
||||||
private static platformInformation: PlatformInformation;
|
private static platformInformation: PlatformInformation;
|
||||||
private static disabled: boolean;
|
private static disabled: boolean;
|
||||||
|
|
||||||
public static getPlatformInformation(): Promise<PlatformInformation> {
|
public static getPlatformInformation(): Promise<PlatformInformation> {
|
||||||
if (this.platformInformation) {
|
if (this.platformInformation) {
|
||||||
return Promise.resolve(this.platformInformation);
|
return Promise.resolve(this.platformInformation);
|
||||||
} else {
|
} else {
|
||||||
return new Promise<PlatformInformation>(resolve => {
|
return new Promise<PlatformInformation>(resolve => {
|
||||||
PlatformInformation.getCurrent().then(info => {
|
PlatformInformation.getCurrent().then(info => {
|
||||||
this.platformInformation = info;
|
this.platformInformation = info;
|
||||||
resolve(this.platformInformation);
|
resolve(this.platformInformation);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable telemetry reporting
|
* Disable telemetry reporting
|
||||||
*/
|
*/
|
||||||
public static disable(): void {
|
public static disable(): void {
|
||||||
this.disabled = true;
|
this.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the telemetry reporter for use.
|
* Initialize the telemetry reporter for use.
|
||||||
*/
|
*/
|
||||||
public static initialize(): void {
|
public static initialize(): void {
|
||||||
if (typeof this.reporter === 'undefined') {
|
if (typeof this.reporter === 'undefined') {
|
||||||
// Check if the user has opted out of telemetry
|
// Check if the user has opted out of telemetry
|
||||||
if (!vscode.workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true)) {
|
if (!vscode.workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true)) {
|
||||||
this.disable();
|
this.disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let packageInfo = Utils.getPackageInfo(packageJson);
|
let packageInfo = Utils.getPackageInfo(packageJson);
|
||||||
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a telemetry event for an exception
|
* Send a telemetry event for an exception
|
||||||
*/
|
*/
|
||||||
public static sendTelemetryEventForException(
|
public static sendTelemetryEventForException(
|
||||||
err: any, methodName: string, extensionConfigName: string): void {
|
err: any, methodName: string, extensionConfigName: string): void {
|
||||||
try {
|
try {
|
||||||
let stackArray: string[];
|
let stackArray: string[];
|
||||||
let firstLine: string = '';
|
let firstLine: string = '';
|
||||||
if (err !== undefined && err.stack !== undefined) {
|
if (err !== undefined && err.stack !== undefined) {
|
||||||
stackArray = err.stack.split('\n');
|
stackArray = err.stack.split('\n');
|
||||||
if (stackArray !== undefined && stackArray.length >= 2) {
|
if (stackArray !== undefined && stackArray.length >= 2) {
|
||||||
firstLine = stackArray[1]; // The first line is the error message and we don't want to send that telemetry event
|
firstLine = stackArray[1]; // The first line is the error message and we don't want to send that telemetry event
|
||||||
firstLine = filterErrorPath(firstLine);
|
firstLine = filterErrorPath(firstLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only adding the method name and the fist line of the stack trace. We don't add the error message because it might have PII
|
// Only adding the method name and the fist line of the stack trace. We don't add the error message because it might have PII
|
||||||
this.sendTelemetryEvent('Exception', { methodName: methodName, errorLine: firstLine });
|
this.sendTelemetryEvent('Exception', { methodName: methodName, errorLine: firstLine });
|
||||||
} catch (telemetryErr) {
|
} catch (telemetryErr) {
|
||||||
// If sending telemetry event fails ignore it so it won't break the extension
|
// If sending telemetry event fails ignore it so it won't break the extension
|
||||||
console.error('Failed to send telemetry event. error: ' + telemetryErr, extensionConfigName);
|
console.error('Failed to send telemetry event. error: ' + telemetryErr, extensionConfigName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a telemetry event using application insights
|
* Send a telemetry event using application insights
|
||||||
*/
|
*/
|
||||||
public static sendTelemetryEvent(
|
public static sendTelemetryEvent(
|
||||||
eventName: string,
|
eventName: string,
|
||||||
properties?: ITelemetryEventProperties,
|
properties?: ITelemetryEventProperties,
|
||||||
measures?: ITelemetryEventMeasures): void {
|
measures?: ITelemetryEventMeasures): void {
|
||||||
|
|
||||||
if (typeof this.disabled === 'undefined') {
|
if (typeof this.disabled === 'undefined') {
|
||||||
this.disabled = false;
|
this.disabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.disabled || typeof (this.reporter) === 'undefined') {
|
if (this.disabled || typeof (this.reporter) === 'undefined') {
|
||||||
// Don't do anything if telemetry is disabled
|
// Don't do anything if telemetry is disabled
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!properties || typeof properties === 'undefined') {
|
if (!properties || typeof properties === 'undefined') {
|
||||||
properties = {};
|
properties = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Augment the properties structure with additional common properties before sending
|
// Augment the properties structure with additional common properties before sending
|
||||||
Promise.all([this.getPlatformInformation()]).then(() => {
|
Promise.all([this.getPlatformInformation()]).then(() => {
|
||||||
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
|
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
|
||||||
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
|
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
|
||||||
|
|
||||||
this.reporter.sendTelemetryEvent(eventName, properties, measures);
|
this.reporter.sendTelemetryEvent(eventName, properties, measures);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Telemetry.initialize();
|
Telemetry.initialize();
|
||||||
|
|||||||
@@ -9,20 +9,20 @@ const testRunner = require('vscode/lib/testrunner');
|
|||||||
const suite = 'Database Admin Tool Extensions for Windows';
|
const suite = 'Database Admin Tool Extensions for Windows';
|
||||||
|
|
||||||
const options: any = {
|
const options: any = {
|
||||||
ui: 'bdd',
|
ui: 'bdd',
|
||||||
useColors: true,
|
useColors: true,
|
||||||
timeout: 600000
|
timeout: 600000
|
||||||
};
|
};
|
||||||
|
|
||||||
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
||||||
options.reporter = 'mocha-multi-reporters';
|
options.reporter = 'mocha-multi-reporters';
|
||||||
options.reporterOptions = {
|
options.reporterOptions = {
|
||||||
reporterEnabled: 'spec, mocha-junit-reporter',
|
reporterEnabled: 'spec, mocha-junit-reporter',
|
||||||
mochaJunitReporterReporterOptions: {
|
mochaJunitReporterReporterOptions: {
|
||||||
testsuitesTitle: `${suite} ${process.platform}`,
|
testsuitesTitle: `${suite} ${process.platform}`,
|
||||||
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
|
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
testRunner.configure(options);
|
testRunner.configure(options);
|
||||||
|
|||||||
@@ -11,57 +11,57 @@ import 'mocha';
|
|||||||
import * as extensionMain from '../main';
|
import * as extensionMain from '../main';
|
||||||
|
|
||||||
describe('buildSsmsMinCommandArgs Method Tests', () => {
|
describe('buildSsmsMinCommandArgs Method Tests', () => {
|
||||||
it('Should be built correctly with all params and UseAAD as false', function (): void {
|
it('Should be built correctly with all params and UseAAD as false', function (): void {
|
||||||
let params: extensionMain.LaunchSsmsDialogParams = {
|
let params: extensionMain.LaunchSsmsDialogParams = {
|
||||||
action: 'myAction',
|
action: 'myAction',
|
||||||
server: 'myServer',
|
server: 'myServer',
|
||||||
database: 'myDatabase',
|
database: 'myDatabase',
|
||||||
user: 'user',
|
user: 'user',
|
||||||
password: 'password',
|
password: 'password',
|
||||||
useAad: false,
|
useAad: false,
|
||||||
urn: 'Server\\Database\\Table'
|
urn: 'Server\\Database\\Table'
|
||||||
};
|
};
|
||||||
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
||||||
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -U "user" -u "Server\\Database\\Table"');
|
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -U "user" -u "Server\\Database\\Table"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be built correctly with all params and UseAAD as true', function (): void {
|
it('Should be built correctly with all params and UseAAD as true', function (): void {
|
||||||
let params: extensionMain.LaunchSsmsDialogParams = {
|
let params: extensionMain.LaunchSsmsDialogParams = {
|
||||||
action: 'myAction',
|
action: 'myAction',
|
||||||
server: 'myServer',
|
server: 'myServer',
|
||||||
database: 'myDatabase',
|
database: 'myDatabase',
|
||||||
user: 'user',
|
user: 'user',
|
||||||
password: 'password',
|
password: 'password',
|
||||||
useAad: true,
|
useAad: true,
|
||||||
urn: 'Server\\Database\\Table'
|
urn: 'Server\\Database\\Table'
|
||||||
};
|
};
|
||||||
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
||||||
// User is omitted since UseAAD is true
|
// User is omitted since UseAAD is true
|
||||||
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -G -u "Server\\Database\\Table"');
|
should(args).equal('-a "myAction" -S "myServer" -D "myDatabase" -G -u "Server\\Database\\Table"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be built correctly and names escaped correctly', function (): void {
|
it('Should be built correctly and names escaped correctly', function (): void {
|
||||||
let params: extensionMain.LaunchSsmsDialogParams = {
|
let params: extensionMain.LaunchSsmsDialogParams = {
|
||||||
action: 'myAction\'"/\\[]tricky',
|
action: 'myAction\'"/\\[]tricky',
|
||||||
server: 'myServer\'"/\\[]tricky',
|
server: 'myServer\'"/\\[]tricky',
|
||||||
database: 'myDatabase\'"/\\[]tricky',
|
database: 'myDatabase\'"/\\[]tricky',
|
||||||
user: 'user\'"/\\[]tricky',
|
user: 'user\'"/\\[]tricky',
|
||||||
password: 'password',
|
password: 'password',
|
||||||
useAad: true,
|
useAad: true,
|
||||||
urn: 'Server\\Database[\'myDatabase\'\'"/\\[]tricky\']\\Table["myTable\'""/\\[]tricky"]'
|
urn: 'Server\\Database[\'myDatabase\'\'"/\\[]tricky\']\\Table["myTable\'""/\\[]tricky"]'
|
||||||
};
|
};
|
||||||
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
||||||
// User is omitted since UseAAD is true
|
// User is omitted since UseAAD is true
|
||||||
should(args).equal('-a "myAction\'\\"/\\[]tricky" -S "myServer\'\\"/\\[]tricky" -D "myDatabase\'\\"/\\[]tricky" -G -u "Server\\Database[\'myDatabase\'\'\\"/\\[]tricky\']\\Table[\\"myTable\'\\"\\"/\\[]tricky\\"]"');
|
should(args).equal('-a "myAction\'\\"/\\[]tricky" -S "myServer\'\\"/\\[]tricky" -D "myDatabase\'\\"/\\[]tricky" -G -u "Server\\Database[\'myDatabase\'\'\\"/\\[]tricky\']\\Table[\\"myTable\'\\"\\"/\\[]tricky\\"]"');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be built correctly with only action and server', function (): void {
|
it('Should be built correctly with only action and server', function (): void {
|
||||||
|
|
||||||
let params: extensionMain.LaunchSsmsDialogParams = {
|
let params: extensionMain.LaunchSsmsDialogParams = {
|
||||||
action: 'myAction',
|
action: 'myAction',
|
||||||
server: 'myServer'
|
server: 'myServer'
|
||||||
};
|
};
|
||||||
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
let args = extensionMain.buildSsmsMinCommandArgs(params);
|
||||||
should(args).equal('-a "myAction" -S "myServer"');
|
should(args).equal('-a "myAction" -S "myServer"');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,19 +7,19 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
export interface IPackageInfo {
|
export interface IPackageInfo {
|
||||||
name: string;
|
name: string;
|
||||||
version: string;
|
version: string;
|
||||||
aiKey: string;
|
aiKey: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPackageInfo(packageJson: any): IPackageInfo {
|
export function getPackageInfo(packageJson: any): IPackageInfo {
|
||||||
if (packageJson) {
|
if (packageJson) {
|
||||||
return {
|
return {
|
||||||
name: packageJson.name,
|
name: packageJson.name,
|
||||||
version: packageJson.version,
|
version: packageJson.version,
|
||||||
aiKey: packageJson.aiKey
|
aiKey: packageJson.aiKey
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,15 +28,15 @@ export function getPackageInfo(packageJson: any): IPackageInfo {
|
|||||||
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
||||||
*/
|
*/
|
||||||
export function getConfiguration(extensionName?: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
export function getConfiguration(extensionName?: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
||||||
if (typeof resource === 'string') {
|
if (typeof resource === 'string') {
|
||||||
try {
|
try {
|
||||||
resource = this.parseUri(resource);
|
resource = this.parseUri(resource);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
resource = undefined;
|
resource = undefined;
|
||||||
}
|
}
|
||||||
} else if (!resource) {
|
} else if (!resource) {
|
||||||
// Fix to avoid adding lots of errors to debug console. Expects a valid resource or null, not undefined
|
// Fix to avoid adding lots of errors to debug console. Expects a valid resource or null, not undefined
|
||||||
resource = null;
|
resource = null;
|
||||||
}
|
}
|
||||||
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
{
|
{
|
||||||
"compileOnSave": true,
|
"compileOnSave": true,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"outDir": "./out",
|
"outDir": "./out",
|
||||||
"lib": [
|
"lib": [
|
||||||
"es6", "es2015.promise"
|
"es6", "es2015.promise"
|
||||||
],
|
],
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"./node_modules/@types"
|
"./node_modules/@types"
|
||||||
],
|
],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"declaration": true
|
"declaration": true
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as data from 'azdata';
|
import * as data from 'azdata';
|
||||||
|
|
||||||
@@ -12,52 +11,51 @@ import * as data from 'azdata';
|
|||||||
* this API from our code
|
* this API from our code
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @class ApiWrapper
|
|
||||||
*/
|
*/
|
||||||
export class ApiWrapper {
|
export class ApiWrapper {
|
||||||
// Data APIs
|
// Data APIs
|
||||||
|
|
||||||
public registerWebviewProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
|
public registerWebviewProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
|
||||||
return data.dashboard.registerWebviewProvider(widgetId, handler);
|
return data.dashboard.registerWebviewProvider(widgetId, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public registerControlHostProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
|
public registerControlHostProvider(widgetId: string, handler: (webview: data.DashboardWebview) => void): void {
|
||||||
return data.dashboard.registerWebviewProvider(widgetId, handler);
|
return data.dashboard.registerWebviewProvider(widgetId, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the configuration for a extensionName
|
* Get the configuration for a extensionName
|
||||||
* @param extensionName The string name of the extension to get the configuration for
|
* @param extensionName The string name of the extension to get the configuration for
|
||||||
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
* @param resource The optional URI, as a URI object or a string, to use to get resource-scoped configurations
|
||||||
*/
|
*/
|
||||||
public getConfiguration(extensionName: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
public getConfiguration(extensionName: string, resource?: vscode.Uri | string): vscode.WorkspaceConfiguration {
|
||||||
if (typeof resource === 'string') {
|
if (typeof resource === 'string') {
|
||||||
try {
|
try {
|
||||||
resource = this.parseUri(resource);
|
resource = this.parseUri(resource);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
resource = undefined;
|
resource = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
return vscode.workspace.getConfiguration(extensionName, resource as vscode.Uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse uri
|
* Parse uri
|
||||||
*/
|
*/
|
||||||
public parseUri(uri: string): vscode.Uri {
|
public parseUri(uri: string): vscode.Uri {
|
||||||
return vscode.Uri.parse(uri);
|
return vscode.Uri.parse(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
|
public showOpenDialog(options: vscode.OpenDialogOptions): Thenable<vscode.Uri[] | undefined> {
|
||||||
return vscode.window.showOpenDialog(options);
|
return vscode.window.showOpenDialog(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
public showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
||||||
return vscode.window.showErrorMessage(message, ...items);
|
return vscode.window.showErrorMessage(message, ...items);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get workspaceRootPath(): string {
|
public get workspaceRootPath(): string {
|
||||||
return vscode.workspace.rootPath;
|
return vscode.workspace.rootPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class AlertData implements IAgentDialogData {
|
|||||||
public static readonly AlertTypeSqlServerEventString: string = localize('alertData.DefaultAlertTypString', 'SQL Server event alert');
|
public static readonly AlertTypeSqlServerEventString: string = localize('alertData.DefaultAlertTypString', 'SQL Server event alert');
|
||||||
public static readonly AlertTypePerformanceConditionString: string = localize('alertDialog.PerformanceCondition', 'SQL Server performance condition alert');
|
public static readonly AlertTypePerformanceConditionString: string = localize('alertDialog.PerformanceCondition', 'SQL Server performance condition alert');
|
||||||
public static readonly AlertTypeWmiEventString: string = localize('alertDialog.WmiEvent', 'WMI event alert');
|
public static readonly AlertTypeWmiEventString: string = localize('alertDialog.WmiEvent', 'WMI event alert');
|
||||||
public static readonly DefaultAlertTypeString: string = AlertData.AlertTypeSqlServerEventString;
|
public static readonly DefaultAlertTypeString: string = AlertData.AlertTypeSqlServerEventString;
|
||||||
|
|
||||||
ownerUri: string;
|
ownerUri: string;
|
||||||
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
|
dialogMode: AgentDialogMode = AgentDialogMode.CREATE;
|
||||||
@@ -50,7 +50,7 @@ export class AlertData implements IAgentDialogData {
|
|||||||
private jobModel: JobData;
|
private jobModel: JobData;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ownerUri:string,
|
ownerUri: string,
|
||||||
alertInfo: azdata.AgentAlertInfo,
|
alertInfo: azdata.AgentAlertInfo,
|
||||||
jobModel?: JobData,
|
jobModel?: JobData,
|
||||||
viaJobDialog: boolean = false
|
viaJobDialog: boolean = false
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const localize = nls.loadMessageBundle();
|
|||||||
|
|
||||||
export class JobData implements IAgentDialogData {
|
export class JobData implements IAgentDialogData {
|
||||||
|
|
||||||
private readonly JobCompletionActionCondition_Always: string = localize('jobData.whenJobCompletes', 'When the job completes');
|
private readonly JobCompletionActionCondition_Always: string = localize('jobData.whenJobCompletes', 'When the job completes');
|
||||||
private readonly JobCompletionActionCondition_OnFailure: string = localize('jobData.whenJobFails', 'When the job fails');
|
private readonly JobCompletionActionCondition_OnFailure: string = localize('jobData.whenJobFails', 'When the job fails');
|
||||||
private readonly JobCompletionActionCondition_OnSuccess: string = localize('jobData.whenJobSucceeds', 'When the job succeeds');
|
private readonly JobCompletionActionCondition_OnSuccess: string = localize('jobData.whenJobSucceeds', 'When the job succeeds');
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
public async save() {
|
public async save() {
|
||||||
let jobInfo: azdata.AgentJobInfo = this.toAgentJobInfo();
|
let jobInfo: azdata.AgentJobInfo = this.toAgentJobInfo();
|
||||||
let result = this.dialogMode === AgentDialogMode.CREATE
|
let result = this.dialogMode === AgentDialogMode.CREATE
|
||||||
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
||||||
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
if (this.dialogMode === AgentDialogMode.EDIT) {
|
if (this.dialogMode === AgentDialogMode.EDIT) {
|
||||||
@@ -142,7 +142,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
localize('jobData.saveSucessMessage', "Job '{0}' updated successfully", jobInfo.name));
|
localize('jobData.saveSucessMessage', "Job '{0}' updated successfully", jobInfo.name));
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showInformationMessage(
|
vscode.window.showInformationMessage(
|
||||||
localize('jobData.newJobSuccessMessage',"Job '{0}' created successfully", jobInfo.name));
|
localize('jobData.newJobSuccessMessage', "Job '{0}' created successfully", jobInfo.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
private jobModel: JobData;
|
private jobModel: JobData;
|
||||||
private viaJobDialog: boolean;
|
private viaJobDialog: boolean;
|
||||||
|
|
||||||
constructor(ownerUri:string, jobModel?: JobData, viaJobDialog: boolean = false) {
|
constructor(ownerUri: string, jobModel?: JobData, viaJobDialog: boolean = false) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
this.jobName = jobModel.name;
|
this.jobName = jobModel.name;
|
||||||
this.jobModel = jobModel;
|
this.jobModel = jobModel;
|
||||||
@@ -102,26 +102,26 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
stepData.jobName = jobStepInfo.jobName;
|
stepData.jobName = jobStepInfo.jobName;
|
||||||
stepData.script = jobStepInfo.script;
|
stepData.script = jobStepInfo.script;
|
||||||
stepData.scriptName = jobStepInfo.scriptName,
|
stepData.scriptName = jobStepInfo.scriptName,
|
||||||
stepData.stepName = jobStepInfo.stepName,
|
stepData.stepName = jobStepInfo.stepName,
|
||||||
stepData.subSystem = jobStepInfo.subSystem,
|
stepData.subSystem = jobStepInfo.subSystem,
|
||||||
stepData.id = jobStepInfo.id,
|
stepData.id = jobStepInfo.id,
|
||||||
stepData.failureAction = jobStepInfo.failureAction,
|
stepData.failureAction = jobStepInfo.failureAction,
|
||||||
stepData.successAction = jobStepInfo.successAction,
|
stepData.successAction = jobStepInfo.successAction,
|
||||||
stepData.failStepId = jobStepInfo.failStepId,
|
stepData.failStepId = jobStepInfo.failStepId,
|
||||||
stepData.successStepId = jobStepInfo.successStepId,
|
stepData.successStepId = jobStepInfo.successStepId,
|
||||||
stepData.command = jobStepInfo.command,
|
stepData.command = jobStepInfo.command,
|
||||||
stepData.commandExecutionSuccessCode = jobStepInfo.commandExecutionSuccessCode,
|
stepData.commandExecutionSuccessCode = jobStepInfo.commandExecutionSuccessCode,
|
||||||
stepData.databaseName = jobStepInfo.databaseName,
|
stepData.databaseName = jobStepInfo.databaseName,
|
||||||
stepData.databaseUserName = jobStepInfo.databaseUserName,
|
stepData.databaseUserName = jobStepInfo.databaseUserName,
|
||||||
stepData.server = jobStepInfo.server,
|
stepData.server = jobStepInfo.server,
|
||||||
stepData.outputFileName = jobStepInfo.outputFileName,
|
stepData.outputFileName = jobStepInfo.outputFileName,
|
||||||
stepData.appendToLogFile = jobStepInfo.appendToLogFile,
|
stepData.appendToLogFile = jobStepInfo.appendToLogFile,
|
||||||
stepData.appendToStepHist = jobStepInfo.appendToStepHist,
|
stepData.appendToStepHist = jobStepInfo.appendToStepHist,
|
||||||
stepData.writeLogToTable = jobStepInfo.writeLogToTable,
|
stepData.writeLogToTable = jobStepInfo.writeLogToTable,
|
||||||
stepData.appendLogToTable = jobStepInfo.appendLogToTable,
|
stepData.appendLogToTable = jobStepInfo.appendLogToTable,
|
||||||
stepData.retryAttempts = jobStepInfo.retryAttempts,
|
stepData.retryAttempts = jobStepInfo.retryAttempts,
|
||||||
stepData.retryInterval = jobStepInfo.retryInterval,
|
stepData.retryInterval = jobStepInfo.retryInterval,
|
||||||
stepData.proxyName = jobStepInfo.proxyName;
|
stepData.proxyName = jobStepInfo.proxyName;
|
||||||
stepData.dialogMode = AgentDialogMode.EDIT;
|
stepData.dialogMode = AgentDialogMode.EDIT;
|
||||||
stepData.viaJobDialog = true;
|
stepData.viaJobDialog = true;
|
||||||
return stepData;
|
return stepData;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class OperatorData implements IAgentDialogData {
|
|||||||
weekdayPagerStartTime: string;
|
weekdayPagerStartTime: string;
|
||||||
weekdayPagerEndTime: string;
|
weekdayPagerEndTime: string;
|
||||||
|
|
||||||
constructor(ownerUri:string, operatorInfo: azdata.AgentOperatorInfo) {
|
constructor(ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
if (operatorInfo) {
|
if (operatorInfo) {
|
||||||
this.dialogMode = AgentDialogMode.EDIT;
|
this.dialogMode = AgentDialogMode.EDIT;
|
||||||
@@ -58,7 +58,7 @@ export class OperatorData implements IAgentDialogData {
|
|||||||
|
|
||||||
public async save() {
|
public async save() {
|
||||||
let agentService = await AgentUtils.getAgentService();
|
let agentService = await AgentUtils.getAgentService();
|
||||||
let result = await agentService.createOperator(this.ownerUri, this.toAgentOperatorInfo());
|
let result = await agentService.createOperator(this.ownerUri, this.toAgentOperatorInfo());
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
// TODO handle error here
|
// TODO handle error here
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export class PickScheduleData implements IAgentDialogData {
|
|||||||
public selectedSchedule: azdata.AgentJobScheduleInfo;
|
public selectedSchedule: azdata.AgentJobScheduleInfo;
|
||||||
private jobName: string;
|
private jobName: string;
|
||||||
|
|
||||||
constructor(ownerUri:string, jobName: string) {
|
constructor(ownerUri: string, jobName: string) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
this.jobName = jobName;
|
this.jobName = jobName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export class ProxyData implements IAgentDialogData {
|
|||||||
credentialId: number;
|
credentialId: number;
|
||||||
isEnabled: boolean;
|
isEnabled: boolean;
|
||||||
|
|
||||||
constructor(ownerUri:string, proxyInfo: azdata.AgentProxyInfo) {
|
constructor(ownerUri: string, proxyInfo: azdata.AgentProxyInfo) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
|
|
||||||
if (proxyInfo) {
|
if (proxyInfo) {
|
||||||
@@ -48,7 +48,7 @@ export class ProxyData implements IAgentDialogData {
|
|||||||
localize('proxyData.saveSucessMessage', "Proxy '{0}' updated successfully", proxyInfo.accountName));
|
localize('proxyData.saveSucessMessage', "Proxy '{0}' updated successfully", proxyInfo.accountName));
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showInformationMessage(
|
vscode.window.showInformationMessage(
|
||||||
localize('proxyData.newJobSuccessMessage',"Proxy '{0}' created successfully", proxyInfo.accountName));
|
localize('proxyData.newJobSuccessMessage', "Proxy '{0}' created successfully", proxyInfo.accountName));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export class ScheduleData implements IAgentDialogData {
|
|||||||
public schedules: azdata.AgentJobScheduleInfo[];
|
public schedules: azdata.AgentJobScheduleInfo[];
|
||||||
public selectedSchedule: azdata.AgentJobScheduleInfo;
|
public selectedSchedule: azdata.AgentJobScheduleInfo;
|
||||||
|
|
||||||
constructor(ownerUri:string) {
|
constructor(ownerUri: string) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,14 +62,14 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private static readonly AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
|
private static readonly AlertSeverity025Label: string = localize('alertDialog.Severity025', '025 - Fatal Error');
|
||||||
private static readonly AllDatabases: string = localize('alertDialog.AllDatabases', '<all databases>');
|
private static readonly AllDatabases: string = localize('alertDialog.AllDatabases', '<all databases>');
|
||||||
|
|
||||||
private static readonly AlertTypes: string[] = [
|
private static readonly AlertTypes: string[] = [
|
||||||
AlertData.AlertTypeSqlServerEventString,
|
AlertData.AlertTypeSqlServerEventString,
|
||||||
// Disabled until next release
|
// Disabled until next release
|
||||||
// AlertData.AlertTypePerformanceConditionString,
|
// AlertData.AlertTypePerformanceConditionString,
|
||||||
// AlertData.AlertTypeWmiEventString
|
// AlertData.AlertTypeWmiEventString
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly AlertSeverities: string[] = [
|
private static readonly AlertSeverities: string[] = [
|
||||||
AlertDialog.AlertSeverity001Label,
|
AlertDialog.AlertSeverity001Label,
|
||||||
AlertDialog.AlertSeverity002Label,
|
AlertDialog.AlertSeverity002Label,
|
||||||
AlertDialog.AlertSeverity003Label,
|
AlertDialog.AlertSeverity003Label,
|
||||||
@@ -100,21 +100,21 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
// Response tab strings
|
// Response tab strings
|
||||||
private static readonly ExecuteJobCheckBoxLabel: string = localize('alertDialog.ExecuteJob', 'Execute Job');
|
private static readonly ExecuteJobCheckBoxLabel: string = localize('alertDialog.ExecuteJob', 'Execute Job');
|
||||||
private static readonly ExecuteJobTextBoxLabel: string = localize('alertDialog.ExecuteJobName', 'Job Name');
|
private static readonly ExecuteJobTextBoxLabel: string = localize('alertDialog.ExecuteJobName', 'Job Name');
|
||||||
private static readonly NotifyOperatorsTextBoxLabel: string = localize('alertDialog.NotifyOperators', 'Notify Operators');
|
private static readonly NotifyOperatorsTextBoxLabel: string = localize('alertDialog.NotifyOperators', 'Notify Operators');
|
||||||
private static readonly NewJobButtonLabel: string = localize('alertDialog.NewJob', 'New Job');
|
private static readonly NewJobButtonLabel: string = localize('alertDialog.NewJob', 'New Job');
|
||||||
private static readonly OperatorListLabel: string = localize('alertDialog.OperatorList', 'Operator List');
|
private static readonly OperatorListLabel: string = localize('alertDialog.OperatorList', 'Operator List');
|
||||||
private static readonly OperatorNameColumnLabel: string = localize('alertDialog.OperatorName', 'Operator');
|
private static readonly OperatorNameColumnLabel: string = localize('alertDialog.OperatorName', 'Operator');
|
||||||
private static readonly OperatorEmailColumnLabel: string = localize('alertDialog.OperatorEmail', 'E-mail');
|
private static readonly OperatorEmailColumnLabel: string = localize('alertDialog.OperatorEmail', 'E-mail');
|
||||||
private static readonly OperatorPagerColumnLabel: string = localize('alertDialog.OperatorPager', 'Pager');
|
private static readonly OperatorPagerColumnLabel: string = localize('alertDialog.OperatorPager', 'Pager');
|
||||||
private static readonly NewOperatorButtonLabel: string = localize('alertDialog.NewOperator', 'New Operator');
|
private static readonly NewOperatorButtonLabel: string = localize('alertDialog.NewOperator', 'New Operator');
|
||||||
|
|
||||||
// Options tab strings
|
// Options tab strings
|
||||||
private static readonly IncludeErrorInEmailCheckBoxLabel: string = localize('alertDialog.IncludeErrorInEmail', 'Include alert error text in e-mail');
|
private static readonly IncludeErrorInEmailCheckBoxLabel: string = localize('alertDialog.IncludeErrorInEmail', 'Include alert error text in e-mail');
|
||||||
private static readonly IncludeErrorInPagerCheckBoxLabel: string = localize('alertDialog.IncludeErrorInPager', 'Include alert error text in pager');
|
private static readonly IncludeErrorInPagerCheckBoxLabel: string = localize('alertDialog.IncludeErrorInPager', 'Include alert error text in pager');
|
||||||
private static readonly AdditionalMessageTextBoxLabel: string = localize('alertDialog.AdditionalNotification', 'Additional notification message to send');
|
private static readonly AdditionalMessageTextBoxLabel: string = localize('alertDialog.AdditionalNotification', 'Additional notification message to send');
|
||||||
private static readonly DelayBetweenResponsesTextBoxLabel: string = localize('alertDialog.DelayBetweenResponse', 'Delay between responses');
|
private static readonly DelayBetweenResponsesTextBoxLabel: string = localize('alertDialog.DelayBetweenResponse', 'Delay between responses');
|
||||||
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
|
private static readonly DelayMinutesTextBoxLabel: string = localize('alertDialog.DelayMinutes', 'Delay Minutes');
|
||||||
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
|
private static readonly DelaySecondsTextBoxLabel: string = localize('alertDialog.DelaySeconds', 'Delay Seconds');
|
||||||
|
|
||||||
// Event Name strings
|
// Event Name strings
|
||||||
private readonly NewAlertDialog = 'NewAlertDialogOpen';
|
private readonly NewAlertDialog = 'NewAlertDialogOpen';
|
||||||
@@ -315,7 +315,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
}],
|
}],
|
||||||
title: AlertDialog.EventAlertText
|
title: AlertDialog.EventAlertText
|
||||||
}
|
}
|
||||||
]).withLayout({ width: '100%' }).component();
|
]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
|
|
||||||
if (this.model.severity > 0) {
|
if (this.model.severity > 0) {
|
||||||
this.severityRadioButton.checked = true;
|
this.severityRadioButton.checked = true;
|
||||||
this.severityDropDown.value = this.severityDropDown.values[this.model.severity-1];
|
this.severityDropDown.value = this.severityDropDown.values[this.model.severity - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.model.databaseName) {
|
if (this.model.databaseName) {
|
||||||
@@ -356,9 +356,9 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
.component();
|
.component();
|
||||||
this.executeJobTextBox.enabled = false;
|
this.executeJobTextBox.enabled = false;
|
||||||
this.newJobButton = view.modelBuilder.button().withProperties({
|
this.newJobButton = view.modelBuilder.button().withProperties({
|
||||||
label: AlertDialog.NewJobButtonLabel,
|
label: AlertDialog.NewJobButtonLabel,
|
||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
this.newJobButton.enabled = false;
|
this.newJobButton.enabled = false;
|
||||||
this.newJobButton.onDidClick(() => {
|
this.newJobButton.onDidClick(() => {
|
||||||
let jobDialog = new JobDialog(this.ownerUri);
|
let jobDialog = new JobDialog(this.ownerUri);
|
||||||
@@ -382,7 +382,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
}, {
|
}, {
|
||||||
component: this.newJobButton,
|
component: this.newJobButton,
|
||||||
title: AlertDialog.NewJobButtonLabel
|
title: AlertDialog.NewJobButtonLabel
|
||||||
}], { componentWidth: '100%'}).component();
|
}], { componentWidth: '100%' }).component();
|
||||||
|
|
||||||
let previewTag = view.modelBuilder.text()
|
let previewTag = view.modelBuilder.text()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
@@ -409,9 +409,9 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newOperatorButton = view.modelBuilder.button().withProperties({
|
this.newOperatorButton = view.modelBuilder.button().withProperties({
|
||||||
label: AlertDialog.NewOperatorButtonLabel,
|
label: AlertDialog.NewOperatorButtonLabel,
|
||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.operatorsTable.enabled = false;
|
this.operatorsTable.enabled = false;
|
||||||
this.newOperatorButton.enabled = false;
|
this.newOperatorButton.enabled = false;
|
||||||
@@ -438,7 +438,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
}, {
|
}, {
|
||||||
component: this.newOperatorButton,
|
component: this.newOperatorButton,
|
||||||
title: ''
|
title: ''
|
||||||
}], { componentWidth: '100%'}).component();
|
}], { componentWidth: '100%' }).component();
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
@@ -548,7 +548,7 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
} else {
|
} else {
|
||||||
this.model.eventDescriptionKeyword = '';
|
this.model.eventDescriptionKeyword = '';
|
||||||
}
|
}
|
||||||
let minutes = this.delayMinutesTextBox.value ? +this.delayMinutesTextBox.value : 0;
|
let minutes = this.delayMinutesTextBox.value ? +this.delayMinutesTextBox.value : 0;
|
||||||
let seconds = this.delaySecondsTextBox.value ? +this.delaySecondsTextBox : 0;
|
let seconds = this.delaySecondsTextBox.value ? +this.delaySecondsTextBox : 0;
|
||||||
this.model.delayBetweenResponses = minutes + seconds;
|
this.model.delayBetweenResponses = minutes + seconds;
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
// Event Name strings
|
// Event Name strings
|
||||||
private readonly NewJobDialogEvent: string = 'NewJobDialogOpened';
|
private readonly NewJobDialogEvent: string = 'NewJobDialogOpened';
|
||||||
private readonly EditJobDialogEvent: string = 'EditJobDialogOpened';
|
private readonly EditJobDialogEvent: string = 'EditJobDialogOpened';
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
private generalTab: azdata.window.DialogTab;
|
private generalTab: azdata.window.DialogTab;
|
||||||
@@ -259,9 +259,9 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
width: 140
|
width: 140
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newStepButton.onDidClick((e)=>{
|
this.newStepButton.onDidClick((e) => {
|
||||||
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true);
|
let stepDialog = new JobStepDialog(this.model.ownerUri, '', this.model, null, true);
|
||||||
stepDialog.onSuccess((step) => {
|
stepDialog.onSuccess((step) => {
|
||||||
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
||||||
this.steps.push(stepInfo);
|
this.steps.push(stepInfo);
|
||||||
@@ -296,7 +296,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.deleteStepButton.enabled = false;
|
this.deleteStepButton.enabled = false;
|
||||||
|
|
||||||
this.moveStepUpButton.onDidClick(() => {
|
this.moveStepUpButton.onDidClick(() => {
|
||||||
let rowNumber = this.stepsTable.selectedRows[0];
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
let previousRow = rowNumber - 1;
|
let previousRow = rowNumber - 1;
|
||||||
let previousStep = this.steps[previousRow];
|
let previousStep = this.steps[previousRow];
|
||||||
let previousStepId = this.steps[previousRow].id;
|
let previousStepId = this.steps[previousRow].id;
|
||||||
@@ -329,7 +329,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
if (this.stepsTable.selectedRows.length === 1) {
|
if (this.stepsTable.selectedRows.length === 1) {
|
||||||
let rowNumber = this.stepsTable.selectedRows[0];
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
let stepData = this.model.jobSteps[rowNumber];
|
let stepData = this.model.jobSteps[rowNumber];
|
||||||
let editStepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
|
let editStepDialog = new JobStepDialog(this.model.ownerUri, '', this.model, stepData, true);
|
||||||
editStepDialog.onSuccess((step) => {
|
editStepDialog.onSuccess((step) => {
|
||||||
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
||||||
for (let i = 0; i < this.steps.length; i++) {
|
for (let i = 0; i < this.steps.length; i++) {
|
||||||
@@ -349,7 +349,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.deleteStepButton.onDidClick(async() => {
|
this.deleteStepButton.onDidClick(async () => {
|
||||||
if (this.stepsTable.selectedRows.length === 1) {
|
if (this.stepsTable.selectedRows.length === 1) {
|
||||||
let rowNumber = this.stepsTable.selectedRows[0];
|
let rowNumber = this.stepsTable.selectedRows[0];
|
||||||
AgentUtils.getAgentService().then(async (agentService) => {
|
AgentUtils.getAgentService().then(async (agentService) => {
|
||||||
@@ -448,7 +448,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.alerts.push(alertInfo);
|
this.alerts.push(alertInfo);
|
||||||
this.alertsTable.data = this.convertAlertsToData(this.alerts);
|
this.alertsTable.data = this.convertAlertsToData(this.alerts);
|
||||||
});
|
});
|
||||||
this.newAlertButton.onDidClick(()=>{
|
this.newAlertButton.onDidClick(() => {
|
||||||
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
alertDialog.jobId = this.model.jobId;
|
alertDialog.jobId = this.model.jobId;
|
||||||
alertDialog.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
|
alertDialog.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
|
||||||
@@ -491,7 +491,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
label: 'Remove schedule',
|
label: 'Remove schedule',
|
||||||
width: 100
|
width: 100
|
||||||
}).component();
|
}).component();
|
||||||
this.pickScheduleButton.onDidClick(()=>{
|
this.pickScheduleButton.onDidClick(() => {
|
||||||
let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri, this.model.name);
|
let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri, this.model.name);
|
||||||
pickScheduleDialog.onSuccess((dialogModel) => {
|
pickScheduleDialog.onSuccess((dialogModel) => {
|
||||||
let selectedSchedule = dialogModel.selectedSchedule;
|
let selectedSchedule = dialogModel.selectedSchedule;
|
||||||
@@ -507,8 +507,8 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
pickScheduleDialog.showDialog();
|
pickScheduleDialog.showDialog();
|
||||||
});
|
});
|
||||||
this.removeScheduleButton.onDidClick(() => {
|
this.removeScheduleButton.onDidClick(() => {
|
||||||
if (this.schedulesTable.selectedRows.length === 1) {
|
if (this.schedulesTable.selectedRows.length === 1) {
|
||||||
let selectedRow = this.schedulesTable.selectedRows[0];
|
let selectedRow = this.schedulesTable.selectedRows[0];
|
||||||
let selectedScheduleName = this.schedulesTable.data[selectedRow][1];
|
let selectedScheduleName = this.schedulesTable.data[selectedRow][1];
|
||||||
for (let i = 0; i < this.schedules.length; i++) {
|
for (let i = 0; i < this.schedules.length; i++) {
|
||||||
if (this.schedules[i].name === selectedScheduleName) {
|
if (this.schedules[i].name === selectedScheduleName) {
|
||||||
@@ -595,22 +595,23 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
let formModel = view.modelBuilder.formContainer().withFormItems([
|
let formModel = view.modelBuilder.formContainer().withFormItems([
|
||||||
{
|
{
|
||||||
components:
|
components:
|
||||||
[{
|
[{
|
||||||
component: emailContainer,
|
component: emailContainer,
|
||||||
title: ''
|
title: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: pagerContainer,
|
component: pagerContainer,
|
||||||
title: ''
|
title: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: eventLogContainer,
|
component: eventLogContainer,
|
||||||
title: ''
|
title: ''
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: deleteJobContainer,
|
component: deleteJobContainer,
|
||||||
title: ''
|
title: ''
|
||||||
}], title: this.NotificationsTabTopLabelString}]).withLayout({ width: '100%' }).component();
|
}], title: this.NotificationsTabTopLabelString
|
||||||
|
}]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
this.emailConditionDropdown.values = this.model.JobCompletionActionConditions;
|
this.emailConditionDropdown.values = this.model.JobCompletionActionConditions;
|
||||||
@@ -694,7 +695,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
|
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
|
||||||
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
|
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
|
||||||
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
|
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
|
||||||
this.model.startStepId = this.startStepDropdown.enabled ? +this.getDropdownValue(this.startStepDropdown) : 1;
|
this.model.startStepId = this.startStepDropdown.enabled ? +this.getDropdownValue(this.startStepDropdown) : 1;
|
||||||
if (!this.model.jobSteps) {
|
if (!this.model.jobSteps) {
|
||||||
this.model.jobSteps = [];
|
this.model.jobSteps = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
private readonly GeneralTabText: string = localize('jobStepDialog.general', 'General');
|
private readonly GeneralTabText: string = localize('jobStepDialog.general', 'General');
|
||||||
private readonly AdvancedTabText: string = localize('jobStepDialog.advanced', 'Advanced');
|
private readonly AdvancedTabText: string = localize('jobStepDialog.advanced', 'Advanced');
|
||||||
private readonly OpenCommandText: string = localize('jobStepDialog.open', 'Open...');
|
private readonly OpenCommandText: string = localize('jobStepDialog.open', 'Open...');
|
||||||
private readonly ParseCommandText: string = localize('jobStepDialog.parse','Parse');
|
private readonly ParseCommandText: string = localize('jobStepDialog.parse', 'Parse');
|
||||||
private readonly SuccessfulParseText: string = localize('jobStepDialog.successParse', 'The command was successfully parsed.');
|
private readonly SuccessfulParseText: string = localize('jobStepDialog.successParse', 'The command was successfully parsed.');
|
||||||
private readonly FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.');
|
private readonly FailureParseText: string = localize('jobStepDialog.failParse', 'The command failed.');
|
||||||
private readonly BlankStepNameErrorText: string = localize('jobStepDialog.blankStepName', 'The step name cannot be left blank');
|
private readonly BlankStepNameErrorText: string = localize('jobStepDialog.blankStepName', 'The step name cannot be left blank');
|
||||||
@@ -124,15 +124,15 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
viaJobDialog: boolean = false
|
viaJobDialog: boolean = false
|
||||||
) {
|
) {
|
||||||
super(ownerUri,
|
super(ownerUri,
|
||||||
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel, viaJobDialog),
|
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel, viaJobDialog),
|
||||||
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
|
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
|
||||||
this.stepId = jobStepInfo ?
|
this.stepId = jobStepInfo ?
|
||||||
jobStepInfo.id : jobModel.jobSteps ?
|
jobStepInfo.id : jobModel.jobSteps ?
|
||||||
jobModel.jobSteps.length + 1 : 1;
|
jobModel.jobSteps.length + 1 : 1;
|
||||||
this.isEdit = jobStepInfo ? true : false;
|
this.isEdit = jobStepInfo ? true : false;
|
||||||
this.model.dialogMode = this.isEdit ? AgentDialogMode.EDIT : AgentDialogMode.CREATE;
|
this.model.dialogMode = this.isEdit ? AgentDialogMode.EDIT : AgentDialogMode.CREATE;
|
||||||
this.jobModel = jobModel;
|
this.jobModel = jobModel;
|
||||||
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
||||||
this.server = server;
|
this.server = server;
|
||||||
this.dialogName = this.isEdit ? this.EditStepDialog : this.NewStepDialog;
|
this.dialogName = this.isEdit ? this.EditStepDialog : this.NewStepDialog;
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
if (this.commandTextBox.value) {
|
if (this.commandTextBox.value) {
|
||||||
queryProvider.parseSyntax(this.ownerUri, this.commandTextBox.value).then(result => {
|
queryProvider.parseSyntax(this.ownerUri, this.commandTextBox.value).then(result => {
|
||||||
if (result && result.parseable) {
|
if (result && result.parseable) {
|
||||||
this.dialog.message = { text: this.SuccessfulParseText, level: 2};
|
this.dialog.message = { text: this.SuccessfulParseText, level: 2 };
|
||||||
} else if (result && !result.parseable) {
|
} else if (result && !result.parseable) {
|
||||||
this.dialog.message = { text: this.FailureParseText };
|
this.dialog.message = { text: this.FailureParseText };
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
}).component();
|
}).component();
|
||||||
this.typeDropdown.onValueChanged((type) => {
|
this.typeDropdown.onValueChanged((type) => {
|
||||||
switch (type.selected) {
|
switch (type.selected) {
|
||||||
case(this.TSQLScript):
|
case (this.TSQLScript):
|
||||||
this.runAsDropdown.value = '';
|
this.runAsDropdown.value = '';
|
||||||
this.runAsDropdown.values = [''];
|
this.runAsDropdown.values = [''];
|
||||||
this.runAsDropdown.enabled = false;
|
this.runAsDropdown.enabled = false;
|
||||||
@@ -256,7 +256,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
this.processExitCodeBox.value = '';
|
this.processExitCodeBox.value = '';
|
||||||
this.processExitCodeBox.enabled = false;
|
this.processExitCodeBox.enabled = false;
|
||||||
break;
|
break;
|
||||||
case(this.Powershell):
|
case (this.Powershell):
|
||||||
this.runAsDropdown.value = this.AgentServiceAccount;
|
this.runAsDropdown.value = this.AgentServiceAccount;
|
||||||
this.runAsDropdown.values = [this.runAsDropdown.value];
|
this.runAsDropdown.values = [this.runAsDropdown.value];
|
||||||
this.runAsDropdown.enabled = true;
|
this.runAsDropdown.enabled = true;
|
||||||
@@ -266,7 +266,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
this.processExitCodeBox.value = '';
|
this.processExitCodeBox.value = '';
|
||||||
this.processExitCodeBox.enabled = false;
|
this.processExitCodeBox.enabled = false;
|
||||||
break;
|
break;
|
||||||
case(this.CmdExec):
|
case (this.CmdExec):
|
||||||
this.databaseDropdown.enabled = false;
|
this.databaseDropdown.enabled = false;
|
||||||
this.databaseDropdown.values = [''];
|
this.databaseDropdown.values = [''];
|
||||||
this.databaseDropdown.value = '';
|
this.databaseDropdown.value = '';
|
||||||
@@ -397,13 +397,13 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
|
|
||||||
let retryAttemptsContainer = view.modelBuilder.formContainer()
|
let retryAttemptsContainer = view.modelBuilder.formContainer()
|
||||||
.withFormItems(
|
.withFormItems(
|
||||||
[{
|
[{
|
||||||
component: this.retryAttemptsBox,
|
component: this.retryAttemptsBox,
|
||||||
title: this.RetryAttemptsLabel
|
title: this.RetryAttemptsLabel
|
||||||
}], {
|
}], {
|
||||||
horizontal: false,
|
horizontal: false,
|
||||||
componentWidth: '100%'
|
componentWidth: '100%'
|
||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
|
|
||||||
let retryIntervalContainer = view.modelBuilder.formContainer()
|
let retryIntervalContainer = view.modelBuilder.formContainer()
|
||||||
@@ -411,7 +411,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
[{
|
[{
|
||||||
component: this.retryIntervalBox,
|
component: this.retryIntervalBox,
|
||||||
title: this.RetryIntervalLabel
|
title: this.RetryIntervalLabel
|
||||||
}], {
|
}], {
|
||||||
horizontal: false
|
horizontal: false
|
||||||
})
|
})
|
||||||
.component();
|
.component();
|
||||||
@@ -427,13 +427,13 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
let fileBrowserTitle = this.FileBrowserDialogTitle + `${this.server}`;
|
let fileBrowserTitle = this.FileBrowserDialogTitle + `${this.server}`;
|
||||||
this.fileBrowserDialog = azdata.window.createModelViewDialog(fileBrowserTitle);
|
this.fileBrowserDialog = azdata.window.createModelViewDialog(fileBrowserTitle);
|
||||||
let fileBrowserTab = azdata.window.createTab('File Browser');
|
let fileBrowserTab = azdata.window.createTab('File Browser');
|
||||||
this.fileBrowserDialog.content = [fileBrowserTab];
|
this.fileBrowserDialog.content = [fileBrowserTab];
|
||||||
fileBrowserTab.registerContent(async (view) => {
|
fileBrowserTab.registerContent(async (view) => {
|
||||||
this.fileBrowserTree = view.modelBuilder.fileBrowserTree()
|
this.fileBrowserTree = view.modelBuilder.fileBrowserTree()
|
||||||
.withProperties({ ownerUri: this.ownerUri, width: 420, height: 700 })
|
.withProperties({ ownerUri: this.ownerUri, width: 420, height: 700 })
|
||||||
.component();
|
.component();
|
||||||
this.selectedPathTextBox = view.modelBuilder.inputBox()
|
this.selectedPathTextBox = view.modelBuilder.inputBox()
|
||||||
.withProperties({ inputType: 'text'})
|
.withProperties({ inputType: 'text' })
|
||||||
.component();
|
.component();
|
||||||
this.fileBrowserTree.onDidChange((args) => {
|
this.fileBrowserTree.onDidChange((args) => {
|
||||||
this.selectedPathTextBox.value = args.fullPath;
|
this.selectedPathTextBox.value = args.fullPath;
|
||||||
@@ -462,7 +462,7 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
component: this.fileBrowserNameBox,
|
component: this.fileBrowserNameBox,
|
||||||
title: this.FileNameLabelString
|
title: this.FileNameLabelString
|
||||||
}
|
}
|
||||||
]).component();
|
]).component();
|
||||||
view.initializeModel(fileBrowserContainer);
|
view.initializeModel(fileBrowserContainer);
|
||||||
});
|
});
|
||||||
this.fileBrowserDialog.okButton.onClick(() => {
|
this.fileBrowserDialog.okButton.onClick(() => {
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
|
|
||||||
|
|
||||||
this.pagerTuesdayCheckBox.onChanged(() => {
|
this.pagerTuesdayCheckBox.onChanged(() => {
|
||||||
if (this.pagerTuesdayCheckBox .checked) {
|
if (this.pagerTuesdayCheckBox.checked) {
|
||||||
this.weekdayPagerStartTimeInput.enabled = true;
|
this.weekdayPagerStartTimeInput.enabled = true;
|
||||||
this.weekdayPagerEndTimeInput.enabled = true;
|
this.weekdayPagerEndTimeInput.enabled = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -153,7 +153,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.pagerWednesdayCheckBox.onChanged(() => {
|
this.pagerWednesdayCheckBox.onChanged(() => {
|
||||||
if (this.pagerWednesdayCheckBox .checked) {
|
if (this.pagerWednesdayCheckBox.checked) {
|
||||||
this.weekdayPagerStartTimeInput.enabled = true;
|
this.weekdayPagerStartTimeInput.enabled = true;
|
||||||
this.weekdayPagerEndTimeInput.enabled = true;
|
this.weekdayPagerEndTimeInput.enabled = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -171,7 +171,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.pagerThursdayCheckBox.onChanged(() => {
|
this.pagerThursdayCheckBox.onChanged(() => {
|
||||||
if (this.pagerThursdayCheckBox .checked) {
|
if (this.pagerThursdayCheckBox.checked) {
|
||||||
this.weekdayPagerStartTimeInput.enabled = true;
|
this.weekdayPagerStartTimeInput.enabled = true;
|
||||||
this.weekdayPagerEndTimeInput.enabled = true;
|
this.weekdayPagerEndTimeInput.enabled = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -362,7 +362,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
}, {
|
}, {
|
||||||
component: pagerSundayCheckboxContainer,
|
component: pagerSundayCheckboxContainer,
|
||||||
title: ''
|
title: ''
|
||||||
}] ,
|
}],
|
||||||
title: OperatorDialog.PagerDutyScheduleLabel
|
title: OperatorDialog.PagerDutyScheduleLabel
|
||||||
}]).withLayout({ width: '100%' }).component();
|
}]).withLayout({ width: '100%' }).component();
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
@@ -20,8 +20,8 @@ export class PickScheduleDialog {
|
|||||||
private readonly CancelButtonText: string = localize('pickSchedule.cancel', 'Cancel');
|
private readonly CancelButtonText: string = localize('pickSchedule.cancel', 'Cancel');
|
||||||
private readonly SchedulesLabelText: string = localize('pickSchedule.availableSchedules', 'Available Schedules:');
|
private readonly SchedulesLabelText: string = localize('pickSchedule.availableSchedules', 'Available Schedules:');
|
||||||
public static readonly ScheduleNameLabelText: string = localize('pickSchedule.scheduleName', 'Name');
|
public static readonly ScheduleNameLabelText: string = localize('pickSchedule.scheduleName', 'Name');
|
||||||
public static readonly SchedulesIDText: string = localize('pickSchedule.scheduleID','ID');
|
public static readonly SchedulesIDText: string = localize('pickSchedule.scheduleID', 'ID');
|
||||||
public static readonly ScheduleDescription: string = localize('pickSchedule.description','Description');
|
public static readonly ScheduleDescription: string = localize('pickSchedule.description', 'Description');
|
||||||
|
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
@@ -74,7 +74,7 @@ export class PickScheduleDialog {
|
|||||||
let data: any[][] = [];
|
let data: any[][] = [];
|
||||||
for (let i = 0; i < this.model.schedules.length; ++i) {
|
for (let i = 0; i < this.model.schedules.length; ++i) {
|
||||||
let schedule = this.model.schedules[i];
|
let schedule = this.model.schedules[i];
|
||||||
data[i] = [ schedule.id, schedule.name, schedule.description ];
|
data[i] = [schedule.id, schedule.name, schedule.description];
|
||||||
}
|
}
|
||||||
this.schedulesTable.data = data;
|
this.schedulesTable.data = data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export class ProxyDialog extends AgentDialog<ProxyData> {
|
|||||||
this.generalTab.registerContent(async view => {
|
this.generalTab.registerContent(async view => {
|
||||||
|
|
||||||
this.proxyNameTextBox = view.modelBuilder.inputBox()
|
this.proxyNameTextBox = view.modelBuilder.inputBox()
|
||||||
.withProperties({width: 420})
|
.withProperties({ width: 420 })
|
||||||
.component();
|
.component();
|
||||||
|
|
||||||
this.credentialNameDropDown = view.modelBuilder.dropDown()
|
this.credentialNameDropDown = view.modelBuilder.dropDown()
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export class ScheduleDialog {
|
|||||||
let data: any[][] = [];
|
let data: any[][] = [];
|
||||||
for (let i = 0; i < this.model.schedules.length; ++i) {
|
for (let i = 0; i < this.model.schedules.length; ++i) {
|
||||||
let schedule = this.model.schedules[i];
|
let schedule = this.model.schedules[i];
|
||||||
data[i] = [ schedule.name ];
|
data[i] = [schedule.name];
|
||||||
}
|
}
|
||||||
this.schedulesTable.data = data;
|
this.schedulesTable.data = data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,57 +22,57 @@ const localize = nls.loadMessageBundle();
|
|||||||
* The main controller class that initializes the extension
|
* The main controller class that initializes the extension
|
||||||
*/
|
*/
|
||||||
export class MainController {
|
export class MainController {
|
||||||
protected _context: vscode.ExtensionContext;
|
protected _context: vscode.ExtensionContext;
|
||||||
|
|
||||||
// PUBLIC METHODS //////////////////////////////////////////////////////
|
// PUBLIC METHODS //////////////////////////////////////////////////////
|
||||||
public constructor(context: vscode.ExtensionContext) {
|
public constructor(context: vscode.ExtensionContext) {
|
||||||
this._context = context;
|
this._context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static showNotYetImplemented(): void {
|
public static showNotYetImplemented(): void {
|
||||||
vscode.window.showInformationMessage(
|
vscode.window.showInformationMessage(
|
||||||
localize('mainController.notImplemented', "This feature is under development. Check-out the latest insiders build if you'd like to try out the most recent changes!"));
|
localize('mainController.notImplemented', "This feature is under development. Check-out the latest insiders build if you'd like to try out the most recent changes!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates the extension
|
* Activates the extension
|
||||||
*/
|
*/
|
||||||
public activate(): void {
|
public activate(): void {
|
||||||
vscode.commands.registerCommand('agent.openJobDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo) => {
|
vscode.commands.registerCommand('agent.openJobDialog', async (ownerUri: string, jobInfo: azdata.AgentJobInfo) => {
|
||||||
let dialog = new JobDialog(ownerUri, jobInfo);
|
let dialog = new JobDialog(ownerUri, jobInfo);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: azdata.AgentJobInfo, jobStepInfo: azdata.AgentJobStepInfo) => {
|
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: azdata.AgentJobInfo, jobStepInfo: azdata.AgentJobStepInfo) => {
|
||||||
AgentUtils.getAgentService().then(async(agentService) => {
|
AgentUtils.getAgentService().then(async (agentService) => {
|
||||||
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
|
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openPickScheduleDialog', async (ownerUri: string, jobName: string) => {
|
vscode.commands.registerCommand('agent.openPickScheduleDialog', async (ownerUri: string, jobName: string) => {
|
||||||
let dialog = new PickScheduleDialog(ownerUri, jobName);
|
let dialog = new PickScheduleDialog(ownerUri, jobName);
|
||||||
await dialog.showDialog();
|
await dialog.showDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: azdata.AgentJobInfo, alertInfo: azdata.AgentAlertInfo) => {
|
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: azdata.AgentJobInfo, alertInfo: azdata.AgentAlertInfo) => {
|
||||||
AgentUtils.getAgentService().then(async (agentService) => {
|
AgentUtils.getAgentService().then(async (agentService) => {
|
||||||
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
|
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openOperatorDialog', async (ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) => {
|
vscode.commands.registerCommand('agent.openOperatorDialog', async (ownerUri: string, operatorInfo: azdata.AgentOperatorInfo) => {
|
||||||
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openProxyDialog', async (ownerUri: string, proxyInfo: azdata.AgentProxyInfo, credentials: azdata.CredentialInfo[]) => {
|
vscode.commands.registerCommand('agent.openProxyDialog', async (ownerUri: string, proxyInfo: azdata.AgentProxyInfo, credentials: azdata.CredentialInfo[]) => {
|
||||||
let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
|
let dialog = new ProxyDialog(ownerUri, proxyInfo, credentials);
|
||||||
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
dialog.dialogName ? await dialog.openDialog(dialog.dialogName) : await dialog.openDialog();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivates the extension
|
* Deactivates the extension
|
||||||
*/
|
*/
|
||||||
public deactivate(): void {
|
public deactivate(): void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
{
|
{
|
||||||
"compileOnSave": true,
|
"compileOnSave": true,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"outDir": "./out",
|
"outDir": "./out",
|
||||||
"lib": [
|
"lib": [
|
||||||
"es6", "es2015.promise"
|
"es6", "es2015.promise"
|
||||||
],
|
],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node"
|
||||||
"declaration": true
|
},
|
||||||
},
|
"exclude": [
|
||||||
"exclude": [
|
"node_modules"
|
||||||
"node_modules"
|
]
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as adal from 'adal-node';
|
import * as adal from 'adal-node';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as request from 'request';
|
import * as request from 'request';
|
||||||
@@ -54,8 +52,8 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all tokens that belong to the given account from the token cache
|
* Clears all tokens that belong to the given account from the token cache
|
||||||
* @param {"data".AccountKey} accountKey Key identifying the account to delete tokens for
|
* @param accountKey Key identifying the account to delete tokens for
|
||||||
* @returns {Thenable<void>} Promise to clear requested tokens from the token cache
|
* @returns Promise to clear requested tokens from the token cache
|
||||||
*/
|
*/
|
||||||
public clear(accountKey: azdata.AccountKey): Thenable<void> {
|
public clear(accountKey: azdata.AccountKey): Thenable<void> {
|
||||||
return this.doIfInitialized(() => this.clearAccountTokens(accountKey));
|
return this.doIfInitialized(() => this.clearAccountTokens(accountKey));
|
||||||
@@ -63,7 +61,7 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the entire token cache. Invoked by command palette action.
|
* Clears the entire token cache. Invoked by command palette action.
|
||||||
* @returns {Thenable<void>} Promise to clear the token cache
|
* @returns Promise to clear the token cache
|
||||||
*/
|
*/
|
||||||
public clearTokenCache(): Thenable<void> {
|
public clearTokenCache(): Thenable<void> {
|
||||||
return this._tokenCache.clear();
|
return this._tokenCache.clear();
|
||||||
@@ -92,13 +90,13 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
// NOTE: Based on ADAL implementation, getting tokens should use the refresh token if necessary
|
// NOTE: Based on ADAL implementation, getting tokens should use the refresh token if necessary
|
||||||
let task = this.getAccessTokens(account, azdata.AzureResource.ResourceManagement)
|
let task = this.getAccessTokens(account, azdata.AzureResource.ResourceManagement)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
return account;
|
return account;
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
account.isStale = true;
|
account.isStale = true;
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
rehydrationTasks.push(task);
|
rehydrationTasks.push(task);
|
||||||
}
|
}
|
||||||
@@ -321,10 +319,10 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
* Retrieves a token for the given user ID for the specific tenant ID. If the token can, it
|
* Retrieves a token for the given user ID for the specific tenant ID. If the token can, it
|
||||||
* will be retrieved from the cache as per the ADAL API. AFAIK, the ADAL API will also utilize
|
* will be retrieved from the cache as per the ADAL API. AFAIK, the ADAL API will also utilize
|
||||||
* the refresh token if there aren't any unexpired tokens to use.
|
* the refresh token if there aren't any unexpired tokens to use.
|
||||||
* @param {string} userId ID of the user to get a token for
|
* @param userId ID of the user to get a token for
|
||||||
* @param {string} tenantId Tenant to get the token for
|
* @param tenantId Tenant to get the token for
|
||||||
* @param {string} resourceId ID of the resource the token will be good for
|
* @param resourceId ID of the resource the token will be good for
|
||||||
* @returns {Thenable<TokenResponse>} Promise to return a token. Rejected if retrieving the token fails.
|
* @returns Promise to return a token. Rejected if retrieving the token fails.
|
||||||
*/
|
*/
|
||||||
private getToken(userId: string, tenantId: string, resourceId: string): Thenable<adal.TokenResponse> {
|
private getToken(userId: string, tenantId: string, resourceId: string): Thenable<adal.TokenResponse> {
|
||||||
let self = this;
|
let self = this;
|
||||||
@@ -346,9 +344,9 @@ export class AzureAccountProvider implements azdata.AccountProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a web request using the provided bearer token
|
* Performs a web request using the provided bearer token
|
||||||
* @param {TokenResponse} accessToken Bearer token for accessing the provided URI
|
* @param accessToken Bearer token for accessing the provided URI
|
||||||
* @param {string} uri URI to access
|
* @param uri URI to access
|
||||||
* @returns {Thenable<any>} Promise to return the deserialized body of the request. Rejected if error occurred.
|
* @returns Promise to return the deserialized body of the request. Rejected if error occurred.
|
||||||
*/
|
*/
|
||||||
private makeWebRequest(accessToken: adal.TokenResponse, uri: string): Thenable<any> {
|
private makeWebRequest(accessToken: adal.TokenResponse, uri: string): Thenable<any> {
|
||||||
return new Promise<any>((resolve, reject) => {
|
return new Promise<any>((resolve, reject) => {
|
||||||
|
|||||||
@@ -77,14 +77,14 @@ export class AzureAccountProviderService implements vscode.Disposable {
|
|||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared');
|
let message = localize('clearTokenCacheSuccess', 'Token cache successfully cleared');
|
||||||
vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`);
|
vscode.window.showInformationMessage(`${constants.extensionName}: ${message}`);
|
||||||
},
|
},
|
||||||
err => {
|
err => {
|
||||||
let message = localize('clearTokenCacheFailure', 'Failed to clear token cache');
|
let message = localize('clearTokenCacheFailure', 'Failed to clear token cache');
|
||||||
vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`);
|
vscode.window.showErrorMessage(`${constants.extensionName}: ${message}: ${err}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private onDidChangeConfiguration(): void {
|
private onDidChangeConfiguration(): void {
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as adal from 'adal-node';
|
import * as adal from 'adal-node';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
@@ -34,8 +32,8 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
.then(cache => self.addToCache(cache, entries))
|
.then(cache => self.addToCache(cache, entries))
|
||||||
.then(updatedCache => self.writeCache(updatedCache))
|
.then(updatedCache => self.writeCache(updatedCache))
|
||||||
.then(
|
.then(
|
||||||
() => callback(null, false),
|
() => callback(null, false),
|
||||||
(err) => callback(err, true)
|
(err) => callback(err, true)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -70,8 +68,8 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
results => callback(null, results),
|
results => callback(null, results),
|
||||||
(err) => callback(err, null)
|
(err) => callback(err, null)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -79,7 +77,7 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
/**
|
/**
|
||||||
* Wrapper to make callback-based find method into a thenable method
|
* Wrapper to make callback-based find method into a thenable method
|
||||||
* @param query Partial object to use to look up tokens. Ideally should be partial of adal.TokenResponse
|
* @param query Partial object to use to look up tokens. Ideally should be partial of adal.TokenResponse
|
||||||
* @returns {Thenable<any[]>} Promise to return the matching adal.TokenResponse objects.
|
* @returns Promise to return the matching adal.TokenResponse objects.
|
||||||
* Rejected if an error was sent in the callback
|
* Rejected if an error was sent in the callback
|
||||||
*/
|
*/
|
||||||
public findThenable(query: any): Thenable<any[]> {
|
public findThenable(query: any): Thenable<any[]> {
|
||||||
@@ -104,16 +102,16 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
.then(cache => self.removeFromCache(cache, entries))
|
.then(cache => self.removeFromCache(cache, entries))
|
||||||
.then(updatedCache => self.writeCache(updatedCache))
|
.then(updatedCache => self.writeCache(updatedCache))
|
||||||
.then(
|
.then(
|
||||||
() => callback(null, null),
|
() => callback(null, null),
|
||||||
(err) => callback(err, null)
|
(err) => callback(err, null)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper to make callback-based remove method into a thenable method
|
* Wrapper to make callback-based remove method into a thenable method
|
||||||
* @param {TokenResponse[]} entries Array of entries to remove from the token cache
|
* @param entries Array of entries to remove from the token cache
|
||||||
* @returns {Thenable<void>} Promise to remove the given tokens from the token cache
|
* @returns Promise to remove the given tokens from the token cache
|
||||||
* Rejected if an error was sent in the callback
|
* Rejected if an error was sent in the callback
|
||||||
*/
|
*/
|
||||||
public removeThenable(entries: adal.TokenResponse[]): Thenable<void> {
|
public removeThenable(entries: adal.TokenResponse[]): Thenable<void> {
|
||||||
@@ -186,8 +184,8 @@ export default class TokenCache implements adal.TokenCache {
|
|||||||
if (splitValues.length === 2 && splitValues[0] && splitValues[1]) {
|
if (splitValues.length === 2 && splitValues[0] && splitValues[1]) {
|
||||||
try {
|
try {
|
||||||
return <EncryptionParams>{
|
return <EncryptionParams>{
|
||||||
key: new Buffer(splitValues[0], 'hex'),
|
key: Buffer.from(splitValues[0], 'hex'),
|
||||||
initializationVector: new Buffer(splitValues[1], 'hex')
|
initializationVector: Buffer.from(splitValues[1], 'hex')
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Swallow the error and fall through to generate new params
|
// Swallow the error and fall through to generate new params
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
|
|
||||||
@@ -15,7 +13,6 @@ import * as constants from './constants';
|
|||||||
* this API from our code
|
* this API from our code
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @class ApiWrapper
|
|
||||||
*/
|
*/
|
||||||
export class ApiWrapper {
|
export class ApiWrapper {
|
||||||
// Data APIs
|
// Data APIs
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ import { AzureResourceResourceTreeNode } from '../../resourceTreeNode';
|
|||||||
|
|
||||||
export function registerAzureResourceDatabaseCommands(appContext: AppContext): void {
|
export function registerAzureResourceDatabaseCommands(appContext: AppContext): void {
|
||||||
appContext.apiWrapper.registerCommand('azure.resource.connectsqldb', async (node?: TreeNode) => {
|
appContext.apiWrapper.registerCommand('azure.resource.connectsqldb', async (node?: TreeNode) => {
|
||||||
if (!node)
|
if (!node) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ import { AzureResourceResourceTreeNode } from '../../resourceTreeNode';
|
|||||||
|
|
||||||
export function registerAzureResourceDatabaseServerCommands(appContext: AppContext): void {
|
export function registerAzureResourceDatabaseServerCommands(appContext: AppContext): void {
|
||||||
appContext.apiWrapper.registerCommand('azure.resource.connectsqlserver', async (node?: TreeNode) => {
|
appContext.apiWrapper.registerCommand('azure.resource.connectsqlserver', async (node?: TreeNode) => {
|
||||||
if (!node)
|
if (!node) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ export class AzureResourceDatabaseServerService implements IAzureResourceDatabas
|
|||||||
|
|
||||||
svrs.forEach((svr) => databaseServers.push({
|
svrs.forEach((svr) => databaseServers.push({
|
||||||
name: svr.name,
|
name: svr.name,
|
||||||
fullName: svr.fullyQualifiedDomainName,
|
fullName: svr.fullyQualifiedDomainName,
|
||||||
loginName: svr.administratorLogin,
|
loginName: svr.administratorLogin,
|
||||||
defaultDatabaseName: 'master'
|
defaultDatabaseName: 'master'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return databaseServers;
|
return databaseServers;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { ServiceClientCredentials } from 'ms-rest';
|
import { ServiceClientCredentials } from 'ms-rest';
|
||||||
|
|
||||||
import { azureResource } from '../../azure-resource';
|
import { azureResource } from '../../azure-resource';
|
||||||
import { AzureResourceDatabaseServer } from './models';
|
import { AzureResourceDatabaseServer } from './models';
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ export class AzureResourceCacheService implements IAzureResourceCacheService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public generateKey(id: string): string {
|
public generateKey(id: string): string {
|
||||||
return `${AzureResourceCacheService.cacheKeyPrefix}.${id}`;
|
return `${AzureResourceCacheService.cacheKeyPrefix}.${id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get<T>(key: string): T | undefined {
|
public get<T>(key: string): T | undefined {
|
||||||
return this._context.workspaceState.get(key);
|
return this._context.workspaceState.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { azureResource } from '../azure-resource';
|
|||||||
import { IAzureResourceSubscriptionFilterService, IAzureResourceCacheService } from '../interfaces';
|
import { IAzureResourceSubscriptionFilterService, IAzureResourceCacheService } from '../interfaces';
|
||||||
|
|
||||||
interface AzureResourceSelectedSubscriptionsCache {
|
interface AzureResourceSelectedSubscriptionsCache {
|
||||||
selectedSubscriptions: { [accountId: string]: azureResource.AzureResourceSubscription[]};
|
selectedSubscriptions: { [accountId: string]: azureResource.AzureResourceSubscription[] };
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AzureResourceSubscriptionFilterService implements IAzureResourceSubscriptionFilterService {
|
export class AzureResourceSubscriptionFilterService implements IAzureResourceSubscriptionFilterService {
|
||||||
@@ -36,7 +36,7 @@ export class AzureResourceSubscriptionFilterService implements IAzureResourceSub
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async saveSelectedSubscriptions(account: Account, selectedSubscriptions: azureResource.AzureResourceSubscription[]): Promise<void> {
|
public async saveSelectedSubscriptions(account: Account, selectedSubscriptions: azureResource.AzureResourceSubscription[]): Promise<void> {
|
||||||
let selectedSubscriptionsCache: { [accountId: string]: azureResource.AzureResourceSubscription[]} = {};
|
let selectedSubscriptionsCache: { [accountId: string]: azureResource.AzureResourceSubscription[] } = {};
|
||||||
|
|
||||||
const cache = this._cacheService.get<AzureResourceSelectedSubscriptionsCache>(this._cacheKey);
|
const cache = this._cacheService.get<AzureResourceSelectedSubscriptionsCache>(this._cacheKey);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export class AzureResourceAccountTreeNode extends AzureResourceContainerTreeNode
|
|||||||
|
|
||||||
if (this._isClearingCache) {
|
if (this._isClearingCache) {
|
||||||
try {
|
try {
|
||||||
const tokens = await this.appContext.apiWrapper.getSecurityToken(this.account, AzureResource.ResourceManagement);
|
const tokens = await this.appContext.apiWrapper.getSecurityToken(this.account, AzureResource.ResourceManagement);
|
||||||
|
|
||||||
for (const tenant of this.account.properties.tenants) {
|
for (const tenant of this.account.properties.tenants) {
|
||||||
const token = tokens[tenant.id].token;
|
const token = tokens[tenant.id].token;
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ export abstract class AzureResourceContainerTreeNodeBase extends AzureResourceTr
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected setCacheKey(id: string): void {
|
protected setCacheKey(id: string): void {
|
||||||
this._cacheKey = this._cacheService.generateKey(id);
|
this._cacheKey = this._cacheService.generateKey(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updateCache<T>(cache: T): void {
|
protected updateCache<T>(cache: T): void {
|
||||||
this._cacheService.update<T>(this._cacheKey, cache);
|
this._cacheService.update<T>(this._cacheKey, cache);
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export class AzureResourceSubscriptionTreeNode extends AzureResourceContainerTre
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get nodePathValue(): string {
|
public get nodePathValue(): string {
|
||||||
return this._id;
|
return this._id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _id: string = undefined;
|
private _id: string = undefined;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export abstract class TreeNode {
|
|||||||
if (children) {
|
if (children) {
|
||||||
for (let child of children) {
|
for (let child of children) {
|
||||||
if (filter && filter(child)) {
|
if (filter && filter(child)) {
|
||||||
let childNode = await this.findNode(child, condition, filter, expandIfNeeded);
|
let childNode = await this.findNode(child, condition, filter, expandIfNeeded);
|
||||||
if (childNode) {
|
if (childNode) {
|
||||||
return childNode;
|
return childNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import * as nls from 'vscode-nls';
|
|||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export function getErrorMessage(error: Error | string): string {
|
export function getErrorMessage(error: Error | string): string {
|
||||||
return (error instanceof Error) ? error.message : error;
|
return (error instanceof Error) ? error.message : error;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AzureResourceErrorMessageUtil {
|
export class AzureResourceErrorMessageUtil {
|
||||||
@@ -19,78 +19,78 @@ export class AzureResourceErrorMessageUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function generateGuid(): string {
|
export function generateGuid(): string {
|
||||||
let hexValues: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
|
let hexValues: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
|
||||||
// c.f. rfc4122 (UUID version 4 = xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx)
|
// c.f. rfc4122 (UUID version 4 = xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx)
|
||||||
let oct: string = '';
|
let oct: string = '';
|
||||||
let tmp: number;
|
let tmp: number;
|
||||||
/* tslint:disable:no-bitwise */
|
/* tslint:disable:no-bitwise */
|
||||||
for (let a: number = 0; a < 4; a++) {
|
for (let a: number = 0; a < 4; a++) {
|
||||||
tmp = (4294967296 * Math.random()) | 0;
|
tmp = (4294967296 * Math.random()) | 0;
|
||||||
oct += hexValues[tmp & 0xF] +
|
oct += hexValues[tmp & 0xF] +
|
||||||
hexValues[tmp >> 4 & 0xF] +
|
hexValues[tmp >> 4 & 0xF] +
|
||||||
hexValues[tmp >> 8 & 0xF] +
|
hexValues[tmp >> 8 & 0xF] +
|
||||||
hexValues[tmp >> 12 & 0xF] +
|
hexValues[tmp >> 12 & 0xF] +
|
||||||
hexValues[tmp >> 16 & 0xF] +
|
hexValues[tmp >> 16 & 0xF] +
|
||||||
hexValues[tmp >> 20 & 0xF] +
|
hexValues[tmp >> 20 & 0xF] +
|
||||||
hexValues[tmp >> 24 & 0xF] +
|
hexValues[tmp >> 24 & 0xF] +
|
||||||
hexValues[tmp >> 28 & 0xF];
|
hexValues[tmp >> 28 & 0xF];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively'
|
// 'Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively'
|
||||||
let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0];
|
let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0];
|
||||||
return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12);
|
return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12);
|
||||||
/* tslint:enable:no-bitwise */
|
/* tslint:enable:no-bitwise */
|
||||||
}
|
}
|
||||||
|
|
||||||
export function equals(one: any, other: any): boolean {
|
export function equals(one: any, other: any): boolean {
|
||||||
if (one === other) {
|
if (one === other) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (one === null || one === undefined || other === null || other === undefined) {
|
if (one === null || one === undefined || other === null || other === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (typeof one !== typeof other) {
|
if (typeof one !== typeof other) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (typeof one !== 'object') {
|
if (typeof one !== 'object') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((Array.isArray(one)) !== (Array.isArray(other))) {
|
if ((Array.isArray(one)) !== (Array.isArray(other))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let i: number;
|
let i: number;
|
||||||
let key: string;
|
let key: string;
|
||||||
|
|
||||||
if (Array.isArray(one)) {
|
if (Array.isArray(one)) {
|
||||||
if (one.length !== other.length) {
|
if (one.length !== other.length) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (i = 0; i < one.length; i++) {
|
for (i = 0; i < one.length; i++) {
|
||||||
if (!equals(one[i], other[i])) {
|
if (!equals(one[i], other[i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const oneKeys: string[] = [];
|
const oneKeys: string[] = [];
|
||||||
|
|
||||||
for (key in one) {
|
for (key in one) {
|
||||||
oneKeys.push(key);
|
oneKeys.push(key);
|
||||||
}
|
}
|
||||||
oneKeys.sort();
|
oneKeys.sort();
|
||||||
const otherKeys: string[] = [];
|
const otherKeys: string[] = [];
|
||||||
for (key in other) {
|
for (key in other) {
|
||||||
otherKeys.push(key);
|
otherKeys.push(key);
|
||||||
}
|
}
|
||||||
otherKeys.sort();
|
otherKeys.sort();
|
||||||
if (!equals(oneKeys, otherKeys)) {
|
if (!equals(oneKeys, otherKeys)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (i = 0; i < oneKeys.length; i++) {
|
for (i = 0; i < oneKeys.length; i++) {
|
||||||
if (!equals(one[oneKeys[i]], other[oneKeys[i]])) {
|
if (!equals(one[oneKeys[i]], other[oneKeys[i]])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import {
|
|||||||
IAzureResourceAccountService,
|
IAzureResourceAccountService,
|
||||||
IAzureResourceSubscriptionService,
|
IAzureResourceSubscriptionService,
|
||||||
IAzureResourceSubscriptionFilterService,
|
IAzureResourceSubscriptionFilterService,
|
||||||
IAzureResourceTenantService } from '../azureResource/interfaces';
|
IAzureResourceTenantService
|
||||||
|
} from '../azureResource/interfaces';
|
||||||
import { AzureResourceServiceNames } from '../azureResource/constants';
|
import { AzureResourceServiceNames } from '../azureResource/constants';
|
||||||
import { AzureResourceTreeProvider } from '../azureResource/tree/treeProvider';
|
import { AzureResourceTreeProvider } from '../azureResource/tree/treeProvider';
|
||||||
import { registerAzureResourceCommands } from '../azureResource/commands';
|
import { registerAzureResourceCommands } from '../azureResource/commands';
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
'use strict';
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
@@ -23,7 +26,7 @@ let controllers: ControllerBase[] = [];
|
|||||||
// The function is a duplicate of \src\paths.js. IT would be better to import path.js but it doesn't
|
// The function is a duplicate of \src\paths.js. IT would be better to import path.js but it doesn't
|
||||||
// work for now because the extension is running in different process.
|
// work for now because the extension is running in different process.
|
||||||
export function getAppDataPath() {
|
export function getAppDataPath() {
|
||||||
var platform = process.platform;
|
let platform = process.platform;
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case 'win32': return process.env['APPDATA'] || path.join(process.env['USERPROFILE'], 'AppData', 'Roaming');
|
case 'win32': return process.env['APPDATA'] || path.join(process.env['USERPROFILE'], 'AppData', 'Roaming');
|
||||||
case 'darwin': return path.join(os.homedir(), 'Library', 'Application Support');
|
case 'darwin': return path.join(os.homedir(), 'Library', 'Application Support');
|
||||||
|
|||||||
@@ -12,110 +12,110 @@ const KUBECONFIG_PATH_KEY = 'mssql-bdc.kubeconfig';
|
|||||||
const KNOWN_KUBECONFIGS_KEY = 'mssql-bdc.knownKubeconfigs';
|
const KNOWN_KUBECONFIGS_KEY = 'mssql-bdc.knownKubeconfigs';
|
||||||
|
|
||||||
export async function addPathToConfig(configKey: string, value: string): Promise<void> {
|
export async function addPathToConfig(configKey: string, value: string): Promise<void> {
|
||||||
await setConfigValue(configKey, value);
|
await setConfigValue(configKey, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setConfigValue(configKey: string, value: any): Promise<void> {
|
async function setConfigValue(configKey: string, value: any): Promise<void> {
|
||||||
await atAllConfigScopes(addValueToConfigAtScope, configKey, value);
|
await atAllConfigScopes(addValueToConfigAtScope, configKey, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addValueToConfigAtScope(configKey: string, value: any, scope: vscode.ConfigurationTarget, valueAtScope: any, createIfNotExist: boolean): Promise<void> {
|
async function addValueToConfigAtScope(configKey: string, value: any, scope: vscode.ConfigurationTarget, valueAtScope: any, createIfNotExist: boolean): Promise<void> {
|
||||||
if (!createIfNotExist) {
|
if (!createIfNotExist) {
|
||||||
if (!valueAtScope || !(valueAtScope[configKey])) {
|
if (!valueAtScope || !(valueAtScope[configKey])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let newValue: any = {};
|
let newValue: any = {};
|
||||||
if (valueAtScope) {
|
if (valueAtScope) {
|
||||||
newValue = Object.assign({}, valueAtScope);
|
newValue = Object.assign({}, valueAtScope);
|
||||||
}
|
}
|
||||||
newValue[configKey] = value;
|
newValue[configKey] = value;
|
||||||
await vscode.workspace.getConfiguration().update(EXTENSION_CONFIG_KEY, newValue, scope);
|
await vscode.workspace.getConfiguration().update(EXTENSION_CONFIG_KEY, newValue, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addValueToConfigArray(configKey: string, value: string): Promise<void> {
|
async function addValueToConfigArray(configKey: string, value: string): Promise<void> {
|
||||||
await atAllConfigScopes(addValueToConfigArrayAtScope, configKey, value);
|
await atAllConfigScopes(addValueToConfigArrayAtScope, configKey, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addValueToConfigArrayAtScope(configKey: string, value: string, scope: vscode.ConfigurationTarget, valueAtScope: any, createIfNotExist: boolean): Promise<void> {
|
async function addValueToConfigArrayAtScope(configKey: string, value: string, scope: vscode.ConfigurationTarget, valueAtScope: any, createIfNotExist: boolean): Promise<void> {
|
||||||
if (!createIfNotExist) {
|
if (!createIfNotExist) {
|
||||||
if (!valueAtScope || !(valueAtScope[configKey])) {
|
if (!valueAtScope || !(valueAtScope[configKey])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let newValue: any = {};
|
let newValue: any = {};
|
||||||
if (valueAtScope) {
|
if (valueAtScope) {
|
||||||
newValue = Object.assign({}, valueAtScope);
|
newValue = Object.assign({}, valueAtScope);
|
||||||
}
|
}
|
||||||
const arrayEntry: string[] = newValue[configKey] || [];
|
const arrayEntry: string[] = newValue[configKey] || [];
|
||||||
arrayEntry.push(value);
|
arrayEntry.push(value);
|
||||||
newValue[configKey] = arrayEntry;
|
newValue[configKey] = arrayEntry;
|
||||||
await vscode.workspace.getConfiguration().update(EXTENSION_CONFIG_KEY, newValue, scope);
|
await vscode.workspace.getConfiguration().update(EXTENSION_CONFIG_KEY, newValue, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigUpdater<T> = (configKey: string, value: T, scope: vscode.ConfigurationTarget, valueAtScope: any, createIfNotExist: boolean) => Promise<void>;
|
type ConfigUpdater<T> = (configKey: string, value: T, scope: vscode.ConfigurationTarget, valueAtScope: any, createIfNotExist: boolean) => Promise<void>;
|
||||||
|
|
||||||
async function atAllConfigScopes<T>(fn: ConfigUpdater<T>, configKey: string, value: T): Promise<void> {
|
async function atAllConfigScopes<T>(fn: ConfigUpdater<T>, configKey: string, value: T): Promise<void> {
|
||||||
const config = vscode.workspace.getConfiguration().inspect(EXTENSION_CONFIG_KEY)!;
|
const config = vscode.workspace.getConfiguration().inspect(EXTENSION_CONFIG_KEY)!;
|
||||||
await fn(configKey, value, vscode.ConfigurationTarget.Global, config.globalValue, true);
|
await fn(configKey, value, vscode.ConfigurationTarget.Global, config.globalValue, true);
|
||||||
await fn(configKey, value, vscode.ConfigurationTarget.Workspace, config.workspaceValue, false);
|
await fn(configKey, value, vscode.ConfigurationTarget.Workspace, config.workspaceValue, false);
|
||||||
await fn(configKey, value, vscode.ConfigurationTarget.WorkspaceFolder, config.workspaceFolderValue, false);
|
await fn(configKey, value, vscode.ConfigurationTarget.WorkspaceFolder, config.workspaceFolderValue, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions for working with the list of known kubeconfigs
|
// Functions for working with the list of known kubeconfigs
|
||||||
|
|
||||||
export function getKnownKubeconfigs(): string[] {
|
export function getKnownKubeconfigs(): string[] {
|
||||||
const kkcConfig = vscode.workspace.getConfiguration(EXTENSION_CONFIG_KEY)[KNOWN_KUBECONFIGS_KEY];
|
const kkcConfig = vscode.workspace.getConfiguration(EXTENSION_CONFIG_KEY)[KNOWN_KUBECONFIGS_KEY];
|
||||||
if (!kkcConfig || !kkcConfig.length) {
|
if (!kkcConfig || !kkcConfig.length) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return kkcConfig as string[];
|
return kkcConfig as string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addKnownKubeconfig(kubeconfigPath: string) {
|
export async function addKnownKubeconfig(kubeconfigPath: string) {
|
||||||
await addValueToConfigArray(KNOWN_KUBECONFIGS_KEY, kubeconfigPath);
|
await addValueToConfigArray(KNOWN_KUBECONFIGS_KEY, kubeconfigPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions for working with the active kubeconfig setting
|
// Functions for working with the active kubeconfig setting
|
||||||
|
|
||||||
export async function setActiveKubeconfig(kubeconfig: string): Promise<void> {
|
export async function setActiveKubeconfig(kubeconfig: string): Promise<void> {
|
||||||
await addPathToConfig(KUBECONFIG_PATH_KEY, kubeconfig);
|
await addPathToConfig(KUBECONFIG_PATH_KEY, kubeconfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getActiveKubeconfig(): string {
|
export function getActiveKubeconfig(): string {
|
||||||
return vscode.workspace.getConfiguration(EXTENSION_CONFIG_KEY)[KUBECONFIG_PATH_KEY];
|
return vscode.workspace.getConfiguration(EXTENSION_CONFIG_KEY)[KUBECONFIG_PATH_KEY];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Functions for working with tool paths
|
// Functions for working with tool paths
|
||||||
|
|
||||||
export function getToolPath(host: Host, shell: Shell, tool: string): string | undefined {
|
export function getToolPath(host: Host, shell: Shell, tool: string): string | undefined {
|
||||||
const baseKey = toolPathBaseKey(tool);
|
const baseKey = toolPathBaseKey(tool);
|
||||||
return getPathSetting(host, shell, baseKey);
|
return getPathSetting(host, shell, baseKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPathSetting(host: Host, shell: Shell, baseKey: string): string | undefined {
|
function getPathSetting(host: Host, shell: Shell, baseKey: string): string | undefined {
|
||||||
const os = shell.platform();
|
const os = shell.platform();
|
||||||
const osOverridePath = host.getConfiguration(EXTENSION_CONFIG_KEY)[osOverrideKey(os, baseKey)];
|
const osOverridePath = host.getConfiguration(EXTENSION_CONFIG_KEY)[osOverrideKey(os, baseKey)];
|
||||||
return osOverridePath || host.getConfiguration(EXTENSION_CONFIG_KEY)[baseKey];
|
return osOverridePath || host.getConfiguration(EXTENSION_CONFIG_KEY)[baseKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toolPathBaseKey(tool: string): string {
|
export function toolPathBaseKey(tool: string): string {
|
||||||
return `mssql-bdc.${tool}-path`;
|
return `mssql-bdc.${tool}-path`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function osOverrideKey(os: Platform, baseKey: string): string {
|
function osOverrideKey(os: Platform, baseKey: string): string {
|
||||||
const osKey = osKeyString(os);
|
const osKey = osKeyString(os);
|
||||||
return osKey ? `${baseKey}.${osKey}` : baseKey; // The 'else' clause should never happen so don't worry that this would result in double-checking a missing base key
|
return osKey ? `${baseKey}.${osKey}` : baseKey; // The 'else' clause should never happen so don't worry that this would result in double-checking a missing base key
|
||||||
}
|
}
|
||||||
|
|
||||||
function osKeyString(os: Platform): string | null {
|
function osKeyString(os: Platform): string | null {
|
||||||
switch (os) {
|
switch (os) {
|
||||||
case Platform.Windows: return 'windows';
|
case Platform.Windows: return 'windows';
|
||||||
case Platform.MacOS: return 'mac';
|
case Platform.MacOS: return 'mac';
|
||||||
case Platform.Linux: return 'linux';
|
case Platform.Linux: return 'linux';
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,36 +10,36 @@ import * as tmp from 'tmp';
|
|||||||
import { succeeded, Errorable } from '../interfaces';
|
import { succeeded, Errorable } from '../interfaces';
|
||||||
|
|
||||||
type DownloadFunc =
|
type DownloadFunc =
|
||||||
(url: string, destination?: string, options?: any)
|
(url: string, destination?: string, options?: any)
|
||||||
=> Promise<Buffer> & stream.Duplex; // Stream has additional events - see https://www.npmjs.com/package/download
|
=> Promise<Buffer> & stream.Duplex; // Stream has additional events - see https://www.npmjs.com/package/download
|
||||||
|
|
||||||
let download: DownloadFunc;
|
let download: DownloadFunc;
|
||||||
|
|
||||||
function ensureDownloadFunc() {
|
function ensureDownloadFunc() {
|
||||||
if (!download) {
|
if (!download) {
|
||||||
const home = process.env['HOME'];
|
const home = process.env['HOME'];
|
||||||
download = require('download');
|
download = require('download');
|
||||||
if (home) {
|
if (home) {
|
||||||
process.env['HOME'] = home;
|
process.env['HOME'] = home;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function toTempFile(sourceUrl: string): Promise<Errorable<string>> {
|
export async function toTempFile(sourceUrl: string): Promise<Errorable<string>> {
|
||||||
const tempFileObj = tmp.fileSync({ prefix: 'mssql-bdc-autoinstall-' });
|
const tempFileObj = tmp.fileSync({ prefix: 'mssql-bdc-autoinstall-' });
|
||||||
const downloadResult = await to(sourceUrl, tempFileObj.name);
|
const downloadResult = await to(sourceUrl, tempFileObj.name);
|
||||||
if (succeeded(downloadResult)) {
|
if (succeeded(downloadResult)) {
|
||||||
return { succeeded: true, result: tempFileObj.name };
|
return { succeeded: true, result: tempFileObj.name };
|
||||||
}
|
}
|
||||||
return { succeeded: false, error: downloadResult.error };
|
return { succeeded: false, error: downloadResult.error };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function to(sourceUrl: string, destinationFile: string): Promise<Errorable<null>> {
|
export async function to(sourceUrl: string, destinationFile: string): Promise<Errorable<null>> {
|
||||||
ensureDownloadFunc();
|
ensureDownloadFunc();
|
||||||
try {
|
try {
|
||||||
await download(sourceUrl, path.dirname(destinationFile), { filename: path.basename(destinationFile) });
|
await download(sourceUrl, path.dirname(destinationFile), { filename: path.basename(destinationFile) });
|
||||||
return { succeeded: true, result: null };
|
return { succeeded: true, result: null };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return { succeeded: false, error: [e.message] };
|
return { succeeded: false, error: [e.message] };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,57 +16,57 @@ import { Errorable, failed } from '../interfaces';
|
|||||||
import { addPathToConfig, toolPathBaseKey } from '../config/config';
|
import { addPathToConfig, toolPathBaseKey } from '../config/config';
|
||||||
|
|
||||||
export async function installKubectl(shell: Shell): Promise<Errorable<null>> {
|
export async function installKubectl(shell: Shell): Promise<Errorable<null>> {
|
||||||
const tool = 'kubectl';
|
const tool = 'kubectl';
|
||||||
const binFile = (shell.isUnix()) ? 'kubectl' : 'kubectl.exe';
|
const binFile = (shell.isUnix()) ? 'kubectl' : 'kubectl.exe';
|
||||||
const os = platformUrlString(shell.platform());
|
const os = platformUrlString(shell.platform());
|
||||||
|
|
||||||
const version = await getStableKubectlVersion();
|
const version = await getStableKubectlVersion();
|
||||||
if (failed(version)) {
|
if (failed(version)) {
|
||||||
return { succeeded: false, error: version.error };
|
return { succeeded: false, error: version.error };
|
||||||
}
|
}
|
||||||
|
|
||||||
const installFolder = getInstallFolder(shell, tool);
|
const installFolder = getInstallFolder(shell, tool);
|
||||||
mkdirp.sync(installFolder);
|
mkdirp.sync(installFolder);
|
||||||
|
|
||||||
const kubectlUrl = `https://storage.googleapis.com/kubernetes-release/release/${version.result.trim()}/bin/${os}/amd64/${binFile}`;
|
const kubectlUrl = `https://storage.googleapis.com/kubernetes-release/release/${version.result.trim()}/bin/${os}/amd64/${binFile}`;
|
||||||
const downloadFile = path.join(installFolder, binFile);
|
const downloadFile = path.join(installFolder, binFile);
|
||||||
const downloadResult = await download.to(kubectlUrl, downloadFile);
|
const downloadResult = await download.to(kubectlUrl, downloadFile);
|
||||||
if (failed(downloadResult)) {
|
if (failed(downloadResult)) {
|
||||||
return { succeeded: false, error: [localize('downloadKubectlFailed', 'Failed to download kubectl: {0}', downloadResult.error[0])] };
|
return { succeeded: false, error: [localize('downloadKubectlFailed', 'Failed to download kubectl: {0}', downloadResult.error[0])] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shell.isUnix()) {
|
if (shell.isUnix()) {
|
||||||
fs.chmodSync(downloadFile, '0777');
|
fs.chmodSync(downloadFile, '0777');
|
||||||
}
|
}
|
||||||
|
|
||||||
await addPathToConfig(toolPathBaseKey(tool), downloadFile);
|
await addPathToConfig(toolPathBaseKey(tool), downloadFile);
|
||||||
return { succeeded: true, result: null };
|
return { succeeded: true, result: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getStableKubectlVersion(): Promise<Errorable<string>> {
|
async function getStableKubectlVersion(): Promise<Errorable<string>> {
|
||||||
const downloadResult = await download.toTempFile('https://storage.googleapis.com/kubernetes-release/release/stable.txt');
|
const downloadResult = await download.toTempFile('https://storage.googleapis.com/kubernetes-release/release/stable.txt');
|
||||||
if (failed(downloadResult)) {
|
if (failed(downloadResult)) {
|
||||||
return { succeeded: false, error: [localize('kubectlVersionCheckFailed', 'Failed to establish kubectl stable version: {0}', downloadResult.error[0])] };
|
return { succeeded: false, error: [localize('kubectlVersionCheckFailed', 'Failed to establish kubectl stable version: {0}', downloadResult.error[0])] };
|
||||||
}
|
}
|
||||||
const version = fs.readFileSync(downloadResult.result, 'utf-8');
|
const version = fs.readFileSync(downloadResult.result, 'utf-8');
|
||||||
fs.unlinkSync(downloadResult.result);
|
fs.unlinkSync(downloadResult.result);
|
||||||
return { succeeded: true, result: version };
|
return { succeeded: true, result: version };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getInstallFolder(shell: Shell, tool: string): string {
|
export function getInstallFolder(shell: Shell, tool: string): string {
|
||||||
return path.join(shell.home(), `.mssql-bdc/tools/${tool}`);
|
return path.join(shell.home(), `.mssql-bdc/tools/${tool}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function platformUrlString(platform: Platform, supported?: Platform[]): string | null {
|
function platformUrlString(platform: Platform, supported?: Platform[]): string | null {
|
||||||
if (supported && supported.indexOf(platform) < 0) {
|
if (supported && supported.indexOf(platform) < 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case Platform.Windows: return 'windows';
|
case Platform.Windows: return 'windows';
|
||||||
case Platform.MacOS: return 'darwin';
|
case Platform.MacOS: return 'darwin';
|
||||||
case Platform.Linux: return 'linux';
|
case Platform.Linux: return 'linux';
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
import { Shell } from '../utility/shell';
|
import { Shell } from '../utility/shell';
|
||||||
@@ -11,111 +11,111 @@ import { Host } from './host';
|
|||||||
import { FS } from '../utility/fs';
|
import { FS } from '../utility/fs';
|
||||||
|
|
||||||
export interface BinCheckContext {
|
export interface BinCheckContext {
|
||||||
readonly host: Host;
|
readonly host: Host;
|
||||||
readonly fs: FS;
|
readonly fs: FS;
|
||||||
readonly shell: Shell;
|
readonly shell: Shell;
|
||||||
readonly installDependenciesCallback: () => void;
|
readonly installDependenciesCallback: () => void;
|
||||||
binFound: boolean;
|
binFound: boolean;
|
||||||
binPath: string;
|
binPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FindBinaryResult {
|
interface FindBinaryResult {
|
||||||
err: number | null;
|
err: number | null;
|
||||||
output: string;
|
output: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findBinary(shell: Shell, binName: string): Promise<FindBinaryResult> {
|
async function findBinary(shell: Shell, binName: string): Promise<FindBinaryResult> {
|
||||||
let cmd = `which ${binName}`;
|
let cmd = `which ${binName}`;
|
||||||
|
|
||||||
if (shell.isWindows()) {
|
if (shell.isWindows()) {
|
||||||
cmd = `where.exe ${binName}.exe`;
|
cmd = `where.exe ${binName}.exe`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const opts = {
|
const opts = {
|
||||||
async: true,
|
async: true,
|
||||||
env: {
|
env: {
|
||||||
HOME: process.env.HOME,
|
HOME: process.env.HOME,
|
||||||
PATH: process.env.PATH
|
PATH: process.env.PATH
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const execResult = await shell.execCore(cmd, opts);
|
const execResult = await shell.execCore(cmd, opts);
|
||||||
if (execResult.code) {
|
if (execResult.code) {
|
||||||
return { err: execResult.code, output: execResult.stderr };
|
return { err: execResult.code, output: execResult.stderr };
|
||||||
}
|
}
|
||||||
|
|
||||||
return { err: null, output: execResult.stdout };
|
return { err: null, output: execResult.stdout };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function execPath(shell: Shell, basePath: string): string {
|
export function execPath(shell: Shell, basePath: string): string {
|
||||||
let bin = basePath;
|
let bin = basePath;
|
||||||
if (shell.isWindows() && bin && !(bin.endsWith('.exe'))) {
|
if (shell.isWindows() && bin && !(bin.endsWith('.exe'))) {
|
||||||
bin = bin + '.exe';
|
bin = bin + '.exe';
|
||||||
}
|
}
|
||||||
return bin;
|
return bin;
|
||||||
}
|
}
|
||||||
|
|
||||||
type CheckPresentFailureReason = 'inferFailed' | 'configuredFileMissing';
|
type CheckPresentFailureReason = 'inferFailed' | 'configuredFileMissing';
|
||||||
const installDependenciesAction = localize('installDependenciesAction','Install dependencies');
|
const installDependenciesAction = localize('installDependenciesAction', 'Install dependencies');
|
||||||
const learnMoreAction = localize('learnMoreAction','Learn more');
|
const learnMoreAction = localize('learnMoreAction', 'Learn more');
|
||||||
function alertNoBin(host: Host, binName: string, failureReason: CheckPresentFailureReason, message: string, installDependencies: () => void): void {
|
function alertNoBin(host: Host, binName: string, failureReason: CheckPresentFailureReason, message: string, installDependencies: () => void): void {
|
||||||
switch (failureReason) {
|
switch (failureReason) {
|
||||||
case 'inferFailed':
|
case 'inferFailed':
|
||||||
host.showErrorMessage(message, installDependenciesAction, learnMoreAction).then(
|
host.showErrorMessage(message, installDependenciesAction, learnMoreAction).then(
|
||||||
(str) => {
|
(str) => {
|
||||||
switch (str) {
|
switch (str) {
|
||||||
case learnMoreAction:
|
case learnMoreAction:
|
||||||
host.showInformationMessage(localize('moreInfoMsg', 'Add {0} directory to path, or set "mssql-bdc.{0}-path" config to {0} binary.', binName));
|
host.showInformationMessage(localize('moreInfoMsg', 'Add {0} directory to path, or set "mssql-bdc.{0}-path" config to {0} binary.', binName));
|
||||||
break;
|
break;
|
||||||
case installDependenciesAction:
|
case installDependenciesAction:
|
||||||
installDependencies();
|
installDependencies();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'configuredFileMissing':
|
case 'configuredFileMissing':
|
||||||
host.showErrorMessage(message, installDependenciesAction).then(
|
host.showErrorMessage(message, installDependenciesAction).then(
|
||||||
(str) => {
|
(str) => {
|
||||||
if (str === installDependenciesAction) {
|
if (str === installDependenciesAction) {
|
||||||
installDependencies();
|
installDependencies();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkForBinary(context: BinCheckContext, bin: string | undefined, binName: string, inferFailedMessage: string, configuredFileMissingMessage: string, alertOnFail: boolean): Promise<boolean> {
|
export async function checkForBinary(context: BinCheckContext, bin: string | undefined, binName: string, inferFailedMessage: string, configuredFileMissingMessage: string, alertOnFail: boolean): Promise<boolean> {
|
||||||
if (!bin) {
|
if (!bin) {
|
||||||
const fb = await findBinary(context.shell, binName);
|
const fb = await findBinary(context.shell, binName);
|
||||||
|
|
||||||
if (fb.err || fb.output.length === 0) {
|
if (fb.err || fb.output.length === 0) {
|
||||||
if (alertOnFail) {
|
if (alertOnFail) {
|
||||||
alertNoBin(context.host, binName, 'inferFailed', inferFailedMessage, context.installDependenciesCallback);
|
alertNoBin(context.host, binName, 'inferFailed', inferFailedMessage, context.installDependenciesCallback);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
context.binFound = true;
|
context.binFound = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.shell.isWindows) {
|
if (context.shell.isWindows) {
|
||||||
context.binFound = context.fs.existsSync(bin);
|
context.binFound = context.fs.existsSync(bin);
|
||||||
} else {
|
} else {
|
||||||
const sr = await context.shell.exec(`ls ${bin}`);
|
const sr = await context.shell.exec(`ls ${bin}`);
|
||||||
context.binFound = (!!sr && sr.code === 0);
|
context.binFound = (!!sr && sr.code === 0);
|
||||||
}
|
}
|
||||||
if (context.binFound) {
|
if (context.binFound) {
|
||||||
context.binPath = bin;
|
context.binPath = bin;
|
||||||
} else {
|
} else {
|
||||||
if (alertOnFail) {
|
if (alertOnFail) {
|
||||||
alertNoBin(context.host, binName, 'configuredFileMissing', configuredFileMissingMessage, context.installDependenciesCallback);
|
alertNoBin(context.host, binName, 'configuredFileMissing', configuredFileMissingMessage, context.installDependenciesCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return context.binFound;
|
return context.binFound;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,61 +6,61 @@
|
|||||||
import { Errorable, failed } from '../interfaces';
|
import { Errorable, failed } from '../interfaces';
|
||||||
|
|
||||||
interface CompatibilityGuaranteed {
|
interface CompatibilityGuaranteed {
|
||||||
readonly guaranteed: true;
|
readonly guaranteed: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CompatibilityNotGuaranteed {
|
interface CompatibilityNotGuaranteed {
|
||||||
readonly guaranteed: false;
|
readonly guaranteed: false;
|
||||||
readonly didCheck: boolean;
|
readonly didCheck: boolean;
|
||||||
readonly clientVersion: string;
|
readonly clientVersion: string;
|
||||||
readonly serverVersion: string;
|
readonly serverVersion: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Compatibility = CompatibilityGuaranteed | CompatibilityNotGuaranteed;
|
export type Compatibility = CompatibilityGuaranteed | CompatibilityNotGuaranteed;
|
||||||
|
|
||||||
export function isGuaranteedCompatible(c: Compatibility): c is CompatibilityGuaranteed {
|
export function isGuaranteedCompatible(c: Compatibility): c is CompatibilityGuaranteed {
|
||||||
return c.guaranteed;
|
return c.guaranteed;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Version {
|
export interface Version {
|
||||||
readonly major: string;
|
readonly major: string;
|
||||||
readonly minor: string;
|
readonly minor: string;
|
||||||
readonly gitVersion: string;
|
readonly gitVersion: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function check(kubectlLoadJSON: (cmd: string) => Promise<Errorable<any>>): Promise<Compatibility> {
|
export async function check(kubectlLoadJSON: (cmd: string) => Promise<Errorable<any>>): Promise<Compatibility> {
|
||||||
const version = await kubectlLoadJSON('version -o json');
|
const version = await kubectlLoadJSON('version -o json');
|
||||||
if (failed(version)) {
|
if (failed(version)) {
|
||||||
return {
|
return {
|
||||||
guaranteed: false,
|
guaranteed: false,
|
||||||
didCheck: false,
|
didCheck: false,
|
||||||
clientVersion: '',
|
clientVersion: '',
|
||||||
serverVersion: ''
|
serverVersion: ''
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const clientVersion: Version = version.result.clientVersion;
|
const clientVersion: Version = version.result.clientVersion;
|
||||||
const serverVersion: Version = version.result.serverVersion;
|
const serverVersion: Version = version.result.serverVersion;
|
||||||
|
|
||||||
if (isCompatible(clientVersion, serverVersion)) {
|
if (isCompatible(clientVersion, serverVersion)) {
|
||||||
return { guaranteed: true };
|
return { guaranteed: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
guaranteed: false,
|
guaranteed: false,
|
||||||
didCheck: true,
|
didCheck: true,
|
||||||
clientVersion: clientVersion.gitVersion,
|
clientVersion: clientVersion.gitVersion,
|
||||||
serverVersion: serverVersion.gitVersion
|
serverVersion: serverVersion.gitVersion
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCompatible(clientVersion: Version, serverVersion: Version): boolean {
|
function isCompatible(clientVersion: Version, serverVersion: Version): boolean {
|
||||||
if (clientVersion.major === serverVersion.major) {
|
if (clientVersion.major === serverVersion.major) {
|
||||||
const clientMinor = Number.parseInt(clientVersion.minor);
|
const clientMinor = Number.parseInt(clientVersion.minor);
|
||||||
const serverMinor = Number.parseInt(serverVersion.minor);
|
const serverMinor = Number.parseInt(serverVersion.minor);
|
||||||
if (Number.isInteger(clientMinor) && Number.isInteger(serverMinor) && Math.abs(clientMinor - serverMinor) <= 1) {
|
if (Number.isInteger(clientMinor) && Number.isInteger(serverMinor) && Math.abs(clientMinor - serverMinor) <= 1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,37 +6,37 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
export interface Host {
|
export interface Host {
|
||||||
showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined>;
|
showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined>;
|
||||||
showWarningMessage(message: string, ...items: string[]): Thenable<string | undefined>;
|
showWarningMessage(message: string, ...items: string[]): Thenable<string | undefined>;
|
||||||
showInformationMessage(message: string, ...items: string[]): Thenable<string | undefined>;
|
showInformationMessage(message: string, ...items: string[]): Thenable<string | undefined>;
|
||||||
getConfiguration(key: string): any;
|
getConfiguration(key: string): any;
|
||||||
onDidChangeConfiguration(listener: (ch: vscode.ConfigurationChangeEvent) => any): vscode.Disposable;
|
onDidChangeConfiguration(listener: (ch: vscode.ConfigurationChangeEvent) => any): vscode.Disposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const host: Host = {
|
export const host: Host = {
|
||||||
showErrorMessage : showErrorMessage,
|
showErrorMessage: showErrorMessage,
|
||||||
showWarningMessage : showWarningMessage,
|
showWarningMessage: showWarningMessage,
|
||||||
showInformationMessage : showInformationMessage,
|
showInformationMessage: showInformationMessage,
|
||||||
getConfiguration : getConfiguration,
|
getConfiguration: getConfiguration,
|
||||||
onDidChangeConfiguration : onDidChangeConfiguration,
|
onDidChangeConfiguration: onDidChangeConfiguration,
|
||||||
};
|
};
|
||||||
|
|
||||||
function showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
function showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
||||||
return vscode.window.showErrorMessage(message, ...items);
|
return vscode.window.showErrorMessage(message, ...items);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showWarningMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
function showWarningMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
||||||
return vscode.window.showWarningMessage(message, ...items);
|
return vscode.window.showWarningMessage(message, ...items);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showInformationMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
function showInformationMessage(message: string, ...items: string[]): Thenable<string | undefined> {
|
||||||
return vscode.window.showInformationMessage(message, ...items);
|
return vscode.window.showInformationMessage(message, ...items);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConfiguration(key: string): any {
|
function getConfiguration(key: string): any {
|
||||||
return vscode.workspace.getConfiguration(key);
|
return vscode.workspace.getConfiguration(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDidChangeConfiguration(listener: (e: vscode.ConfigurationChangeEvent) => any): vscode.Disposable {
|
function onDidChangeConfiguration(listener: (e: vscode.ConfigurationChangeEvent) => any): vscode.Disposable {
|
||||||
return vscode.workspace.onDidChangeConfiguration(listener);
|
return vscode.workspace.onDidChangeConfiguration(listener);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,128 +15,128 @@ import * as compatibility from './compatibility';
|
|||||||
import { getToolPath } from '../config/config';
|
import { getToolPath } from '../config/config';
|
||||||
|
|
||||||
export interface Kubectl {
|
export interface Kubectl {
|
||||||
checkPresent(errorMessageMode: CheckPresentMessageMode): Promise<boolean>;
|
checkPresent(errorMessageMode: CheckPresentMessageMode): Promise<boolean>;
|
||||||
asJson<T>(command: string): Promise<Errorable<T>>;
|
asJson<T>(command: string): Promise<Errorable<T>>;
|
||||||
invokeAsync(command: string, stdin?: string): Promise<ShellResult | undefined>;
|
invokeAsync(command: string, stdin?: string): Promise<ShellResult | undefined>;
|
||||||
getContext(): Context;
|
getContext(): Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Context {
|
interface Context {
|
||||||
readonly host: Host;
|
readonly host: Host;
|
||||||
readonly fs: FS;
|
readonly fs: FS;
|
||||||
readonly shell: Shell;
|
readonly shell: Shell;
|
||||||
readonly installDependenciesCallback: () => void;
|
readonly installDependenciesCallback: () => void;
|
||||||
binFound: boolean;
|
binFound: boolean;
|
||||||
binPath: string;
|
binPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class KubectlImpl implements Kubectl {
|
class KubectlImpl implements Kubectl {
|
||||||
constructor(host: Host, fs: FS, shell: Shell, installDependenciesCallback: () => void, kubectlFound: boolean) {
|
constructor(host: Host, fs: FS, shell: Shell, installDependenciesCallback: () => void, kubectlFound: boolean) {
|
||||||
this.context = { host : host, fs : fs, shell : shell, installDependenciesCallback : installDependenciesCallback, binFound : kubectlFound, binPath : 'kubectl' };
|
this.context = { host: host, fs: fs, shell: shell, installDependenciesCallback: installDependenciesCallback, binFound: kubectlFound, binPath: 'kubectl' };
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly context: Context;
|
readonly context: Context;
|
||||||
|
|
||||||
checkPresent(errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
|
checkPresent(errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
|
||||||
return checkPresent(this.context, errorMessageMode);
|
return checkPresent(this.context, errorMessageMode);
|
||||||
}
|
}
|
||||||
asJson<T>(command: string): Promise<Errorable<T>> {
|
asJson<T>(command: string): Promise<Errorable<T>> {
|
||||||
return asJson(this.context, command);
|
return asJson(this.context, command);
|
||||||
}
|
}
|
||||||
invokeAsync(command: string, stdin?: string): Promise<ShellResult | undefined> {
|
invokeAsync(command: string, stdin?: string): Promise<ShellResult | undefined> {
|
||||||
return invokeAsync(this.context, command, stdin);
|
return invokeAsync(this.context, command, stdin);
|
||||||
}
|
}
|
||||||
|
|
||||||
getContext(): Context {
|
getContext(): Context {
|
||||||
return this.context;
|
return this.context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function create(host: Host, fs: FS, shell: Shell, installDependenciesCallback: () => void): Kubectl {
|
export function create(host: Host, fs: FS, shell: Shell, installDependenciesCallback: () => void): Kubectl {
|
||||||
return new KubectlImpl(host, fs, shell, installDependenciesCallback, false);
|
return new KubectlImpl(host, fs, shell, installDependenciesCallback, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CheckPresentMessageMode {
|
export enum CheckPresentMessageMode {
|
||||||
Command,
|
Command,
|
||||||
Activation,
|
Activation,
|
||||||
Silent,
|
Silent,
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkPresent(context: Context, errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
|
async function checkPresent(context: Context, errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
|
||||||
if (context.binFound) {
|
if (context.binFound) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await checkForKubectlInternal(context, errorMessageMode);
|
return await checkForKubectlInternal(context, errorMessageMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkForKubectlInternal(context: Context, errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
|
async function checkForKubectlInternal(context: Context, errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
|
||||||
const binName = 'kubectl';
|
const binName = 'kubectl';
|
||||||
const bin = getToolPath(context.host, context.shell, binName);
|
const bin = getToolPath(context.host, context.shell, binName);
|
||||||
|
|
||||||
const contextMessage = getCheckKubectlContextMessage(errorMessageMode);
|
const contextMessage = getCheckKubectlContextMessage(errorMessageMode);
|
||||||
const inferFailedMessage = localize('binaryNotFound', 'Could not find {0} binary. {1}', binName, contextMessage);
|
const inferFailedMessage = localize('binaryNotFound', 'Could not find {0} binary. {1}', binName, contextMessage);
|
||||||
const configuredFileMissingMessage = localize('binaryNotInstalled', '{0} is not installed. {1}', bin, contextMessage);
|
const configuredFileMissingMessage = localize('binaryNotInstalled', '{0} is not installed. {1}', bin, contextMessage);
|
||||||
|
|
||||||
return await binutil.checkForBinary(context, bin, binName, inferFailedMessage, configuredFileMissingMessage, errorMessageMode !== CheckPresentMessageMode.Silent);
|
return await binutil.checkForBinary(context, bin, binName, inferFailedMessage, configuredFileMissingMessage, errorMessageMode !== CheckPresentMessageMode.Silent);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCheckKubectlContextMessage(errorMessageMode: CheckPresentMessageMode): string {
|
function getCheckKubectlContextMessage(errorMessageMode: CheckPresentMessageMode): string {
|
||||||
if (errorMessageMode === CheckPresentMessageMode.Activation) {
|
if (errorMessageMode === CheckPresentMessageMode.Activation) {
|
||||||
return localize('kubernetesRequired',' SQL Server Big data cluster requires kubernetes.');
|
return localize('kubernetesRequired', ' SQL Server Big data cluster requires kubernetes.');
|
||||||
} else if (errorMessageMode === CheckPresentMessageMode.Command) {
|
} else if (errorMessageMode === CheckPresentMessageMode.Command) {
|
||||||
return localize('cannotExecuteCmd', ' Cannot execute command.');
|
return localize('cannotExecuteCmd', ' Cannot execute command.');
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function invokeAsync(context: Context, command: string, stdin?: string): Promise<ShellResult | undefined> {
|
async function invokeAsync(context: Context, command: string, stdin?: string): Promise<ShellResult | undefined> {
|
||||||
if (await checkPresent(context, CheckPresentMessageMode.Command)) {
|
if (await checkPresent(context, CheckPresentMessageMode.Command)) {
|
||||||
const bin = baseKubectlPath(context);
|
const bin = baseKubectlPath(context);
|
||||||
const cmd = `${bin} ${command}`;
|
const cmd = `${bin} ${command}`;
|
||||||
const sr = await context.shell.exec(cmd, stdin);
|
const sr = await context.shell.exec(cmd, stdin);
|
||||||
if (sr && sr.code !== 0) {
|
if (sr && sr.code !== 0) {
|
||||||
checkPossibleIncompatibility(context);
|
checkPossibleIncompatibility(context);
|
||||||
}
|
}
|
||||||
return sr;
|
return sr;
|
||||||
} else {
|
} else {
|
||||||
return { code: -1, stdout: '', stderr: '' };
|
return { code: -1, stdout: '', stderr: '' };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: invalidate this when the context changes or if we know kubectl has changed (e.g. config)
|
// TODO: invalidate this when the context changes or if we know kubectl has changed (e.g. config)
|
||||||
let checkedCompatibility = false; // We don't want to spam the user (or CPU!) repeatedly running the version check
|
let checkedCompatibility = false; // We don't want to spam the user (or CPU!) repeatedly running the version check
|
||||||
|
|
||||||
async function checkPossibleIncompatibility(context: Context): Promise<void> {
|
async function checkPossibleIncompatibility(context: Context): Promise<void> {
|
||||||
if (checkedCompatibility) {
|
if (checkedCompatibility) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
checkedCompatibility = true;
|
checkedCompatibility = true;
|
||||||
const compat = await compatibility.check((cmd) => asJson<compatibility.Version>(context, cmd));
|
const compat = await compatibility.check((cmd) => asJson<compatibility.Version>(context, cmd));
|
||||||
if (!compatibility.isGuaranteedCompatible(compat) && compat.didCheck) {
|
if (!compatibility.isGuaranteedCompatible(compat) && compat.didCheck) {
|
||||||
const versionAlert = localize('kubectlVersionIncompatible', 'kubectl version ${0} may be incompatible with cluster Kubernetes version {1}', compat.clientVersion, compat.serverVersion);
|
const versionAlert = localize('kubectlVersionIncompatible', 'kubectl version ${0} may be incompatible with cluster Kubernetes version {1}', compat.clientVersion, compat.serverVersion);
|
||||||
context.host.showWarningMessage(versionAlert);
|
context.host.showWarningMessage(versionAlert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function baseKubectlPath(context: Context): string {
|
export function baseKubectlPath(context: Context): string {
|
||||||
let bin = getToolPath(context.host, context.shell, 'kubectl');
|
let bin = getToolPath(context.host, context.shell, 'kubectl');
|
||||||
if (!bin) {
|
if (!bin) {
|
||||||
bin = 'kubectl';
|
bin = 'kubectl';
|
||||||
}
|
}
|
||||||
return bin;
|
return bin;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function asJson<T>(context: Context, command: string): Promise<Errorable<T>> {
|
async function asJson<T>(context: Context, command: string): Promise<Errorable<T>> {
|
||||||
const shellResult = await invokeAsync(context, command);
|
const shellResult = await invokeAsync(context, command);
|
||||||
if (!shellResult) {
|
if (!shellResult) {
|
||||||
return { succeeded: false, error: [localize('cannotRunCommand', 'Unable to run command ({0})', command)] };
|
return { succeeded: false, error: [localize('cannotRunCommand', 'Unable to run command ({0})', command)] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shellResult.code === 0) {
|
if (shellResult.code === 0) {
|
||||||
return { succeeded: true, result: JSON.parse(shellResult.stdout.trim()) as T };
|
return { succeeded: true, result: JSON.parse(shellResult.stdout.trim()) as T };
|
||||||
|
|
||||||
}
|
}
|
||||||
return { succeeded: false, error: [ shellResult.stderr ] };
|
return { succeeded: false, error: [shellResult.stderr] };
|
||||||
}
|
}
|
||||||
@@ -11,126 +11,126 @@ import { Kubectl } from './kubectl';
|
|||||||
import { failed, ClusterType } from '../interfaces';
|
import { failed, ClusterType } from '../interfaces';
|
||||||
|
|
||||||
export interface KubectlContext {
|
export interface KubectlContext {
|
||||||
readonly clusterName: string;
|
readonly clusterName: string;
|
||||||
readonly contextName: string;
|
readonly contextName: string;
|
||||||
readonly userName: string;
|
readonly userName: string;
|
||||||
readonly active: boolean;
|
readonly active: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Kubeconfig {
|
interface Kubeconfig {
|
||||||
readonly apiVersion: string;
|
readonly apiVersion: string;
|
||||||
readonly 'current-context': string;
|
readonly 'current-context': string;
|
||||||
readonly clusters: {
|
readonly clusters: {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
readonly cluster: {
|
readonly cluster: {
|
||||||
readonly server: string;
|
readonly server: string;
|
||||||
readonly 'certificate-authority'?: string;
|
readonly 'certificate-authority'?: string;
|
||||||
readonly 'certificate-authority-data'?: string;
|
readonly 'certificate-authority-data'?: string;
|
||||||
};
|
};
|
||||||
}[] | undefined;
|
}[] | undefined;
|
||||||
readonly contexts: {
|
readonly contexts: {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
readonly context: {
|
readonly context: {
|
||||||
readonly cluster: string;
|
readonly cluster: string;
|
||||||
readonly user: string;
|
readonly user: string;
|
||||||
readonly namespace?: string;
|
readonly namespace?: string;
|
||||||
};
|
};
|
||||||
}[] | undefined;
|
}[] | undefined;
|
||||||
readonly users: {
|
readonly users: {
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
readonly user: {};
|
readonly user: {};
|
||||||
}[] | undefined;
|
}[] | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClusterConfig {
|
export interface ClusterConfig {
|
||||||
readonly server: string;
|
readonly server: string;
|
||||||
readonly certificateAuthority: string | undefined;
|
readonly certificateAuthority: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function getKubeconfig(kubectl: Kubectl): Promise<Kubeconfig | null> {
|
async function getKubeconfig(kubectl: Kubectl): Promise<Kubeconfig | null> {
|
||||||
const shellResult = await kubectl.asJson<any>('config view -o json');
|
const shellResult = await kubectl.asJson<any>('config view -o json');
|
||||||
if (failed(shellResult)) {
|
if (failed(shellResult)) {
|
||||||
vscode.window.showErrorMessage(shellResult.error[0]);
|
vscode.window.showErrorMessage(shellResult.error[0]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return shellResult.result;
|
return shellResult.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCurrentClusterConfig(kubectl: Kubectl): Promise<ClusterConfig | undefined> {
|
export async function getCurrentClusterConfig(kubectl: Kubectl): Promise<ClusterConfig | undefined> {
|
||||||
const kubeConfig = await getKubeconfig(kubectl);
|
const kubeConfig = await getKubeconfig(kubectl);
|
||||||
if (!kubeConfig || !kubeConfig.clusters || !kubeConfig.contexts) {
|
if (!kubeConfig || !kubeConfig.clusters || !kubeConfig.contexts) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const contextConfig = kubeConfig.contexts.find((context) => context.name === kubeConfig['current-context'])!;
|
const contextConfig = kubeConfig.contexts.find((context) => context.name === kubeConfig['current-context'])!;
|
||||||
const clusterConfig = kubeConfig.clusters.find((cluster) => cluster.name === contextConfig.context.cluster)!;
|
const clusterConfig = kubeConfig.clusters.find((cluster) => cluster.name === contextConfig.context.cluster)!;
|
||||||
return {
|
return {
|
||||||
server: clusterConfig.cluster.server,
|
server: clusterConfig.cluster.server,
|
||||||
certificateAuthority: clusterConfig.cluster['certificate-authority']
|
certificateAuthority: clusterConfig.cluster['certificate-authority']
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getContexts(kubectl: Kubectl): Promise<KubectlContext[]> {
|
export async function getContexts(kubectl: Kubectl): Promise<KubectlContext[]> {
|
||||||
const kubectlConfig = await getKubeconfig(kubectl);
|
const kubectlConfig = await getKubeconfig(kubectl);
|
||||||
if (!kubectlConfig) {
|
if (!kubectlConfig) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const currentContext = kubectlConfig['current-context'];
|
const currentContext = kubectlConfig['current-context'];
|
||||||
const contexts = kubectlConfig.contexts || [];
|
const contexts = kubectlConfig.contexts || [];
|
||||||
return contexts.map((c) => {
|
return contexts.map((c) => {
|
||||||
return {
|
return {
|
||||||
clusterName: c.context.cluster,
|
clusterName: c.context.cluster,
|
||||||
contextName: c.name,
|
contextName: c.name,
|
||||||
userName: c.context.user,
|
userName: c.context.user,
|
||||||
active: c.name === currentContext
|
active: c.name === currentContext
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setContext(kubectl: Kubectl, targetContext: string): Promise<void> {
|
export async function setContext(kubectl: Kubectl, targetContext: string): Promise<void> {
|
||||||
const shellResult = await kubectl.invokeAsync(`config use-context ${targetContext}`);
|
const shellResult = await kubectl.invokeAsync(`config use-context ${targetContext}`);
|
||||||
if (!shellResult || shellResult.code !== 0) {
|
if (!shellResult || shellResult.code !== 0) {
|
||||||
// TODO: Update error handling for now.
|
// TODO: Update error handling for now.
|
||||||
let errMsg = shellResult ? shellResult.stderr : localize('runKubectlFailed', 'Unable to run kubectl');
|
let errMsg = shellResult ? shellResult.stderr : localize('runKubectlFailed', 'Unable to run kubectl');
|
||||||
vscode.window.showErrorMessage(localize('setClusterFailed', 'Failed to set \'{0}\' as current cluster: {1}', targetContext, errMsg));
|
vscode.window.showErrorMessage(localize('setClusterFailed', 'Failed to set \'{0}\' as current cluster: {1}', targetContext, errMsg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function inferCurrentClusterType(kubectl: Kubectl): Promise<ClusterType> {
|
export async function inferCurrentClusterType(kubectl: Kubectl): Promise<ClusterType> {
|
||||||
let latestContextName = '';
|
let latestContextName = '';
|
||||||
|
|
||||||
const ctxsr = await kubectl.invokeAsync('config current-context');
|
const ctxsr = await kubectl.invokeAsync('config current-context');
|
||||||
if (ctxsr && ctxsr.code === 0) {
|
if (ctxsr && ctxsr.code === 0) {
|
||||||
latestContextName = ctxsr.stdout.trim();
|
latestContextName = ctxsr.stdout.trim();
|
||||||
} else {
|
} else {
|
||||||
return ClusterType.Other;
|
return ClusterType.Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cisr = await kubectl.invokeAsync('cluster-info');
|
const cisr = await kubectl.invokeAsync('cluster-info');
|
||||||
if (!cisr || cisr.code !== 0) {
|
if (!cisr || cisr.code !== 0) {
|
||||||
return ClusterType.Unknown;
|
return ClusterType.Unknown;
|
||||||
}
|
}
|
||||||
const masterInfos = cisr.stdout.split('\n')
|
const masterInfos = cisr.stdout.split('\n')
|
||||||
.filter((s) => s.indexOf('master is running at') >= 0);
|
.filter((s) => s.indexOf('master is running at') >= 0);
|
||||||
|
|
||||||
if (masterInfos.length === 0) {
|
if (masterInfos.length === 0) {
|
||||||
return ClusterType.Other;
|
return ClusterType.Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
const masterInfo = masterInfos[0];
|
const masterInfo = masterInfos[0];
|
||||||
if (masterInfo.indexOf('azmk8s.io') >= 0 || masterInfo.indexOf('azure.com') >= 0) {
|
if (masterInfo.indexOf('azmk8s.io') >= 0 || masterInfo.indexOf('azure.com') >= 0) {
|
||||||
return ClusterType.AKS;
|
return ClusterType.AKS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (latestContextName) {
|
if (latestContextName) {
|
||||||
const gcsr = await kubectl.invokeAsync(`config get-contexts ${latestContextName}`);
|
const gcsr = await kubectl.invokeAsync(`config get-contexts ${latestContextName}`);
|
||||||
if (gcsr && gcsr.code === 0) {
|
if (gcsr && gcsr.code === 0) {
|
||||||
if (gcsr.stdout.indexOf('minikube') >= 0) {
|
if (gcsr.stdout.indexOf('minikube') >= 0) {
|
||||||
return ClusterType.Minikube;
|
return ClusterType.Minikube;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ClusterType.Other;
|
return ClusterType.Other;
|
||||||
}
|
}
|
||||||
@@ -8,22 +8,22 @@ import * as nls from 'vscode-nls';
|
|||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export interface ISqlServerBigDataClusterChannel {
|
export interface ISqlServerBigDataClusterChannel {
|
||||||
showOutput(message: any, title?: string): void;
|
showOutput(message: any, title?: string): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const outputChannelName = localize('bigDataClusterOutputChannel', 'SQL Server big data cluster');
|
const outputChannelName = localize('bigDataClusterOutputChannel', 'SQL Server big data cluster');
|
||||||
class SqlServerBigDataCluster implements ISqlServerBigDataClusterChannel {
|
class SqlServerBigDataCluster implements ISqlServerBigDataClusterChannel {
|
||||||
private readonly channel: vscode.OutputChannel = vscode.window.createOutputChannel(outputChannelName);
|
private readonly channel: vscode.OutputChannel = vscode.window.createOutputChannel(outputChannelName);
|
||||||
|
|
||||||
showOutput(message: any, title?: string): void {
|
showOutput(message: any, title?: string): void {
|
||||||
if (title) {
|
if (title) {
|
||||||
const simplifiedTime = (new Date()).toISOString().replace(/z|t/gi, ' ').trim(); // YYYY-MM-DD HH:mm:ss.sss
|
const simplifiedTime = (new Date()).toISOString().replace(/z|t/gi, ' ').trim(); // YYYY-MM-DD HH:mm:ss.sss
|
||||||
const hightlightingTitle = `[${title} ${simplifiedTime}]`;
|
const hightlightingTitle = `[${title} ${simplifiedTime}]`;
|
||||||
this.channel.appendLine(hightlightingTitle);
|
this.channel.appendLine(hightlightingTitle);
|
||||||
}
|
}
|
||||||
this.channel.appendLine(message);
|
this.channel.appendLine(message);
|
||||||
this.channel.show();
|
this.channel.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sqlserverbigdataclusterchannel: ISqlServerBigDataClusterChannel = new SqlServerBigDataCluster();
|
export const sqlserverbigdataclusterchannel: ISqlServerBigDataClusterChannel = new SqlServerBigDataCluster();
|
||||||
@@ -35,26 +35,26 @@ export function deactivate(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function installDependencies() {
|
export async function installDependencies() {
|
||||||
const gotKubectl = await kubectl.checkPresent(CheckPresentMessageMode.Silent);
|
const gotKubectl = await kubectl.checkPresent(CheckPresentMessageMode.Silent);
|
||||||
|
|
||||||
|
|
||||||
const installPromises = [
|
const installPromises = [
|
||||||
installDependency('kubectl', gotKubectl, installKubectl)
|
installDependency('kubectl', gotKubectl, installKubectl)
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all(installPromises);
|
await Promise.all(installPromises);
|
||||||
|
|
||||||
sqlserverbigdataclusterchannel.showOutput(localize('done', 'Done'));
|
sqlserverbigdataclusterchannel.showOutput(localize('done', 'Done'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function installDependency(name: string, alreadyGot: boolean, installFunc: (shell: Shell) => Promise<Errorable<null>>): Promise<void> {
|
async function installDependency(name: string, alreadyGot: boolean, installFunc: (shell: Shell) => Promise<Errorable<null>>): Promise<void> {
|
||||||
if (alreadyGot) {
|
if (alreadyGot) {
|
||||||
sqlserverbigdataclusterchannel.showOutput(localize('dependencyInstalled', '{0} already installed...', name));
|
sqlserverbigdataclusterchannel.showOutput(localize('dependencyInstalled', '{0} already installed...', name));
|
||||||
} else {
|
} else {
|
||||||
sqlserverbigdataclusterchannel.showOutput(localize('installingDependency', 'Installing {0}...', name));
|
sqlserverbigdataclusterchannel.showOutput(localize('installingDependency', 'Installing {0}...', name));
|
||||||
const result = await installFunc(shell);
|
const result = await installFunc(shell);
|
||||||
if (failed(result)) {
|
if (failed(result)) {
|
||||||
sqlserverbigdataclusterchannel.showOutput(localize('installingDependencyFailed', 'Unable to install {0}: {1}', name, result.error[0]));
|
sqlserverbigdataclusterchannel.showOutput(localize('installingDependencyFailed', 'Unable to install {0}: {1}', name, result.error[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@ import { Kubectl } from './kubectl/kubectl';
|
|||||||
*/
|
*/
|
||||||
export class MainController {
|
export class MainController {
|
||||||
protected _context: vscode.ExtensionContext;
|
protected _context: vscode.ExtensionContext;
|
||||||
protected _kubectl : Kubectl;
|
protected _kubectl: Kubectl;
|
||||||
|
|
||||||
public constructor(context: vscode.ExtensionContext, kubectl: Kubectl) {
|
public constructor(context: vscode.ExtensionContext, kubectl: Kubectl) {
|
||||||
this._context = context;
|
this._context = context;
|
||||||
|
|||||||
@@ -11,16 +11,16 @@ import mkdirp = require('mkdirp');
|
|||||||
import { Kubectl, baseKubectlPath } from '../kubectl/kubectl';
|
import { Kubectl, baseKubectlPath } from '../kubectl/kubectl';
|
||||||
import { KubectlContext } from '../kubectl/kubectlUtils';
|
import { KubectlContext } from '../kubectl/kubectlUtils';
|
||||||
|
|
||||||
export interface Scriptable {
|
export interface Scriptable {
|
||||||
getScriptProperties(): Promise<ScriptingDictionary<string>>;
|
getScriptProperties(): Promise<ScriptingDictionary<string>>;
|
||||||
getTargetKubectlContext() : KubectlContext;
|
getTargetKubectlContext(): KubectlContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScriptingDictionary<V> {
|
export interface ScriptingDictionary<V> {
|
||||||
[name: string]: V;
|
[name: string]: V;
|
||||||
}
|
}
|
||||||
|
|
||||||
const deployFilePrefix : string = 'mssql-bdc-deploy';
|
const deployFilePrefix: string = 'mssql-bdc-deploy';
|
||||||
export class ScriptGenerator {
|
export class ScriptGenerator {
|
||||||
|
|
||||||
private _shell: Shell;
|
private _shell: Shell;
|
||||||
@@ -33,7 +33,7 @@ export class ScriptGenerator {
|
|||||||
this._kubectlPath = baseKubectlPath(this._kubectl.getContext());
|
this._kubectlPath = baseKubectlPath(this._kubectl.getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
public async generateDeploymentScript(scriptable: Scriptable) : Promise<void> {
|
public async generateDeploymentScript(scriptable: Scriptable): Promise<void> {
|
||||||
let targetClusterName = scriptable.getTargetKubectlContext().clusterName;
|
let targetClusterName = scriptable.getTargetKubectlContext().clusterName;
|
||||||
let targetContextName = scriptable.getTargetKubectlContext().contextName;
|
let targetContextName = scriptable.getTargetKubectlContext().contextName;
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ export class ScriptGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleError = (err: NodeJS.ErrnoException) => {
|
const handleError = (err: NodeJS.ErrnoException) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
vscode.window.showErrorMessage(err.message);
|
vscode.window.showErrorMessage(err.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -5,61 +5,61 @@
|
|||||||
import * as sysfs from 'fs';
|
import * as sysfs from 'fs';
|
||||||
|
|
||||||
export interface FS {
|
export interface FS {
|
||||||
existsSync(path: string): boolean;
|
existsSync(path: string): boolean;
|
||||||
readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
|
readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
|
||||||
readFileSync(filename: string, encoding: string): string;
|
readFileSync(filename: string, encoding: string): string;
|
||||||
readFileToBufferSync(filename: string): Buffer;
|
readFileToBufferSync(filename: string): Buffer;
|
||||||
writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
|
writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
|
||||||
writeFileSync(filename: string, data: any): void;
|
writeFileSync(filename: string, data: any): void;
|
||||||
dirSync(path: string): string[];
|
dirSync(path: string): string[];
|
||||||
unlinkAsync(path: string): Promise<void>;
|
unlinkAsync(path: string): Promise<void>;
|
||||||
existsAsync(path: string): Promise<boolean>;
|
existsAsync(path: string): Promise<boolean>;
|
||||||
openAsync(path: string, flags: string): Promise<void>;
|
openAsync(path: string, flags: string): Promise<void>;
|
||||||
statSync(path: string): sysfs.Stats;
|
statSync(path: string): sysfs.Stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fs: FS = {
|
export const fs: FS = {
|
||||||
existsSync: (path) => sysfs.existsSync(path),
|
existsSync: (path) => sysfs.existsSync(path),
|
||||||
readFile: (filename, encoding, callback) => sysfs.readFile(filename, encoding, callback),
|
readFile: (filename, encoding, callback) => sysfs.readFile(filename, encoding, callback),
|
||||||
readFileSync: (filename, encoding) => sysfs.readFileSync(filename, encoding),
|
readFileSync: (filename, encoding) => sysfs.readFileSync(filename, encoding),
|
||||||
readFileToBufferSync: (filename) => sysfs.readFileSync(filename),
|
readFileToBufferSync: (filename) => sysfs.readFileSync(filename),
|
||||||
writeFile: (filename, data, callback) => sysfs.writeFile(filename, data, callback),
|
writeFile: (filename, data, callback) => sysfs.writeFile(filename, data, callback),
|
||||||
writeFileSync: (filename, data) => sysfs.writeFileSync(filename, data),
|
writeFileSync: (filename, data) => sysfs.writeFileSync(filename, data),
|
||||||
dirSync: (path) => sysfs.readdirSync(path),
|
dirSync: (path) => sysfs.readdirSync(path),
|
||||||
|
|
||||||
unlinkAsync: (path) => {
|
unlinkAsync: (path) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
sysfs.unlink(path, (error) => {
|
sysfs.unlink(path, (error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject();
|
reject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
existsAsync: (path) => {
|
existsAsync: (path) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
sysfs.exists(path, (exists) => {
|
sysfs.exists(path, (exists) => {
|
||||||
resolve(exists);
|
resolve(exists);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
openAsync: (path, flags) => {
|
openAsync: (path, flags) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
sysfs.open(path, flags, (error, _fd) => {
|
sysfs.open(path, flags, (error, _fd) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject();
|
reject();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
statSync: (path) => sysfs.statSync(path)
|
statSync: (path) => sysfs.statSync(path)
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,193 +12,193 @@ import { getActiveKubeconfig, getToolPath } from '../config/config';
|
|||||||
import { host } from '../kubectl/host';
|
import { host } from '../kubectl/host';
|
||||||
|
|
||||||
export enum Platform {
|
export enum Platform {
|
||||||
Windows,
|
Windows,
|
||||||
MacOS,
|
MacOS,
|
||||||
Linux,
|
Linux,
|
||||||
Unsupported,
|
Unsupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExecCallback extends shelljs.ExecCallback {}
|
export interface ExecCallback extends shelljs.ExecCallback { }
|
||||||
|
|
||||||
export interface Shell {
|
export interface Shell {
|
||||||
isWindows(): boolean;
|
isWindows(): boolean;
|
||||||
isUnix(): boolean;
|
isUnix(): boolean;
|
||||||
platform(): Platform;
|
platform(): Platform;
|
||||||
home(): string;
|
home(): string;
|
||||||
combinePath(basePath: string, relativePath: string): string;
|
combinePath(basePath: string, relativePath: string): string;
|
||||||
fileUri(filePath: string): vscode.Uri;
|
fileUri(filePath: string): vscode.Uri;
|
||||||
execOpts(): any;
|
execOpts(): any;
|
||||||
exec(cmd: string, stdin?: string): Promise<ShellResult | undefined>;
|
exec(cmd: string, stdin?: string): Promise<ShellResult | undefined>;
|
||||||
execCore(cmd: string, opts: any, stdin?: string): Promise<ShellResult>;
|
execCore(cmd: string, opts: any, stdin?: string): Promise<ShellResult>;
|
||||||
unquotedPath(path: string): string;
|
unquotedPath(path: string): string;
|
||||||
which(bin: string): string | null;
|
which(bin: string): string | null;
|
||||||
cat(path: string): string;
|
cat(path: string): string;
|
||||||
ls(path: string): string[];
|
ls(path: string): string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const shell: Shell = {
|
export const shell: Shell = {
|
||||||
isWindows : isWindows,
|
isWindows: isWindows,
|
||||||
isUnix : isUnix,
|
isUnix: isUnix,
|
||||||
platform : platform,
|
platform: platform,
|
||||||
home : home,
|
home: home,
|
||||||
combinePath : combinePath,
|
combinePath: combinePath,
|
||||||
fileUri : fileUri,
|
fileUri: fileUri,
|
||||||
execOpts : execOpts,
|
execOpts: execOpts,
|
||||||
exec : exec,
|
exec: exec,
|
||||||
execCore : execCore,
|
execCore: execCore,
|
||||||
unquotedPath : unquotedPath,
|
unquotedPath: unquotedPath,
|
||||||
which: which,
|
which: which,
|
||||||
cat: cat,
|
cat: cat,
|
||||||
ls: ls,
|
ls: ls,
|
||||||
};
|
};
|
||||||
|
|
||||||
const WINDOWS: string = 'win32';
|
const WINDOWS: string = 'win32';
|
||||||
|
|
||||||
export interface ShellResult {
|
export interface ShellResult {
|
||||||
readonly code: number;
|
readonly code: number;
|
||||||
readonly stdout: string;
|
readonly stdout: string;
|
||||||
readonly stderr: string;
|
readonly stderr: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShellHandler = (code: number, stdout: string, stderr: string) => void;
|
export type ShellHandler = (code: number, stdout: string, stderr: string) => void;
|
||||||
|
|
||||||
function isWindows(): boolean {
|
function isWindows(): boolean {
|
||||||
return (process.platform === WINDOWS);
|
return (process.platform === WINDOWS);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isUnix(): boolean {
|
function isUnix(): boolean {
|
||||||
return !isWindows();
|
return !isWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
function platform(): Platform {
|
function platform(): Platform {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case 'win32': return Platform.Windows;
|
case 'win32': return Platform.Windows;
|
||||||
case 'darwin': return Platform.MacOS;
|
case 'darwin': return Platform.MacOS;
|
||||||
case 'linux': return Platform.Linux;
|
case 'linux': return Platform.Linux;
|
||||||
default: return Platform.Unsupported;
|
default: return Platform.Unsupported;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function concatIfBoth(s1: string | undefined, s2: string | undefined): string | undefined {
|
function concatIfBoth(s1: string | undefined, s2: string | undefined): string | undefined {
|
||||||
return s1 && s2 ? s1.concat(s2) : undefined;
|
return s1 && s2 ? s1.concat(s2) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function home(): string {
|
function home(): string {
|
||||||
return process.env['HOME'] ||
|
return process.env['HOME'] ||
|
||||||
concatIfBoth(process.env['HOMEDRIVE'], process.env['HOMEPATH']) ||
|
concatIfBoth(process.env['HOMEDRIVE'], process.env['HOMEPATH']) ||
|
||||||
process.env['USERPROFILE'] ||
|
process.env['USERPROFILE'] ||
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
function combinePath(basePath: string, relativePath: string) {
|
function combinePath(basePath: string, relativePath: string) {
|
||||||
let separator = '/';
|
let separator = '/';
|
||||||
if (isWindows()) {
|
if (isWindows()) {
|
||||||
relativePath = relativePath.replace(/\//g, '\\');
|
relativePath = relativePath.replace(/\//g, '\\');
|
||||||
separator = '\\';
|
separator = '\\';
|
||||||
}
|
}
|
||||||
return basePath + separator + relativePath;
|
return basePath + separator + relativePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isWindowsFilePath(filePath: string) {
|
function isWindowsFilePath(filePath: string) {
|
||||||
return filePath[1] === ':' && filePath[2] === '\\';
|
return filePath[1] === ':' && filePath[2] === '\\';
|
||||||
}
|
}
|
||||||
|
|
||||||
function fileUri(filePath: string): vscode.Uri {
|
function fileUri(filePath: string): vscode.Uri {
|
||||||
if (isWindowsFilePath(filePath)) {
|
if (isWindowsFilePath(filePath)) {
|
||||||
return vscode.Uri.parse('file:///' + filePath.replace(/\\/g, '/'));
|
return vscode.Uri.parse('file:///' + filePath.replace(/\\/g, '/'));
|
||||||
}
|
}
|
||||||
return vscode.Uri.parse('file://' + filePath);
|
return vscode.Uri.parse('file://' + filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
function execOpts(): any {
|
function execOpts(): any {
|
||||||
let env = process.env;
|
let env = process.env;
|
||||||
if (isWindows()) {
|
if (isWindows()) {
|
||||||
env = Object.assign({ }, env, { HOME: home() });
|
env = Object.assign({}, env, { HOME: home() });
|
||||||
}
|
}
|
||||||
env = shellEnvironment(env);
|
env = shellEnvironment(env);
|
||||||
const opts = {
|
const opts = {
|
||||||
cwd: vscode.workspace.rootPath,
|
cwd: vscode.workspace.rootPath,
|
||||||
env: env,
|
env: env,
|
||||||
async: true
|
async: true
|
||||||
};
|
};
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function exec(cmd: string, stdin?: string): Promise<ShellResult | undefined> {
|
async function exec(cmd: string, stdin?: string): Promise<ShellResult | undefined> {
|
||||||
try {
|
try {
|
||||||
return await execCore(cmd, execOpts(), stdin);
|
return await execCore(cmd, execOpts(), stdin);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
vscode.window.showErrorMessage(ex);
|
vscode.window.showErrorMessage(ex);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function execCore(cmd: string, opts: any, stdin?: string): Promise<ShellResult> {
|
function execCore(cmd: string, opts: any, stdin?: string): Promise<ShellResult> {
|
||||||
return new Promise<ShellResult>((resolve) => {
|
return new Promise<ShellResult>((resolve) => {
|
||||||
const proc = shelljs.exec(cmd, opts, (code, stdout, stderr) => resolve({code : code, stdout : stdout, stderr : stderr}));
|
const proc = shelljs.exec(cmd, opts, (code, stdout, stderr) => resolve({ code: code, stdout: stdout, stderr: stderr }));
|
||||||
if (stdin) {
|
if (stdin) {
|
||||||
proc.stdin.end(stdin);
|
proc.stdin.end(stdin);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function unquotedPath(path: string): string {
|
function unquotedPath(path: string): string {
|
||||||
if (isWindows() && path && path.length > 1 && path.startsWith('"') && path.endsWith('"')) {
|
if (isWindows() && path && path.length > 1 && path.startsWith('"') && path.endsWith('"')) {
|
||||||
return path.substring(1, path.length - 1);
|
return path.substring(1, path.length - 1);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shellEnvironment(baseEnvironment: any): any {
|
export function shellEnvironment(baseEnvironment: any): any {
|
||||||
const env = Object.assign({}, baseEnvironment);
|
const env = Object.assign({}, baseEnvironment);
|
||||||
const pathVariable = pathVariableName(env);
|
const pathVariable = pathVariableName(env);
|
||||||
for (const tool of ['kubectl']) {
|
for (const tool of ['kubectl']) {
|
||||||
const toolPath = getToolPath(host, shell, tool);
|
const toolPath = getToolPath(host, shell, tool);
|
||||||
if (toolPath) {
|
if (toolPath) {
|
||||||
const toolDirectory = path.dirname(toolPath);
|
const toolDirectory = path.dirname(toolPath);
|
||||||
const currentPath = env[pathVariable];
|
const currentPath = env[pathVariable];
|
||||||
env[pathVariable] = toolDirectory + (currentPath ? `${pathEntrySeparator()}${currentPath}` : '');
|
env[pathVariable] = toolDirectory + (currentPath ? `${pathEntrySeparator()}${currentPath}` : '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const kubeconfig = getActiveKubeconfig();
|
const kubeconfig = getActiveKubeconfig();
|
||||||
if (kubeconfig) {
|
if (kubeconfig) {
|
||||||
env['KUBECONFIG'] = kubeconfig;
|
env['KUBECONFIG'] = kubeconfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pathVariableName(env: any): string {
|
function pathVariableName(env: any): string {
|
||||||
if (isWindows()) {
|
if (isWindows()) {
|
||||||
for (const v of Object.keys(env)) {
|
for (const v of Object.keys(env)) {
|
||||||
if (v.toLowerCase() === 'path') {
|
if (v.toLowerCase() === 'path') {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 'PATH';
|
return 'PATH';
|
||||||
}
|
}
|
||||||
|
|
||||||
function pathEntrySeparator() {
|
function pathEntrySeparator() {
|
||||||
return isWindows() ? ';' : ':';
|
return isWindows() ? ';' : ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
function which(bin: string): string | null {
|
function which(bin: string): string | null {
|
||||||
return shelljs.which(bin);
|
return shelljs.which(bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
function cat(path: string): string {
|
function cat(path: string): string {
|
||||||
return shelljs.cat(path);
|
return shelljs.cat(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ls(path: string): string[] {
|
function ls(path: string): string[] {
|
||||||
return shelljs.ls(path);
|
return shelljs.ls(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shellMessage(sr: ShellResult | undefined, invocationFailureMessage: string): string {
|
export function shellMessage(sr: ShellResult | undefined, invocationFailureMessage: string): string {
|
||||||
if (!sr) {
|
if (!sr) {
|
||||||
return invocationFailureMessage;
|
return invocationFailureMessage;
|
||||||
}
|
}
|
||||||
return sr.code === 0 ? sr.stdout : sr.stderr;
|
return sr.code === 0 ? sr.stdout : sr.stderr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
|
||||||
import { WizardPageBase } from '../../wizardPageBase';
|
import { WizardPageBase } from '../../wizardPageBase';
|
||||||
import { CreateClusterWizard } from '../createClusterWizard';
|
import { CreateClusterWizard } from '../createClusterWizard';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
@@ -347,7 +345,7 @@ export class ClusterProfilePage extends WizardPageBase<CreateClusterWizard> {
|
|||||||
case ClusterPoolType.Spark:
|
case ClusterPoolType.Spark:
|
||||||
return localize('bdc-create.SparkPoolDisplayName', 'Spark pool');
|
return localize('bdc-create.SparkPoolDisplayName', 'Spark pool');
|
||||||
default:
|
default:
|
||||||
throw 'unknown pool type';
|
throw new Error('unknown pool type');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +362,7 @@ export class ClusterProfilePage extends WizardPageBase<CreateClusterWizard> {
|
|||||||
case ClusterPoolType.Spark:
|
case ClusterPoolType.Spark:
|
||||||
return localize('bdc-create.SparkPoolDescription', 'TODO: Add description');
|
return localize('bdc-create.SparkPoolDescription', 'TODO: Add description');
|
||||||
default:
|
default:
|
||||||
throw 'unknown pool type';
|
throw new Error('unknown pool type');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { WizardPageBase } from '../../wizardPageBase';
|
import { WizardPageBase } from '../../wizardPageBase';
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { DacFxDataModel } from './models';
|
import { DacFxDataModel } from './models';
|
||||||
@@ -15,19 +14,16 @@ export abstract class BasePage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method constructs all the elements of the page.
|
* This method constructs all the elements of the page.
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
*/
|
||||||
public async abstract start(): Promise<boolean>;
|
public async abstract start(): Promise<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when the user is entering the page.
|
* This method is called when the user is entering the page.
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
*/
|
||||||
public async abstract onPageEnter(): Promise<boolean>;
|
public async abstract onPageEnter(): Promise<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when the user is leaving the page.
|
* This method is called when the user is leaving the page.
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
*/
|
||||||
async onPageLeave(): Promise<boolean> {
|
async onPageLeave(): Promise<boolean> {
|
||||||
return true;
|
return true;
|
||||||
@@ -35,7 +31,6 @@ export abstract class BasePage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Override this method to cleanup what you don't need cached in the page.
|
* Override this method to cleanup what you don't need cached in the page.
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
*/
|
||||||
public async cleanup(): Promise<boolean> {
|
public async cleanup(): Promise<boolean> {
|
||||||
return true;
|
return true;
|
||||||
@@ -136,4 +131,3 @@ export abstract class BasePage {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
|||||||
@@ -2,13 +2,9 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import { RequestType, NotificationType } from 'vscode-languageclient';
|
import { RequestType, NotificationType } from 'vscode-languageclient';
|
||||||
|
|
||||||
/**
|
|
||||||
* @interface IMessage
|
|
||||||
*/
|
|
||||||
export interface IMessage {
|
export interface IMessage {
|
||||||
jsonrpc: string;
|
jsonrpc: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
@@ -97,7 +96,7 @@ export function generateGuid(): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function verifyPlatform(): Thenable<boolean> {
|
export function verifyPlatform(): Thenable<boolean> {
|
||||||
if (os.platform() === 'darwin' && parseFloat(os.release()) < 16.0) {
|
if (os.platform() === 'darwin' && parseFloat(os.release()) < 16) {
|
||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import { ErrorAction, CloseAction } from 'vscode-languageclient';
|
import { ErrorAction, CloseAction } from 'vscode-languageclient';
|
||||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||||
import { PlatformInformation } from 'service-downloader/out/platform';
|
import { PlatformInformation } from 'service-downloader/out/platform';
|
||||||
@@ -20,22 +18,21 @@ import { IMessage, ITelemetryEventProperties, ITelemetryEventMeasures } from './
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle Language Service client errors
|
* Handle Language Service client errors
|
||||||
* @class LanguageClientErrorHandler
|
|
||||||
*/
|
*/
|
||||||
export class LanguageClientErrorHandler {
|
export class LanguageClientErrorHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance of LanguageClientErrorHandler.
|
* Creates an instance of LanguageClientErrorHandler.
|
||||||
* @memberOf LanguageClientErrorHandler
|
* @memberOf LanguageClientErrorHandler
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show an error message prompt with a link to known issues wiki page
|
* Show an error message prompt with a link to known issues wiki page
|
||||||
* @memberOf LanguageClientErrorHandler
|
* @memberOf LanguageClientErrorHandler
|
||||||
*/
|
*/
|
||||||
showOnErrorPrompt(): void {
|
showOnErrorPrompt(): void {
|
||||||
// TODO add telemetry
|
// TODO add telemetry
|
||||||
// Telemetry.sendTelemetryEvent('SqlToolsServiceCrash');
|
// Telemetry.sendTelemetryEvent('SqlToolsServiceCrash');
|
||||||
@@ -50,16 +47,11 @@ export class LanguageClientErrorHandler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for language service client error
|
* Callback for language service client error
|
||||||
*
|
*
|
||||||
* @param {Error} error
|
* @memberOf LanguageClientErrorHandler
|
||||||
* @param {Message} message
|
*/
|
||||||
* @param {number} count
|
|
||||||
* @returns {ErrorAction}
|
|
||||||
*
|
|
||||||
* @memberOf LanguageClientErrorHandler
|
|
||||||
*/
|
|
||||||
error(error: Error, message: IMessage, count: number): ErrorAction {
|
error(error: Error, message: IMessage, count: number): ErrorAction {
|
||||||
this.showOnErrorPrompt();
|
this.showOnErrorPrompt();
|
||||||
|
|
||||||
@@ -68,13 +60,11 @@ export class LanguageClientErrorHandler {
|
|||||||
return ErrorAction.Shutdown;
|
return ErrorAction.Shutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for language service client closed
|
* Callback for language service client closed
|
||||||
*
|
*
|
||||||
* @returns {CloseAction}
|
* @memberOf LanguageClientErrorHandler
|
||||||
*
|
*/
|
||||||
* @memberOf LanguageClientErrorHandler
|
|
||||||
*/
|
|
||||||
closed(): CloseAction {
|
closed(): CloseAction {
|
||||||
this.showOnErrorPrompt();
|
this.showOnErrorPrompt();
|
||||||
|
|
||||||
@@ -134,16 +124,16 @@ export class Telemetry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable telemetry reporting
|
* Disable telemetry reporting
|
||||||
*/
|
*/
|
||||||
public static disable(): void {
|
public static disable(): void {
|
||||||
this.disabled = true;
|
this.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the telemetry reporter for use.
|
* Initialize the telemetry reporter for use.
|
||||||
*/
|
*/
|
||||||
public static initialize(): void {
|
public static initialize(): void {
|
||||||
if (typeof this.reporter === 'undefined') {
|
if (typeof this.reporter === 'undefined') {
|
||||||
// Check if the user has opted out of telemetry
|
// Check if the user has opted out of telemetry
|
||||||
@@ -156,9 +146,9 @@ export class Telemetry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a telemetry event for an exception
|
* Send a telemetry event for an exception
|
||||||
*/
|
*/
|
||||||
public static sendTelemetryEventForException(
|
public static sendTelemetryEventForException(
|
||||||
err: any, methodName: string, extensionConfigName: string): void {
|
err: any, methodName: string, extensionConfigName: string): void {
|
||||||
try {
|
try {
|
||||||
@@ -181,9 +171,9 @@ export class Telemetry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a telemetry event using application insights
|
* Send a telemetry event using application insights
|
||||||
*/
|
*/
|
||||||
public static sendTelemetryEvent(
|
public static sendTelemetryEvent(
|
||||||
eventName: string,
|
eventName: string,
|
||||||
properties?: ITelemetryEventProperties,
|
properties?: ITelemetryEventProperties,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { ImportDataModel } from './models';
|
import { ImportDataModel } from './models';
|
||||||
@@ -15,19 +14,16 @@ export abstract class BasePage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method constructs all the elements of the page.
|
* This method constructs all the elements of the page.
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
*/
|
||||||
public async abstract start(): Promise<boolean>;
|
public async abstract start(): Promise<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when the user is entering the page.
|
* This method is called when the user is entering the page.
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
*/
|
||||||
public async abstract onPageEnter(): Promise<boolean>;
|
public async abstract onPageEnter(): Promise<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called when the user is leaving the page.
|
* This method is called when the user is leaving the page.
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
*/
|
||||||
async onPageLeave(): Promise<boolean> {
|
async onPageLeave(): Promise<boolean> {
|
||||||
return true;
|
return true;
|
||||||
@@ -35,7 +31,6 @@ export abstract class BasePage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Override this method to cleanup what you don't need cached in the page.
|
* Override this method to cleanup what you don't need cached in the page.
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
*/
|
||||||
public async cleanup(): Promise<boolean> {
|
public async cleanup(): Promise<boolean> {
|
||||||
return true;
|
return true;
|
||||||
@@ -136,4 +131,3 @@ export abstract class BasePage {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
|
|
||||||
@@ -133,7 +131,6 @@ export class SummaryPage extends ImportPage {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the connection string to send to the middleware
|
* Gets the connection string to send to the middleware
|
||||||
* @returns {Promise<string>}
|
|
||||||
*/
|
*/
|
||||||
private async getConnectionString(): Promise<string> {
|
private async getConnectionString(): Promise<string> {
|
||||||
let options = this.model.server.options;
|
let options = this.model.server.options;
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"compileOnSave": true,
|
"compileOnSave": true,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"outDir": "./out",
|
"outDir": "./out",
|
||||||
"lib": [
|
"lib": [
|
||||||
"es6", "es2015.promise"
|
"es6", "es2015.promise"
|
||||||
],
|
],
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"declaration": false
|
"declaration": false
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import { normalize, join } from 'path';
|
import { normalize, join } from 'path';
|
||||||
@@ -12,10 +12,10 @@ const TEST_SETUP_COMPLETED_TEXT: string = 'Test Setup Completed';
|
|||||||
const EXTENSION_LOADED_TEXT: string = 'Test Extension Loaded';
|
const EXTENSION_LOADED_TEXT: string = 'Test Extension Loaded';
|
||||||
const ALL_EXTENSION_LOADED_TEXT: string = 'All Extensions Loaded';
|
const ALL_EXTENSION_LOADED_TEXT: string = 'All Extensions Loaded';
|
||||||
|
|
||||||
var statusBarItemTimer: NodeJS.Timer;
|
let statusBarItemTimer: NodeJS.Timer;
|
||||||
|
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
var statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
let statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
||||||
vscode.commands.registerCommand('test.setupIntegrationTest', async () => {
|
vscode.commands.registerCommand('test.setupIntegrationTest', async () => {
|
||||||
let extensionInstallersFolder = normalize(join(__dirname, '../extensionInstallers'));
|
let extensionInstallersFolder = normalize(join(__dirname, '../extensionInstallers'));
|
||||||
let installers = fs.readdirSync(extensionInstallersFolder);
|
let installers = fs.readdirSync(extensionInstallersFolder);
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ export enum EngineType {
|
|||||||
BigDataCluster
|
BigDataCluster
|
||||||
}
|
}
|
||||||
|
|
||||||
var connectionProviderMapping = {};
|
let connectionProviderMapping = {};
|
||||||
var authenticationTypeMapping = {};
|
let authenticationTypeMapping = {};
|
||||||
connectionProviderMapping[ConnectionProvider.SQLServer] = { name: 'MSSQL', displayName: 'Microsoft SQL Server' };
|
connectionProviderMapping[ConnectionProvider.SQLServer] = { name: 'MSSQL', displayName: 'Microsoft SQL Server' };
|
||||||
|
|
||||||
authenticationTypeMapping[AuthenticationType.SqlLogin] = { name: 'SqlLogin', displayName: 'SQL Login' };
|
authenticationTypeMapping[AuthenticationType.SqlLogin] = { name: 'SqlLogin', displayName: 'SQL Login' };
|
||||||
@@ -80,7 +80,7 @@ export class TestServerProfile {
|
|||||||
public get engineType(): EngineType { return this._profile.engineType; }
|
public get engineType(): EngineType { return this._profile.engineType; }
|
||||||
}
|
}
|
||||||
|
|
||||||
var TestingServers: TestServerProfile[] = [
|
let TestingServers: TestServerProfile[] = [
|
||||||
new TestServerProfile(
|
new TestServerProfile(
|
||||||
{
|
{
|
||||||
serverName: getConfigValue(EnvironmentVariable_STANDALONE_SERVER),
|
serverName: getConfigValue(EnvironmentVariable_STANDALONE_SERVER),
|
||||||
@@ -121,7 +121,7 @@ function getEnumMappingEntry(mapping: any, enumValue: any): INameDisplayNamePair
|
|||||||
if (entry) {
|
if (entry) {
|
||||||
return entry;
|
return entry;
|
||||||
} else {
|
} else {
|
||||||
throw `Unknown enum type: ${enumValue.toString()}`;
|
throw new Error(`Unknown enum type: ${enumValue.toString()}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,4 +146,4 @@ export async function getTestingServers(): Promise<TestServerProfile[]> {
|
|||||||
});
|
});
|
||||||
await promise;
|
await promise;
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
export var context = {
|
export let context = {
|
||||||
RunTest: true
|
RunTest: true
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,14 +18,14 @@
|
|||||||
|
|
||||||
"tab.bigDataClusterDescription": "Tasks and information about your SQL Server Big Data Cluster",
|
"tab.bigDataClusterDescription": "Tasks and information about your SQL Server Big Data Cluster",
|
||||||
"title.bigDataCluster": "SQL Server Big Data Cluster",
|
"title.bigDataCluster": "SQL Server Big Data Cluster",
|
||||||
"title.submitSparkJob": "Submit Spark Job",
|
"title.submitSparkJob": "Submit Spark Job",
|
||||||
"title.newSparkJob": "New Spark Job",
|
"title.newSparkJob": "New Spark Job",
|
||||||
"title.openSparkHistory": "View Spark History",
|
"title.openSparkHistory": "View Spark History",
|
||||||
"title.openYarnHistory": "View Yarn History",
|
"title.openYarnHistory": "View Yarn History",
|
||||||
"title.tasks": "Tasks",
|
"title.tasks": "Tasks",
|
||||||
"title.installPackages": "Install Packages",
|
"title.installPackages": "Install Packages",
|
||||||
"title.configurePython": "Configure Python for Notebooks",
|
"title.configurePython": "Configure Python for Notebooks",
|
||||||
|
|
||||||
"title.searchServers": "Search: Servers",
|
"title.searchServers": "Search: Servers",
|
||||||
"title.clearSearchServerResult": "Search: Clear Search Server Results"
|
"title.clearSearchServerResult": "Search: Clear Search Server Results"
|
||||||
}
|
}
|
||||||
|
|||||||
54
extensions/mssql/src/api/mssqlapis.d.ts
vendored
54
extensions/mssql/src/api/mssqlapis.d.ts
vendored
@@ -10,24 +10,17 @@ import * as vscode from 'vscode';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The APIs provided by Mssql extension
|
* The APIs provided by Mssql extension
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface MssqlExtensionApi
|
|
||||||
*/
|
*/
|
||||||
export interface MssqlExtensionApi {
|
export interface MssqlExtensionApi {
|
||||||
/**
|
/**
|
||||||
* Gets the object explorer API that supports querying over the connections supported by this extension
|
* Gets the object explorer API that supports querying over the connections supported by this extension
|
||||||
*
|
*
|
||||||
* @returns {IMssqlObjectExplorerBrowser}
|
|
||||||
* @memberof IMssqlExtensionApi
|
|
||||||
*/
|
*/
|
||||||
getMssqlObjectExplorerBrowser(): MssqlObjectExplorerBrowser;
|
getMssqlObjectExplorerBrowser(): MssqlObjectExplorerBrowser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Cms Service APIs to communicate with CMS connections supported by this extension
|
* Get the Cms Service APIs to communicate with CMS connections supported by this extension
|
||||||
*
|
*
|
||||||
* @returns {Promise<CmsService>}
|
|
||||||
* @memberof IMssqlExtensionApi
|
|
||||||
*/
|
*/
|
||||||
getCmsServiceProvider(): Promise<CmsService>;
|
getCmsServiceProvider(): Promise<CmsService>;
|
||||||
}
|
}
|
||||||
@@ -35,25 +28,16 @@ export interface MssqlExtensionApi {
|
|||||||
/**
|
/**
|
||||||
* A browser supporting actions over the object explorer connections provided by this extension.
|
* A browser supporting actions over the object explorer connections provided by this extension.
|
||||||
* Currently this is the
|
* Currently this is the
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface MssqlObjectExplorerBrowser
|
|
||||||
*/
|
*/
|
||||||
export interface MssqlObjectExplorerBrowser {
|
export interface MssqlObjectExplorerBrowser {
|
||||||
/**
|
/**
|
||||||
* Gets the matching node given a context object, e.g. one from a right-click on a node in Object Explorer
|
* Gets the matching node given a context object, e.g. one from a right-click on a node in Object Explorer
|
||||||
*
|
|
||||||
* @param {azdata.ObjectExplorerContext} objectExplorerContext
|
|
||||||
* @returns {Promise<T>}
|
|
||||||
*/
|
*/
|
||||||
getNode<T extends ITreeNode>(objectExplorerContext: azdata.ObjectExplorerContext): Promise<T>;
|
getNode<T extends ITreeNode>(objectExplorerContext: azdata.ObjectExplorerContext): Promise<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tree node in the object explorer tree
|
* A tree node in the object explorer tree
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface ITreeNode
|
|
||||||
*/
|
*/
|
||||||
export interface ITreeNode {
|
export interface ITreeNode {
|
||||||
getNodeInfo(): azdata.NodeInfo;
|
getNodeInfo(): azdata.NodeInfo;
|
||||||
@@ -63,10 +47,6 @@ export interface ITreeNode {
|
|||||||
/**
|
/**
|
||||||
* A HDFS file node. This is a leaf node in the object explorer tree, and its contents
|
* A HDFS file node. This is a leaf node in the object explorer tree, and its contents
|
||||||
* can be queried
|
* can be queried
|
||||||
*
|
|
||||||
* @export
|
|
||||||
* @interface IFileNode
|
|
||||||
* @extends {ITreeNode}
|
|
||||||
*/
|
*/
|
||||||
export interface IFileNode extends ITreeNode {
|
export interface IFileNode extends ITreeNode {
|
||||||
getFileContentsAsString(maxBytes?: number): Promise<string>;
|
getFileContentsAsString(maxBytes?: number): Promise<string>;
|
||||||
@@ -79,64 +59,31 @@ export interface IFileNode extends ITreeNode {
|
|||||||
export interface CmsService {
|
export interface CmsService {
|
||||||
/**
|
/**
|
||||||
* Connects to or creates a Central management Server
|
* Connects to or creates a Central management Server
|
||||||
*
|
|
||||||
* @param {string} name
|
|
||||||
* @param {string} description
|
|
||||||
* @param {azdata.ConnectionInfo} connectiondetails
|
|
||||||
* @param {string} ownerUri
|
|
||||||
* @returns {Thenable<azdata.ListRegisteredServersResult>}
|
|
||||||
*/
|
*/
|
||||||
createCmsServer(name: string, description:string, connectiondetails: azdata.ConnectionInfo, ownerUri: string): Thenable<ListRegisteredServersResult>;
|
createCmsServer(name: string, description:string, connectiondetails: azdata.ConnectionInfo, ownerUri: string): Thenable<ListRegisteredServersResult>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets all Registered Servers inside a CMS on a particular level
|
* gets all Registered Servers inside a CMS on a particular level
|
||||||
*
|
|
||||||
* @param {string} ownerUri
|
|
||||||
* @param {string} relativePath
|
|
||||||
* @returns {Thenable<azdata.ListRegisteredServersResult>}
|
|
||||||
*/
|
*/
|
||||||
getRegisteredServers(ownerUri: string, relativePath: string): Thenable<ListRegisteredServersResult>;
|
getRegisteredServers(ownerUri: string, relativePath: string): Thenable<ListRegisteredServersResult>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a Registered Server inside a CMS on a particular level
|
* Adds a Registered Server inside a CMS on a particular level
|
||||||
*
|
|
||||||
* @param {string} ownerUri
|
|
||||||
* @param {string} relativePath
|
|
||||||
* @param {string} registeredServerName
|
|
||||||
* @param {string} registeredServerDescription
|
|
||||||
* @param {azdata.ConnectionInfo} connectiondetails
|
|
||||||
* @returns {Thenable<boolean>>}
|
|
||||||
*/
|
*/
|
||||||
addRegisteredServer (ownerUri: string, relativePath: string, registeredServerName: string, registeredServerDescription:string, connectionDetails:azdata.ConnectionInfo): Thenable<boolean>;
|
addRegisteredServer (ownerUri: string, relativePath: string, registeredServerName: string, registeredServerDescription:string, connectionDetails:azdata.ConnectionInfo): Thenable<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a Registered Server inside a CMS on a particular level
|
* Removes a Registered Server inside a CMS on a particular level
|
||||||
*
|
|
||||||
* @param {string} ownerUri
|
|
||||||
* @param {string} relativePath
|
|
||||||
* @param {string} registeredServerName
|
|
||||||
* @returns {Thenable<boolean>}
|
|
||||||
*/
|
*/
|
||||||
removeRegisteredServer (ownerUri: string, relativePath: string, registeredServerName: string): Thenable<boolean>;
|
removeRegisteredServer (ownerUri: string, relativePath: string, registeredServerName: string): Thenable<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a Server Group inside a CMS on a particular level
|
* Adds a Server Group inside a CMS on a particular level
|
||||||
*
|
|
||||||
* @param {string} ownerUri
|
|
||||||
* @param {string} relativePath
|
|
||||||
* @param {string} groupName
|
|
||||||
* @param {string} groupDescription
|
|
||||||
* @param {azdata.ConnectionInfo} connectiondetails
|
|
||||||
*/
|
*/
|
||||||
addServerGroup (ownerUri: string, relativePath: string, groupName: string, groupDescription:string): Thenable<boolean>;
|
addServerGroup (ownerUri: string, relativePath: string, groupName: string, groupDescription:string): Thenable<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a Server Group inside a CMS on a particular level
|
* Removes a Server Group inside a CMS on a particular level
|
||||||
*
|
|
||||||
* @param {string} ownerUri
|
|
||||||
* @param {string} relativePath
|
|
||||||
* @param {string} groupName
|
|
||||||
* @param {string} groupDescription
|
|
||||||
*/
|
*/
|
||||||
removeServerGroup (ownerUri: string, relativePath: string, groupName: string): Thenable<boolean>;
|
removeServerGroup (ownerUri: string, relativePath: string, groupName: string): Thenable<boolean>;
|
||||||
}
|
}
|
||||||
@@ -162,4 +109,3 @@ export interface ListRegisteredServersResult {
|
|||||||
registeredServersList: Array<RegisteredServerResult>;
|
registeredServersList: Array<RegisteredServerResult>;
|
||||||
registeredServerGroups: Array<RegisteredServerGroup>;
|
registeredServerGroups: Array<RegisteredServerGroup>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
|
|
||||||
@@ -13,7 +11,6 @@ import * as azdata from 'azdata';
|
|||||||
* this API from our code
|
* this API from our code
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @class ApiWrapper
|
|
||||||
*/
|
*/
|
||||||
export class ApiWrapper {
|
export class ApiWrapper {
|
||||||
// Data APIs
|
// Data APIs
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ export class CmsService {
|
|||||||
this.appContext.registerService<CmsService>(constants.CmsService, this);
|
this.appContext.registerService<CmsService>(constants.CmsService, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
createCmsServer(name: string, description:string, connectiondetails: azdata.ConnectionInfo, ownerUri: string): Thenable<ListRegisteredServersResult> {
|
createCmsServer(name: string, description: string, connectiondetails: azdata.ConnectionInfo, ownerUri: string): Thenable<ListRegisteredServersResult> {
|
||||||
let connectparams: ConnectParams = { ownerUri: ownerUri, connection: connectiondetails };
|
let connectparams: ConnectParams = { ownerUri: ownerUri, connection: connectiondetails };
|
||||||
let cmsparams: contracts.CreateCentralManagementServerParams = { registeredServerName: name, registeredServerDescription: description, connectParams: connectparams};
|
let cmsparams: contracts.CreateCentralManagementServerParams = { registeredServerName: name, registeredServerDescription: description, connectParams: connectparams };
|
||||||
|
|
||||||
return this.client.sendRequest(contracts.CreateCentralManagementServerRequest.type, cmsparams).then(
|
return this.client.sendRequest(contracts.CreateCentralManagementServerRequest.type, cmsparams).then(
|
||||||
r => {
|
r => {
|
||||||
@@ -35,7 +35,7 @@ export class CmsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRegisteredServers(ownerUri: string, relativePath: string): Thenable<ListRegisteredServersResult> {
|
getRegisteredServers(ownerUri: string, relativePath: string): Thenable<ListRegisteredServersResult> {
|
||||||
let params: contracts.ListRegisteredServersParams = { parentOwnerUri: ownerUri, relativePath: relativePath };
|
let params: contracts.ListRegisteredServersParams = { parentOwnerUri: ownerUri, relativePath: relativePath };
|
||||||
return this.client.sendRequest(contracts.ListRegisteredServersRequest.type, params).then(
|
return this.client.sendRequest(contracts.ListRegisteredServersRequest.type, params).then(
|
||||||
r => {
|
r => {
|
||||||
@@ -48,7 +48,7 @@ export class CmsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addRegisteredServer (ownerUri: string, relativePath: string, registeredServerName: string, registeredServerDescription:string, connectionDetails:azdata.ConnectionInfo): Thenable<boolean> {
|
addRegisteredServer(ownerUri: string, relativePath: string, registeredServerName: string, registeredServerDescription: string, connectionDetails: azdata.ConnectionInfo): Thenable<boolean> {
|
||||||
let params: contracts.AddRegisteredServerParams = { parentOwnerUri: ownerUri, relativePath: relativePath, registeredServerName: registeredServerName, registeredServerDescription: registeredServerDescription, registeredServerConnectionDetails: connectionDetails };
|
let params: contracts.AddRegisteredServerParams = { parentOwnerUri: ownerUri, relativePath: relativePath, registeredServerName: registeredServerName, registeredServerDescription: registeredServerDescription, registeredServerConnectionDetails: connectionDetails };
|
||||||
return this.client.sendRequest(contracts.AddRegisteredServerRequest.type, params).then(
|
return this.client.sendRequest(contracts.AddRegisteredServerRequest.type, params).then(
|
||||||
r => {
|
r => {
|
||||||
@@ -61,7 +61,7 @@ export class CmsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeRegisteredServer (ownerUri: string, relativePath: string, registeredServerName: string): Thenable<boolean> {
|
removeRegisteredServer(ownerUri: string, relativePath: string, registeredServerName: string): Thenable<boolean> {
|
||||||
let params: contracts.RemoveRegisteredServerParams = { parentOwnerUri: ownerUri, relativePath: relativePath, registeredServerName: registeredServerName };
|
let params: contracts.RemoveRegisteredServerParams = { parentOwnerUri: ownerUri, relativePath: relativePath, registeredServerName: registeredServerName };
|
||||||
return this.client.sendRequest(contracts.RemoveRegisteredServerRequest.type, params).then(
|
return this.client.sendRequest(contracts.RemoveRegisteredServerRequest.type, params).then(
|
||||||
r => {
|
r => {
|
||||||
@@ -74,7 +74,7 @@ export class CmsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addServerGroup (ownerUri: string, relativePath: string, groupName: string, groupDescription:string): Thenable<boolean> {
|
addServerGroup(ownerUri: string, relativePath: string, groupName: string, groupDescription: string): Thenable<boolean> {
|
||||||
let params: contracts.AddServerGroupParams = { parentOwnerUri: ownerUri, relativePath: relativePath, groupName: groupName, groupDescription: groupDescription };
|
let params: contracts.AddServerGroupParams = { parentOwnerUri: ownerUri, relativePath: relativePath, groupName: groupName, groupDescription: groupDescription };
|
||||||
return this.client.sendRequest(contracts.AddServerGroupRequest.type, params).then(
|
return this.client.sendRequest(contracts.AddServerGroupRequest.type, params).then(
|
||||||
r => {
|
r => {
|
||||||
@@ -87,7 +87,7 @@ export class CmsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeServerGroup (ownerUri: string, relativePath: string, groupName: string): Thenable<boolean> {
|
removeServerGroup(ownerUri: string, relativePath: string, groupName: string): Thenable<boolean> {
|
||||||
let params: contracts.RemoveServerGroupParams = { parentOwnerUri: ownerUri, relativePath: relativePath, groupName: groupName };
|
let params: contracts.RemoveServerGroupParams = { parentOwnerUri: ownerUri, relativePath: relativePath, groupName: groupName };
|
||||||
return this.client.sendRequest(contracts.RemoveServerGroupRequest.type, params).then(
|
return this.client.sendRequest(contracts.RemoveServerGroupRequest.type, params).then(
|
||||||
r => {
|
r => {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import { NotificationType, RequestType } from 'vscode-languageclient';
|
import { NotificationType, RequestType } from 'vscode-languageclient';
|
||||||
import { ITelemetryEventProperties, ITelemetryEventMeasures } from './telemetry';
|
import { ITelemetryEventProperties, ITelemetryEventMeasures } from './telemetry';
|
||||||
@@ -377,37 +376,37 @@ export namespace GenerateDeployPlanRequest {
|
|||||||
|
|
||||||
|
|
||||||
export interface CreateCentralManagementServerParams {
|
export interface CreateCentralManagementServerParams {
|
||||||
registeredServerName: string;
|
registeredServerName: string;
|
||||||
registeredServerDescription : string;
|
registeredServerDescription: string;
|
||||||
connectParams: ConnectParams;
|
connectParams: ConnectParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ListRegisteredServersParams extends RegisteredServerParamsBase {
|
export interface ListRegisteredServersParams extends RegisteredServerParamsBase {
|
||||||
// same as base
|
// same as base
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddRegisteredServerParams extends RegisteredServerParamsBase {
|
export interface AddRegisteredServerParams extends RegisteredServerParamsBase {
|
||||||
registeredServerName: string;
|
registeredServerName: string;
|
||||||
registeredServerDescription : string;
|
registeredServerDescription: string;
|
||||||
registeredServerConnectionDetails: azdata.ConnectionInfo;
|
registeredServerConnectionDetails: azdata.ConnectionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RemoveRegisteredServerParams extends RegisteredServerParamsBase {
|
export interface RemoveRegisteredServerParams extends RegisteredServerParamsBase {
|
||||||
registeredServerName: string;
|
registeredServerName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddServerGroupParams extends RegisteredServerParamsBase {
|
export interface AddServerGroupParams extends RegisteredServerParamsBase {
|
||||||
groupName: string;
|
groupName: string;
|
||||||
groupDescription: string;
|
groupDescription: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RemoveServerGroupParams extends RegisteredServerParamsBase {
|
export interface RemoveServerGroupParams extends RegisteredServerParamsBase {
|
||||||
groupName: string;
|
groupName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RegisteredServerParamsBase {
|
export interface RegisteredServerParamsBase {
|
||||||
parentOwnerUri: string;
|
parentOwnerUri: string;
|
||||||
relativePath: string;
|
relativePath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace CreateCentralManagementServerRequest {
|
export namespace CreateCentralManagementServerRequest {
|
||||||
@@ -442,7 +441,7 @@ export interface SchemaCompareParams {
|
|||||||
taskExecutionMode: TaskExecutionMode;
|
taskExecutionMode: TaskExecutionMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SchemaCompareGenerateScriptParams {
|
export interface SchemaCompareGenerateScriptParams {
|
||||||
operationId: string;
|
operationId: string;
|
||||||
targetDatabaseName: string;
|
targetDatabaseName: string;
|
||||||
scriptFilePath: string;
|
scriptFilePath: string;
|
||||||
@@ -453,7 +452,7 @@ export namespace SchemaCompareRequest {
|
|||||||
export const type = new RequestType<SchemaCompareParams, azdata.SchemaCompareResult, void, void>('schemaCompare/compare');
|
export const type = new RequestType<SchemaCompareParams, azdata.SchemaCompareResult, void, void>('schemaCompare/compare');
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace SchemaCompareGenerateScriptRequest {
|
export namespace SchemaCompareGenerateScriptRequest {
|
||||||
export const type = new RequestType<SchemaCompareGenerateScriptParams, azdata.ResultStatus, void, void>('schemaCompare/generateScript');
|
export const type = new RequestType<SchemaCompareGenerateScriptParams, azdata.ResultStatus, void, void>('schemaCompare/generateScript');
|
||||||
}
|
}
|
||||||
// ------------------------------- <Schema Compare> -----------------------------
|
// ------------------------------- <Schema Compare> -----------------------------
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
export default require('error-ex')('EscapeException');
|
export default require('error-ex')('EscapeException');
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import { SqlOpsDataClient, SqlOpsFeature } from 'dataprotocol-client';
|
import { SqlOpsDataClient, SqlOpsFeature } from 'dataprotocol-client';
|
||||||
import { ClientCapabilities, StaticFeature, RPCMessageType, ServerCapabilities } from 'vscode-languageclient';
|
import { ClientCapabilities, StaticFeature, RPCMessageType, ServerCapabilities } from 'vscode-languageclient';
|
||||||
@@ -12,7 +11,6 @@ import * as contracts from './contracts';
|
|||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as Utils from './utils';
|
import * as Utils from './utils';
|
||||||
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
||||||
import { ConnectParams } from 'dataprotocol-client/lib/protocol';
|
|
||||||
|
|
||||||
export class TelemetryFeature implements StaticFeature {
|
export class TelemetryFeature implements StaticFeature {
|
||||||
|
|
||||||
@@ -170,7 +168,7 @@ export class SchemaCompareServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
let schemaCompare = (sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.SchemaCompareResult> => {
|
let schemaCompare = (sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.SchemaCompareResult> => {
|
||||||
let params: contracts.SchemaCompareParams = {sourceEndpointInfo: sourceEndpointInfo, targetEndpointInfo: targetEndpointInfo, taskExecutionMode: taskExecutionMode};
|
let params: contracts.SchemaCompareParams = { sourceEndpointInfo: sourceEndpointInfo, targetEndpointInfo: targetEndpointInfo, taskExecutionMode: taskExecutionMode };
|
||||||
return client.sendRequest(contracts.SchemaCompareRequest.type, params).then(
|
return client.sendRequest(contracts.SchemaCompareRequest.type, params).then(
|
||||||
r => {
|
r => {
|
||||||
return r;
|
return r;
|
||||||
@@ -182,8 +180,8 @@ export class SchemaCompareServicesFeature extends SqlOpsFeature<undefined> {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let schemaCompareGenerateScript = (operationId: string, targetDatabaseName: string, scriptFilePath: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.DacFxResult> => {
|
let schemaCompareGenerateScript = (operationId: string, targetDatabaseName: string, scriptFilePath: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.DacFxResult> => {
|
||||||
let params: contracts.SchemaCompareGenerateScriptParams = {operationId: operationId, targetDatabaseName: targetDatabaseName, scriptFilePath: scriptFilePath, taskExecutionMode: taskExecutionMode};
|
let params: contracts.SchemaCompareGenerateScriptParams = { operationId: operationId, targetDatabaseName: targetDatabaseName, scriptFilePath: scriptFilePath, taskExecutionMode: taskExecutionMode };
|
||||||
return client.sendRequest(contracts.SchemaCompareGenerateScriptRequest.type, params).then(
|
return client.sendRequest(contracts.SchemaCompareGenerateScriptRequest.type, params).then(
|
||||||
r => {
|
r => {
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ export function sparkJobSubmissionYarnUIMessage(yarnUIURL: string): string { ret
|
|||||||
export function sparkJobSubmissionSparkHistoryLinkMessage(sparkHistoryLink: string): string { return localize('sparkJobSubmission_SparkHistoryLinkMessage', 'Spark History Url: {0} ', sparkHistoryLink); }
|
export function sparkJobSubmissionSparkHistoryLinkMessage(sparkHistoryLink: string): string { return localize('sparkJobSubmission_SparkHistoryLinkMessage', 'Spark History Url: {0} ', sparkHistoryLink); }
|
||||||
export function sparkJobSubmissionGetApplicationIdFailed(err: string): string { return localize('sparkJobSubmission_GetApplicationIdFailed', 'Get Application Id Failed. {0}', err); }
|
export function sparkJobSubmissionGetApplicationIdFailed(err: string): string { return localize('sparkJobSubmission_GetApplicationIdFailed', 'Get Application Id Failed. {0}', err); }
|
||||||
export function sparkJobSubmissionLocalFileNotExisted(path: string): string { return localize('sparkJobSubmission_LocalFileNotExisted', 'Local file {0} does not existed. ', path); }
|
export function sparkJobSubmissionLocalFileNotExisted(path: string): string { return localize('sparkJobSubmission_LocalFileNotExisted', 'Local file {0} does not existed. ', path); }
|
||||||
export const sparkJobSubmissionNoSqlBigDataClusterFound = localize('sparkJobSubmission_NoSqlBigDataClusterFound','No Sql Server Big Data Cluster found.');
|
export const sparkJobSubmissionNoSqlBigDataClusterFound = localize('sparkJobSubmission_NoSqlBigDataClusterFound', 'No Sql Server Big Data Cluster found.');
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
'use strict';
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
@@ -74,7 +73,9 @@ export abstract class Command extends vscode.Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
this.disposable && this.disposable.dispose();
|
if (this.disposable) {
|
||||||
|
this.disposable.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected get apiWrapper(): ApiWrapper {
|
protected get apiWrapper(): ApiWrapper {
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ export class SqlClusterConnection {
|
|||||||
return FileSourceFactory.instance.createHdfsFileSource(options);
|
return FileSourceFactory.instance.createHdfsFileSource(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updatePassword(password : string): void{
|
public updatePassword(password: string): void {
|
||||||
if(password){
|
if (password) {
|
||||||
this._password = password;
|
this._password = password;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ export class HdfsFileSource implements IFileSource {
|
|||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
let hdfsFiles: IFile[] = files.map(file => {
|
let hdfsFiles: IFile[] = files.map(file => {
|
||||||
let hdfsFile = <IHdfsFileStatus> file;
|
let hdfsFile = <IHdfsFileStatus>file;
|
||||||
return new File(File.createPath(path, hdfsFile.pathSuffix), hdfsFile.type === 'DIRECTORY');
|
return new File(File.createPath(path, hdfsFile.pathSuffix), hdfsFile.type === 'DIRECTORY');
|
||||||
});
|
});
|
||||||
resolve(hdfsFiles);
|
resolve(hdfsFiles);
|
||||||
@@ -195,9 +195,9 @@ export class HdfsFileSource implements IFileSource {
|
|||||||
error = <HdfsError>err;
|
error = <HdfsError>err;
|
||||||
if (error.message.includes('Stream exceeded specified max')) {
|
if (error.message.includes('Stream exceeded specified max')) {
|
||||||
// We have data > maxbytes, show we're truncating
|
// We have data > maxbytes, show we're truncating
|
||||||
let previewNote: string = '#################################################################################################################### \r\n'+
|
let previewNote: string = '#################################################################################################################### \r\n' +
|
||||||
'########################### '+ localize('maxSizeNotice', "NOTICE: This file has been truncated at {0} for preview. ", bytes(maxBytes)) + '############################### \r\n' +
|
'########################### ' + localize('maxSizeNotice', "NOTICE: This file has been truncated at {0} for preview. ", bytes(maxBytes)) + '############################### \r\n' +
|
||||||
'#################################################################################################################### \r\n';
|
'#################################################################################################################### \r\n';
|
||||||
data.splice(0, 0, Buffer.from(previewNote, 'utf-8'));
|
data.splice(0, 0, Buffer.from(previewNote, 'utf-8'));
|
||||||
vscode.window.showWarningMessage(localize('maxSizeReached', "The file has been truncated at {0} for preview.", bytes(maxBytes)));
|
vscode.window.showWarningMessage(localize('maxSizeReached', "The file has been truncated at {0} for preview.", bytes(maxBytes)));
|
||||||
resolve(Buffer.concat(data));
|
resolve(Buffer.concat(data));
|
||||||
@@ -236,15 +236,15 @@ export class HdfsFileSource implements IFileSource {
|
|||||||
lineReader.close();
|
lineReader.close();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on('error', (err) => {
|
.on('error', (err) => {
|
||||||
error = <HdfsError>err;
|
error = <HdfsError>err;
|
||||||
reject(error);
|
reject(error);
|
||||||
})
|
})
|
||||||
.on('close', () => {
|
.on('close', () => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
resolve(Buffer.from(lineData.join(os.EOL)));
|
resolve(Buffer.from(lineData.join(os.EOL)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -345,7 +345,7 @@ export class ErrorNode extends TreeNode {
|
|||||||
public static create(message: string, parent: TreeNode, errorCode?: number): ErrorNode {
|
public static create(message: string, parent: TreeNode, errorCode?: number): ErrorNode {
|
||||||
let node = new ErrorNode(message);
|
let node = new ErrorNode(message);
|
||||||
node.parent = parent;
|
node.parent = parent;
|
||||||
if(errorCode){
|
if (errorCode) {
|
||||||
node.errorStatusCode = errorCode;
|
node.errorStatusCode = errorCode;
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export class MssqlObjectExplorerNodeProvider extends ProviderBase implements azd
|
|||||||
}
|
}
|
||||||
|
|
||||||
private hasExpansionError(children: TreeNode[]): boolean {
|
private hasExpansionError(children: TreeNode[]): boolean {
|
||||||
if(children.find(c => c.errorStatusCode > 0)){
|
if (children.find(c => c.errorStatusCode > 0)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------------------------
|
||||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export abstract class TreeNode implements ITreeNode {
|
|||||||
if (children) {
|
if (children) {
|
||||||
for (let child of children) {
|
for (let child of children) {
|
||||||
if (filter && filter(child)) {
|
if (filter && filter(child)) {
|
||||||
let childNode = await this.findNode(child, condition, filter, expandIfNeeded);
|
let childNode = await this.findNode(child, condition, filter, expandIfNeeded);
|
||||||
if (childNode) {
|
if (childNode) {
|
||||||
return childNode;
|
return childNode;
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ export abstract class TreeNode implements ITreeNode {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateFileSource(connection: SqlClusterConnection): void{
|
public updateFileSource(connection: SqlClusterConnection): void {
|
||||||
this.fileSource = connection.createHdfsFileSource();
|
this.fileSource = connection.createHdfsFileSource();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import * as azdata from 'azdata';
|
|||||||
* A tree node in the object explorer tree
|
* A tree node in the object explorer tree
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @interface ITreeNode
|
|
||||||
*/
|
*/
|
||||||
export interface ITreeNode {
|
export interface ITreeNode {
|
||||||
getNodeInfo(): azdata.NodeInfo;
|
getNodeInfo(): azdata.NodeInfo;
|
||||||
@@ -22,9 +21,8 @@ export interface ITreeNode {
|
|||||||
* can be queried
|
* can be queried
|
||||||
*
|
*
|
||||||
* @export
|
* @export
|
||||||
* @interface IFileNode
|
|
||||||
* @extends {ITreeNode}
|
* @extends {ITreeNode}
|
||||||
*/
|
*/
|
||||||
export interface IFileNode extends ITreeNode {
|
export interface IFileNode extends ITreeNode {
|
||||||
getFileContentsAsString(maxBytes?: number): Promise<string>;
|
getFileContentsAsString(maxBytes?: number): Promise<string>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// This code is originally from https://github.com/harrisiirak/webhdfs
|
// This code is originally from https://github.com/harrisiirak/webhdfs
|
||||||
// License: https://github.com/harrisiirak/webhdfs/blob/master/LICENSE
|
// License: https://github.com/harrisiirak/webhdfs/blob/master/LICENSE
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as querystring from 'querystring';
|
import * as querystring from 'querystring';
|
||||||
@@ -53,10 +51,8 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Generate WebHDFS REST API endpoint URL for given operation
|
* Generate WebHDFS REST API endpoint URL for given operation
|
||||||
*
|
*
|
||||||
* @param {string} operation WebHDFS operation name
|
* @param operation WebHDFS operation name
|
||||||
* @param {string} path
|
* @returns WebHDFS REST API endpoint URL
|
||||||
* @param {object} params
|
|
||||||
* @returns {string} WebHDFS REST API endpoint URL
|
|
||||||
*/
|
*/
|
||||||
private getOperationEndpoint(operation: string, path: string, params?: object): string {
|
private getOperationEndpoint(operation: string, path: string, params?: object): string {
|
||||||
let endpoint = this._url;
|
let endpoint = this._url;
|
||||||
@@ -73,8 +69,8 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Gets localized status message for given status code
|
* Gets localized status message for given status code
|
||||||
*
|
*
|
||||||
* @param {number} statusCode Http status code
|
* @param statusCode Http status code
|
||||||
* @returns {string} status message
|
* @returns status message
|
||||||
*/
|
*/
|
||||||
private toStatusMessage(statusCode: number): string {
|
private toStatusMessage(statusCode: number): string {
|
||||||
let statusMessage: string = undefined;
|
let statusMessage: string = undefined;
|
||||||
@@ -93,9 +89,9 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Gets status message from response
|
* Gets status message from response
|
||||||
*
|
*
|
||||||
* @param {request.Response} response response object
|
* @param response response object
|
||||||
* @param {boolean} strict If set true then RemoteException must be present in the body
|
* @param strict If set true then RemoteException must be present in the body
|
||||||
* @returns {string} Error message interpreted by status code
|
* @returns Error message interpreted by status code
|
||||||
*/
|
*/
|
||||||
private getStatusMessage(response: request.Response): string {
|
private getStatusMessage(response: request.Response): string {
|
||||||
if (!response) { return undefined; }
|
if (!response) { return undefined; }
|
||||||
@@ -107,8 +103,8 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Gets remote exception message from response body
|
* Gets remote exception message from response body
|
||||||
*
|
*
|
||||||
* @param {any} responseBody response body
|
* @param responseBody response body
|
||||||
* @returns {string} Error message interpreted by status code
|
* @returns Error message interpreted by status code
|
||||||
*/
|
*/
|
||||||
private getRemoteExceptionMessage(responseBody: any): string {
|
private getRemoteExceptionMessage(responseBody: any): string {
|
||||||
if (!responseBody) { return undefined; }
|
if (!responseBody) { return undefined; }
|
||||||
@@ -128,10 +124,10 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Generates error message descriptive as much as possible
|
* Generates error message descriptive as much as possible
|
||||||
*
|
*
|
||||||
* @param {string} statusMessage status message
|
* @param statusMessage status message
|
||||||
* @param {string} [remoteExceptionMessage] remote exception message
|
* @param [remoteExceptionMessage] remote exception message
|
||||||
* @param {any} [error] error
|
* @param [error] error
|
||||||
* @returns {string} error message
|
* @returns error message
|
||||||
*/
|
*/
|
||||||
private getErrorMessage(statusMessage: string, remoteExceptionMessage?: string, error?: any): string {
|
private getErrorMessage(statusMessage: string, remoteExceptionMessage?: string, error?: any): string {
|
||||||
statusMessage = statusMessage === '' ? undefined : statusMessage;
|
statusMessage = statusMessage === '' ? undefined : statusMessage;
|
||||||
@@ -140,16 +136,16 @@ export class WebHDFS {
|
|||||||
return statusMessage && remoteExceptionMessage ?
|
return statusMessage && remoteExceptionMessage ?
|
||||||
`${statusMessage} (${remoteExceptionMessage})` :
|
`${statusMessage} (${remoteExceptionMessage})` :
|
||||||
statusMessage || remoteExceptionMessage || messageFromError ||
|
statusMessage || remoteExceptionMessage || messageFromError ||
|
||||||
localize('webhdfs.unknownError', 'Unknown Error');
|
localize('webhdfs.unknownError', 'Unknown Error');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse error state from response and return valid Error object
|
* Parse error state from response and return valid Error object
|
||||||
*
|
*
|
||||||
* @param {request.Response} response response object
|
* @param response response object
|
||||||
* @param {any} [responseBody] response body
|
* @param [responseBody] response body
|
||||||
* @param {any} [error] error
|
* @param [error] error
|
||||||
* @returns {HdfsError} HdfsError object
|
* @returns HdfsError object
|
||||||
*/
|
*/
|
||||||
private parseError(response: request.Response, responseBody?: any, error?: any): HdfsError {
|
private parseError(response: request.Response, responseBody?: any, error?: any): HdfsError {
|
||||||
let statusMessage: string = this.getStatusMessage(response);
|
let statusMessage: string = this.getStatusMessage(response);
|
||||||
@@ -165,8 +161,8 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Check if response is redirect
|
* Check if response is redirect
|
||||||
*
|
*
|
||||||
* @param {request.Response} response response object
|
* @param response response object
|
||||||
* @returns {boolean} if response is redirect
|
* @returns if response is redirect
|
||||||
*/
|
*/
|
||||||
private isRedirect(response: request.Response): boolean {
|
private isRedirect(response: request.Response): boolean {
|
||||||
return [301, 307].indexOf(response.statusCode) !== -1 &&
|
return [301, 307].indexOf(response.statusCode) !== -1 &&
|
||||||
@@ -176,8 +172,8 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Check if response is successful
|
* Check if response is successful
|
||||||
*
|
*
|
||||||
* @param {request.Response} response response object
|
* @param response response object
|
||||||
* @returns {boolean} if response is successful
|
* @returns if response is successful
|
||||||
*/
|
*/
|
||||||
private isSuccess(response: request.Response): boolean {
|
private isSuccess(response: request.Response): boolean {
|
||||||
return [200, 201].indexOf(response.statusCode) !== -1;
|
return [200, 201].indexOf(response.statusCode) !== -1;
|
||||||
@@ -186,8 +182,8 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Check if response is error
|
* Check if response is error
|
||||||
*
|
*
|
||||||
* @param {request.Response} response response object
|
* @param response response object
|
||||||
* @returns {boolean} if response is error
|
* @returns if response is error
|
||||||
*/
|
*/
|
||||||
private isError(response: request.Response): boolean {
|
private isError(response: request.Response): boolean {
|
||||||
return [400, 401, 402, 403, 404, 500].indexOf(response.statusCode) !== -1;
|
return [400, 401, 402, 403, 404, 500].indexOf(response.statusCode) !== -1;
|
||||||
@@ -196,10 +192,8 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Send a request to WebHDFS REST API
|
* Send a request to WebHDFS REST API
|
||||||
*
|
*
|
||||||
* @param {string} method HTTP method
|
* @param method HTTP method
|
||||||
* @param {string} url
|
* @param opts Options for request
|
||||||
* @param {object} opts Options for request
|
|
||||||
* @param {(error: HdfsError, response: request.Response) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
private sendRequest(method: string, url: string, opts: object,
|
private sendRequest(method: string, url: string, opts: object,
|
||||||
@@ -234,10 +228,6 @@ export class WebHDFS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Change file permissions
|
* Change file permissions
|
||||||
*
|
|
||||||
* @param {string} path
|
|
||||||
* @param {string} mode
|
|
||||||
* @param {(error: HdfsError) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public chmod(path: string, mode: string, callback: (error: HdfsError) => void): void {
|
public chmod(path: string, mode: string, callback: (error: HdfsError) => void): void {
|
||||||
@@ -253,10 +243,8 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Change file owner
|
* Change file owner
|
||||||
*
|
*
|
||||||
* @param {string} path
|
* @param userId User name
|
||||||
* @param {string} userId User name
|
* @param groupId Group name
|
||||||
* @param {string} groupId Group name
|
|
||||||
* @param {(error: HdfsError) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public chown(path: string, userId: string, groupId: string, callback: (error: HdfsError) => void): void {
|
public chown(path: string, userId: string, groupId: string, callback: (error: HdfsError) => void): void {
|
||||||
@@ -279,8 +267,6 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Read directory contents
|
* Read directory contents
|
||||||
*
|
*
|
||||||
* @param {string} path
|
|
||||||
* @param {(error: HdfsError, files: any[]) => void)} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public readdir(path: string, callback: (error: HdfsError, files: any[]) => void): void {
|
public readdir(path: string, callback: (error: HdfsError, files: any[]) => void): void {
|
||||||
@@ -305,10 +291,6 @@ export class WebHDFS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Make new directory
|
* Make new directory
|
||||||
*
|
|
||||||
* @param {string} path
|
|
||||||
* @param {string} [permission=0755]
|
|
||||||
* @param {(error: HdfsError) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public mkdir(path: string, permission: string = '0755', callback: (error: HdfsError) => void): void {
|
public mkdir(path: string, permission: string = '0755', callback: (error: HdfsError) => void): void {
|
||||||
@@ -327,10 +309,6 @@ export class WebHDFS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Rename path
|
* Rename path
|
||||||
*
|
|
||||||
* @param {string} path
|
|
||||||
* @param {string} destination
|
|
||||||
* @param {(error: HdfsError) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public rename(path: string, destination: string, callback: (error: HdfsError) => void): void {
|
public rename(path: string, destination: string, callback: (error: HdfsError) => void): void {
|
||||||
@@ -350,9 +328,6 @@ export class WebHDFS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get file status for given path
|
* Get file status for given path
|
||||||
*
|
|
||||||
* @param {string} path
|
|
||||||
* @param {(error: HdfsError, fileStatus: any) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public stat(path: string, callback: (error: HdfsError, fileStatus: any) => void): void {
|
public stat(path: string, callback: (error: HdfsError, fileStatus: any) => void): void {
|
||||||
@@ -376,8 +351,6 @@ export class WebHDFS {
|
|||||||
* Wraps stat method
|
* Wraps stat method
|
||||||
*
|
*
|
||||||
* @see WebHDFS.stat
|
* @see WebHDFS.stat
|
||||||
* @param {string} path
|
|
||||||
* @param {(error: HdfsError, exists: boolean) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public exists(path: string, callback: (error: HdfsError, exists: boolean) => void): void {
|
public exists(path: string, callback: (error: HdfsError, exists: boolean) => void): void {
|
||||||
@@ -392,12 +365,7 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Write data to the file
|
* Write data to the file
|
||||||
*
|
*
|
||||||
* @param {string} path
|
* @param append If set to true then append data to the file
|
||||||
* @param {string | Buffer} data
|
|
||||||
* @param {boolean} append If set to true then append data to the file
|
|
||||||
* @param {object} opts
|
|
||||||
* @param {(error: HdfsError) => void} callback
|
|
||||||
* @returns {fs.WriteStream}
|
|
||||||
*/
|
*/
|
||||||
public writeFile(path: string, data: string | Buffer, append: boolean, opts: object,
|
public writeFile(path: string, data: string | Buffer, append: boolean, opts: object,
|
||||||
callback: (error: HdfsError) => void): fs.WriteStream {
|
callback: (error: HdfsError) => void): fs.WriteStream {
|
||||||
@@ -427,11 +395,6 @@ export class WebHDFS {
|
|||||||
* Append data to the file
|
* Append data to the file
|
||||||
*
|
*
|
||||||
* @see writeFile
|
* @see writeFile
|
||||||
* @param {string} path
|
|
||||||
* @param {string | Buffer} data
|
|
||||||
* @param {object} opts
|
|
||||||
* @param {(error: HdfsError) => void} callback
|
|
||||||
* @returns {fs.WriteStream}
|
|
||||||
*/
|
*/
|
||||||
public appendFile(path: string, data: string | Buffer, opts: object, callback: (error: HdfsError) => void): fs.WriteStream {
|
public appendFile(path: string, data: string | Buffer, opts: object, callback: (error: HdfsError) => void): fs.WriteStream {
|
||||||
return this.writeFile(path, data, true, opts, callback);
|
return this.writeFile(path, data, true, opts, callback);
|
||||||
@@ -442,8 +405,6 @@ export class WebHDFS {
|
|||||||
*
|
*
|
||||||
* @fires Request#data
|
* @fires Request#data
|
||||||
* @fires WebHDFS#finish
|
* @fires WebHDFS#finish
|
||||||
* @param {path} path
|
|
||||||
* @param {(error: HdfsError, buffer: Buffer) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public readFile(path: string, callback: (error: HdfsError, buffer: Buffer) => void): void {
|
public readFile(path: string, callback: (error: HdfsError, buffer: Buffer) => void): void {
|
||||||
@@ -475,10 +436,7 @@ export class WebHDFS {
|
|||||||
* Create writable stream for given path
|
* Create writable stream for given path
|
||||||
*
|
*
|
||||||
* @fires WebHDFS#finish
|
* @fires WebHDFS#finish
|
||||||
* @param {string} path
|
* @param [append] If set to true then append data to the file
|
||||||
* @param {boolean} [append] If set to true then append data to the file
|
|
||||||
* @param {object} [opts]
|
|
||||||
* @returns {fs.WriteStream}
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* let hdfs = WebHDFS.createClient();
|
* let hdfs = WebHDFS.createClient();
|
||||||
@@ -593,9 +551,6 @@ export class WebHDFS {
|
|||||||
*
|
*
|
||||||
* @fires Request#data
|
* @fires Request#data
|
||||||
* @fires WebHDFS#finish
|
* @fires WebHDFS#finish
|
||||||
* @param {string} path
|
|
||||||
* @param {object} [opts]
|
|
||||||
* @returns {fs.ReadStream}
|
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* let hdfs = WebHDFS.createClient();
|
* let hdfs = WebHDFS.createClient();
|
||||||
@@ -677,10 +632,6 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Create symbolic link to the destination path
|
* Create symbolic link to the destination path
|
||||||
*
|
*
|
||||||
* @param {string} src
|
|
||||||
* @param {string} destination
|
|
||||||
* @param {boolean} [createParent=false]
|
|
||||||
* @param {(error: HdfsError) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public symlink(src: string, destination: string, createParent: boolean = false, callback: (error: HdfsError) => void): void {
|
public symlink(src: string, destination: string, createParent: boolean = false, callback: (error: HdfsError) => void): void {
|
||||||
@@ -702,9 +653,6 @@ export class WebHDFS {
|
|||||||
/**
|
/**
|
||||||
* Unlink path
|
* Unlink path
|
||||||
*
|
*
|
||||||
* @param {string} path
|
|
||||||
* @param {boolean} [recursive=false]
|
|
||||||
* @param {(error: any) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public unlink(path: string, recursive: boolean = false, callback: (error: HdfsError) => void): void {
|
public unlink(path: string, recursive: boolean = false, callback: (error: HdfsError) => void): void {
|
||||||
@@ -720,9 +668,6 @@ export class WebHDFS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @alias WebHDFS.unlink
|
* @alias WebHDFS.unlink
|
||||||
* @param {string} path
|
|
||||||
* @param {boolean} [recursive=false]
|
|
||||||
* @param {(error: any) => void} callback
|
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
public rmdir(path: string, recursive: boolean = false, callback: (error: HdfsError) => void): void {
|
public rmdir(path: string, recursive: boolean = false, callback: (error: HdfsError) => void): void {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export default class ProgressIndicator {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
|
this._statusBarItem = window.createStatusBarItem(StatusBarAlignment.Left);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _tasks: string[] = [];
|
private _tasks: string[] = [];
|
||||||
public beginTask(task: string): void {
|
public beginTask(task: string): void {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user