Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
56 changes: 55 additions & 1 deletion packages/@aws-cdk/core/test/test.cross-environment-token.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Test } from 'nodeunit';
import { App, CfnOutput, Construct, PhysicalName, Resource, Stack } from '../lib';
import { App, CfnOutput, CfnResource, Construct, PhysicalName, Resource, Stack } from '../lib';
import { toCloudFormation } from './util';

// tslint:disable:object-literal-key-quotes
Expand Down Expand Up @@ -195,6 +195,53 @@ export = {

test.done();
},

'cross environment when stack is a substack'(test: Test) {
const app = new App();

const parentStack = new Stack(app, 'ParentStack', {
env: { account: '112233', region: 'us-east-1' }
});

const childStack = new Stack(parentStack, 'ChildStack', {
env: { account: '998877', region: 'eu-west-2' }
});

const childResource = new MyResource(childStack, 'ChildResource', PhysicalName.GENERATE_IF_NEEDED);

new CfnResource(parentStack, 'ParentResource', {
type: 'Parent::Resource',
properties: {
RefToChildResource: childResource.name
}
});

const assembly = app.synth();

test.deepEqual(assembly.getStack(parentStack.stackName).template, {
Resources: {
ParentResource: {
Type: 'Parent::Resource',
Properties: {
RefToChildResource: 'parentstackchildstack83c5ackchildresource852877eeb919bda2008e'
}
}
}
});

test.deepEqual(assembly.getStack(childStack.stackName).template, {
Resources: {
ChildResource8C37244D: {
Type: 'My::Resource',
Properties: {
resourceName: 'parentstackchildstack83c5ackchildresource852877eeb919bda2008e'
}
}
}
});

test.done();
}
};

class MyResource extends Resource {
Expand All @@ -212,5 +259,12 @@ class MyResource extends Resource {
service: 'myservice',
});
this.name = this.getResourceNameAttribute('simple-name');

new CfnResource(this, 'Resource', {
type: 'My::Resource',
properties: {
resourceName: this.physicalName
}
});
}
}
117 changes: 117 additions & 0 deletions packages/@aws-cdk/core/test/test.stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,103 @@ export = {
test.done();
},

'Stacks can be children of other stacks (substack) and they will be synthesized separately'(test: Test) {
// GIVEN
const app = new App();

// WHEN
const parentStack = new Stack(app, 'parent');
const childStack = new Stack(parentStack, 'child');
new CfnResource(parentStack, 'MyParentResource', { type: 'Resource::Parent' });
new CfnResource(childStack, 'MyChildResource', { type: 'Resource::Child' });

// THEN
const assembly = app.synth();
test.deepEqual(assembly.getStack(parentStack.stackName).template, { Resources: { MyParentResource: { Type: 'Resource::Parent' } } });
test.deepEqual(assembly.getStack(childStack.stackName).template, { Resources: { MyChildResource: { Type: 'Resource::Child' } } });
test.done();
},

'cross-stack reference (substack references parent stack)'(test: Test) {
// GIVEN
const app = new App();
const parentStack = new Stack(app, 'parent');
const childStack = new Stack(parentStack, 'child');

// WHEN (a resource from the child stack references a resource from the parent stack)
const parentResource = new CfnResource(parentStack, 'MyParentResource', { type: 'Resource::Parent' });
new CfnResource(childStack, 'MyChildResource', {
type: 'Resource::Child',
properties: {
ChildProp: parentResource.getAtt('AttOfParentResource')
}
});

// THEN
const assembly = app.synth();
test.deepEqual(assembly.getStack(parentStack.stackName).template, {
Resources: { MyParentResource: { Type: 'Resource::Parent' } },
Outputs: { ExportsOutputFnGetAttMyParentResourceAttOfParentResourceC2D0BB9E: {
Value: { 'Fn::GetAtt': [ 'MyParentResource', 'AttOfParentResource' ] },
Export: { Name: 'parent:ExportsOutputFnGetAttMyParentResourceAttOfParentResourceC2D0BB9E' } }
}
});
test.deepEqual(assembly.getStack(childStack.stackName).template, {
Resources: {
MyChildResource: {
Type: 'Resource::Child',
Properties: {
ChildProp: {
'Fn::ImportValue': 'parent:ExportsOutputFnGetAttMyParentResourceAttOfParentResourceC2D0BB9E'
}
}
}
}
});
test.done();
},

'cross-stack reference (parent stack references substack)'(test: Test) {
// GIVEN
const app = new App();
const parentStack = new Stack(app, 'parent');
const childStack = new Stack(parentStack, 'child');

// WHEN (a resource from the child stack references a resource from the parent stack)
const childResource = new CfnResource(childStack, 'MyChildResource', { type: 'Resource::Child' });
new CfnResource(parentStack, 'MyParentResource', {
type: 'Resource::Parent',
properties: {
ParentProp: childResource.getAtt('AttributeOfChildResource')
}
});

// THEN
const assembly = app.synth();
test.deepEqual(assembly.getStack(parentStack.stackName).template, {
Resources: {
MyParentResource: {
Type: 'Resource::Parent',
Properties: {
ParentProp: { 'Fn::ImportValue': 'parentchild13F9359B:childExportsOutputFnGetAttMyChildResourceAttributeOfChildResource420052FC' }
}
}
}
});

test.deepEqual(assembly.getStack(childStack.stackName).template, {
Resources: {
MyChildResource: { Type: 'Resource::Child' } },
Outputs: {
ExportsOutputFnGetAttMyChildResourceAttributeOfChildResource52813264: {
Value: { 'Fn::GetAtt': [ 'MyChildResource', 'AttributeOfChildResource' ] },
Export: { Name: 'parentchild13F9359B:childExportsOutputFnGetAttMyChildResourceAttributeOfChildResource420052FC' }
}
}
});
test.done();
},

'cannot create cyclic reference between stacks'(test: Test) {
// GIVEN
const app = new App();
Expand Down Expand Up @@ -439,6 +536,26 @@ export = {
test.done();
},

'Stack.of() works for substacks'(test: Test) {
// GIVEN
const app = new App();

// WHEN
const parentStack = new Stack(app, 'ParentStack');
const parentResource = new CfnResource(parentStack, 'ParentResource', { type: 'parent::resource' });

// we will define a substack under the /resource/... just for giggles.
const childStack = new Stack(parentResource, 'ChildStack');
const childResource = new CfnResource(childStack, 'ChildResource', { type: 'child::resource' });

// THEN
test.same(Stack.of(parentStack), parentStack);
test.same(Stack.of(parentResource), parentStack);
test.same(Stack.of(childStack), childStack);
test.same(Stack.of(childResource), childStack);
test.done();
},

'stack.availabilityZones falls back to Fn::GetAZ[0],[2] if region is not specified'(test: Test) {
// GIVEN
const app = new App();
Expand Down