Merge lp:~ricardokirkner/isitdeployable/docker into lp:isitdeployable
- docker
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Ricardo Kirkner |
Approved revision: | 225 |
Merge reported by: | Otto Co-Pilot |
Merged at revision: | not available |
Proposed branch: | lp:~ricardokirkner/isitdeployable/docker |
Merge into: | lp:isitdeployable |
Diff against target: |
1016 lines (+609/-176) 19 files modified
.bzrignore (+1/-1) .dockerignore (+2/-0) Dockerfile (+26/-0) Dockerfile.test (+4/-0) Makefile (+24/-21) Makefile.docker (+62/-0) README.docker (+35/-0) branches/wait-for-it/LICENSE (+20/-0) branches/wait-for-it/README.md (+69/-0) branches/wait-for-it/wait-for-it.sh (+161/-0) django_project/settings_base.py (+98/-149) django_project/settings_build.py (+12/-0) django_project/settings_devel.py (+17/-5) docker-compose.dev.yml (+24/-0) docker-compose.secrets.yml (+5/-0) docker-compose.test.yml (+9/-0) docker-compose.yml (+19/-0) requirements-docker.txt (+19/-0) requirements.txt (+2/-0) |
To merge this branch: | bzr merge lp:~ricardokirkner/isitdeployable/docker |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Guillermo Gonzalez | Approve | ||
Review via email: mp+327809@code.launchpad.net |
Commit message
added tooling to build and run application using docker
Description of the change
Otto Co-Pilot (otto-copilot) wrote : | # |
Project setup failed
https:/
Otto Co-Pilot (otto-copilot) wrote : | # |
Project setup failed
https:/
Otto Co-Pilot (otto-copilot) wrote : | # |
Project setup failed
https:/
Otto Co-Pilot (otto-copilot) wrote : | # |
Project setup failed
https:/
Otto Co-Pilot (otto-copilot) wrote : | # |
Project setup failed
https:/
Otto Co-Pilot (otto-copilot) wrote : | # |
Project setup failed
https:/
Otto Co-Pilot (otto-copilot) wrote : | # |
Project setup failed
https:/
- 225. By Ricardo Kirkner
-
do not override default $(ENV) target in docker Makefile
Preview Diff
1 | === modified file '.bzrignore' | |||
2 | --- .bzrignore 2016-07-14 21:54:18 +0000 | |||
3 | +++ .bzrignore 2017-08-01 11:41:20 +0000 | |||
4 | @@ -15,7 +15,7 @@ | |||
5 | 15 | ./tmp/supervisor-childlogs/* | 15 | ./tmp/supervisor-childlogs/* |
6 | 16 | ./.sass-cache | 16 | ./.sass-cache |
7 | 17 | ./revtracker/static/css/* | 17 | ./revtracker/static/css/* |
9 | 18 | ./virtualenv | 18 | ./env |
10 | 19 | ./lib/versioninfo.py | 19 | ./lib/versioninfo.py |
11 | 20 | ./static | 20 | ./static |
12 | 21 | ./logs/* | 21 | ./logs/* |
13 | 22 | 22 | ||
14 | === added file '.dockerignore' | |||
15 | --- .dockerignore 1970-01-01 00:00:00 +0000 | |||
16 | +++ .dockerignore 2017-08-01 11:41:20 +0000 | |||
17 | @@ -0,0 +1,2 @@ | |||
18 | 1 | .bzr | ||
19 | 2 | env | ||
20 | 0 | 3 | ||
21 | === added file 'Dockerfile' | |||
22 | --- Dockerfile 1970-01-01 00:00:00 +0000 | |||
23 | +++ Dockerfile 2017-08-01 11:41:20 +0000 | |||
24 | @@ -0,0 +1,26 @@ | |||
25 | 1 | FROM ubuntu:trusty | ||
26 | 2 | |||
27 | 3 | RUN mkdir -p /usr/src/app | ||
28 | 4 | WORKDIR /usr/src/app | ||
29 | 5 | |||
30 | 6 | # install system dependencies (debs) | ||
31 | 7 | COPY dependencies.txt dependencies-devel.txt /usr/src/app/ | ||
32 | 8 | RUN apt-get update && apt-get upgrade -y \ | ||
33 | 9 | && apt-get install -y software-properties-common \ | ||
34 | 10 | && apt-add-repository --yes ppa:mojo-maintainers \ | ||
35 | 11 | && apt-add-repository --yes ppa:ubuntuone/isitdeployable-dependencies \ | ||
36 | 12 | && apt-get update \ | ||
37 | 13 | && cat dependencies.txt dependencies-devel.txt | xargs apt-get install -y --no-install-recommends \ | ||
38 | 14 | && apt-get install -y python-pip \ | ||
39 | 15 | && rm -rf /var/lib/apt/lists/* | ||
40 | 16 | |||
41 | 17 | # install python dependencies (wheels) | ||
42 | 18 | COPY branches/wheels branches/wheels | ||
43 | 19 | COPY requirements.txt /usr/src/app | ||
44 | 20 | RUN pip install --find-links=branches/wheels --no-index -r requirements.txt | ||
45 | 21 | |||
46 | 22 | # add app source code | ||
47 | 23 | COPY . /usr/src/app | ||
48 | 24 | |||
49 | 25 | # start container | ||
50 | 26 | CMD ["make", "app-start"] | ||
51 | 0 | 27 | ||
52 | === added file 'Dockerfile.test' | |||
53 | --- Dockerfile.test 1970-01-01 00:00:00 +0000 | |||
54 | +++ Dockerfile.test 2017-08-01 11:41:20 +0000 | |||
55 | @@ -0,0 +1,4 @@ | |||
56 | 1 | FROM deployable:dev | ||
57 | 2 | |||
58 | 3 | COPY requirements-devel.txt /usr/src/app | ||
59 | 4 | RUN pip install --find-links=branches/wheels --no-index -r requirements-devel.txt | ||
60 | 0 | 5 | ||
61 | === modified file 'Makefile' | |||
62 | --- Makefile 2016-07-27 14:51:28 +0000 | |||
63 | +++ Makefile 2017-08-01 11:41:20 +0000 | |||
64 | @@ -17,28 +17,20 @@ | |||
65 | 17 | LOCAL_SETTINGS_DIR ?= ../local_config | 17 | LOCAL_SETTINGS_DIR ?= ../local_config |
66 | 18 | LOCAL_SETTINGS_PATH = $(LOCAL_SETTINGS_DIR)/settings.py | 18 | LOCAL_SETTINGS_PATH = $(LOCAL_SETTINGS_DIR)/settings.py |
67 | 19 | 19 | ||
71 | 20 | HERE := $(shell pwd) | 20 | ENV = $(CURDIR)/env |
69 | 21 | VIRTUALENV_DIR ?= ${HERE}/virtualenv | ||
70 | 22 | VIRTUALENV_BIN := ${VIRTUALENV_DIR}/bin | ||
72 | 23 | PYTHONPATH := ${HERE}/revtracker:${HERE}/lib:${HERE}:${PYTHONPATH} | 21 | PYTHONPATH := ${HERE}/revtracker:${HERE}/lib:${HERE}:${PYTHONPATH} |
73 | 24 | 22 | ||
74 | 25 | CM ?= /usr/lib/config-manager/cm.py | 23 | CM ?= /usr/lib/config-manager/cm.py |
75 | 26 | CONFIGMANAGER = config-manager.txt | 24 | CONFIGMANAGER = config-manager.txt |
79 | 27 | PYTHON = $(VIRTUALENV_DIR)/bin/python | 25 | GUNICORN ?= $(ENV)/bin/gunicorn |
80 | 28 | # use env's python to run pip in order to overcome shebang's max line length limitation | 26 | PYTHON ?= $(ENV)/bin/python |
81 | 29 | PIP = $(PYTHON) $(VIRTUALENV_DIR)/bin/pip | 27 | PIP ?= $(ENV)/bin/pip |
82 | 30 | 28 | ||
83 | 31 | # Several targets assume (wrongly) that $(ENV) already exists. As a stop-gap | 29 | # Several targets assume (wrongly) that $(ENV) already exists. As a stop-gap |
84 | 32 | # we ifdef them with ENV_CREATED to avoid spurious | 30 | # we ifdef them with ENV_CREATED to avoid spurious |
85 | 33 | # '/bin/sh: 1: /.../env/bin/python: not found' errors | 31 | # '/bin/sh: 1: /.../env/bin/python: not found' errors |
86 | 34 | ENV_CREATED = $(shell test -e $(PYTHON) && echo "yes" || echo "no") | 32 | ENV_CREATED = $(shell test -e $(PYTHON) && echo "yes" || echo "no") |
87 | 35 | 33 | ||
88 | 36 | include makefiles/css.mk | ||
89 | 37 | include makefiles/gem.mk | ||
90 | 38 | include makefiles/js.mk | ||
91 | 39 | ifeq (yes,$(ENV_CREATED)) | ||
92 | 40 | include Makefile.db | ||
93 | 41 | endif | ||
94 | 42 | WHEELS_BRANCH_URL ?= lp:isitdeployable-dependencies | 34 | WHEELS_BRANCH_URL ?= lp:isitdeployable-dependencies |
95 | 43 | WHEELS_DIR = branches/wheels | 35 | WHEELS_DIR = branches/wheels |
96 | 44 | 36 | ||
97 | @@ -78,13 +70,13 @@ | |||
98 | 78 | cp django_project/settings.py.example $(LOCAL_SETTINGS_PATH) | 70 | cp django_project/settings.py.example $(LOCAL_SETTINGS_PATH) |
99 | 79 | 71 | ||
100 | 80 | 72 | ||
102 | 81 | $(VIRTUALENV_DIR): | 73 | $(ENV): |
103 | 82 | echo 'creating new virtualenv...' | 74 | echo 'creating new virtualenv...' |
105 | 83 | virtualenv --clear --system-site-packages $(VIRTUALENV_DIR) | 75 | virtualenv --clear --system-site-packages $(ENV) |
106 | 84 | 76 | ||
107 | 85 | clean-virtualenv: | 77 | clean-virtualenv: |
108 | 86 | echo 'cleaning virtualenv...' | 78 | echo 'cleaning virtualenv...' |
110 | 87 | rm -rf $(VIRTUALENV_DIR) | 79 | rm -rf $(ENV) |
111 | 88 | 80 | ||
112 | 89 | version: | 81 | version: |
113 | 90 | bzr version-info --format=python > lib/versioninfo.py | 82 | bzr version-info --format=python > lib/versioninfo.py |
114 | @@ -101,7 +93,7 @@ | |||
115 | 101 | 93 | ||
116 | 102 | sourcedeps: fetch-sourcedeps install-wheels | 94 | sourcedeps: fetch-sourcedeps install-wheels |
117 | 103 | 95 | ||
119 | 104 | bootstrap: $(LOCAL_SETTINGS_PATH) $(VIRTUALENV_DIR) sourcedeps install-wheels-dev | 96 | bootstrap: $(LOCAL_SETTINGS_PATH) $(ENV) sourcedeps install-wheels-dev |
120 | 105 | 97 | ||
121 | 106 | 98 | ||
122 | 107 | # Management | 99 | # Management |
123 | @@ -115,7 +107,7 @@ | |||
124 | 115 | run: ARGS=0.0.0.0:8000 | 107 | run: ARGS=0.0.0.0:8000 |
125 | 116 | run: collectstatic | 108 | run: collectstatic |
126 | 117 | $(MAKE) manage ARGS="loaddata fixtures/group.json" | 109 | $(MAKE) manage ARGS="loaddata fixtures/group.json" |
128 | 118 | $(VIRTUALENV_DIR)/bin/gunicorn django_project.wsgi:application --workers=2 --reload --pid=logs/gunicorn.pid --bind=$(ARGS) --timeout=99999 | 110 | $(GUNICORN) django_project.wsgi:application --workers=2 --reload --pid=logs/gunicorn.pid --bind=$(ARGS) --timeout=99999 |
129 | 119 | 111 | ||
130 | 120 | start-supervisor: logs | 112 | start-supervisor: logs |
131 | 121 | @echo Starting supervised processes | 113 | @echo Starting supervised processes |
132 | @@ -141,14 +133,14 @@ | |||
133 | 141 | [ -d $(WHEELS_DIR) ] && (cd $(WHEELS_DIR) && bzr pull) || (bzr branch $(WHEELS_BRANCH_URL) $(WHEELS_DIR)) | 133 | [ -d $(WHEELS_DIR) ] && (cd $(WHEELS_DIR) && bzr pull) || (bzr branch $(WHEELS_BRANCH_URL) $(WHEELS_DIR)) |
134 | 142 | 134 | ||
135 | 143 | update-wheels: ARGS=-r requirements-devel.txt | 135 | update-wheels: ARGS=-r requirements-devel.txt |
137 | 144 | update-wheels: $(VIRTUALENV_DIR) | 136 | update-wheels: $(ENV) |
138 | 145 | $(PIP) wheel -w $(WHEELS_DIR) -f $(WHEELS_DIR) $(ARGS) | 137 | $(PIP) wheel -w $(WHEELS_DIR) -f $(WHEELS_DIR) $(ARGS) |
139 | 146 | 138 | ||
140 | 147 | install-wheels: ARGS=-r requirements.txt | 139 | install-wheels: ARGS=-r requirements.txt |
142 | 148 | install-wheels: $(VIRTUALENV_DIR) | 140 | install-wheels: $(ENV) |
143 | 149 | $(PIP) install --find-links=$(WHEELS_DIR) --no-index $(ARGS) | 141 | $(PIP) install --find-links=$(WHEELS_DIR) --no-index $(ARGS) |
144 | 150 | 142 | ||
146 | 151 | install-wheels-dev: $(VIRTUALENV_DIR) install-wheels | 143 | install-wheels-dev: $(ENV) install-wheels |
147 | 152 | $(MAKE) install-wheels ARGS="-r requirements-devel.txt --pre" | 144 | $(MAKE) install-wheels ARGS="-r requirements-devel.txt --pre" |
148 | 153 | 145 | ||
149 | 154 | 146 | ||
150 | @@ -162,7 +154,7 @@ | |||
151 | 162 | REV_DIR=$(STATIC_ROOT)/combo/rev-r$$(cat $(STATIC_ROOT)/combo/revno) | 154 | REV_DIR=$(STATIC_ROOT)/combo/rev-r$$(cat $(STATIC_ROOT)/combo/revno) |
152 | 163 | 155 | ||
153 | 164 | collectstatic: js css | 156 | collectstatic: js css |
155 | 165 | DJANGO_SETTINGS_MODULE=django_project.settings_base $(DJANGO_MANAGE) collectstatic --noinput \ | 157 | DJANGO_SETTINGS_MODULE=django_project.settings_build $(DJANGO_MANAGE) collectstatic --noinput \ |
156 | 166 | > logs/collectstatic.log 2>&1 || (cat logs/collectstatic.log && false) | 158 | > logs/collectstatic.log 2>&1 || (cat logs/collectstatic.log && false) |
157 | 167 | cd $(STATIC_ROOT)/combo | 159 | cd $(STATIC_ROOT)/combo |
158 | 168 | [ -L $(REV_DIR) ] && (echo 'existing rev symbolink, removing' && rm $(REV_DIR)) \ | 160 | [ -L $(REV_DIR) ] && (echo 'existing rev symbolink, removing' && rm $(REV_DIR)) \ |
159 | @@ -187,4 +179,15 @@ | |||
160 | 187 | conn-check $(CONN_CHECK_CONFIG_PATH) | 179 | conn-check $(CONN_CHECK_CONFIG_PATH) |
161 | 188 | 180 | ||
162 | 189 | 181 | ||
163 | 182 | # static assets related targets | ||
164 | 183 | include makefiles/css.mk | ||
165 | 184 | include makefiles/gem.mk | ||
166 | 185 | include makefiles/js.mk | ||
167 | 186 | # database related targets | ||
168 | 187 | ifeq (yes,$(ENV_CREATED)) | ||
169 | 188 | include Makefile.db | ||
170 | 189 | endif | ||
171 | 190 | # deployment related targets | ||
172 | 191 | include Makefile.docker | ||
173 | 192 | |||
174 | 190 | .PHONY: build-tarball install-wheels | 193 | .PHONY: build-tarball install-wheels |
175 | 191 | 194 | ||
176 | === added file 'Makefile.docker' | |||
177 | --- Makefile.docker 1970-01-01 00:00:00 +0000 | |||
178 | +++ Makefile.docker 2017-08-01 11:41:20 +0000 | |||
179 | @@ -0,0 +1,62 @@ | |||
180 | 1 | |||
181 | 2 | PROJECT_NAME = django_project | ||
182 | 3 | |||
183 | 4 | # define docker related variables | ||
184 | 5 | DOCKER_COMPOSE_FILES ?= -f docker-compose.yml -f docker-compose.dev.yml | ||
185 | 6 | DOCKER_COMPOSE ?= $(ENV)/bin/docker-compose | ||
186 | 7 | TAG ?= deployable:dev | ||
187 | 8 | |||
188 | 9 | # pre-process arguments | ||
189 | 10 | # if the first argument is "special" (docker-compose, docker-test)... | ||
190 | 11 | ifneq (,$(filter $(firstword $(MAKECMDGOALS)),docker-compose docker-test)) | ||
191 | 12 | # use the rest as sub-arguments | ||
192 | 13 | ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) | ||
193 | 14 | # ...and turn them into do-nothing targets | ||
194 | 15 | $(eval $(ARGS):;@:) | ||
195 | 16 | endif | ||
196 | 17 | |||
197 | 18 | |||
198 | 19 | docker-bootstrap: $(ENV) fetch-sourcedeps | ||
199 | 20 | $(ENV)/bin/pip install --find-links=$(WHEELS_DIR) --no-index -r requirements-docker.txt | ||
200 | 21 | |||
201 | 22 | docker-build: version ## Build images | ||
202 | 23 | $(MAKE) docker-compose ARGS="build" | ||
203 | 24 | |||
204 | 25 | docker-run: ## Run stack in foreground | ||
205 | 26 | DOCKER_COMPOSE_FILES="$(DOCKER_COMPOSE_FILES) -f docker-compose.secrets.yml" $(MAKE) docker-compose ARGS="up" | ||
206 | 27 | |||
207 | 28 | docker-start: ## Run stack in background | ||
208 | 29 | DOCKER_COMPOSE_FILES="$(DOCKER_COMPOSE_FILES) -f docker-compose.secrets.yml" $(MAKE) docker-compose ARGS="up -d" | ||
209 | 30 | |||
210 | 31 | docker-stop: ## Stop containers | ||
211 | 32 | DOCKER_COMPOSE_FILES="$(DOCKER_COMPOSE_FILES) -f docker-compose.secrets.yml" $(MAKE) docker-compose ARGS="down" | ||
212 | 33 | |||
213 | 34 | docker-clean: docker-stop ## Remove images | ||
214 | 35 | docker rmi $(TAG) | ||
215 | 36 | |||
216 | 37 | docker-compose: $(ENV) | ||
217 | 38 | $(DOCKER_COMPOSE) $(DOCKER_COMPOSE_FILES) $(ARGS) | ||
218 | 39 | |||
219 | 40 | docker-test: ## Run tests using containers | ||
220 | 41 | DOCKER_COMPOSE_FILES='-f docker-compose.yml -f docker-compose.test.yml' $(MAKE) docker-compose ARGS="up --build -d" | ||
221 | 42 | DOCKER_COMPOSE_FILES='-f docker-compose.yml -f docker-compose.test.yml' $(MAKE) docker-compose ARGS="run app make test $(ARGS)" | ||
222 | 43 | DOCKER_COMPOSE_FILES='-f docker-compose.yml -f docker-compose.test.yml' $(MAKE) docker-compose ARGS="down" | ||
223 | 44 | docker rmi deployable:test | ||
224 | 45 | |||
225 | 46 | ### targets for in-container use | ||
226 | 47 | |||
227 | 48 | app-update-db: | ||
228 | 49 | $(MAKE) manage ARGS='syncdb --noinput' PYTHON=python | ||
229 | 50 | $(MAKE) manage ARGS='migrate --noinput' PYTHON=python | ||
230 | 51 | |||
231 | 52 | app-start: BIND=0.0.0.0:8000 | ||
232 | 53 | app-start: WORKERS=3 | ||
233 | 54 | app-start: app-update-db collectstatic | ||
234 | 55 | $(MAKE) manage ARGS="loaddata fixtures/group.json" | ||
235 | 56 | gunicorn --workers=$(WORKERS) --bind=$(BIND) $(PROJECT_NAME).wsgi:application | ||
236 | 57 | |||
237 | 58 | worker-worker: | ||
238 | 59 | python $(PROJECT_NAME)/celeryapp.py worker | ||
239 | 60 | |||
240 | 61 | worker-beat: | ||
241 | 62 | python $(PROJECT_NAME)/celeryapp.py beat | ||
242 | 0 | 63 | ||
243 | === added file 'README.docker' | |||
244 | --- README.docker 1970-01-01 00:00:00 +0000 | |||
245 | +++ README.docker 2017-08-01 11:41:20 +0000 | |||
246 | @@ -0,0 +1,35 @@ | |||
247 | 1 | ------ | ||
248 | 2 | Docker | ||
249 | 3 | ------ | ||
250 | 4 | |||
251 | 5 | It's as simple as: | ||
252 | 6 | |||
253 | 7 | $ sudo apt install docker.io config-manager | ||
254 | 8 | $ make docker-bootstrap | ||
255 | 9 | $ make docker-build | ||
256 | 10 | $ make docker-run | ||
257 | 11 | |||
258 | 12 | .. important: | ||
259 | 13 | |||
260 | 14 | Notice that docker.io can't be run inside a container easily, thus the suggested way to run it is to | ||
261 | 15 | install it on your host and run it from there directly (or run everything inside a virtual machine like VirtualBox or KVM). | ||
262 | 16 | |||
263 | 17 | .. important: | ||
264 | 18 | |||
265 | 19 | Before running any docker commands you'll need to add yourself to the `docker` group. Otherwise all docker commands will | ||
266 | 20 | have to be run as root. | ||
267 | 21 | |||
268 | 22 | sudo groupadd -a -G docker $USER | ||
269 | 23 | sg docker bash | ||
270 | 24 | |||
271 | 25 | .. note: | ||
272 | 26 | |||
273 | 27 | You only need to run the `sg` command in the current terminal. The next time you login with your user, you should | ||
274 | 28 | already be a part of the docker group. | ||
275 | 29 | |||
276 | 30 | You can now interact with the service by opening http://localhost:8000 in your browser of choice. | ||
277 | 31 | |||
278 | 32 | To run the tests simply do: | ||
279 | 33 | |||
280 | 34 | $ make docker-test | ||
281 | 35 | |||
282 | 0 | 36 | ||
283 | === added directory 'branches/wait-for-it' | |||
284 | === added file 'branches/wait-for-it/LICENSE' | |||
285 | --- branches/wait-for-it/LICENSE 1970-01-01 00:00:00 +0000 | |||
286 | +++ branches/wait-for-it/LICENSE 2017-08-01 11:41:20 +0000 | |||
287 | @@ -0,0 +1,20 @@ | |||
288 | 1 | The MIT License (MIT) | ||
289 | 2 | Copyright (c) 2016 Giles Hall | ||
290 | 3 | |||
291 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
292 | 5 | this software and associated documentation files (the "Software"), to deal in | ||
293 | 6 | the Software without restriction, including without limitation the rights to | ||
294 | 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
295 | 8 | of the Software, and to permit persons to whom the Software is furnished to do | ||
296 | 9 | so, subject to the following conditions: | ||
297 | 10 | |||
298 | 11 | The above copyright notice and this permission notice shall be included in all | ||
299 | 12 | copies or substantial portions of the Software. | ||
300 | 13 | |||
301 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
302 | 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
303 | 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
304 | 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
305 | 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
306 | 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
307 | 20 | SOFTWARE. | ||
308 | 0 | 21 | ||
309 | === added file 'branches/wait-for-it/README.md' | |||
310 | --- branches/wait-for-it/README.md 1970-01-01 00:00:00 +0000 | |||
311 | +++ branches/wait-for-it/README.md 2017-08-01 11:41:20 +0000 | |||
312 | @@ -0,0 +1,69 @@ | |||
313 | 1 | # HELP NEEDED | ||
314 | 2 | |||
315 | 3 | Hi there! I wrote `wait-for-it` in order to help me orchestrate containers I operate at my day job. I thought it was a neat little script, so I published it. I assumed I would be its only user, but that's not what happened! `wait-for-it` has received more stars then all of my other public repositories put together. I had no idea this tool would solicit such an audience, and I was equally unprepared to carve out the time required to address my user's issues and patches. I would like to solicit a volunteer from the community who would be willing to be a co-maintainer of this repository. If this is something you might be interested in, please email me at `waitforit@polymerase.org`. Thanks! | ||
316 | 4 | |||
317 | 5 | ## wait-for-it | ||
318 | 6 | |||
319 | 7 | `wait-for-it.sh` is a pure bash script that will wait on the availability of a host and TCP port. It is useful for synchronizing the spin-up of interdependent services, such as linked docker containers. Since it is a pure bash script, it does not have any external dependencies. | ||
320 | 8 | |||
321 | 9 | ## Usage | ||
322 | 10 | |||
323 | 11 | ``` | ||
324 | 12 | wait-for-it.sh host:port [-s] [-t timeout] [-- command args] | ||
325 | 13 | -h HOST | --host=HOST Host or IP under test | ||
326 | 14 | -p PORT | --port=PORT TCP port under test | ||
327 | 15 | Alternatively, you specify the host and port as host:port | ||
328 | 16 | -s | --strict Only execute subcommand if the test succeeds | ||
329 | 17 | -q | --quiet Don't output any status messages | ||
330 | 18 | -t TIMEOUT | --timeout=TIMEOUT | ||
331 | 19 | Timeout in seconds, zero for no timeout | ||
332 | 20 | -- COMMAND ARGS Execute command with args after the test finishes | ||
333 | 21 | ``` | ||
334 | 22 | |||
335 | 23 | ## Examples | ||
336 | 24 | |||
337 | 25 | For example, let's test to see if we can access port 80 on www.google.com, and if it is available, echo the message `google is up`. | ||
338 | 26 | |||
339 | 27 | ``` | ||
340 | 28 | $ ./wait-for-it.sh www.google.com:80 -- echo "google is up" | ||
341 | 29 | wait-for-it.sh: waiting 15 seconds for www.google.com:80 | ||
342 | 30 | wait-for-it.sh: www.google.com:80 is available after 0 seconds | ||
343 | 31 | google is up | ||
344 | 32 | ``` | ||
345 | 33 | |||
346 | 34 | You can set your own timeout with the `-t` or `--timeout=` option. Setting the timeout value to 0 will disable the timeout: | ||
347 | 35 | |||
348 | 36 | ``` | ||
349 | 37 | $ ./wait-for-it.sh -t 0 www.google.com:80 -- echo "google is up" | ||
350 | 38 | wait-for-it.sh: waiting for www.google.com:80 without a timeout | ||
351 | 39 | wait-for-it.sh: www.google.com:80 is available after 0 seconds | ||
352 | 40 | google is up | ||
353 | 41 | ``` | ||
354 | 42 | |||
355 | 43 | The subcommand will be executed regardless if the service is up or not. If you wish to execute the subcommand only if the service is up, add the `--strict` argument. In this example, we will test port 81 on www.google.com which will fail: | ||
356 | 44 | |||
357 | 45 | ``` | ||
358 | 46 | $ ./wait-for-it.sh www.google.com:81 --timeout=1 --strict -- echo "google is up" | ||
359 | 47 | wait-for-it.sh: waiting 1 seconds for www.google.com:81 | ||
360 | 48 | wait-for-it.sh: timeout occurred after waiting 1 seconds for www.google.com:81 | ||
361 | 49 | wait-for-it.sh: strict mode, refusing to execute subprocess | ||
362 | 50 | ``` | ||
363 | 51 | |||
364 | 52 | If you don't want to execute a subcommand, leave off the `--` argument. This way, you can test the exit condition of `wait-for-it.sh` in your own scripts, and determine how to proceed: | ||
365 | 53 | |||
366 | 54 | ``` | ||
367 | 55 | $ ./wait-for-it.sh www.google.com:80 | ||
368 | 56 | wait-for-it.sh: waiting 15 seconds for www.google.com:80 | ||
369 | 57 | wait-for-it.sh: www.google.com:80 is available after 0 seconds | ||
370 | 58 | $ echo $? | ||
371 | 59 | 0 | ||
372 | 60 | $ ./wait-for-it.sh www.google.com:81 | ||
373 | 61 | wait-for-it.sh: waiting 15 seconds for www.google.com:81 | ||
374 | 62 | wait-for-it.sh: timeout occurred after waiting 15 seconds for www.google.com:81 | ||
375 | 63 | $ echo $? | ||
376 | 64 | 124 | ||
377 | 65 | ``` | ||
378 | 66 | |||
379 | 67 | ## Thanks | ||
380 | 68 | |||
381 | 69 | I wrote this script for my employer, [Ginkgo Bioworks](http://www.ginkgobioworks.com/), who was kind enough to let me release it as an open source tool. We are always looking to [hire](https://jobs.lever.co/ginkgobioworks) talented folks who are interested in working in the field of synthetic biology. | ||
382 | 0 | 70 | ||
383 | === added file 'branches/wait-for-it/wait-for-it.sh' | |||
384 | --- branches/wait-for-it/wait-for-it.sh 1970-01-01 00:00:00 +0000 | |||
385 | +++ branches/wait-for-it/wait-for-it.sh 2017-08-01 11:41:20 +0000 | |||
386 | @@ -0,0 +1,161 @@ | |||
387 | 1 | #!/usr/bin/env bash | ||
388 | 2 | # Use this script to test if a given TCP host/port are available | ||
389 | 3 | |||
390 | 4 | cmdname=$(basename $0) | ||
391 | 5 | |||
392 | 6 | echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } | ||
393 | 7 | |||
394 | 8 | usage() | ||
395 | 9 | { | ||
396 | 10 | cat << USAGE >&2 | ||
397 | 11 | Usage: | ||
398 | 12 | $cmdname host:port [-s] [-t timeout] [-- command args] | ||
399 | 13 | -h HOST | --host=HOST Host or IP under test | ||
400 | 14 | -p PORT | --port=PORT TCP port under test | ||
401 | 15 | Alternatively, you specify the host and port as host:port | ||
402 | 16 | -s | --strict Only execute subcommand if the test succeeds | ||
403 | 17 | -q | --quiet Don't output any status messages | ||
404 | 18 | -t TIMEOUT | --timeout=TIMEOUT | ||
405 | 19 | Timeout in seconds, zero for no timeout | ||
406 | 20 | -- COMMAND ARGS Execute command with args after the test finishes | ||
407 | 21 | USAGE | ||
408 | 22 | exit 1 | ||
409 | 23 | } | ||
410 | 24 | |||
411 | 25 | wait_for() | ||
412 | 26 | { | ||
413 | 27 | if [[ $TIMEOUT -gt 0 ]]; then | ||
414 | 28 | echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" | ||
415 | 29 | else | ||
416 | 30 | echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" | ||
417 | 31 | fi | ||
418 | 32 | start_ts=$(date +%s) | ||
419 | 33 | while : | ||
420 | 34 | do | ||
421 | 35 | (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 | ||
422 | 36 | result=$? | ||
423 | 37 | if [[ $result -eq 0 ]]; then | ||
424 | 38 | end_ts=$(date +%s) | ||
425 | 39 | echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" | ||
426 | 40 | break | ||
427 | 41 | fi | ||
428 | 42 | sleep 1 | ||
429 | 43 | done | ||
430 | 44 | return $result | ||
431 | 45 | } | ||
432 | 46 | |||
433 | 47 | wait_for_wrapper() | ||
434 | 48 | { | ||
435 | 49 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 | ||
436 | 50 | if [[ $QUIET -eq 1 ]]; then | ||
437 | 51 | timeout $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & | ||
438 | 52 | else | ||
439 | 53 | timeout $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & | ||
440 | 54 | fi | ||
441 | 55 | PID=$! | ||
442 | 56 | trap "kill -INT -$PID" INT | ||
443 | 57 | wait $PID | ||
444 | 58 | RESULT=$? | ||
445 | 59 | if [[ $RESULT -ne 0 ]]; then | ||
446 | 60 | echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" | ||
447 | 61 | fi | ||
448 | 62 | return $RESULT | ||
449 | 63 | } | ||
450 | 64 | |||
451 | 65 | # process arguments | ||
452 | 66 | while [[ $# -gt 0 ]] | ||
453 | 67 | do | ||
454 | 68 | case "$1" in | ||
455 | 69 | *:* ) | ||
456 | 70 | hostport=(${1//:/ }) | ||
457 | 71 | HOST=${hostport[0]} | ||
458 | 72 | PORT=${hostport[1]} | ||
459 | 73 | shift 1 | ||
460 | 74 | ;; | ||
461 | 75 | --child) | ||
462 | 76 | CHILD=1 | ||
463 | 77 | shift 1 | ||
464 | 78 | ;; | ||
465 | 79 | -q | --quiet) | ||
466 | 80 | QUIET=1 | ||
467 | 81 | shift 1 | ||
468 | 82 | ;; | ||
469 | 83 | -s | --strict) | ||
470 | 84 | STRICT=1 | ||
471 | 85 | shift 1 | ||
472 | 86 | ;; | ||
473 | 87 | -h) | ||
474 | 88 | HOST="$2" | ||
475 | 89 | if [[ $HOST == "" ]]; then break; fi | ||
476 | 90 | shift 2 | ||
477 | 91 | ;; | ||
478 | 92 | --host=*) | ||
479 | 93 | HOST="${1#*=}" | ||
480 | 94 | shift 1 | ||
481 | 95 | ;; | ||
482 | 96 | -p) | ||
483 | 97 | PORT="$2" | ||
484 | 98 | if [[ $PORT == "" ]]; then break; fi | ||
485 | 99 | shift 2 | ||
486 | 100 | ;; | ||
487 | 101 | --port=*) | ||
488 | 102 | PORT="${1#*=}" | ||
489 | 103 | shift 1 | ||
490 | 104 | ;; | ||
491 | 105 | -t) | ||
492 | 106 | TIMEOUT="$2" | ||
493 | 107 | if [[ $TIMEOUT == "" ]]; then break; fi | ||
494 | 108 | shift 2 | ||
495 | 109 | ;; | ||
496 | 110 | --timeout=*) | ||
497 | 111 | TIMEOUT="${1#*=}" | ||
498 | 112 | shift 1 | ||
499 | 113 | ;; | ||
500 | 114 | --) | ||
501 | 115 | shift | ||
502 | 116 | CLI="$@" | ||
503 | 117 | break | ||
504 | 118 | ;; | ||
505 | 119 | --help) | ||
506 | 120 | usage | ||
507 | 121 | ;; | ||
508 | 122 | *) | ||
509 | 123 | echoerr "Unknown argument: $1" | ||
510 | 124 | usage | ||
511 | 125 | ;; | ||
512 | 126 | esac | ||
513 | 127 | done | ||
514 | 128 | |||
515 | 129 | if [[ "$HOST" == "" || "$PORT" == "" ]]; then | ||
516 | 130 | echoerr "Error: you need to provide a host and port to test." | ||
517 | 131 | usage | ||
518 | 132 | fi | ||
519 | 133 | |||
520 | 134 | TIMEOUT=${TIMEOUT:-15} | ||
521 | 135 | STRICT=${STRICT:-0} | ||
522 | 136 | CHILD=${CHILD:-0} | ||
523 | 137 | QUIET=${QUIET:-0} | ||
524 | 138 | |||
525 | 139 | if [[ $CHILD -gt 0 ]]; then | ||
526 | 140 | wait_for | ||
527 | 141 | RESULT=$? | ||
528 | 142 | exit $RESULT | ||
529 | 143 | else | ||
530 | 144 | if [[ $TIMEOUT -gt 0 ]]; then | ||
531 | 145 | wait_for_wrapper | ||
532 | 146 | RESULT=$? | ||
533 | 147 | else | ||
534 | 148 | wait_for | ||
535 | 149 | RESULT=$? | ||
536 | 150 | fi | ||
537 | 151 | fi | ||
538 | 152 | |||
539 | 153 | if [[ $CLI != "" ]]; then | ||
540 | 154 | if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then | ||
541 | 155 | echoerr "$cmdname: strict mode, refusing to execute subprocess" | ||
542 | 156 | exit $RESULT | ||
543 | 157 | fi | ||
544 | 158 | exec $CLI | ||
545 | 159 | else | ||
546 | 160 | exit $RESULT | ||
547 | 161 | fi | ||
548 | 0 | 162 | ||
549 | === modified file 'django_project/settings_base.py' | |||
550 | --- django_project/settings_base.py 2016-11-03 21:48:25 +0000 | |||
551 | +++ django_project/settings_base.py 2017-08-01 11:41:20 +0000 | |||
552 | @@ -2,120 +2,47 @@ | |||
553 | 2 | 2 | ||
554 | 3 | import os | 3 | import os |
555 | 4 | import pwd | 4 | import pwd |
557 | 5 | import sys | 5 | from datetime import timedelta |
558 | 6 | |||
559 | 7 | import dj_database_url | ||
560 | 8 | import djcelery | ||
561 | 9 | from getenv import env | ||
562 | 6 | 10 | ||
563 | 7 | # Needed to have celery work from management commands | 11 | # Needed to have celery work from management commands |
564 | 8 | import djcelery | ||
565 | 9 | djcelery.setup_loader() | 12 | djcelery.setup_loader() |
566 | 10 | 13 | ||
575 | 11 | from datetime import timedelta | 14 | |
576 | 12 | 15 | # base directories | |
577 | 13 | DEBUG = True | 16 | |
578 | 14 | TEMPLATE_DEBUG = DEBUG | 17 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
579 | 15 | 18 | _LOGS_DIR = os.path.abspath( | |
580 | 16 | 19 | os.path.join(BASE_DIR, os.pardir, os.pardir, 'logs')) | |
581 | 17 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) | 20 | LOGS_DIR = os.path.abspath(os.getenv('DPA_LOGS_DIR', _LOGS_DIR)) |
574 | 18 | SRC_DIR = os.path.join(BASE_DIR, 'revtracker') | ||
582 | 19 | HOST_DIR = os.path.abspath( | 21 | HOST_DIR = os.path.abspath( |
583 | 20 | os.getenv('DPA_LP_CACHE_HOST_DIR', os.path.abspath( | 22 | os.getenv('DPA_LP_CACHE_HOST_DIR', os.path.abspath( |
584 | 21 | os.path.join(BASE_DIR, os.path.pardir, os.path.pardir)))) | 23 | os.path.join(BASE_DIR, os.path.pardir, os.path.pardir)))) |
585 | 22 | LOGS_DIR = os.path.abspath( | ||
586 | 23 | os.getenv('DPA_LOGS_DIR', os.path.join(BASE_DIR, 'logs'))) | ||
587 | 24 | OOPS_DIR = os.path.join(LOGS_DIR, 'www-oops') | 24 | OOPS_DIR = os.path.join(LOGS_DIR, 'www-oops') |
592 | 25 | 25 | SRC_DIR = os.path.join(BASE_DIR, 'revtracker') | |
593 | 26 | 26 | ||
594 | 27 | ADMINS = ( | 27 | # django settings |
595 | 28 | # ('Your Name', 'your_email@example.com'), | 28 | |
596 | 29 | ADMIN_MEDIA_PREFIX = '/static/admin/' | ||
597 | 30 | ALLOWED_HOSTS = env('ALLOWED_HOSTS', '[]') | ||
598 | 31 | AUTHENTICATION_BACKENDS = ( | ||
599 | 32 | 'django_openid_auth.auth.OpenIDBackend', | ||
600 | 33 | 'django.contrib.auth.backends.ModelBackend', | ||
601 | 29 | ) | 34 | ) |
605 | 30 | 35 | CSRF_COOKIE_DOMAIN = None | |
606 | 31 | MANAGERS = ADMINS | 36 | CSRF_COOKIE_HTTPONLY = False |
607 | 32 | 37 | CSRF_COOKIE_NAME = 'csrftoken' | |
608 | 38 | CSRF_COOKIE_PATH = '/' | ||
609 | 39 | CSRF_COOKIE_SECURE = False | ||
610 | 40 | CSRF_FAILURE_VIEW = 'django.views.csrf.csrf_failure' | ||
611 | 33 | DATABASES = { | 41 | DATABASES = { |
630 | 34 | 'default': { | 42 | 'default': dj_database_url.config( |
631 | 35 | 'ENGINE': 'django.db.backends.postgresql_psycopg2', | 43 | default='postgres://postgres@localhost/revtracker') |
614 | 36 | 'ATOMIC_REQUESTS': False, | ||
615 | 37 | 'AUTOCOMMIT': True, | ||
616 | 38 | 'CONN_MAX_AGE': 600, | ||
617 | 39 | 'HOST': 'localhost', | ||
618 | 40 | 'NAME': 'revtracker', | ||
619 | 41 | 'OPTIONS': {}, | ||
620 | 42 | 'PORT': '', | ||
621 | 43 | 'TEST': { | ||
622 | 44 | 'NAME': None, | ||
623 | 45 | 'MIRROR': None, | ||
624 | 46 | 'CHARSET': None, | ||
625 | 47 | 'COLLATION': None, | ||
626 | 48 | }, | ||
627 | 49 | 'TIME_ZONE': 'UTC', | ||
628 | 50 | 'USER': 'postgres', | ||
629 | 51 | }, | ||
632 | 52 | } | 44 | } |
699 | 53 | 45 | DEBUG = env('DEBUG', '').lower() == 'true' | |
634 | 54 | TIME_ZONE = 'UTC' | ||
635 | 55 | |||
636 | 56 | LANGUAGE_CODE = 'en-us' | ||
637 | 57 | |||
638 | 58 | SITE_ID = 1 | ||
639 | 59 | |||
640 | 60 | USE_I18N = True | ||
641 | 61 | |||
642 | 62 | USE_L10N = True | ||
643 | 63 | |||
644 | 64 | MEDIA_ROOT = '' | ||
645 | 65 | |||
646 | 66 | MEDIA_URL = '' | ||
647 | 67 | |||
648 | 68 | STATIC_ROOT = 'static' | ||
649 | 69 | |||
650 | 70 | STATIC_URL = '/static/' | ||
651 | 71 | |||
652 | 72 | ADMIN_MEDIA_PREFIX = '/static/admin/' | ||
653 | 73 | |||
654 | 74 | STATICFILES_DIRS = ( | ||
655 | 75 | os.path.join(BASE_DIR, 'build/revtracker/js'), | ||
656 | 76 | ) | ||
657 | 77 | |||
658 | 78 | STATICFILES_FINDERS = ( | ||
659 | 79 | 'django.contrib.staticfiles.finders.FileSystemFinder', | ||
660 | 80 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', | ||
661 | 81 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder', | ||
662 | 82 | ) | ||
663 | 83 | |||
664 | 84 | SECRET_KEY = '6s!*-&#t8mks^8+7_2w%!oh8wh9uzzm-vzh5)l+7r2403+tm^!' | ||
665 | 85 | |||
666 | 86 | TEMPLATE_LOADERS = ( | ||
667 | 87 | 'django.template.loaders.filesystem.Loader', | ||
668 | 88 | 'django.template.loaders.app_directories.Loader', | ||
669 | 89 | 'django.template.loaders.eggs.Loader', | ||
670 | 90 | ) | ||
671 | 91 | |||
672 | 92 | MIDDLEWARE_CLASSES = ( | ||
673 | 93 | 'django.middleware.common.CommonMiddleware', | ||
674 | 94 | 'django.contrib.sessions.middleware.SessionMiddleware', | ||
675 | 95 | 'django.middleware.csrf.CsrfViewMiddleware', | ||
676 | 96 | 'django.contrib.auth.middleware.AuthenticationMiddleware', | ||
677 | 97 | 'django.contrib.messages.middleware.MessageMiddleware', | ||
678 | 98 | 'waffle.middleware.WaffleMiddleware', | ||
679 | 99 | #'debug_toolbar.middleware.DebugToolbarMiddleware', | ||
680 | 100 | ) | ||
681 | 101 | |||
682 | 102 | INTERNAL_IPS = ('127.0.0.1',) | ||
683 | 103 | |||
684 | 104 | ROOT_URLCONF = 'django_project.urls' | ||
685 | 105 | |||
686 | 106 | TEMPLATE_DIRS = ( | ||
687 | 107 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". | ||
688 | 108 | # Always use forward slashes, even on Windows. | ||
689 | 109 | # Don't forget to use absolute paths, not relative paths. | ||
690 | 110 | ) | ||
691 | 111 | |||
692 | 112 | TEMPLATE_CONTEXT_PROCESSORS = ( | ||
693 | 113 | "django.contrib.auth.context_processors.auth", | ||
694 | 114 | "django.core.context_processors.csrf", | ||
695 | 115 | "django.core.context_processors.static", | ||
696 | 116 | "django.core.context_processors.request", | ||
697 | 117 | ) | ||
698 | 118 | |||
700 | 119 | INSTALLED_APPS = ( | 46 | INSTALLED_APPS = ( |
701 | 120 | 'django.contrib.auth', | 47 | 'django.contrib.auth', |
702 | 121 | 'django.contrib.contenttypes', | 48 | 'django.contrib.contenttypes', |
703 | @@ -135,7 +62,8 @@ | |||
704 | 135 | 'pgtools', | 62 | 'pgtools', |
705 | 136 | #'debug_toolbar', | 63 | #'debug_toolbar', |
706 | 137 | ) | 64 | ) |
708 | 138 | 65 | INTERNAL_IPS = ('127.0.0.1',) | |
709 | 66 | LANGUAGE_CODE = 'en-us' | ||
710 | 139 | LOGGING = { | 67 | LOGGING = { |
711 | 140 | 'version': 1, | 68 | 'version': 1, |
712 | 141 | 'disable_existing_loggers': False, | 69 | 'disable_existing_loggers': False, |
713 | @@ -174,13 +102,57 @@ | |||
714 | 174 | }, | 102 | }, |
715 | 175 | } | 103 | } |
716 | 176 | } | 104 | } |
717 | 105 | LOGIN_URL = '/openid/login' | ||
718 | 106 | LOGIN_REDIRECT_URL = '/' | ||
719 | 107 | MIDDLEWARE_CLASSES = ( | ||
720 | 108 | 'django.middleware.common.CommonMiddleware', | ||
721 | 109 | 'django.contrib.sessions.middleware.SessionMiddleware', | ||
722 | 110 | 'django.middleware.csrf.CsrfViewMiddleware', | ||
723 | 111 | 'django.contrib.auth.middleware.AuthenticationMiddleware', | ||
724 | 112 | 'django.contrib.messages.middleware.MessageMiddleware', | ||
725 | 113 | 'waffle.middleware.WaffleMiddleware', | ||
726 | 114 | #'debug_toolbar.middleware.DebugToolbarMiddleware', | ||
727 | 115 | ) | ||
728 | 116 | ROOT_URLCONF = 'django_project.urls' | ||
729 | 117 | SECRET_KEY = env('SECRET_KEY', '') | ||
730 | 118 | SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' | ||
731 | 119 | STATIC_ROOT = 'static' | ||
732 | 120 | STATIC_URL = '/static/' | ||
733 | 121 | STATICFILES_DIRS = ( | ||
734 | 122 | os.path.join(BASE_DIR, 'build/revtracker/js'), | ||
735 | 123 | ) | ||
736 | 124 | STATICFILES_FINDERS = ( | ||
737 | 125 | 'django.contrib.staticfiles.finders.FileSystemFinder', | ||
738 | 126 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder', | ||
739 | 127 | ) | ||
740 | 128 | TEMPLATE_CONTEXT_PROCESSORS = ( | ||
741 | 129 | "django.contrib.auth.context_processors.auth", | ||
742 | 130 | "django.core.context_processors.csrf", | ||
743 | 131 | "django.core.context_processors.static", | ||
744 | 132 | "django.core.context_processors.request", | ||
745 | 133 | ) | ||
746 | 134 | TEMPLATE_LOADERS = ( | ||
747 | 135 | 'django.template.loaders.filesystem.Loader', | ||
748 | 136 | 'django.template.loaders.app_directories.Loader', | ||
749 | 137 | 'django.template.loaders.eggs.Loader', | ||
750 | 138 | ) | ||
751 | 139 | TEST_RUNNER = 'django.test.runner.DiscoverRunner' | ||
752 | 140 | TIME_ZONE = 'UTC' | ||
753 | 141 | USE_I18N = True | ||
754 | 142 | USE_L10N = True | ||
755 | 143 | |||
756 | 144 | # debug-toolbar settings | ||
757 | 177 | 145 | ||
758 | 178 | DEBUG_TOOLBAR_CONFIG = { | 146 | DEBUG_TOOLBAR_CONFIG = { |
759 | 179 | 'INTERCEPT_REDIRECTS': False, | 147 | 'INTERCEPT_REDIRECTS': False, |
760 | 180 | } | 148 | } |
761 | 181 | 149 | ||
763 | 182 | BRANCH_CACHE_DIR = "branches" | 150 | # celery settings |
764 | 183 | 151 | ||
765 | 152 | CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL', 'amqp://') | ||
766 | 153 | CELERY_ACCEPT_CONTENT = ['json'] | ||
767 | 154 | CELERY_TASK_SERIALIZER = 'json' | ||
768 | 155 | CELERY_RESULT_SERIALIZER = 'json' | ||
769 | 184 | CELERYBEAT_SCHEDULE = { | 156 | CELERYBEAT_SCHEDULE = { |
770 | 185 | "update_all_projects": { | 157 | "update_all_projects": { |
771 | 186 | "task": "revtracker.tasks.update_all_projects", | 158 | "task": "revtracker.tasks.update_all_projects", |
772 | @@ -192,14 +164,25 @@ | |||
773 | 192 | CELERYD_PREFETCH_MULTIPLIER = 1 | 164 | CELERYD_PREFETCH_MULTIPLIER = 1 |
774 | 193 | CELERYBEAT_SCHEDULE_FILENAME = 'tmp/celerybeat-schedule' | 165 | CELERYBEAT_SCHEDULE_FILENAME = 'tmp/celerybeat-schedule' |
775 | 194 | 166 | ||
784 | 195 | LOGIN_URL = '/openid/login' | 167 | # django-openid-auth settings |
785 | 196 | LOGIN_REDIRECT_URL = '/' | 168 | |
786 | 197 | 169 | OPENID_CREATE_USERS = True | |
787 | 198 | AUTHENTICATION_BACKENDS = ( | 170 | OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO = True |
788 | 199 | 'django_openid_auth.auth.OpenIDBackend', | 171 | OPENID_UPDATE_DETAILS_FROM_SREG = True |
789 | 200 | 'django.contrib.auth.backends.ModelBackend', | 172 | OPENID_SREG_REQUIRED_FIELDS = ['nickname'] |
790 | 201 | ) | 173 | OPENID_SSO_SERVER_URL = 'https://login.ubuntu.com/' |
791 | 202 | 174 | ||
792 | 175 | # revtracker settings | ||
793 | 176 | |||
794 | 177 | BRANCH_CACHE_DIR = "branches" | ||
795 | 178 | COMBO_URL = env('COMBO_URL', 'http://127.0.0.1:8001/') | ||
796 | 179 | CONVOY_ROOT = os.path.join(STATIC_ROOT, 'combo') | ||
797 | 180 | GIT_SSH_DEFAULT_USERNAME = pwd.getpwuid(os.getuid()).pw_name | ||
798 | 181 | GIT_SSH_DEFAULT_PORT = None | ||
799 | 182 | GIT_SSH_PRIVATE_KEY = os.path.expanduser('~/.ssh/id_rsa') | ||
800 | 183 | GIT_SSH_PUBLIC_KEY = os.path.expanduser('~/.ssh/id_rsa.pub') | ||
801 | 184 | LP_INSTANCE = 'production' | ||
802 | 185 | MULTILANG_OP_ENDPOINTS = False | ||
803 | 203 | OOPSES = { | 186 | OOPSES = { |
804 | 204 | 'publishers': [{ | 187 | 'publishers': [{ |
805 | 205 | 'inherit_id': False, | 188 | 'inherit_id': False, |
806 | @@ -209,40 +192,6 @@ | |||
807 | 209 | }], | 192 | }], |
808 | 210 | 'template': {'reporter': 'DEFAULT'}, | 193 | 'template': {'reporter': 'DEFAULT'}, |
809 | 211 | } | 194 | } |
825 | 212 | 195 | SOFT_TIMEOUT_MILLISECONDS = 10000 | |
826 | 213 | USE_HTTPS = True | 196 | USE_HTTPS = env('USE_HTTPS', 'true').lower() == 'true' |
812 | 214 | |||
813 | 215 | OPENID_SSO_SERVER_URL = 'https://login.ubuntu.com/' | ||
814 | 216 | OPENID_CREATE_USERS = True | ||
815 | 217 | OPENID_UPDATE_DETAILS_FROM_SREG = True | ||
816 | 218 | OPENID_SREG_REQUIRED_FIELDS = ['nickname'] | ||
817 | 219 | OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO = True | ||
818 | 220 | |||
819 | 221 | MULTILANG_OP_ENDPOINTS = False | ||
820 | 222 | |||
821 | 223 | COMBO_URL = 'http://127.0.0.1:8001/' | ||
822 | 224 | |||
823 | 225 | CONVOY_ROOT = os.path.join(STATIC_ROOT, 'combo') | ||
824 | 226 | |||
827 | 227 | WAFFLE_OVERRIDE = True | 197 | WAFFLE_OVERRIDE = True |
828 | 228 | SOFT_TIMEOUT_MILLISECONDS = 10000 | ||
829 | 229 | |||
830 | 230 | CSRF_COOKIE_DOMAIN = None | ||
831 | 231 | CSRF_COOKIE_HTTPONLY = False | ||
832 | 232 | CSRF_COOKIE_NAME = 'csrftoken' | ||
833 | 233 | CSRF_COOKIE_PATH = '/' | ||
834 | 234 | CSRF_COOKIE_SECURE = False | ||
835 | 235 | CSRF_FAILURE_VIEW = 'django.views.csrf.csrf_failure' | ||
836 | 236 | |||
837 | 237 | TEST_RUNNER = 'django.test.runner.DiscoverRunner' | ||
838 | 238 | SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' | ||
839 | 239 | |||
840 | 240 | LP_INSTANCE = 'production' | ||
841 | 241 | |||
842 | 242 | GIT_SSH_DEFAULT_USERNAME = pwd.getpwuid(os.getuid()).pw_name | ||
843 | 243 | GIT_SSH_DEFAULT_PORT = None | ||
844 | 244 | GIT_SSH_PRIVATE_KEY = os.path.expanduser('~/.ssh/id_rsa') | ||
845 | 245 | GIT_SSH_PUBLIC_KEY = os.path.expanduser('~/.ssh/id_rsa.pub') | ||
846 | 246 | |||
847 | 247 | |||
848 | 248 | sys.path.insert(0, os.path.dirname(__file__)) | ||
849 | 249 | 198 | ||
850 | === added file 'django_project/settings_build.py' | |||
851 | --- django_project/settings_build.py 1970-01-01 00:00:00 +0000 | |||
852 | +++ django_project/settings_build.py 2017-08-01 11:41:20 +0000 | |||
853 | @@ -0,0 +1,12 @@ | |||
854 | 1 | import os | ||
855 | 2 | |||
856 | 3 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||
857 | 4 | |||
858 | 5 | os.environ.setdefault( | ||
859 | 6 | 'DPA_LOGS_DIR', | ||
860 | 7 | os.path.abspath(os.path.join(BASE_DIR, 'logs'))) | ||
861 | 8 | |||
862 | 9 | from django_project.settings_base import * # noqa | ||
863 | 10 | |||
864 | 11 | DATABASES = {} | ||
865 | 12 | SECRET_KEY = 'build-secret-key' | ||
866 | 0 | 13 | ||
867 | === modified file 'django_project/settings_devel.py' | |||
868 | --- django_project/settings_devel.py 2016-07-25 20:52:24 +0000 | |||
869 | +++ django_project/settings_devel.py 2017-08-01 11:41:20 +0000 | |||
870 | @@ -1,8 +1,20 @@ | |||
875 | 1 | from django_project.settings_base import * # noqa | 1 | import os |
876 | 2 | 2 | ||
877 | 3 | DATABASES['default']['HOST'] = '/dev/shm/pg_deployable' | 3 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
878 | 4 | USE_HTTPS = False | 4 | |
879 | 5 | os.environ.setdefault('ALLOWED_HOSTS', "['*']") | ||
880 | 5 | # Serve combo data from a relative url - served by project's gunicorn | 6 | # Serve combo data from a relative url - served by project's gunicorn |
881 | 6 | # directly. | 7 | # directly. |
883 | 7 | COMBO_URL = '/combo/' | 8 | os.environ.setdefault('COMBO_URL', '/combo/') |
884 | 9 | os.environ.setdefault( | ||
885 | 10 | 'DATABASE_URL', | ||
886 | 11 | 'postgres://postgres@%2Fdev%2Fshm%2Fpg_deployable/revtracker') | ||
887 | 12 | os.environ.setdefault('DEBUG', 'true') | ||
888 | 13 | os.environ.setdefault( | ||
889 | 14 | 'DPA_LOGS_DIR', | ||
890 | 15 | os.path.abspath(os.path.join(BASE_DIR, 'logs'))) | ||
891 | 16 | os.environ.setdefault( | ||
892 | 17 | 'SECRET_KEY', '6s!*-&#t8mks^8+7_2w%!oh8wh9uzzm-vzh5)l+7r2403+tm^!') | ||
893 | 18 | os.environ.setdefault('USE_HTTPS', 'false') | ||
894 | 8 | 19 | ||
895 | 20 | from django_project.settings_base import * # noqa | ||
896 | 9 | 21 | ||
897 | === added file 'docker-compose.dev.yml' | |||
898 | --- docker-compose.dev.yml 1970-01-01 00:00:00 +0000 | |||
899 | +++ docker-compose.dev.yml 2017-08-01 11:41:20 +0000 | |||
900 | @@ -0,0 +1,24 @@ | |||
901 | 1 | version: '2' | ||
902 | 2 | services: | ||
903 | 3 | app: | ||
904 | 4 | restart: always | ||
905 | 5 | build: . | ||
906 | 6 | image: deployable:dev | ||
907 | 7 | command: ["./branches/wait-for-it/wait-for-it.sh", "db:5432", "--", "make", "app-start"] | ||
908 | 8 | volumes: | ||
909 | 9 | - .:/usr/src/app | ||
910 | 10 | ports: | ||
911 | 11 | - "8000:8000" | ||
912 | 12 | environment: | ||
913 | 13 | CELERY_BROKER_URL: amqp://amqp | ||
914 | 14 | DATABASE_URL: postgres://postgres@db/postgres | ||
915 | 15 | DJANGO_SETTINGS_MODULE: "django_project.settings_devel" | ||
916 | 16 | worker: | ||
917 | 17 | restart: always | ||
918 | 18 | image: deployable:dev | ||
919 | 19 | volumes: | ||
920 | 20 | - .:/usr/src/app | ||
921 | 21 | environment: | ||
922 | 22 | CELERY_BROKER_URL: amqp://amqp | ||
923 | 23 | DATABASE_URL: postgres://postgres@db/postgres | ||
924 | 24 | DJANGO_SETTINGS_MODULE: "django_project.settings_devel" | ||
925 | 0 | 25 | ||
926 | === added file 'docker-compose.secrets.yml' | |||
927 | --- docker-compose.secrets.yml 1970-01-01 00:00:00 +0000 | |||
928 | +++ docker-compose.secrets.yml 2017-08-01 11:41:20 +0000 | |||
929 | @@ -0,0 +1,5 @@ | |||
930 | 1 | version: '2' | ||
931 | 2 | services: | ||
932 | 3 | app: | ||
933 | 4 | # environment: | ||
934 | 5 | # SECRET_KEY: 'changeme' | ||
935 | 0 | 6 | ||
936 | === added file 'docker-compose.test.yml' | |||
937 | --- docker-compose.test.yml 1970-01-01 00:00:00 +0000 | |||
938 | +++ docker-compose.test.yml 2017-08-01 11:41:20 +0000 | |||
939 | @@ -0,0 +1,9 @@ | |||
940 | 1 | version: '2' | ||
941 | 2 | services: | ||
942 | 3 | app: | ||
943 | 4 | extends: | ||
944 | 5 | file: docker-compose.dev.yml | ||
945 | 6 | service: app | ||
946 | 7 | build: | ||
947 | 8 | dockerfile: Dockerfile.test | ||
948 | 9 | image: deployable:test | ||
949 | 0 | 10 | ||
950 | === added file 'docker-compose.yml' | |||
951 | --- docker-compose.yml 1970-01-01 00:00:00 +0000 | |||
952 | +++ docker-compose.yml 2017-08-01 11:41:20 +0000 | |||
953 | @@ -0,0 +1,19 @@ | |||
954 | 1 | version: '2' | ||
955 | 2 | services: | ||
956 | 3 | db: | ||
957 | 4 | image: postgres | ||
958 | 5 | expose: | ||
959 | 6 | - "5432" | ||
960 | 7 | amqp: | ||
961 | 8 | image: rabbitmq | ||
962 | 9 | app: | ||
963 | 10 | build: . | ||
964 | 11 | image: deployable | ||
965 | 12 | expose: | ||
966 | 13 | - "8000" | ||
967 | 14 | depends_on: | ||
968 | 15 | - db | ||
969 | 16 | - amqp | ||
970 | 17 | worker: | ||
971 | 18 | image: deployable | ||
972 | 19 | command: ["make", "worker-worker", "worker-beat"] | ||
973 | 0 | 20 | ||
974 | === added file 'requirements-docker.txt' | |||
975 | --- requirements-docker.txt 1970-01-01 00:00:00 +0000 | |||
976 | +++ requirements-docker.txt 2017-08-01 11:41:20 +0000 | |||
977 | @@ -0,0 +1,19 @@ | |||
978 | 1 | # direct dependencies | ||
979 | 2 | docker_compose==1.14.0 | ||
980 | 3 | |||
981 | 4 | # indirect dependencies | ||
982 | 5 | PyYAML==3.12 | ||
983 | 6 | backports.ssl_match_hostname==3.5.0.1 | ||
984 | 7 | cached_property==1.3.0 | ||
985 | 8 | colorama==0.3.9 | ||
986 | 9 | docker==2.4.2 | ||
987 | 10 | docker_pycreds==0.2.1 | ||
988 | 11 | dockerpty==0.4.1 | ||
989 | 12 | docopt==0.6.2 | ||
990 | 13 | enum34==1.1.6 | ||
991 | 14 | functools32==3.2.3-2 | ||
992 | 15 | ipaddress==1.0.18 | ||
993 | 16 | jsonschema==2.6.0 | ||
994 | 17 | requests==2.11.1 | ||
995 | 18 | texttable==0.8.8 | ||
996 | 19 | websocket_client==0.44.0 | ||
997 | 0 | 20 | ||
998 | === modified file 'requirements.txt' | |||
999 | --- requirements.txt 2016-09-02 22:32:27 +0000 | |||
1000 | +++ requirements.txt 2017-08-01 11:41:20 +0000 | |||
1001 | @@ -11,6 +11,7 @@ | |||
1002 | 11 | django-debug-toolbar==0.10.0 | 11 | django-debug-toolbar==0.10.0 |
1003 | 12 | django-devserver==0.7.0 | 12 | django-devserver==0.7.0 |
1004 | 13 | django-factory==0.10 | 13 | django-factory==0.10 |
1005 | 14 | django-getenv==1.3.1 | ||
1006 | 14 | django-kombu==0.9.4 | 15 | django-kombu==0.9.4 |
1007 | 15 | django-openid-auth==0.9 | 16 | django-openid-auth==0.9 |
1008 | 16 | # A checkout of https://github.com/bfirsh/django-ordered-model at 2998740eeda348473d8a8965b40b2292c31efd85 | 17 | # A checkout of https://github.com/bfirsh/django-ordered-model at 2998740eeda348473d8a8965b40b2292c31efd85 |
1009 | @@ -18,6 +19,7 @@ | |||
1010 | 18 | django-picklefield==0.2.1 | 19 | django-picklefield==0.2.1 |
1011 | 19 | django-pgtools==0.2 | 20 | django-pgtools==0.2 |
1012 | 20 | django-waffle==0.10.1 | 21 | django-waffle==0.10.1 |
1013 | 22 | dj-database-url==0.4.2 | ||
1014 | 21 | gorun==1.7 | 23 | gorun==1.7 |
1015 | 22 | gunicorn==19.3.0 | 24 | gunicorn==19.3.0 |
1016 | 23 | html5lib==0.9999999 | 25 | html5lib==0.9999999 |
besides the weird missing modules errors, it worked!