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:
Anthony Dresser
2019-04-18 00:34:53 -07:00
committed by GitHub
parent b852f032d3
commit ddd89fc52a
431 changed files with 3147 additions and 3789 deletions

View File

@@ -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'

View File

@@ -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'

View File

@@ -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';

View File

@@ -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');
}
})); }));
} }

View File

@@ -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');

View File

@@ -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);
}); });
}); });
} };

View File

@@ -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;

View File

@@ -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 || {};

View File

@@ -1,3 +1,3 @@
{ {
"adminToolExtWin.launchSsmsServerPropertiesDialog": "Properties" "adminToolExtWin.launchSsmsServerPropertiesDialog": "Properties"
} }

View File

@@ -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"
] ]
} }

View File

@@ -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);

View File

@@ -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();

View File

@@ -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);

View File

@@ -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"');
}); });
}); });

View File

@@ -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);
} }

View File

@@ -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"
] ]
} }

View File

@@ -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';

View File

@@ -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;
} }
} }

View File

@@ -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

View File

@@ -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));
} }
} }

View File

@@ -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;

View File

@@ -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
} }

View File

@@ -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;
} }

View File

@@ -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));
} }
} }

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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 = [];
} }

View File

@@ -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(() => {

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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()

View File

@@ -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;
} }

View File

@@ -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 {
} }
} }

View File

@@ -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" ]
]
} }

View File

@@ -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) => {

View File

@@ -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 {

View File

@@ -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';

View File

@@ -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

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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';

View File

@@ -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);
} }

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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';

View File

@@ -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';

View File

@@ -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');

View File

@@ -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;
} }
} }

View File

@@ -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] };
} }
} }

View File

@@ -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;
} }
} }

View File

@@ -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;
} }

View File

@@ -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;
} }

View File

@@ -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);
} }

View File

@@ -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] };
} }

View File

@@ -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;
} }

View File

@@ -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();

View File

@@ -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]));
} }
} }
} }

View File

@@ -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;

View File

@@ -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);
} }
}; };

View File

@@ -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)
}; };

View File

@@ -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;
} }

View File

@@ -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');
} }
} }

View File

@@ -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';

View File

@@ -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.

View File

@@ -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;
} }
} }

View File

@@ -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.

View File

@@ -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;
} }

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;
} }
} }

View File

@@ -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;

View File

@@ -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"
] ]
} }

View File

@@ -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');

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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
}; };

View File

@@ -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"
} }

View File

@@ -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>;
} }

View File

@@ -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

View File

@@ -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 => {

View File

@@ -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> -----------------------------

View File

@@ -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');

View File

@@ -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;

View File

@@ -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.');

View File

@@ -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 {

View File

@@ -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;
} }
} }

View File

@@ -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)));
} }
}); });
}); });
} }

View File

@@ -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;

View File

@@ -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;

View File

@@ -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.

View File

@@ -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();
} }
/** /**

View File

@@ -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>;
} }

View File

@@ -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 {

View File

@@ -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