Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cdk): transparent cross-stack references #1436

Merged
merged 44 commits into from
Jan 9, 2019
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7b97ebb
Fix tag manager tests to use resolve(token) instead of token.resolve()
rix0rrr Sep 29, 2018
1f938cf
Introduce StackAwareToken, make all pseudos Stack-Aware.
rix0rrr Sep 29, 2018
929b003
Merge branch 'master' into huijbers/x-stack-references
Dec 18, 2018
d02e16d
Remove concept of freezing
Dec 18, 2018
ac062fc
Add explicit preprocessor step for references
Dec 18, 2018
935fd82
Get rid of "context" parameter for Token resolution
Dec 18, 2018
9f40aa2
Make refs and attributes Stack-aware
Dec 21, 2018
c1d4dc1
Create tests for things I'll have to do later
Dec 21, 2018
5d85318
Fix core tests
Dec 26, 2018
4219539
Merge branch 'master' into huijbers/x-stack-references
rix0rrr Dec 28, 2018
d8876bf
Remove CloudFormationToken
rix0rrr Dec 28, 2018
0a724b4
Rename StackAwareCloudFormationToken -> StackAwareToken
rix0rrr Dec 28, 2018
445805f
CloudFormationConcat is no longer configurable, but just the default
rix0rrr Dec 28, 2018
cc928f8
Remove sourceStack argument to substitution
rix0rrr Dec 28, 2018
3cb539f
Make JSII happy
rix0rrr Dec 28, 2018
0840d76
Make Pseudo parameters (StackId etc.) attributes of Stack
rix0rrr Dec 28, 2018
73353c0
Add cdk deployment ordering; WIP - fighting with dependency cycles
rix0rrr Dec 28, 2018
f161a4d
Reorganizing to get rid of cycles, add integ test
rix0rrr Dec 31, 2018
7a105e9
Merge remote-tracking branch 'origin/master' into huijbers/x-stack-re…
rix0rrr Jan 4, 2019
ba3a4db
Rename StackAwareToken => CfnReference
rix0rrr Jan 4, 2019
8093361
Move resolve() into the context of a Construct, and hide the global m…
rix0rrr Jan 4, 2019
6330ab5
Introduce concept of references and use it to implement cross-stack refs
rix0rrr Jan 4, 2019
2c224c4
Fix some bugs
rix0rrr Jan 4, 2019
b17d811
More context attachments trying to make the tests work
rix0rrr Jan 4, 2019
a8e00d9
More work to get tests to pass
rix0rrr Jan 7, 2019
eef74a5
Also generate private (tools) packages in global tsconfig
Jan 7, 2019
5978c6b
Fix examples
Jan 7, 2019
996f998
Merge branch 'master' into huijbers/x-stack-references
Jan 8, 2019
e0ec521
Review comments
rix0rrr Jan 8, 2019
3a0d5b5
Fix compilation
rix0rrr Jan 8, 2019
1d5388d
Review comments
rix0rrr Jan 8, 2019
3ee48f7
Undo more refactoring breakage
rix0rrr Jan 8, 2019
d1b3c22
Fold ArnUtils.fromComponents() and ArnUtils.parse() into Stack
rix0rrr Jan 8, 2019
85cc4d2
Missing commit
rix0rrr Jan 8, 2019
8e64bc2
Replace construct library's use of CloudFormationJSON with stringifyJ…
rix0rrr Jan 8, 2019
5694b9c
Remove additional scope argument for IAM policies
rix0rrr Jan 8, 2019
d1a643e
Merge remote-tracking branch 'origin/master' into huijbers/x-stack-re…
rix0rrr Jan 8, 2019
12854e6
arnFromComponents() -> formatArn()
rix0rrr Jan 8, 2019
c7d4314
Move logic for collecting tokens to token layer
Jan 8, 2019
d2a656f
validate() is now protected
Jan 8, 2019
fdeaa55
Move protected() methods down in source
Jan 8, 2019
00cbe07
Call validateTree() instead of protected validate() in tests
Jan 8, 2019
0346946
Fix test
Jan 8, 2019
34bfb34
Fix another test
Jan 8, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-apigateway/lib/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ export class Stage extends cdk.Construct implements cdk.IDependable {
if (!path.startsWith('/')) {
throw new Error(`Path must begin with "/": ${path}`);
}
return `https://${this.restApi.restApiId}.execute-api.${new cdk.AwsRegion()}.amazonaws.com/${this.stageName}${path}`;
return `https://${this.restApi.restApiId}.execute-api.${new cdk.AwsRegion(this)}.amazonaws.com/${this.stageName}${path}`;
}

