@@ -78,6 +78,26 @@ export class AzureSpringApps {
7878 return this . _client . beginRequest ( httpRequest ) ;
7979 }
8080
81+ /**
82+ * send request using webClient.sendRequest
83+ * @param method
84+ * @param url
85+ * @param body
86+ * @param headers
87+ * @returns webClient.WebResponse
88+ */
89+ protected sendRequestV2 ( method : string , url : string , body ?: any , headers ?: any ) : Promise < webClient . WebResponse > {
90+ var httpRequest = new webClient . WebRequest ( ) ;
91+ httpRequest . method = method ;
92+ httpRequest . uri = url ;
93+ if ( body )
94+ httpRequest . body = body ;
95+ if ( headers )
96+ httpRequest . headers = headers ;
97+ tl . debug ( `Sending ${ method } request to ${ url } ` ) ;
98+ return webClient . sendRequest ( httpRequest ) ;
99+ }
100+
81101 /**
82102 * Deploys an artifact to an Azure Spring Cloud deployment
83103 * @param artifactToUpload
@@ -322,6 +342,30 @@ export class AzureSpringApps {
322342 }
323343 }
324344
345+ protected async getDeploymentInfo ( appName : String , deploymentName : String ) : Promise < Object > {
346+ tl . debug ( `Query deployment ${ deploymentName } for app ${ appName } ` )
347+ const requestUri = this . _client . getRequestUri ( `${ this . _resourceId } /apps/{appName}/deployments/{deploymentName}` , {
348+ '{appName}' : appName ,
349+ '{deploymentName}' : deploymentName
350+ } , null , API_VERSION ) ;
351+
352+ try {
353+ const response = await this . sendRequest ( 'GET' , requestUri ) ;
354+ if ( response . statusCode == 404 ) {
355+ tl . debug ( `404 when querying deployment ${ deploymentName } for app ${ appName } ` ) ;
356+ throw Error ( tl . loc ( 'NoDeploymentsExist' ) ) ;
357+ } if ( response . statusCode != 200 ) {
358+ tl . error ( `${ tl . loc ( 'UnableToGetDeploymentInformation' ) } ${ tl . loc ( 'StatusCode' ) } : ${ response . statusCode } ` ) ;
359+ throw ToError ( response ) ;
360+ } else {
361+ tl . debug ( 'Found deployment ${deploymentName} for app ${appName}.' ) ;
362+ return response . body ;
363+ }
364+ } catch ( error ) {
365+ throw ( error ) ;
366+ }
367+ }
368+
325369 /**
326370 * Returns the currently inactive deployment, or `undefined` if none exists.
327371 * @param appName
@@ -477,6 +521,7 @@ export class AzureSpringApps {
477521 var response = await this . sendRequest ( method , requestUri , JSON . stringify ( deploymentUpdateRequestBody ) ) ;
478522 } catch ( error ) {
479523 tl . debug ( 'Error when sending app update request' ) ;
524+ await this . printLatestAppInstanceLog ( appName , deploymentName ) ;
480525 throw ( error ) ;
481526 }
482527 console . log ( JSON . stringify ( response . body , null , 2 ) ) ;
@@ -496,6 +541,7 @@ export class AzureSpringApps {
496541 await this . awaitOperationCompletion ( operationStatusUrl ) ;
497542 } catch ( error ) {
498543 tl . debug ( 'Error in awaiting operation completion' ) ;
544+ await this . printLatestAppInstanceLog ( appName , deploymentName ) ;
499545 throw error ;
500546 } finally {
501547 //A build log is available on the deployment when uploading a folder. Let's display it.
@@ -650,4 +696,51 @@ export class AzureSpringApps {
650696 throw ( error ) ;
651697 }
652698 }
699+
700+ private async printLatestAppInstanceLog ( appName : string , deploymentName : string ) {
701+ console . info ( 'Some error occured during deployment. Printing latest app instance log:' ) ;
702+ const logStream = await this . logStreamConstructor ( ) ;
703+ const deploymentResource = await this . getDeploymentInfo ( appName , deploymentName ) ;
704+ const instances = deploymentResource [ "properties" ] [ "instances" ] ;
705+ let startTime = instances [ 0 ] . startTime ;
706+ let instanceName = instances [ 0 ] . name ;
707+
708+ // print the newly created instance log
709+ for ( const tempInstance of instances ) {
710+ if ( tempInstance . startTime > startTime ) {
711+ startTime = tempInstance . startTime ;
712+ instanceName = tempInstance . name ;
713+ }
714+ }
715+ let streamingUrl = `https://${ logStream [ "baseUrl" ] } /api/logstream/apps/${ appName } /instances/${ instanceName } ?follow=true` ;
716+ const credentials = Buffer . from ( `primary:${ logStream [ "primaryKey" ] } ` ) . toString ( 'base64' ) ;
717+ const headers = {
718+ "Authorization" : `Basic ${ credentials } `
719+ } ;
720+ await this . sendRequestV2 ( 'GET' , streamingUrl , null , headers ) . then ( response => {
721+ console . info ( response . body ) ;
722+ } ) ;
723+ }
724+
725+ public async logStreamConstructor ( ) {
726+ tl . debug ( "Constructing log stream" ) ;
727+ let ret = { } ;
728+ let requestUri = this . _client . getRequestUri ( `${ this . _resourceId } /listTestKeys` , { } , null , API_VERSION ) ;
729+ try {
730+ var response : webClient . WebResponse = await this . sendRequest ( 'POST' , requestUri ) ;
731+ if ( ! response . body . enabled ) {
732+ tl . warning ( tl . loc ( 'PrivateTestEndpointNotEnabled but log stream needs it' ) ) ;
733+ return null ;
734+ } else {
735+ tl . debug ( 'log stream constructed.' ) ;
736+ ret [ "primaryKey" ] = response . body . primaryKey ;
737+ }
738+ } catch ( error ) {
739+ tl . error ( tl . loc ( 'UnableToRetrieveTestEndpointKeys' ) ) ;
740+ throw ( error ) ;
741+ }
742+ const serviceResponse = await this . getServiceInfo ( ) ;
743+ ret [ "baseUrl" ] = serviceResponse [ "properties" ] [ "fqdn" ] ;
744+ return ret ;
745+ }
653746}
0 commit comments