added cloudformation stack and deployment script

This commit is contained in:
tmont 2021-09-13 15:09:18 -07:00
parent f912a34b59
commit 4b2b49e9d3
5 changed files with 2029 additions and 2 deletions

1783
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@
"devDependencies": {
"@fortawesome/fontawesome-free": "5.15.4",
"serve": "12.0.1",
"sql.js": "1.6.1"
"sql.js": "1.6.1",
"tail-stack-events": "2.1.0"
}
}

View File

@ -0,0 +1,86 @@
AWSTemplateFormatVersion: "2010-09-09"
Description: "genreviews site"
Resources:
GenreviewsSiteBucket:
Type: "AWS::S3::Bucket"
Properties:
BucketName: "genreviews.tmont.com"
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: false
IgnorePublicAcls: false
RestrictPublicBuckets: false
DeletionPolicy: Retain
GenreviewsSiteCachePolicy:
Type: "AWS::CloudFront::CachePolicy"
Properties:
CachePolicyConfig:
Comment: "Cache policy for genreviews.tmont.com distribution"
DefaultTTL: 300 # five minutes
MaxTTL: 31536000
MinTTL: 60
Name: "genreviews-cache-policy"
ParametersInCacheKeyAndForwardedToOrigin:
CookiesConfig:
CookieBehavior: none
EnableAcceptEncodingBrotli: true
EnableAcceptEncodingGzip: true
HeadersConfig:
HeaderBehavior: none
QueryStringsConfig:
QueryStringBehavior: none
GenreviewsSiteDistribution:
Type: "AWS::CloudFront::Distribution"
Properties:
DistributionConfig:
Aliases:
- genreviews.tmont.com
Comment: "Frontend proxy for genreviews.tmont.com"
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
CachePolicyId: !Ref GenreviewsSiteCachePolicy
Compress: true
TargetOriginId: s3-genreviews-bucket
ViewerProtocolPolicy: "redirect-to-https"
DefaultRootObject: "index.html"
Enabled: true
HttpVersion: http2
IPV6Enabled: true
Origins:
- DomainName: !GetAtt GenreviewsSiteBucket.RegionalDomainName
Id: s3-genreviews-bucket
S3OriginConfig:
OriginAccessIdentity: ""
ViewerCertificate:
AcmCertificateArn: "arn:aws:acm:us-east-1:592283802202:certificate/73845214-de19-46df-9504-d3c9995564b2"
MinimumProtocolVersion: "TLSv1"
SslSupportMethod: "sni-only"
Tags:
- Key: app
Value: genreviews
GenreviewsSiteDNS:
Type: "AWS::Route53::RecordSetGroup"
Properties:
Comment: "DNS for genreviews.tmont.com CloudFront proxy"
HostedZoneName: "tmont.com."
RecordSets:
- Name: genreviews.tmont.com
Type: "A"
AliasTarget:
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html#cfn-route53-aliastarget-hostedzoneid
HostedZoneId: "Z2FDTNDATAQYW2"
DNSName: !GetAtt GenreviewsSiteDistribution.DomainName
- Name: genreviews.tmont.com
Type: "AAAA"
AliasTarget:
HostedZoneId: "Z2FDTNDATAQYW2"
DNSName: !GetAtt GenreviewsSiteDistribution.DomainName

36
scripts/deploy.sh Executable file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -euo pipefail
readonly thisDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly rootDir="$(dirname "${thisDir}")"
main() {
SECONDS=0
echo "copying files to S3..."
aws s3 cp --recursive --acl public-read "${rootDir}/web/" s3://genreviews.tmont.com/
local distId
echo "querying for CloudFront distribution..."
distId=$(
aws cloudfront list-distributions \
--query "DistributionList.Items[?contains(Aliases.Items, 'genreviews.tmont.com')].Id | [0]" \
--output text
)
if [[ -z "${distId}" ]]; then
echo "failed to find cloudfront distribution"
exit 1
fi
echo "found distribution \"${distId}\", invalidating CloudFront cache..."
aws cloudfront create-invalidation \
--distribution-id "${distId}" \
--paths '/*'
echo "all done in ${SECONDS}s"
}
main "$@"

123
scripts/update-stack.sh Executable file
View File

@ -0,0 +1,123 @@
#!/bin/bash
set -euo pipefail
getStackAction() {
local stackName=$1
local region=$2
local command="create"
aws cloudformation describe-stacks \
--stack-name "${stackName}" \
--output text \
--region "${region}" &> /dev/null
# shellcheck disable=SC2181
if [[ $? -eq 0 ]]; then
command="update"
fi
echo "${command}"
}
checkError() {
# shellcheck disable=SC2181
if [[ $? -ne 0 ]]; then
echo "$1"
exit 1
fi
}
usage() {
cat << USAGE
Updates or creates a CloudFormation stack
Usage: $0 [--region region] template.yaml
Options:
--region region The region to create/update the stack in (us-west-2)
-h|--help Show this message
Example:
$0 path/to/template.yaml
USAGE
}
main() {
local cfnFile=
local region=us-west-2
parseArgs() {
while [[ $# -gt 0 ]]; do
local key="$1"
shift
case "${key}" in
-h | --help)
usage
exit 0
;;
--region)
region=$1
shift
;;
*)
if [[ -n "${cfnFile}" ]]; then
echo "only one template file allowed"
exit 1
fi
cfnFile="${key}"
;;
esac
done
}
parseArgs "$@"
if [[ ! -f "${cfnFile}" ]]; then
echo "template \"${cfnFile}\" does not exist"
exit 1
fi
local stackName
stackName=$(basename "${cfnFile%.*}")
local action
action=$(getStackAction "${stackName}" "${region}")
local command=
local extraOpts=
if [ "${action}" = "create" ]; then
command="create-stack"
extraOpts="--on-failure DO_NOTHING"
else
command="update-stack"
fi
local shouldContinue
read -r -p "${action} stack ${stackName} in ${region} (profile: ${AWS_PROFILE}), continue? [y/n] " shouldContinue
if [ "${shouldContinue}" != "y" ]; then
echo "ok bye"
exit
fi
aws cloudformation ${command} \
--stack-name "${stackName}" \
${extraOpts} \
--template-body "file://${cfnFile}" \
--region "${region}" \
> /dev/null
checkError "${command} failed"
echo
local -r tailStackEvents="node_modules/.bin/tail-stack-events"
if [ -x "${tailStackEvents}" ]; then
"${tailStackEvents}" --region "${region}" --stack-name "${stackName}" --die --outputs
fi
echo
echo "finished in ${SECONDS}s"
}
main "$@"