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(amplify-domain): Added config for auto subdomain creation #13342

Merged
merged 10 commits into from
Mar 11, 2021
5 changes: 4 additions & 1 deletion packages/@aws-cdk/aws-amplify/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ mySinglePageApp.addCustomRule(amplify.CustomRule.SINGLE_PAGE_APPLICATION_REDIREC
Add a domain and map sub domains to branches:

```ts
const domain = amplifyApp.addDomain('example.com');
const domain = amplifyApp.addDomain('example.com', {
enableAutoSubdomain: true, // in case subdomains should be auto registered for branches
autoSubdomainCreationPatterns: ['*', 'pr*'], // regex for branches that should auto register subdomains
});
domain.mapRoot(master); // map master branch to domain root
domain.mapSubDomain(master, 'www');
domain.mapSubDomain(dev); // sub domain prefix defaults to branch name
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-amplify/lib/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ export class App extends Resource implements IApp, iam.IGrantable {
return new Domain(this, id, {
...options,
app: this,
autoSubDomainIamRole: this.grantPrincipal as iam.IRole,
});
}
}
Expand Down
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-amplify/lib/domain.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as iam from '@aws-cdk/aws-iam';
import { Lazy, Resource, IResolvable } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CfnDomain } from './amplify.generated';
Expand All @@ -21,6 +22,20 @@ export interface DomainOptions {
* @default - use `addSubDomain()` to add subdomains
*/
readonly subDomains?: SubDomain[];

/**
* Automatically create subdomains for connected branches
*
* @default false
*/
readonly enableAutoSubdomain?: boolean;

/**
* Branches which should automatically create subdomains
*
* @default - all repository branches ['*', 'pr*']
*/
readonly autoSubdomainCreationPatterns?: string[];
}

/**
Expand All @@ -31,6 +46,12 @@ export interface DomainProps extends DomainOptions {
* The application to which the domain must be connected
*/
readonly app: IApp;

/**
* The IAM role with access to Route53 when using enableAutoSubdomain
* @default the IAM role from App.grantPrincipal
*/
readonly autoSubDomainIamRole?: iam.IRole;
}

/**
Expand Down Expand Up @@ -106,6 +127,9 @@ export class Domain extends Resource {
appId: props.app.appId,
domainName,
subDomainSettings: Lazy.any({ produce: () => this.renderSubDomainSettings() }, { omitEmptyArray: true }),
enableAutoSubDomain: !!props.enableAutoSubdomain,
autoSubDomainCreationPatterns: props.autoSubdomainCreationPatterns || ['*', 'pr*'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes it so that only when a user passes enableAutoSubdomain: true all branches will automatically get their own subdomains deployed right? if enableAutoSubDomain: false this default doesn't really matter right?

This is fine with me I'm just making sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the web interface that's the behavior, by enabling enableAutoSubDomain=true all branches listen. But when I tried from the CloudFormation without providing autoSubdomainCreationPatterns it didn't seem to get a default so I tried to keep a similar behaviour

and yes, when enableAutoSubDomain=false the autoSubdomainCreationPatterns is filled but ignored

autoSubDomainIamRole: props.autoSubDomainIamRole?.roleArn,
});

this.arn = domain.attrArn;
Expand Down
111 changes: 111 additions & 0 deletions packages/@aws-cdk/aws-amplify/test/domain.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as iam from '@aws-cdk/aws-iam';
import '@aws-cdk/assert/jest';
import { App, SecretValue, Stack } from '@aws-cdk/core';
import * as amplify from '../lib';
Expand Down Expand Up @@ -120,3 +121,113 @@ test('throws at synthesis without subdomains', () => {
// THEN
expect(() => app.synth()).toThrow(/The domain doesn't contain any subdomains/);
});

test('auto subdomain all branches', () => {
// GIVEN
const stack = new Stack();
const app = new amplify.App(stack, 'App', {
sourceCodeProvider: new amplify.GitHubSourceCodeProvider({
owner: 'aws',
repository: 'aws-cdk',
oauthToken: SecretValue.plainText('secret'),
}),
});
const prodBranch = app.addBranch('master');

// WHEN
const domain = app.addDomain('amazon.com', {
enableAutoSubdomain: true,
});
domain.mapRoot(prodBranch);

// THEN
expect(stack).toHaveResource('AWS::Amplify::Domain', {
EnableAutoSubDomain: true,
AutoSubDomainCreationPatterns: [
'*',
'pr*',
],
AutoSubDomainIAMRole: {
'Fn::GetAtt': [
'AppRole1AF9B530',
'Arn',
],
},
});
});

test('auto subdomain some branches', () => {
// GIVEN
const stack = new Stack();
const app = new amplify.App(stack, 'App', {
sourceCodeProvider: new amplify.GitHubSourceCodeProvider({
owner: 'aws',
repository: 'aws-cdk',
oauthToken: SecretValue.plainText('secret'),
}),
});
const prodBranch = app.addBranch('master');

// WHEN
const domain = app.addDomain('amazon.com', {
enableAutoSubdomain: true,
autoSubdomainCreationPatterns: ['features/**'],
});
domain.mapRoot(prodBranch);

// THEN
expect(stack).toHaveResource('AWS::Amplify::Domain', {
EnableAutoSubDomain: true,
AutoSubDomainCreationPatterns: ['features/**'],
AutoSubDomainIAMRole: {
'Fn::GetAtt': [
'AppRole1AF9B530',
'Arn',
],
},
});
});

test('auto subdomain with IAM role', () => {
// GIVEN
const stack = new Stack();
const app = new amplify.App(stack, 'App', {
sourceCodeProvider: new amplify.GitHubSourceCodeProvider({
owner: 'aws',
repository: 'aws-cdk',
oauthToken: SecretValue.plainText('secret'),
}),
role: iam.Role.fromRoleArn(
stack,
'AmplifyRole',
`arn:aws:iam::${Stack.of(stack).account}:role/AmplifyRole`,
{ mutable: false },
),
});
const prodBranch = app.addBranch('master');

// WHEN
const domain = app.addDomain('amazon.com', {
enableAutoSubdomain: true,
autoSubdomainCreationPatterns: ['features/**'],
});
domain.mapRoot(prodBranch);

// THEN
expect(stack).toHaveResource('AWS::Amplify::Domain', {
EnableAutoSubDomain: true,
AutoSubDomainCreationPatterns: ['features/**'],
AutoSubDomainIAMRole: {
'Fn::Join': [
'',
[
'arn:aws:iam::',
{
Ref: 'AWS::AccountId',
},
':role/AmplifyRole',
],
],
},
});
});