Skip to content

Commit

Permalink
Add tests for 'configure' (Add docker files to workspace) (microsoft#303
Browse files Browse the repository at this point in the history
)

* Add tests for 'configure'

* Python

* Linux

* work

* work

* Fix casing

* clean-up

* Remove randomness.ts, fix assert message

* Update to 0.1.0-alpha

* Revert "Update to 0.1.0-alpha"

This reverts commit f175340.

* PR comments

* fix lint

* fix lint

* fix build

* increase timeout
  • Loading branch information
StephenWeatherford authored Jul 18, 2018
1 parent c238460 commit ea78dc7
Show file tree
Hide file tree
Showing 16 changed files with 867 additions and 100 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ package-lock.json

# Artifacts from running vscode extension tests
.vscode-test
testOutput
.vs
30 changes: 27 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,35 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
],
"env": {
"NO_TIMEOUTS": "1",
},
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": ["${workspaceRoot}/out/**/*.js"],
"outFiles": [
"${workspaceRoot}/out/**/*.js"
],
"preLaunchTask": "npm"
},
{
"name": "Launch Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceRoot}/test/test.code-workspace",
"--extensionDevelopmentPath=${workspaceRoot}",
"--extensionTestsPath=${workspaceRoot}/out/test"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/test"
],
"preLaunchTask": "npm"
}
]
}
}
2 changes: 2 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ typings/**
**/*.map
.gitignore
tsconfig.json
test/**
testOutput/**
56 changes: 42 additions & 14 deletions configureWorkspace/config-utils.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,70 @@
import vscode = require('vscode');
import { IAzureQuickPickItem, IAzureUserInput } from 'vscode-azureextensionui';
import { ext } from "../extensionVariables";

export type OS = 'Windows' | 'Linux';
export type Platform = 'Go' |
'Java' |
'.NET Core Console' |
'ASP.NET Core' |
'Node.js' |
'Python' |
'Other';

/**
* Prompts for a port number
* @throws `UserCancelledError` if the user cancels.
*/
export async function promptForPort(port: number): Promise<string> {
let opt: vscode.InputBoxOptions = {
placeHolder: `${port}`,
prompt: 'What port does your app listen on?',
value: `${port}`
}

return vscode.window.showInputBox(opt);
return ext.ui.showInputBox(opt);
}

