hello
Last active
March 30, 2024 18:56
-
-
Save jhw/fe1d085c37b6f7246b9e5f4fcbf850f4 to your computer and use it in GitHub Desktop.
Can you replicate an APIGWV1 website pattern with APIGWV2?
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
env | |
*.pyc | |
__pycache__ | |
tmp | |
setenv-priv.sh |
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
AppName=apigwv2-website-demo |
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
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation delete-stack --stack-name $AppName |
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
#!/usr/bin/env bash | |
. app.props | |
echo "DomainName: $DOMAIN_NAME" | |
echo "CertificateArn: $CERTIFICATE_ARN" | |
aws cloudformation deploy --stack-name $AppName --template-file stack.json --capabilities CAPABILITY_NAMED_IAM --parameter-overrides DomainName=$DOMAIN_NAME CertificateArn=$CERTIFICATE_ARN | |
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
from botocore.exceptions import ClientError | |
import boto3, os, re, sys, time | |
def fetch_log_events(logs, kwargs): | |
events, token = [], None | |
while True: | |
if token: | |
kwargs["nextToken"]=token | |
resp=logs.filter_log_events(**kwargs) | |
events+=resp["events"] | |
if "nextToken" in resp: | |
token=resp["nextToken"] | |
else: | |
break | |
return sorted(events, | |
key=lambda x: x["timestamp"]) | |
if __name__=="__main__": | |
try: | |
if len(sys.argv) < 3: | |
raise RuntimeError("please enter lambda name, window") | |
lambdaname, window = sys.argv[1:3] | |
if not re.search("^\\d+$", window): | |
raise RuntimeError("window is invalid") | |
window=int(window) | |
logs=boto3.client("logs") | |
starttime=int(1000*(time.time()-window)) | |
loggroupname="/aws/lambda/%s" % lambdaname | |
kwargs={"logGroupName": loggroupname, | |
"startTime": starttime, | |
"interleaved": True} | |
events=fetch_log_events(logs, kwargs) | |
for event in events: | |
msg=re.sub("\\r|\\n", "", event["message"]) | |
print (msg) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) |
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
from botocore.exceptions import ClientError | |
import boto3, os, re, sys | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
bucketkey=hungarorise("app-bucket") | |
if bucketkey not in outputs: | |
raise RuntimeError("bucket not found") | |
bucketname=outputs[bucketkey] | |
s3=boto3.client("s3") | |
paginator=s3.get_paginator("list_objects_v2") | |
pages=paginator.paginate(Bucket=bucketname) | |
for struct in pages: | |
if "Contents" in struct: | |
for obj in struct["Contents"]: | |
print (obj["Key"]) | |
s3.delete_object(Bucket=bucketname, | |
Key=obj["Key"]) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) |
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
import json, os | |
if __name__=="__main__": | |
if not os.path.exists("tmp"): | |
os.mkdir("tmp") | |
struct=json.loads(open("stack.json").read()) | |
with open("tmp/stack.json", 'w') as f: | |
f.write(json.dumps(struct, | |
indent=2)) |
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
<html> | |
<head> | |
<title>Hello World</title> | |
</head> | |
<body> | |
<div>Hello World!</div> | |
</body> | |
</html> |
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
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stack-events --stack-name $AppName --query "StackEvents[].{\"1.Timestamp\":Timestamp,\"2.Id\":LogicalResourceId,\"3.Type\":ResourceType,\"4.Status\":ResourceStatus,\"5.Reason\":ResourceStatusReason}" |
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
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stacks --stack-name $AppName --query 'Stacks[0].Outputs' --output table |
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
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stack-resources --stack-name $AppName --query "StackResources[].{\"1.Timestamp\":Timestamp,\"2.LogicalId\":LogicalResourceId,\"3.PhysicalId\":PhysicalResourceId,\"4.Type\":ResourceType,\"5.Status\":ResourceStatus}" |
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
#!/usr/bin/env bash | |
aws cloudformation describe-stacks --query "Stacks[].{\"1.Name\":StackName,\"2.Status\":StackStatus}" |
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
from botocore.exceptions import ClientError | |
import boto3, os, re, sys | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
bucketkey=hungarorise("app-bucket") | |
if bucketkey not in outputs: | |
raise RuntimeError("bucket not found") | |
bucketname=outputs[bucketkey] | |
s3=boto3.client("s3") | |
print (s3.put_object(Bucket=bucketname, | |
Key="index.html", | |
Body=open("index.html").read(), | |
ContentType="text/html")) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) |
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
awscli | |
boto3 | |
botocore | |
pyyaml | |
requests |
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
#!/usr/bin/env bash | |
export AWS_DEFAULT_OUTPUT=table | |
export AWS_PROFILE=#{your-aws-profile-here} | |
export CERTIFICATE_ARN=#{your-certificate-arn-here} | |
export DOMAIN_NAME=#{your-fully-qualified-domain-name-here} | |
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
{ | |
"Outputs": { | |
"AppBucket": { | |
"Value": { | |
"Ref": "AppBucket" | |
} | |
}, | |
"AppRestApi": { | |
"Value": { | |
"Ref": "AppRestApi" | |
} | |
} | |
}, | |
"Parameters": { | |
"CertificateArn": { | |
"Type": "String" | |
}, | |
"DomainName": { | |
"Type": "String" | |
} | |
}, | |
"Resources": { | |
"AppBasePathMapping": { | |
"Properties": { | |
"DomainName": { | |
"Ref": "DomainName" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"Stage": { | |
"Ref": "AppStage" | |
} | |
}, | |
"Type": "AWS::ApiGateway::BasePathMapping" | |
}, | |
"AppBucket": { | |
"Properties": { | |
"NotificationConfiguration": { | |
"EventBridgeConfiguration": { | |
"EventBridgeEnabled": true | |
} | |
} | |
}, | |
"Type": "AWS::S3::Bucket" | |
}, | |
"AppDeployment": { | |
"DependsOn": [ | |
"AppProxyMethod", | |
"AppRedirectMethod" | |
], | |
"Properties": { | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Deployment" | |
}, | |
"AppDomainName": { | |
"Properties": { | |
"CertificateArn": { | |
"Ref": "CertificateArn" | |
}, | |
"DomainName": { | |
"Ref": "DomainName" | |
} | |
}, | |
"Type": "AWS::ApiGateway::DomainName" | |
}, | |
"AppPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"s3:GetObject" | |
], | |
"Effect": "Allow", | |
"Resource": { | |
"Fn::Sub": "arn:aws:s3:::${AppBucket}/*" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "app-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "AppRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"AppProxyMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "GET", | |
"Integration": { | |
"Credentials": { | |
"Fn::GetAtt": [ | |
"AppRole", | |
"Arn" | |
] | |
}, | |
"IntegrationHttpMethod": "ANY", | |
"IntegrationResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Content-Type": "integration.response.header.Content-Type" | |
}, | |
"StatusCode": 200 | |
}, | |
{ | |
"SelectionPattern": "404", | |
"StatusCode": 404 | |
} | |
], | |
"PassthroughBehavior": "WHEN_NO_MATCH", | |
"RequestParameters": { | |
"integration.request.path.proxy": "method.request.path.proxy" | |
}, | |
"Type": "AWS", | |
"Uri": { | |
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:s3:path/${AppBucket}/{proxy}" | |
} | |
}, | |
"MethodResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Content-Type": true | |
}, | |
"StatusCode": 200 | |
}, | |
{ | |
"StatusCode": 404 | |
} | |
], | |
"RequestParameters": { | |
"method.request.path.proxy": true | |
}, | |
"ResourceId": { | |
"Ref": "AppResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppRecordSet": { | |
"Properties": { | |
"AliasTarget": { | |
"DNSName": { | |
"Fn::GetAtt": [ | |
"AppDomainName", | |
"DistributionDomainName" | |
] | |
}, | |
"EvaluateTargetHealth": false, | |
"HostedZoneId": { | |
"Fn::GetAtt": [ | |
"AppDomainName", | |
"DistributionHostedZoneId" | |
] | |
} | |
}, | |
"HostedZoneName": { | |
"Fn::Sub": [ | |
"${prefix}.${suffix}.", | |
{ | |
"prefix": { | |
"Fn::Select": [ | |
1, | |
{ | |
"Fn::Split": [ | |
".", | |
{ | |
"Ref": "DomainName" | |
} | |
] | |
} | |
] | |
}, | |
"suffix": { | |
"Fn::Select": [ | |
2, | |
{ | |
"Fn::Split": [ | |
".", | |
{ | |
"Ref": "DomainName" | |
} | |
] | |
} | |
] | |
} | |
} | |
] | |
}, | |
"Name": { | |
"Ref": "DomainName" | |
}, | |
"Type": "A" | |
}, | |
"Type": "AWS::Route53::RecordSet" | |
}, | |
"AppRedirectMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "GET", | |
"Integration": { | |
"IntegrationResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Location": { | |
"Fn::Sub": "'https://${DomainName}/index.html'" | |
} | |
}, | |
"ResponseTemplates": { | |
"application/json": "{}" | |
}, | |
"StatusCode": 302 | |
} | |
], | |
"RequestTemplates": { | |
"application/json": "{\"statusCode\" : 302}" | |
}, | |
"Type": "MOCK" | |
}, | |
"MethodResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Location": true | |
}, | |
"StatusCode": 302 | |
} | |
], | |
"ResourceId": { | |
"Fn::GetAtt": [ | |
"AppRestApi", | |
"RootResourceId" | |
] | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppResource": { | |
"Properties": { | |
"ParentId": { | |
"Fn::GetAtt": [ | |
"AppRestApi", | |
"RootResourceId" | |
] | |
}, | |
"PathPart": "{proxy+}", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Resource" | |
}, | |
"AppRestApi": { | |
"Properties": { | |
# "BinaryMediaTypes": ["*/*"], | |
"Name": { | |
"Fn::Sub": "app-rest-api-${AWS::StackName}" | |
} | |
}, | |
"Type": "AWS::ApiGateway::RestApi" | |
}, | |
"AppRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "apigateway.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"AppStage": { | |
"Properties": { | |
"DeploymentId": { | |
"Ref": "AppDeployment" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"StageName": "prod" | |
}, | |
"Type": "AWS::ApiGateway::Stage" | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment