@@ -5,9 +5,9 @@ import { Mode } from './aws-auth/credentials';
5
5
import { ISDK } from './aws-auth/sdk' ;
6
6
import { CredentialsOptions , SdkForEnvironment , SdkProvider } from './aws-auth/sdk-provider' ;
7
7
import { deployStack , DeployStackResult , destroyStack , makeBodyParameterAndUpload , DeploymentMethod } from './deploy-stack' ;
8
+ import { EnvironmentResources , EnvironmentResourcesRegistry } from './environment-resources' ;
8
9
import { HotswapMode } from './hotswap/common' ;
9
10
import { loadCurrentTemplateWithNestedStacks , loadCurrentTemplate , flattenNestedStackNames , TemplateWithNestedStackCount } from './nested-stack-helpers' ;
10
- import { ToolkitInfo } from './toolkit-info' ;
11
11
import { CloudFormationStack , Template , ResourcesToImport , ResourceIdentifierSummaries } from './util/cloudformation' ;
12
12
import { StackActivityProgress } from './util/cloudformation/stack-activity-monitor' ;
13
13
import { replaceEnvPlaceholders } from './util/placeholders' ;
@@ -38,6 +38,11 @@ export interface PreparedSdkWithLookupRoleForEnvironment {
38
38
* the default credentials (not the assume role credentials)
39
39
*/
40
40
readonly didAssumeRole : boolean ;
41
+
42
+ /**
43
+ * An object for accessing the bootstrap resources in this environment
44
+ */
45
+ readonly envResources : EnvironmentResources ;
41
46
}
42
47
43
48
export interface DeployStackOptions {
@@ -256,6 +261,7 @@ export interface StackExistsOptions {
256
261
257
262
export interface DeploymentsProps {
258
263
sdkProvider : SdkProvider ;
264
+ readonly toolkitStackName ?: string ;
259
265
readonly quiet ?: boolean ;
260
266
}
261
267
@@ -280,6 +286,11 @@ export interface PreparedSdkForEnvironment {
280
286
* @default - no execution role is used
281
287
*/
282
288
readonly cloudFormationRoleArn ?: string ;
289
+
290
+ /**
291
+ * Access class for environmental resources to help the deployment
292
+ */
293
+ readonly envResources : EnvironmentResources ;
283
294
}
284
295
285
296
/**
@@ -289,12 +300,13 @@ export interface PreparedSdkForEnvironment {
289
300
*/
290
301
export class Deployments {
291
302
private readonly sdkProvider : SdkProvider ;
292
- private readonly toolkitInfoCache = new Map < string , ToolkitInfo > ( ) ;
293
303
private readonly sdkCache = new Map < string , SdkForEnvironment > ( ) ;
294
304
private readonly publisherCache = new Map < AssetManifest , cdk_assets . AssetPublishing > ( ) ;
305
+ private readonly environmentResources : EnvironmentResourcesRegistry ;
295
306
296
307
constructor ( private readonly props : DeploymentsProps ) {
297
308
this . sdkProvider = props . sdkProvider ;
309
+ this . environmentResources = new EnvironmentResourcesRegistry ( props . toolkitStackName ) ;
298
310
}
299
311
300
312
public async readCurrentTemplateWithNestedStacks (
@@ -317,21 +329,18 @@ export class Deployments {
317
329
318
330
public async resourceIdentifierSummaries (
319
331
stackArtifact : cxapi . CloudFormationStackArtifact ,
320
- toolkitStackName ?: string ,
321
332
) : Promise < ResourceIdentifierSummaries > {
322
333
debug ( `Retrieving template summary for stack ${ stackArtifact . displayName } .` ) ;
323
334
// Currently, needs to use `deploy-role` since it may need to read templates in the staging
324
335
// bucket which have been encrypted with a KMS key (and lookup-role may not read encrypted things)
325
- const { stackSdk, resolvedEnvironment } = await this . prepareSdkFor ( stackArtifact , undefined , Mode . ForReading ) ;
336
+ const { stackSdk, resolvedEnvironment, envResources } = await this . prepareSdkFor ( stackArtifact , undefined , Mode . ForReading ) ;
326
337
const cfn = stackSdk . cloudFormation ( ) ;
327
338
328
- const toolkitInfo = await this . lookupToolkit ( resolvedEnvironment , stackSdk , toolkitStackName ) ;
329
-
330
339
// Upload the template, if necessary, before passing it to CFN
331
340
const cfnParam = await makeBodyParameterAndUpload (
332
341
stackArtifact ,
333
342
resolvedEnvironment ,
334
- toolkitInfo ,
343
+ envResources ,
335
344
this . sdkProvider ,
336
345
stackSdk ) ;
337
346
@@ -355,16 +364,19 @@ export class Deployments {
355
364
} ;
356
365
}
357
366
358
- const { stackSdk, resolvedEnvironment, cloudFormationRoleArn } = await this . prepareSdkFor ( options . stack , options . roleArn , Mode . ForWriting ) ;
359
-
360
- const toolkitInfo = await this . lookupToolkit ( resolvedEnvironment , stackSdk , options . toolkitStackName ) ;
367
+ const {
368
+ stackSdk,
369
+ resolvedEnvironment,
370
+ cloudFormationRoleArn,
371
+ envResources,
372
+ } = await this . prepareSdkFor ( options . stack , options . roleArn , Mode . ForWriting ) ;
361
373
362
374
// Do a verification of the bootstrap stack version
363
375
await this . validateBootstrapStackVersion (
364
376
options . stack . stackName ,
365
377
options . stack . requiresBootstrapStackVersion ,
366
378
options . stack . bootstrapStackVersionSsmParameter ,
367
- toolkitInfo ) ;
379
+ envResources ) ;
368
380
369
381
return deployStack ( {
370
382
stack : options . stack ,
@@ -376,7 +388,7 @@ export class Deployments {
376
388
sdkProvider : this . sdkProvider ,
377
389
roleArn : cloudFormationRoleArn ,
378
390
reuseAssets : options . reuseAssets ,
379
- toolkitInfo ,
391
+ envResources ,
380
392
tags : options . tags ,
381
393
deploymentMethod,
382
394
force : options . force ,
@@ -420,6 +432,7 @@ export class Deployments {
420
432
return {
421
433
resolvedEnvironment : result . resolvedEnvironment ,
422
434
stackSdk : result . sdk ,
435
+ envResources : result . envResources ,
423
436
} ;
424
437
}
425
438
} catch { }
@@ -464,6 +477,7 @@ export class Deployments {
464
477
stackSdk : stackSdk . sdk ,
465
478
resolvedEnvironment,
466
479
cloudFormationRoleArn : arns . cloudFormationRoleArn ,
480
+ envResources : this . environmentResources . for ( resolvedEnvironment , stackSdk . sdk ) ,
467
481
} ;
468
482
}
469
483
@@ -504,9 +518,11 @@ export class Deployments {
504
518
assumeRoleExternalId : stack . lookupRole ?. assumeRoleExternalId ,
505
519
} ) ;
506
520
521
+ const envResources = this . environmentResources . for ( resolvedEnvironment , stackSdk . sdk ) ;
522
+
507
523
// if we succeed in assuming the lookup role, make sure we have the correct bootstrap stack version
508
524
if ( stackSdk . didAssumeRole && stack . lookupRole ?. bootstrapStackVersionSsmParameter && stack . lookupRole . requiresBootstrapStackVersion ) {
509
- const version = await ToolkitInfo . versionFromSsmParameter ( stackSdk . sdk , stack . lookupRole . bootstrapStackVersionSsmParameter ) ;
525
+ const version = await envResources . versionFromSsmParameter ( stack . lookupRole . bootstrapStackVersionSsmParameter ) ;
510
526
if ( version < stack . lookupRole . requiresBootstrapStackVersion ) {
511
527
throw new Error ( `Bootstrap stack version '${ stack . lookupRole . requiresBootstrapStackVersion } ' is required, found version '${ version } '.` ) ;
512
528
}
@@ -515,7 +531,7 @@ export class Deployments {
515
531
} else if ( ! stackSdk . didAssumeRole && stack . lookupRole ?. requiresBootstrapStackVersion ) {
516
532
warning ( upgradeMessage ) ;
517
533
}
518
- return { ...stackSdk , resolvedEnvironment } ;
534
+ return { ...stackSdk , resolvedEnvironment, envResources } ;
519
535
} catch ( e : any ) {
520
536
debug ( e ) ;
521
537
// only print out the warnings if the lookupRole exists AND there is a required
@@ -528,33 +544,18 @@ export class Deployments {
528
544
}
529
545
}
530
546
531
- /**
532
- * Look up the toolkit for a given environment, using a given SDK
533
- */
534
- public async lookupToolkit ( resolvedEnvironment : cxapi . Environment , sdk : ISDK , toolkitStackName ?: string ) {
535
- const key = `${ resolvedEnvironment . account } :${ resolvedEnvironment . region } :${ toolkitStackName } ` ;
536
- const existing = this . toolkitInfoCache . get ( key ) ;
537
- if ( existing ) {
538
- return existing ;
539
- }
540
- const ret = await ToolkitInfo . lookup ( resolvedEnvironment , sdk , toolkitStackName ) ;
541
- this . toolkitInfoCache . set ( key , ret ) ;
542
- return ret ;
543
- }
544
-
545
547
private async prepareAndValidateAssets ( asset : cxapi . AssetManifestArtifact , options : AssetOptions ) {
546
- const { stackSdk, resolvedEnvironment } = await this . prepareSdkFor ( options . stack , options . roleArn , Mode . ForWriting ) ;
547
- const toolkitInfo = await this . lookupToolkit ( resolvedEnvironment , stackSdk , options . toolkitStackName ) ;
548
- const stackEnv = await this . sdkProvider . resolveEnvironment ( options . stack . environment ) ;
548
+ const { envResources } = await this . prepareSdkFor ( options . stack , options . roleArn , Mode . ForWriting ) ;
549
+
549
550
await this . validateBootstrapStackVersion (
550
551
options . stack . stackName ,
551
552
asset . requiresBootstrapStackVersion ,
552
553
asset . bootstrapStackVersionSsmParameter ,
553
- toolkitInfo ) ;
554
+ envResources ) ;
554
555
555
556
const manifest = AssetManifest . fromFile ( asset . file ) ;
556
557
557
- return { manifest, stackEnv } ;
558
+ return { manifest, stackEnv : envResources . environment } ;
558
559
}
559
560
560
561
/**
@@ -582,16 +583,15 @@ export class Deployments {
582
583
*/
583
584
// eslint-disable-next-line max-len
584
585
public async buildSingleAsset ( assetArtifact : cxapi . AssetManifestArtifact , assetManifest : AssetManifest , asset : IManifestEntry , options : BuildStackAssetsOptions ) {
585
- const { stackSdk, resolvedEnvironment : stackEnv } = await this . prepareSdkFor ( options . stack , options . roleArn , Mode . ForWriting ) ;
586
- const toolkitInfo = await this . lookupToolkit ( stackEnv , stackSdk , options . toolkitStackName ) ;
586
+ const { resolvedEnvironment, envResources } = await this . prepareSdkFor ( options . stack , options . roleArn , Mode . ForWriting ) ;
587
587
588
588
await this . validateBootstrapStackVersion (
589
589
options . stack . stackName ,
590
590
assetArtifact . requiresBootstrapStackVersion ,
591
591
assetArtifact . bootstrapStackVersionSsmParameter ,
592
- toolkitInfo ) ;
592
+ envResources ) ;
593
593
594
- const publisher = this . cachedPublisher ( assetManifest , stackEnv , options . stackName ) ;
594
+ const publisher = this . cachedPublisher ( assetManifest , resolvedEnvironment , options . stackName ) ;
595
595
await publisher . buildEntry ( asset ) ;
596
596
if ( publisher . hasFailures ) {
597
597
throw new Error ( `Failed to build asset ${ asset . id } ` ) ;
@@ -624,17 +624,17 @@ export class Deployments {
624
624
625
625
/**
626
626
* Validate that the bootstrap stack has the right version for this stack
627
+ *
628
+ * Call into envResources.validateVersion, but prepend the stack name in case of failure.
627
629
*/
628
630
private async validateBootstrapStackVersion (
629
631
stackName : string ,
630
632
requiresBootstrapStackVersion : number | undefined ,
631
633
bootstrapStackVersionSsmParameter : string | undefined ,
632
- toolkitInfo : ToolkitInfo ) {
633
-
634
- if ( requiresBootstrapStackVersion === undefined ) { return ; }
634
+ envResources : EnvironmentResources ) {
635
635
636
636
try {
637
- await toolkitInfo . validateVersion ( requiresBootstrapStackVersion , bootstrapStackVersionSsmParameter ) ;
637
+ await envResources . validateVersion ( requiresBootstrapStackVersion , bootstrapStackVersionSsmParameter ) ;
638
638
} catch ( e : any ) {
639
639
throw new Error ( `${ stackName } : ${ e . message } ` ) ;
640
640
}
0 commit comments