From 179c0ba5b663f1d035f809d22ee84dc6b1e646dc Mon Sep 17 00:00:00 2001 From: Mariana Mihova <10135329+marianan@users.noreply.github.com> Date: Mon, 29 Mar 2021 07:31:00 -0700 Subject: [PATCH] Allow user to select between Edge Runtime 1.0 or 1.1 (#569) * Allow user to select between Edge Runtime 1.0 or 1.1 * Update per PR feedback * Fix lint issues * Update a stale link in readme * Update based on PR feedback --- CHANGELOG.md | 3 ++ README.md | 2 +- package-lock.json | 46 ++++++++++++++++++++----------- package.json | 31 +++++++++++++-------- src/common/constants.ts | 6 +++- src/common/version.ts | 41 ++++++++++++++++++++++++--- src/container/containerManager.ts | 4 +-- src/edge/edgeManager.ts | 45 +++++++++++++++++++++++++++++- src/edge/simulator.ts | 4 ++- src/extension.ts | 8 ++++++ 10 files changed, 153 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc347c91..ba70ceb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ # Change Log +## 1.24.0 - 2021-3-26 +### Changed +* Allow user to select Edge Runtime version between 1.0 and 1.1 ## 1.23.0 - 2020-9-23 ### Fixed diff --git a/README.md b/README.md index 9f592ee6..2c7ce82c 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ You can also trigger following frequently-used commands in context menu. - [Develop and deploy a Python module](https://docs.microsoft.com/azure/iot-edge/tutorial-python-module) - [Develop and deploy a Node.js module](https://docs.microsoft.com/azure/iot-edge/tutorial-node-module) - [Develop and deploy a C module](https://docs.microsoft.com/azure/iot-edge/tutorial-c-module) -- [Register a new Azure IoT Edge device](https://docs.microsoft.com/en-us/azure/iot-edge/how-to-register-device-vscode) +- [Register a new Azure IoT Edge device](https://docs.microsoft.com/en-us/azure/iot-edge/how-to-register-device) - [Deploy Azure IoT Edge modules](https://docs.microsoft.com/azure/iot-edge/how-to-deploy-modules-vscode) - [Debug C# module](https://docs.microsoft.com/azure/iot-edge/how-to-develop-csharp-module) - [Debug Node.js module](https://docs.microsoft.com/azure/iot-edge/how-to-develop-node-module) diff --git a/package-lock.json b/package-lock.json index 871e33e0..952de02d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "azure-iot-edge", - "version": "1.23.0", + "version": "1.24.0-rc1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1883,18 +1883,32 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + } } }, "emitter-listener": { @@ -2971,9 +2985,9 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "interpret": { "version": "1.2.0", @@ -6366,9 +6380,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xmldom": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz", + "integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==" }, "xpath.js": { "version": "1.1.0", diff --git a/package.json b/package.json index 60a5d5c6..80c580a0 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "azure-iot-edge", "displayName": "Azure IoT Edge", "description": "This extension is now a part of Azure IoT Tools extension pack. We highly recommend installing Azure IoT Tools to get full capabilities for Azure IoT development. Develop, deploy, debug, and manage your IoT Edge solution.", - "version": "1.23.0", + "version": "1.24.0-rc1", "publisher": "vsciot-vscode", "aiKey": "95b20d64-f54f-4de3-8ad5-165a75a6c6fe", "icon": "logo.png", @@ -43,6 +43,7 @@ "onCommand:azure-iot-edge.addModule", "onCommand:azure-iot-edge.stopSolution", "onCommand:azure-iot-edge.setupIotedgehubdev", + "onCommand:azure-iot-edge.setDefaultEdgeRuntimeVersion", "onCommand:azure-iot-edge.startEdgeHubSingle", "onCommand:azure-iot-edge.setModuleCred", "onCommand:azure-iot-edge.setDefaultPlatform", @@ -166,6 +167,11 @@ "title": "Setup IoT Edge Simulator", "category": "Azure IoT Edge" }, + { + "command": "azure-iot-edge.setDefaultEdgeRuntimeVersion", + "title": "Set Default IoT Edge Runtime Version", + "category": "Azure IoT Edge" + }, { "command": "azure-iot-edge.startEdgeHubSingle", "title": "Start IoT Edge Hub Simulator for Single Module", @@ -191,16 +197,6 @@ "type": "object", "title": "Azure IoT Edge configuration", "properties": { - "azure-iot-edge.version.edgeHub": { - "type": "string", - "default": "1.0", - "description": "Set the edgeHub image version, which will be referenced in deployment manifest." - }, - "azure-iot-edge.version.edgeAgent": { - "type": "string", - "default": "1.0", - "description": "Set the edgeAgent image version, which will be referenced in deployment manifest." - }, "azure-iot-edge.version.tempSensor": { "type": "string", "default": "1.0", @@ -284,6 +280,19 @@ }, "description": "Current default target platform for Edge Module" }, + "azure-iot-edge.version.supported.edgeRuntime": { + "type": "array", + "default": [ + "1.0", + "1.1" + ], + "description": "List of supported Edge Runtime images versions" + }, + "azure-iot-edge.version.default.edgeRuntime": { + "type": "string", + "default": "1.0", + "description": "Set the edgeAgent and edgeHub images version, which will be referenced in deployment manifest." + }, "azure-iot-edge.3rdPartyModuleTemplates": { "type": "object", "default": {}, diff --git a/src/common/constants.ts b/src/common/constants.ts index 89661123..df0f65de 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -14,7 +14,7 @@ export class Constants { public static deploymentTemplatePattern = "**/deployment.template.json"; public static debugDeploymentTemplatePattern = "**/deployment.debug.template.json"; public static tsonPattern = "**/*.template.json"; - public static deploymentTsonPattern = "**/deployment.*.template.json,**/deployment.template.json"; + public static deploymentJsonPattern = "**/deployment.*.template.json,**/deployment.template.json"; public static tson = ".template.json"; public static deploymentTemplateDesc = "Deployment Template file"; public static deploymentFilePattern = "**/deployment.json"; @@ -89,6 +89,7 @@ export class Constants { public static moduleName = "Module Name"; public static moduleNamePrompt = "Provide a Module Name"; public static moduleNameDft = "SampleModule"; + public static edgeRuntimeVersionPrompt = "Select Azure IoT Edge Runtime (Edge Hub and Edge Agent images) version"; public static registryPlaceholder = ""; public static repoNamePlaceholder = ""; public static tagPlaceholder = ""; @@ -108,6 +109,7 @@ export class Constants { public static runSolutionEvent = "runSolution"; public static generateDeploymentEvent = "generateDeployment"; public static addModuleEvent = "addModule"; + public static selectEdgeRuntimeVerEvent = "selectEdgeVer"; public static launchCSharp = "launch_csharp.json"; public static launchNode = "launch_node.json"; public static launchC = "launch_c.json"; @@ -159,6 +161,8 @@ export class Constants { public static versionEdgeAgent = "version.edgeAgent"; public static versionEdgeHub = "version.edgeHub"; + public static versionEdgeRuntime = "version.supported.edgeRuntime"; + public static versionDefaultEdgeRuntime = "version.default.edgeRuntime"; public static versionTempSensor = "version.tempSensor"; public static versionCModule = "version.cmodule"; public static versionPythonModule = "version.pythonmodule"; diff --git a/src/common/version.ts b/src/common/version.ts index 497fac92..f2c1ccb6 100644 --- a/src/common/version.ts +++ b/src/common/version.ts @@ -1,6 +1,8 @@ import { Configuration } from "./configuration"; import { Constants } from "./constants"; +type ImageJson = "${string}:${string}"; + export class Versions { public static getRunTimeVersionMap(): Map { const verMap: Map = new Map(); @@ -9,6 +11,10 @@ export class Versions { return verMap; } + public static getSupportedEdgeRuntimeVersions(): string[] { + return Versions.getValue(Constants.versionEdgeRuntime, []) as string[]; + } + public static installCSharpTemplate(): boolean { return Versions.getValue(Constants.installCSharpModule, true) as boolean; } @@ -49,15 +55,42 @@ export class Versions { return Versions.getValue(Constants.versionTempSensor, "1.0") as string; } + public static updateSystemModuleImageVersion(templateJson: any, moduleName: string, versionMap: Map) { + if (templateJson !== undefined) { + const sysModuleImage = + templateJson.modulesContent.$edgeAgent["properties.desired"].systemModules[moduleName].settings.image; + templateJson.modulesContent.$edgeAgent["properties.desired"].systemModules[moduleName].settings.image = + Versions.getNewImageVersionJson(sysModuleImage, versionMap); + } + } + + public static edgeHubVersion(): string { + return Versions.getDefaultEdgeRuntimeVersion(); + } + private static edgeAgentVersion(): string { - return Versions.getValue(Constants.versionEdgeAgent) as string; + return Versions.getDefaultEdgeRuntimeVersion(); } - private static edgeHubVersion(): string { - return Versions.getValue(Constants.versionEdgeHub, "1.0") as string; + private static getDefaultEdgeRuntimeVersion(): string { + return Versions.getValue(Constants.versionDefaultEdgeRuntime, "1.0") as string; + } + + private static getNewImageVersionJson(input: ImageJson, versionMap: Map): string { + if (input !== undefined) { + const imageName: string = input.split(":")[0]; + switch (imageName) { + case "mcr.microsoft.com/azureiotedge-agent": + return imageName + ":" + versionMap.get(Constants.edgeAgentVerPlaceHolder); + case "mcr.microsoft.com/azureiotedge-hub": + return imageName + ":" + versionMap.get(Constants.edgeHubVerPlaceHolder); + default: + return input; + } + } } - private static getValue(key: string, defaultVal: string|boolean = null): string | boolean { + private static getValue(key: string, defaultVal: string|string[]|boolean = null): string | string[] | boolean { const value = Configuration.getConfigurationProperty(key); if (value === undefined || value === null) { return defaultVal; diff --git a/src/container/containerManager.ts b/src/container/containerManager.ts index 228c89c3..39e0f30c 100644 --- a/src/container/containerManager.ts +++ b/src/container/containerManager.ts @@ -43,7 +43,7 @@ export class ContainerManager { } public async buildSolution(outputChannel: vscode.OutputChannel, templateUri?: vscode.Uri, push: boolean = true, run: boolean = false): Promise { - const pattern = `{${Constants.deploymentTsonPattern}}`; + const pattern = `{${Constants.deploymentJsonPattern}}`; const templateFile: string = await Utility.getInputFilePath(templateUri, pattern, Constants.deploymentTemplateDesc, @@ -56,7 +56,7 @@ export class ContainerManager { } public async generateDeployment(outputChannel: vscode.OutputChannel, templateUri?: vscode.Uri): Promise { - const pattern = `{${Constants.deploymentTsonPattern}}`; + const pattern = `{${Constants.deploymentJsonPattern}}`; const templateFile: string = await Utility.getInputFilePath(templateUri, pattern, Constants.deploymentTemplateDesc, diff --git a/src/edge/edgeManager.ts b/src/edge/edgeManager.ts index 0730318b..d6f0806b 100644 --- a/src/edge/edgeManager.ts +++ b/src/edge/edgeManager.ts @@ -59,7 +59,7 @@ export class EdgeManager { } public async addModuleForSolution(outputChannel: vscode.OutputChannel, templateUri?: vscode.Uri): Promise { - const pattern = `{${Constants.deploymentTsonPattern}}`; + const pattern = `{${Constants.deploymentJsonPattern}}`; let templateFile: string = await Utility.getInputFilePath(templateUri, pattern, Constants.deploymentTemplateDesc, @@ -156,6 +156,27 @@ export class EdgeManager { } } + public async selectDefaultEdgeRuntimeVersion(outputChannel: vscode.OutputChannel) { + const edgeRuntimeVersions: string[] = Versions.getSupportedEdgeRuntimeVersions(); + const edgeVersionPick = await vscode.window.showQuickPick(edgeRuntimeVersions, { placeHolder: Constants.edgeRuntimeVersionPrompt, ignoreFocusOut: true }); + if (!edgeVersionPick) { + throw new UserCancelledError(); + } + + TelemetryClient.sendEvent(`${Constants.selectEdgeRuntimeVerEvent}`, { + template: edgeVersionPick, + }); + + await Configuration.setWorkspaceConfigurationProperty(Constants.versionDefaultEdgeRuntime, edgeVersionPick); + outputChannel.appendLine(`Default Azure IoT Edge Runtime is ${edgeVersionPick} now.`); + + // If there is an active workspace, update the deployment templates + // with the desired runtime version + if (Utility.checkWorkspace() !== undefined) { + await this.updateRuntimeVersionInDeploymentTemplate(); + } + } + public async selectDefaultPlatform(outputChannel: vscode.OutputChannel) { if (!Utility.checkWorkspace(Constants.noWorkspaceSetDefaultPlatformMsg)) { return; @@ -372,6 +393,28 @@ export class EdgeManager { } } + private async updateRuntimeVersionInDeploymentTemplate() { + const pattern = `{${Constants.deploymentJsonPattern}}`; + const description = `${Constants.deploymentTemplateDesc}`; + + const fileList: vscode.Uri[] = await vscode.workspace.findFiles(pattern); + if (!fileList || fileList.length === 0) { + vscode.window.showErrorMessage(`No ${description} can be found under this workspace.`); + return; + } + + const versionMap = Versions.getRunTimeVersionMap(); + for (const deploymentTemplateFile of fileList) { + const deploymentTemplateFilePath: string = deploymentTemplateFile.fsPath; + const templateJson = await fse.readJson(deploymentTemplateFilePath); + + Versions.updateSystemModuleImageVersion(templateJson, "edgeAgent", versionMap); + Versions.updateSystemModuleImageVersion(templateJson, "edgeHub", versionMap); + + await fse.writeFile(deploymentTemplateFilePath, JSON.stringify(templateJson, null, 2), { encoding: "utf8" }); + } + } + private async addModuleToDeploymentTemplate(templateJson: any, templateFile: string, envFilePath: string, moduleInfo: ModuleInfo, isTempsensorNeeded: boolean, isDebug: boolean = false): Promise<{ usernameEnv: string, passwordEnv: string }> { const modules = templateJson.modulesContent.$edgeAgent["properties.desired"].modules; diff --git a/src/edge/simulator.ts b/src/edge/simulator.ts index 21027c91..2b338901 100644 --- a/src/edge/simulator.ts +++ b/src/edge/simulator.ts @@ -20,6 +20,7 @@ import { SimulatorInfo } from "../common/SimulatorInfo"; import { TelemetryClient } from "../common/telemetryClient"; import { UserCancelledError } from "../common/UserCancelledError"; import { Utility } from "../common/utility"; +import { Versions } from "../common/version"; import { IDeviceItem } from "../typings/IDeviceItem"; import { InstallResult, InstallReturn } from "./InstallResult"; @@ -156,8 +157,9 @@ export class Simulator { return await this.callWithInstallationCheck(outputChannel, async () => { await this.checkIoTedgehubdevConnectionString(outputChannel); const inputs = await this.inputInputNames(); + const imgVersion = Versions.edgeHubVersion(); await this.setModuleCred(outputChannel); - await Executor.runInTerminal(Simulator.adjustTerminalCommand(this.getAdjustedSimulatorExecutorPath() + ` start -i "${inputs}"`)); + await Executor.runInTerminal(Simulator.adjustTerminalCommand(this.getAdjustedSimulatorExecutorPath() + ` start -er "${imgVersion}" -i "${inputs}"`)); }); } diff --git a/src/extension.ts b/src/extension.ts index e68a6db1..284144fd 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -176,6 +176,14 @@ export function activate(context: vscode.ExtensionContext) { return configDiagnosticProvider.updateDiagnostics(document, diagCollection); }); + initCommandAsync(context, outputChannel, + "azure-iot-edge.setDefaultEdgeRuntimeVersion", + async (): Promise => { + await edgeManager.selectDefaultEdgeRuntimeVersion(outputChannel); + const document = vscode.window && vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document : null; + return configDiagnosticProvider.updateDiagnostics(document, diagCollection); + }); + initCommandAsync(context, outputChannel, "azure-iot-edge.showGallery", async (): Promise => {