@@ -6,11 +6,11 @@ nav_order: 4
6
6
# Epidata API Development Guide
7
7
8
8
** Prerequisite:** this guide assumes that you have read the
9
- [ frontend development guide] ( https://github.com/cmu-delphi/operations/blob/master /docs/frontend_development.md ) .
9
+ [ frontend development guide] ( https://github.com/cmu-delphi/operations/blob/main /docs/frontend_development.md ) .
10
10
11
11
This guide describes how to write and test code for the Epidata API. For
12
12
preliminary steps,
13
- [ install docker and create a virtual network] ( https://github.com/cmu-delphi/operations/blob/master /docs/frontend_development.md#setup ) .
13
+ [ install docker and create a virtual network] ( https://github.com/cmu-delphi/operations/blob/main /docs/frontend_development.md#setup ) .
14
14
15
15
After reading this guide, you may want to visit
16
16
[ the ` fluview_meta ` tutorial] ( new_endpoint_tutorial.md ) for an example of how
@@ -28,7 +28,7 @@ You likely won't need to modify the `operations` repo, so cloning directly from
28
28
` cmu-delphi ` is usually sufficient. However, since you _ are_ going to be
29
29
modifying ` delphi-epidata ` sources, you'll first need to fork the repository
30
30
and then clone your personal fork. For more details, see the Delphi-specific
31
- [ discussion on forking and branching] ( https://github.com/cmu-delphi/operations/blob/master /docs/backend_development.md#everyone ) .
31
+ [ discussion on forking and branching] ( https://github.com/cmu-delphi/operations/blob/main /docs/backend_development.md#everyone ) .
32
32
33
33
Here's an example of how to setup your local workspace. Note that you will need
34
34
to use your own GitHub username where indicated.
@@ -124,9 +124,9 @@ docker run --rm -p 127.0.0.1:10080:80 \
124
124
Unit tests are self-contained, and do not depend on external services like
125
125
databases or web servers. You can run unit tests at any time according to the
126
126
instructions in the
127
- [ backend development guide] ( https://github.com/cmu-delphi/operations/blob/master /docs/backend_development.md ) .
127
+ [ backend development guide] ( https://github.com/cmu-delphi/operations/blob/main /docs/backend_development.md ) .
128
128
129
- First, [ build the ` delphi_python ` image] ( https://github.com/cmu-delphi/operations/blob/master /docs/backend_development.md#creating-an-image ) .
129
+ First, [ build the ` delphi_python ` image] ( https://github.com/cmu-delphi/operations/blob/main /docs/backend_development.md#creating-an-image ) .
130
130
Your test sources will live in, and be executed from within, this image.
131
131
132
132
Then run the tests in a container based on that image:
@@ -242,7 +242,7 @@ point for additional tests. For example, see the tests for the
242
242
243
243
To run the existing tests and any new tests that you write, you must
244
244
follow the
245
- [ backend development guide] ( https://github.com/cmu-delphi/operations/blob/master /docs/backend_development.md )
245
+ [ backend development guide] ( https://github.com/cmu-delphi/operations/blob/main /docs/backend_development.md )
246
246
_ within the same workspace_ , so that the ` delphi_python ` image is created with
247
247
any changes you have made (e.g. adding new integration tests). That image will
248
248
contain the test driver and the source code of your integration tests. Then,
@@ -259,7 +259,7 @@ More concretely, you can run Epidata API integration tests like this:
259
259
above.
260
260
261
261
3 . Build the ` delphi_python ` image per the
262
- [ backend development guide] ( https://github.com/cmu-delphi/operations/blob/master /docs/backend_development.md#creating-an-image ) .
262
+ [ backend development guide] ( https://github.com/cmu-delphi/operations/blob/main /docs/backend_development.md#creating-an-image ) .
263
263
Your test sources will live in, and be executed from within, this image.
264
264
265
265
4 . Run integration tests in a container based on the ` delphi_python ` image:
@@ -285,3 +285,78 @@ More concretely, you can run Epidata API integration tests like this:
285
285
```
286
286
287
287
5 . Bring down the servers, for example with the ` docker stop ` command.
288
+
289
+ # rapid iteration
290
+
291
+ The workflow described above requires containers to be stopped, rebuilt, and
292
+ restarted each time code (including tests) is changed, which can be tedious. To
293
+ reduce friction, it's possible to
294
+ [ bind-mount] ( https://docs.docker.com/storage/bind-mounts/ ) your local source
295
+ files into a container, which replace the corresponding files from the image.
296
+ This allows your code changes to be reflected immediately, without needing to
297
+ rebuild containers.
298
+
299
+ There are some drawbacks however, as discussed in the
300
+ [ Epicast development guide] ( https://github.com/cmu-delphi/www-epicast/blob/main/docs/epicast_development.md#develop ) .
301
+ For example:
302
+
303
+ - Code running in the container is able to read (and possibly also write) your local filesystem.
304
+ - The command line specification of bind-mounts is quite tedious.
305
+ - Bind mounts do not interact well with ` selinux ` on some systems, leading to
306
+ various access denials at runtime. As a workaround, you may have to use the
307
+ [ dangerous "Z" flag] ( https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label ) ,
308
+ or temporarily disable ` selinux ` -- neither of which is advised.
309
+
310
+ ## bind-mounting
311
+
312
+ ### non-server code
313
+
314
+ Python sources (e.g. data acquisition, API clients, and tests), can be
315
+ bind-mounted into a ` delphi_python ` container as follows:
316
+
317
+ ``` bash
318
+ docker run --rm --network delphi-net \
319
+ --mount type=bind,source=" $( pwd) " /repos/delphi/delphi-epidata,target=/usr/src/app/repos/delphi/delphi-epidata,readonly \
320
+ --mount type=bind,source=" $( pwd) " /repos/delphi/delphi-epidata/src,target=/usr/src/app/delphi/epidata,readonly \
321
+ delphi_python \
322
+ python3 -m undefx.py3tester.py3tester --color \
323
+ repos/delphi/delphi-epidata/integrations
324
+ ```
325
+
326
+ The command above maps two local directories into the container:
327
+
328
+ - ` /repos/delphi/delphi-epidata ` : The entire repo, notably including unit and
329
+ integration test sources.
330
+ - ` /repos/delphi/delphi-epidata/src ` : Just the source code, which forms the
331
+ container's ` delphi.epidata ` python package.
332
+
333
+ ### server code
334
+
335
+ Local web sources (e.g. PHP files) can be bind-mounted into a
336
+ ` delphi_web_epidata ` container as follows:
337
+
338
+ ``` bash
339
+ docker run --rm -p 127.0.0.1:10080:80 \
340
+ --mount type=bind,source=" $( pwd) " /repos/delphi/delphi-epidata/src/server/api.php,target=/var/www/html/epidata/api.php,readonly \
341
+ --mount type=bind,source=" $( pwd) " /repos/delphi/delphi-epidata/src/server/api_helpers.php,target=/var/www/html/epidata/api_helpers.php,readonly \
342
+ --network delphi-net --name delphi_web_epidata \
343
+ delphi_web_epidata
344
+ ```
345
+
346
+ The command above mounts two specific files into the image. It may be tempting
347
+ to bind mount the ` src/server ` directory rather than specific files, however
348
+ that is currently problematic for a couple of reasons:
349
+
350
+ 1 . ` server/.htaccess ` [ from the local repository] ( ../src/server/.htaccess ) uses
351
+ the ` Header ` directive, however the web server in the container doesn't have
352
+ the corresponding module enabled. This causes the server to deny access to
353
+ the API.
354
+ 2 . ` server/database_config.php `
355
+ [ in the image] ( ../dev/docker/web/epidata/assets/database_config.php ) contains
356
+ database credentials for use in conjunction with the
357
+ ` delphi_database_epidata ` container during development. However, the same
358
+ file from [ the local repository] ( ../src/server/database_config.php ) only
359
+ contains placeholder values. This prevents communication with the database.
360
+
361
+ There is currently no benefit to bind-mounting sources into the database
362
+ container because schema changes require restarting the container anyway.
0 commit comments