Skip to content

Commit 43c651d

Browse files
authored
Merge #1124 'SAM debugconfig: sam.buildArguments, sam.localArguments'
2 parents d943ba8 + d0963c9 commit 43c651d

File tree

8 files changed

+106
-163
lines changed

8 files changed

+106
-163
lines changed

designs/sam-debugging/local-sam-debugging.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ The required fields are: type, request, invokeTarget
203203
"containerBuild": false,
204204
"skipNewImageCheck": false,
205205
"dockerNetwork": "aaaaa",
206-
"buildArguments": "--foo",
207-
"localArguments": "--foo",
206+
"buildArguments": ["--foo"],
207+
"localArguments": ["--foo"],
208208
// used when invokeTarget references a SAM Template
209209
"template": {
210210
// SAM Template Parameter substitutions
@@ -269,8 +269,8 @@ The required fields are: type, request, invokeTarget, lambda.runtime
269269
"containerBuild": false,
270270
"skipNewImageCheck": false,
271271
"dockerNetwork": "aaaaa",
272-
"buildArguments": "--foo",
273-
"localArguments": "--foo"
272+
"buildArguments": ["--foo"],
273+
"localArguments": ["--foo"]
274274
},
275275
// AWS related arguments
276276
"aws": {

package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,10 @@
281281
"properties": {
282282
"buildArguments": {
283283
"description": "%AWS.configuration.description.awssam.debug.buildArguments%",
284-
"type": "string"
284+
"type": "array",
285+
"items": {
286+
"type": "string"
287+
}
285288
},
286289
"containerBuild": {
287290
"description": "%AWS.configuration.description.awssam.debug.containerBuild%",
@@ -293,7 +296,10 @@
293296
},
294297
"localArguments": {
295298
"description": "%AWS.configuration.description.awssam.debug.localArguments%",
296-
"type": "string"
299+
"type": "array",
300+
"items": {
301+
"type": "string"
302+
}
297303
},
298304
"skipNewImageCheck": {
299305
"description": "%AWS.configuration.description.awssam.debug.skipNewImageCheck%",

src/shared/sam/cli/samCliBuild.ts

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
import { fileExists } from '../../filesystemUtilities'
77
import { getLogger, Logger } from '../../logger'
8-
import { DefaultSamCliProcessInvoker } from './samCliInvoker'
98
import { logAndThrowIfUnexpectedExitCode, SamCliProcessInvoker } from './samCliInvokerUtils'
9+
import { DefaultSamCliProcessInvoker } from './samCliInvoker'
1010

1111
export interface SamCliBuildInvocationArguments {
1212
/**
@@ -23,16 +23,17 @@ export interface SamCliBuildInvocationArguments {
2323
*/
2424
templatePath: string
2525
/**
26-
* Environment variables to set on the child process.
26+
* Environment variables set when invoking the SAM process (NOT passed to the Lambda).
2727
*/
2828
environmentVariables?: NodeJS.ProcessEnv
2929
/**
3030
* Manages the sam cli execution.
3131
*/
3232
invoker: SamCliProcessInvoker
3333
/**
34-
* If your functions depend on packages that have natively compiled dependencies,
35-
* use this flag to build your function inside an AWS Lambda-like Docker container.
34+
* - true: If your Lambda depends on packages that need to be compiled natively,
35+
* use this flag to build your function inside an AWS Lambda-like Docker container.
36+
* - false: Lambda will be built on local machine instead of in a Docker image.
3637
*/
3738
useContainer?: boolean
3839
/**
@@ -42,13 +43,16 @@ export interface SamCliBuildInvocationArguments {
4243
*/
4344
dockerNetwork?: string
4445
/**
45-
* Specifies whether the command should skip pulling down the latest Docker image for Lambda runtime.
46+
* - true: Do not pull the latest Docker image for Lambda runtime.
47+
* - false: Pull the latest Docker image if necessary
4648
*/
4749
skipPullImage?: boolean
4850
/**
4951
* The path to a custom dependency manifest (ex: package.json) to use instead of the default one.
5052
*/
5153
manifestPath?: string
54+
/** SAM args specified by user (`sam.buildArguments`). */
55+
extraArgs?: string[]
5256
}
5357

5458
export interface FileFunctions {
@@ -59,64 +63,44 @@ export interface FileFunctions {
5963
* An elaborate way to run `sam build`.
6064
*/
6165
export class SamCliBuildInvocation {
62-
private readonly buildDir: string
63-
private readonly baseDir?: string
64-
private readonly environmentVariables?: NodeJS.ProcessEnv
65-
private readonly templatePath: string
66-
private readonly invoker: SamCliProcessInvoker
67-
private readonly useContainer: boolean
68-
private readonly dockerNetwork?: string
69-
private readonly skipPullImage: boolean
70-
private readonly manifestPath?: string
71-
72-
/**
73-
* @see SamCliBuildInvocationArguments for parameter info
74-
* invoker - Defaults to DefaultSamCliProcessInvoker
75-
* useContainer - Defaults to false (function will be built on local machine instead of in a docker image)
76-
* skipPullImage - Defaults to false (the latest Docker image will be pulled down if necessary)
77-
*/
7866
public constructor(
79-
{
80-
invoker = new DefaultSamCliProcessInvoker(),
81-
useContainer = false,
82-
skipPullImage = false,
83-
...params
84-
}: SamCliBuildInvocationArguments,
67+
private readonly args: SamCliBuildInvocationArguments,
8568
private readonly context: { file: FileFunctions } = { file: getDefaultFileFunctions() }
8669
) {
87-
this.buildDir = params.buildDir
88-
this.baseDir = params.baseDir
89-
this.templatePath = params.templatePath
90-
this.environmentVariables = params.environmentVariables
91-
this.invoker = invoker
92-
this.useContainer = useContainer
93-
this.dockerNetwork = params.dockerNetwork
94-
this.skipPullImage = skipPullImage
95-
this.manifestPath = params.manifestPath
70+
this.args.invoker = this.args.invoker ?? new DefaultSamCliProcessInvoker()
71+
this.args.useContainer = !!this.args.useContainer
72+
this.args.skipPullImage = !!this.args.skipPullImage
9673
}
9774

98-
public async execute(): Promise<void> {
75+
/**
76+
*
77+
* @returns process exit/status code
78+
*/
79+
public async execute(): Promise<number> {
9980
await this.validate()
10081

101-
const invokeArgs: string[] = ['build', '--build-dir', this.buildDir, '--template', this.templatePath]
82+
const invokeArgs: string[] = ['build', '--build-dir', this.args.buildDir, '--template', this.args.templatePath]
10283

103-
this.addArgumentIf(invokeArgs, !!this.baseDir, '--base-dir', this.baseDir!)
104-
this.addArgumentIf(invokeArgs, !!this.dockerNetwork, '--docker-network', this.dockerNetwork!)
105-
this.addArgumentIf(invokeArgs, !!this.useContainer, '--use-container')
106-
this.addArgumentIf(invokeArgs, !!this.skipPullImage, '--skip-pull-image')
107-
this.addArgumentIf(invokeArgs, !!this.manifestPath, '--manifest', this.manifestPath!)
84+
this.addArgumentIf(invokeArgs, !!this.args.baseDir, '--base-dir', this.args.baseDir!)
85+
this.addArgumentIf(invokeArgs, !!this.args.dockerNetwork, '--docker-network', this.args.dockerNetwork!)
86+
this.addArgumentIf(invokeArgs, !!this.args.useContainer, '--use-container')
87+
this.addArgumentIf(invokeArgs, !!this.args.skipPullImage, '--skip-pull-image')
88+
this.addArgumentIf(invokeArgs, !!this.args.manifestPath, '--manifest', this.args.manifestPath!)
89+
invokeArgs.push(...(this.args.extraArgs ?? []))
10890

10991
const env: NodeJS.ProcessEnv = {
11092
...process.env,
111-
...this.environmentVariables,
93+
...this.args.environmentVariables,
11294
}
11395

114-
const childProcessResult = await this.invoker.invoke({
96+
const childProcessResult = await this.args.invoker.invoke({
11597
spawnOptions: { env },
11698
arguments: invokeArgs,
11799
})
118100

119101
logAndThrowIfUnexpectedExitCode(childProcessResult, 0)
102+
103+
return childProcessResult.exitCode
120104
}
121105

122106
private addArgumentIf(args: string[], addIfConditional: boolean, ...argsToAdd: string[]) {
@@ -126,10 +110,10 @@ export class SamCliBuildInvocation {
126110
}
127111

128112
private async validate(): Promise<void> {
129-
if (!(await this.context.file.fileExists(this.templatePath))) {
113+
if (!(await this.context.file.fileExists(this.args.templatePath))) {
130114
const logger: Logger = getLogger()
131115

132-
const err = new Error(`template path does not exist: ${this.templatePath}`)
116+
const err = new Error(`template path does not exist: ${this.args.templatePath}`)
133117
logger.error(err)
134118
throw err
135119
}

src/shared/sam/cli/samCliLocalInvoke.ts

Lines changed: 24 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -170,84 +170,66 @@ export interface SamCliLocalInvokeInvocationArguments {
170170
*/
171171
dockerNetwork?: string
172172
/**
173-
* Specifies whether the command should skip pulling down the latest Docker image for Lambda runtime.
173+
* - true: Do not pull the latest Docker image for Lambda runtime.
174+
* - false: Pull the latest Docker image if necessary
174175
*/
175176
skipPullImage?: boolean
176177
/**
177178
* Host path to a debugger that will be mounted into the Lambda container.
178179
*/
179180
debuggerPath?: string
181+
/** SAM args specified by user (`sam.localArguments`). */
182+
extraArgs?: string[]
180183
}
181184

182185
/**
183186
* An elaborate way to run `sam local`.
184187
*/
185188
export class SamCliLocalInvokeInvocation {
186-
private readonly templateResourceName: string
187-
private readonly templatePath: string
188-
private readonly eventPath: string
189-
private readonly environmentVariablePath: string
190-
private readonly debugPort?: string
191-
private readonly invoker: SamLocalInvokeCommand
192-
private readonly dockerNetwork?: string
193-
private readonly skipPullImage: boolean
194-
private readonly debuggerPath?: string
195-
196-
/**
197-
* @see SamCliLocalInvokeInvocationArguments for parameter info
198-
* skipPullImage - Defaults to false (the latest Docker image will be pulled down if necessary)
199-
*/
200-
public constructor({ skipPullImage = false, ...params }: SamCliLocalInvokeInvocationArguments) {
201-
this.templateResourceName = params.templateResourceName
202-
this.templatePath = params.templatePath
203-
this.eventPath = params.eventPath
204-
this.environmentVariablePath = params.environmentVariablePath
205-
this.debugPort = params.debugPort
206-
this.invoker = params.invoker
207-
this.dockerNetwork = params.dockerNetwork
208-
this.skipPullImage = skipPullImage
209-
this.debuggerPath = params.debuggerPath
189+
public constructor(private readonly args: SamCliLocalInvokeInvocationArguments) {
190+
this.args.skipPullImage = !!this.args.skipPullImage
210191
}
211192

212193
public async execute(timeout?: Timeout): Promise<void> {
213194
await this.validate()
214195

215-
const args = [
196+
const invokeArgs = [
216197
'local',
217198
'invoke',
218-
this.templateResourceName,
199+
this.args.templateResourceName,
219200
'--template',
220-
this.templatePath,
201+
this.args.templatePath,
221202
'--event',
222-
this.eventPath,
203+
this.args.eventPath,
223204
'--env-vars',
224-
this.environmentVariablePath,
205+
this.args.environmentVariablePath,
225206
]
226207

227-
this.addArgumentIf(args, !!this.debugPort, '-d', this.debugPort!)
228-
this.addArgumentIf(args, !!this.dockerNetwork, '--docker-network', this.dockerNetwork!)
229-
this.addArgumentIf(args, !!this.skipPullImage, '--skip-pull-image')
230-
this.addArgumentIf(args, !!this.debuggerPath, '--debugger-path', this.debuggerPath!)
208+
this.addArgumentIf(invokeArgs, !!this.args.debugPort, '-d', this.args.debugPort!)
209+
this.addArgumentIf(invokeArgs, !!this.args.dockerNetwork, '--docker-network', this.args.dockerNetwork!)
210+
this.addArgumentIf(invokeArgs, !!this.args.skipPullImage, '--skip-pull-image')
211+
this.addArgumentIf(invokeArgs, !!this.args.debuggerPath, '--debugger-path', this.args.debuggerPath!)
212+
invokeArgs.push(...(this.args.extraArgs ?? []))
231213

232-
await this.invoker.invoke({
214+
await this.args.invoker.invoke({
233215
command: 'sam',
234-
args,
235-
isDebug: !!this.debugPort,
216+
args: invokeArgs,
217+
isDebug: !!this.args.debugPort,
236218
timeout,
237219
})
238220
}
239221

240222
protected async validate(): Promise<void> {
241-
if (!this.templateResourceName) {
223+
if (!this.args.templateResourceName) {
242224
throw new Error('template resource name is missing or empty')
243225
}
244226

245-
if (!(await fileExists(this.templatePath))) {
246-
throw new Error(`template path does not exist: ${this.templatePath}`)
227+
if (!(await fileExists(this.args.templatePath))) {
228+
throw new Error(`template path does not exist: ${this.args.templatePath}`)
247229
}
248230

249-
if (!(await fileExists(this.eventPath))) {
250-
throw new Error(`event path does not exist: ${this.eventPath}`)
231+
if (!(await fileExists(this.args.eventPath))) {
232+
throw new Error(`event path does not exist: ${this.args.eventPath}`)
251233
}
252234
}
253235

src/shared/sam/debugger/csharpSamDebug.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ export async function makeCsharpConfig(config: SamLaunchRequestArgs): Promise<Sa
5656

5757
/**
5858
* Launches and attaches debugger to a SAM dotnet (csharp) project.
59+
*
60+
* We spin up a C# Lambda Docker container, download and build the debugger for
61+
* Linux, then mount it with the SAM app on run. User's C# workspace dir will
62+
* have a `.vsdbg` dir after the first run.
5963
*/
6064
export async function invokeCsharpLambda(ctx: ExtContext, config: SamLaunchRequestArgs): Promise<void> {
6165
config.samLocalInvokeCommand = new DefaultSamLocalInvokeCommand(getChannelLogger(ctx.outputChannel), [

src/shared/sam/debugger/samDebugSession.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ export interface SamLaunchRequestArgs extends DebugProtocol.AttachRequestArgumen
5959
/**
6060
* SAM/CFN template absolute path used for SAM CLI invoke.
6161
* - For `target=code` this is the _generated_ template path.
62-
* - For `target=template` this is the template found in the workspace.
62+
* - For `target=template` this is the _generated_ template path (TODO: in
63+
* the future we may change this to be the template found in the workspace.
6364
*/
6465
samTemplatePath: string
6566

0 commit comments

Comments
 (0)