export async function quickPickPlatform(): Promise<string> {
/**
* Prompts for a platform
* @throws `UserCancelledError` if the user cancels.
*/
export async function quickPickPlatform(): Promise<Platform> {
let opt: vscode.QuickPickOptions = {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: 'Select Application Platform'
}

const items: string[] = [];
items.push('Go');
items.push('Java');
items.push('.NET Core Console');
items.push('ASP.NET Core');
items.push('Node.js');
items.push('Python');
items.push('Other');
const platforms: Platform[] = [
'Go',
'Java',
'.NET Core Console',
'ASP.NET Core',
'Node.js',
'Python',
'Other'
];

return vscode.window.showQuickPick(items, opt);
const items = platforms.map(p => <IAzureQuickPickItem<Platform>>{ label: p, data: p });
let response = await ext.ui.showQuickPick(items, opt);
return response.data;
}

export async function quickPickOS(): Promise<string> {
/**
* Prompts for an OS
* @throws `UserCancelledError` if the user cancels.
*/
export async function quickPickOS(): Promise<OS> {
let opt: vscode.QuickPickOptions = {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: 'Select Operating System'
}

const items: string[] = ['Windows', 'Linux'];
const OSes: OS[] = ['Windows', 'Linux'];
const items = OSes.map(p => <IAzureQuickPickItem<OS>>{ label: p, data: p });

return vscode.window.showQuickPick(items, opt);
let response = await ext.ui.showQuickPick(items, opt);
return response.data;
}
102 changes: 47 additions & 55 deletions configureWorkspace/configure.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as fs from 'fs';
import * as glob from 'glob';
import * as gradleParser from 'gradle-to-js/lib/parser';
import { match } from 'minimatch';
import * as path from 'path';
import * as pomParser from 'pom-parser';
import vscode = require('vscode');
import * as gradleParser from "gradle-to-js/lib/parser";
import * as path from "path";
import * as pomParser from "pom-parser";
import * as vscode from "vscode";
import { globAsync } from '../helpers/async';
import { reporter } from '../telemetry/telemetry';
import { promptForPort, quickPickOS, quickPickPlatform } from './config-utils';
import { OS, Platform, promptForPort, quickPickOS, quickPickPlatform } from './config-utils';

// tslint:disable-next-line:max-func-body-length
function genDockerFile(serviceName: string, platform: string, os: string, port: string, { cmd, author, version, artifactName }: PackageJson): string {
Expand Down Expand Up @@ -400,8 +400,8 @@ interface PackageJson {
artifactName: string
}

async function getPackageJson(folder: vscode.WorkspaceFolder): Promise<vscode.Uri[]> {
return vscode.workspace.findFiles(new vscode.RelativePattern(folder, 'package.json'), null, 1, null);
async function getPackageJson(folderPath: string): Promise<vscode.Uri[]> {
return vscode.workspace.findFiles(new vscode.RelativePattern(folderPath, 'package.json'), null, 1, null);
}

function getDefaultPackageJson(): PackageJson {
Expand All @@ -415,9 +415,9 @@ function getDefaultPackageJson(): PackageJson {
};
}

async function readPackageJson(folder: vscode.WorkspaceFolder): Promise<PackageJson> {
async function readPackageJson(folderPath: string): Promise<PackageJson> {
// open package.json and look for main, scripts start
const uris: vscode.Uri[] = await getPackageJson(folder);
const uris: vscode.Uri[] = await getPackageJson(folderPath);
let pkg: PackageJson = getDefaultPackageJson(); //default

if (uris && uris.length > 0) {
Expand Down Expand Up @@ -447,13 +447,13 @@ async function readPackageJson(folder: vscode.WorkspaceFolder): Promise<PackageJ
return pkg;
}

async function readPomOrGradle(folder: vscode.WorkspaceFolder): Promise<PackageJson> {
async function readPomOrGradle(folderPath: string): Promise<PackageJson> {
let pkg: PackageJson = getDefaultPackageJson(); //default

if (fs.existsSync(path.join(folder.uri.fsPath, 'pom.xml'))) {
const json = await new Promise<any>((resolve, reject) => {
if (fs.existsSync(path.join(folderPath, 'pom.xml'))) {
let json = await new Promise<any>((resolve, reject) => {
pomParser.parse({
filePath: path.join(folder.uri.fsPath, 'pom.xml')
filePath: path.join(folderPath, 'pom.xml')
}, (error, response) => {
if (error) {
reject(`Failed to parse pom.xml: ${error}`);
Expand All @@ -462,16 +462,17 @@ async function readPomOrGradle(folder: vscode.WorkspaceFolder): Promise<PackageJ
resolve(response.pomObject);
});
});
json = json || {};

if (json.project.version) {
if (json.project && json.project.version) {
pkg.version = json.project.version;
}

if (json.project.artifactid) {
if (json.project && json.project.artifactid) {
pkg.artifactName = `target/${json.project.artifactid}-${pkg.version}.jar`;
}
} else if (fs.existsSync(path.join(folder.uri.fsPath, 'build.gradle'))) {
const json = await gradleParser.parseFile(path.join(folder.uri.fsPath, 'build.gradle'));
} else if (fs.existsSync(path.join(folderPath, 'build.gradle'))) {
const json = await gradleParser.parseFile(path.join(folderPath, 'build.gradle'));

if (json.jar && json.jar.version) {
pkg.version = json.jar.version;
Expand All @@ -482,32 +483,23 @@ async function readPomOrGradle(folder: vscode.WorkspaceFolder): Promise<PackageJ
if (json.jar && json.jar.archiveName) {
pkg.artifactName = `build/libs/${json.jar.archiveName}`;
} else {
const baseName = json.jar && json.jar.baseName ? json.jar.baseName : json.archivesBaseName || folder.name;
const baseName = json.jar && json.jar.baseName ? json.jar.baseName : json.archivesBaseName || path.basename(folderPath);
pkg.artifactName = `build/libs/${baseName}-${pkg.version}.jar`;
}
}

return pkg;
}

async function findCSProjFile(folder: vscode.WorkspaceFolder): Promise<string> {
// Returns the relative path of the project file without the extension
async function findCSProjFile(folderPath: string): Promise<string> {
const opt: vscode.QuickPickOptions = {
matchOnDescription: true,
matchOnDetail: true,
placeHolder: 'Select Project'
}

const projectFiles: string[] = await new Promise<string[]>((resolve, reject) => {

glob('**/*.csproj', { cwd: folder.uri.fsPath }, (err, matches: string[]) => {
if (err) {
reject();
} else {
resolve(matches);
}
});

});
const projectFiles: string[] = await globAsync('**/*.csproj', { cwd: folderPath });

if (!projectFiles) {
return;
Expand Down Expand Up @@ -546,53 +538,53 @@ const YES_OR_NO_PROMPT: vscode.MessageItem[] = [
}
];

export async function configure(): Promise<void> {
let folder: vscode.WorkspaceFolder;
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1) {
folder = vscode.workspace.workspaceFolders[0];
} else {
folder = await (<any>vscode).window.showWorkspaceFolderPick();
}

if (!folder) {
if (!vscode.workspace.workspaceFolders) {
vscode.window.showErrorMessage('Docker files can only be generated if VS Code is opened on a folder.');
export async function configure(folderPath?: string): Promise<void> {
if (!folderPath) {
let folder: vscode.WorkspaceFolder;
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1) {
folder = vscode.workspace.workspaceFolders[0];
} else {
vscode.window.showErrorMessage('Docker files can only be generated if a workspace folder is picked in VS Code.');
folder = await vscode.window.showWorkspaceFolderPick();
}
return;

if (!folder) {
if (!vscode.workspace.workspaceFolders) {
throw new Error('Docker files can only be generated if VS Code is opened on a folder.');
} else {
throw new Error('Docker files can only be generated if a workspace folder is picked in VS Code.');
}
}

folderPath = folder.uri.fsPath;
}

const platformType = await quickPickPlatform();
if (!platformType) { return; }
const platformType: Platform = await quickPickPlatform();

let os;
let os: OS | undefined;
if (platformType.toLowerCase().includes('.net')) {
os = await quickPickOS();
if (!os) { return; }
}

let port;
let port: string;
if (platformType.toLowerCase().includes('.net')) {
port = await promptForPort(80);
} else {
port = await promptForPort(3000);
}
if (!port) { return; }

let serviceName: string;
if (platformType.toLowerCase().includes('.net')) {
serviceName = await findCSProjFile(folder);
serviceName = await findCSProjFile(folderPath);
} else {
serviceName = path.basename(folder.uri.fsPath).toLowerCase();
serviceName = path.basename(folderPath).toLowerCase();
}
if (!serviceName) { return; }

let pkg: PackageJson = getDefaultPackageJson();
if (platformType.toLowerCase() === 'java') {
pkg = await readPomOrGradle(folder);
pkg = await readPomOrGradle(folderPath);
} else {
pkg = await readPackageJson(folder);
pkg = await readPackageJson(folderPath);
}

await Promise.all(Object.keys(DOCKER_FILE_TYPES).map(async (fileName) => {
Expand All @@ -616,7 +608,7 @@ export async function configure(): Promise<void> {
});

async function createWorkspaceFileIfNotExists(fileName: string, generatorFunction: GeneratorFunction): Promise<void> {
const workspacePath = path.join(folder.uri.fsPath, fileName);
const workspacePath = path.join(folderPath, fileName);
if (fs.existsSync(workspacePath)) {
const item: vscode.MessageItem = await vscode.window.showErrorMessage(`A ${fileName} already exists. Would you like to override it?`, ...YES_OR_NO_PROMPT);
if (item.title.toLowerCase() === 'yes') {
Expand Down
13 changes: 9 additions & 4 deletions dockerExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import * as opn from 'opn';
import * as path from 'path';
import vscode = require('vscode');

import { AzureUserInput } from 'vscode-azureextensionui';
import { ConfigurationParams, DidChangeConfigurationNotification, DocumentSelector, LanguageClient, LanguageClientOptions, Middleware, ServerOptions, TransportKind } from 'vscode-languageclient';
import { buildImage } from './commands/build-image';
import { composeDown, composeUp } from './commands/docker-compose';
Expand Down Expand Up @@ -36,14 +38,14 @@ import { AzureImageNode, AzureRegistryNode, AzureRepositoryNode } from './explor
import { DockerHubImageNode, DockerHubOrgNode, DockerHubRepositoryNode } from './explorer/models/dockerHubNodes';
import { browseAzurePortal } from './explorer/utils/azureUtils';
import { browseDockerHub, dockerHubLogout } from './explorer/utils/dockerHubUtils';
import { ext } from "./extensionVariables";
import { Reporter } from './telemetry/telemetry';
import { AzureAccount } from './typings/azure-account.api';

export const FROM_DIRECTIVE_PATTERN = /^\s*FROM\s*([\w-\/:]*)(\s*AS\s*[a-z][a-z0-9-_\\.]*)?$/i;
export const COMPOSE_FILE_GLOB_PATTERN = '**/[dD]ocker-[cC]ompose*.{yaml,yml}';
export const DOCKERFILE_GLOB_PATTERN = '**/{*.dockerfile,[dD]ocker[fF]ile}';

export let diagnosticCollection: vscode.DiagnosticCollection;
export let dockerExplorerProvider: DockerExplorerProvider;

export type KeyInfo = { [keyName: string]: string; };
Expand All @@ -65,11 +67,14 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
const outputChannel = util.getOutputChannel();
let azureAccount: AzureAccount;

// This allows for standard interactions with the end user (as opposed to test input)
ext.ui = new AzureUserInput(ctx.globalState);

for (let i = 0; i < installedExtensions.length; i++) {
const ext = installedExtensions[i];
if (ext.id === 'ms-vscode.azure-account') {
const extension = installedExtensions[i];
if (extension.id === 'ms-vscode.azure-account') {
try {
azureAccount = await ext.activate();
azureAccount = await extension.activate();
} catch (error) {
console.log('Failed to activate the Azure Account Extension: ' + error);
}
Expand Down
Loading

0 comments on commit ea78dc7

Please sign in to comment.