-
Notifications
You must be signed in to change notification settings - Fork 0
/
hugo-cf-invalidation.py
127 lines (101 loc) · 4.04 KB
/
hugo-cf-invalidation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#!/usr/bin/python
#
# Copyright 2017 Oxalide
# Licensed under MIT
## modules
import sys, re, boto3, time, argparse
from botocore.exceptions import ClientError
## vars
urls = []
## main
print "Purge CloudFront from Hugo New Or Modified Content\n"
# parse distribution ID from argument
parser = argparse.ArgumentParser(description='Push invalidation request to CloudFront')
parser.add_argument('distributionId', metavar='ID', type=str, help='Target distribution ID')
parser.add_argument('--stsrole', dest='stsrole', type=str, default='0', help='ARN for sts:assmerole')
parser.add_argument('--prefix', dest='urlprefix', type=str, default='', help='Prefix URL with a string, ex: for /draft/index.html, prefix need to be "/draft"')
args = parser.parse_args()
print "DistributionID: "+ args.distributionId +"\n"
urlprefix = args.urlprefix if (args.urlprefix != "" ) else ""
# for each line from stdin, rewrite the correct path regarding the final URL
for line in sys.stdin:
if not line: break # quit switch
# ignore change of files used for building static content
excludes = [
re.compile('^(\..*)$'),
re.compile('(.*\.toml)$'),
re.compile('(archetypes/.*)'),
re.compile('(data/.*)'),
re.compile('(themes/.*/layouts/.*)'),
re.compile('(themes/.*/archetypes/.*)'),
re.compile('(themes/.*\.md)$'),
]
if any(regex.match(line) for regex in excludes):
continue
# match and format purge url
content = re.compile('^(content/)+')
static = re.compile('^(static/)+')
theme = re.compile('^(themes/hyde)(.*)+')
if content.match(line):
urls.append(urlprefix +"/post/"+ re.search("^(content/post/)(.*)(\.md)$",line).group(2) +"/")
urls.append(urlprefix +"/post/"+ re.search("^(content/post/)(.*)(\.md)$",line).group(2) +"/index.html")
if static.match(line):
urls.append(urlprefix +"/post/"+
re.search("^(static/post/)(.*)/(.*)$",line).group(2)
+"/"+
re.search("^(static/post/)(.*)/(.*)$",line).group(3)
)
if theme.match(line):
urls.append(urlprefix +"/"+ re.search("^(themes/hyde/)(.*)$",line).group(2))
# no change
if len(urls) == 0:
print "Nothing to do !"
exit(0)
# if there are change
else:
# also purge this objects if there is at leat a change on the site
urls.append(urlprefix +"/")
urls.append(urlprefix +"/index.html")
urls.append(urlprefix +"/index.xml")
urls.append(urlprefix +"/sitemap.xml")
print "Objects to invalidate:"
for url in urls:
print "\t"+ url
print
# connect to AWS and push invalidation request
try:
# use sts:assumerole if provided
if args.stsrole != '0':
# assume role
print "Use sts:assumerole => "+ args.stsrole + "\n"
sts_client = boto3.client('sts')
assumedRoleObject = sts_client.assume_role(
RoleArn=args.stsrole,
RoleSessionName="AssumeRoleHugoCFInvalidation"
)
# use new credentials to connect to cloudfront
client = boto3.client(
'cloudfront',
aws_access_key_id=assumedRoleObject['Credentials']['AccessKeyId'],
aws_secret_access_key=assumedRoleObject['Credentials']['SecretAccessKey'],
aws_session_token=assumedRoleObject['Credentials']['SessionToken'],
)
else:
# use "default" credentials to connect to cloudfront
client = boto3.client('cloudfront')
# push invalidation request to cloudfront
response = client.create_invalidation(
DistributionId=args.distributionId,
InvalidationBatch={
'Paths': {
'Quantity': len(urls),
'Items': urls
},
'CallerReference': str(time.time())
}
)
print "Invalidation status: "+ response['Invalidation']['Status'] +"\n"
exit(0)
except ClientError as e:
print "Unexpected error: %s\n" % e
exit(1)