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

[AzureSpringCloudV0] Print app logs when deployment failed #19096

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "azure-spring-cloud-deployment-tests",
"version": "1.0.2",
"description": "Azure Pipelines Azure Spring Cloud Deployment Task Tests",
"main": "L0.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+ssh://[email protected]/Microsoft/azure-pipelines-tasks.git"
},
"author": "Microsoft Corporation",
"license": "MIT",
"bugs": {
"url": "https://github.com/Microsoft/azure-pipelines-tasks/issues"
},
"homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme",
"dependencies": {
"nock": "9.0.11",
"mocha": "8.3.2"
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,26 @@ export class AzureSpringApps {
return this._client.beginRequest(httpRequest);
}

/**
* send request using webClient.sendRequest
* @param method
* @param url
* @param body
* @param headers
* @returns webClient.WebResponse
*/
protected sendRequestV2(method: string, url: string, body?: any, headers?: any): Promise<webClient.WebResponse> {
var httpRequest = new webClient.WebRequest();
httpRequest.method = method;
httpRequest.uri = url;
if (body)
httpRequest.body = body;
if (headers)
httpRequest.headers = headers;
tl.debug(`Sending ${method} request to ${url}`);
return webClient.sendRequest(httpRequest);
}

/**
* Deploys an artifact to an Azure Spring Cloud deployment
* @param artifactToUpload
Expand Down Expand Up @@ -322,6 +342,30 @@ export class AzureSpringApps {
}
}

protected async getDeploymentInfo(appName: String, deploymentName: String): Promise<Object> {
tl.debug(`Query deployment ${deploymentName} for app ${appName}`)
const requestUri = this._client.getRequestUri(`${this._resourceId}/apps/{appName}/deployments/{deploymentName}`, {
'{appName}': appName,
'{deploymentName}': deploymentName
}, null, API_VERSION);

try {
const response = await this.sendRequest('GET', requestUri);
if (response.statusCode == 404) {
tl.debug(`404 when querying deployment ${deploymentName} for app ${appName}`);
throw Error(tl.loc('NoDeploymentsExist'));
} if (response.statusCode != 200) {
tl.error(`${tl.loc('UnableToGetDeploymentInformation')} ${tl.loc('StatusCode')}: ${response.statusCode}`);
throw ToError(response);
} else {
tl.debug('Found deployment ${deploymentName} for app ${appName}.');
return response.body;
}
} catch (error) {
throw (error);
}
}

/**
* Returns the currently inactive deployment, or `undefined` if none exists.
* @param appName
Expand Down Expand Up @@ -477,6 +521,7 @@ export class AzureSpringApps {
var response = await this.sendRequest(method, requestUri, JSON.stringify(deploymentUpdateRequestBody));
} catch (error) {
tl.debug('Error when sending app update request');
await this.printLatestAppInstanceLog(appName, deploymentName);
throw (error);
}
console.log(JSON.stringify(response.body, null, 2));
Expand All @@ -496,6 +541,7 @@ export class AzureSpringApps {
await this.awaitOperationCompletion(operationStatusUrl);
} catch (error) {
tl.debug('Error in awaiting operation completion');
await this.printLatestAppInstanceLog(appName, deploymentName);
throw error;
} finally {
//A build log is available on the deployment when uploading a folder. Let's display it.
Expand Down Expand Up @@ -650,4 +696,51 @@ export class AzureSpringApps {
throw (error);
}
}

private async printLatestAppInstanceLog(appName: string, deploymentName: string) {
console.info('Some error occured during deployment. Printing latest app instance log:');
const logStream = await this.logStreamConstructor();
const deploymentResource = await this.getDeploymentInfo(appName, deploymentName);
const instances = deploymentResource["properties"]["instances"];
let startTime = instances[0].startTime;
let instanceName = instances[0].name;

// print the newly created instance log
for (const tempInstance of instances) {
if (tempInstance.startTime > startTime) {
startTime = tempInstance.startTime;
instanceName = tempInstance.name;
}
}
let streamingUrl = `https://${logStream["baseUrl"]}/api/logstream/apps/${appName}/instances/${instanceName}?follow=true`;
const credentials = Buffer.from(`primary:${logStream["primaryKey"]}`).toString('base64');
const headers = {
"Authorization" : `Basic ${credentials}`
};
await this.sendRequestV2('GET', streamingUrl, null, headers).then(response => {
console.info(response.body);
});
}

public async logStreamConstructor() {
tl.debug("Constructing log stream");
let ret = {};
let requestUri = this._client.getRequestUri(`${this._resourceId}/listTestKeys`, {}, null, API_VERSION);
try {
var response: webClient.WebResponse = await this.sendRequest('POST', requestUri);
if (!response.body.enabled) {
tl.warning(tl.loc('PrivateTestEndpointNotEnabled but log stream needs it'));
return null;
} else {
tl.debug('log stream constructed.');
ret["primaryKey"] = response.body.primaryKey;
}
} catch (error) {
tl.error(tl.loc('UnableToRetrieveTestEndpointKeys'));
throw (error);
}
const serviceResponse = await this.getServiceInfo();
ret["baseUrl"] = serviceResponse["properties"]["fqdn"];
return ret;
}
}
Loading