@@ -9,7 +9,6 @@ import * as vscode from 'vscode'
9
9
import * as path from 'path'
10
10
import * as localizedText from '../localizedText'
11
11
import { DefaultS3Client } from '../clients/s3Client'
12
- import { Wizard } from '../wizards/wizard'
13
12
import { DataQuickPickItem , createMultiPick , createQuickPick } from '../ui/pickerPrompter'
14
13
import { DefaultCloudFormationClient } from '../clients/cloudFormationClient'
15
14
import * as CloudFormation from '../cloudformation/cloudformation'
@@ -28,14 +27,14 @@ import { createExitPrompter } from '../ui/common/exitPrompter'
28
27
import { getConfigFileUri , SamConfig , validateSamSyncConfig , writeSamconfigGlobal } from './config'
29
28
import { cast , Optional } from '../utilities/typeConstructors'
30
29
import { pushIf , toRecord } from '../utilities/collectionUtils'
31
- import { getOverriddenParameters } from '../../lambda/config/parameterUtils'
30
+ import { getParameters } from '../../lambda/config/parameterUtils'
32
31
import { addTelemetryEnvVar } from './cli/samCliInvokerUtils'
33
32
import { samSyncParamUrl , samSyncUrl , samUpgradeUrl } from '../constants'
34
33
import { openUrl } from '../utilities/vsCodeUtils'
35
34
import { showOnce } from '../utilities/messages'
36
35
import { IamConnection } from '../../auth/connection'
37
36
import { CloudFormationTemplateRegistry } from '../fs/templateRegistry'
38
- import { TreeNode } from '../treeview/resourceTreeDataProvider'
37
+ import { isTreeNode , TreeNode } from '../treeview/resourceTreeDataProvider'
39
38
import { getSpawnEnv } from '../env/resolveEnv'
40
39
import {
41
40
getProjectRoot ,
@@ -52,13 +51,19 @@ import { ParamsSource, createSyncParamsSourcePrompter } from '../ui/sam/paramsSo
52
51
import { createEcrPrompter } from '../ui/sam/ecrPrompter'
53
52
import { BucketSource , createBucketNamePrompter , createBucketSourcePrompter } from '../ui/sam/bucketPrompter'
54
53
import { runInTerminal } from './processTerminal'
54
+ import {
55
+ TemplateParametersForm ,
56
+ TemplateParametersWizard ,
57
+ } from '../../awsService/appBuilder/wizards/templateParametersWizard'
58
+ import { CompositeWizard } from '../wizards/compositeWizard'
55
59
56
60
export interface SyncParams {
57
61
readonly paramsSource : ParamsSource
58
62
readonly region : string
59
63
readonly deployType : 'infra' | 'code'
60
64
readonly projectRoot : vscode . Uri
61
65
readonly template : TemplateItem
66
+ readonly templateParameters : any
62
67
readonly stackName : string
63
68
readonly bucketSource : BucketSource
64
69
readonly bucketName : string
@@ -147,7 +152,30 @@ export const syncFlagItems: DataQuickPickItem<string>[] = [
147
152
} ,
148
153
]
149
154
150
- export class SyncWizard extends Wizard < SyncParams > {
155
+ export enum SamSyncEntryPoints {
156
+ SamTemplateFile ,
157
+ SamConfigFile ,
158
+ RegionNodeContextMenu ,
159
+ AppBuilderNodeButton ,
160
+ CommandPalette ,
161
+ }
162
+
163
+ function getSyncEntryPoint ( arg : vscode . Uri | AWSTreeNodeBase | TreeNode | undefined ) {
164
+ if ( arg instanceof vscode . Uri ) {
165
+ if ( arg . path . endsWith ( 'samconfig.toml' ) ) {
166
+ return SamSyncEntryPoints . SamConfigFile
167
+ }
168
+ return SamSyncEntryPoints . SamTemplateFile
169
+ } else if ( arg instanceof AWSTreeNodeBase ) {
170
+ return SamSyncEntryPoints . RegionNodeContextMenu
171
+ } else if ( isTreeNode ( arg ) ) {
172
+ return SamSyncEntryPoints . AppBuilderNodeButton
173
+ } else {
174
+ return SamSyncEntryPoints . CommandPalette
175
+ }
176
+ }
177
+
178
+ export class SyncWizard extends CompositeWizard < SyncParams > {
151
179
registry : CloudFormationTemplateRegistry
152
180
public constructor (
153
181
state : Pick < SyncParams , 'deployType' > & Partial < SyncParams > ,
@@ -156,17 +184,38 @@ export class SyncWizard extends Wizard<SyncParams> {
156
184
) {
157
185
super ( { initState : state , exitPrompterProvider : shouldPromptExit ? createExitPrompter : undefined } )
158
186
this . registry = registry
187
+ }
188
+
189
+ public override async init ( ) : Promise < this> {
159
190
this . form . template . bindPrompter ( ( ) => createTemplatePrompter ( this . registry , syncMementoRootKey , samSyncUrl ) )
191
+ this . form . templateParameters . bindPrompter (
192
+ async ( { template } ) =>
193
+ this . createWizardPrompter < TemplateParametersWizard , TemplateParametersForm > (
194
+ TemplateParametersWizard ,
195
+ template ! . uri ,
196
+ samSyncUrl ,
197
+ syncMementoRootKey
198
+ ) ,
199
+ {
200
+ showWhen : async ( { template } ) => {
201
+ const samTemplateParameters = await getParameters ( template ! . uri )
202
+ return ! ! samTemplateParameters && samTemplateParameters . size > 0
203
+ } ,
204
+ }
205
+ )
206
+
160
207
this . form . projectRoot . setDefault ( ( { template } ) => getProjectRoot ( template ) )
161
208
162
209
this . form . paramsSource . bindPrompter ( async ( { projectRoot } ) => {
163
210
const existValidSamConfig : boolean | undefined = await validateSamSyncConfig ( projectRoot )
164
211
return createSyncParamsSourcePrompter ( existValidSamConfig )
165
212
} )
213
+
166
214
this . form . region . bindPrompter ( ( ) => createRegionPrompter ( ) . transform ( ( r ) => r . id ) , {
167
215
showWhen : ( { paramsSource } ) =>
168
216
paramsSource === ParamsSource . Specify || paramsSource === ParamsSource . SpecifyAndSave ,
169
217
} )
218
+
170
219
this . form . stackName . bindPrompter (
171
220
( { region } ) =>
172
221
createStackPrompter ( new DefaultCloudFormationClient ( region ! ) , syncMementoRootKey , samSyncUrl ) ,
@@ -210,6 +259,7 @@ export class SyncWizard extends Wizard<SyncParams> {
210
259
paramsSource === ParamsSource . Specify || paramsSource === ParamsSource . SpecifyAndSave ,
211
260
}
212
261
)
262
+ return this
213
263
}
214
264
}
215
265
@@ -296,30 +346,22 @@ export async function saveAndBindArgs(args: SyncParams): Promise<{ readonly boun
296
346
return { boundArgs }
297
347
}
298
348
299
- async function loadLegacyParameterOverrides ( template : TemplateItem ) {
300
- try {
301
- const params = await getOverriddenParameters ( template . uri )
302
- if ( ! params ) {
303
- return
304
- }
305
-
306
- return [ ...params . entries ( ) ] . map ( ( [ k , v ] ) => `${ k } =${ v } ` )
307
- } catch ( err ) {
308
- getLogger ( ) . warn ( `sam: unable to load legacy parameter overrides: %s` , err )
309
- }
310
- }
311
-
312
349
export async function runSamSync ( args : SyncParams ) {
313
350
telemetry . record ( { lambdaPackageType : args . ecrRepoUri !== undefined ? 'Image' : 'Zip' } )
314
351
315
352
const { path : samCliPath , parsedVersion } = await getSamCliPathAndVersion ( )
316
353
const { boundArgs } = await saveAndBindArgs ( args )
317
- const overrides = await loadLegacyParameterOverrides ( args . template )
318
- if ( overrides !== undefined ) {
319
- // Leaving this out of the definitions file as this is _very_ niche and specific to the
320
- // implementation. Plus we would have to redefine `sam_sync` to add it.
321
- telemetry . record ( { isUsingTemplatesJson : true } as any )
322
- boundArgs . push ( '--parameter-overrides' , ...overrides )
354
+
355
+ if ( ! ! args . templateParameters && Object . entries ( args . templateParameters ) . length > 0 ) {
356
+ const templateParameters = new Map < string , string > ( Object . entries ( args . templateParameters ) )
357
+ const paramsToSet : string [ ] = [ ]
358
+ for ( const [ key , value ] of templateParameters . entries ( ) ) {
359
+ if ( value ) {
360
+ await updateRecentResponse ( syncMementoRootKey , args . template . uri . fsPath , key , value )
361
+ paramsToSet . push ( `ParameterKey=${ key } ,ParameterValue=${ value } ` )
362
+ }
363
+ }
364
+ paramsToSet . length > 0 && boundArgs . push ( '--parameter-overrides' , paramsToSet . join ( ' ' ) )
323
365
}
324
366
325
367
// '--no-watch' was not added until https://github.com/aws/aws-sam-cli/releases/tag/v1.77.0
@@ -431,21 +473,30 @@ export async function prepareSyncParams(
431
473
) : Promise < Partial < SyncParams > > {
432
474
// Skip creating dependency layers by default for backwards compat
433
475
const baseParams : Partial < SyncParams > = { skipDependencyLayer : true }
476
+ const entryPoint = getSyncEntryPoint ( arg )
434
477
435
- if ( arg instanceof AWSTreeNodeBase ) {
436
- // "Deploy" command was invoked on a regionNode.
437
- return { ...baseParams , region : arg . regionCode }
438
- } else if ( arg instanceof vscode . Uri ) {
439
- if ( arg . path . endsWith ( 'samconfig.toml' ) ) {
440
- // "Deploy" command was invoked on a samconfig.toml file.
441
- // TODO: add step to verify samconfig content to skip param source prompter
442
- const config = await SamConfig . fromConfigFileUri ( arg )
478
+ switch ( entryPoint ) {
479
+ case SamSyncEntryPoints . SamTemplateFile : {
480
+ const entryPointArg = arg as vscode . Uri
481
+ const template = {
482
+ uri : entryPointArg ,
483
+ data : await CloudFormation . load ( entryPointArg . fsPath , validate ) ,
484
+ }
485
+
486
+ return {
487
+ ...baseParams ,
488
+ template : template ,
489
+ projectRoot : getProjectRootUri ( template . uri ) ,
490
+ }
491
+ }
492
+ case SamSyncEntryPoints . SamConfigFile : {
493
+ const config = await SamConfig . fromConfigFileUri ( arg as vscode . Uri )
443
494
const params = getSyncParamsFromConfig ( config )
444
495
const projectRoot = vscode . Uri . joinPath ( config . location , '..' )
445
496
const templateUri = params . templatePath
446
497
? vscode . Uri . file ( path . resolve ( projectRoot . fsPath , params . templatePath ) )
447
498
: undefined
448
- const template = templateUri
499
+ const samConfigFileTemplate = templateUri
449
500
? {
450
501
uri : templateUri ,
451
502
data : await CloudFormation . load ( templateUri . fsPath ) ,
@@ -454,29 +505,38 @@ export async function prepareSyncParams(
454
505
// Always use the dependency layer if the user specified to do so
455
506
const skipDependencyLayer = ! config . getCommandParam ( 'sync' , 'dependency_layer' )
456
507
457
- return { ...baseParams , ...params , template, projectRoot, skipDependencyLayer } as SyncParams
508
+ return {
509
+ ...baseParams ,
510
+ ...params ,
511
+ template : samConfigFileTemplate ,
512
+ projectRoot,
513
+ skipDependencyLayer,
514
+ } as SyncParams
458
515
}
459
-
460
- // "Deploy" command was invoked on a template.yaml file.
461
- const template = {
462
- uri : arg ,
463
- data : await CloudFormation . load ( arg . fsPath , validate ) ,
516
+ case SamSyncEntryPoints . RegionNodeContextMenu : {
517
+ const entryPointArg = arg as AWSTreeNodeBase
518
+ return { ...baseParams , region : entryPointArg . regionCode }
464
519
}
465
-
466
- return { ...baseParams , template, projectRoot : getProjectRootUri ( template . uri ) }
467
- } else if ( arg && arg . getTreeItem ( ) ) {
468
- // "Deploy" command was invoked on a TreeNode on the AppBuilder.
469
- const templateUri = ( arg . getTreeItem ( ) as vscode . TreeItem ) . resourceUri
470
- if ( templateUri ) {
471
- const template = {
472
- uri : templateUri ,
473
- data : await CloudFormation . load ( templateUri . fsPath , validate ) ,
520
+ case SamSyncEntryPoints . AppBuilderNodeButton : {
521
+ const entryPointArg = arg as TreeNode
522
+ const templateUri = ( entryPointArg . getTreeItem ( ) as vscode . TreeItem ) . resourceUri
523
+ if ( templateUri ) {
524
+ const template = {
525
+ uri : templateUri ,
526
+ data : await CloudFormation . load ( templateUri . fsPath , validate ) ,
527
+ }
528
+ return {
529
+ ...baseParams ,
530
+ template,
531
+ projectRoot : getProjectRootUri ( templateUri ) ,
532
+ }
474
533
}
475
- return { ... baseParams , template , projectRoot : getProjectRootUri ( template . uri ) }
534
+ return baseParams
476
535
}
536
+ case SamSyncEntryPoints . CommandPalette :
537
+ default :
538
+ return baseParams
477
539
}
478
-
479
- return baseParams
480
540
}
481
541
482
542
export type SamSyncResult = {
0 commit comments