Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AzureRMWebAppTask migrated to nodejs #2506

Merged
merged 65 commits into from
Sep 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
5c87a1c
Migrating from Powershell to Node.js
vincent1173 Aug 11, 2016
fa03c87
Made Change to Friendly Name
vincent1173 Aug 11, 2016
28e9932
Additional Changes
vincent1173 Aug 11, 2016
8656196
Additional Changes
vincent1173 Aug 11, 2016
f704897
Made changes to RMUtil
vincent1173 Aug 12, 2016
b703fef
Merge branch 'master' of https://github.com/Microsoft/vsts-tasks into…
vincent1173 Aug 12, 2016
2aeb4cb
Made change to Rest Call
vincent1173 Aug 12, 2016
88bd1e0
Added Q
vincent1173 Aug 12, 2016
3f2fc9e
Added Q Library
vincent1173 Aug 12, 2016
2165c5c
Rearranged module headers
vincent1173 Aug 17, 2016
0a879a2
Made changes to task.json
vincent1173 Aug 18, 2016
9ad95f3
Redefining error message
vincent1173 Aug 18, 2016
6d5f42e
Removing PS Files
vincent1173 Aug 18, 2016
857b167
MSDEPloyexePath Function added
vincent1173 Aug 19, 2016
74c50bc
MSDEPloyexePath Function added
vincent1173 Aug 19, 2016
93f9a5e
Changed then with await, package.json updated
vincent1173 Aug 22, 2016
f5ca7e1
Removing .taskkey
vincent1173 Aug 22, 2016
a9f58b9
Run MSDeploycommand function updated
vincent1173 Aug 22, 2016
811338a
Async await changes
vincent1173 Aug 24, 2016
b835158
Handling files with spaces
vincent1173 Aug 24, 2016
b6f3080
CheckFile Function added
vincent1173 Aug 24, 2016
f28dd86
Fix for task not failing in case of error
vincent1173 Aug 25, 2016
8164962
Fixed review comments
vincent1173 Aug 25, 2016
6905985
Destination output url Fix
vincent1173 Aug 25, 2016
a435918
Publishing profile Fix
vincent1173 Aug 26, 2016
e7d9a4f
SetParamFile find Fix
vincent1173 Aug 26, 2016
66fb795
SetParam File Fix
vincent1173 Aug 26, 2016
f697987
File supplied Fix
vincent1173 Aug 26, 2016
9151d36
Fixing few formatting issues
mvvsubbu Aug 26, 2016
2fc7486
Users/ajya/node js folder support to task (#2328)
Aug 26, 2016
dd227f2
PR Review Fix (MSDeploy return code Fix)
vincent1173 Aug 30, 2016
180d22f
Added WebDeploy Function
vincent1173 Aug 30, 2016
3f70859
Added Comments at Method Level
vincent1173 Aug 30, 2016
283fc8a
AzureRMUtil Update Deployment History Fix
vincent1173 Aug 30, 2016
90903b1
Fixing Formatting issues
vincent1173 Aug 30, 2016
58a5f6f
Destination URL Fix
vincent1173 Aug 30, 2016
07cf6d8
Migrating AzureRmWebApp from Powershell to Node.js (#2262)
vincent1173 Aug 31, 2016
2aeb121
common part moved to main
Aug 31, 2016
2e64fed
Deployment of webapplication using KUDU service
Aug 31, 2016
de54213
Indentation correction of deferred statement
Sep 1, 2016
d18690f
added messages that will be help for debugging.
Sep 1, 2016
bae8f21
Adding unit test for AzureRMWebAppDeployment Task (#2386)
asranja Sep 1, 2016
6cfd9f0
Azure RM Upgrade scenario handling in task
mvvsubbu Sep 1, 2016
f7aee8d
Review comment fixes
mvvsubbu Sep 6, 2016
8893cda
Merge pull request #2389 from Microsoft/users/ajya/devKuduSupportARMW…
mvvsubbu Sep 6, 2016
051afc5
Changed Request to HttpClient
vincent1173 Sep 6, 2016
dd8efd8
Changes Reqyest to HttpClient
vincent1173 Sep 8, 2016
21e4d3d
Changed Error to defer(reject)
vincent1173 Sep 8, 2016
9aa3e20
Changed tl to defer(resolve)
vincent1173 Sep 8, 2016
ad36411
SetParamFile issue fix
vincent1173 Sep 8, 2016
af3d0cb
Merge pull request #2442 from Microsoft/users/vinca/AzureRestCall
vincent1173 Sep 9, 2016
fc2c47f
Merge pull request #2396 from Microsoft/users/subraman/azurermupgradefix
mvvsubbu Sep 9, 2016
db7590f
msDepoyBatchFIle Path FIx
vincent1173 Sep 9, 2016
8f8a430
Merge pull request #2452 from Microsoft/users/vinca/setParameterFix
vincent1173 Sep 12, 2016
d47e9f4
Conditional selection of deployment tool and check for param file on …
Sep 12, 2016
f9a492a
Added unit test (#2444)
asranja Sep 12, 2016
2e08efa
resolving merge conflicts
Sep 12, 2016
af472f7
Task upgrade fix for not reading right inputs
mvvsubbu Sep 15, 2016
a9c9467
Merge pull request #2532 from Microsoft/users/subraman/upgradebugfixes
mvvsubbu Sep 16, 2016
d821050
Reverting compact changes handling in UI
mvvsubbu Sep 16, 2016
f7f416c
Path Issue & Bug Bash Fix (#2512)
vincent1173 Sep 16, 2016
27af6ce
Merge pull request #2542 from Microsoft/users/subraman/revertupgradef…
mvvsubbu Sep 16, 2016
3a9d7e2
enabling appoffline feature by default (#2555)
Sep 19, 2016
38fc110
Parameter Content Fix (#2557)
vincent1173 Sep 19, 2016
d08a528
Help mark down corrected
Sep 19, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
272 changes: 272 additions & 0 deletions Tasks/AzureRmWebAppDeployment/AzureRMUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
/// <reference path="../../definitions/node.d.ts" />
/// <reference path="../../definitions/q.d.ts" />
/// <reference path="../../definitions/vsts-task-lib.d.ts" />
/// <reference path="../../definitions/vso-node-api.d.ts" />

var adal = require ('adal-node');
var parseString = require('xml2js').parseString;

import tl = require('vsts-task-lib/task');
import Q = require('q');
import httpClient = require('vso-node-api/HttpClient');
import restClient = require('vso-node-api/RestClient');

var httpObj = new httpClient.HttpClient(tl.getVariable("AZURE_HTTP_USER_AGENT"));
var restObj = new restClient.RestClient(httpObj);

var AuthenticationContext = adal.AuthenticationContext;
var authUrl = 'https://login.windows.net/';
var armUrl = 'https://management.azure.com/';
var azureApiVersion = 'api-version=2015-08-01';

/**
* updates the deployment status in kudu service
*
* @param publishingProfile Publish Profile details
* @param isDeploymentSuccess Status of Deployment
*
* @returns promise with string
*/
export function updateDeploymentStatus(publishingProfile, isDeploymentSuccess: boolean): Q.Promise<string> {
var deferred = Q.defer<string>();

var webAppPublishKuduUrl = publishingProfile.publishUrl;
if(webAppPublishKuduUrl) {
var requestDetails = getUpdateHistoryRequest(webAppPublishKuduUrl, isDeploymentSuccess);
var accessToken = 'Basic ' + (new Buffer(publishingProfile.userName + ':' + publishingProfile.userPWD).toString('base64'));
var headers = {
authorization: accessToken
};

restObj.replace(requestDetails['requestUrl'], null, requestDetails['requestBody'], headers, null,
(error, response, body) => {
if(error) {
deferred.reject(error);
}
else if(response === 200) {
deferred.resolve(tl.loc("Successfullyupdateddeploymenthistory", body.url));
}
else {
tl.warning(body);
deferred.reject(tl.loc("Failedtoupdatedeploymenthistory"));
}
});
}
else {
deferred.reject(tl.loc('WARNINGCannotupdatedeploymentstatusSCMendpointisnotenabledforthiswebsite'));
}

return deferred.promise;
}

/**
* Gets the Azure RM Web App Connections details from SPN
*
* @param SPN Service Principal Name
* @param webAppName Name of the web App
* @param resourceGroupName Resource Group Name
* @param deployToSlotFlag Flag to check slot deployment
* @param slotName Name of the slot
*
* @returns (JSON)
*/
export async function getAzureRMWebAppPublishProfile(SPN, webAppName: string, resourceGroupName: string, deployToSlotFlag: boolean, slotName: string) {
if(!deployToSlotFlag) {
var webAppID = await getAzureRMWebAppID(SPN, webAppName, 'Microsoft.Web/Sites');
// webAppID Format ==> /subscriptions/<subscriptionId>/resourceGroups/<resource_grp_name>/providers/Microsoft.Web/sites/<webAppName>
resourceGroupName = webAppID.id.split ('/')[4];
}
var publishProfile = await getWebAppPublishProfile(SPN, webAppName, resourceGroupName, deployToSlotFlag, slotName);
return publishProfile;
}

function getAuthorizationToken(SPN): Q.Promise<string> {

var deferred = Q.defer<string>();
var authorityUrl = authUrl + SPN.tenantID;

var context = new AuthenticationContext(authorityUrl);
context.acquireTokenWithClientCredentials(armUrl, SPN.servicePrincipalClientID, SPN.servicePrincipalKey, (error, tokenResponse) => {
if(error) {
deferred.reject(error);
}
else {
deferred.resolve(tokenResponse.accessToken);
}
});

return deferred.promise;
}

function getDeploymentAuthor(): string {
var author = tl.getVariable('build.sourceVersionAuthor');

if(author === undefined) {
author = tl.getVariable('build.requestedfor');
}

if(author === undefined) {
author = tl.getVariable('release.requestedfor');
}

if(author === undefined) {
author = tl.getVariable('agent.name');
}

return author;
}

function getUpdateHistoryRequest(webAppPublishKuduUrl: string, isDeploymentSuccess: boolean): any {

var status = isDeploymentSuccess ? 4 : 3;
var status_text = (status == 4) ? "success" : "failed";
var author = getDeploymentAuthor();

var buildUrl = tl.getVariable('build.buildUri');
var releaseUrl = tl.getVariable('release.releaseUri');

var buildId = tl.getVariable('build.buildId');
var releaseId = tl.getVariable('release.releaseId');

var collectionUrl = tl.getVariable('system.TeamFoundationCollectionUri');
var teamProject = tl.getVariable('system.teamProject');

var buildOrReleaseUrl = "" ;
var deploymentId = "";

if(releaseUrl !== undefined) {
deploymentId = releaseId + Date.now();
buildOrReleaseUrl = collectionUrl + teamProject + "/_apps/hub/ms.vss-releaseManagement-web.hub-explorer?releaseId=" + releaseId + "&_a=release-summary";
}
else if(buildUrl !== undefined) {
deploymentId = buildId + Date.now();
buildOrReleaseUrl = collectionUrl + teamProject + "/_build?buildId=" + buildId + "&_a=summary";
}
else {
throw new Error(tl.loc('CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved'));
}

var message = "Updating Deployment History For Deployment " + buildOrReleaseUrl;
var requestBody = {
status : status,
status_text : status_text,
message : message,
author : author,
deployer : 'VSTS',
details : buildOrReleaseUrl
};

var webAppHostUrl = webAppPublishKuduUrl.split(':')[0];
var requestUrl = "https://" + encodeURIComponent(webAppHostUrl) + "/deployments/" + encodeURIComponent(deploymentId);

var requestDetails = new Array<string>();
requestDetails["requestBody"] = requestBody;
requestDetails["requestUrl"] = requestUrl;
return requestDetails;
}

async function getWebAppPublishProfile(SPN, webAppName: string, resourceGroupName: string, deployToSlotFlag: boolean, slotName: string ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not required to be separate function merge both functions

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


var deferred = Q.defer();
var slotUrl = deployToSlotFlag ? "/slots/" + slotName : "";
var accessToken = await getAuthorizationToken(SPN);

var url = armUrl + 'subscriptions/' + SPN.subscriptionId + '/resourceGroups/' + resourceGroupName +
'/providers/Microsoft.Web/sites/' + webAppName + slotUrl + '/publishxml?' + azureApiVersion;
var headers = {
authorization: 'Bearer '+ accessToken

};

httpObj.get('POST', url, headers, (error, response, body) => {
if(error) {
deferred.reject(error);
}
else if(response.statusCode === 200) {
parseString(body, (error, result) => {
for (var index in result.publishData.publishProfile) {
if (result.publishData.publishProfile[index].$.publishMethod === "MSDeploy")
deferred.resolve(result.publishData.publishProfile[index].$);
}
deferred.reject(tl.loc('ErrorNoSuchDeployingMethodExists'));
});
}
else {
tl.error(response.statusMessage);
deferred.reject(tl.loc('UnabletoretrieveconnectiondetailsforazureRMWebApp0StatusCode1', webAppName, response.statusCode));
}
});

return deferred.promise;
}

async function getAzureRMWebAppID(SPN, webAppName: string, resourceType: string) {

var deferred = Q.defer<any>();
var accessToken = await getAuthorizationToken(SPN);

var url = armUrl + 'subscriptions/' + SPN.subscriptionId + '/resources?$filter=resourceType EQ \'' + resourceType +
'\' AND name EQ \'' + webAppName + '\'&api-version=2016-07-01';
var headers = {
authorization: 'Bearer '+ accessToken
};

httpObj.get('GET', url, headers, (error, response, body) => {
if(error) {
deferred.reject(error);
}
else if(response.statusCode === 200) {
var webAppIDDetails = JSON.parse(body);
deferred.resolve(webAppIDDetails.value[0]);
}
else {
tl.error(response.statusMessage);
deferred.reject(tl.loc('UnabletoretrieveWebAppIDforazureRMWebApp0StatusCode1', webAppName, response.statusCode));
}
});

return deferred.promise;
}

/**
* REST request for azure webapp config details. Config details contains virtual application mappings.
*
* @param SPN Subscription details
* @param webAppName Web application name
* @param deployToSlotFlag Should deploy to slot
* @param slotName Slot for deployment
*/
export async function getAzureRMWebAppConfigDetails(SPN, webAppName: string, resourceGroupName: string, deployToSlotFlag: boolean, slotName: string) {

if(!deployToSlotFlag) {
var webAppID = await getAzureRMWebAppID(SPN, webAppName, 'Microsoft.Web/Sites');
resourceGroupName = webAppID.id.split ('/')[4];
}

var deferred = Q.defer<any>();
var accessToken = await getAuthorizationToken(SPN);
var headers = {
authorization: 'Bearer '+ accessToken
};

var slotUrl = deployToSlotFlag ? "/slots/" + slotName : "";
var configUrl = armUrl + 'subscriptions/' + SPN.subscriptionId + '/resourceGroups/' + resourceGroupName +
'/providers/Microsoft.Web/sites/' + webAppName + slotUrl + '/config/web?' + azureApiVersion;
tl.debug(tl.loc("Requestingconfigdetails", configUrl));

httpObj.get('GET', configUrl, headers, (error, response, body) => {
if( error ) {
deferred.reject(error);
}
else if(response.statusCode === 200) {
var obj = JSON.parse(body);
deferred.resolve(obj);
}
else {
tl.error(response.statusMessage);
deferred.reject(tl.loc('ErrorOccurredStausCode0',response.statusCode));
}
});

return deferred.promise;
}
Loading