-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathfabfile.py
More file actions
187 lines (151 loc) · 5.12 KB
/
fabfile.py
File metadata and controls
187 lines (151 loc) · 5.12 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
from fabric.api import local, run, env, settings
env.user = 'root'
env.hosts = ['break.sedamcvrkuta.com:22202']
network_name = 'workshop'
image_tag = 'delicb/workshop'
db_container_name = 'workshop-postgres'
db_user = 'workshop'
db_name = 'seventweets'
db_port = 5432
db_image = 'postgres:9.6.2'
db_volume = 'workshop-postgres-data'
gunicorn_port = 8000
external_port = 80
service_container_name = 'seventweets'
def create_network():
"""
Creates network for communication between different docker containers
needed for seventweets to work. If network already exists, this command
will not fail.
"""
with settings(warn_only=True):
run(f'docker network create {network_name}')
def create_volume():
"""
Creates volume for data storage for postgres DB. If volume already exists
it will be kept and command will not fail.
"""
with settings(warn_only=True):
run(f'docker volume create {db_volume}')
def start_db(db_pass):
"""
Starts postgres database. If database is already running, it will
keep running.
:param db_pass: Database password to use.
"""
with settings(warn_only=True):
run(f'docker run -d --name {db_container_name} --net {network_name} '
f'-v {db_volume}:/var/lib/postgresql/data '
f'--restart unless-stopped -e POSTGRES_USER={db_user} '
f'-e POSTGRES_PASSWORD={db_pass} '
f'-e POSTGRES_DB={db_name} '
f'-p 127.0.0.1:{db_port}:{db_port} {db_image}')
def pull_image(image=image_tag):
"""
Pulls image with provided name and tag.
:param image: Reference to image to pull.
"""
run(f'docker pull {image}')
def migrate(db_pass, image=image_tag):
"""
Performs migrations on database.
:param db_pass: Password for database.
:param image: Name of seventweets image.
"""
run(f'docker run '
f'--rm '
f'--net {network_name} '
f'-e ST_DB_USER={db_user} -e ST_DB_PASS={db_pass} '
f'-e ST_DB_HOST={db_container_name} '
f'-e ST_DB_NAME={db_name} '
f'{image} '
f'python3 -m seventweets migrate')
def start_service(db_pass, api_token, image=image_tag):
"""
Starts seventweets service.
:param db_pass: Password for database.
:param api_token: API token to use.
:param image: Name of seventweets image.
:return:
"""
run(f'docker run -d '
f'--name {service_container_name} '
f'--net {network_name} '
f'-e ST_DB_USER={db_user} '
f'-e ST_DB_PASS={db_pass} '
f'-e ST_DB_HOST={db_container_name} '
f'-e ST_DB_NAME={db_name} '
f'-e ST_DB_PORT={db_port} '
f'-e ST_API_TOKEN={api_token} '
f'-p 0.0.0.0:{external_port}:{gunicorn_port} '
f'{image}')
def check_db_connection(db_pass, image=image_tag):
"""
Tries to connect to database for max 10 seconds.
This is useful to check if communication between service and database
is working and allows waiting for database to become responsive (relevant
only for first deploy mostly).
:param db_pass: Password for database.
:param image: Name of seventweets image.
"""
run(f'docker run --rm '
f'--net {network_name} '
f'-e ST_DB_USER={db_user} '
f'-e ST_DB_PASS={db_pass} '
f'-e ST_DB_HOST={db_container_name} '
f'-e ST_DB_NAME={db_name} '
f'-e ST_DB_PORT={db_port} '
f'{image} '
f'python -m seventweets test_db -v -t 10')
def stop_service():
"""
Stops seventweets service. If it is not running, command will not fail.
"""
with settings(warn_only=True):
run(f'docker stop {service_container_name}')
run(f'docker rm {service_container_name}')
def build_image(image=image_tag):
"""
Builds seventweets image locally.
:param image: Name to give to image.
"""
local(f'docker build -t {image} . --build-arg PORT={gunicorn_port}')
def push_image(image=image_tag):
"""
Pushes seventweets image to docker hub.
:param image: Name of image to push.
"""
local(f'docker push {image}')
def app_logs():
"""
Prints seventweets logs (stdout) from remote server.
"""
run(f'docker logs {service_container_name}')
def deploy(db_pass, api_token, image=image_tag):
"""
Builds and deploys application.
This command will:
- build seventweets image locally
- push image to docker hub
- create network on remote server
- stop existing seventweets service on server
- create volume on server
- start database on server
- pull new seventweets image on server
- check if database connection is working
- perform database migrations
- start seventweets service
:param db_pass: Password for database.
:param api_token: API token for protected API endpoints on seventweets.
:param image: Name of image to use.
"""
build_image(image)
push_image(image)
create_network()
stop_service()
create_volume()
start_db(db_pass)
pull_image(image)
check_db_connection(db_pass)
migrate(db_pass)
start_service(db_pass, api_token, image)