Adding auto sync support (#41)
* Adding auto sync support * Updated delete and push to support login * Fixes based on feedback.
This commit is contained in:
Родитель
c539ead5cf
Коммит
e7a9226ea3
|
@ -73,6 +73,7 @@ This extension requires:
|
|||
- [Terraform](https://www.terraform.io/downloads.html)
|
||||
- [Docker](http://www.docker.io) if you are running the execute test feature locally.
|
||||
- [GraphViz dot](http://www.graphviz.org) if you are using the visualize feature.
|
||||
|
||||
- NOTE: On Windows after installing the graphViz msi/zip, you will most likely need to add your PATH env variable `(Ex. c:\Program Files(x86)\GraphViz2.38\bin)` in order to use dot from the command line.
|
||||
|
||||
## Supported Environments
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"workspaceContains:**/*.tf",
|
||||
"onCommand:vscode-terraform-azure.init",
|
||||
"onCommand:vscode-terraform-azure.plan",
|
||||
"onCommand:vscode-terraform-azure.apply",
|
||||
|
@ -41,6 +42,11 @@
|
|||
"default": "**/*.{tf,txt,yml,tfvars,rb}",
|
||||
"description": "Indicates the files that should be synchronized to Azure cloudshell using the glob pattern string, for example: **/*.{tf,txt,yml,tfvars,rb}"
|
||||
},
|
||||
"tf-azure.syncEnabled": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "When terminal is set to `cloudshell`, indicates whether changes to files that match tf-azure.files setting glob pattern should automatically sync to cloudshell."
|
||||
},
|
||||
"tf-azure.test-container": {
|
||||
"type": "string",
|
||||
"default": "microsoft/terraform-test",
|
||||
|
|
|
@ -4,7 +4,7 @@ import { BaseShell } from "./baseShell";
|
|||
import { openCloudConsole, OSes } from "./cloudConsole";
|
||||
import { delay } from "./cloudConsoleLauncher";
|
||||
import { aciConfig, Constants, exportContainerCmd, exportTestScript } from "./Constants";
|
||||
import { azFilePush, escapeFile, TerminalType, TFTerminal } from "./shared";
|
||||
import { azFileDelete, azFilePush, escapeFile, TerminalType, TFTerminal } from "./shared";
|
||||
|
||||
import { CSTerminal } from "./utilities";
|
||||
|
||||
|
@ -32,19 +32,20 @@ export class CloudShell extends BaseShell {
|
|||
TerminalType.CloudShell,
|
||||
Constants.TerraformTerminalName);
|
||||
|
||||
public async pushFiles(files: vscode.Uri[]) {
|
||||
public async pushFiles(files: vscode.Uri[], syncAllFiles: boolean) {
|
||||
this.outputChannel.appendLine("Attempting to upload files to CloudShell");
|
||||
const RETRY_INTERVAL = 500;
|
||||
const RETRY_TIMES = 30;
|
||||
|
||||
// Checking if the terminal has been created
|
||||
if (( this.csTerm.terminal != null) && (this.csTerm.storageAccountKey != null)) {
|
||||
for (let i = 0; i < RETRY_TIMES; i++ ) {
|
||||
if (this.csTerm.ws.readyState !== ws.OPEN ) {
|
||||
// Checking if the terminal has been created and user is logged in.
|
||||
await this.checkInitTerm();
|
||||
|
||||
for (let i = 0; i < RETRY_TIMES; i++) {
|
||||
if (this.csTerm.ws.readyState !== ws.OPEN) {
|
||||
// wait for valid ws connection
|
||||
await delay (RETRY_INTERVAL);
|
||||
await delay(RETRY_INTERVAL);
|
||||
} else {
|
||||
for (const file of files.map( (a) => a.fsPath)) {
|
||||
for (const file of files.map((a) => a.fsPath)) {
|
||||
try {
|
||||
if (await fsExtra.pathExists(file)) {
|
||||
this.outputChannel.appendLine(`Uploading file ${file} to cloud shell`);
|
||||
|
@ -56,34 +57,14 @@ export class CloudShell extends BaseShell {
|
|||
this.outputChannel.appendLine(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (syncAllFiles) {
|
||||
vscode.window.showInformationMessage(
|
||||
"Uploaded all the text files in the current workspace to CloudShell");
|
||||
"Synced all matched files in the current workspace to CloudShell");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const message = "Do you want to open CloudShell?";
|
||||
const ok: MessageItem = { title : "Yes" };
|
||||
const cancel: MessageItem = { title : "No", isCloseAffordance: true };
|
||||
vscode.window.showWarningMessage(message, ok, cancel).then( (response) => {
|
||||
if ( response === ok ) {
|
||||
this.startCloudShell().then((terminal) => {
|
||||
this.csTerm.terminal = terminal[0];
|
||||
this.csTerm.ws = terminal[1];
|
||||
this.csTerm.storageAccountName = terminal[2];
|
||||
this.csTerm.storageAccountKey = terminal[3];
|
||||
this.csTerm.fileShareName = terminal[4];
|
||||
this.csTerm.ResourceGroup = terminal[5];
|
||||
this.outputChannel.appendLine(`Obtained cloudshell terminal, retrying push files.\n`);
|
||||
this.pushFiles(files);
|
||||
return;
|
||||
});
|
||||
} else {
|
||||
console.log("Push to cloud shell cancelled by user.");
|
||||
}
|
||||
});
|
||||
// TODO THIS LINE SEEMS UNNECESSARY console.log("Cloudshell terminal not opened when trying to transfer files");
|
||||
}
|
||||
}
|
||||
|
||||
public async pullFiles(files: vscode.Uri[]) {
|
||||
|
@ -91,7 +72,29 @@ export class CloudShell extends BaseShell {
|
|||
}
|
||||
|
||||
public async deleteFiles(files: vscode.Uri[]) {
|
||||
return;
|
||||
const RETRY_INTERVAL = 500;
|
||||
const RETRY_TIMES = 3;
|
||||
|
||||
// Checking if the terminal has been created and user is logged in.
|
||||
await this.checkInitTerm();
|
||||
|
||||
for (let i = 0; i < RETRY_TIMES; i++) {
|
||||
if (this.csTerm.ws.readyState !== ws.OPEN) {
|
||||
// wait for valid ws connection
|
||||
await delay(RETRY_INTERVAL);
|
||||
} else {
|
||||
for (const file of files.map((a) => a.fsPath)) {
|
||||
try {
|
||||
this.outputChannel.appendLine(`Deleting file ${file} from cloud shell`);
|
||||
await azFileDelete(this.csTerm.storageAccountName,
|
||||
this.csTerm.storageAccountKey,
|
||||
this.csTerm.fileShareName, file);
|
||||
} catch (err) {
|
||||
this.outputChannel.appendLine(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected runTerraformInternal(TFCommand: string, WorkDir: string) {
|
||||
|
@ -286,37 +289,24 @@ export class CloudShell extends BaseShell {
|
|||
|
||||
}
|
||||
|
||||
protected async uploadTFFiles(TFFiles) {
|
||||
console.log("Uploading files to CloudShell");
|
||||
const RETRY_INTERVAL = 500;
|
||||
const RETRY_TIMES = 30;
|
||||
protected stop(interval: NodeJS.Timer): void {
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
// Checking if the terminal has been created
|
||||
if ( (this.csTerm.terminal != null) && (this.csTerm.storageAccountKey != null) ) {
|
||||
for (let i = 0; i < RETRY_TIMES; i++ ) {
|
||||
if (this.csTerm.ws.readyState !== ws.OPEN ) {
|
||||
await delay (RETRY_INTERVAL);
|
||||
} else {
|
||||
for (const file of TFFiles.map( (a) => a.fsPath)) {
|
||||
try {
|
||||
if (fsExtra.existsSync(file)) {
|
||||
console.log(`Uploading file ${file} to cloud shell`);
|
||||
azFilePush(this.csTerm.storageAccountName, this.csTerm.storageAccountKey, this.csTerm.fileShareName, file);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
vscode.window.showInformationMessage("Uploaded all the text files in the current workspace to CloudShell");
|
||||
break;
|
||||
}
|
||||
private async delayWrap(ms: number) {
|
||||
await delay(500);
|
||||
}
|
||||
|
||||
private checkInitTerm(): Promise<void> {
|
||||
return new Promise<void> ((resolve, reject) => {
|
||||
if ((this.csTerm.terminal !== null) && (this.csTerm.storageAccountKey !== undefined)) {
|
||||
resolve();
|
||||
} else {
|
||||
const message = "Do you want to open CloudShell?";
|
||||
const ok: MessageItem = { title : "Yes" };
|
||||
const cancel: MessageItem = { title : "No", isCloseAffordance: true };
|
||||
vscode.window.showWarningMessage(message, ok, cancel).then( (response) => {
|
||||
if ( response === ok ) {
|
||||
const ok: MessageItem = { title: "Yes" };
|
||||
const cancel: MessageItem = { title: "No", isCloseAffordance: true };
|
||||
vscode.window.showWarningMessage(message, ok, cancel).then((response) => {
|
||||
if (response === ok) {
|
||||
this.startCloudShell().then((terminal) => {
|
||||
this.csTerm.terminal = terminal[0];
|
||||
this.csTerm.ws = terminal[1];
|
||||
|
@ -324,18 +314,17 @@ export class CloudShell extends BaseShell {
|
|||
this.csTerm.storageAccountKey = terminal[3];
|
||||
this.csTerm.fileShareName = terminal[4];
|
||||
this.csTerm.ResourceGroup = terminal[5];
|
||||
console.log(`Obtained terminal and fileshare data\n`);
|
||||
this.uploadTFFiles(TFFiles);
|
||||
return;
|
||||
this.outputChannel.appendLine(`Obtained cloudshell terminal, retrying push files.\n`);
|
||||
this.delayWrap(500);
|
||||
resolve();
|
||||
}).catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
} else {
|
||||
console.log("Push to cloud shell cancelled by user.");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
console.log("Terminal not opened when trying to transfer files");
|
||||
}
|
||||
}
|
||||
|
||||
protected stop(interval: NodeJS.Timer): void {
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// Import the module and reference it with the alias vscode in your code below
|
||||
import * as vscode from "vscode";
|
||||
|
||||
import { commands, Disposable, extensions, GlobPattern, window } from "vscode";
|
||||
import { commands, Disposable, extensions, GlobPattern, MessageItem, window } from "vscode";
|
||||
|
||||
import { AzureServiceClient, BaseResource } from "ms-rest-azure";
|
||||
import { join } from "path";
|
||||
|
@ -20,6 +20,9 @@ import { isDotInstalled } from "./utils/dotUtils";
|
|||
let cs: CloudShell;
|
||||
let is: IntegratedShell;
|
||||
let outputChannel: vscode.OutputChannel;
|
||||
let fileWatcher: vscode.FileSystemWatcher;
|
||||
let isFirstPush = true;
|
||||
let _disposable: Disposable;
|
||||
|
||||
function getShell(): BaseShell {
|
||||
let activeShell = null;
|
||||
|
@ -35,6 +38,7 @@ function getShell(): BaseShell {
|
|||
function init(): void {
|
||||
cs = new CloudShell(outputChannel);
|
||||
is = new IntegratedShell(outputChannel);
|
||||
initFileWatcher();
|
||||
outputChannel.show();
|
||||
}
|
||||
|
||||
|
@ -48,18 +52,13 @@ export function activate(ctx: vscode.ExtensionContext) {
|
|||
|
||||
outputChannel.appendLine("Loading extension");
|
||||
|
||||
const fileWatcher = vscode.workspace.createFileSystemWatcher(filesGlobSetting());
|
||||
|
||||
// TODO: Implement filewatcher handlers and config to automatically sync changes in workspace to cloudshell.
|
||||
fileWatcher.onDidDelete((deletedUri) => {
|
||||
outputChannel.appendLine("Deleted: " + deletedUri.path);
|
||||
});
|
||||
fileWatcher.onDidCreate((createdUri) => {
|
||||
outputChannel.appendLine("Created: " + createdUri.path);
|
||||
});
|
||||
fileWatcher.onDidChange((changedUri) => {
|
||||
outputChannel.appendLine("Changed: " + changedUri.path);
|
||||
});
|
||||
ctx.subscriptions.push(vscode.workspace.onDidChangeConfiguration((e) => {
|
||||
if (e.affectsConfiguration("tf-azure.files")) {
|
||||
// dispose of current file watcher and re-init
|
||||
fileWatcher.dispose();
|
||||
initFileWatcher();
|
||||
}
|
||||
}));
|
||||
|
||||
ctx.subscriptions.push(vscode.commands.registerCommand("vscode-terraform-azure.init", () => {
|
||||
getShell().runTerraformCmd("terraform init", Constants.clouddrive);
|
||||
|
@ -106,7 +105,7 @@ export function activate(ctx: vscode.ExtensionContext) {
|
|||
// Create a function that will sync the files to Cloudshell
|
||||
if (terminalSetToCloudshell()) {
|
||||
vscode.workspace.findFiles(filesGlobSetting()).then((tfFiles) => {
|
||||
cs.pushFiles(tfFiles);
|
||||
cs.pushFiles(tfFiles, true);
|
||||
});
|
||||
} else {
|
||||
vscode.window.showErrorMessage("Push function only available when using cloudshell.")
|
||||
|
@ -122,6 +121,10 @@ export function filesGlobSetting(): GlobPattern {
|
|||
return vscode.workspace.getConfiguration("tf-azure").get("files") as GlobPattern;
|
||||
}
|
||||
|
||||
export function workspaceSyncEnabled(): boolean {
|
||||
return vscode.workspace.getConfiguration("tf-azure").get("syncEnabled") as boolean;
|
||||
}
|
||||
|
||||
export async function TFLogin(api: AzureAccount) {
|
||||
outputChannel.appendLine("Attempting - TFLogin");
|
||||
if (!(await api.waitForLogin())) {
|
||||
|
@ -129,3 +132,47 @@ export async function TFLogin(api: AzureAccount) {
|
|||
}
|
||||
outputChannel.appendLine("Succeeded - TFLogin");
|
||||
}
|
||||
|
||||
function initFileWatcher(): void {
|
||||
// TODO: Implement filewatcher handlers and config to automatically sync changes in workspace to cloudshell.
|
||||
const subscriptions: Disposable[] = [];
|
||||
|
||||
fileWatcher = vscode.workspace.createFileSystemWatcher(filesGlobSetting());
|
||||
|
||||
// enable file watcher to detect file changes.
|
||||
fileWatcher.onDidDelete((deletedUri) => {
|
||||
if (terminalSetToCloudshell() && workspaceSyncEnabled()) {
|
||||
|
||||
cs.deleteFiles([deletedUri]);
|
||||
}
|
||||
}, this, subscriptions);
|
||||
fileWatcher.onDidCreate((createdUri) => {
|
||||
pushHelper(createdUri);
|
||||
}, this, subscriptions);
|
||||
fileWatcher.onDidChange((changedUri) => {
|
||||
pushHelper(changedUri);
|
||||
}, this, subscriptions);
|
||||
|
||||
this._disposable = Disposable.from(...subscriptions);
|
||||
}
|
||||
|
||||
function pushHelper(uri: vscode.Uri) {
|
||||
if (terminalSetToCloudshell() && workspaceSyncEnabled()) {
|
||||
if (isFirstPush) {
|
||||
// do initial sync of workspace before enabling file watcher.
|
||||
vscode.workspace.findFiles(filesGlobSetting()).then((tfFiles) => {
|
||||
cs.pushFiles(tfFiles, false);
|
||||
});
|
||||
isFirstPush = false;
|
||||
return;
|
||||
}
|
||||
cs.pushFiles([uri], false);
|
||||
}
|
||||
}
|
||||
|
||||
export function deactivate(): void {
|
||||
this._disposable.dispose();
|
||||
if (fileWatcher) {
|
||||
fileWatcher.dispose();
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче