From a20c1f691db0a44b496d6cfb82e08118484a163d Mon Sep 17 00:00:00 2001 From: Shivangi Date: Mon, 25 Mar 2019 12:58:01 +0530 Subject: [PATCH 01/13] Multiple images loading --- .../resources.resjson/en-US/resources.resjson | 6 +++ .../AzureWebAppContainerV1/package-lock.json | 6 +++ Tasks/AzureWebAppContainerV1/task.json | 37 ++++++++++++++++- Tasks/AzureWebAppContainerV1/task.loc.json | 37 ++++++++++++++++- .../AzureWebAppContainerV1/taskparameters.ts | 2 +- .../ContainerBasedDeploymentUtility.ts | 40 ++++++++++++++++--- 6 files changed, 119 insertions(+), 9 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson index c6a999aebac1..315d4406a290 100644 --- a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson @@ -17,6 +17,12 @@ "loc.input.help.slotName": "Enter or Select an existing Slot other than the Production slot.", "loc.input.label.imageName": "Image name", "loc.input.help.imageName": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'.", + "loc.input.label.ConfigurationType": "Configuration Type", + "loc.input.help.ConfigurationType": "Type of the configuration: File Path or Inline Configuration", + "loc.input.label.ConfigurationPath": "Configuration Path", + "loc.input.help.ConfigurationPath": "Path of the configuration. Should be fully qualified path or relative to the default working directory.", + "loc.input.label.Inline": "Inline Configuration", + "loc.input.help.Inline": "Enter the script to execute.", "loc.input.label.containerCommand": "Startup command ", "loc.input.label.appSettings": "App settings", "loc.input.help.appSettings": "Edit web app application settings following the syntax -key value . Value containing spaces should be enclosed in double quotes.
Example : -Port 5000 -RequestTimeout 5000
-WEBSITE_TIME_ZONE \"Eastern Standard Time\"", diff --git a/Tasks/AzureWebAppContainerV1/package-lock.json b/Tasks/AzureWebAppContainerV1/package-lock.json index 793a3318c639..2f7806beba6a 100644 --- a/Tasks/AzureWebAppContainerV1/package-lock.json +++ b/Tasks/AzureWebAppContainerV1/package-lock.json @@ -70,6 +70,7 @@ "decompress-zip": "0.3.0", "jsonwebtoken": "7.3.0", "ltx": "2.6.2", + "node-stream-zip": "1.7.0", "q": "1.4.1", "typed-rest-client": "0.12.0", "vsts-task-lib": "2.0.5", @@ -397,6 +398,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz", "integrity": "sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8=" }, + "node-stream-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.7.0.tgz", + "integrity": "sha512-kYVtF3lK++53Bg6hZNplYVMrR7Lt0IYdLWehgoHUJLJcSwg/xd2Rm2Z7kJ5W8ZA7pdeg/DiUQDatbYwL3C7qSw==" + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", diff --git a/Tasks/AzureWebAppContainerV1/task.json b/Tasks/AzureWebAppContainerV1/task.json index aacfa75b8da5..6b4848d39932 100644 --- a/Tasks/AzureWebAppContainerV1/task.json +++ b/Tasks/AzureWebAppContainerV1/task.json @@ -98,9 +98,44 @@ "type": "string", "label": "Image name", "defaultValue": "", - "required": true, + "required": false, "helpMarkDown": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'." }, + { + "name": "ConfigurationType", + "type": "radio", + "label": "Configuration Type", + "required": false, + "helpMarkDown": "Type of the configuration: File Path or Inline Configuration", + "defaultValue": "FilePath", + "options": { + "FilePath": "Configuration File Path", + "InlineConfiguration": "Inline Configuration" + } + }, + { + "name": "ConfigurationPath", + "type": "filePath", + "label": "Configuration Path", + "defaultValue": "", + "required": false, + "helpMarkDown": "Path of the configuration. Should be fully qualified path or relative to the default working directory.", + "visibleRule": "ConfigurationType = FilePath" + }, + { + "name": "Inline", + "type": "multiLine", + "label": "Inline Configuration", + "required": false, + "defaultValue": "# You can write your configuration scripts inline here. \n# You can also pass predefined and custom variables to this script using arguments", + "helpMarkDown": "Enter the script to execute.", + "visibleRule": "ConfigurationType = InlineConfiguration", + "properties": { + "resizable": "true", + "rows": "10", + "maxLength": "5000" + } + }, { "name": "containerCommand", "type": "string", diff --git a/Tasks/AzureWebAppContainerV1/task.loc.json b/Tasks/AzureWebAppContainerV1/task.loc.json index 5b6ee8694e9a..f434f4ed9bff 100644 --- a/Tasks/AzureWebAppContainerV1/task.loc.json +++ b/Tasks/AzureWebAppContainerV1/task.loc.json @@ -97,9 +97,44 @@ "type": "string", "label": "ms-resource:loc.input.label.imageName", "defaultValue": "", - "required": true, + "required": false, "helpMarkDown": "ms-resource:loc.input.help.imageName" }, + { + "name": "ConfigurationType", + "type": "radio", + "label": "ms-resource:loc.input.label.ConfigurationType", + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.ConfigurationType", + "defaultValue": "FilePath", + "options": { + "FilePath": "Configuration File Path", + "InlineConfiguration": "Inline Configuration" + } + }, + { + "name": "ConfigurationPath", + "type": "filePath", + "label": "ms-resource:loc.input.label.ConfigurationPath", + "defaultValue": "", + "required": false, + "helpMarkDown": "ms-resource:loc.input.help.ConfigurationPath", + "visibleRule": "ConfigurationType = FilePath" + }, + { + "name": "Inline", + "type": "multiLine", + "label": "ms-resource:loc.input.label.Inline", + "required": false, + "defaultValue": "# You can write your configuration scripts inline here. \n# You can also pass predefined and custom variables to this script using arguments", + "helpMarkDown": "ms-resource:loc.input.help.Inline", + "visibleRule": "ConfigurationType = InlineConfiguration", + "properties": { + "resizable": "true", + "rows": "10", + "maxLength": "5000" + } + }, { "name": "containerCommand", "type": "string", diff --git a/Tasks/AzureWebAppContainerV1/taskparameters.ts b/Tasks/AzureWebAppContainerV1/taskparameters.ts index ef3da29cd26c..5e7c83eeb6bf 100644 --- a/Tasks/AzureWebAppContainerV1/taskparameters.ts +++ b/Tasks/AzureWebAppContainerV1/taskparameters.ts @@ -14,7 +14,7 @@ export class TaskParametersUtility { public static async getParameters(): Promise { var taskParameters: TaskParameters = { connectedServiceName: tl.getInput('azureSubscription', true), - ImageName: tl.getInput('imageName', true), + ImageName: tl.getInput('imageName', false), AppSettings: tl.getInput('appSettings', false), StartupCommand: tl.getInput('containerCommand', false), ConfigurationSettings: tl.getInput('configurationStrings', false), diff --git a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts index 19ebf099694d..a6c481e0cfad 100644 --- a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts +++ b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts @@ -4,6 +4,7 @@ import util = require('util'); import { AzureAppService } from '../azure-arm-rest/azure-arm-app-service'; import { parse } from './ParameterParserUtility'; import { AzureAppServiceUtility } from './AzureAppServiceUtility'; +import fs = require('fs'); enum registryTypes { "AzureContainerRegistry", @@ -22,25 +23,52 @@ export class ContainerBasedDeploymentUtility { public async deployWebAppImage(properties: any): Promise { let imageName: string = properties["ImageName"]; - tl.debug("Deploying an image " + imageName + " to the webapp " + this._appService.getName()); + let isMultiContainer: boolean = false; + if(imageName == null) { + isMultiContainer = true; + } + tl.debug(`is multicontainer app : ${isMultiContainer}`); + let configurationType: string = tl.getInput('ConfigurationType'); + let configurationPath: string = tl.getPathInput('ConfigurationPath', false); + let configurationInline: string = tl.getInput('Inline', false); + if(imageName != null) { + tl.debug("Deploying an image " + imageName + " to the webapp " + this._appService.getName()); + } let isLinuxApp: boolean = properties["isLinuxContainerApp"]; tl.debug("Updating the webapp configuration."); - await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], imageName, isLinuxApp); + await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], imageName, isLinuxApp, isMultiContainer, configurationType, configurationPath, configurationInline); tl.debug('making a restart request to app service'); await this._appService.restart(); } - private async _updateConfigurationDetails(configSettings: any, startupCommand: string, imageName: string, isLinuxApp: boolean): Promise { + private async _updateConfigurationDetails(configSettings: any, startupCommand: string, imageName: string, isLinuxApp: boolean, isMultiContainer: boolean, configurationType: string, configurationPath: string, configurationInline: string): Promise { var appSettingsNewProperties = !!configSettings ? parse(configSettings.trim()): { }; appSettingsNewProperties.appCommandLine = { 'value': startupCommand } if(isLinuxApp) { - appSettingsNewProperties.linuxFxVersion = { - 'value': "DOCKER|" + imageName + if(isMultiContainer) { + if (configurationType.toUpperCase() == 'FILEPATH') { + let rawdata = fs.readFileSync(configurationPath); + appSettingsNewProperties.linuxFxVersion = { + 'value': "COMPOSE|" + (new Buffer(rawdata).toString('base64')) + } + tl.debug('you requested filepath'); + } + else { + appSettingsNewProperties.linuxFxVersion = { + 'value': "COMPOSE|" + (new Buffer(configurationInline).toString('base64')) + } + tl.debug('you requested inline'); + } + } + else { + appSettingsNewProperties.linuxFxVersion = { + 'value': "DOCKER|" + imageName + } } } else { @@ -49,7 +77,7 @@ export class ContainerBasedDeploymentUtility { } } - tl.debug(`CONATINER UPDATE CONFIG VALUES : ${JSON.stringify(appSettingsNewProperties)}`); + tl.debug(`CONTAINER UPDATE CONFIG VALUES : ${JSON.stringify(appSettingsNewProperties)}`); await this._appServiceUtility.updateConfigurationSettings(appSettingsNewProperties); } From 0cfef742230c4d76531fa079a44e0d9eb317072f Mon Sep 17 00:00:00 2001 From: Shivangi Date: Wed, 27 Mar 2019 10:19:09 +0530 Subject: [PATCH 02/13] publishing log file --- .../resources.resjson/en-US/resources.resjson | 11 +- .../AzureWebAppContainerV1/package-lock.json | 334 ++++++++++-------- Tasks/AzureWebAppContainerV1/task.json | 40 +-- Tasks/AzureWebAppContainerV1/task.loc.json | 40 +-- .../AzureWebAppContainerV1/taskparameters.ts | 16 +- .../ContainerBasedDeploymentUtility.ts | 97 +++-- 6 files changed, 283 insertions(+), 255 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson index 315d4406a290..68e5552a419e 100644 --- a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson @@ -17,12 +17,8 @@ "loc.input.help.slotName": "Enter or Select an existing Slot other than the Production slot.", "loc.input.label.imageName": "Image name", "loc.input.help.imageName": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'.", - "loc.input.label.ConfigurationType": "Configuration Type", - "loc.input.help.ConfigurationType": "Type of the configuration: File Path or Inline Configuration", - "loc.input.label.ConfigurationPath": "Configuration Path", - "loc.input.help.ConfigurationPath": "Path of the configuration. Should be fully qualified path or relative to the default working directory.", - "loc.input.label.Inline": "Inline Configuration", - "loc.input.help.Inline": "Enter the script to execute.", + "loc.input.label.configFilePath": "Configuration File", + "loc.input.help.configFilePath": "Path of the configuration. Should be fully qualified path or relative to the default working directory.", "loc.input.label.containerCommand": "Startup command ", "loc.input.label.appSettings": "App settings", "loc.input.help.appSettings": "Edit web app application settings following the syntax -key value . Value containing spaces should be enclosed in double quotes.
Example : -Port 5000 -RequestTimeout 5000
-WEBSITE_TIME_ZONE \"Eastern Standard Time\"", @@ -181,5 +177,6 @@ "loc.messages.RestartedAppService": "App Service '%s' restarted successfully.", "loc.messages.RestartedAppServiceSlot": "App Service '%s-%s' restarted successfully.", "loc.messages.FailedToRestartAppService": "Failed to restart App Service '%s'. Error: %s", - "loc.messages.FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s" + "loc.messages.FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s", + "loc.messages.FailedToGetConfigurationFile": "Failed to get configuration file for multi containers" } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/package-lock.json b/Tasks/AzureWebAppContainerV1/package-lock.json index 2f7806beba6a..4882b9f71234 100644 --- a/Tasks/AzureWebAppContainerV1/package-lock.json +++ b/Tasks/AzureWebAppContainerV1/package-lock.json @@ -20,9 +20,9 @@ "integrity": "sha512-0WS7XU7sXzQ7J1nbnMKKYdjrrFoO3YtZYgUzeV8JFXffPnHfvSJQleR70I8BOAsOm14i4dyaAZ3YzqIl1YhkXQ==" }, "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "archiver": { "version": "1.2.0", @@ -30,13 +30,13 @@ "integrity": "sha1-+1xq9UQ7P6akJjRHU7rSp7REqt0=", "requires": { "archiver-utils": "1.3.0", - "async": "2.1.4", + "async": "2.6.2", "buffer-crc32": "0.2.13", - "glob": "7.1.1", - "lodash": "4.17.2", - "readable-stream": "2.2.2", - "tar-stream": "1.5.2", - "zip-stream": "1.1.0" + "glob": "7.1.3", + "lodash": "4.17.11", + "readable-stream": "2.3.6", + "tar-stream": "1.6.2", + "zip-stream": "1.2.0" } }, "archiver-utils": { @@ -44,20 +44,20 @@ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", "requires": { - "glob": "7.1.1", - "graceful-fs": "4.1.11", + "glob": "7.1.3", + "graceful-fs": "4.1.15", "lazystream": "1.0.0", - "lodash": "4.17.2", - "normalize-path": "2.0.1", - "readable-stream": "2.2.2" + "lodash": "4.17.11", + "normalize-path": "2.1.1", + "readable-stream": "2.3.6" } }, "async": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz", - "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "requires": { - "lodash": "4.17.2" + "lodash": "4.17.11" } }, "azurermdeploycommon": { @@ -79,9 +79,14 @@ } }, "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, "binary": { "version": "0.3.0", @@ -93,37 +98,46 @@ } }, "bl": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.1.2.tgz", - "integrity": "sha1-/cqHGplxOqANGeO7ukHER4emU5g=", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", "requires": { - "readable-stream": "2.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", - "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" - } - } + "readable-stream": "2.3.6", + "safe-buffer": "5.1.2" } }, "brace-expansion": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.6.tgz", - "integrity": "sha1-cZfX6qm4fmSDkOph/GbIRCdCDfk=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "balanced-match": "0.4.2", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "requires": { + "base64-js": "1.3.0", + "ieee754": "1.1.13" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -134,10 +148,10 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, - "buffer-shims": { + "buffer-fill": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", - "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, "buffers": { "version": "0.1.1", @@ -153,14 +167,14 @@ } }, "compress-commons": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.1.0.tgz", - "integrity": "sha1-n0RguxKIVkx0c5FuApiqPDINyts=", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", "requires": { "buffer-crc32": "0.2.13", - "crc32-stream": "1.0.0", - "normalize-path": "2.0.1", - "readable-stream": "2.2.2" + "crc32-stream": "2.0.0", + "normalize-path": "2.1.1", + "readable-stream": "2.3.6" } }, "concat-map": { @@ -173,13 +187,21 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "5.2.1" + } + }, "crc32-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-1.0.0.tgz", - "integrity": "sha1-6hVeXh1zjtN3hDj/6S/+KhQa6z8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", "requires": { - "buffer-crc32": "0.2.13", - "readable-stream": "2.2.2" + "crc": "3.8.0", + "readable-stream": "2.3.6" } }, "decompress-zip": { @@ -188,10 +210,10 @@ "integrity": "sha1-rjvLfjTGWHmt/nfhnDD4ZgK0vbA=", "requires": { "binary": "0.3.0", - "graceful-fs": "4.1.11", + "graceful-fs": "4.1.15", "mkpath": "0.1.0", "nopt": "3.0.6", - "q": "1.5.1", + "q": "1.4.1", "readable-stream": "1.1.14", "touch": "0.0.3" }, @@ -201,11 +223,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" - }, "readable-stream": { "version": "1.1.14", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", @@ -225,59 +242,59 @@ } }, "ecdsa-sig-formatter": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", - "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "requires": { "safe-buffer": "5.1.2" } }, "end-of-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.1.0.tgz", - "integrity": "sha1-6TUyWLqpEIll78QcsO+K3i88+wc=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "requires": { - "once": "1.3.3" - }, - "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "requires": { - "wrappy": "1.0.2" - } - } + "once": "1.4.0" } }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", "inherits": "2.0.3", - "minimatch": "3.0.3", + "minimatch": "3.0.4", "once": "1.4.0", "path-is-absolute": "1.0.1" } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, "hoek": { "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -319,28 +336,28 @@ "integrity": "sha1-hRGNanDj/M3xQ4n056HD+cip+7o=", "requires": { "joi": "6.10.1", - "jws": "3.1.5", + "jws": "3.2.2", "lodash.once": "4.1.1", "ms": "0.7.3", "xtend": "4.0.1" } }, "jwa": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", - "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", "requires": { "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.10", + "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "5.1.2" } }, "jws": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", - "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "requires": { - "jwa": "1.1.6", + "jwa": "1.4.1", "safe-buffer": "5.1.2" } }, @@ -349,13 +366,13 @@ "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "requires": { - "readable-stream": "2.2.2" + "readable-stream": "2.3.6" } }, "lodash": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.2.tgz", - "integrity": "sha1-NKMFW6vgTOQkZ7YH1wAHLH/2v0I=" + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, "lodash.once": { "version": "4.1.1", @@ -371,11 +388,11 @@ } }, "minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.6" + "brace-expansion": "1.1.11" } }, "mkpath": { @@ -408,13 +425,16 @@ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "requires": { - "abbrev": "1.0.9" + "abbrev": "1.1.1" } }, "normalize-path": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz", - "integrity": "sha1-R4hqwWYnYNQmG32XnSQXCdPOP3o=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } }, "once": { "version": "1.4.0", @@ -430,9 +450,9 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "q": { "version": "1.4.1", @@ -440,19 +460,24 @@ "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=" }, "readable-stream": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.2.tgz", - "integrity": "sha1-qeb+w8fdqF+LsbO6cChgRVb8gl4=", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "buffer-shims": "1.0.0", "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -464,9 +489,9 @@ "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, "shelljs": { "version": "0.3.0", @@ -474,21 +499,32 @@ "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=" }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.2" + } }, "tar-stream": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.2.tgz", - "integrity": "sha1-+8bG6DwaGdTLSMfZYXH8JI7/x78=", - "requires": { - "bl": "1.1.2", - "end-of-stream": "1.1.0", - "readable-stream": "2.2.2", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "1.2.2", + "buffer-alloc": "1.2.0", + "end-of-stream": "1.4.1", + "fs-constants": "1.0.0", + "readable-stream": "2.3.6", + "to-buffer": "1.1.1", "xtend": "4.0.1" } }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "topo": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", @@ -510,7 +546,7 @@ "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", "requires": { - "abbrev": "1.0.9" + "abbrev": "1.1.1" } } } @@ -554,24 +590,12 @@ "resolved": "https://registry.npmjs.org/vsts-task-lib/-/vsts-task-lib-2.0.5.tgz", "integrity": "sha1-y9WrIy6rtxDJaXkFMYcmlZHA1RA=", "requires": { - "minimatch": "3.0.3", + "minimatch": "3.0.4", "mockery": "1.7.0", - "q": "1.5.1", - "semver": "5.4.1", + "q": "1.4.1", + "semver": "5.6.0", "shelljs": "0.3.0", - "uuid": "3.2.1" - }, - "dependencies": { - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" - }, - "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" - } + "uuid": "3.1.0" } }, "winreg": { @@ -604,14 +628,14 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" }, "zip-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.1.0.tgz", - "integrity": "sha1-KtR5//wWjgWoiOjDSP9oE7PxNzM=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", "requires": { "archiver-utils": "1.3.0", - "compress-commons": "1.1.0", - "lodash": "4.17.2", - "readable-stream": "2.2.2" + "compress-commons": "1.2.2", + "lodash": "4.17.11", + "readable-stream": "2.3.6" } } } diff --git a/Tasks/AzureWebAppContainerV1/task.json b/Tasks/AzureWebAppContainerV1/task.json index 6b4848d39932..39cb2e345d14 100644 --- a/Tasks/AzureWebAppContainerV1/task.json +++ b/Tasks/AzureWebAppContainerV1/task.json @@ -95,46 +95,19 @@ }, { "name": "imageName", - "type": "string", + "type": "multiline", "label": "Image name", "defaultValue": "", - "required": false, + "required": true, "helpMarkDown": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'." }, { - "name": "ConfigurationType", - "type": "radio", - "label": "Configuration Type", - "required": false, - "helpMarkDown": "Type of the configuration: File Path or Inline Configuration", - "defaultValue": "FilePath", - "options": { - "FilePath": "Configuration File Path", - "InlineConfiguration": "Inline Configuration" - } - }, - { - "name": "ConfigurationPath", + "name": "configFilePath", "type": "filePath", - "label": "Configuration Path", + "label": "Configuration File", "defaultValue": "", "required": false, - "helpMarkDown": "Path of the configuration. Should be fully qualified path or relative to the default working directory.", - "visibleRule": "ConfigurationType = FilePath" - }, - { - "name": "Inline", - "type": "multiLine", - "label": "Inline Configuration", - "required": false, - "defaultValue": "# You can write your configuration scripts inline here. \n# You can also pass predefined and custom variables to this script using arguments", - "helpMarkDown": "Enter the script to execute.", - "visibleRule": "ConfigurationType = InlineConfiguration", - "properties": { - "resizable": "true", - "rows": "10", - "maxLength": "5000" - } + "helpMarkDown": "Path of the configuration. Should be fully qualified path or relative to the default working directory." }, { "name": "containerCommand", @@ -362,6 +335,7 @@ "RestartedAppService": "App Service '%s' restarted successfully.", "RestartedAppServiceSlot": "App Service '%s-%s' restarted successfully.", "FailedToRestartAppService": "Failed to restart App Service '%s'. Error: %s", - "FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s" + "FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s", + "FailedToGetConfigurationFile": "Failed to get configuration file for multi containers" } } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/task.loc.json b/Tasks/AzureWebAppContainerV1/task.loc.json index f434f4ed9bff..8350a9c158c7 100644 --- a/Tasks/AzureWebAppContainerV1/task.loc.json +++ b/Tasks/AzureWebAppContainerV1/task.loc.json @@ -94,46 +94,19 @@ }, { "name": "imageName", - "type": "string", + "type": "multiline", "label": "ms-resource:loc.input.label.imageName", "defaultValue": "", - "required": false, + "required": true, "helpMarkDown": "ms-resource:loc.input.help.imageName" }, { - "name": "ConfigurationType", - "type": "radio", - "label": "ms-resource:loc.input.label.ConfigurationType", - "required": false, - "helpMarkDown": "ms-resource:loc.input.help.ConfigurationType", - "defaultValue": "FilePath", - "options": { - "FilePath": "Configuration File Path", - "InlineConfiguration": "Inline Configuration" - } - }, - { - "name": "ConfigurationPath", + "name": "configFilePath", "type": "filePath", - "label": "ms-resource:loc.input.label.ConfigurationPath", + "label": "ms-resource:loc.input.label.configFilePath", "defaultValue": "", "required": false, - "helpMarkDown": "ms-resource:loc.input.help.ConfigurationPath", - "visibleRule": "ConfigurationType = FilePath" - }, - { - "name": "Inline", - "type": "multiLine", - "label": "ms-resource:loc.input.label.Inline", - "required": false, - "defaultValue": "# You can write your configuration scripts inline here. \n# You can also pass predefined and custom variables to this script using arguments", - "helpMarkDown": "ms-resource:loc.input.help.Inline", - "visibleRule": "ConfigurationType = InlineConfiguration", - "properties": { - "resizable": "true", - "rows": "10", - "maxLength": "5000" - } + "helpMarkDown": "ms-resource:loc.input.help.configFilePath" }, { "name": "containerCommand", @@ -361,6 +334,7 @@ "RestartedAppService": "ms-resource:loc.messages.RestartedAppService", "RestartedAppServiceSlot": "ms-resource:loc.messages.RestartedAppServiceSlot", "FailedToRestartAppService": "ms-resource:loc.messages.FailedToRestartAppService", - "FailedToRestartAppServiceSlot": "ms-resource:loc.messages.FailedToRestartAppServiceSlot" + "FailedToRestartAppServiceSlot": "ms-resource:loc.messages.FailedToRestartAppServiceSlot", + "FailedToGetConfigurationFile": "ms-resource:loc.messages.FailedToGetConfigurationFile" } } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/taskparameters.ts b/Tasks/AzureWebAppContainerV1/taskparameters.ts index 5e7c83eeb6bf..6956fbab3dcc 100644 --- a/Tasks/AzureWebAppContainerV1/taskparameters.ts +++ b/Tasks/AzureWebAppContainerV1/taskparameters.ts @@ -3,6 +3,7 @@ import { AzureResourceFilterUtility } from 'azurermdeploycommon/operations/Azure import { AzureEndpoint } from 'azurermdeploycommon/azure-arm-rest/azureModels'; import { AzureRMEndpoint } from 'azurermdeploycommon/azure-arm-rest/azure-arm-endpoint'; import { AzureAppService } from 'azurermdeploycommon/azure-arm-rest/azure-arm-app-service'; +import fs = require('fs'); const osTypeMap = new Map([ [ 'app,conatiner,xenon', 'Windows' ], @@ -14,7 +15,7 @@ export class TaskParametersUtility { public static async getParameters(): Promise { var taskParameters: TaskParameters = { connectedServiceName: tl.getInput('azureSubscription', true), - ImageName: tl.getInput('imageName', false), + ImageName: tl.getInput('imageName', true), AppSettings: tl.getInput('appSettings', false), StartupCommand: tl.getInput('containerCommand', false), ConfigurationSettings: tl.getInput('configurationStrings', false), @@ -22,7 +23,8 @@ export class TaskParametersUtility { OSType: tl.getInput('osType', false), DeployToSlotOrASEFlag: tl.getBoolInput('deployToSlotOrASE', false), ResourceGroupName: tl.getInput('resourceGroupName', false), - SlotName:tl.getInput('slotName', false) + SlotName: tl.getInput('slotName', false), + ConfigFilePath: tl.getPathInput('configFilePath', false) } taskParameters.azureEndpoint = await new AzureRMEndpoint(taskParameters.connectedServiceName).getEndpoint(); @@ -36,6 +38,14 @@ export class TaskParametersUtility { var endpointTelemetry = '{"endpointId":"' + taskParameters.connectedServiceName + '"}'; console.log("##vso[telemetry.publish area=TaskEndpointId;feature=AzureRmWebAppDeployment]" + endpointTelemetry); + taskParameters.isMultiContainer = false; + taskParameters.isMultiContainer = taskParameters.ImageName && taskParameters.ImageName.indexOf("\n") !=-1; + tl.debug(`is multicontainer app : ${taskParameters.isMultiContainer}`); + + if(taskParameters.isMultiContainer && fs.statSync(taskParameters.ConfigFilePath).isDirectory()) { + throw new Error(tl.loc('FailedToGetConfigurationFile')); + } + return taskParameters; } @@ -76,4 +86,6 @@ export interface TaskParameters { DeployToSlotOrASEFlag?: boolean; SlotName?: string; isLinuxContainerApp?: boolean; + ConfigFilePath?: string; + isMultiContainer?: boolean; } diff --git a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts index a6c481e0cfad..ee73cd153a5a 100644 --- a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts +++ b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts @@ -5,6 +5,8 @@ import { AzureAppService } from '../azure-arm-rest/azure-arm-app-service'; import { parse } from './ParameterParserUtility'; import { AzureAppServiceUtility } from './AzureAppServiceUtility'; import fs = require('fs'); +import * as os from "os"; +import path = require('path'); enum registryTypes { "AzureContainerRegistry", @@ -23,27 +25,29 @@ export class ContainerBasedDeploymentUtility { public async deployWebAppImage(properties: any): Promise { let imageName: string = properties["ImageName"]; - let isMultiContainer: boolean = false; - if(imageName == null) { - isMultiContainer = true; - } - tl.debug(`is multicontainer app : ${isMultiContainer}`); - let configurationType: string = tl.getInput('ConfigurationType'); - let configurationPath: string = tl.getPathInput('ConfigurationPath', false); - let configurationInline: string = tl.getInput('Inline', false); - if(imageName != null) { - tl.debug("Deploying an image " + imageName + " to the webapp " + this._appService.getName()); + let configFilePath: string = properties["ConfigFilePath"]; + let isMultiContainer: boolean = properties["isMultiContainer"]; + let isLinuxApp: boolean = properties["isLinuxContainerApp"]; + let updatedConfigFilePath: string; + tl.debug("Deploying image " + imageName + " to the webapp " + this._appService.getName()); + + if(isMultiContainer) { + updatedConfigFilePath = this.updateImagesInConfigFile(configFilePath, imageName); } - let isLinuxApp: boolean = properties["isLinuxContainerApp"]; tl.debug("Updating the webapp configuration."); - await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], imageName, isLinuxApp, isMultiContainer, configurationType, configurationPath, configurationInline); + await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], imageName, isLinuxApp, isMultiContainer, configFilePath); tl.debug('making a restart request to app service'); await this._appService.restart(); + + // uploading log file + if(isMultiContainer) { + console.log(`##vso[task.uploadfile]${updatedConfigFilePath}`); + } } - private async _updateConfigurationDetails(configSettings: any, startupCommand: string, imageName: string, isLinuxApp: boolean, isMultiContainer: boolean, configurationType: string, configurationPath: string, configurationInline: string): Promise { + private async _updateConfigurationDetails(configSettings: any, startupCommand: string, imageName: string, isLinuxApp: boolean, isMultiContainer?: boolean, configFilePath?: string): Promise { var appSettingsNewProperties = !!configSettings ? parse(configSettings.trim()): { }; appSettingsNewProperties.appCommandLine = { 'value': startupCommand @@ -51,18 +55,9 @@ export class ContainerBasedDeploymentUtility { if(isLinuxApp) { if(isMultiContainer) { - if (configurationType.toUpperCase() == 'FILEPATH') { - let rawdata = fs.readFileSync(configurationPath); - appSettingsNewProperties.linuxFxVersion = { - 'value': "COMPOSE|" + (new Buffer(rawdata).toString('base64')) - } - tl.debug('you requested filepath'); - } - else { - appSettingsNewProperties.linuxFxVersion = { - 'value': "COMPOSE|" + (new Buffer(configurationInline).toString('base64')) - } - tl.debug('you requested inline'); + let fileData = fs.readFileSync(configFilePath); + appSettingsNewProperties.linuxFxVersion = { + 'value': "COMPOSE|" + (new Buffer(fileData).toString('base64')) } } else { @@ -231,4 +226,56 @@ export class ContainerBasedDeploymentUtility { delete webAppSettings["properties"]["DOCKER_REGISTRY_SERVER_USERNAME"]; delete webAppSettings["properties"]["DOCKER_REGISTRY_SERVER_PASSWORD"]; } + + private updateImagesInConfigFile(configFilePath, images): string { + const tempDirectory = this.getTempDirectory(); + var contents = fs.readFileSync(configFilePath).toString(); + var imageList = images.split("\n"); + imageList.forEach((image: string) => { + let imageName = image.split(":")[0]; + if (contents.indexOf(imageName) > 0) { + contents = this.tokenizeImages(contents, imageName, image); + } + }); + + let newFilePath = path.join(tempDirectory, path.basename(configFilePath)); + fs.writeFileSync( + path.join(newFilePath), + contents + ); + + return newFilePath; + } + + private getTempDirectory(): string { + return tl.getVariable('agent.tempDirectory') || os.tmpdir(); + } + + private tokenizeImages(currentString: string, imageName: string, imageNameWithNewTag: string) { + let i = currentString.indexOf(imageName); + if (i < 0) { + tl.debug(`No occurence of replacement token: ${imageName} found`); + return currentString; + } + + let newString = ""; + currentString.split("\n") + .forEach((line) => { + if (line.indexOf(imageName) > 0 && line.toLocaleLowerCase().indexOf("image") > 0) { + let i = line.indexOf(imageName); + newString += line.substring(0, i); + let leftOverString = line.substring(i); + if (leftOverString.endsWith("\"")) { + newString += imageNameWithNewTag + "\"" + "\n"; + } else { + newString += imageNameWithNewTag + "\n"; + } + } + else { + newString += line + "\n"; + } + }); + + return newString; + } } \ No newline at end of file From eb1afaa5b9a1f0a1e53f97f5e07179046128ad11 Mon Sep 17 00:00:00 2001 From: Shivangi Date: Wed, 27 Mar 2019 14:03:29 +0530 Subject: [PATCH 03/13] Adding few more changes --- .../Strings/resources.resjson/en-US/resources.resjson | 2 +- Tasks/AzureWebAppContainerV1/task.json | 2 +- Tasks/AzureWebAppContainerV1/taskparameters.ts | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson index 68e5552a419e..232fe38aa3e1 100644 --- a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson @@ -178,5 +178,5 @@ "loc.messages.RestartedAppServiceSlot": "App Service '%s-%s' restarted successfully.", "loc.messages.FailedToRestartAppService": "Failed to restart App Service '%s'. Error: %s", "loc.messages.FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s", - "loc.messages.FailedToGetConfigurationFile": "Failed to get configuration file for multi containers" + "loc.messages.FailedToGetConfigurationFile": "Failed to get configuration file for multi containers. Please enter the valid configuration file path." } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/task.json b/Tasks/AzureWebAppContainerV1/task.json index 39cb2e345d14..8afa30c88c45 100644 --- a/Tasks/AzureWebAppContainerV1/task.json +++ b/Tasks/AzureWebAppContainerV1/task.json @@ -336,6 +336,6 @@ "RestartedAppServiceSlot": "App Service '%s-%s' restarted successfully.", "FailedToRestartAppService": "Failed to restart App Service '%s'. Error: %s", "FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s", - "FailedToGetConfigurationFile": "Failed to get configuration file for multi containers" + "FailedToGetConfigurationFile": "Failed to get configuration file for multi containers. Please enter the valid configuration file path." } } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/taskparameters.ts b/Tasks/AzureWebAppContainerV1/taskparameters.ts index 6956fbab3dcc..b2090ca24c0d 100644 --- a/Tasks/AzureWebAppContainerV1/taskparameters.ts +++ b/Tasks/AzureWebAppContainerV1/taskparameters.ts @@ -3,6 +3,7 @@ import { AzureResourceFilterUtility } from 'azurermdeploycommon/operations/Azure import { AzureEndpoint } from 'azurermdeploycommon/azure-arm-rest/azureModels'; import { AzureRMEndpoint } from 'azurermdeploycommon/azure-arm-rest/azure-arm-endpoint'; import { AzureAppService } from 'azurermdeploycommon/azure-arm-rest/azure-arm-app-service'; +import { PackageUtility } from 'azurermdeploycommon/webdeployment-common/packageUtility'; import fs = require('fs'); const osTypeMap = new Map([ @@ -42,8 +43,12 @@ export class TaskParametersUtility { taskParameters.isMultiContainer = taskParameters.ImageName && taskParameters.ImageName.indexOf("\n") !=-1; tl.debug(`is multicontainer app : ${taskParameters.isMultiContainer}`); - if(taskParameters.isMultiContainer && fs.statSync(taskParameters.ConfigFilePath).isDirectory()) { - throw new Error(tl.loc('FailedToGetConfigurationFile')); + if(taskParameters.isMultiContainer) + { + PackageUtility.getPackagePath(taskParameters.ConfigFilePath); + if(fs.statSync(taskParameters.ConfigFilePath).isDirectory()) { + throw new Error(tl.loc('FailedToGetConfigurationFile')); + } } return taskParameters; From a6f6accbe795c08cc7d3caccf4c9cde1671385fb Mon Sep 17 00:00:00 2001 From: Shivangi Date: Fri, 29 Mar 2019 11:52:10 +0530 Subject: [PATCH 04/13] Changing patch version to pass the checks --- Tasks/AzureFunctionAppContainerV1/task.json | 2 +- Tasks/AzureFunctionAppContainerV1/task.loc.json | 2 +- Tasks/AzureFunctionAppV1/task.json | 2 +- Tasks/AzureFunctionAppV1/task.loc.json | 2 +- Tasks/AzureWebAppV1/task.json | 2 +- Tasks/AzureWebAppV1/task.loc.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Tasks/AzureFunctionAppContainerV1/task.json b/Tasks/AzureFunctionAppContainerV1/task.json index 1eda3ce199aa..b07d02949bd9 100644 --- a/Tasks/AzureFunctionAppContainerV1/task.json +++ b/Tasks/AzureFunctionAppContainerV1/task.json @@ -19,7 +19,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 4 + "Patch": 5 }, "minimumAgentVersion": "2.104.1", "groups": [ diff --git a/Tasks/AzureFunctionAppContainerV1/task.loc.json b/Tasks/AzureFunctionAppContainerV1/task.loc.json index c4caf2ceb3c0..88ac44b36459 100644 --- a/Tasks/AzureFunctionAppContainerV1/task.loc.json +++ b/Tasks/AzureFunctionAppContainerV1/task.loc.json @@ -19,7 +19,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 4 + "Patch": 5 }, "minimumAgentVersion": "2.104.1", "groups": [ diff --git a/Tasks/AzureFunctionAppV1/task.json b/Tasks/AzureFunctionAppV1/task.json index 82623259a3c5..3908964b31f2 100644 --- a/Tasks/AzureFunctionAppV1/task.json +++ b/Tasks/AzureFunctionAppV1/task.json @@ -19,7 +19,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 6 + "Patch": 7 }, "minimumAgentVersion": "2.104.1", "groups": [ diff --git a/Tasks/AzureFunctionAppV1/task.loc.json b/Tasks/AzureFunctionAppV1/task.loc.json index e3ed9a2e39e8..f3bce494f308 100644 --- a/Tasks/AzureFunctionAppV1/task.loc.json +++ b/Tasks/AzureFunctionAppV1/task.loc.json @@ -19,7 +19,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 6 + "Patch": 7 }, "minimumAgentVersion": "2.104.1", "groups": [ diff --git a/Tasks/AzureWebAppV1/task.json b/Tasks/AzureWebAppV1/task.json index 5e3909dbe096..4e14a0e7890a 100644 --- a/Tasks/AzureWebAppV1/task.json +++ b/Tasks/AzureWebAppV1/task.json @@ -19,7 +19,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 6 + "Patch": 7 }, "minimumAgentVersion": "2.104.1", "groups": [ diff --git a/Tasks/AzureWebAppV1/task.loc.json b/Tasks/AzureWebAppV1/task.loc.json index 15bdb2ed4a55..50d9e2415e38 100644 --- a/Tasks/AzureWebAppV1/task.loc.json +++ b/Tasks/AzureWebAppV1/task.loc.json @@ -19,7 +19,7 @@ "version": { "Major": 1, "Minor": 0, - "Patch": 6 + "Patch": 7 }, "minimumAgentVersion": "2.104.1", "groups": [ From 6600994b64c6cd87cb331f94c6c4e8ca92b4a04b Mon Sep 17 00:00:00 2001 From: Shivangi Date: Fri, 29 Mar 2019 13:57:46 +0530 Subject: [PATCH 05/13] Resolving comments --- Tasks/AzureWebAppContainerV1/taskparameters.ts | 15 ++++++++------- .../operations/ContainerBasedDeploymentUtility.ts | 8 +++----- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/taskparameters.ts b/Tasks/AzureWebAppContainerV1/taskparameters.ts index b2090ca24c0d..f593848cddd0 100644 --- a/Tasks/AzureWebAppContainerV1/taskparameters.ts +++ b/Tasks/AzureWebAppContainerV1/taskparameters.ts @@ -39,18 +39,19 @@ export class TaskParametersUtility { var endpointTelemetry = '{"endpointId":"' + taskParameters.connectedServiceName + '"}'; console.log("##vso[telemetry.publish area=TaskEndpointId;feature=AzureRmWebAppDeployment]" + endpointTelemetry); - taskParameters.isMultiContainer = false; taskParameters.isMultiContainer = taskParameters.ImageName && taskParameters.ImageName.indexOf("\n") !=-1; - tl.debug(`is multicontainer app : ${taskParameters.isMultiContainer}`); - - if(taskParameters.isMultiContainer) - { - PackageUtility.getPackagePath(taskParameters.ConfigFilePath); - if(fs.statSync(taskParameters.ConfigFilePath).isDirectory()) { + taskParameters.ConfigFilePath = PackageUtility.getPackagePath(taskParameters.ConfigFilePath); + if(fs.statSync(taskParameters.ConfigFilePath).isFile()) { + taskParameters.isMultiContainer = true; + } + else { + if(taskParameters.isMultiContainer) { throw new Error(tl.loc('FailedToGetConfigurationFile')); } } + tl.debug(`is multicontainer app : ${taskParameters.isMultiContainer}`); + return taskParameters; } diff --git a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts index ee73cd153a5a..a8a220ea5399 100644 --- a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts +++ b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts @@ -33,6 +33,9 @@ export class ContainerBasedDeploymentUtility { if(isMultiContainer) { updatedConfigFilePath = this.updateImagesInConfigFile(configFilePath, imageName); + + // uploading log file + console.log(`##vso[task.uploadfile]${updatedConfigFilePath}`); } tl.debug("Updating the webapp configuration."); @@ -40,11 +43,6 @@ export class ContainerBasedDeploymentUtility { tl.debug('making a restart request to app service'); await this._appService.restart(); - - // uploading log file - if(isMultiContainer) { - console.log(`##vso[task.uploadfile]${updatedConfigFilePath}`); - } } private async _updateConfigurationDetails(configSettings: any, startupCommand: string, imageName: string, isLinuxApp: boolean, isMultiContainer?: boolean, configFilePath?: string): Promise { From 4e54323738323bb599cc3f144a97d406fa8f8d11 Mon Sep 17 00:00:00 2001 From: Shivangi Date: Fri, 29 Mar 2019 15:02:21 +0530 Subject: [PATCH 06/13] Resolving more comments --- Tasks/AzureWebAppContainerV1/taskparameters.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/taskparameters.ts b/Tasks/AzureWebAppContainerV1/taskparameters.ts index f593848cddd0..13fd05be72d9 100644 --- a/Tasks/AzureWebAppContainerV1/taskparameters.ts +++ b/Tasks/AzureWebAppContainerV1/taskparameters.ts @@ -44,10 +44,8 @@ export class TaskParametersUtility { if(fs.statSync(taskParameters.ConfigFilePath).isFile()) { taskParameters.isMultiContainer = true; } - else { - if(taskParameters.isMultiContainer) { - throw new Error(tl.loc('FailedToGetConfigurationFile')); - } + else if (taskParameters.isMultiContainer) { + throw new Error(tl.loc('FailedToGetConfigurationFile')); } tl.debug(`is multicontainer app : ${taskParameters.isMultiContainer}`); From ba89d0fbd202e56a7ecf8865ae0bfcedb64a5b53 Mon Sep 17 00:00:00 2001 From: Shivangi Date: Fri, 29 Mar 2019 15:48:04 +0530 Subject: [PATCH 07/13] Passing the checks --- Tasks/AzureWebAppContainerV1/Tests/utils.ts | 8 +++++++- Tasks/AzureWebAppContainerV1/taskparameters.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/Tests/utils.ts b/Tasks/AzureWebAppContainerV1/Tests/utils.ts index f47fd44f15ec..351961dec2c9 100644 --- a/Tasks/AzureWebAppContainerV1/Tests/utils.ts +++ b/Tasks/AzureWebAppContainerV1/Tests/utils.ts @@ -50,6 +50,10 @@ export function mockTaskArgument(): ma.TaskLibAnswers{ }, "webAppPkg": { "isDirectory": true + }, + "/home/site/wwwroot": { + "isDirectory": true, + "isFile": false } }, "osType": { @@ -66,7 +70,8 @@ export function mockTaskArgument(): ma.TaskLibAnswers{ "webAppPkg.zip": true, "webAppPkg": true, "publishxml.pubxml": true, - "publishxml": true + "publishxml": true, + "/home/site/wwwroot": true } } @@ -78,4 +83,5 @@ export function mockTaskInputParameters(tr) { tr.setInput('appName', 'mytestapp'); tr.setInput('imageName', 'dockernamespace/dockerrepository:DockerImageTag'); tr.setInput('AppSettings', '-port 1173'); + tr.setInput('configFilePath', '/home/site/wwwroot'); } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/taskparameters.ts b/Tasks/AzureWebAppContainerV1/taskparameters.ts index 13fd05be72d9..7448edf058ab 100644 --- a/Tasks/AzureWebAppContainerV1/taskparameters.ts +++ b/Tasks/AzureWebAppContainerV1/taskparameters.ts @@ -41,7 +41,7 @@ export class TaskParametersUtility { taskParameters.isMultiContainer = taskParameters.ImageName && taskParameters.ImageName.indexOf("\n") !=-1; taskParameters.ConfigFilePath = PackageUtility.getPackagePath(taskParameters.ConfigFilePath); - if(fs.statSync(taskParameters.ConfigFilePath).isFile()) { + if(tl.stats(taskParameters.ConfigFilePath).isFile()) { taskParameters.isMultiContainer = true; } else if (taskParameters.isMultiContainer) { From 3ef54357e7faa02ab84850e0335091cf47305fa4 Mon Sep 17 00:00:00 2001 From: Shivangi Date: Tue, 2 Apr 2019 15:47:58 +0530 Subject: [PATCH 08/13] Resolving comments --- .../operations/ContainerBasedDeploymentUtility.ts | 12 ++++-------- .../webdeployment-common/utility.ts | 5 +++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts index a8a220ea5399..9975d43bcc0e 100644 --- a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts +++ b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts @@ -5,8 +5,8 @@ import { AzureAppService } from '../azure-arm-rest/azure-arm-app-service'; import { parse } from './ParameterParserUtility'; import { AzureAppServiceUtility } from './AzureAppServiceUtility'; import fs = require('fs'); -import * as os from "os"; import path = require('path'); +var deployUtility = require('../webdeployment-common/utility.js'); enum registryTypes { "AzureContainerRegistry", @@ -39,7 +39,7 @@ export class ContainerBasedDeploymentUtility { } tl.debug("Updating the webapp configuration."); - await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], imageName, isLinuxApp, isMultiContainer, configFilePath); + await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], imageName, isLinuxApp, isMultiContainer, updatedConfigFilePath); tl.debug('making a restart request to app service'); await this._appService.restart(); @@ -226,7 +226,7 @@ export class ContainerBasedDeploymentUtility { } private updateImagesInConfigFile(configFilePath, images): string { - const tempDirectory = this.getTempDirectory(); + const tempDirectory = deployUtility.getTempDirectory(); var contents = fs.readFileSync(configFilePath).toString(); var imageList = images.split("\n"); imageList.forEach((image: string) => { @@ -245,10 +245,6 @@ export class ContainerBasedDeploymentUtility { return newFilePath; } - private getTempDirectory(): string { - return tl.getVariable('agent.tempDirectory') || os.tmpdir(); - } - private tokenizeImages(currentString: string, imageName: string, imageNameWithNewTag: string) { let i = currentString.indexOf(imageName); if (i < 0) { @@ -273,7 +269,7 @@ export class ContainerBasedDeploymentUtility { newString += line + "\n"; } }); - + return newString; } } \ No newline at end of file diff --git a/Tasks/Common/AzureRmDeploy-common/webdeployment-common/utility.ts b/Tasks/Common/AzureRmDeploy-common/webdeployment-common/utility.ts index db9e49158e06..f49ad56e4dbe 100644 --- a/Tasks/Common/AzureRmDeploy-common/webdeployment-common/utility.ts +++ b/Tasks/Common/AzureRmDeploy-common/webdeployment-common/utility.ts @@ -2,6 +2,7 @@ import path = require('path'); import tl = require('vsts-task-lib/task'); import { PackageType } from './packageUtility'; import zipUtility = require('./ziputility.js'); +import * as os from "os"; /** * Validates the input package and finds out input type * @@ -218,3 +219,7 @@ export function getFileNameFromPath(filePath: string, extension?: string): strin return fileName; } + +export function getTempDirectory(): string { + return tl.getVariable('agent.tempDirectory') || os.tmpdir(); +} \ No newline at end of file From 0a079c20e4725168f037a5ed91bacae4d2a5ce0e Mon Sep 17 00:00:00 2001 From: Shivangi Date: Thu, 4 Apr 2019 12:01:48 +0530 Subject: [PATCH 09/13] Making imageName not mandatory --- .../resources.resjson/en-US/resources.resjson | 6 ++- Tasks/AzureWebAppContainerV1/task.json | 8 ++- Tasks/AzureWebAppContainerV1/task.loc.json | 8 ++- .../AzureWebAppContainerV1/taskparameters.ts | 52 +++++++++++++++---- .../ContainerBasedDeploymentUtility.ts | 15 ++++-- 5 files changed, 68 insertions(+), 21 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson index 232fe38aa3e1..ec8b5f4286ca 100644 --- a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson @@ -178,5 +178,9 @@ "loc.messages.RestartedAppServiceSlot": "App Service '%s-%s' restarted successfully.", "loc.messages.FailedToRestartAppService": "Failed to restart App Service '%s'. Error: %s", "loc.messages.FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s", - "loc.messages.FailedToGetConfigurationFile": "Failed to get configuration file for multi containers. Please enter the valid configuration file path." + "loc.messages.FailedToGetConfigurationFile": "Failed to get configuration file for multi containers. Please enter the valid configuration file path.", + "loc.messages.FailedToDeployToWebApp": "No deployment can happen to the webapp '%s'. For single-container, provide a valid image name and for multi-container, config file is mandatory and image names can also be provided if you want tags to be substituted.", + "loc.messages.SingleContainerDeployment": "Single Container Deployment to the webapp '%s' because only image name is given", + "loc.messages.MultiContainerDeploymentWithTransformation": "Multi Container Deployment to the webapp '%s' with transformation of configuration file because both image name and configuration file are given", + "loc.messages.MultiContainerDeploymentWithoutTransformation": "Multi Container Deployment to the webapp '%s' without transformation of configuration file because only configuration file is given" } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/task.json b/Tasks/AzureWebAppContainerV1/task.json index 8afa30c88c45..6790c42d7848 100644 --- a/Tasks/AzureWebAppContainerV1/task.json +++ b/Tasks/AzureWebAppContainerV1/task.json @@ -98,7 +98,7 @@ "type": "multiline", "label": "Image name", "defaultValue": "", - "required": true, + "required": false, "helpMarkDown": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'." }, { @@ -336,6 +336,10 @@ "RestartedAppServiceSlot": "App Service '%s-%s' restarted successfully.", "FailedToRestartAppService": "Failed to restart App Service '%s'. Error: %s", "FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s", - "FailedToGetConfigurationFile": "Failed to get configuration file for multi containers. Please enter the valid configuration file path." + "FailedToGetConfigurationFile": "Failed to get configuration file for multi containers. Please enter the valid configuration file path.", + "FailedToDeployToWebApp": "No deployment can happen to the webapp '%s'. For single-container, provide a valid image name and for multi-container, config file is mandatory and image names can also be provided if you want tags to be substituted.", + "SingleContainerDeployment": "Single Container Deployment to the webapp '%s' because only image name is given", + "MultiContainerDeploymentWithTransformation": "Multi Container Deployment to the webapp '%s' with transformation of configuration file because both image name and configuration file are given", + "MultiContainerDeploymentWithoutTransformation": "Multi Container Deployment to the webapp '%s' without transformation of configuration file because only configuration file is given" } } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/task.loc.json b/Tasks/AzureWebAppContainerV1/task.loc.json index 8350a9c158c7..94e60217fb7b 100644 --- a/Tasks/AzureWebAppContainerV1/task.loc.json +++ b/Tasks/AzureWebAppContainerV1/task.loc.json @@ -97,7 +97,7 @@ "type": "multiline", "label": "ms-resource:loc.input.label.imageName", "defaultValue": "", - "required": true, + "required": false, "helpMarkDown": "ms-resource:loc.input.help.imageName" }, { @@ -335,6 +335,10 @@ "RestartedAppServiceSlot": "ms-resource:loc.messages.RestartedAppServiceSlot", "FailedToRestartAppService": "ms-resource:loc.messages.FailedToRestartAppService", "FailedToRestartAppServiceSlot": "ms-resource:loc.messages.FailedToRestartAppServiceSlot", - "FailedToGetConfigurationFile": "ms-resource:loc.messages.FailedToGetConfigurationFile" + "FailedToGetConfigurationFile": "ms-resource:loc.messages.FailedToGetConfigurationFile", + "FailedToDeployToWebApp": "ms-resource:loc.messages.FailedToDeployToWebApp", + "SingleContainerDeployment": "ms-resource:loc.messages.SingleContainerDeployment", + "MultiContainerDeploymentWithTransformation": "ms-resource:loc.messages.MultiContainerDeploymentWithTransformation", + "MultiContainerDeploymentWithoutTransformation": "ms-resource:loc.messages.MultiContainerDeploymentWithoutTransformation" } } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/taskparameters.ts b/Tasks/AzureWebAppContainerV1/taskparameters.ts index 7448edf058ab..745c338a6fd7 100644 --- a/Tasks/AzureWebAppContainerV1/taskparameters.ts +++ b/Tasks/AzureWebAppContainerV1/taskparameters.ts @@ -16,7 +16,7 @@ export class TaskParametersUtility { public static async getParameters(): Promise { var taskParameters: TaskParameters = { connectedServiceName: tl.getInput('azureSubscription', true), - ImageName: tl.getInput('imageName', true), + ImageName: tl.getInput('imageName', false), AppSettings: tl.getInput('appSettings', false), StartupCommand: tl.getInput('containerCommand', false), ConfigurationSettings: tl.getInput('configurationStrings', false), @@ -39,16 +39,10 @@ export class TaskParametersUtility { var endpointTelemetry = '{"endpointId":"' + taskParameters.connectedServiceName + '"}'; console.log("##vso[telemetry.publish area=TaskEndpointId;feature=AzureRmWebAppDeployment]" + endpointTelemetry); - taskParameters.isMultiContainer = taskParameters.ImageName && taskParameters.ImageName.indexOf("\n") !=-1; - taskParameters.ConfigFilePath = PackageUtility.getPackagePath(taskParameters.ConfigFilePath); - if(tl.stats(taskParameters.ConfigFilePath).isFile()) { - taskParameters.isMultiContainer = true; - } - else if (taskParameters.isMultiContainer) { - throw new Error(tl.loc('FailedToGetConfigurationFile')); - } - - tl.debug(`is multicontainer app : ${taskParameters.isMultiContainer}`); + let containerDetails = await this.getContainerKind(taskParameters); + taskParameters.ImageName = containerDetails["imageName"]; + taskParameters.isMultiContainer = containerDetails["isMultiContainer"]; + taskParameters.ConfigFilePath = containerDetails["configFilePath"]; return taskParameters; } @@ -75,6 +69,42 @@ export class TaskParametersUtility { osType: osType }; } + + private static async getContainerKind(taskParameters: TaskParameters): Promise { + let imageName = taskParameters.ImageName; + let isMultiLineImages: boolean = imageName && imageName.indexOf("\n") != -1; + let isMultiContainer = false; + let configFilePath = PackageUtility.getPackagePath(taskParameters.ConfigFilePath); + + if(!imageName && tl.stats(configFilePath).isDirectory()) { + throw new Error(tl.loc('FailedToDeployToWebApp', taskParameters.WebAppName)); + } + + if(imageName && !isMultiLineImages && tl.stats(configFilePath).isDirectory()) { + console.log(tl.loc("SingleContainerDeployment", taskParameters.WebAppName)); + } + + if(tl.stats(configFilePath).isFile()) { + isMultiContainer = true; + if(imageName) { + console.log(tl.loc("MultiContainerDeploymentWithTransformation", taskParameters.WebAppName)); + } + else { + console.log(tl.loc("MultiContainerDeploymentWithoutTransformation", taskParameters.WebAppName)); + } + } + else if (isMultiLineImages) { + throw new Error(tl.loc('FailedToGetConfigurationFile')); + } + + tl.debug(`is multicontainer app : ${isMultiContainer}`); + + return { + imageName: imageName, + isMultiContainer: isMultiContainer, + configFilePath: configFilePath + }; + } } export interface TaskParameters { diff --git a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts index 9975d43bcc0e..deb9558b5247 100644 --- a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts +++ b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts @@ -28,24 +28,29 @@ export class ContainerBasedDeploymentUtility { let configFilePath: string = properties["ConfigFilePath"]; let isMultiContainer: boolean = properties["isMultiContainer"]; let isLinuxApp: boolean = properties["isLinuxContainerApp"]; - let updatedConfigFilePath: string; - tl.debug("Deploying image " + imageName + " to the webapp " + this._appService.getName()); + let updatedConfigFilePath: string = configFilePath; + + if(imageName) { + tl.debug("Deploying image " + imageName + " to the webapp " + this._appService.getName()); + } if(isMultiContainer) { - updatedConfigFilePath = this.updateImagesInConfigFile(configFilePath, imageName); + if(imageName) { + updatedConfigFilePath = this.updateImagesInConfigFile(configFilePath, imageName); + } // uploading log file console.log(`##vso[task.uploadfile]${updatedConfigFilePath}`); } tl.debug("Updating the webapp configuration."); - await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], imageName, isLinuxApp, isMultiContainer, updatedConfigFilePath); + await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], isLinuxApp, imageName, isMultiContainer, updatedConfigFilePath); tl.debug('making a restart request to app service'); await this._appService.restart(); } - private async _updateConfigurationDetails(configSettings: any, startupCommand: string, imageName: string, isLinuxApp: boolean, isMultiContainer?: boolean, configFilePath?: string): Promise { + private async _updateConfigurationDetails(configSettings: any, startupCommand: string, isLinuxApp: boolean, imageName?: string, isMultiContainer?: boolean, configFilePath?: string): Promise { var appSettingsNewProperties = !!configSettings ? parse(configSettings.trim()): { }; appSettingsNewProperties.appCommandLine = { 'value': startupCommand From a8fabeb86e99614d8b8f7155ec72df191feafa8c Mon Sep 17 00:00:00 2001 From: Shivangi Date: Tue, 9 Apr 2019 15:49:51 +0530 Subject: [PATCH 10/13] Editing tooltips --- .../resources.resjson/en-US/resources.resjson | 14 ++++++------- Tasks/AzureWebAppContainerV1/Tests/utils.ts | 2 +- Tasks/AzureWebAppContainerV1/task.json | 14 ++++++------- Tasks/AzureWebAppContainerV1/task.loc.json | 6 +++--- .../AzureWebAppContainerV1/taskparameters.ts | 16 +++++++-------- .../ContainerBasedDeploymentUtility.ts | 20 +++++++++---------- 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson index ec8b5f4286ca..04a845642af4 100644 --- a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson @@ -17,8 +17,8 @@ "loc.input.help.slotName": "Enter or Select an existing Slot other than the Production slot.", "loc.input.label.imageName": "Image name", "loc.input.help.imageName": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'.", - "loc.input.label.configFilePath": "Configuration File", - "loc.input.help.configFilePath": "Path of the configuration. Should be fully qualified path or relative to the default working directory.", + "loc.input.label.multicontainerConfigFile": "Configuration File", + "loc.input.help.multicontainerConfigFile": "Path of the Docker-Compose file. Should be a fully qualified path or relative to the default working directory.", "loc.input.label.containerCommand": "Startup command ", "loc.input.label.appSettings": "App settings", "loc.input.help.appSettings": "Edit web app application settings following the syntax -key value . Value containing spaces should be enclosed in double quotes.
Example : -Port 5000 -RequestTimeout 5000
-WEBSITE_TIME_ZONE \"Eastern Standard Time\"", @@ -178,9 +178,9 @@ "loc.messages.RestartedAppServiceSlot": "App Service '%s-%s' restarted successfully.", "loc.messages.FailedToRestartAppService": "Failed to restart App Service '%s'. Error: %s", "loc.messages.FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s", - "loc.messages.FailedToGetConfigurationFile": "Failed to get configuration file for multi containers. Please enter the valid configuration file path.", - "loc.messages.FailedToDeployToWebApp": "No deployment can happen to the webapp '%s'. For single-container, provide a valid image name and for multi-container, config file is mandatory and image names can also be provided if you want tags to be substituted.", - "loc.messages.SingleContainerDeployment": "Single Container Deployment to the webapp '%s' because only image name is given", - "loc.messages.MultiContainerDeploymentWithTransformation": "Multi Container Deployment to the webapp '%s' with transformation of configuration file because both image name and configuration file are given", - "loc.messages.MultiContainerDeploymentWithoutTransformation": "Multi Container Deployment to the webapp '%s' without transformation of configuration file because only configuration file is given" + "loc.messages.FailedToGetConfigurationFile": "Failed to locate the Docker-Compose file which is required for deploying multi-container apps. Please enter a valid Docker-Compose file path.", + "loc.messages.FailedToDeployToWebApp": "Deployment to the webapp '%s' failed. For single-container, just specify a valid image name. For multi-container specifying a Docker-Compose file is mandatory and specifying image names is optional. Provided images names if the tags in Docker-Compose file need to be substituted.", + "loc.messages.SingleContainerDeployment": "Single-container Deployment to the webapp '%s' as only the image detail was sepcified.", + "loc.messages.MultiContainerDeploymentWithTransformation": "Multi-container deployment to the webapp '%s' with the transformation of Docker-Compose file as both image name and Docker-Compose file were specified", + "loc.messages.MultiContainerDeploymentWithoutTransformation": "Multi-container deployment to the webapp '%s' without transformation of Docker-Compose file because only Docker-Compose file was specified." } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/Tests/utils.ts b/Tasks/AzureWebAppContainerV1/Tests/utils.ts index 351961dec2c9..3718ae370d32 100644 --- a/Tasks/AzureWebAppContainerV1/Tests/utils.ts +++ b/Tasks/AzureWebAppContainerV1/Tests/utils.ts @@ -83,5 +83,5 @@ export function mockTaskInputParameters(tr) { tr.setInput('appName', 'mytestapp'); tr.setInput('imageName', 'dockernamespace/dockerrepository:DockerImageTag'); tr.setInput('AppSettings', '-port 1173'); - tr.setInput('configFilePath', '/home/site/wwwroot'); + tr.setInput(' multicontainerConfigFile', '/home/site/wwwroot'); } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/task.json b/Tasks/AzureWebAppContainerV1/task.json index 6790c42d7848..6ae98f2a48dc 100644 --- a/Tasks/AzureWebAppContainerV1/task.json +++ b/Tasks/AzureWebAppContainerV1/task.json @@ -102,12 +102,12 @@ "helpMarkDown": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'." }, { - "name": "configFilePath", + "name": "multicontainerConfigFile", "type": "filePath", "label": "Configuration File", "defaultValue": "", "required": false, - "helpMarkDown": "Path of the configuration. Should be fully qualified path or relative to the default working directory." + "helpMarkDown": "Path of the Docker-Compose file. Should be a fully qualified path or relative to the default working directory." }, { "name": "containerCommand", @@ -336,10 +336,10 @@ "RestartedAppServiceSlot": "App Service '%s-%s' restarted successfully.", "FailedToRestartAppService": "Failed to restart App Service '%s'. Error: %s", "FailedToRestartAppServiceSlot": "Failed to restart App Service '%s-%s'. Error: %s", - "FailedToGetConfigurationFile": "Failed to get configuration file for multi containers. Please enter the valid configuration file path.", - "FailedToDeployToWebApp": "No deployment can happen to the webapp '%s'. For single-container, provide a valid image name and for multi-container, config file is mandatory and image names can also be provided if you want tags to be substituted.", - "SingleContainerDeployment": "Single Container Deployment to the webapp '%s' because only image name is given", - "MultiContainerDeploymentWithTransformation": "Multi Container Deployment to the webapp '%s' with transformation of configuration file because both image name and configuration file are given", - "MultiContainerDeploymentWithoutTransformation": "Multi Container Deployment to the webapp '%s' without transformation of configuration file because only configuration file is given" + "FailedToGetConfigurationFile": "Failed to locate the Docker-Compose file which is required for deploying multi-container apps. Please enter a valid Docker-Compose file path.", + "FailedToDeployToWebApp": "Deployment to the webapp '%s' failed. For single-container, just specify a valid image name. For multi-container specifying a Docker-Compose file is mandatory and specifying image names is optional. Provided images names if the tags in Docker-Compose file need to be substituted.", + "SingleContainerDeployment": "Single-container Deployment to the webapp '%s' as only the image detail was sepcified.", + "MultiContainerDeploymentWithTransformation": "Multi-container deployment to the webapp '%s' with the transformation of Docker-Compose file as both image name and Docker-Compose file were specified", + "MultiContainerDeploymentWithoutTransformation": "Multi-container deployment to the webapp '%s' without transformation of Docker-Compose file because only Docker-Compose file was specified." } } \ No newline at end of file diff --git a/Tasks/AzureWebAppContainerV1/task.loc.json b/Tasks/AzureWebAppContainerV1/task.loc.json index 94e60217fb7b..f8d81dac6c26 100644 --- a/Tasks/AzureWebAppContainerV1/task.loc.json +++ b/Tasks/AzureWebAppContainerV1/task.loc.json @@ -101,12 +101,12 @@ "helpMarkDown": "ms-resource:loc.input.help.imageName" }, { - "name": "configFilePath", + "name": "multicontainerConfigFile", "type": "filePath", - "label": "ms-resource:loc.input.label.configFilePath", + "label": "ms-resource:loc.input.label.multicontainerConfigFile", "defaultValue": "", "required": false, - "helpMarkDown": "ms-resource:loc.input.help.configFilePath" + "helpMarkDown": "ms-resource:loc.input.help.multicontainerConfigFile" }, { "name": "containerCommand", diff --git a/Tasks/AzureWebAppContainerV1/taskparameters.ts b/Tasks/AzureWebAppContainerV1/taskparameters.ts index 745c338a6fd7..b12a175c34e1 100644 --- a/Tasks/AzureWebAppContainerV1/taskparameters.ts +++ b/Tasks/AzureWebAppContainerV1/taskparameters.ts @@ -25,7 +25,7 @@ export class TaskParametersUtility { DeployToSlotOrASEFlag: tl.getBoolInput('deployToSlotOrASE', false), ResourceGroupName: tl.getInput('resourceGroupName', false), SlotName: tl.getInput('slotName', false), - ConfigFilePath: tl.getPathInput('configFilePath', false) + MulticontainerConfigFile: tl.getPathInput('multicontainerConfigFile', false) } taskParameters.azureEndpoint = await new AzureRMEndpoint(taskParameters.connectedServiceName).getEndpoint(); @@ -42,7 +42,7 @@ export class TaskParametersUtility { let containerDetails = await this.getContainerKind(taskParameters); taskParameters.ImageName = containerDetails["imageName"]; taskParameters.isMultiContainer = containerDetails["isMultiContainer"]; - taskParameters.ConfigFilePath = containerDetails["configFilePath"]; + taskParameters. MulticontainerConfigFile = containerDetails["multicontainerConfigFile"]; return taskParameters; } @@ -74,17 +74,17 @@ export class TaskParametersUtility { let imageName = taskParameters.ImageName; let isMultiLineImages: boolean = imageName && imageName.indexOf("\n") != -1; let isMultiContainer = false; - let configFilePath = PackageUtility.getPackagePath(taskParameters.ConfigFilePath); + let multicontainerConfigFile = PackageUtility.getPackagePath(taskParameters.MulticontainerConfigFile); - if(!imageName && tl.stats(configFilePath).isDirectory()) { + if(!imageName && tl.stats(multicontainerConfigFile).isDirectory()) { throw new Error(tl.loc('FailedToDeployToWebApp', taskParameters.WebAppName)); } - if(imageName && !isMultiLineImages && tl.stats(configFilePath).isDirectory()) { + if(imageName && !isMultiLineImages && tl.stats(multicontainerConfigFile).isDirectory()) { console.log(tl.loc("SingleContainerDeployment", taskParameters.WebAppName)); } - if(tl.stats(configFilePath).isFile()) { + if(tl.stats(multicontainerConfigFile).isFile()) { isMultiContainer = true; if(imageName) { console.log(tl.loc("MultiContainerDeploymentWithTransformation", taskParameters.WebAppName)); @@ -102,7 +102,7 @@ export class TaskParametersUtility { return { imageName: imageName, isMultiContainer: isMultiContainer, - configFilePath: configFilePath + multicontainerConfigFile: multicontainerConfigFile }; } } @@ -120,6 +120,6 @@ export interface TaskParameters { DeployToSlotOrASEFlag?: boolean; SlotName?: string; isLinuxContainerApp?: boolean; - ConfigFilePath?: string; + MulticontainerConfigFile?: string; isMultiContainer?: boolean; } diff --git a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts index deb9558b5247..2072e24861c4 100644 --- a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts +++ b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts @@ -25,10 +25,10 @@ export class ContainerBasedDeploymentUtility { public async deployWebAppImage(properties: any): Promise { let imageName: string = properties["ImageName"]; - let configFilePath: string = properties["ConfigFilePath"]; + let multicontainerConfigFile: string = properties["MulticontainerConfigFile"]; let isMultiContainer: boolean = properties["isMultiContainer"]; let isLinuxApp: boolean = properties["isLinuxContainerApp"]; - let updatedConfigFilePath: string = configFilePath; + let updatedMulticontainerConfigFile: string = multicontainerConfigFile; if(imageName) { tl.debug("Deploying image " + imageName + " to the webapp " + this._appService.getName()); @@ -36,21 +36,21 @@ export class ContainerBasedDeploymentUtility { if(isMultiContainer) { if(imageName) { - updatedConfigFilePath = this.updateImagesInConfigFile(configFilePath, imageName); + updatedMulticontainerConfigFile = this.updateImagesInConfigFile(multicontainerConfigFile, imageName); } // uploading log file - console.log(`##vso[task.uploadfile]${updatedConfigFilePath}`); + console.log(`##vso[task.uploadfile]${updatedMulticontainerConfigFile}`); } tl.debug("Updating the webapp configuration."); - await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], isLinuxApp, imageName, isMultiContainer, updatedConfigFilePath); + await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], isLinuxApp, imageName, isMultiContainer, updatedMulticontainerConfigFile); tl.debug('making a restart request to app service'); await this._appService.restart(); } - private async _updateConfigurationDetails(configSettings: any, startupCommand: string, isLinuxApp: boolean, imageName?: string, isMultiContainer?: boolean, configFilePath?: string): Promise { + private async _updateConfigurationDetails(configSettings: any, startupCommand: string, isLinuxApp: boolean, imageName?: string, isMultiContainer?: boolean, multicontainerConfigFile?: string): Promise { var appSettingsNewProperties = !!configSettings ? parse(configSettings.trim()): { }; appSettingsNewProperties.appCommandLine = { 'value': startupCommand @@ -58,7 +58,7 @@ export class ContainerBasedDeploymentUtility { if(isLinuxApp) { if(isMultiContainer) { - let fileData = fs.readFileSync(configFilePath); + let fileData = fs.readFileSync(multicontainerConfigFile); appSettingsNewProperties.linuxFxVersion = { 'value': "COMPOSE|" + (new Buffer(fileData).toString('base64')) } @@ -230,9 +230,9 @@ export class ContainerBasedDeploymentUtility { delete webAppSettings["properties"]["DOCKER_REGISTRY_SERVER_PASSWORD"]; } - private updateImagesInConfigFile(configFilePath, images): string { + private updateImagesInConfigFile(multicontainerConfigFile, images): string { const tempDirectory = deployUtility.getTempDirectory(); - var contents = fs.readFileSync(configFilePath).toString(); + var contents = fs.readFileSync(multicontainerConfigFile).toString(); var imageList = images.split("\n"); imageList.forEach((image: string) => { let imageName = image.split(":")[0]; @@ -241,7 +241,7 @@ export class ContainerBasedDeploymentUtility { } }); - let newFilePath = path.join(tempDirectory, path.basename(configFilePath)); + let newFilePath = path.join(tempDirectory, path.basename(multicontainerConfigFile)); fs.writeFileSync( path.join(newFilePath), contents From 8d9596c6ad1214cfbc9a86cc0f6e9381f4166739 Mon Sep 17 00:00:00 2001 From: Shivangi Date: Wed, 10 Apr 2019 15:19:33 +0530 Subject: [PATCH 11/13] Changing tooltip of imageName --- .../Strings/resources.resjson/en-US/resources.resjson | 2 +- Tasks/AzureWebAppContainerV1/task.json | 5 ++++- Tasks/AzureWebAppContainerV1/task.loc.json | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson index c58e05fa1677..464f44464fdc 100644 --- a/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson +++ b/Tasks/AzureWebAppContainerV1/Strings/resources.resjson/en-US/resources.resjson @@ -15,7 +15,7 @@ "loc.input.label.slotName": "Slot", "loc.input.help.slotName": "Enter or Select an existing Slot other than the Production slot.", "loc.input.label.imageName": "Image name", - "loc.input.help.imageName": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'.", + "loc.input.help.imageName": "Specify the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' or 'python:3.7.2-alpine/'. For multi-container scenario multiple container image names can be provided.", "loc.input.label.multicontainerConfigFile": "Configuration File", "loc.input.help.multicontainerConfigFile": "Path of the Docker-Compose file. Should be a fully qualified path or relative to the default working directory.", "loc.input.label.containerCommand": "Startup command ", diff --git a/Tasks/AzureWebAppContainerV1/task.json b/Tasks/AzureWebAppContainerV1/task.json index 1aca0f30dd99..29e7f87995d1 100644 --- a/Tasks/AzureWebAppContainerV1/task.json +++ b/Tasks/AzureWebAppContainerV1/task.json @@ -83,11 +83,14 @@ }, { "name": "imageName", + "aliases": [ + "containers" + ], "type": "multiline", "label": "Image name", "defaultValue": "", "required": false, - "helpMarkDown": "A globally unique top-level domain name for your specific registry or namespace.
Note: Fully qualified image name will be of the format: '`/`:`'. For example, 'myregistry.azurecr.io/nginx:latest'." + "helpMarkDown": "Specify the fully qualified container image name. For example, 'myregistry.azurecr.io/nginx:latest' or 'python:3.7.2-alpine/'. For multi-container scenario multiple container image names can be provided." }, { "name": "multicontainerConfigFile", diff --git a/Tasks/AzureWebAppContainerV1/task.loc.json b/Tasks/AzureWebAppContainerV1/task.loc.json index f9dbea7c01b9..27d971160e1a 100644 --- a/Tasks/AzureWebAppContainerV1/task.loc.json +++ b/Tasks/AzureWebAppContainerV1/task.loc.json @@ -83,6 +83,9 @@ }, { "name": "imageName", + "aliases": [ + "containers" + ], "type": "multiline", "label": "ms-resource:loc.input.label.imageName", "defaultValue": "", From 0a919b7ec6f0743dce3c7383ae2f3c3a310e6adb Mon Sep 17 00:00:00 2001 From: Shivangi Date: Fri, 12 Apr 2019 13:10:22 +0530 Subject: [PATCH 12/13] git commit -m "resolving checks" --- Tasks/AzureWebAppContainerV1/Tests/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tasks/AzureWebAppContainerV1/Tests/utils.ts b/Tasks/AzureWebAppContainerV1/Tests/utils.ts index 3718ae370d32..4efebf943eea 100644 --- a/Tasks/AzureWebAppContainerV1/Tests/utils.ts +++ b/Tasks/AzureWebAppContainerV1/Tests/utils.ts @@ -83,5 +83,5 @@ export function mockTaskInputParameters(tr) { tr.setInput('appName', 'mytestapp'); tr.setInput('imageName', 'dockernamespace/dockerrepository:DockerImageTag'); tr.setInput('AppSettings', '-port 1173'); - tr.setInput(' multicontainerConfigFile', '/home/site/wwwroot'); + tr.setInput('multicontainerConfigFile', '/home/site/wwwroot'); } \ No newline at end of file From 93f13418fdd5547a693c80cc16d068ccfe1bb0a6 Mon Sep 17 00:00:00 2001 From: Shivangi Date: Fri, 12 Apr 2019 13:42:49 +0530 Subject: [PATCH 13/13] Resolving last comment --- .../operations/ContainerBasedDeploymentUtility.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts index 2072e24861c4..0f2374c2db12 100644 --- a/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts +++ b/Tasks/Common/AzureRmDeploy-common/operations/ContainerBasedDeploymentUtility.ts @@ -30,11 +30,8 @@ export class ContainerBasedDeploymentUtility { let isLinuxApp: boolean = properties["isLinuxContainerApp"]; let updatedMulticontainerConfigFile: string = multicontainerConfigFile; - if(imageName) { - tl.debug("Deploying image " + imageName + " to the webapp " + this._appService.getName()); - } - if(isMultiContainer) { + tl.debug("Deploying Docker-Compose file " + multicontainerConfigFile + " to the webapp " + this._appService.getName()); if(imageName) { updatedMulticontainerConfigFile = this.updateImagesInConfigFile(multicontainerConfigFile, imageName); } @@ -42,6 +39,9 @@ export class ContainerBasedDeploymentUtility { // uploading log file console.log(`##vso[task.uploadfile]${updatedMulticontainerConfigFile}`); } + else if(imageName) { + tl.debug("Deploying image " + imageName + " to the webapp " + this._appService.getName()); + } tl.debug("Updating the webapp configuration."); await this._updateConfigurationDetails(properties["ConfigurationSettings"], properties["StartupCommand"], isLinuxApp, imageName, isMultiContainer, updatedMulticontainerConfigFile);