Skip to content

Commit 92a056e

Browse files
authored
Merge pull request #3260 from Microsoft/users/dikhakha/AzureAppServiceManage2
monitor status of slot swap operation
2 parents 229e4d5 + 318f032 commit 92a056e

File tree

5 files changed

+100
-32
lines changed

5 files changed

+100
-32
lines changed

Tasks/AzureAppServiceManage/Strings/resources.resjson/en-US/resources.resjson

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"loc.messages.Failedtoupdateslotswaphistory": "Failed to update slot swap history for Azure Web App : %s",
2727
"loc.messages.WARNINGCannotupdateslotswapstatusSCMendpointisnotenabledforthiswebsite": "WARNING : Cannot update slot swap status : SCM (Source Control Manager) endpoint is not enabled for this Azure Web App",
2828
"loc.messages.CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved": "Cannot update Kudu deployment log as unique deployment ID cannot be retrieved for this Azure Web App",
29-
"loc.messages.Failedtoswapslots": "Failed to swap slots. Status %s for Azure Web App : %s",
29+
"loc.messages.FailedToSwapWebAppSlots": "Failed to swap slots for Azure Web App: %s. Error: %s",
30+
"loc.messages.SlotSwapOperationNotCompleted": "Slot swap operation was not completed for Azure Web App: %s",
3031
"loc.messages.Successfullyswappedslots": "Successfully swapped web app %s slots from %s to %s",
3132
"loc.messages.SourceAndTargetSlotCannotBeSame": "Source and target slot cannot be same",
3233
"loc.messages.Successfullyupdateddeploymenthistory": "Successfully updated deployment History at %s",

Tasks/AzureAppServiceManage/azureappservicemanage.ts

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ var azureRmUtil = require('azurerest-common/azurerestutility.js');
55
var kuduLogUtil = require('azurerest-common/kududeploymentstatusutility.js');
66

