This repository has been archived by the owner on Jun 13, 2024. It is now read-only.
forked from aws/aws-cdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(cloudfront): add support for Origin Groups (aws#9360)
Fixes aws#9109 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
- Loading branch information
Showing
9 changed files
with
445 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './http-origin'; | ||
export * from './load-balancer-origin'; | ||
export * from './s3-origin'; | ||
export * from './origin-group'; |
49 changes: 49 additions & 0 deletions
49
packages/@aws-cdk/aws-cloudfront-origins/lib/origin-group.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import * as cloudfront from '@aws-cdk/aws-cloudfront'; | ||
import { Construct } from '@aws-cdk/core'; | ||
|
||
/** Construction properties for {@link OriginGroup}. */ | ||
export interface OriginGroupProps { | ||
/** | ||
* The primary origin that should serve requests for this group. | ||
*/ | ||
readonly primaryOrigin: cloudfront.IOrigin; | ||
|
||
/** | ||
* The fallback origin that should serve requests when the primary fails. | ||
*/ | ||
readonly fallbackOrigin: cloudfront.IOrigin; | ||
|
||
/** | ||
* The list of HTTP status codes that, | ||
* when returned from the primary origin, | ||
* would cause querying the fallback origin. | ||
* | ||
* @default - 500, 502, 503 and 504 | ||
*/ | ||
readonly fallbackStatusCodes?: number[]; | ||
} | ||
|
||
/** | ||
* An Origin that represents a group. | ||
* Consists of a primary Origin, | ||
* and a fallback Origin called when the primary returns one of the provided HTTP status codes. | ||
*/ | ||
export class OriginGroup implements cloudfront.IOrigin { | ||
public constructor(private readonly props: OriginGroupProps) { | ||
} | ||
|
||
public bind(scope: Construct, options: cloudfront.OriginBindOptions): cloudfront.OriginBindConfig { | ||
const primaryOriginConfig = this.props.primaryOrigin.bind(scope, options); | ||
if (primaryOriginConfig.failoverConfig) { | ||
throw new Error('An OriginGroup cannot use an Origin with its own failover configuration as its primary origin!'); | ||
} | ||
|
||
return { | ||
originProperty: primaryOriginConfig.originProperty, | ||
failoverConfig: { | ||
failoverOrigin: this.props.fallbackOrigin, | ||
statusCodes: this.props.fallbackStatusCodes, | ||
}, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
144 changes: 144 additions & 0 deletions
144
packages/@aws-cdk/aws-cloudfront-origins/test/integ.origin-group.expected.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
{ | ||
"Resources": { | ||
"Bucket83908E77": { | ||
"Type": "AWS::S3::Bucket", | ||
"UpdateReplacePolicy": "Delete", | ||
"DeletionPolicy": "Delete" | ||
}, | ||
"BucketPolicyE9A3008A": { | ||
"Type": "AWS::S3::BucketPolicy", | ||
"Properties": { | ||
"Bucket": { | ||
"Ref": "Bucket83908E77" | ||
}, | ||
"PolicyDocument": { | ||
"Statement": [ | ||
{ | ||
"Action": [ | ||
"s3:GetObject*", | ||
"s3:GetBucket*", | ||
"s3:List*" | ||
], | ||
"Effect": "Allow", | ||
"Principal": { | ||
"CanonicalUser": { | ||
"Fn::GetAtt": [ | ||
"DistributionOrigin1S3Origin5F5C0696", | ||
"S3CanonicalUserId" | ||
] | ||
} | ||
}, | ||
"Resource": [ | ||
{ | ||
"Fn::GetAtt": [ | ||
"Bucket83908E77", | ||
"Arn" | ||
] | ||
}, | ||
{ | ||
"Fn::Join": [ | ||
"", | ||
[ | ||
{ | ||
"Fn::GetAtt": [ | ||
"Bucket83908E77", | ||
"Arn" | ||
] | ||
}, | ||
"/*" | ||
] | ||
] | ||
} | ||
] | ||
} | ||
], | ||
"Version": "2012-10-17" | ||
} | ||
} | ||
}, | ||
"DistributionOrigin1S3Origin5F5C0696": { | ||
"Type": "AWS::CloudFront::CloudFrontOriginAccessIdentity", | ||
"Properties": { | ||
"CloudFrontOriginAccessIdentityConfig": { | ||
"Comment": "Allows CloudFront to reach the bucket" | ||
} | ||
} | ||
}, | ||
"DistributionCFDistribution882A7313": { | ||
"Type": "AWS::CloudFront::Distribution", | ||
"Properties": { | ||
"DistributionConfig": { | ||
"DefaultCacheBehavior": { | ||
"ForwardedValues": { | ||
"QueryString": false | ||
}, | ||
"TargetOriginId": "cloudfrontorigingroupDistributionOrigin137659A54", | ||
"ViewerProtocolPolicy": "allow-all" | ||
}, | ||
"Enabled": true, | ||
"OriginGroups": { | ||
"Items": [ | ||
{ | ||
"FailoverCriteria": { | ||
"StatusCodes": { | ||
"Items": [ | ||
500, | ||
502, | ||
503, | ||
504 | ||
], | ||
"Quantity": 4 | ||
} | ||
}, | ||
"Id": "cloudfrontorigingroupDistributionOriginGroup10B57F1D1", | ||
"Members": { | ||
"Items": [ | ||
{ | ||
"OriginId": "cloudfrontorigingroupDistributionOrigin137659A54" | ||
}, | ||
{ | ||
"OriginId": "cloudfrontorigingroupDistributionOrigin2CCE5D500" | ||
} | ||
], | ||
"Quantity": 2 | ||
} | ||
} | ||
], | ||
"Quantity": 1 | ||
}, | ||
"Origins": [ | ||
{ | ||
"DomainName": { | ||
"Fn::GetAtt": [ | ||
"Bucket83908E77", | ||
"RegionalDomainName" | ||
] | ||
}, | ||
"Id": "cloudfrontorigingroupDistributionOrigin137659A54", | ||
"S3OriginConfig": { | ||
"OriginAccessIdentity": { | ||
"Fn::Join": [ | ||
"", | ||
[ | ||
"origin-access-identity/cloudfront/", | ||
{ | ||
"Ref": "DistributionOrigin1S3Origin5F5C0696" | ||
} | ||
] | ||
] | ||
} | ||
} | ||
}, | ||
{ | ||
"CustomOriginConfig": { | ||
"OriginProtocolPolicy": "https-only" | ||
}, | ||
"DomainName": "www.example.com", | ||
"Id": "cloudfrontorigingroupDistributionOrigin2CCE5D500" | ||
} | ||
] | ||
} | ||
} | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
packages/@aws-cdk/aws-cloudfront-origins/test/integ.origin-group.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import * as cloudfront from '@aws-cdk/aws-cloudfront'; | ||
import * as s3 from '@aws-cdk/aws-s3'; | ||
import * as cdk from '@aws-cdk/core'; | ||
import * as origins from '../lib'; | ||
|
||
const app = new cdk.App(); | ||
const stack = new cdk.Stack(app, 'cloudfront-origin-group'); | ||
|
||
const bucket = new s3.Bucket(stack, 'Bucket', { | ||
removalPolicy: cdk.RemovalPolicy.DESTROY, | ||
}); | ||
|
||
const originGroup = new origins.OriginGroup({ | ||
primaryOrigin: new origins.S3Origin(bucket), | ||
fallbackOrigin: new origins.HttpOrigin('www.example.com'), | ||
}); | ||
|
||
new cloudfront.Distribution(stack, 'Distribution', { | ||
defaultBehavior: { origin: originGroup }, | ||
}); | ||
|
||
app.synth(); |
142 changes: 142 additions & 0 deletions
142
packages/@aws-cdk/aws-cloudfront-origins/test/origin-group.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import '@aws-cdk/assert/jest'; | ||
import * as cloudfront from '@aws-cdk/aws-cloudfront'; | ||
import * as s3 from '@aws-cdk/aws-s3'; | ||
import { Stack } from '@aws-cdk/core'; | ||
import * as origins from '../lib'; | ||
|
||
let stack: Stack; | ||
let bucket: s3.IBucket; | ||
let primaryOrigin: cloudfront.IOrigin; | ||
beforeEach(() => { | ||
stack = new Stack(); | ||
bucket = new s3.Bucket(stack, 'Bucket'); | ||
primaryOrigin = new origins.S3Origin(bucket); | ||
}); | ||
|
||
describe('Origin Groups', () => { | ||
test('correctly render the OriginGroups property of DistributionConfig', () => { | ||
const failoverOrigin = new origins.S3Origin(s3.Bucket.fromBucketName(stack, 'ImportedBucket', 'imported-bucket')); | ||
const originGroup = new origins.OriginGroup({ | ||
primaryOrigin, | ||
fallbackOrigin: failoverOrigin, | ||
fallbackStatusCodes: [500], | ||
}); | ||
|
||
new cloudfront.Distribution(stack, 'Distribution', { | ||
defaultBehavior: { origin: originGroup }, | ||
}); | ||
|
||
const primaryOriginId = 'DistributionOrigin13547B94F'; | ||
const failoverOriginId = 'DistributionOrigin2C85CC43B'; | ||
expect(stack).toHaveResourceLike('AWS::CloudFront::Distribution', { | ||
DistributionConfig: { | ||
Origins: [ | ||
{ | ||
Id: primaryOriginId, | ||
DomainName: { | ||
'Fn::GetAtt': ['Bucket83908E77', 'RegionalDomainName'], | ||
}, | ||
S3OriginConfig: { | ||
OriginAccessIdentity: { | ||
'Fn::Join': ['', [ | ||
'origin-access-identity/cloudfront/', | ||
{ Ref: 'DistributionOrigin1S3Origin5F5C0696' }, | ||
]], | ||
}, | ||
}, | ||
}, | ||
{ | ||
Id: failoverOriginId, | ||
DomainName: { | ||
'Fn::Join': ['', [ | ||
'imported-bucket.s3.', | ||
{ Ref: 'AWS::Region' }, | ||
'.', | ||
{ Ref: 'AWS::URLSuffix' }, | ||
]], | ||
}, | ||
S3OriginConfig: { | ||
OriginAccessIdentity: { | ||
'Fn::Join': ['', [ | ||
'origin-access-identity/cloudfront/', | ||
{ Ref: 'DistributionOrigin2S3OriginE484D4BF' }, | ||
]], | ||
}, | ||
}, | ||
}, | ||
], | ||
OriginGroups: { | ||
Items: [ | ||
{ | ||
FailoverCriteria: { | ||
StatusCodes: { | ||
Items: [500], | ||
Quantity: 1, | ||
}, | ||
}, | ||
Id: 'DistributionOriginGroup1A1A31B49', | ||
Members: { | ||
Items: [ | ||
{ OriginId: primaryOriginId }, | ||
{ OriginId: failoverOriginId }, | ||
], | ||
Quantity: 2, | ||
}, | ||
}, | ||
], | ||
Quantity: 1, | ||
}, | ||
}, | ||
}); | ||
}); | ||
|
||
test('cannot have an Origin with their own failover configuration as the primary Origin', () => { | ||
const failoverOrigin = new origins.S3Origin(s3.Bucket.fromBucketName(stack, 'ImportedBucket', 'imported-bucket')); | ||
const originGroup = new origins.OriginGroup({ | ||
primaryOrigin, | ||
fallbackOrigin: failoverOrigin, | ||
}); | ||
const groupOfGroups = new origins.OriginGroup({ | ||
primaryOrigin: originGroup, | ||
fallbackOrigin: failoverOrigin, | ||
}); | ||
|
||
expect(() => { | ||
new cloudfront.Distribution(stack, 'Distribution', { | ||
defaultBehavior: { origin: groupOfGroups }, | ||
}); | ||
}).toThrow(/An OriginGroup cannot use an Origin with its own failover configuration as its primary origin!/); | ||
}); | ||
|
||
test('cannot have an Origin with their own failover configuration as the fallback Origin', () => { | ||
const originGroup = new origins.OriginGroup({ | ||
primaryOrigin, | ||
fallbackOrigin: new origins.S3Origin(s3.Bucket.fromBucketName(stack, 'ImportedBucket', 'imported-bucket')), | ||
}); | ||
const groupOfGroups = new origins.OriginGroup({ | ||
primaryOrigin, | ||
fallbackOrigin: originGroup, | ||
}); | ||
|
||
expect(() => { | ||
new cloudfront.Distribution(stack, 'Distribution', { | ||
defaultBehavior: { origin: groupOfGroups }, | ||
}); | ||
}).toThrow(/An Origin cannot use an Origin with its own failover configuration as its fallback origin!/); | ||
}); | ||
|
||
test('cannot have an empty array of fallbackStatusCodes', () => { | ||
const failoverOrigin = new origins.S3Origin(s3.Bucket.fromBucketName(stack, 'ImportedBucket', 'imported-bucket')); | ||
const originGroup = new origins.OriginGroup({ | ||
primaryOrigin, | ||
fallbackOrigin: failoverOrigin, | ||
fallbackStatusCodes: [], | ||
}); | ||
|
||
expect(() => { | ||
new cloudfront.Distribution(stack, 'Distribution', { | ||
defaultBehavior: { origin: originGroup }, | ||
}); | ||
}).toThrow(/fallbackStatusCodes cannot be empty/); | ||
}); | ||
}); |
Oops, something went wrong.