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

@@ -12,110 +12,110 @@ const KUBECONFIG_PATH_KEY = 'mssql-bdc.kubeconfig';
const KNOWN_KUBECONFIGS_KEY = 'mssql-bdc.knownKubeconfigs';
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> {
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> {
if (!createIfNotExist) {
if (!valueAtScope || !(valueAtScope[configKey])) {
return;
}
}
if (!createIfNotExist) {
if (!valueAtScope || !(valueAtScope[configKey])) {
return;
}
}
let newValue: any = {};
if (valueAtScope) {
newValue = Object.assign({}, valueAtScope);
}
newValue[configKey] = value;
await vscode.workspace.getConfiguration().update(EXTENSION_CONFIG_KEY, newValue, scope);
let newValue: any = {};
if (valueAtScope) {
newValue = Object.assign({}, valueAtScope);
}
newValue[configKey] = value;
await vscode.workspace.getConfiguration().update(EXTENSION_CONFIG_KEY, newValue, scope);
}
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> {
if (!createIfNotExist) {
if (!valueAtScope || !(valueAtScope[configKey])) {
return;
}
}
if (!createIfNotExist) {
if (!valueAtScope || !(valueAtScope[configKey])) {
return;
}
}
let newValue: any = {};
if (valueAtScope) {
newValue = Object.assign({}, valueAtScope);
}
const arrayEntry: string[] = newValue[configKey] || [];
arrayEntry.push(value);
newValue[configKey] = arrayEntry;
await vscode.workspace.getConfiguration().update(EXTENSION_CONFIG_KEY, newValue, scope);
let newValue: any = {};
if (valueAtScope) {
newValue = Object.assign({}, valueAtScope);
}
const arrayEntry: string[] = newValue[configKey] || [];
arrayEntry.push(value);
newValue[configKey] = arrayEntry;
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>;
async function atAllConfigScopes<T>(fn: ConfigUpdater<T>, configKey: string, value: T): Promise<void> {
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.Workspace, config.workspaceValue, false);
await fn(configKey, value, vscode.ConfigurationTarget.WorkspaceFolder, config.workspaceFolderValue, false);
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.Workspace, config.workspaceValue, false);
await fn(configKey, value, vscode.ConfigurationTarget.WorkspaceFolder, config.workspaceFolderValue, false);
}
// Functions for working with the list of known kubeconfigs
export function getKnownKubeconfigs(): string[] {
const kkcConfig = vscode.workspace.getConfiguration(EXTENSION_CONFIG_KEY)[KNOWN_KUBECONFIGS_KEY];
if (!kkcConfig || !kkcConfig.length) {
return [];
}
return kkcConfig as string[];
const kkcConfig = vscode.workspace.getConfiguration(EXTENSION_CONFIG_KEY)[KNOWN_KUBECONFIGS_KEY];
if (!kkcConfig || !kkcConfig.length) {
return [];
}
return kkcConfig as 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
export async function setActiveKubeconfig(kubeconfig: string): Promise<void> {
await addPathToConfig(KUBECONFIG_PATH_KEY, kubeconfig);
await addPathToConfig(KUBECONFIG_PATH_KEY, kubeconfig);
}
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
export function getToolPath(host: Host, shell: Shell, tool: string): string | undefined {
const baseKey = toolPathBaseKey(tool);
return getPathSetting(host, shell, baseKey);
const baseKey = toolPathBaseKey(tool);
return getPathSetting(host, shell, baseKey);
}
function getPathSetting(host: Host, shell: Shell, baseKey: string): string | undefined {
const os = shell.platform();
const osOverridePath = host.getConfiguration(EXTENSION_CONFIG_KEY)[osOverrideKey(os, baseKey)];
return osOverridePath || host.getConfiguration(EXTENSION_CONFIG_KEY)[baseKey];
const os = shell.platform();
const osOverridePath = host.getConfiguration(EXTENSION_CONFIG_KEY)[osOverrideKey(os, baseKey)];
return osOverridePath || host.getConfiguration(EXTENSION_CONFIG_KEY)[baseKey];
}
export function toolPathBaseKey(tool: string): string {
return `mssql-bdc.${tool}-path`;
return `mssql-bdc.${tool}-path`;
}
function osOverrideKey(os: Platform, baseKey: string): string {
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
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
}
function osKeyString(os: Platform): string | null {
switch (os) {
case Platform.Windows: return 'windows';
case Platform.MacOS: return 'mac';
case Platform.Linux: return 'linux';
default: return null;
}
switch (os) {
case Platform.Windows: return 'windows';
case Platform.MacOS: return 'mac';
case Platform.Linux: return 'linux';
default: return null;
}
}

View File

@@ -10,36 +10,36 @@ import * as tmp from 'tmp';
import { succeeded, Errorable } from '../interfaces';
type DownloadFunc =
(url: string, destination?: string, options?: any)
=> Promise<Buffer> & stream.Duplex; // Stream has additional events - see https://www.npmjs.com/package/download
(url: string, destination?: string, options?: any)
=> Promise<Buffer> & stream.Duplex; // Stream has additional events - see https://www.npmjs.com/package/download
let download: DownloadFunc;
function ensureDownloadFunc() {
if (!download) {
const home = process.env['HOME'];
download = require('download');
if (home) {
process.env['HOME'] = home;
}
}
if (!download) {
const home = process.env['HOME'];
download = require('download');
if (home) {
process.env['HOME'] = home;
}
}
}
export async function toTempFile(sourceUrl: string): Promise<Errorable<string>> {
const tempFileObj = tmp.fileSync({ prefix: 'mssql-bdc-autoinstall-' });
const downloadResult = await to(sourceUrl, tempFileObj.name);
if (succeeded(downloadResult)) {
return { succeeded: true, result: tempFileObj.name };
}
return { succeeded: false, error: downloadResult.error };
const tempFileObj = tmp.fileSync({ prefix: 'mssql-bdc-autoinstall-' });
const downloadResult = await to(sourceUrl, tempFileObj.name);
if (succeeded(downloadResult)) {
return { succeeded: true, result: tempFileObj.name };
}
return { succeeded: false, error: downloadResult.error };
}
export async function to(sourceUrl: string, destinationFile: string): Promise<Errorable<null>> {
ensureDownloadFunc();
try {
await download(sourceUrl, path.dirname(destinationFile), { filename: path.basename(destinationFile) });
return { succeeded: true, result: null };
} catch (e) {
return { succeeded: false, error: [e.message] };
}
ensureDownloadFunc();
try {
await download(sourceUrl, path.dirname(destinationFile), { filename: path.basename(destinationFile) });
return { succeeded: true, result: null };
} catch (e) {
return { succeeded: false, error: [e.message] };
}
}

View File

@@ -16,57 +16,57 @@ import { Errorable, failed } from '../interfaces';
import { addPathToConfig, toolPathBaseKey } from '../config/config';
export async function installKubectl(shell: Shell): Promise<Errorable<null>> {
const tool = 'kubectl';
const binFile = (shell.isUnix()) ? 'kubectl' : 'kubectl.exe';
const os = platformUrlString(shell.platform());
const tool = 'kubectl';
const binFile = (shell.isUnix()) ? 'kubectl' : 'kubectl.exe';
const os = platformUrlString(shell.platform());
const version = await getStableKubectlVersion();
if (failed(version)) {
return { succeeded: false, error: version.error };
}
const version = await getStableKubectlVersion();
if (failed(version)) {
return { succeeded: false, error: version.error };
}
const installFolder = getInstallFolder(shell, tool);
mkdirp.sync(installFolder);
const installFolder = getInstallFolder(shell, tool);
mkdirp.sync(installFolder);
const kubectlUrl = `https://storage.googleapis.com/kubernetes-release/release/${version.result.trim()}/bin/${os}/amd64/${binFile}`;
const downloadFile = path.join(installFolder, binFile);
const downloadResult = await download.to(kubectlUrl, downloadFile);
if (failed(downloadResult)) {
return { succeeded: false, error: [localize('downloadKubectlFailed', 'Failed to download kubectl: {0}', downloadResult.error[0])] };
}
const kubectlUrl = `https://storage.googleapis.com/kubernetes-release/release/${version.result.trim()}/bin/${os}/amd64/${binFile}`;
const downloadFile = path.join(installFolder, binFile);
const downloadResult = await download.to(kubectlUrl, downloadFile);
if (failed(downloadResult)) {
return { succeeded: false, error: [localize('downloadKubectlFailed', 'Failed to download kubectl: {0}', downloadResult.error[0])] };
}
if (shell.isUnix()) {
fs.chmodSync(downloadFile, '0777');
}
if (shell.isUnix()) {
fs.chmodSync(downloadFile, '0777');
}
await addPathToConfig(toolPathBaseKey(tool), downloadFile);
return { succeeded: true, result: null };
await addPathToConfig(toolPathBaseKey(tool), downloadFile);
return { succeeded: true, result: null };
}
async function getStableKubectlVersion(): Promise<Errorable<string>> {
const downloadResult = await download.toTempFile('https://storage.googleapis.com/kubernetes-release/release/stable.txt');
if (failed(downloadResult)) {
return { succeeded: false, error: [localize('kubectlVersionCheckFailed', 'Failed to establish kubectl stable version: {0}', downloadResult.error[0])] };
}
const version = fs.readFileSync(downloadResult.result, 'utf-8');
fs.unlinkSync(downloadResult.result);
return { succeeded: true, result: version };
const downloadResult = await download.toTempFile('https://storage.googleapis.com/kubernetes-release/release/stable.txt');
if (failed(downloadResult)) {
return { succeeded: false, error: [localize('kubectlVersionCheckFailed', 'Failed to establish kubectl stable version: {0}', downloadResult.error[0])] };
}
const version = fs.readFileSync(downloadResult.result, 'utf-8');
fs.unlinkSync(downloadResult.result);
return { succeeded: true, result: version };
}
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 {
if (supported && supported.indexOf(platform) < 0) {
return null;
}
switch (platform) {
case Platform.Windows: return 'windows';
case Platform.MacOS: return 'darwin';
case Platform.Linux: return 'linux';
default: return null;
}
if (supported && supported.indexOf(platform) < 0) {
return null;
}
switch (platform) {
case Platform.Windows: return 'windows';
case Platform.MacOS: return 'darwin';
case Platform.Linux: return 'linux';
default: return null;
}
}

View File

@@ -3,7 +3,7 @@
* 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();
import { Shell } from '../utility/shell';
@@ -11,111 +11,111 @@ import { Host } from './host';
import { FS } from '../utility/fs';
export interface BinCheckContext {
readonly host: Host;
readonly fs: FS;
readonly shell: Shell;
readonly installDependenciesCallback: () => void;
binFound: boolean;
binPath: string;
readonly host: Host;
readonly fs: FS;
readonly shell: Shell;
readonly installDependenciesCallback: () => void;
binFound: boolean;
binPath: string;
}
interface FindBinaryResult {
err: number | null;
output: string;
err: number | null;
output: string;
}
async function findBinary(shell: Shell, binName: string): Promise<FindBinaryResult> {
let cmd = `which ${binName}`;
let cmd = `which ${binName}`;
if (shell.isWindows()) {
cmd = `where.exe ${binName}.exe`;
}
if (shell.isWindows()) {
cmd = `where.exe ${binName}.exe`;
}
const opts = {
async: true,
env: {
HOME: process.env.HOME,
PATH: process.env.PATH
}
};
const opts = {
async: true,
env: {
HOME: process.env.HOME,
PATH: process.env.PATH
}
};
const execResult = await shell.execCore(cmd, opts);
if (execResult.code) {
return { err: execResult.code, output: execResult.stderr };
}
const execResult = await shell.execCore(cmd, opts);
if (execResult.code) {
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 {
let bin = basePath;
if (shell.isWindows() && bin && !(bin.endsWith('.exe'))) {
bin = bin + '.exe';
}
return bin;
let bin = basePath;
if (shell.isWindows() && bin && !(bin.endsWith('.exe'))) {
bin = bin + '.exe';
}
return bin;
}
type CheckPresentFailureReason = 'inferFailed' | 'configuredFileMissing';
const installDependenciesAction = localize('installDependenciesAction','Install dependencies');
const learnMoreAction = localize('learnMoreAction','Learn more');
const installDependenciesAction = localize('installDependenciesAction', 'Install dependencies');
const learnMoreAction = localize('learnMoreAction', 'Learn more');
function alertNoBin(host: Host, binName: string, failureReason: CheckPresentFailureReason, message: string, installDependencies: () => void): void {
switch (failureReason) {
case 'inferFailed':
host.showErrorMessage(message, installDependenciesAction, learnMoreAction).then(
(str) => {
switch (str) {
case learnMoreAction:
host.showInformationMessage(localize('moreInfoMsg', 'Add {0} directory to path, or set "mssql-bdc.{0}-path" config to {0} binary.', binName));
break;
case installDependenciesAction:
installDependencies();
break;
}
switch (failureReason) {
case 'inferFailed':
host.showErrorMessage(message, installDependenciesAction, learnMoreAction).then(
(str) => {
switch (str) {
case learnMoreAction:
host.showInformationMessage(localize('moreInfoMsg', 'Add {0} directory to path, or set "mssql-bdc.{0}-path" config to {0} binary.', binName));
break;
case installDependenciesAction:
installDependencies();
break;
}
}
);
break;
case 'configuredFileMissing':
host.showErrorMessage(message, installDependenciesAction).then(
(str) => {
if (str === installDependenciesAction) {
installDependencies();
}
}
);
break;
}
}
);
break;
case 'configuredFileMissing':
host.showErrorMessage(message, installDependenciesAction).then(
(str) => {
if (str === installDependenciesAction) {
installDependencies();
}
}
);
break;
}
}
export async function checkForBinary(context: BinCheckContext, bin: string | undefined, binName: string, inferFailedMessage: string, configuredFileMissingMessage: string, alertOnFail: boolean): Promise<boolean> {
if (!bin) {
const fb = await findBinary(context.shell, binName);
if (!bin) {
const fb = await findBinary(context.shell, binName);
if (fb.err || fb.output.length === 0) {
if (alertOnFail) {
alertNoBin(context.host, binName, 'inferFailed', inferFailedMessage, context.installDependenciesCallback);
}
return false;
}
if (fb.err || fb.output.length === 0) {
if (alertOnFail) {
alertNoBin(context.host, binName, 'inferFailed', inferFailedMessage, context.installDependenciesCallback);
}
return false;
}
context.binFound = true;
context.binFound = true;
return true;
}
return true;
}
if (context.shell.isWindows) {
context.binFound = context.fs.existsSync(bin);
} else {
const sr = await context.shell.exec(`ls ${bin}`);
context.binFound = (!!sr && sr.code === 0);
}
if (context.binFound) {
context.binPath = bin;
} else {
if (alertOnFail) {
alertNoBin(context.host, binName, 'configuredFileMissing', configuredFileMissingMessage, context.installDependenciesCallback);
}
}
if (context.shell.isWindows) {
context.binFound = context.fs.existsSync(bin);
} else {
const sr = await context.shell.exec(`ls ${bin}`);
context.binFound = (!!sr && sr.code === 0);
}
if (context.binFound) {
context.binPath = bin;
} else {
if (alertOnFail) {
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';
interface CompatibilityGuaranteed {
readonly guaranteed: true;
readonly guaranteed: true;
}
interface CompatibilityNotGuaranteed {
readonly guaranteed: false;
readonly didCheck: boolean;
readonly clientVersion: string;
readonly serverVersion: string;
readonly guaranteed: false;
readonly didCheck: boolean;
readonly clientVersion: string;
readonly serverVersion: string;
}
export type Compatibility = CompatibilityGuaranteed | CompatibilityNotGuaranteed;
export function isGuaranteedCompatible(c: Compatibility): c is CompatibilityGuaranteed {
return c.guaranteed;
return c.guaranteed;
}
export interface Version {
readonly major: string;
readonly minor: string;
readonly gitVersion: string;
readonly major: string;
readonly minor: string;
readonly gitVersion: string;
}
export async function check(kubectlLoadJSON: (cmd: string) => Promise<Errorable<any>>): Promise<Compatibility> {
const version = await kubectlLoadJSON('version -o json');
if (failed(version)) {
return {
guaranteed: false,
didCheck: false,
clientVersion: '',
serverVersion: ''
};
}
const version = await kubectlLoadJSON('version -o json');
if (failed(version)) {
return {
guaranteed: false,
didCheck: false,
clientVersion: '',
serverVersion: ''
};
}
const clientVersion: Version = version.result.clientVersion;
const serverVersion: Version = version.result.serverVersion;
const clientVersion: Version = version.result.clientVersion;
const serverVersion: Version = version.result.serverVersion;
if (isCompatible(clientVersion, serverVersion)) {
return { guaranteed: true };
}
if (isCompatible(clientVersion, serverVersion)) {
return { guaranteed: true };
}
return {
guaranteed: false,
didCheck: true,
clientVersion: clientVersion.gitVersion,
serverVersion: serverVersion.gitVersion
};
return {
guaranteed: false,
didCheck: true,
clientVersion: clientVersion.gitVersion,
serverVersion: serverVersion.gitVersion
};
}
function isCompatible(clientVersion: Version, serverVersion: Version): boolean {
if (clientVersion.major === serverVersion.major) {
const clientMinor = Number.parseInt(clientVersion.minor);
const serverMinor = Number.parseInt(serverVersion.minor);
if (Number.isInteger(clientMinor) && Number.isInteger(serverMinor) && Math.abs(clientMinor - serverMinor) <= 1) {
return true;
}
}
return false;
if (clientVersion.major === serverVersion.major) {
const clientMinor = Number.parseInt(clientVersion.minor);
const serverMinor = Number.parseInt(serverVersion.minor);
if (Number.isInteger(clientMinor) && Number.isInteger(serverMinor) && Math.abs(clientMinor - serverMinor) <= 1) {
return true;
}
}
return false;
}

View File

@@ -6,37 +6,37 @@
import * as vscode from 'vscode';
export interface Host {
showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined>;
showWarningMessage(message: string, ...items: string[]): Thenable<string | undefined>;
showInformationMessage(message: string, ...items: string[]): Thenable<string | undefined>;
getConfiguration(key: string): any;
onDidChangeConfiguration(listener: (ch: vscode.ConfigurationChangeEvent) => any): vscode.Disposable;
showErrorMessage(message: string, ...items: string[]): Thenable<string | undefined>;
showWarningMessage(message: string, ...items: string[]): Thenable<string | undefined>;
showInformationMessage(message: string, ...items: string[]): Thenable<string | undefined>;
getConfiguration(key: string): any;
onDidChangeConfiguration(listener: (ch: vscode.ConfigurationChangeEvent) => any): vscode.Disposable;
}
export const host: Host = {
showErrorMessage : showErrorMessage,
showWarningMessage : showWarningMessage,
showInformationMessage : showInformationMessage,
getConfiguration : getConfiguration,
onDidChangeConfiguration : onDidChangeConfiguration,
showErrorMessage: showErrorMessage,
showWarningMessage: showWarningMessage,
showInformationMessage: showInformationMessage,
getConfiguration: getConfiguration,
onDidChangeConfiguration: onDidChangeConfiguration,
};
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> {
return vscode.window.showWarningMessage(message, ...items);
return vscode.window.showWarningMessage(message, ...items);
}
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 {
return vscode.workspace.getConfiguration(key);
return vscode.workspace.getConfiguration(key);
}
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';
export interface Kubectl {
checkPresent(errorMessageMode: CheckPresentMessageMode): Promise<boolean>;
asJson<T>(command: string): Promise<Errorable<T>>;
invokeAsync(command: string, stdin?: string): Promise<ShellResult | undefined>;
getContext(): Context;
checkPresent(errorMessageMode: CheckPresentMessageMode): Promise<boolean>;
asJson<T>(command: string): Promise<Errorable<T>>;
invokeAsync(command: string, stdin?: string): Promise<ShellResult | undefined>;
getContext(): Context;
}
interface Context {
readonly host: Host;
readonly fs: FS;
readonly shell: Shell;
readonly installDependenciesCallback: () => void;
binFound: boolean;
binPath: string;
readonly host: Host;
readonly fs: FS;
readonly shell: Shell;
readonly installDependenciesCallback: () => void;
binFound: boolean;
binPath: string;
}
class KubectlImpl implements Kubectl {
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' };
}
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' };
}
readonly context: Context;
readonly context: Context;
checkPresent(errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
return checkPresent(this.context, errorMessageMode);
}
asJson<T>(command: string): Promise<Errorable<T>> {
return asJson(this.context, command);
}
invokeAsync(command: string, stdin?: string): Promise<ShellResult | undefined> {
return invokeAsync(this.context, command, stdin);
}
checkPresent(errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
return checkPresent(this.context, errorMessageMode);
}
asJson<T>(command: string): Promise<Errorable<T>> {
return asJson(this.context, command);
}
invokeAsync(command: string, stdin?: string): Promise<ShellResult | undefined> {
return invokeAsync(this.context, command, stdin);
}
getContext(): Context {
return this.context;
}
getContext(): Context {
return this.context;
}
}
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 {
Command,
Activation,
Silent,
Command,
Activation,
Silent,
}
async function checkPresent(context: Context, errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
if (context.binFound) {
return true;
}
if (context.binFound) {
return true;
}
return await checkForKubectlInternal(context, errorMessageMode);
return await checkForKubectlInternal(context, errorMessageMode);
}
async function checkForKubectlInternal(context: Context, errorMessageMode: CheckPresentMessageMode): Promise<boolean> {
const binName = 'kubectl';
const bin = getToolPath(context.host, context.shell, binName);
const binName = 'kubectl';
const bin = getToolPath(context.host, context.shell, binName);
const contextMessage = getCheckKubectlContextMessage(errorMessageMode);
const inferFailedMessage = localize('binaryNotFound', 'Could not find {0} binary. {1}', binName, contextMessage);
const configuredFileMissingMessage = localize('binaryNotInstalled', '{0} is not installed. {1}', bin, contextMessage);
const contextMessage = getCheckKubectlContextMessage(errorMessageMode);
const inferFailedMessage = localize('binaryNotFound', 'Could not find {0} binary. {1}', binName, 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 {
if (errorMessageMode === CheckPresentMessageMode.Activation) {
return localize('kubernetesRequired',' SQL Server Big data cluster requires kubernetes.');
} else if (errorMessageMode === CheckPresentMessageMode.Command) {
return localize('cannotExecuteCmd', ' Cannot execute command.');
}
return '';
if (errorMessageMode === CheckPresentMessageMode.Activation) {
return localize('kubernetesRequired', ' SQL Server Big data cluster requires kubernetes.');
} else if (errorMessageMode === CheckPresentMessageMode.Command) {
return localize('cannotExecuteCmd', ' Cannot execute command.');
}
return '';
}
async function invokeAsync(context: Context, command: string, stdin?: string): Promise<ShellResult | undefined> {
if (await checkPresent(context, CheckPresentMessageMode.Command)) {
const bin = baseKubectlPath(context);
const cmd = `${bin} ${command}`;
const sr = await context.shell.exec(cmd, stdin);
if (sr && sr.code !== 0) {
checkPossibleIncompatibility(context);
}
return sr;
} else {
return { code: -1, stdout: '', stderr: '' };
}
if (await checkPresent(context, CheckPresentMessageMode.Command)) {
const bin = baseKubectlPath(context);
const cmd = `${bin} ${command}`;
const sr = await context.shell.exec(cmd, stdin);
if (sr && sr.code !== 0) {
checkPossibleIncompatibility(context);
}
return sr;
} else {
return { code: -1, stdout: '', stderr: '' };
}
}
// 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
async function checkPossibleIncompatibility(context: Context): Promise<void> {
if (checkedCompatibility) {
return;
}
checkedCompatibility = true;
const compat = await compatibility.check((cmd) => asJson<compatibility.Version>(context, cmd));
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);
context.host.showWarningMessage(versionAlert);
}
if (checkedCompatibility) {
return;
}
checkedCompatibility = true;
const compat = await compatibility.check((cmd) => asJson<compatibility.Version>(context, cmd));
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);
context.host.showWarningMessage(versionAlert);
}
}
export function baseKubectlPath(context: Context): string {
let bin = getToolPath(context.host, context.shell, 'kubectl');
if (!bin) {
bin = 'kubectl';
}
return bin;
let bin = getToolPath(context.host, context.shell, 'kubectl');
if (!bin) {
bin = 'kubectl';
}
return bin;
}
async function asJson<T>(context: Context, command: string): Promise<Errorable<T>> {
const shellResult = await invokeAsync(context, command);
if (!shellResult) {
return { succeeded: false, error: [localize('cannotRunCommand', 'Unable to run command ({0})', command)] };
}
const shellResult = await invokeAsync(context, command);
if (!shellResult) {
return { succeeded: false, error: [localize('cannotRunCommand', 'Unable to run command ({0})', command)] };
}
if (shellResult.code === 0) {
return { succeeded: true, result: JSON.parse(shellResult.stdout.trim()) as T };
if (shellResult.code === 0) {
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';
export interface KubectlContext {
readonly clusterName: string;
readonly contextName: string;
readonly userName: string;
readonly active: boolean;
readonly clusterName: string;
readonly contextName: string;
readonly userName: string;
readonly active: boolean;
}
interface Kubeconfig {
readonly apiVersion: string;
readonly 'current-context': string;
readonly clusters: {
readonly name: string;
readonly cluster: {
readonly server: string;
readonly 'certificate-authority'?: string;
readonly 'certificate-authority-data'?: string;
};
}[] | undefined;
readonly contexts: {
readonly name: string;
readonly context: {
readonly cluster: string;
readonly user: string;
readonly namespace?: string;
};
}[] | undefined;
readonly users: {
readonly name: string;
readonly user: {};
}[] | undefined;
readonly apiVersion: string;
readonly 'current-context': string;
readonly clusters: {
readonly name: string;
readonly cluster: {
readonly server: string;
readonly 'certificate-authority'?: string;
readonly 'certificate-authority-data'?: string;
};
}[] | undefined;
readonly contexts: {
readonly name: string;
readonly context: {
readonly cluster: string;
readonly user: string;
readonly namespace?: string;
};
}[] | undefined;
readonly users: {
readonly name: string;
readonly user: {};
}[] | undefined;
}
export interface ClusterConfig {
readonly server: string;
readonly certificateAuthority: string | undefined;
readonly server: string;
readonly certificateAuthority: string | undefined;
}
async function getKubeconfig(kubectl: Kubectl): Promise<Kubeconfig | null> {
const shellResult = await kubectl.asJson<any>('config view -o json');
if (failed(shellResult)) {
vscode.window.showErrorMessage(shellResult.error[0]);
return null;
}
return shellResult.result;
const shellResult = await kubectl.asJson<any>('config view -o json');
if (failed(shellResult)) {
vscode.window.showErrorMessage(shellResult.error[0]);
return null;
}
return shellResult.result;
}
export async function getCurrentClusterConfig(kubectl: Kubectl): Promise<ClusterConfig | undefined> {
const kubeConfig = await getKubeconfig(kubectl);
if (!kubeConfig || !kubeConfig.clusters || !kubeConfig.contexts) {
return undefined;
}
const contextConfig = kubeConfig.contexts.find((context) => context.name === kubeConfig['current-context'])!;
const clusterConfig = kubeConfig.clusters.find((cluster) => cluster.name === contextConfig.context.cluster)!;
return {
server: clusterConfig.cluster.server,
certificateAuthority: clusterConfig.cluster['certificate-authority']
};
const kubeConfig = await getKubeconfig(kubectl);
if (!kubeConfig || !kubeConfig.clusters || !kubeConfig.contexts) {
return undefined;
}
const contextConfig = kubeConfig.contexts.find((context) => context.name === kubeConfig['current-context'])!;
const clusterConfig = kubeConfig.clusters.find((cluster) => cluster.name === contextConfig.context.cluster)!;
return {
server: clusterConfig.cluster.server,
certificateAuthority: clusterConfig.cluster['certificate-authority']
};
}
export async function getContexts(kubectl: Kubectl): Promise<KubectlContext[]> {
const kubectlConfig = await getKubeconfig(kubectl);
if (!kubectlConfig) {
return [];
}
const currentContext = kubectlConfig['current-context'];
const contexts = kubectlConfig.contexts || [];
return contexts.map((c) => {
return {
clusterName: c.context.cluster,
contextName: c.name,
userName: c.context.user,
active: c.name === currentContext
};
});
const kubectlConfig = await getKubeconfig(kubectl);
if (!kubectlConfig) {
return [];
}
const currentContext = kubectlConfig['current-context'];
const contexts = kubectlConfig.contexts || [];
return contexts.map((c) => {
return {
clusterName: c.context.cluster,
contextName: c.name,
userName: c.context.user,
active: c.name === currentContext
};
});
}
export async function setContext(kubectl: Kubectl, targetContext: string): Promise<void> {
const shellResult = await kubectl.invokeAsync(`config use-context ${targetContext}`);
if (!shellResult || shellResult.code !== 0) {
// TODO: Update error handling for now.
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));
}
const shellResult = await kubectl.invokeAsync(`config use-context ${targetContext}`);
if (!shellResult || shellResult.code !== 0) {
// TODO: Update error handling for now.
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));
}
}
export async function inferCurrentClusterType(kubectl: Kubectl): Promise<ClusterType> {
let latestContextName = '';
let latestContextName = '';
const ctxsr = await kubectl.invokeAsync('config current-context');
if (ctxsr && ctxsr.code === 0) {
latestContextName = ctxsr.stdout.trim();
} else {
return ClusterType.Other;
}
const ctxsr = await kubectl.invokeAsync('config current-context');
if (ctxsr && ctxsr.code === 0) {
latestContextName = ctxsr.stdout.trim();
} else {
return ClusterType.Other;
}
const cisr = await kubectl.invokeAsync('cluster-info');
if (!cisr || cisr.code !== 0) {
return ClusterType.Unknown;
}
const masterInfos = cisr.stdout.split('\n')
.filter((s) => s.indexOf('master is running at') >= 0);
const cisr = await kubectl.invokeAsync('cluster-info');
if (!cisr || cisr.code !== 0) {
return ClusterType.Unknown;
}
const masterInfos = cisr.stdout.split('\n')
.filter((s) => s.indexOf('master is running at') >= 0);
if (masterInfos.length === 0) {
return ClusterType.Other;
}
if (masterInfos.length === 0) {
return ClusterType.Other;
}
const masterInfo = masterInfos[0];
if (masterInfo.indexOf('azmk8s.io') >= 0 || masterInfo.indexOf('azure.com') >= 0) {
return ClusterType.AKS;
}
const masterInfo = masterInfos[0];
if (masterInfo.indexOf('azmk8s.io') >= 0 || masterInfo.indexOf('azure.com') >= 0) {
return ClusterType.AKS;
}
if (latestContextName) {
const gcsr = await kubectl.invokeAsync(`config get-contexts ${latestContextName}`);
if (gcsr && gcsr.code === 0) {
if (gcsr.stdout.indexOf('minikube') >= 0) {
return ClusterType.Minikube;
}
}
}
if (latestContextName) {
const gcsr = await kubectl.invokeAsync(`config get-contexts ${latestContextName}`);
if (gcsr && gcsr.code === 0) {
if (gcsr.stdout.indexOf('minikube') >= 0) {
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();
export interface ISqlServerBigDataClusterChannel {
showOutput(message: any, title?: string): void;
showOutput(message: any, title?: string): void;
}
const outputChannelName = localize('bigDataClusterOutputChannel', 'SQL Server big data cluster');
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 {
if (title) {
const simplifiedTime = (new Date()).toISOString().replace(/z|t/gi, ' ').trim(); // YYYY-MM-DD HH:mm:ss.sss
const hightlightingTitle = `[${title} ${simplifiedTime}]`;
this.channel.appendLine(hightlightingTitle);
}
this.channel.appendLine(message);
this.channel.show();
}
showOutput(message: any, title?: string): void {
if (title) {
const simplifiedTime = (new Date()).toISOString().replace(/z|t/gi, ' ').trim(); // YYYY-MM-DD HH:mm:ss.sss
const hightlightingTitle = `[${title} ${simplifiedTime}]`;
this.channel.appendLine(hightlightingTitle);
}
this.channel.appendLine(message);
this.channel.show();
}
}
export const sqlserverbigdataclusterchannel: ISqlServerBigDataClusterChannel = new SqlServerBigDataCluster();

View File

@@ -35,26 +35,26 @@ export function deactivate(): void {
}
export async function installDependencies() {
const gotKubectl = await kubectl.checkPresent(CheckPresentMessageMode.Silent);
const gotKubectl = await kubectl.checkPresent(CheckPresentMessageMode.Silent);
const installPromises = [
installDependency('kubectl', gotKubectl, installKubectl)
];
const installPromises = [
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> {
if (alreadyGot) {
sqlserverbigdataclusterchannel.showOutput(localize('dependencyInstalled', '{0} already installed...', name));
} else {
sqlserverbigdataclusterchannel.showOutput(localize('installingDependency', 'Installing {0}...', name));
const result = await installFunc(shell);
if (failed(result)) {
sqlserverbigdataclusterchannel.showOutput(localize('installingDependencyFailed', 'Unable to install {0}: {1}', name, result.error[0]));
}
}
if (alreadyGot) {
sqlserverbigdataclusterchannel.showOutput(localize('dependencyInstalled', '{0} already installed...', name));
} else {
sqlserverbigdataclusterchannel.showOutput(localize('installingDependency', 'Installing {0}...', name));
const result = await installFunc(shell);
if (failed(result)) {
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 {
protected _context: vscode.ExtensionContext;
protected _kubectl : Kubectl;
protected _kubectl: Kubectl;
public constructor(context: vscode.ExtensionContext, kubectl: Kubectl) {
this._context = context;

View File

@@ -11,16 +11,16 @@ import mkdirp = require('mkdirp');
import { Kubectl, baseKubectlPath } from '../kubectl/kubectl';
import { KubectlContext } from '../kubectl/kubectlUtils';
export interface Scriptable {
getScriptProperties(): Promise<ScriptingDictionary<string>>;
getTargetKubectlContext() : KubectlContext;
}
export interface Scriptable {
getScriptProperties(): Promise<ScriptingDictionary<string>>;
getTargetKubectlContext(): KubectlContext;
}
export interface ScriptingDictionary<V> {
export interface ScriptingDictionary<V> {
[name: string]: V;
}
const deployFilePrefix : string = 'mssql-bdc-deploy';
const deployFilePrefix: string = 'mssql-bdc-deploy';
export class ScriptGenerator {
private _shell: Shell;
@@ -33,7 +33,7 @@ export class ScriptGenerator {
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 targetContextName = scriptable.getTargetKubectlContext().contextName;
@@ -67,7 +67,7 @@ export class ScriptGenerator {
}
const handleError = (err: NodeJS.ErrnoException) => {
if (err) {
vscode.window.showErrorMessage(err.message);
}
if (err) {
vscode.window.showErrorMessage(err.message);
}
};

View File

@@ -5,61 +5,61 @@
import * as sysfs from 'fs';
export interface FS {
existsSync(path: string): boolean;
readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
readFileSync(filename: string, encoding: string): string;
readFileToBufferSync(filename: string): Buffer;
writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
writeFileSync(filename: string, data: any): void;
dirSync(path: string): string[];
unlinkAsync(path: string): Promise<void>;
existsAsync(path: string): Promise<boolean>;
openAsync(path: string, flags: string): Promise<void>;
statSync(path: string): sysfs.Stats;
existsSync(path: string): boolean;
readFile(filename: string, encoding: string, callback: (err: NodeJS.ErrnoException, data: string) => void): void;
readFileSync(filename: string, encoding: string): string;
readFileToBufferSync(filename: string): Buffer;
writeFile(filename: string, data: any, callback?: (err: NodeJS.ErrnoException) => void): void;
writeFileSync(filename: string, data: any): void;
dirSync(path: string): string[];
unlinkAsync(path: string): Promise<void>;
existsAsync(path: string): Promise<boolean>;
openAsync(path: string, flags: string): Promise<void>;
statSync(path: string): sysfs.Stats;
}
export const fs: FS = {
existsSync: (path) => sysfs.existsSync(path),
readFile: (filename, encoding, callback) => sysfs.readFile(filename, encoding, callback),
readFileSync: (filename, encoding) => sysfs.readFileSync(filename, encoding),
readFileToBufferSync: (filename) => sysfs.readFileSync(filename),
writeFile: (filename, data, callback) => sysfs.writeFile(filename, data, callback),
writeFileSync: (filename, data) => sysfs.writeFileSync(filename, data),
dirSync: (path) => sysfs.readdirSync(path),
existsSync: (path) => sysfs.existsSync(path),
readFile: (filename, encoding, callback) => sysfs.readFile(filename, encoding, callback),
readFileSync: (filename, encoding) => sysfs.readFileSync(filename, encoding),
readFileToBufferSync: (filename) => sysfs.readFileSync(filename),
writeFile: (filename, data, callback) => sysfs.writeFile(filename, data, callback),
writeFileSync: (filename, data) => sysfs.writeFileSync(filename, data),
dirSync: (path) => sysfs.readdirSync(path),
unlinkAsync: (path) => {
return new Promise((resolve, reject) => {
sysfs.unlink(path, (error) => {
if (error) {
reject();
return;
}
unlinkAsync: (path) => {
return new Promise((resolve, reject) => {
sysfs.unlink(path, (error) => {
if (error) {
reject();
return;
}
resolve();
});
});
},
resolve();
});
});
},
existsAsync: (path) => {
return new Promise((resolve) => {
sysfs.exists(path, (exists) => {
resolve(exists);
});
});
},
existsAsync: (path) => {
return new Promise((resolve) => {
sysfs.exists(path, (exists) => {
resolve(exists);
});
});
},
openAsync: (path, flags) => {
return new Promise((resolve, reject) => {
sysfs.open(path, flags, (error, _fd) => {
if (error) {
reject();
return;
}
openAsync: (path, flags) => {
return new Promise((resolve, reject) => {
sysfs.open(path, flags, (error, _fd) => {
if (error) {
reject();
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';
export enum Platform {
Windows,
MacOS,
Linux,
Unsupported,
Windows,
MacOS,
Linux,
Unsupported,
}
export interface ExecCallback extends shelljs.ExecCallback {}
export interface ExecCallback extends shelljs.ExecCallback { }
export interface Shell {
isWindows(): boolean;
isUnix(): boolean;
platform(): Platform;
home(): string;
combinePath(basePath: string, relativePath: string): string;
fileUri(filePath: string): vscode.Uri;
execOpts(): any;
exec(cmd: string, stdin?: string): Promise<ShellResult | undefined>;
execCore(cmd: string, opts: any, stdin?: string): Promise<ShellResult>;
unquotedPath(path: string): string;
which(bin: string): string | null;
cat(path: string): string;
ls(path: string): string[];
isWindows(): boolean;
isUnix(): boolean;
platform(): Platform;
home(): string;
combinePath(basePath: string, relativePath: string): string;
fileUri(filePath: string): vscode.Uri;
execOpts(): any;
exec(cmd: string, stdin?: string): Promise<ShellResult | undefined>;
execCore(cmd: string, opts: any, stdin?: string): Promise<ShellResult>;
unquotedPath(path: string): string;
which(bin: string): string | null;
cat(path: string): string;
ls(path: string): string[];
}
export const shell: Shell = {
isWindows : isWindows,
isUnix : isUnix,
platform : platform,
home : home,
combinePath : combinePath,
fileUri : fileUri,
execOpts : execOpts,
exec : exec,
execCore : execCore,
unquotedPath : unquotedPath,
which: which,
cat: cat,
ls: ls,
isWindows: isWindows,
isUnix: isUnix,
platform: platform,
home: home,
combinePath: combinePath,
fileUri: fileUri,
execOpts: execOpts,
exec: exec,
execCore: execCore,
unquotedPath: unquotedPath,
which: which,
cat: cat,
ls: ls,
};
const WINDOWS: string = 'win32';
export interface ShellResult {
readonly code: number;
readonly stdout: string;
readonly stderr: string;
readonly code: number;
readonly stdout: string;
readonly stderr: string;
}
export type ShellHandler = (code: number, stdout: string, stderr: string) => void;
function isWindows(): boolean {
return (process.platform === WINDOWS);
return (process.platform === WINDOWS);
}
function isUnix(): boolean {
return !isWindows();
return !isWindows();
}
function platform(): Platform {
switch (process.platform) {
case 'win32': return Platform.Windows;
case 'darwin': return Platform.MacOS;
case 'linux': return Platform.Linux;
default: return Platform.Unsupported;
}
switch (process.platform) {
case 'win32': return Platform.Windows;
case 'darwin': return Platform.MacOS;
case 'linux': return Platform.Linux;
default: return Platform.Unsupported;
}
}
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 {
return process.env['HOME'] ||
concatIfBoth(process.env['HOMEDRIVE'], process.env['HOMEPATH']) ||
process.env['USERPROFILE'] ||
'';
return process.env['HOME'] ||
concatIfBoth(process.env['HOMEDRIVE'], process.env['HOMEPATH']) ||
process.env['USERPROFILE'] ||
'';
}
function combinePath(basePath: string, relativePath: string) {
let separator = '/';
if (isWindows()) {
relativePath = relativePath.replace(/\//g, '\\');
separator = '\\';
}
return basePath + separator + relativePath;
let separator = '/';
if (isWindows()) {
relativePath = relativePath.replace(/\//g, '\\');
separator = '\\';
}
return basePath + separator + relativePath;
}
function isWindowsFilePath(filePath: string) {
return filePath[1] === ':' && filePath[2] === '\\';
return filePath[1] === ':' && filePath[2] === '\\';
}
function fileUri(filePath: string): vscode.Uri {
if (isWindowsFilePath(filePath)) {
return vscode.Uri.parse('file:///' + filePath.replace(/\\/g, '/'));
}
return vscode.Uri.parse('file://' + filePath);
if (isWindowsFilePath(filePath)) {
return vscode.Uri.parse('file:///' + filePath.replace(/\\/g, '/'));
}
return vscode.Uri.parse('file://' + filePath);
}
function execOpts(): any {
let env = process.env;
if (isWindows()) {
env = Object.assign({ }, env, { HOME: home() });
}
env = shellEnvironment(env);
const opts = {
cwd: vscode.workspace.rootPath,
env: env,
async: true
};
return opts;
let env = process.env;
if (isWindows()) {
env = Object.assign({}, env, { HOME: home() });
}
env = shellEnvironment(env);
const opts = {
cwd: vscode.workspace.rootPath,
env: env,
async: true
};
return opts;
}
async function exec(cmd: string, stdin?: string): Promise<ShellResult | undefined> {
try {
return await execCore(cmd, execOpts(), stdin);
} catch (ex) {
vscode.window.showErrorMessage(ex);
return undefined;
}
try {
return await execCore(cmd, execOpts(), stdin);
} catch (ex) {
vscode.window.showErrorMessage(ex);
return undefined;
}
}
function execCore(cmd: string, opts: any, stdin?: string): Promise<ShellResult> {
return new Promise<ShellResult>((resolve) => {
const proc = shelljs.exec(cmd, opts, (code, stdout, stderr) => resolve({code : code, stdout : stdout, stderr : stderr}));
if (stdin) {
proc.stdin.end(stdin);
}
});
return new Promise<ShellResult>((resolve) => {
const proc = shelljs.exec(cmd, opts, (code, stdout, stderr) => resolve({ code: code, stdout: stdout, stderr: stderr }));
if (stdin) {
proc.stdin.end(stdin);
}
});
}
function unquotedPath(path: string): string {
if (isWindows() && path && path.length > 1 && path.startsWith('"') && path.endsWith('"')) {
return path.substring(1, path.length - 1);
}
return path;
if (isWindows() && path && path.length > 1 && path.startsWith('"') && path.endsWith('"')) {
return path.substring(1, path.length - 1);
}
return path;
}
export function shellEnvironment(baseEnvironment: any): any {
const env = Object.assign({}, baseEnvironment);
const pathVariable = pathVariableName(env);
for (const tool of ['kubectl']) {
const toolPath = getToolPath(host, shell, tool);
if (toolPath) {
const toolDirectory = path.dirname(toolPath);
const currentPath = env[pathVariable];
env[pathVariable] = toolDirectory + (currentPath ? `${pathEntrySeparator()}${currentPath}` : '');
}
}
const env = Object.assign({}, baseEnvironment);
const pathVariable = pathVariableName(env);
for (const tool of ['kubectl']) {
const toolPath = getToolPath(host, shell, tool);
if (toolPath) {
const toolDirectory = path.dirname(toolPath);
const currentPath = env[pathVariable];
env[pathVariable] = toolDirectory + (currentPath ? `${pathEntrySeparator()}${currentPath}` : '');
}
}
const kubeconfig = getActiveKubeconfig();
if (kubeconfig) {
env['KUBECONFIG'] = kubeconfig;
}
const kubeconfig = getActiveKubeconfig();
if (kubeconfig) {
env['KUBECONFIG'] = kubeconfig;
}
return env;
return env;
}
function pathVariableName(env: any): string {
if (isWindows()) {
for (const v of Object.keys(env)) {
if (v.toLowerCase() === 'path') {
return v;
}
}
}
return 'PATH';
if (isWindows()) {
for (const v of Object.keys(env)) {
if (v.toLowerCase() === 'path') {
return v;
}
}
}
return 'PATH';
}
function pathEntrySeparator() {
return isWindows() ? ';' : ':';
return isWindows() ? ';' : ':';
}
function which(bin: string): string | null {
return shelljs.which(bin);
return shelljs.which(bin);
}
function cat(path: string): string {
return shelljs.cat(path);
return shelljs.cat(path);
}
function ls(path: string): string[] {
return shelljs.ls(path);
return shelljs.ls(path);
}
export function shellMessage(sr: ShellResult | undefined, invocationFailureMessage: string): string {
if (!sr) {
return invocationFailureMessage;
}
return sr.code === 0 ? sr.stdout : sr.stderr;
if (!sr) {
return invocationFailureMessage;
}
return sr.code === 0 ? sr.stdout : sr.stderr;
}

View File

@@ -2,10 +2,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';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { WizardPageBase } from '../../wizardPageBase';
import { CreateClusterWizard } from '../createClusterWizard';
import * as nls from 'vscode-nls';
@@ -347,7 +345,7 @@ export class ClusterProfilePage extends WizardPageBase<CreateClusterWizard> {
case ClusterPoolType.Spark:
return localize('bdc-create.SparkPoolDisplayName', 'Spark pool');
default:
throw 'unknown pool type';
throw new Error('unknown pool type');
}
}
@@ -364,7 +362,7 @@ export class ClusterProfilePage extends WizardPageBase<CreateClusterWizard> {
case ClusterPoolType.Spark:
return localize('bdc-create.SparkPoolDescription', 'TODO: Add description');
default:
throw 'unknown pool type';
throw new Error('unknown pool type');
}
}

View File

@@ -2,7 +2,6 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as azdata from 'azdata';
import { WizardPageBase } from '../../wizardPageBase';