private renderMethodSettings(props: StageProps): CfnStage.MethodSettingProperty[] | undefined {
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-cloudtrail/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export class CloudTrail extends cdk.Construct {
.addServicePrincipal(cloudTrailPrincipal));

s3bucket.addToResourcePolicy(new iam.PolicyStatement()
.addResource(s3bucket.arnForObjects(new cdk.FnConcat('AWSLogs/', new cdk.AwsAccountId(), "/*")))
.addResource(s3bucket.arnForObjects(new cdk.FnConcat('AWSLogs/', new cdk.AwsAccountId(this), "/*")))
.addActions("s3:PutObject")
.addServicePrincipal(cloudTrailPrincipal)
.setCondition("StringEquals", {'s3:x-amz-acl': "bucket-owner-full-control"}));
Expand Down
6 changes: 3 additions & 3 deletions packages/@aws-cdk/aws-cloudwatch/lib/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class AlarmWidget extends ConcreteWidget {
properties: {
view: 'timeSeries',
title: this.props.title,
region: this.props.region || new AwsRegion(),
region: this.props.region || new AwsRegion(undefined),
annotations: {
alarms: [this.props.alarm.alarmArn]
},
Expand Down Expand Up @@ -150,7 +150,7 @@ export class GraphWidget extends ConcreteWidget {
properties: {
view: 'timeSeries',
title: this.props.title,
region: this.props.region || new AwsRegion(),
region: this.props.region || new AwsRegion(undefined),
metrics: (this.props.left || []).map(m => metricJson(m, 'left')).concat(
(this.props.right || []).map(m => metricJson(m, 'right'))),
annotations: {
Expand Down Expand Up @@ -197,7 +197,7 @@ export class SingleValueWidget extends ConcreteWidget {
properties: {
view: 'singleValue',
title: this.props.title,
region: this.props.region || new AwsRegion(),
region: this.props.region || new AwsRegion(undefined),
metrics: this.props.metrics.map(m => metricJson(m, 'left'))
}
}];
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-codecommit/lib/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ class ImportedRepositoryRef extends RepositoryRef {

private repositoryCloneUrl(protocol: 'https' | 'ssh'): string {
return new cdk.FnConcat(`${protocol}://git-codecommit.`,
new cdk.AwsRegion(),
new cdk.AwsRegion(this),
'.',
new cdk.AwsURLSuffix(),
new cdk.AwsURLSuffix(this),
'/v1/repos/',
this.repositoryName).toString();
}
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-codedeploy/lib/deployment-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupRef {

this._autoScalingGroups = props.autoScalingGroups || [];
this.installAgent = props.installAgent === undefined ? true : props.installAgent;
const region = (new cdk.AwsRegion()).toString();
const region = (new cdk.AwsRegion(this)).toString();
this.codeDeployBucket = s3.BucketRef.import(this, 'CodeDeployBucket', {
bucketName: `aws-codedeploy-${region}`,
});
Expand Down Expand Up @@ -371,7 +371,7 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupRef {

this.codeDeployBucket.grantRead(asg.role, 'latest/*');

const region = (new cdk.AwsRegion()).toString();
const region = (new cdk.AwsRegion(this)).toString();
switch (asg.osType) {
case ec2.OperatingSystemType.Linux:
asg.addUserData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class AwsLogDriver extends LogDriver {
options: removeEmpty({
'awslogs-group': this.logGroup.logGroupName,
'awslogs-stream-prefix': this.props.streamPrefix,
'awslogs-region': `${new cdk.AwsRegion()}`,
'awslogs-region': `${new cdk.AwsRegion(this)}`,
'awslogs-datetime-format': this.props.datetimeFormat,
'awslogs-multiline-pattern': this.props.multilinePattern,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class ApplicationLoadBalancer extends BaseLoadBalancer implements IApplic

// FIXME: can't use grantPut() here because that only takes IAM objects, not arbitrary principals
bucket.addToResourcePolicy(new iam.PolicyStatement()
.addPrincipal(new iam.AccountPrincipal(account))
.addPrincipal(new iam.AccountPrincipal(this, account))
.addAction('s3:PutObject')
.addResource(bucket.arnForObjects(prefix || '', '*')));
}
Expand Down
20 changes: 11 additions & 9 deletions packages/@aws-cdk/aws-iam/lib/policy-document.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { AwsAccountId, AwsPartition, Token } from '@aws-cdk/cdk';
import { Construct } from '@aws-cdk/cdk';
import { Token } from '@aws-cdk/cdk';
import { AwsAccountId, AwsPartition } from '@aws-cdk/cdk';

export class PolicyDocument extends Token {
private statements = new Array<PolicyStatement>();
Expand Down Expand Up @@ -81,8 +83,8 @@ export class ArnPrincipal extends PolicyPrincipal {
}

export class AccountPrincipal extends ArnPrincipal {
constructor(public readonly accountId: any) {
super(`arn:${new AwsPartition()}:iam::${accountId}:root`);
constructor(public readonly anchor: Construct, public readonly accountId: any) {
super(`arn:${new AwsPartition(anchor)}:iam::${accountId}:root`);
}
}

Expand Down Expand Up @@ -136,8 +138,8 @@ export class FederatedPrincipal extends PolicyPrincipal {
}

export class AccountRootPrincipal extends AccountPrincipal {
constructor() {
super(new AwsAccountId());
constructor(anchor: Construct) {
super(anchor, new AwsAccountId(anchor));
}
}

Expand Down Expand Up @@ -213,8 +215,8 @@ export class PolicyStatement extends Token {
return this.addPrincipal(new ArnPrincipal(arn));
}

public addAwsAccountPrincipal(accountId: string): PolicyStatement {
return this.addPrincipal(new AccountPrincipal(accountId));
public addAwsAccountPrincipal(anchor: Construct, accountId: string): PolicyStatement {
return this.addPrincipal(new AccountPrincipal(anchor, accountId));
}

public addServicePrincipal(service: string): PolicyStatement {
Expand All @@ -225,8 +227,8 @@ export class PolicyStatement extends Token {
return this.addPrincipal(new FederatedPrincipal(federated, conditions));
}

public addAccountRootPrincipal(): PolicyStatement {
return this.addPrincipal(new AccountRootPrincipal());
public addAccountRootPrincipal(anchor: Construct): PolicyStatement {
return this.addPrincipal(new AccountRootPrincipal(anchor));
}

//
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-iam/test/example.external-id.lit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class ExampleConstruct extends cdk.Construct {

/// !show
const role = new iam.Role(this, 'MyRole', {
assumedBy: new iam.AccountPrincipal('123456789012'),
assumedBy: new iam.AccountPrincipal(this, '123456789012'),
externalId: 'SUPPLY-ME',
});
/// !hide
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-iam/test/integ.role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ policy.attachToRole(role);

// Role with an external ID
new Role(stack, 'TestRole2', {
assumedBy: new AccountRootPrincipal(),
assumedBy: new AccountRootPrincipal(stack),
externalId: 'supply-me',
});

Expand Down
23 changes: 16 additions & 7 deletions packages/@aws-cdk/aws-iam/test/test.policy-document.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { FnConcat, resolve } from '@aws-cdk/cdk';
import { FnConcat, resolve, Stack } from '@aws-cdk/cdk';
import { Test } from 'nodeunit';
import { Anyone, CanonicalUserPrincipal, PolicyDocument, PolicyPrincipal, PolicyStatement, PrincipalPolicyFragment } from '../lib';

export = {
'the Permission class is a programming model for iam'(test: Test) {
const stack = new Stack();

const p = new PolicyStatement();
p.addAction('sqs:SendMessage');
p.addActions('dynamodb:CreateTable', 'dynamodb:DeleteTable');
p.addResource('myQueue');
p.addResource('yourQueue');

p.addAllResources();
p.addAwsAccountPrincipal(new FnConcat('my', { account: 'account' }, 'name').toString());
p.addAwsAccountPrincipal(stack, new FnConcat('my', { account: 'account' }, 'name').toString());
p.limitToAccount('12221121221');

test.deepEqual(resolve(p), { Action:
Expand Down Expand Up @@ -106,8 +108,10 @@ export = {
},

'addAccountRootPrincipal adds a principal with the current account root'(test: Test) {
const stack = new Stack();

const p = new PolicyStatement();
p.addAccountRootPrincipal();
p.addAccountRootPrincipal(stack);
test.deepEqual(resolve(p), {
Effect: "Allow",
Principal: {
Expand Down Expand Up @@ -144,9 +148,11 @@ export = {
},

'addAwsAccountPrincipal can be used multiple times'(test: Test) {
const stack = new Stack();

const p = new PolicyStatement();
p.addAwsAccountPrincipal('1234');
p.addAwsAccountPrincipal('5678');
p.addAwsAccountPrincipal(stack, '1234');
p.addAwsAccountPrincipal(stack, '5678');
test.deepEqual(resolve(p), {
Effect: 'Allow',
Principal: {
Expand Down Expand Up @@ -213,7 +219,9 @@ export = {
},

'addPrincipal prohibits mixing principal types'(test: Test) {
const s = new PolicyStatement().addAccountRootPrincipal();
const stack = new Stack();

const s = new PolicyStatement().addAccountRootPrincipal(stack);
test.throws(() => { s.addServicePrincipal('rds.amazonaws.com'); },
/Attempted to add principal key Service/);
test.throws(() => { s.addFederatedPrincipal('federation', { ConditionOp: { ConditionKey: 'ConditionValue' } }); },
Expand All @@ -222,11 +230,12 @@ export = {
},

'addPrincipal correctly merges array in'(test: Test) {
const stack = new Stack();
const arrayPrincipal: PolicyPrincipal = {
assumeRoleAction: 'sts:AssumeRole',
policyFragment: () => new PrincipalPolicyFragment({ AWS: ['foo', 'bar'] }),
};
const s = new PolicyStatement().addAccountRootPrincipal()
const s = new PolicyStatement().addAccountRootPrincipal(stack)
.addPrincipal(arrayPrincipal);
test.deepEqual(resolve(s), {
Effect: 'Allow',
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-kinesis/lib/stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export abstract class StreamRef extends cdk.Construct implements logs.ILogSubscr
if (!this.cloudWatchLogsRole) {
// Create a role to be assumed by CWL that can write to this stream and pass itself.
this.cloudWatchLogsRole = new iam.Role(this, 'CloudWatchLogsCanPutRecords', {
assumedBy: new iam.ServicePrincipal(new cdk.FnConcat('logs.', new cdk.AwsRegion(), '.amazonaws.com').toString()),
assumedBy: new iam.ServicePrincipal(new cdk.FnConcat('logs.', new cdk.AwsRegion(this), '.amazonaws.com').toString()),
});
this.cloudWatchLogsRole.addToPolicy(new iam.PolicyStatement().addAction('kinesis:PutRecord').addResource(this.streamArn));
this.cloudWatchLogsRole.addToPolicy(new iam.PolicyStatement().addAction('iam:PassRole').addResource(this.cloudWatchLogsRole.roleArn));
Expand Down Expand Up @@ -215,7 +215,7 @@ export abstract class StreamRef extends cdk.Construct implements logs.ILogSubscr

dest.addToPolicy(new iam.PolicyStatement()
.addAction('logs:PutSubscriptionFilter')
.addAwsAccountPrincipal(sourceStack.env.account)
.addAwsAccountPrincipal(this, sourceStack.env.account)
.addAllResources());

return dest.logSubscriptionDestination(sourceLogGroup);
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-kms/lib/key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export class EncryptionKey extends EncryptionKeyRef {
this.addToResourcePolicy(new PolicyStatement()
.addAllResources()
.addActions(...actions)
.addAccountRootPrincipal());
.addAccountRootPrincipal(this));
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-kms/test/integ.key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const key = new EncryptionKey(stack, 'MyKey');
key.addToResourcePolicy(new PolicyStatement()
.addAllResources()
.addAction('kms:encrypt')
.addAwsPrincipal(new AwsAccountId().toString()));
.addAwsPrincipal(new AwsAccountId(stack).toString()));

key.addAlias('alias/bar');

Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ export abstract class FunctionRef extends cdk.Construct
//
// (Wildcards in principals are unfortunately not supported.
this.addPermission('InvokedByCloudWatchLogs', {
principal: new iam.ServicePrincipal(new cdk.FnConcat('logs.', new cdk.AwsRegion(), '.amazonaws.com').toString()),
principal: new iam.ServicePrincipal(new cdk.FnConcat('logs.', new cdk.AwsRegion(this), '.amazonaws.com').toString()),
sourceArn: arn
});
this.logSubscriptionDestinationPolicyAddedFor.push(arn);
Expand Down Expand Up @@ -348,7 +348,7 @@ export abstract class FunctionRef extends cdk.Construct
const permissionId = `AllowBucketNotificationsFrom${bucketId}`;
if (!this.tryFindChild(permissionId)) {
this.addPermission(permissionId, {
sourceAccount: new cdk.AwsAccountId().toString(),
sourceAccount: new cdk.AwsAccountId(this).toString(),
principal: new iam.ServicePrincipal('s3.amazonaws.com'),
sourceArn: bucketArn,
});
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-lambda/test/test.alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export = {

// WHEN
alias.addPermission('Perm', {
principal: new AccountPrincipal('123456')
principal: new AccountPrincipal(stack, '123456')
});

// THEN
Expand Down
6 changes: 3 additions & 3 deletions packages/@aws-cdk/aws-lambda/test/test.lambda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export = {
fn.addPermission('S3Permission', {
action: 'lambda:*',
principal: new iam.ServicePrincipal('s3.amazonaws.com'),
sourceAccount: new cdk.AwsAccountId().toString(),
sourceAccount: new cdk.AwsAccountId(stack).toString(),
sourceArn: 'arn:aws:s3:::my_bucket'
});

Expand Down Expand Up @@ -191,7 +191,7 @@ export = {
/Invalid principal type for Lambda permission statement/);

fn.addPermission('S1', { principal: new iam.ServicePrincipal('my-service') });
fn.addPermission('S2', { principal: new iam.AccountPrincipal('account') });
fn.addPermission('S2', { principal: new iam.AccountPrincipal(stack, 'account') });

test.done();
},
Expand Down Expand Up @@ -1036,7 +1036,7 @@ export = {
// GIVEN
const stack = new cdk.Stack();
const role = new iam.Role(stack, 'Role', {
assumedBy: new iam.AccountPrincipal('1234'),
assumedBy: new iam.AccountPrincipal(stack, '1234'),
});
const fn = new lambda.Function(stack, 'Function', {
code: lambda.Code.inline('xxx'),
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-route53/lib/hosted-zone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export class PrivateHostedZone extends HostedZoneRef {
}

function toVpcProperty(vpc: ec2.VpcNetworkRef): CfnHostedZone.VPCProperty {
return { vpcId: vpc.vpcId, vpcRegion: new cdk.AwsRegion() };
return { vpcId: vpc.vpcId, vpcRegion: new cdk.AwsRegion(vpc) };
}

function determineHostedZoneProps(props: PublicHostedZoneProps) {
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-s3/lib/bucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export abstract class BucketRef extends cdk.Construct {
* @returns an ObjectS3Url token
*/
public urlForObject(key?: any): string {
const components = [ 'https://', 's3.', new cdk.AwsRegion(), '.', new cdk.AwsURLSuffix(), '/', this.bucketName ];
const components = [ 'https://', 's3.', new cdk.AwsRegion(this), '.', new cdk.AwsURLSuffix(this), '/', this.bucketName ];
if (key) {
// trim prepending '/'
if (typeof key === 'string' && key.startsWith('/')) {
Expand Down
2 changes: 1 addition & 1 deletion packages/@aws-cdk/aws-stepfunctions/lib/state-machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class StateMachine extends cdk.Construct implements IStateMachine {
super(parent, id);

this.role = props.role || new iam.Role(this, 'Role', {
assumedBy: new iam.ServicePrincipal(`states.${new cdk.AwsRegion()}.amazonaws.com`),
assumedBy: new iam.ServicePrincipal(`states.${new cdk.AwsRegion(this)}.amazonaws.com`),
});

const graph = new StateGraph(props.definition.startState, `State Machine ${id} definition`);
Expand Down
11 changes: 10 additions & 1 deletion packages/@aws-cdk/cdk/lib/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export class App extends Root {
return;
}

this.applyCrossEnvironmentReferences();

const result: cxapi.SynthesizeResponse = {
version: cxapi.PROTO_RESPONSE_VERSION,
stacks: this.synthesizeStacks(Object.keys(this.stacks)),
Expand Down Expand Up @@ -81,7 +83,8 @@ export class App extends Root {
environment,
missing,
template: stack.toCloudFormation(),
metadata: this.collectMetadata(stack)
metadata: this.collectMetadata(stack),
dependsOn: stack.dependencyStackIds(),
};
}

Expand Down Expand Up @@ -123,6 +126,12 @@ export class App extends Root {
}
}

public applyCrossEnvironmentReferences() {
for (const stack of Object.values(this.stacks)) {
stack.applyCrossEnvironmentReferences();
}
}

private collectRuntimeInformation(): cxapi.AppRuntime {
const libraries: { [name: string]: string } = {};

Expand Down
Loading