commit
a338ef4d47
|
@ -0,0 +1,62 @@
|
|||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/golang:latest
|
||||
environment:
|
||||
HUGO_VERSION: "0.53"
|
||||
S3DEPLOY_VERSION: "2.3.0"
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- install-v1-{{ checksum ".circleci/config.yml" }}
|
||||
- install-v1-
|
||||
- run:
|
||||
name: Make bin folder
|
||||
command: mkdir -p $HOME/bin
|
||||
- run:
|
||||
name: Install Hugo
|
||||
command: ./deploy/ci-install-hugo.sh
|
||||
- run:
|
||||
name: Install s3deploy
|
||||
command: ./deploy/ci-install-s3deploy.sh
|
||||
- save_cache:
|
||||
key: install-v1-{{ checksum ".circleci/config.yml" }}
|
||||
paths:
|
||||
- /home/circleci/bin
|
||||
- run:
|
||||
name: Hugo Build
|
||||
command: $HOME/bin/hugo -v --destination workspace/public
|
||||
- persist_to_workspace:
|
||||
root: workspace
|
||||
paths:
|
||||
- public
|
||||
|
||||
deploy:
|
||||
docker:
|
||||
- image: circleci/golang:latest
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- install-v1-{{ checksum ".circleci/config.yml" }}
|
||||
- install-v1-
|
||||
- attach_workspace:
|
||||
at: workspace
|
||||
- run:
|
||||
name: Deploy to S3
|
||||
command: $HOME/bin/s3deploy -source=workspace/public/ -bucket=$BUCKET -region=$REGION
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- build
|
||||
- deploy:
|
||||
requires:
|
||||
- build
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- ga-cf-templates
|
|
@ -1,7 +1,6 @@
|
|||
.DS_Store
|
||||
*~
|
||||
public
|
||||
deploy
|
||||
.*.swp
|
||||
node_modules
|
||||
*.log
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
routes:
|
||||
- route: "^.+\\.(js|css|svg|ttf|png|jpg)$"
|
||||
# cache static assets for 20 years
|
||||
headers:
|
||||
Cache-Control: "max-age=630720000, no-transform, public"
|
||||
gzip: true
|
||||
- route: "^.+\\.(html|xml|json|js)$"
|
||||
gzip: true
|
|
@ -0,0 +1,16 @@
|
|||
# Deploying the InfluxData Docs
|
||||
|
||||
Use the following command to deploy a CloudFormation stack using the template in this directory.
|
||||
|
||||
```sh
|
||||
aws cloudformation deploy \
|
||||
--template-file docs-website.yml \
|
||||
--stack-name="${STACK_NAME}" \
|
||||
--capabilities CAPABILITY_IAM /
|
||||
--no-execute-changeset \
|
||||
--parameter-overrides \
|
||||
AcmCertificateArn="${ACM_ARN}" \
|
||||
DomainName="${DOMAIN_NAME}"
|
||||
```
|
||||
|
||||
The `--no-execute-changeset` option will display the actions that will be taken. Remove the `--no-execute-changeset` option to actually deploy a change.
|
|
@ -0,0 +1,11 @@
|
|||
HUGO_DOWNLOAD=hugo_extended_${HUGO_VERSION}_Linux-64bit.tar.gz
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
# Install Hugo if not already cached or upgrade an old version.
|
||||
if [ ! -e $HOME/bin/hugo ] || ! [[ `$HOME/bin/hugo version` =~ v${HUGO_VERSION} ]]; then
|
||||
wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/${HUGO_DOWNLOAD}
|
||||
tar xvzf ${HUGO_DOWNLOAD} hugo
|
||||
mv hugo $HOME/bin/hugo
|
||||
fi
|
|
@ -0,0 +1,11 @@
|
|||
S3DEPLOY_DOWNLOAD=s3deploy_${S3DEPLOY_VERSION}_Linux-64bit.tar.gz
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
# Install s3deploy if not already cached or upgrade an old version.
|
||||
if [ ! -e $HOME/bin/s3deploy ] || ! [[ `$HOME/bin/s3deploy -V` =~ ${S3DEPLOY_VERSION} ]]; then
|
||||
wget https://github.com/bep/s3deploy/releases/download/v${S3DEPLOY_VERSION}/${S3DEPLOY_DOWNLOAD}
|
||||
tar xvzf ${S3DEPLOY_DOWNLOAD} s3deploy
|
||||
mv s3deploy $HOME/bin/s3deploy
|
||||
fi
|
|
@ -0,0 +1,230 @@
|
|||
###############################################################################
|
||||
### AWS Cloudformation Template
|
||||
### InfluxData Documentation Website Hosting and Deployment
|
||||
###############################################################################
|
||||
AWSTemplateFormatVersion: 2010-09-09
|
||||
Description: >
|
||||
Cloudformation template to stand up the AWS resources for hosting the
|
||||
InfluxData documentation static website created using Hugo. Cloudfront
|
||||
distribution is used to cache requests to an S3 bucket configured as a static
|
||||
website. A Lambda@Edge function rewrites requests with paths ending in
|
||||
index.html and requests to old v1 docs endpoints, which reside in a second
|
||||
bucket. Finally, a lambda is used to generate new versions of the docs using
|
||||
the GitHub source based on event and webhook triggers.
|
||||
|
||||
###############################################################################
|
||||
Parameters:
|
||||
###############################################################################
|
||||
|
||||
AcmCertificateArn:
|
||||
Type: String
|
||||
Description: >
|
||||
The ARN of the SSL certificate to use for the CloudFront distribution.
|
||||
|
||||
DomainName:
|
||||
Type: String
|
||||
Description: The website domain name.
|
||||
Default: dev.docs.influxdata.com
|
||||
|
||||
###############################################################################
|
||||
Outputs:
|
||||
###############################################################################
|
||||
|
||||
DocsProdBucketArn:
|
||||
Description: The ARN of the S3 bucket hosting the static content.
|
||||
Value: !GetAtt DocsV2Bucket.Arn
|
||||
Export:
|
||||
Name: !Sub ${AWS::StackName}-bucket-arn
|
||||
|
||||
###############################################################################
|
||||
Resources:
|
||||
###############################################################################
|
||||
|
||||
DocsCloudFrontDistribution:
|
||||
Type: AWS::CloudFront::Distribution
|
||||
Properties:
|
||||
DistributionConfig:
|
||||
Aliases:
|
||||
- !Ref DomainName
|
||||
DefaultCacheBehavior:
|
||||
Compress: true
|
||||
ForwardedValues:
|
||||
QueryString: false
|
||||
TargetOriginId: !Ref DocsV2Bucket
|
||||
ViewerProtocolPolicy: redirect-to-https
|
||||
LambdaFunctionAssociations:
|
||||
- EventType: origin-request
|
||||
LambdaFunctionARN: !Ref DocsOriginRequestRewriteLambdaVersion
|
||||
DefaultRootObject: index.html
|
||||
CustomErrorResponses:
|
||||
- ErrorCachingMinTTL: 300
|
||||
ErrorCode: 403
|
||||
ResponseCode: 404
|
||||
ResponsePagePath: /404.html
|
||||
Enabled: true
|
||||
HttpVersion: http2
|
||||
Origins:
|
||||
- DomainName:
|
||||
!Join [ "", [ !Ref DocsV2Bucket, ".s3.amazonaws.com" ] ]
|
||||
Id: !Ref DocsV2Bucket
|
||||
S3OriginConfig:
|
||||
OriginAccessIdentity:
|
||||
!Join [ "", [ "origin-access-identity/cloudfront/", !Ref DocsCloudFrontOriginAccessIdentity ] ]
|
||||
- DomainName:
|
||||
!Join [ "", [ !Ref DocsV1Bucket, ".s3.amazonaws.com" ] ]
|
||||
Id: !Ref DocsV1Bucket
|
||||
S3OriginConfig:
|
||||
OriginAccessIdentity:
|
||||
!Join [ "", [ "origin-access-identity/cloudfront/", !Ref DocsCloudFrontOriginAccessIdentity ] ]
|
||||
PriceClass: PriceClass_200
|
||||
ViewerCertificate:
|
||||
AcmCertificateArn: !Ref AcmCertificateArn
|
||||
MinimumProtocolVersion: TLSv1.1_2016
|
||||
SslSupportMethod: sni-only
|
||||
Tags:
|
||||
- Key: Domain
|
||||
Value: !Ref DomainName
|
||||
|
||||
DocsCloudFrontOriginAccessIdentity:
|
||||
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
|
||||
Properties:
|
||||
CloudFrontOriginAccessIdentityConfig:
|
||||
Comment: !Sub 'CloudFront Origin Access Identity for ${DomainName}'
|
||||
|
||||
DocsV2Bucket:
|
||||
Type: AWS::S3::Bucket
|
||||
Properties:
|
||||
BucketEncryption:
|
||||
ServerSideEncryptionConfiguration:
|
||||
-
|
||||
ServerSideEncryptionByDefault:
|
||||
SSEAlgorithm: AES256
|
||||
Tags:
|
||||
- Key: Domain
|
||||
Value: !Ref DomainName
|
||||
|
||||
DocsV2BucketPolicy:
|
||||
Type: AWS::S3::BucketPolicy
|
||||
Properties:
|
||||
Bucket: !Ref DocsV2Bucket
|
||||
PolicyDocument:
|
||||
Statement:
|
||||
-
|
||||
Action:
|
||||
- s3:GetObject
|
||||
Effect: Allow
|
||||
Resource: !Join [ "", [ "arn:aws:s3:::", !Ref DocsV2Bucket, "/*" ] ]
|
||||
Principal:
|
||||
CanonicalUser: !GetAtt DocsCloudFrontOriginAccessIdentity.S3CanonicalUserId
|
||||
|
||||
DocsV1Bucket:
|
||||
Type: AWS::S3::Bucket
|
||||
Properties:
|
||||
BucketEncryption:
|
||||
ServerSideEncryptionConfiguration:
|
||||
-
|
||||
ServerSideEncryptionByDefault:
|
||||
SSEAlgorithm: AES256
|
||||
Tags:
|
||||
- Key: Domain
|
||||
Value: !Ref DomainName
|
||||
|
||||
DocsV1BucketPolicy:
|
||||
Type: AWS::S3::BucketPolicy
|
||||
Properties:
|
||||
Bucket: !Ref DocsV1Bucket
|
||||
PolicyDocument:
|
||||
Statement:
|
||||
-
|
||||
Action:
|
||||
- s3:GetObject
|
||||
Effect: Allow
|
||||
Resource: !Join [ "", [ "arn:aws:s3:::", !Ref DocsV1Bucket, "/*" ] ]
|
||||
Principal:
|
||||
CanonicalUser: !GetAtt DocsCloudFrontOriginAccessIdentity.S3CanonicalUserId
|
||||
|
||||
DocsOriginRequestRewriteLambda:
|
||||
Type: AWS::Lambda::Function
|
||||
Properties:
|
||||
Description: >
|
||||
Lambda function performing request URI rewriting.
|
||||
Code:
|
||||
ZipFile: |
|
||||
const config = {
|
||||
suffix: '.html',
|
||||
appendToDirs: 'index.html',
|
||||
removeTrailingSlash: false,
|
||||
};
|
||||
|
||||
const regexSuffixless = /\/[^/.]+$/; // e.g. "/some/page" but not "/", "/some/" or "/some.jpg"
|
||||
const regexTrailingSlash = /.+\/$/; // e.g. "/some/" or "/some/page/" but not root "/"
|
||||
|
||||
exports.handler = function handler(event, context, callback) {
|
||||
const { request } = event.Records[0].cf;
|
||||
const { uri } = request;
|
||||
const { suffix, appendToDirs, removeTrailingSlash } = config;
|
||||
|
||||
// Append ".html" to origin request
|
||||
if (suffix && uri.match(regexSuffixless)) {
|
||||
request.uri = uri + suffix;
|
||||
callback(null, request);
|
||||
return;
|
||||
}
|
||||
|
||||
// Append "index.html" to origin request
|
||||
if (appendToDirs && uri.match(regexTrailingSlash)) {
|
||||
request.uri = uri + appendToDirs;
|
||||
callback(null, request);
|
||||
return;
|
||||
}
|
||||
|
||||
// Redirect (301) non-root requests ending in "/" to URI without trailing slash
|
||||
if (removeTrailingSlash && uri.match(/.+\/$/)) {
|
||||
const response = {
|
||||
// body: '',
|
||||
// bodyEncoding: 'text',
|
||||
headers: {
|
||||
'location': [{
|
||||
key: 'Location',
|
||||
value: uri.slice(0, -1)
|
||||
}]
|
||||
},
|
||||
status: '301',
|
||||
statusDescription: 'Moved Permanently'
|
||||
};
|
||||
callback(null, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// If nothing matches, return request unchanged
|
||||
callback(null, request);
|
||||
};
|
||||
Handler: index.handler
|
||||
MemorySize: 128
|
||||
Role: !Sub ${DocsOriginRequestRewriteLambdaRole.Arn}
|
||||
Runtime: nodejs8.10
|
||||
Tags:
|
||||
- Key: Domain
|
||||
Value: !Ref DomainName
|
||||
|
||||
DocsOriginRequestRewriteLambdaVersion:
|
||||
Type: AWS::Lambda::Version
|
||||
Properties:
|
||||
FunctionName: !Ref DocsOriginRequestRewriteLambda
|
||||
Description: !Sub "URL rewriting for ${DomainName}"
|
||||
|
||||
DocsOriginRequestRewriteLambdaRole:
|
||||
Type: AWS::IAM::Role
|
||||
Properties:
|
||||
AssumeRolePolicyDocument:
|
||||
Version: 2012-10-17
|
||||
Statement:
|
||||
- Effect: Allow
|
||||
Principal:
|
||||
Service:
|
||||
- edgelambda.amazonaws.com
|
||||
- lambda.amazonaws.com
|
||||
Action:
|
||||
- sts:AssumeRole
|
||||
ManagedPolicyArns:
|
||||
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
|
Loading…
Reference in New Issue