Skip to content

Commit 6e6e26f

Browse files
committed
Setup CloudFront distribution with SSL and pakaging.
1 parent 7e05ba9 commit 6e6e26f

File tree

9 files changed

+383
-47
lines changed

9 files changed

+383
-47
lines changed

01-webotron/Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pycodestyle = "*"
99
pylint = "*"
1010
pydocstyle = "*"
1111
pyflakes = "*"
12+
setuptools = "*"
1213

1314
[packages]
1415
boto3 = "*"

01-webotron/Pipfile.lock

Lines changed: 123 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

01-webotron/setup.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from setuptools import setup
2+
3+
setup(
4+
name='webotron-20',
5+
version='0.1',
6+
author='Ankit K Singh',
7+
author_email='er.ankit.cs@gmail.com',
8+
description='Webotron 20 is a tool to deploy static website to AWS.',
9+
license='GPLv3+',
10+
packages=['webotron'],
11+
url='https://github.com/erankitcs/automating-aws-with-python',
12+
install_requires=[
13+
'click',
14+
'boto3'
15+
],
16+
entry_points='''
17+
[console_scripts]
18+
webotron=webotron.webotron:cli
19+
'''
20+
)

01-webotron/webotron/bucket.py

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
import mimetypes
77
import boto3
88
from botocore.exceptions import ClientError
9-
import util
9+
from webotron import util
1010
from hashlib import md5
1111
from functools import reduce
1212

1313

1414
class BucketManager:
1515
"""Manage an S3 Bucket."""
16+
1617
CHUNK_SIZE = 8388608
1718

1819
def __init__(self, session):
@@ -104,24 +105,25 @@ def configure_website(self, bucket):
104105
)
105106

106107
def load_manifest(self, bucket):
107-
"""Load manifest for caching purpose"""
108+
"""Load manifest for caching purpose."""
108109
paginator = self.s3.meta.client.get_paginator('list_objects_v2')
109110
for page in paginator.paginate(Bucket=bucket.name):
110-
for obj in page.get('Contents',[]):
111+
for obj in page.get('Contents', []):
111112
self.manifest[obj['Key']] = obj['ETag']
113+
112114
@staticmethod
113115
def hash_data(data):
114-
"""Generate md5 hash for data"""
115-
hash=md5()
116+
"""Generate md5 hash for data."""
117+
hash = md5()
116118
hash.update(data)
117119
return hash
118120

119121
def gen_etag(self, path):
120-
"""Generate etag for file"""
122+
"""Generate etag for file."""
121123
hashes = []
122-
with open(path,'rb') as f:
124+
with open(path, 'rb') as f:
123125
while True:
124-
data=f.read(self.CHUNK_SIZE)
126+
data = f.read(self.CHUNK_SIZE)
125127
if not data:
126128
break
127129
hashes.append(self.hash_data(data))
@@ -132,21 +134,19 @@ def gen_etag(self, path):
132134
else:
133135
hash = self.hash_data(
134136
reduce(
135-
lambda x,y: x+y,
137+
lambda x, y: x+y,
136138
(
137139
h.digest() for h in hashes
138140
)
139141
)
140142
)
141-
return '"{}-{}"'.format(hash.hexdigest(),len(hashes))
142-
143-
143+
return '"{}-{}"'.format(hash.hexdigest(), len(hashes))
144144

145145
def upload_file(self, bucket, path, key):
146146
"""Upload path to S3 bucket with key."""
147147
content_type = mimetypes.guess_type(key)[0] or 'text/plain'
148148
etag = self.gen_etag(path)
149-
if self.manifest.get(key,'') == etag:
149+
if self.manifest.get(key, '') == etag:
150150
print("Skipping {}, etag match".format(key))
151151
return
152152
return bucket.upload_file(
@@ -158,21 +158,56 @@ def upload_file(self, bucket, path, key):
158158
Config=self.transfer_config
159159
)
160160

161+
def delete_files(self, bucket, objects):
162+
"""Delete files from given bucket."""
163+
response = bucket.delete_objects(
164+
Delete={
165+
'Objects': objects
166+
},
167+
RequestPayer='Webotron'
168+
)
169+
print(response)
170+
for item in response['Deleted']:
171+
print(
172+
'File has been successfully deleted : {}'.format(item['Key'])
173+
)
174+
if 'Errors' in response.keys():
175+
for item in response['Errors']:
176+
print(
177+
'Error in deleteFile : {} ,'
178+
'ErrorCode: {} , ErrorMsg: {}'.format(
179+
item['Key'], item['Code'], item['Message']
180+
)
181+
)
182+
161183
def sync(self, pathname, bucket_name):
162184
"""Sync contents of path to bucket."""
163185
bucket = self.s3.Bucket(bucket_name)
164186
root = Path(pathname).expanduser().resolve()
165187
self.load_manifest(bucket)
188+
self.file_list_source = []
166189

167190
def handle_directory(target):
168191
for p in target.iterdir():
169192
if p.is_dir():
170193
handle_directory(p)
171194
if p.is_file():
195+
self.file_list_source.append(
196+
str(p.relative_to(root).as_posix())
197+
)
172198
self.upload_file(
173199
bucket,
174200
str(p),
175201
str(p.relative_to(root).as_posix())
176202
)
177203

204+
def handle_bucket(directory_flist, bucket_keylist):
205+
files_delete = []
206+
for key in bucket_keylist.keys():
207+
if key not in directory_flist:
208+
key_dic = {'Key': key}
209+
files_delete.append(key_dic)
210+
self.delete_files(bucket, files_delete)
211+
178212
handle_directory(root)
213+
handle_bucket(self.file_list_source, self.manifest)

0 commit comments

Comments
 (0)