import resolveCfImportValue from '../utils/resolve-cf-import-value.js' import ServerlessError from '../../../serverless-error.js' export default { async getStackInfo() { // NOTE: this is the global gatheredData object which will be passed around this.gatheredData = { inputs: { compose: this.serverless.compose.serviceParams, }, info: { functions: [], layers: [], endpoints: [], service: this.serverless.service.service, stage: this.provider.getStage(), region: this.provider.getRegion(), stack: this.provider.naming.getStackName(), }, outputs: [], } const stackName = this.provider.naming.getStackName() const stackData = {} const sdkRequests = [ this.provider .request('CloudFormation', 'describeStacks', { StackName: stackName }) .then((result) => { if (result) stackData.outputs = result.Stacks[0].Outputs }), ] const httpApiId = this.serverless.service.provider.httpApi && this.serverless.service.provider.httpApi.id if (httpApiId) { sdkRequests.push( (httpApiId['Fn::ImportValue'] ? resolveCfImportValue(this.provider, httpApiId['Fn::ImportValue']) : Promise.resolve(httpApiId) ) .then((id) => { return this.provider.request('ApiGatewayV2', 'getApi', { ApiId: id, }) }) .then( (result) => { stackData.externalHttpApiEndpoint = result.ApiEndpoint }, (error) => { throw new ServerlessError( `Could not resolve provider.httpApi.id parameter. ${error.message}`, 'UNABLE_TO_RESOLVE_HTTP_API_ID', ) }, ), ) } // Get info from CloudFormation Outputs return Promise.all(sdkRequests).then(async () => { let outputs if (stackData.outputs) { ;({ outputs } = stackData) const serviceEndpointOutputRegex = this.provider.naming.getServiceEndpointRegex() // Outputs this.gatheredData.outputs = outputs // Functions this.serverless.service.getAllFunctions().forEach((func) => { const functionObj = this.serverless.service.getFunction(func) const functionInfo = {} functionInfo.name = func functionInfo.deployedName = functionObj.name functionInfo.artifactSize = functionObj.artifactSize const functionUrlOutput = outputs.find( (output) => output.OutputKey === this.provider.naming.getLambdaFunctionUrlOutputLogicalId(func), ) if (functionUrlOutput) { functionInfo.url = functionUrlOutput.OutputValue } this.gatheredData.info.functions.push(functionInfo) }) // Layers this.serverless.service.getAllLayers().forEach((layer) => { const layerInfo = {} layerInfo.name = layer const layerOutputId = this.provider.naming.getLambdaLayerOutputLogicalId(layer) for (const output of outputs) { if (output.OutputKey === layerOutputId) { layerInfo.arn = output.OutputValue break } } this.gatheredData.info.layers.push(layerInfo) }) // CloudFront const cloudFrontDomainName = outputs.find( (output) => output.OutputKey === this.provider.naming.getCloudFrontDistributionDomainNameLogicalId(), ) if (cloudFrontDomainName) { this.gatheredData.info.cloudFront = cloudFrontDomainName.OutputValue } // Endpoints outputs .filter((x) => x.OutputKey.match(serviceEndpointOutputRegex)) .forEach((x) => { if (x.OutputKey === 'HttpApiUrl') { this.gatheredData.info.endpoints.push(`httpApi: ${x.OutputValue}`) } else { this.gatheredData.info.endpoints.push(x.OutputValue) } if ( this.serverless.service.deployment && this.serverless.service.deployment.deploymentId ) { this.serverless.service.deployment.apiId = x.OutputValue.split('//')[1].split('.')[0] } }) } if (stackData.externalHttpApiEndpoint) { this.gatheredData.info.endpoints.push( `httpApi: ${stackData.externalHttpApiEndpoint}`, ) } return Promise.resolve() }) }, }