in src/shared/sam/localLambdaRunner.ts [187:326]
async function invokeLambdaHandler(
timer: Timeout,
env: NodeJS.ProcessEnv,
config: SamLaunchRequestArgs
): Promise<boolean> {
getLogger('channel').info(localize('AWS.output.starting.sam.app.locally', 'Starting SAM application locally'))
getLogger().debug(`localLambdaRunner.invokeLambdaFunction: ${config.name}`)
const debugPort = !config.noDebug ? config.debugPort?.toString() : undefined
if (config.invokeTarget.target === 'api') {
// sam local start-api ...
const samCliContext = new DefaultSamCliProcessInvokerContext()
const sam = await samCliContext.cliConfig.getOrDetectSamCli()
if (!sam.path) {
getLogger().warn('SAM CLI not found and not configured')
} else if (sam.autoDetected) {
getLogger().info('SAM CLI not configured, using SAM found at: %O', sam.path)
}
const samCommand = sam.path ? sam.path : 'sam'
const samArgs = await buildSamCliStartApiArguments({
templatePath: config.templatePath,
dockerNetwork: config.sam?.dockerNetwork,
environmentVariablePath: config.envFile,
environmentVariables: env,
port: config.apiPort?.toString(),
debugPort: debugPort,
debuggerPath: config.debuggerPath,
debugArgs: config.debugArgs,
skipPullImage: config.sam?.skipNewImageCheck,
parameterOverrides: config.parameterOverrides,
containerEnvFile: config.containerEnvFile,
extraArgs: config.sam?.localArguments,
name: config.name,
})
const recordApigwTelemetry = (result: telemetry.Result) => {
telemetry.recordApigatewayInvokeLocal({
result: result,
runtime: config.runtime as telemetry.Runtime,
debug: !config.noDebug,
httpMethod: config.api?.httpMethod,
architecture: config.architecture,
})
}
// We want async behavior so `await` is intentionally not used here, we
// need to call requestLocalApi() while it is up.
samStartApi = new Promise(resolve => {
config
.samLocalInvokeCommand!.invoke({
options: {
env: {
...process.env,
...env,
},
},
command: samCommand,
args: samArgs,
// "sam local start-api" produces "attach" messages similar to "sam local invoke".
waitForCues: true,
timeout: timer,
name: config.name,
})
.then(sam => {
recordApigwTelemetry('Succeeded')
samStartApiProc = sam
resolve(true)
})
.catch(e => {
recordApigwTelemetry('Failed')
getLogger().warn(e as Error)
getLogger('channel').error(
localize(
'AWS.error.during.apig.local',
'Failed to start local API Gateway: {0}',
(e as Error).message
)
)
resolve(false)
})
})
return true
} else {
// 'target=code' or 'target=template'
const localInvokeArgs: SamCliLocalInvokeInvocationArguments = {
templateResourceName: makeResourceName(config),
templatePath: config.templatePath,
eventPath: config.eventPayloadFile,
environmentVariablePath: config.envFile,
environmentVariables: env,
invoker: config.samLocalInvokeCommand!,
dockerNetwork: config.sam?.dockerNetwork,
debugPort: debugPort,
debuggerPath: config.debuggerPath,
debugArgs: config.debugArgs,
containerEnvFile: config.containerEnvFile,
extraArgs: config.sam?.localArguments,
skipPullImage: config.sam?.skipNewImageCheck ?? (isImageLambdaConfig(config) || config.sam?.containerBuild),
parameterOverrides: config.parameterOverrides,
name: config.name,
}
// sam local invoke ...
const command = new SamCliLocalInvokeInvocation(localInvokeArgs)
let samVersion: string | undefined
let invokeResult: telemetry.Result = 'Failed'
try {
samVersion = await getSamCliVersion(getSamCliContext())
await command.execute(timer)
invokeResult = 'Succeeded'
} catch (err) {
getLogger('channel').error(
localize(
'AWS.error.during.sam.local',
'Failed to run SAM application locally: {0}',
(err as Error).message
)
)
return false
} finally {
if (config.sam?.buildDir === undefined) {
await remove(config.templatePath)
}
telemetry.recordLambdaInvokeLocal({
lambdaPackageType: isImageLambdaConfig(config) ? 'Image' : 'Zip',
result: invokeResult,
runtime: config.runtime as telemetry.Runtime,
debug: !config.noDebug,
version: samVersion,
architecture: config.architecture,
})
}
return true
}
}