77
async function swapSlot(endPoint, resourceGroupName: string, webAppName: string, sourceSlot: string, swapWithProduction: boolean, targetSlot: string, preserveVnet: boolean) {
8-
if(swapWithProduction) {
9-
targetSlot = "production";
8+
try {
9+
await azureRmUtil.swapWebAppSlot(endPoint, resourceGroupName, webAppName, sourceSlot, targetSlot, preserveVnet);
10+
tl._writeLine(tl.loc("Successfullyswappedslots", webAppName, sourceSlot, targetSlot));
1011
}
11-
if(sourceSlot === targetSlot){
12-
throw new Error(tl.loc("SourceAndTargetSlotCannotBeSame"));
12+
catch(error) {
13+
if(!!error)
14+
throw new Error(tl.loc("FailedToSwapWebAppSlots", webAppName, error));
15+
else
16+
throw new Error(tl.loc("SlotSwapOperationNotCompleted", webAppName));
1317
}
14-
tl._writeLine(await azureRmUtil.swapWebAppSlot(endPoint, resourceGroupName, webAppName, sourceSlot, targetSlot, preserveVnet));
1518
}
1619

1720
async function updateKuduDeploymentLog(endPoint, webAppName, resourceGroupName, slotFlag, slotName, taskResult, customMessage, deploymentId) {
@@ -40,6 +43,8 @@ async function run() {
4043
var endPointAuthCreds = tl.getEndpointAuthorization(connectedServiceName, true);
4144
var subscriptionId = tl.getEndpointDataParameter(connectedServiceName, 'subscriptionid', true);
4245
var taskResult = true;
46+
var errorMessage: string = "";
47+
var updateDeploymentStatus: boolean = true;
4348

4449
var endPoint = new Array();
4550
endPoint["servicePrincipalClientID"] = tl.getEndpointAuthorizationParameter(connectedServiceName, 'serviceprincipalid', true);
@@ -65,35 +70,46 @@ async function run() {
6570
break;
6671
}
6772
case "Swap Slots": {
73+
if (swapWithProduction) {
74+
targetSlot = "production";
75+
}
76+
if (sourceSlot === targetSlot) {
77+
updateDeploymentStatus = false;
78+
throw new Error(tl.loc("SourceAndTargetSlotCannotBeSame"));
79+
}
6880
await swapSlot(endPoint, resourceGroupName, webAppName, sourceSlot, swapWithProduction, targetSlot, preserveVnet);
6981
break;
7082
}
7183
default:
7284
throw Error(tl.loc('InvalidAction'));
7385
}
7486
}
75-
catch(exception)
76-
{
87+
catch(exception) {
7788
taskResult = false;
78-
tl.setResult(tl.TaskResult.Failed, exception);
79-
}
80-
var customMessage = {
81-
type: action
89+
errorMessage = exception;
8290
}
83-
var deploymentId = kuduLogUtil.generateDeploymentId();
91+
if (updateDeploymentStatus) {
92+
var customMessage = {
93+
type: action
94+
}
95+
var deploymentId = kuduLogUtil.generateDeploymentId();
8496

85-
if(action === "Swap Slots") {
86-
customMessage['type'] = 'SlotSwap'; // for Ibiza CD flow
87-
customMessage['sourceSlot'] = sourceSlot;
88-
customMessage['targetSlot'] = swapWithProduction ? "Production" : targetSlot;
97+
if(action === "Swap Slots") {
98+
customMessage['type'] = 'SlotSwap'; // for Ibiza CD flow
99+
customMessage['sourceSlot'] = sourceSlot;
100+
customMessage['targetSlot'] = swapWithProduction ? "Production" : targetSlot;
89101

90-
await updateKuduDeploymentLog(endPoint, webAppName, resourceGroupName, true, sourceSlot, taskResult, customMessage, deploymentId);
91-
await updateKuduDeploymentLog(endPoint, webAppName, resourceGroupName, !(swapWithProduction), targetSlot, taskResult, customMessage, deploymentId);
102+
await updateKuduDeploymentLog(endPoint, webAppName, resourceGroupName, true, sourceSlot, taskResult, customMessage, deploymentId);
103+
await updateKuduDeploymentLog(endPoint, webAppName, resourceGroupName, !(swapWithProduction), targetSlot, taskResult, customMessage, deploymentId);
104+
}
105+
else {
106+
customMessage['slotName'] = (specifySlotFlag) ? slotName : 'Production';
107+
await updateKuduDeploymentLog(endPoint, webAppName, resourceGroupName, specifySlotFlag, slotName, taskResult, customMessage, deploymentId);
108+
}
92109
}
93-
else {
94-
customMessage['slotName'] = (specifySlotFlag) ? slotName : 'Production';
95-
await updateKuduDeploymentLog(endPoint, webAppName, resourceGroupName, specifySlotFlag, slotName, taskResult, customMessage, deploymentId);
110+
if (!taskResult) {
111+
tl.setResult(tl.TaskResult.Failed, errorMessage);
96112
}
97113
}
98114

99-
run();
115+
run();

Tasks/AzureAppServiceManage/task.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@
183183
"Failedtoupdateslotswaphistory": "Failed to update slot swap history for Azure Web App : %s",
184184
"WARNINGCannotupdateslotswapstatusSCMendpointisnotenabledforthiswebsite": "WARNING : Cannot update slot swap status : SCM (Source Control Manager) endpoint is not enabled for this Azure Web App",
185185
"CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved": "Cannot update Kudu deployment log as unique deployment ID cannot be retrieved for this Azure Web App",
186-
"Failedtoswapslots": "Failed to swap slots. Status %s for Azure Web App : %s",
186+
"FailedToSwapWebAppSlots": "Failed to swap slots for Azure Web App: %s. Error: %s",
187+
"SlotSwapOperationNotCompleted": "Slot swap operation was not completed for Azure Web App: %s",
187188
"Successfullyswappedslots": "Successfully swapped web app %s slots from %s to %s",
188189
"SourceAndTargetSlotCannotBeSame": "Source and target slot cannot be same",
189190
"Successfullyupdateddeploymenthistory": "Successfully updated deployment History at %s",

Tasks/AzureAppServiceManage/task.loc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,8 @@
182182
"Failedtoupdateslotswaphistory": "ms-resource:loc.messages.Failedtoupdateslotswaphistory",
183183
"WARNINGCannotupdateslotswapstatusSCMendpointisnotenabledforthiswebsite": "ms-resource:loc.messages.WARNINGCannotupdateslotswapstatusSCMendpointisnotenabledforthiswebsite",
184184
"CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved": "ms-resource:loc.messages.CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved",
185-
"Failedtoswapslots": "ms-resource:loc.messages.Failedtoswapslots",
185+
"FailedToSwapWebAppSlots": "ms-resource:loc.messages.FailedToSwapWebAppSlots",
186+
"SlotSwapOperationNotCompleted": "ms-resource:loc.messages.SlotSwapOperationNotCompleted",
186187
"Successfullyswappedslots": "ms-resource:loc.messages.Successfullyswappedslots",
187188
"SourceAndTargetSlotCannotBeSame": "ms-resource:loc.messages.SourceAndTargetSlotCannotBeSame",
188189
"Successfullyupdateddeploymenthistory": "ms-resource:loc.messages.Successfullyupdateddeploymenthistory",

Tasks/Common/azurerest-common/azurerestutility.ts

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,54 @@ export async function updateWebAppAppSettings(endpoint, webAppName: string, reso
308308
return deferred.promise;
309309
}
310310

311-
export async function swapWebAppSlot(endpoint, resourceGroupName: string, webAppName: string, sourceSlot: string, targetSlot: string,preserveVnet: boolean) {
311+
async function getOperationStatus(SPN, webAppName: string, resourceGroupName: string, slotName: string, url: string) {
312+
var deferred = Q.defer();
313+
var accessToken = await getAuthorizationToken(SPN);
314+
var headers = {
315+
authorization: 'Bearer ' + accessToken
316+
};
317+
httpObj.get('GET', url, headers, (error, response, body) => {
318+
if (error) {
319+
deferred.reject(error);
320+
}
321+
else {
322+
deferred.resolve(response);
323+
}
324+
});
325+
return deferred.promise;
326+
}
327+
328+
function monitorSlotSwap(SPN, webAppName, resourceGroupName, sourceSlot, targetSlot, url) {
329+
var deferred = Q.defer();
330+
var attempts = 0;
331+
var poll = async function() {
332+
if (attempts < 360) {
333+
attempts++;
334+
await getOperationStatus(SPN, webAppName, resourceGroupName, sourceSlot, url).then((response) => {
335+
if (response['statusCode'] === 200) {
336+
deferred.resolve();
337+
}
338+
else if(response['statusCode'] === 202) {
339+
tl.debug("Slot swap operation is in progress. Attempt : "+ attempts);
340+
setTimeout(poll, 5000);
341+
}
342+
else {
343+
deferred.reject(response['statusMessage']);
344+
}
345+
}).catch((error) => {
346+
deferred.reject(error);
347+
});
348+
}
349+
else {
350+
deferred.reject("");
351+
}
352+
}
353+
poll();
354+
return deferred.promise;
355+
}
312356

357+
export async function swapWebAppSlot(endpoint, resourceGroupName: string, webAppName: string, sourceSlot: string, targetSlot: string,preserveVnet: boolean) {
358+
313359
var deferred = Q.defer<any>();
314360
var url = armUrl + 'subscriptions/' + endpoint.subscriptionId + '/resourceGroups/' + resourceGroupName +
315361
'/providers/Microsoft.Web/sites/' + webAppName + "/slots/" + sourceSlot + '/slotsswap?' + azureApiVersion;
@@ -328,16 +374,19 @@ export async function swapWebAppSlot(endpoint, resourceGroupName: string, webApp
328374
);
329375

330376
tl._writeLine(tl.loc('StartingSwapSlot',webAppName));
331-
httpObj.send('POST', url, body, headers, (error, response, body) => {
377+
httpObj.send('POST', url, body, headers, async (error, response, body) => {
332378
if(error) {
333379
deferred.reject(error);
334380
}
335-
if(response.statusCode === 202) {
336-
deferred.resolve(tl.loc("Successfullyswappedslots", webAppName, sourceSlot, targetSlot));
381+
else if(response.statusCode === 202) {
382+
await monitorSlotSwap(endpoint, webAppName, resourceGroupName, sourceSlot, targetSlot, response.headers.location).then(() => {
383+
deferred.resolve();
384+
}).catch((error) => {
385+
deferred.reject(error);
386+
});
337387
}
338388
else {
339-
tl.error(response.statusMessage);
340-
deferred.reject(tl.loc("Failedtoswapslots",response.statusCode, webAppName));
389+
deferred.reject(response.statusMessage);
341390
}
342391
});
343392
return deferred.promise;
@@ -429,4 +478,4 @@ export async function restartAppService(endpoint, resourceGroupName: string, web
429478
}
430479
});
431480
return deferred.promise;
432-
}
481+
}

0 commit comments

Comments
 (0)