From 27c64029c5eaba7cce201df0442a14cb04447dc1 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 29 Dec 2017 08:23:49 -0500 Subject: [PATCH] Configure Travis for CI/CD from master to AWS Includes: * test that we can autodeploy the beanstalk branch, then swap config to master * add bucket_name (not included with travis setup) * configure with restricted account for travis * update docs --- .ebextensions/.gitignore | 5 + .ebextensions/01_packages.config | 32 +++++++ .ebextensions/02_python.config | 31 ++++++ .ebextensions/03_apache.config | 16 ++++ .ebextensions/04_logging.config | 5 + .ebextensions/05_elb.config | 6 ++ .ebextensions/enable_cache_headers.conf | 6 ++ .ebextensions/enable_mod_deflate.conf | 26 +++++ .elasticbeanstalk/config.yml | 20 ++++ .travis.yml | 36 ++++--- docs/docs.md | 7 ++ hamlet/settings/aws.py | 122 ++++++++++++++++++++++++ requirements.txt | 36 +++++++ 13 files changed, 335 insertions(+), 13 deletions(-) create mode 100644 .ebextensions/.gitignore create mode 100644 .ebextensions/01_packages.config create mode 100644 .ebextensions/02_python.config create mode 100644 .ebextensions/03_apache.config create mode 100644 .ebextensions/04_logging.config create mode 100644 .ebextensions/05_elb.config create mode 100644 .ebextensions/enable_cache_headers.conf create mode 100644 .ebextensions/enable_mod_deflate.conf create mode 100644 .elasticbeanstalk/config.yml create mode 100644 hamlet/settings/aws.py create mode 100644 requirements.txt diff --git a/.ebextensions/.gitignore b/.ebextensions/.gitignore new file mode 100644 index 0000000..bca646a --- /dev/null +++ b/.ebextensions/.gitignore @@ -0,0 +1,5 @@ + +# Elastic Beanstalk Files +.elasticbeanstalk/* +!.elasticbeanstalk/*.cfg.yml +!.elasticbeanstalk/*.global.yml diff --git a/.ebextensions/01_packages.config b/.ebextensions/01_packages.config new file mode 100644 index 0000000..f700b99 --- /dev/null +++ b/.ebextensions/01_packages.config @@ -0,0 +1,32 @@ +# Installing a file with wget feels a little YOLO, but this config requires a +# particular version of mod_wsgi to work, and that version isn't available via +# yum yet. See +# https://serverfault.com/questions/884469/mod-wsgi-call-to-site-addsitedir-failed-on-aws-elastic-beanstalk-python-3 . +packages: + yum: + git: [] + python36-virtualenv: [] + gcc: [] + gcc-c++: [] + postgresql96-devel: [] + httpd24-devel: [] +files: + "/tmp/update-wsgi.sh" : + mode: "000755" + owner: root + group: root + content: | + # update mod_wsgi + cd /tmp + wget -q "https://github.com/GrahamDumpleton/mod_wsgi/archive/4.4.21.tar.gz" && \ + tar -xzf '4.4.21.tar.gz' && \ + cd ./mod_wsgi-4.4.21 && \ + sudo ./configure --with-python=/usr/bin/python3.6 && \ + sudo make && \ + sudo make install && \ + sudo service httpd restart + +commands: + mod_wsgi_update: + command: /tmp/update-wsgi.sh + cwd: /tmp diff --git a/.ebextensions/02_python.config b/.ebextensions/02_python.config new file mode 100644 index 0000000..f8c4636 --- /dev/null +++ b/.ebextensions/02_python.config @@ -0,0 +1,31 @@ +--- +option_settings: + - namespace: aws:elasticbeanstalk:application:environment + option_name: DJANGO_SETTINGS_MODULE + value: hamlet.settings.aws + - option_name: PYTHONPATH + value: "/opt/python/current/app/hamlet:$PYTHONPATH" + - option_name: S3_MODELS_BUCKET + value: "s3://hamlet-models/" + - option_name: MODELS_DIR + value: /models + - namespace: aws:elasticbeanstalk:container:python + option_name: WSGIPath + value: hamlet/wsgi.py + - namespace: aws:elasticbeanstalk:container:python:staticfiles + option_name: /static/ + value: staticfiles/ + +container_commands: + 01_create_models_dir: + command: "sudo mkdir --mode=755 ${MODELS_DIR}" + test: '[ ! -d "${MODELS_DIR}" ]' + 02_sync_models_stored_in_s3: + command: "aws s3 sync ${S3_MODELS_BUCKET} ${MODELS_DIR}" + 03_migrate: + command: "source /opt/python/run/venv/bin/activate && python manage.py migrate --noinput" + leader_only: true + 04_collectstatic: + command: "source /opt/python/run/venv/bin/activate && python manage.py collectstatic --noinput" + 05_compress: + command: "source /opt/python/run/venv/bin/activate && python manage.py compress" diff --git a/.ebextensions/03_apache.config b/.ebextensions/03_apache.config new file mode 100644 index 0000000..39eaf3a --- /dev/null +++ b/.ebextensions/03_apache.config @@ -0,0 +1,16 @@ +container_commands: + 01_setup_apache: + command: "cp .ebextensions/enable_mod_deflate.conf /etc/httpd/conf.d/enable_mod_deflate.conf" + 02_setup_cache_headers: + command: "cp .ebextensions/enable_cache_headers.conf /etc/httpd/conf.d/enable_cache_headers.conf" + +files: + "/etc/httpd/conf.d/ssl_rewrite.conf": + mode: "000644" + owner: root + group: root + content: | + RewriteEngine On + + RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L] + diff --git a/.ebextensions/04_logging.config b/.ebextensions/04_logging.config new file mode 100644 index 0000000..d2025bd --- /dev/null +++ b/.ebextensions/04_logging.config @@ -0,0 +1,5 @@ +commands: + 01_change_permissions: + command: chmod g+s /opt/python/log + 02_change_owner: + command: chown root:wsgi /opt/python/log diff --git a/.ebextensions/05_elb.config b/.ebextensions/05_elb.config new file mode 100644 index 0000000..4367999 --- /dev/null +++ b/.ebextensions/05_elb.config @@ -0,0 +1,6 @@ +option_settings: + aws:elb:listener:443: + SSLCertificateId: arn:aws:acm:us-east-1:672626379771:certificate/4d482670-0299-47f3-8250-ca232c5d1bd2 + ListenerProtocol: HTTPS + InstancePort: 80 + diff --git a/.ebextensions/enable_cache_headers.conf b/.ebextensions/enable_cache_headers.conf new file mode 100644 index 0000000..d9f0a2c --- /dev/null +++ b/.ebextensions/enable_cache_headers.conf @@ -0,0 +1,6 @@ + + + Header set Cache-Control "max-age=31536000, public" + + + diff --git a/.ebextensions/enable_mod_deflate.conf b/.ebextensions/enable_mod_deflate.conf new file mode 100644 index 0000000..03ed556 --- /dev/null +++ b/.ebextensions/enable_mod_deflate.conf @@ -0,0 +1,26 @@ +# mod_deflate configuration + + # Restrict compression to these MIME types + AddOutputFilterByType DEFLATE text/plain + AddOutputFilterByType DEFLATE text/html + AddOutputFilterByType DEFLATE application/xhtml+xml + AddOutputFilterByType DEFLATE text/xml + AddOutputFilterByType DEFLATE application/xml + AddOutputFilterByType DEFLATE application/xml+rss + AddOutputFilterByType DEFLATE application/x-javascript + AddOutputFilterByType DEFLATE text/javascript + AddOutputFilterByType DEFLATE text/css + # Level of compression (Highest 9 - Lowest 1) + DeflateCompressionLevel 9 + # Netscape 4.x has some problems. + BrowserMatch ^Mozilla/4 gzip-only-text/html + # Netscape 4.06-4.08 have some more problems + BrowserMatch ^Mozilla/4\.0[678] no-gzip + # MSIE masquerades as Netscape, but it is fine + BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html + + # Make sure proxies don't deliver the wrong content + Header append Vary User-Agent env=!dont-vary + + + diff --git a/.elasticbeanstalk/config.yml b/.elasticbeanstalk/config.yml new file mode 100644 index 0000000..6f7e2a3 --- /dev/null +++ b/.elasticbeanstalk/config.yml @@ -0,0 +1,20 @@ +branch-defaults: + beanstalk: + environment: Hamtest +environment-defaults: + Hamtest: + branch: null + repository: null +global: + application_name: hamlet + default_ec2_keyname: mit-dornera + default_platform: arn:aws:elasticbeanstalk:us-east-1::platform/Python 3.6 running + on 64bit Amazon Linux/2.6.1 + default_region: us-east-1 + include_git_submodules: true + instance_profile: null + platform_name: null + platform_version: null + profile: null + sc: git + workspace_type: Application diff --git a/.travis.yml b/.travis.yml index c3db55b..8928ba6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,30 @@ language: python python: - - "3.6" +- '3.6' install: - - "pip install pipenv" - - "pip install coveralls" - - "pipenv install" -script: - coverage run manage.py test -after_success: - coveralls +- pip install pipenv +- pip install coveralls +- pipenv install +script: coverage run manage.py test +after_success: coveralls services: - - postgresql +- postgresql before_script: - - psql -c 'create database travis_ci_test;' -U postgres +- psql -c 'create database travis_ci_test;' -U postgres env: global: - - DJANGO_DB=travis_ci_test - - DJANGO_DB_USER=postgres - - DJANGO_SETTINGS_MODULE=hamlet.settings.test + - DJANGO_DB=travis_ci_test + - DJANGO_DB_USER=postgres + - DJANGO_SETTINGS_MODULE=hamlet.settings.test +deploy: + provider: elasticbeanstalk + access_key_id: AKIAJQXIO6JJ6FWT7HFQ + secret_access_key: # This is encrypted, so it's OK to have it here. + secure: JFotdLDjfTiRFlhmc1eWIT35kbocYizPgVu96bGZX1gvRudRY6x7SLsha2RPqv80ImkhWkfxhdxnCtvTUoprghk6YhA8Z28pz8BmdiZDT3i/AfGvtETSK5h7Z3Vm6wY3M37cz740+eL9rThlcElTGtz0KNtvnQglPiQJIJqaeTpMFVpV6DDYqiQd+sHo09Lyr709HsNTLq6m+AmlIrnG0keywZjQvwzg+9c73UJ1Z1iEgY0h6fAzHA4C83q1f/NUP1UBk0PFzjHNp0fcDv+Jyjl9BMx5bmz/ug7c6mlpRbTjKrS8ncvlQnR+wXSy1naFYhWJEAxRVmLqviY1PST1URFFOJoTR8bHPOWCV4jib7MFHDb0HW9U1n+6hYYRrJgvAdu9wSeShoRXBNGlX1PiL/xWbZOJFyWw6rLCCUimKci3gCfnGP/VVTlatnOm8P8J8lg6Oy4MypHfJzzhStdspj4BKfv1hQWKQbF1DRseInDjeiE29/wZ/osV7B37ArgBN2o2ikCB4kZnSlvex6zSSHZborgpSRLz36XUqhOaUcd0XbgFu5YVdyTzRjgUV0zFZKtFUqPv49kb9HboSv1D6gQV1gXtWyR8M+GL0B9mZ08om7nj0SMkbZSTNAa+PqyXwmbsYobSQa1llstCe3zuh5V5Sh4luz4uRfeAeqz2nAs= + region: us-east-1 + bucket_name: elasticbeanstalk-us-east-1-672626379771 + app: hamlet + env: hamtest + on: + repo: MITLibraries/hamlet + branch: master diff --git a/docs/docs.md b/docs/docs.md index 6fdddce..86b44e0 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -51,6 +51,13 @@ We tried to deploy on Heroku but the model file needs ~2GB of memory and that ge https://mitlibraries-hamlet.mit.edu/ +Environment Varibles defined in AWS for security reasons: +-All Database variables (these are standard and can put directly in your code) +-SECRET_KEY - will be created by TS3 or provided by developer securely + +All other variables are defined with the config files of the .ebextensions folder and can be changed/modified and or added to for future use. + + ### Deployment The goal is to have master autodeploy via Travis. Right now if you want something to be deployed, ask Andy. diff --git a/hamlet/settings/aws.py b/hamlet/settings/aws.py new file mode 100644 index 0000000..218c130 --- /dev/null +++ b/hamlet/settings/aws.py @@ -0,0 +1,122 @@ +import os +import sys + +from .base import * # noqa +from gensim.models.doc2vec import Doc2Vec + +# CHECK FOR EC2 TO ADD IP TO ALLOWED HOSTS +#----------------------------------------------------------------------------- +def is_ec2_linux(): + """Detect if we are running on an EC2 Linux Instance + See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/identify_ec2_instances.html + """ + if os.path.isfile("/sys/hypervisor/uuid"): + with open("/sys/hypervisor/uuid") as f: + uuid = f.read() + return uuid.startswith("ec2") + return False + +def get_linux_ec2_private_ip(): + """Get the private IP Address of the machine if running on an EC2 linux server""" + try: + from urllib2 import urlopen + except: + from urllib.request import urlopen + if not is_ec2_linux(): + return None + try: + response = urlopen('http://169.254.169.254/latest/meta-data/local-ipv4') + return response.read() + except: + return None + finally: + if response: + response.close() +#-------------------------------------------------------------------------- + + +# DATABASE CONFIGURATION +# ----------------------------------------------------------------------------- + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.environ['RDS_DB_NAME'], + 'USER': os.environ['RDS_USERNAME'], + 'PASSWORD': os.environ['RDS_PASSWORD'], + 'HOST': os.environ['RDS_HOSTNAME'], + 'PORT': os.environ['RDS_PORT'], + } +} + +# GENERAL CONFIGURATION +# ----------------------------------------------------------------------------- +#GET SECRET KEY FROM ENV VARIABLE +SECRET_KEY = os.environ ['SECRET_KEY'] + +# Honor the 'X-Forwarded-Proto' header for request.is_secure() +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') + + +ALLOWED_HOSTS = [ + '.compute-1.amazonaws.com', # allows viewing of instances directly + 'mitlibraries-hamlet.mit.edu', + 'localhost', + ] + +private_ip = get_linux_ec2_private_ip() +if private_ip: + ALLOWED_HOSTS.append(private_ip) + +# STATIC FILE CONFIGURATION +# ----------------------------------------------------------------------------- + +MIDDLEWARE.insert(1,'whitenoise.middleware.WhiteNoiseMiddleware') + +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') + +STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' + +COMPRESS_ENABLED = True +COMPRESS_OFFLINE = True + +#MODEL FILES STORED ON S3 +#MODELS_DIR IS AN ENV VARIABLE DEFINED IN EB AS /models +MODELS_DIR = os.environ.get('MODELS_DIR') +MODEL_FILE = os.path.join(MODELS_DIR, 'hamlet.model') +NEURAL_NET = Doc2Vec.load(MODEL_FILE) + +# LOGGING CONFIGURATION +# ----------------------------------------------------------------------------- + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'formatters': { + 'brief': { + 'format': '%(asctime)s %(levelname)s %(name)s[%(funcName)s]: %(message)s', # noqa + }, + }, + 'handlers': { + 'console_info': { + 'level': 'INFO', + 'class': 'logging.StreamHandler', + 'stream': sys.stdout + }, + }, + 'loggers': { + '': { + 'handlers': ['console_info'], + 'level': 'INFO', + } + } +} + +# Will be emailed by the management command about API usage. +ADMINS = [('Andromeda Yelton', 'm31@mit.edu')] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7da6c3e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,36 @@ +rjsmin==1.0.12 --hash=sha256:dd9591aa73500b08b7db24367f8d32c6470021f39d5ab4e50c7c02e4401386f1 +coverage==4.4.2 --hash=sha256:d1ee76f560c3c3e8faada866a07a32485445e16ed2206ac8378bd90dadffb9f0 --hash=sha256:007eeef7e23f9473622f7d94a3e029a45d55a92a1f083f0f3512f5ab9a669b05 --hash=sha256:17307429935f96c986a1b1674f78079528833410750321d22b5fb35d1883828e --hash=sha256:845fddf89dca1e94abe168760a38271abfc2e31863fbb4ada7f9a99337d7c3dc --hash=sha256:3f4d0b3403d3e110d2588c275540649b1841725f5a11a7162620224155d00ba2 --hash=sha256:4c4f368ffe1c2e7602359c2c50233269f3abe1c48ca6b288dcd0fb1d1c679733 --hash=sha256:f8c55dd0f56d3d618dfacf129e010cbe5d5f94b6951c1b2f13ab1a2f79c284da --hash=sha256:cdd92dd9471e624cd1d8c1a2703d25f114b59b736b0f1f659a98414e535ffb3d --hash=sha256:2ad357d12971e77360034c1596011a03f50c0f9e1ecd12e081342b8d1aee2236 --hash=sha256:e9a0e1caed2a52f15c96507ab78a48f346c05681a49c5b003172f8073da6aa6b --hash=sha256:eea9135432428d3ca7ee9be86af27cb8e56243f73764a9b6c3e0bda1394916be --hash=sha256:700d7579995044dc724847560b78ac786f0ca292867447afda7727a6fbaa082e --hash=sha256:66f393e10dd866be267deb3feca39babba08ae13763e0fc7a1063cbe1f8e49f6 --hash=sha256:5ff16548492e8a12e65ff3d55857ccd818584ed587a6c2898a9ebbe09a880674 --hash=sha256:d00e29b78ff610d300b2c37049a41234d48ea4f2d2581759ebcf67caaf731c31 --hash=sha256:87d942863fe74b1c3be83a045996addf1639218c2cb89c5da18c06c0fe3917ea --hash=sha256:358d635b1fc22a425444d52f26287ae5aea9e96e254ff3c59c407426f44574f4 --hash=sha256:81912cfe276e0069dca99e1e4e6be7b06b5fc8342641c6b472cb2fed7de7ae18 --hash=sha256:079248312838c4c8f3494934ab7382a42d42d5f365f0cf7516f938dbb3f53f3f --hash=sha256:b0059630ca5c6b297690a6bf57bf2fdac1395c24b7935fd73ee64190276b743b --hash=sha256:493082f104b5ca920e97a485913de254cbe351900deed72d4264571c73464cd0 --hash=sha256:e3ba9b14607c23623cf38f90b23f5bed4a3be87cbfa96e2e9f4eabb975d1e98b --hash=sha256:82cbd3317320aa63c65555aa4894bf33a13fb3a77f079059eb5935eea415938d --hash=sha256:9721f1b7275d3112dc7ccf63f0553c769f09b5c25a26ee45872c7f5c09edf6c1 --hash=sha256:bd4800e32b4c8d99c3a2c943f1ac430cbf80658d884123d19639bcde90dad44a --hash=sha256:f29841e865590af72c4b90d7b5b8e93fd560f5dea436c1d5ee8053788f9285de --hash=sha256:f3a5c6d054c531536a83521c00e5d4004f1e126e2e2556ce399bef4180fbe540 --hash=sha256:dd707a21332615108b736ef0b8513d3edaf12d2a7d5fc26cd04a169a8ae9b526 --hash=sha256:2e1a5c6adebb93c3b175103c2f855eda957283c10cf937d791d81bef8872d6ca --hash=sha256:f87f522bde5540d8a4b11df80058281ac38c44b13ce29ced1e294963dd51a8f8 --hash=sha256:a7cfaebd8f24c2b537fa6a271229b051cdac9c1734bb6f939ccfc7c055689baa --hash=sha256:309d91bd7a35063ec7a0e4d75645488bfab3f0b66373e7722f23da7f5b0f34cc --hash=sha256:0388c12539372bb92d6dde68b4627f0300d948965bbb7fc104924d715fdc0965 --hash=sha256:ab3508df9a92c1d3362343d235420d08e2662969b83134f8a97dc1451cbe5e84 --hash=sha256:43a155eb76025c61fc20c3d03b89ca28efa6f5be572ab6110b2fb68eda96bfea --hash=sha256:f98b461cb59f117887aa634a66022c0bd394278245ed51189f63a036516e32de --hash=sha256:b6cebae1502ce5b87d7c6f532fa90ab345cfbda62b95aeea4e431e164d498a3d --hash=sha256:a4497faa4f1c0fc365ba05eaecfb6b5d24e3c8c72e95938f9524e29dadb15e76 --hash=sha256:2b4d7f03a8a6632598cbc5df15bbca9f778c43db7cf1a838f4fa2c8599a8691a --hash=sha256:1afccd7e27cac1b9617be8c769f6d8a6d363699c9b86820f40c74cfb3328921c +django-appconf==1.0.2 --hash=sha256:ddab987d14b26731352c01ee69c090a4ebfc9141ed223bef039d79587f22acd9 --hash=sha256:6a4d9aea683b4c224d97ab8ee11ad2d29a37072c0c6c509896dd9857466fb261 +django-autocomplete-light==3.2.10 --hash=sha256:5ccb1c8c4b75cf72bc5dabd920190ea1ca3a340f56fb6b12d07a62202837fa75 +boto3==1.5.3 --hash=sha256:5f0e6f5c4e70bd226946073caef9b7e6fb715ed9af6887a77f3de3d8530514d7 --hash=sha256:19fc09ad1ad7f30880823d41f277b59f781190852c9cde0ad81c4ef6a1c2be2a +gevent==1.2.2 --hash=sha256:9b492bb1a043540abb6e54fdb5537531e24962ca49c09f3b47dc4f9c37f6297c --hash=sha256:de13a8e378103af84a8bf6015ad1d2761d46f29b8393e8dd6d9bb7cb51bbb713 --hash=sha256:deafd70d04ab62428d4e291e8e2c0fb22f38690e6a9f23a67ee6c304087634da --hash=sha256:b67a10799923f9fed546ca5f8b93a2819c71a60132d7a97b4a13fbdab66b278a --hash=sha256:35790f1a3c8e431ada3471b70bb2105050009ea4beb15cbe41b86bc716a7ffa9 --hash=sha256:c9dd6534c46ed782e2d7236767cd07115cb29ce8670c2fc0794f264de9024fe0 --hash=sha256:b7e0e6400c2f3ce78a9ae1cdd55b53166feedd003d60c033863881227129a4d3 --hash=sha256:0901975628790e8a57fc92bb7062e5b856edea48c8de9caf36cfda14eae07329 --hash=sha256:df52e06a2754c2d905aad75a7dc06a732c804d9edbc87f06f47c8f483ba98bca --hash=sha256:70558dd45c7a1f8046ba45792e489dd0f409bd8a3b7a0635ca9d3055223b3dff --hash=sha256:8a710eddb3e9e5f22bdbd458b5f211b94f59409ecd6896f15b9fee2cba266a59 --hash=sha256:60109741377367eef8ded9283a1bf629621b73acaf3e1e8aac9d1a0f50fa0f05 --hash=sha256:552719cec4721673b8c7d2f9de666e3f7591b9b182f801ecaef1c76e638052aa --hash=sha256:a16db4f56699ef07f0249b953ff949aae641e50b2bdc4710f11c0d8d9089b296 --hash=sha256:59e9237af027f8db85e5d78a9da2e328ae96f01d67a0d62abcecad3db7876908 --hash=sha256:833bebdc36bfeeedefc200ca9aee9b8eddd80f56b63ca1e886e18b97b1240edd --hash=sha256:81cb24e0f7bd9888596364e8d8ed0d65c2547c84884c67bb46d956faeed67396 --hash=sha256:1af93825db5753550fa8ff5ab2f2132e8733170b3f8d38347b34fa4a984cb624 --hash=sha256:2ff045a91509c35664c27a849c8cbf742a227f587b7cdbc88301e9c85dcaedff --hash=sha256:a66cf99f08da65c501826a19e30f5a6e7ba942fdd79baba5ce2d51eebaa13444 --hash=sha256:4791c8ae9c57d6f153354736e1ccab1e2baf6c8d9ae5a77a9ac90f41e2966b2d --hash=sha256:74bce0c30bb2240e3d5d515ba8cb3eadf840c2bde7109a1979c7a26c9d0f5a6a --hash=sha256:a0ed8ba787b9c0c1c565c2675d71652e6c1e2d4e91f53530860d0303e867fe85 --hash=sha256:c35b29de49211014ec66d056fd4f9ba7a04795e2a654697f72879c0cf365d6d4 --hash=sha256:6892fabc9051e8c0a171d543b6536859aabeb6d169db79b2f45d64dc2a15808c --hash=sha256:fce894a64db3911897cdad6c37fbb23dfb18b7bf8b9cb8c00a8ea0a7253651c9 --hash=sha256:4f098002126ebef7f2907188b6c8b09e5193161ce968847d9e6a8bc832b0db9a --hash=sha256:33fa6759eabc9176ddbe0d29b66867a82e19a61f06eb7cfabbac35343c0ecf24 --hash=sha256:7f93b67b680f4a921f517294048d05f8f6f0ed5962b78d6685a6cf0fcd7d8202 +jmespath==0.9.3 --hash=sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63 --hash=sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64 +botocore==1.8.17 --hash=sha256:fb68fc9f90c28ea8a3e855e154989b15ac810b1a261c6f0b893a064a9d6a81f2 --hash=sha256:8bcc7f5c835a27c250fac9ec2cb561f937be72a067739e3ca53a5a1cf41030b3 +django-libsass==0.7 --hash=sha256:49db3334b87e1f7955c4f9fb9945bc296f8bfd27a14d6d89706e4b0e5dc5de1c +psycopg2==2.7.3.2 --hash=sha256:594aa9a095de16614f703d759e10c018bdffeafce2921b8e80a0e8a0ebbc12e5 --hash=sha256:1cf5d84290c771eeecb734abe2c6c3120e9837eb12f99474141a862b9061ac51 --hash=sha256:0344b181e1aea37a58c218ccb0f0f771295de9aa25a625ed076e6996c6530f9e --hash=sha256:25250867a4cd1510fb755ef9cb38da3065def999d8e92c44e49a39b9b76bc893 --hash=sha256:317612d5d0ca4a9f7e42afb2add69b10be360784d21ce4ecfbca19f1f5eadf43 --hash=sha256:9d6266348b15b4a48623bf4d3e50445d8e581da413644f365805b321703d0fac --hash=sha256:ddca39cc55877653b5fcf59976d073e3d58c7c406ef54ae8e61ddf8782867182 --hash=sha256:988d2ec7560d42ef0ac34b3b97aad14c4f068792f00e1524fa1d3749fe4e4b64 --hash=sha256:7a9c6c62e6e05df5406e9b5235c31c376a22620ef26715a663cee57083b3c2ea --hash=sha256:7a75565181e75ba0b9fb174b58172bf6ea9b4331631cfe7bafff03f3641f5d73 --hash=sha256:94e4128ba1ea56f02522fffac65520091a9de3f5c00da31539e085e13db4771b --hash=sha256:92179bd68c2efe72924a99b6745a9172471931fc296f9bfdf9645b75eebd6344 --hash=sha256:b9358e203168fef7bfe9f430afaed3a2a624717a1d19c7afa7dfcbd76e3cd95c --hash=sha256:009e0bc09a57dbef4b601cb8b46a2abad51f5274c8be4bba276ff2884cd4cc53 --hash=sha256:d3ac07240e2304181ffdb13c099840b5eb555efc7be9344503c0c03aa681de79 --hash=sha256:40fa5630cd7d237cd93c4d4b64b9e5ed9273d1cfce55241c7f9066f5db70629d --hash=sha256:6c2f1a76a9ebd9ecf7825b9e20860139ca502c2bf1beabf6accf6c9e66a7e0c3 --hash=sha256:37f54452c7787dbdc0a634ca9773362b91709917f0b365ed14b831f03cbd34ba --hash=sha256:8f5942a4daf1ffac42109dc4a72f786af4baa4fa702ede1d7c57b4b696c2e7d6 --hash=sha256:bf708455cd1e9fa96c05126e89a0c59b200d086c7df7bbafc7d9be769e4149a3 --hash=sha256:82c40ea3ac1555e0462803380609fbe8b26f52620f3d4f8eb480cfd8ceed8a14 --hash=sha256:207ba4f9125a0a4200691e82d5eee7ea1485708eabe99a07fc7f08696fae62f4 --hash=sha256:0cd4c848f0e9d805d531e44973c8f48962e20eb7fc0edac3db4f9dbf9ed5ab82 --hash=sha256:57baf63aeb2965ca4b52613ce78e968b6d2bde700c97f6a7e8c6c236b51ab83e --hash=sha256:2954557393cfc9a5c11a5199c7a78cd9c0c793a047552d27b1636da50d013916 --hash=sha256:7c31dade89634807196a6b20ced831fbd5bec8a21c4e458ea950c9102c3aa96f --hash=sha256:1286dd16d0e46d59fa54582725986704a7a3f3d9aca6c5902a7eceb10c60cb7e --hash=sha256:697ff63bc5451e0b0db48ad205151123d25683b3754198be7ab5fcb44334e519 --hash=sha256:fc993c9331d91766d54757bbc70231e29d5ceb2d1ac08b1570feaa0c38ab9582 --hash=sha256:9d64fed2681552ed642e9c0cc831a9e95ab91de72b47d0cb68b5bf506ba88647 --hash=sha256:5c3213be557d0468f9df8fe2487eaf2990d9799202c5ff5cb8d394d09fad9b2a +six==1.11.0 --hash=sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb --hash=sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9 +libsass==0.13.4 --hash=sha256:ac3f331f6aa01e7e39bbb90d81b2c5005d44348bb292e9f199b58b4b88a11d9b --hash=sha256:c6d1d2417083528b2666ed777d822b710fe0a035d13449a35455c2772aadd056 --hash=sha256:1ead4bc795ecbc241814e49afb67aa470e4de4abb583b2b78259c57cd680c92c --hash=sha256:f2f173fb84fd86bbf81b2d4fd524564465a167eb993c8ca8f40fe0d123ff5232 --hash=sha256:628425f94b0f6f1ffb9a34ad083c116fa13e78c88dad9c486b6283d81c25e3ef --hash=sha256:8616e62f90fc799a5bbf6752cb857a9716d6c092f49842a0737795c534056f22 --hash=sha256:f2b79e0102d191dc0b51d4441e95bb6c511cf0250be2884cb5861b6ed510b289 --hash=sha256:4edd087648bed801c5df7b5d13440302e41316d83a7306f7cae16d1ac7b8acbc --hash=sha256:54321343e4bf6e3f7067b3e78a3f5f6968ed13867e8abba77f57dcb6fc06b54a --hash=sha256:814e6177940339471682f70723db831bda714e68af49cde66c85a41b58dc3e1c --hash=sha256:9f7c0ee9e0b949e7fe21882d56704fd9bd808f7984c82370e4825b3a25358fa7 --hash=sha256:1906045ad9a2518bf6ba2af3cc67a1485f924e6120aca01d7017447e512a7d64 --hash=sha256:113af1377418e87457636f3c9aa36486bf5283c62ac9bc00e4694f8e53c3802c +docutils==0.14 --hash=sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6 --hash=sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6 --hash=sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274 +django-compressor==2.2 --hash=sha256:7732676cfb9d58498dfb522b036f75f3f253f72ea1345ac036434fdc418c2e57 --hash=sha256:9616570e5b08e92fa9eadc7a1b1b49639cce07ef392fc27c74230ab08075b30f +rcssmin==1.0.6 --hash=sha256:ca87b695d3d7864157773a61263e5abb96006e9ff0e021eff90cbe0e1ba18270 +certifi==2017.11.5 --hash=sha256:244be0d93b71e93fc0a0a479862051414d0e00e16435707e5bf5000f92e04694 --hash=sha256:5ec74291ca1136b40f0379e1128ff80e866597e4e2c1e755739a913bbc3613c0 +numpy==1.13.3 --hash=sha256:910e7ae5eeee8d322775187692c5c66719cd58d230fbfd57245ea3cf75716910 --hash=sha256:f5c9ca457057cd5e12ddab36cded8b1f38bf1f45bf550d4ca2839b11ec57f597 --hash=sha256:d29e72413b66df23c75b9b469253c823698ea2e00f58e9e0df64b7a50696e8ac --hash=sha256:539345898a4ae17421c159ae2a350901a5e6ce3da8f24168c6c67b3536e13de8 --hash=sha256:929928932f91082a168e36984179deddd58f8e98822ad2f33a2955d7c4eec596 --hash=sha256:62b09f3d1ea01d79c16a6642cb21599f53b9338c59971b2418a573155d2202ec --hash=sha256:c4b1914d86c43399438518a2ac8bcba2fb64dd5a18efddded3783b9daae70933 --hash=sha256:6c6feb0647380db6e1d5d49ef9fb59c42240f25fb8df8b6e82ecb436c7e0621a --hash=sha256:da2f47e46d7a93b73891d1981378717dc73c6ad5cc4fd23c934bfea7847fa958 --hash=sha256:4c767b6d9c9a071bb36ea34eb240ee5192fe0bc4c13be5e6c51e0350a30f7ac0 --hash=sha256:b2f98838f4bbc3bf23af7e97ffcad18a2dc6bbb0726796781e02b9347af6685f --hash=sha256:11fcbed36c101a3b9c4636e791efccba82409ebbedaba938c97be8bdddd029cc --hash=sha256:8969c8f987f8bcc3e30c014532cfc20e4a8f86a50c361596e086310853adacb7 --hash=sha256:2875e8055a1ea8d933b1c9d0f8714c0aa11c097bfadfcb8564c4d868fbf09a41 --hash=sha256:09b87d652c03508447d0f618e1d3ae57595acd3e0f0c11ac91bf68ed7bdb3a28 --hash=sha256:9cad35b911e150f00bb8080950c7e9f172714bbd0234f5ab74b4e3e2d9288b37 --hash=sha256:479863de17f66810db00bccf35289555365da45d3b053ccf539b95ab3b9c24f6 --hash=sha256:b162c6b044960b4ea0f42be049ce2af1d18c60f82748f0a27bd5ad182a731bf3 --hash=sha256:fa656dccfa9141774440575a6e7875d08b93f4a332eb5ae40877b26bed291c01 --hash=sha256:7dfa5b49fb2a080bd0d39bfbcff1177bacb14fcb28c857fd65fd0c18938935de --hash=sha256:e8e0e75db757e41463888939d26c8058b4ecd25e563c597e9119f512dc0ee1da --hash=sha256:c8dc6aa96882df6323bf9545934e37c6e05959bd789ae4b14d50509b093907aa --hash=sha256:36ee86d5adbabc4fa2643a073f93d5504bdfed37a149a3a49f4dde259f35a750 +gunicorn==19.7.1 --hash=sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6 --hash=sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622 +urllib3==1.22 --hash=sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b --hash=sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f +pytz==2017.3 --hash=sha256:80af0f3008046b9975242012a985f04c5df1f01eed4ec1633d56cc47a75a6a48 --hash=sha256:feb2365914948b8620347784b6b6da356f31c9d03560259070b2f30cff3d469d --hash=sha256:59707844a9825589878236ff2f4e0dc9958511b7ffaae94dc615da07d4a68d33 --hash=sha256:d0ef5ef55ed3d37854320d4926b04a4cb42a2e88f71da9ddfdacfde8e364f027 --hash=sha256:c41c62827ce9cafacd6f2f7018e4f83a6f1986e87bfd000b8cfbd4ab5da95f1a --hash=sha256:8cc90340159b5d7ced6f2ba77694d946fc975b09f1a51d93f3ce3bb399396f94 --hash=sha256:dd2e4ca6ce3785c8dd342d1853dd9052b19290d5bf66060846e5dc6b8d6667f7 --hash=sha256:699d18a2a56f19ee5698ab1123bbcc1d269d061996aeb1eda6d89248d3542b82 --hash=sha256:fae4cffc040921b8a2d60c6cf0b5d662c1190fe54d718271db4eb17d44a185b7 +smart-open==1.5.5 --hash=sha256:9e2591241e92f552cf4225b1b70bbaeace0122fd9068bfc769567aeb947e1a4e +tika==1.15 --hash=sha256:ca9d4341aea64f9dcec349b3c68021d12cd9bb65b8f344fb7b94c1fa8c45979d --hash=sha256:41dd030375c4c5d6dfc24f0626ff1ccd57e6bac9f123c2bca33e3586993ed441 +python-dateutil==2.6.1 --hash=sha256:95511bae634d69bc7329ba55e646499a842bc4ec342ad54a8cdb65645a0aad3c --hash=sha256:891c38b2a02f5bb1be3e4793866c8df49c7d19baabf9c1bad62547e0b4866aca +bz2file==0.98 --hash=sha256:64c1f811e31556ba9931953c8ec7b397488726c63e09a4c67004f43bdd28da88 +gensim==3.2.0 --hash=sha256:6d60cc07a38a44afbff8e367b2dda07c47283778296fe610d9a462af04500adb --hash=sha256:92ff7882b75f061332d4791063b25995b3a5d80e20db28e5730143a8d4cb54c5 --hash=sha256:864b78dfb05a88364e7a0cdaaa27402bb5b083984eb2f0d20a07abbac9f6fa86 --hash=sha256:604e9119fb70a8471cdb17b3c26342ebc736afe7d5bda64709bb875e7d61a62e --hash=sha256:9ea7ec096f32a45d77c80fa184cd01ecd97b9bde23290716580cbf9b36ef52ff --hash=sha256:6d958f758999580c718b1e81e481661cd27ae868db7c75f3f3d46359a236d5d1 --hash=sha256:849fe53a478f089e84884780ce4ec8df062822756ff803839c33efced87c38ae --hash=sha256:b1910c34c366dc37c0032b539b16c3096c286b5722d39cb5ef1d4381ac99e3b1 --hash=sha256:1f0769fd1fb2d1d242742445fb071fc56f449a4bf5c03d1144e056f48fe6f9f8 --hash=sha256:6ac0caed58fa497d6865222233dd1ab692550fff0df98999d0248c3e96213d7f --hash=sha256:cf41d6733f542a6ec2bbc7ba52d331748446aa8f9024386e01ed44493d2b0b82 --hash=sha256:ff63f5824aa05bb237b47c1076ead327bc215350f63d10d467d0c1b389c09d50 --hash=sha256:de2aac640120a23cb8240f9c42e6ecaac73e854e1bd5c51a28d8cc2d79e06abd --hash=sha256:3a65dfffa8a426a37465995723d6c4d9e64f713fab95fecf9eae536c87e7dfd9 --hash=sha256:79e3a0d29aa0f2962f1cfbc3b4181bbbcafdf5d034be2b6d40fd2bb827681546 --hash=sha256:ee697a69002b84ed8c4d1fbea8ec8a5789b1245265043a0a8f77d53396637f78 --hash=sha256:5ff568b5c40433c577ddc6a14614166848865168776648fc75091cf772f146f2 --hash=sha256:db00b68c6567ba0598d400b917c889e8801adf249170ce0a80ec38187d1b0797 --hash=sha256:affb4af6f76f848ff41ffe972cb885f2bf774f3ed46a72e304d95971a5462e16 --hash=sha256:71a28be2663cd9b115ea4f2c4397435270adefdbcdd34dc3d267be791b196403 --hash=sha256:e181ec9b254dea6987169342c7f8ede6fbf62af4e58fd3bcb53de1bc1916901b --hash=sha256:b1ab55a0ebfcf31d39ddda58bc68f0c38e9900f72b855449a86f1edf0ce0f3ed --hash=sha256:a86990e9c231822862549f0e9d75bdea4c242114f9d1399822c4b52177d1de3c --hash=sha256:8a0e465e4e7e09ddf07ea372da685ab058a1435eacc75b10ccee8caf25bcc276 +greenlet==0.4.12 --hash=sha256:96888e47898a471073b394ea641b7d675c1d054c580dd4a04a382bd34e67d89e --hash=sha256:d2d5103f6cba131e1be660230018e21f276911d2b68b629ead1c5cb5e5472ac7 --hash=sha256:bc339de0e0969de5118d0b62a080a7611e2ba729a90f4a3ad78559c51bc5576d --hash=sha256:b8ab98f8ae25938326dc4c21e3689a933531500ae4f3bfcefe36e3e25fda4dbf --hash=sha256:416a3328d7e0a19aa1df3ec09524a109061fd7b80e010ef0dff9f695b4ac5e20 --hash=sha256:21232907c8c26838b16915bd8fbbf82fc70c996073464cc70981dd4a96bc841c --hash=sha256:6803d8c6b235c861c50afddf00c7467ffbcd5ab960d137ff0f9c36f2cb11ee4b --hash=sha256:76dab055476dd4dabb00a967b4df1990b25542d17eaa40a18f66971d10193e0b --hash=sha256:70b9ff28921f5a3c03df4896ec8c55f5f94c593d7a79abd98b4c5c4a692ba873 --hash=sha256:7114b757b4146f4c87a0f00f1e58abd4c4729836679af0fc37266910a4a72eb0 --hash=sha256:0d90c709355ed13f16676f84e5a9cd67826a9f5c5143381c21e8fc3100ade1f1 --hash=sha256:ebae83b6247f83b1e8d887733dfa8046ce6e29d8b3e2a7380256e9de5c6ae55d --hash=sha256:e841e3ece633acae5e2bf6102140a605ffee7d5d4921dca1625c5fdc0f0b3248 --hash=sha256:3e5e9be157ece49e4f97f3225460caf758ccb00f934fcbc5db34367cc1ff0aee --hash=sha256:e77b708c37b652c7501b9f8f6056b23633c567aaa0d29edfef1c11673c64b949 --hash=sha256:0da1fc809c3bdb93fbacd0f921f461aacd53e554a7b7d4e9953ba09131c4206e --hash=sha256:66fa5b101fcf4521138c1a29668074268d938bbb7de739c8faa9f92ea1f05e1f --hash=sha256:e5451e1ce06b74a4861576c2db74405a4398c4809a105774550a9e52cfc8c4da --hash=sha256:9c407aa6adfd4eea1232e81aa9f3cb3d9b955a9891c4819bf9b498c77efba14b --hash=sha256:b56ac981f07b77e72ad5154278b93396d706572ea52c2fce79fee2abfcc8bfa6 --hash=sha256:e4c99c6010a5d153d481fdaf63b8a0782825c0721506d880403a3b9b82ae347e +boto==2.48.0 --hash=sha256:13be844158d1bd80a94c972c806ec8381b9ea72035aa06123c5db6bc6a6f3ead --hash=sha256:deb8925b734b109679e3de65856018996338758f4b916ff4fe7bb62b6d7000d1 +s3transfer==0.1.12 --hash=sha256:23c156ca4d64b022476c92c44bf938bef71af9ce0dcd8fd6585e7bce52f66e47 --hash=sha256:10891b246296e0049071d56c32953af05cea614dca425a601e4c0be35990121e +django==1.11.8 --hash=sha256:fad46f44f6f4de66aacaa92e7753dbc4fe3ae834aa2daffaca0bf16c64798186 --hash=sha256:fed3e79bb5a3a8d5eb054c7a1ec1de229ef3f43335a67821cc3e489e9582f711 +scipy==1.0.0 --hash=sha256:70e6fc3f2f52c9152f05e27eb9bd8543cb862cacb71f8521a571e4ffb837f450 --hash=sha256:08041e5336fcd57defcc78650b44b3df652eff3e3a801638d894e50494fb630d --hash=sha256:ff8b6637d8d2c074ed67f3d57513e62f94747c6f1210f43e60ad3d8e93a424e4 --hash=sha256:5964dba6a3c0be226d44d2520de8fb4ba1501768bad57eec687d36d3f53b6254 --hash=sha256:bf36f3485e7b7291c36330a93bbfd4f5e8db23bbe4ea46c37b2839fef463f4e2 --hash=sha256:e3a5673c105eab802fdecb77f102d877352e201df9328698a265b7f57546b34b --hash=sha256:cd23894e1cc6eaa00e6807b6b12e4ca66d5ff092986c9c3eb01e97f24e2d6462 --hash=sha256:23a7238279ae94e088396b8b05a9795ef598dc79c5cd1adb91ad1ff87c7514fd --hash=sha256:3b66d5e40152175bca75cbbfd1eb5c108c50de9ae5625923f1c4f8f51cbe2dea --hash=sha256:fa17be6c66985931d3a391f61a6ba97c902585cf26020aa3eb24604115732d22 --hash=sha256:d84df0bc86bbdd49f0a6b6bad5cd62ccb02a3bfe546bf79263de44ae081bcd7b --hash=sha256:912499ddb521b7ac6287ac4ccf5f296a83d38996c2d04f43c9e62a91f7b420aa --hash=sha256:889602ead28054a15e8c26e1a6b8420d5a4fa777cfeb3ec98cfa52b9f317d153 --hash=sha256:5774adb6047983489bc81edaa72cd132e665e5680f0b2cf8ea28cd3b99e65d39 --hash=sha256:01c7040a83eb4e020ab729488637dcadef54cb728b035b76668ab92a72515d60 --hash=sha256:046705c604c6f1d63cad3e89677c0618b7abb40ed09a4c241c671a2d8e5128a9 --hash=sha256:1f58fbd59e8d9652759df0d137832ff2a325ed708c173cba20c86589d811c210 --hash=sha256:424500b2fe573d30de6dea927076c01acaadb3efb3d1f40340e8cc37151ccf27 --hash=sha256:97123a25216616723083942eb595f47fee18da6b637a88b803de5f078009003c --hash=sha256:a79b99b8b5af9a63312bd053bbb7bdb7710e6bbb9cc81617f9f6b9b1e49c72f8 --hash=sha256:9bd193686fd837472bdb6425486cb234ed0a4db76b930c141cc8d095ab213c8d --hash=sha256:a9e479648aab5f36330da94f351ebbfe79acb4e6f5e6ac6aeddc9291eb096839 --hash=sha256:87ea1f11a0e9ec08c264dc64551d501fa307289460705f6fccd84cbfc7926d10 +chardet==3.0.4 --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae +whitenoise==3.3.1 --hash=sha256:15f43b2e701821b95c9016cf469d29e2a546cb1c7dead584ba82c36f843995cf --hash=sha256:9d81515f2b5b27051910996e1e860b1332e354d9e7bcf30c98f21dcb6713e0dd +requests==2.18.4 --hash=sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b --hash=sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e +idna==2.6 --hash=sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4 --hash=sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f +nltk==3.2.5 --hash=sha256:2661f9971d983db314bbebd51ba770811a362c6597fd0f303bb1d3beadcb4834 --hash=sha256:8a3bad9ff7f67d2828a7915c2fab93e6ca910c2015ef40799e1805fccf2354e5 +dj-database-url==0.4.2 --hash=sha256:e16d94c382ea0564c48038fa7fe8d9c890ef1ab1a8ec4cb48e732c124b9482fd --hash=sha256:a6832d8445ee9d788c5baa48aef8130bf61fdc442f7d9a548424d25cd85c9f08