From 6e49f1e0970a74d857ec1a76a982151117cd5934 Mon Sep 17 00:00:00 2001 From: anya Date: Wed, 12 Sep 2018 22:29:12 +0300 Subject: [PATCH] Add project --- Docker/Dockerfile | 15 ++++ Docker/config/mydjango.conf | 17 +++++ Docker/docker-compose.yml | 35 +++++++++ Docker/entrypoint.sh | 17 +++++ Docker/systemd/celery.service | 7 ++ Docker/systemd/django.service | 7 ++ PUBLISH | 0 README.md | 22 ++++++ ansible/deploy.yaml | 27 +++++++ ansible/hosts | 5 ++ ansible/system.yaml | 8 +++ db.sqlite3 | Bin 0 -> 131072 bytes manage.py | 15 ++++ mysite/__init__.py | 7 ++ mysite/celery.py | 32 +++++++++ mysite/settings.py | 130 ++++++++++++++++++++++++++++++++++ mysite/urls.py | 23 ++++++ mysite/wsgi.py | 16 +++++ rates/__init__.py | 0 rates/admin.py | 3 + rates/apps.py | 5 ++ rates/migrations/__init__.py | 0 rates/models.py | 3 + rates/tasks.py | 20 ++++++ rates/tests.py | 11 +++ rates/views.py | 14 ++++ requirements.txt | 4 ++ 27 files changed, 443 insertions(+) create mode 100644 Docker/Dockerfile create mode 100644 Docker/config/mydjango.conf create mode 100644 Docker/docker-compose.yml create mode 100755 Docker/entrypoint.sh create mode 100644 Docker/systemd/celery.service create mode 100644 Docker/systemd/django.service create mode 100644 PUBLISH create mode 100644 ansible/deploy.yaml create mode 100644 ansible/hosts create mode 100644 ansible/system.yaml create mode 100644 db.sqlite3 create mode 100755 manage.py create mode 100644 mysite/__init__.py create mode 100644 mysite/celery.py create mode 100644 mysite/settings.py create mode 100644 mysite/urls.py create mode 100644 mysite/wsgi.py create mode 100644 rates/__init__.py create mode 100644 rates/admin.py create mode 100644 rates/apps.py create mode 100644 rates/migrations/__init__.py create mode 100644 rates/models.py create mode 100644 rates/tasks.py create mode 100644 rates/tests.py create mode 100644 rates/views.py create mode 100644 requirements.txt diff --git a/Docker/Dockerfile b/Docker/Dockerfile new file mode 100644 index 0000000..13eb148 --- /dev/null +++ b/Docker/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.6-alpine + +MAINTAINER Anna Sudnitsyna + +WORKDIR /usr/src/app +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt +RUN pip install gunicorn + +COPY . . + +ADD Docker/entrypoint.sh / + +EXPOSE 8000 +ENTRYPOINT /entrypoint.sh diff --git a/Docker/config/mydjango.conf b/Docker/config/mydjango.conf new file mode 100644 index 0000000..8e19165 --- /dev/null +++ b/Docker/config/mydjango.conf @@ -0,0 +1,17 @@ +upstream web { + ip_hash; + server web:8000; +} + +# portal +server { + location / { + proxy_pass http://web/; + } + location /static { + alias /src/static; + } + + listen 8000; + server_name localhost; +} \ No newline at end of file diff --git a/Docker/docker-compose.yml b/Docker/docker-compose.yml new file mode 100644 index 0000000..3411a7c --- /dev/null +++ b/Docker/docker-compose.yml @@ -0,0 +1,35 @@ +version: '2' +services: + nginx: + image: nginx:latest + container_name: ng02 + ports: + - "80:8000" + volumes: + - static-files:/src/static + - ./config:/etc/nginx/conf.d + depends_on: + - web + + redis: + image: redis + container_name: rd02 + ports: + - "6379:6379" + + web: + build: + context: ../ + dockerfile: Docker/Dockerfile + container_name: dg02 + volumes: + - static-files:/usr/src/app/static + expose: + - "8000" + depends_on: + - redis + + # command: bash -c "python3 manage.py collectstatic && gunicorn deplodock.wsgi --bind 0.0.0.0:8000" + +volumes: + static-files: \ No newline at end of file diff --git a/Docker/entrypoint.sh b/Docker/entrypoint.sh new file mode 100755 index 0000000..4e89853 --- /dev/null +++ b/Docker/entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +collect_static() { + python3 manage.py collectstatic --noinput +} + +run_gunicorn(){ + gunicorn mysite.wsgi --bind 0.0.0.0:8000 + } + +run_celery() { + celery -A mysite worker -l info -B +} + +collect_static && run_celery& + +run_gunicorn \ No newline at end of file diff --git a/Docker/systemd/celery.service b/Docker/systemd/celery.service new file mode 100644 index 0000000..0dd3cce --- /dev/null +++ b/Docker/systemd/celery.service @@ -0,0 +1,7 @@ +[Unit] +Description=Celery daemon for Django Project + +[Service] +WorkingDirectory=/usr/src/app +ExecStart=/usr/bin/celery -A mysite worker -l info -B +Restart=always \ No newline at end of file diff --git a/Docker/systemd/django.service b/Docker/systemd/django.service new file mode 100644 index 0000000..704a39c --- /dev/null +++ b/Docker/systemd/django.service @@ -0,0 +1,7 @@ +[Unit] +Description=Gunicorn daemon for Django Project + +[Service] +WorkingDirectory=/usr/src/app +ExecStart=/usr/bin/gunicorn mysite.wsgi --bind 0.0.0.0:8000 +Restart=always diff --git a/PUBLISH b/PUBLISH new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index b83ad91..354e6be 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,24 @@ # cb_parser +Application gets xml from https://www.cbr-xml-daily.ru/daily_utf8.xml once a day according to schedule and save data to redis. +Data is available at the main page. + +### Deploy: + +##### Docker: +```sh +docker-compose up --build -d [--force-recreate] +``` +(App started on localhost:80) + +##### Ansible: + +Update hosts file and run: +```sh +ansible-playbook -i hosts deploy.yaml +``` + +Tested on: +- Ubuntu 18.04 x64 +- Ubuntu 18.10 x64 +- Ubuntu 19.04 x64 diff --git a/ansible/deploy.yaml b/ansible/deploy.yaml new file mode 100644 index 0000000..75b41e3 --- /dev/null +++ b/ansible/deploy.yaml @@ -0,0 +1,27 @@ +--- +- hosts: all + gather_facts: no + tasks: +# Set up environment + - name: Running apt update + apt: update_cache=yes + - name: Enable ru_RU.UTF-8 + lineinfile: dest=/etc/locale.gen line='ru_RU.UTF-8 UTF-8' + - name: Gen locale + command: locale-gen + - name: Installing required packages + apt: name={{item}} state=present + with_items: + - python3-pip + - docker.io + - name: install compose + pip: + name: docker-compose + executable: pip3 +# Deploy project + - name: copy files + synchronize: src=/home/anya/PycharmProjects/cb_parser_celery/mysite dest=/src + - name: run the service defined in my_project's docker-compose.yml + docker_service: + build: yes + project_src: /src/mysite/Docker diff --git a/ansible/hosts b/ansible/hosts new file mode 100644 index 0000000..45ae915 --- /dev/null +++ b/ansible/hosts @@ -0,0 +1,5 @@ +[py3-hosts] +root ansible_ssh_host=188.166.64.76 ansible_ssh_user=root privatekeyfile=~/.ssh/id_rsa_do + +[py3-hosts:vars] +ansible_python_interpreter=/usr/bin/python3 \ No newline at end of file diff --git a/ansible/system.yaml b/ansible/system.yaml new file mode 100644 index 0000000..ca20d70 --- /dev/null +++ b/ansible/system.yaml @@ -0,0 +1,8 @@ +--- + - hosts: all + gather_facts: no + tasks: + - name: Read SSH public key + slurp: src=~/.ssh/id_rsa_do.pub + register: public_key +# debug: msg="{{ public_key['content'] | b64decode }}" \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..883ebe5efb9999e72941eebc0fdc645d5bc96349 GIT binary patch literal 131072 zcmeI*TWlj&83*tgdu-=spIkOOrMn@Hce7oS-Nxf<+*P6JHr-9To9*7zu23}{+Y_(1 zzOC(ScVAkZR#nACJRnfvp@0Mk@l<%=rLB-EZUPAes#K^dfsm*GajAIe13Ylf@r-9Y zo@7Im(lq?Ns^ghC=R4p0&RjBcrt!t|XG$$Syjp8iv{pDFj0&PC+!qcDf^dZX$9|fx zd+7(soS;8N+vklw9ue+7__B``CjVk(|FH`KKzeJg9tmRi*+x?0h0s%5=eY+ZE?6w788lm|y>po?ap z1$!VCZ3}VInM5{|e0Z3~dEAVXG2-0N%B6zVsx_LbRw$@?qfu+96}qNcQE$2>l}@A+ ziPYi{4Yq6sOREk2`dX=>tNB{BrB_?6TXnsu()EtJhKR*digN!T4e_uUB4uAM4pgoc zOI5YHR(3^BEi9yCiTegEO%_#F8 z3PEdhHu_B~#A%W-B_q=HoprA7<`tEAD!ULQpA~%MX@UHiyg|N2en6h46L>)Y0uX=z z1Rwwb2tWV=5P$##Ah3f1Bg5Y50d|$oZ)nlLce)3cC2vA3T+^z>nt5x8-@EWn_`Gu> z4`AIT8K3ZYj}I87`F#tO-m{n#z4K;>N~ze;TI?QNXoxoGC!Z0>-^tI(TjVwJH9CP8 z1Rwwb2tWV=5P$##AOHafKmY>om%u)0>VRlI9Ao_SACzVfiT1}BY@dBWX>yWZ{j-NO zq>wZz^QmH^wpRB}NRu;s(z-L?8I$CxL4HfXe2RfR|L-TC7RcYoZ^_TdtK_S60xt+a z00Izz00bZa0SG_<0uX=z1l}is3BM#v9dKO#AMi=S>>=AVf7AAPM3RKbNjCb=uK$Bx zIwi9ye*Hi0p_4Og(z^a16D2{O>bd@B$H_zF1c?%v zh@n4)ei?c#^le%QF9<*Y0uX=z1Rwwb2tWV=5P-nW3G9=^sOT@~Wxb`V#`W-cXJ-B? zeFVNcb8Ji!4~c&E_ZEy|qjyN6BKnNFwo7HwSzy$+EeK6Y;+*JXF>G^#JhEiOVOQ59 zojFDTHfJ~_iBqD)YO=|paY>vNy+##&2|n1FWz^xb28bk1i(XcVPX}a4oEJStE$d3% z-oPm zfB*y_009U<00Izz00bZa0SN4U0rvd=IC)VZ|0eH|f0DnFcgXL_TjUM$3-VL)I(e0R zpS(=IL%u;?qJ{8+00bZa0SG_<0uX=z1Rwwb2tZ&*1$hxmJt zy-OqfeVD%wv3Ktve;?rQ0ru|k^LHPAmn83?=w)vnuXk_|)f_-<92hq#ytR2tWV=5P$##AOHafKmY=q;i0SG_<0uX=z1Rwwb2tWV=5ZFKQ6XYrD{RHsjaoHs%uTXp%xppwR*GjLoF55Y$lb;rjki#iTx)pEG=GI3NNob zu=H3s;#}MxAQC>e(qAqTJ{sXo(zYVe_UJ@FK1Z`s+_T~t(xlRw64wh0IcKZ;Zj+R= z{>C{OC230cjtAr?X-c)tQ!-aV%_bA6SU#3l*Q%xK&IBin1TU{FpTBJ4ISX|u;`U;P`Aoms8 zAfgStuL|1~dh($7bE5(Iahm+u&64j#qIu_(cr2e=&AR73wxzuLg554>B7>=$)$_7rWiTf@4^qTr5AW2 z%PY&5mKV>Qxnj&*dceLtZ6PpU+pR^84t_;AZ5@=h|7rcPk$}9oC_Z<>LC-;~t;*I3 z&LzQ(y2Dw}ShaqM529nNRbvOx{+#-{-Kwy~E*gGUxOdwfv%WGAkh59wxs25>ogK!? zqthpSa|d1eqp#4m`l1tMYh1kS)}-ieVy)Es)f??me?Xp@5!+8XK&@k5U?aF~VO6z? z9tq#j8u_bQb;xdSh}ryDft>5+^M$I)~&jJ`#Z+Q{Tq8Fqt)9F;N)us zz4zvf60_aQ-Tc-~wEf^rK&~ak_EY?ht4ks(y|<&5wVYm7E3~Pynn~vhi9#aB@3Xp8 zklb#vx|G{IFu%3xQj58CGh#PZc~W#haXB226A5uWYrlnN7j+5d>+N`#65Hy0E5GjT zb!VS+vUXog2g|4IgXKnATA@;^s^wa-JBpl7rIUJ2OFIi3G*-(P!FMk1tKS(2brxf* zZjL%e+eZ%uWR(t| z_AQ~CsxzaHx^4sA;@jE)YPoBAzQyMijOe*xI58 zle7|$qfv4FF8it5DBar#>D{w>7qYvxvbM#fZA-O3ZbdgBvpijEt^ZtVPt#?P z^F-V)pNnp^arGvrD!tRwp>GNUY*T6r6M@I$PN#_p*;D~LL=Xr-00Izz00bZa0SG_<0uX?}t`@-c|E}&HBnJTqKmY;|fB*y_ z009U<00I!$5dmEP?+7D;KmY;|fB*y_009U<00Izz00efm0IvUcb@w1S2tWV=5P$## zAOHafKmY;|fWVFj1ZkA<;3ov~Hu)ZTfjmLtL<+qVdOh?~Xg%~q=;NV@;2(nD4SqgY zq=oQ;00bZa0SG_<0uX=z1R(JLD{y4oCx}tSPrrFfr(c0#d`rPets3sk2^({cjCINx zUkYR^*O_CM3y;!rhvxiRp2~fzyHs^$jsKNF*nR+&xbk{jHVqG zjOOhXqCr|=F6Co6I7+iT>_x*PJYC61hJ7uEEekdo9`2MdS~p7=&9ccmhiHkZS&21g zE@thp&yhj8Z1%XGShc?SsUE~tPwtO%ukoj zXFNtL))y1lnzCjd^L0ua?O6+0X`@kV<`IdOjw&A3vNe|#WzAc2j(UB<;9SZ`fqqF0 z{d&5_En5O~R+!H_>ft4g=Iteo#=9jWA}u*P&ziOuV-0u9u
updated on \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{6}$" + assert re.match(re.compile(pattern), res.content.decode("utf-8")) diff --git a/rates/views.py b/rates/views.py new file mode 100644 index 0000000..f441664 --- /dev/null +++ b/rates/views.py @@ -0,0 +1,14 @@ +from django.http import HttpResponse +import redis +from .tasks import parse_cb + + +def index(request): + r = redis.StrictRedis(host="redis", port=6379, db=0) + try: + data = r.get("result").decode() + last_time = r.get("time").decode() + except AttributeError: + parse_cb.delay() + return HttpResponse("Service is not available.") + return HttpResponse("data: {}

updated on {}".format(data, last_time)) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0b3b09b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +celery==4.2.1 +Django==2.0 +redis +requests==2.19.1