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

Azure App Service Manage Task - Refactor & Bug fixes #6001

Merged
merged 30 commits into from
Dec 21, 2017

Conversation

vincent1173
Copy link
Contributor

Issues Fixed:

  • Get Kudu credentials from Publishing credentials instead of publishing profile.
  • Invoke web-request for slots for Start/Stop/Restart/Swap to avoid Cold-start.

"node_modules/azurestack-common/node_modules/vsts-task-lib",
"node_modules/azurestack-common/node_modules/vso-node-api"
"node_modules/azure-arm-rest/node_modules/vsts-task-lib",
"node_modules/azure-arm-rest/node_modules/vso-node-api"
],
Copy link
Member

Choose a reason for hiding this comment

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

I think now there is no vso-node-api.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.


export class AzureResourceFilterManagementClient extends azureServiceClient.ServiceClient {
public _azureResourceFilter: AzureResourceFilter;

Copy link
Member

Choose a reason for hiding this comment

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

Should public members not start with _

this._client = client;
}

public getResources(resourceType: string, resourceName: string, options: any, callback: azureServiceClient.ApiCallback) {
Copy link
Member

Choose a reason for hiding this comment

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

while the callback based approach is what is used most in this library - for newer methods we are keeping it all in promises for cleaner code. If you want to use Promises for the public methods - that might keep the code simpler. This method would be changed to
public getResources(resourceType: string, resourceName: string) : Promise

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Don't have the callback version at all. That will help you avoid creating the wrapper

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed callback as discussed offline.

import { AzureResourceFilterManagementClient } from './azure-arm-resource-filter';
import { AzureEndpoint } from './azureModels';

export class AzureResourceFilterController {
Copy link
Member

Choose a reason for hiding this comment

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

why do you need this wrapper class. If it is for callback to promise conversion - you can directly use promises in the client class itself

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@sachinma , this wrapper class is created as the logic required to find resources is common for Manage and deploy task. Resolving the promise here.

private _azureResourceFilterManagementClient: AzureResourceFilterManagementClient;
private _endpoint: AzureEndpoint;

constructor(endpoint) {
Copy link
Member

Choose a reason for hiding this comment

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

consider providing an overload or a converter method directly in the base client class

@@ -101,3 +102,118 @@ export class ApplicationTokenCredentials {
return deferred.promise;
}
}

export class AzureRMEndpoint {
Copy link
Member

Choose a reason for hiding this comment

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

Consider moving to a separate file


import { AzureRMEndpoint } from 'azure-arm-rest/azure-arm-common';
import { AzureEndpoint } from 'azure-arm-rest/azureModels';
import {AzureAppService } from 'azure-arm-rest/azure-arm-app-service';
Copy link
Contributor

Choose a reason for hiding this comment

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

missing space 👅

switch(action) {
case "Start Azure App Service": {
console.log(await azureRmUtil.startAppService(endPoint, resourceGroupName, webAppName, specifySlotFlag, slotName));
await waitForAppServiceToStart(endPoint, resourceGroupName, webAppName, specifySlotFlag, slotName);
var appService: AzureAppService = new AzureAppService(azureEndpoint, resourceGroupName, webAppName, slotName);
Copy link
Contributor

Choose a reason for hiding this comment

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

can this be moved outside switch and reused in all cases ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not required for Swap slots, so made it duplicate.
Will check for other efficient ways,

@@ -86,7 +86,7 @@ async function toWebResponse(response: httpClient.HttpClientResponse): Promise<W
return res;
}

function sleepFor(sleepDurationInSeconds): Promise<any> {
export function sleepFor(sleepDurationInSeconds): Promise<any> {
return new Promise((resolve, reeject) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

"reeject" the promise 😝


result = result.concat(response.body.value);
if(response.body.nextLink) {
var nextResult = await this._client.accumulateResultFromPagedResult(response.body.nextLink);
Copy link
Contributor

Choose a reason for hiding this comment

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

the second set of results can also have nextLink, right ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

accumulateResultFromPagedResult has a loop that queries for the result for next result API and so on.

private _endpoint: AzureEndpoint;
private _client: ServiceClient;

constructor(endpoint: AzureEndpoint, resourceGroupName: string, resourceName: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

consider renaming resourceName to applicationInsightName.


}

private webTestData = {
Copy link
Contributor

Choose a reason for hiding this comment

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

private variables should start with _

import webClient = require("./webClient");
import { AzureEndpoint } from "./azureModels";
export class AzureRMEndpoint {
public _endpoint: AzureEndpoint;
Copy link

Choose a reason for hiding this comment

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

I assume _variablename format you have choosen for private variables only. At few places public variables are defined with underscore and some places private variables are without underscore. Can we keep pattern same.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure. thanks

break;
}
default: {
this._endpoint.environmentAuthorityUrl = (!!this._endpoint.environmentAuthorityUrl) ? this._endpoint.environmentAuthorityUrl : "https://login.windows.net/";
Copy link

Choose a reason for hiding this comment

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

Move "https://login.windows.net/" to constants. Should we define a constants file and add all constants there.


}

private _getAzureStackData(endpoint: AzureEndpoint) {
Copy link

Choose a reason for hiding this comment

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

By defining this method I am assuming you are removing dependency from azurestack-common. Please make sure all modules that are dependent on azurestack-common will get updated. Let me know if you need help regarding azure stack validations.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the dependency is removed only for Azue App Service Manage task, and will be removing for Azure App Service Deploy task too.
As discussed, it may be a code redundancy, will inform the other task owners as well. (Azure Key vault & Azure RG task)

@@ -2,7 +2,7 @@ import tl = require('vsts-task-lib/task');
import Q = require('q');
import querystring = require('querystring');
import webClient = require("./webClient");
var util = require('util');
import { AzureEndpoint } from "./azureModels";
Copy link

Choose a reason for hiding this comment

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

Where it's being used ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.

{
'{resourceGroupName}': this._resourceGroupName,
'{resourceName}': this._resourceName,
}, null, '2015-05-01');
Copy link

Choose a reason for hiding this comment

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

There should be constant for API Version

httpRequest.uri = this._client.getRequestUri(`//subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/microsoft.insights/webtests`,
{
'{resourceGroupName}': this._resourceGroupName
}, null, '2015-05-01');
Copy link

Choose a reason for hiding this comment

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

Constant for API Version

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will do it with deploy task.


public async create(appInsightsResource: any, applicationUrl: string) {
var webTestName = "vsts-web-test-" + Date.now();
var webTestData = JSON.parse(JSON.stringify(this.webTestData));
Copy link

Choose a reason for hiding this comment

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

should we create a new private method populateWebTestData

// Initialize Azure Endpoint for specific environment
switch(this._endpoint.environment.toLowerCase()) {
case this._environments.AzureStack: {
this._getAzureStackData(this._endpoint).then((endpoint) => {
Copy link

Choose a reason for hiding this comment

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

We need to initialize this value if Azure Stack data is not being initialized from server.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure. done

}
case "Install Extensions": {
if(appServiceKuduService) {
await updateDeploymentStatusInKudu(appServiceKuduService, taskResult, DeploymentID, {"type": action});
Copy link
Member

Choose a reason for hiding this comment

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

where is the DeploymentID initialized ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.

activeDirectoryResourceID: tl.getEndpointDataParameter(this._connectedServiceName, 'activeDirectoryServiceEndpointResourceId', true)
} as AzureEndpoint;

if(this.endpoint.environment != null && ( !this.endpoint.environmentAuthorityUrl || !this.endpoint.activeDirectoryResourceID)) {
Copy link

Choose a reason for hiding this comment

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

Check for Azure Stack can be moved above instead of nested check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

import { AzureRMEndpoint } from 'azure-arm-rest/azure-arm-endpoint';
import { AzureEndpoint } from 'azure-arm-rest/azureModels';
import {AzureAppService } from 'azure-arm-rest/azure-arm-app-service';
// import { AzureAppService } from 'azure-arm-rest/AzureAppService';
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment ?

retryIntervalInSeconds: reqOptions && reqOptions.retryIntervalInSeconds ? reqOptions.retryIntervalInSeconds : 10,
retryCount: reqOptions && reqOptions.retryCount ? reqOptions.retryCount : 6,
retriableErrorCodes: reqOptions && reqOptions.retriableErrorCodes ? reqOptions.retriableErrorCodes : ["ETIMEDOUT"],
retriableStatusCodes: reqOptions && reqOptions.retriableStatusCodes ? reqOptions.retriableStatusCodes : [409, 500, 502, 503]
Copy link
Contributor

Choose a reason for hiding this comment

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

please add 504 Gateway timeout as well.

@vincent1173 vincent1173 merged commit 6b63550 into master Dec 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: AzureAppService Label to monitor Azure App Service issues Area: Release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants