Skip to content

Commit 5bcb9a9

Browse files
committed
add suggestions
also: - fix DJANGO_ALLOWED_HOSTS - change manage.py to src/manage.py
1 parent 6b9fc59 commit 5bcb9a9

File tree

1 file changed

+60
-4
lines changed

1 file changed

+60
-4
lines changed

chapter_11_ansible.asciidoc

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ At my registrar, the control screens looked a bit like <<registrar-control-scree
232232
.Domain setup
233233
image::images/gandi_add_dns_a_record.png["Registrar control screen for adding a DNS record"]
234234

235+
// CSANAD: due to technical reasons, I cannot check on Digital Ocean whether this
236+
// screenshot needs to be update. Please, someone else have a look!
237+
235238

236239
((("A-Records")))
237240
In the DNS system, pointing a domain at a specific IP address is called an "A-Record".
@@ -304,6 +307,8 @@ The "hate" part is that the actual syntax is surprisingly fiddly to get right:
304307
the difference between lists and key/value maps is subtle and I can never quite remember it honestly.]
305308
for.
306309

310+
// CSANAD: I would make it more obvious we created another directory for the
311+
// ansible file.
307312

308313
[role="sourcecode"]
309314
.infra/ansible-provision.yaml (ch11l001)
@@ -514,6 +519,8 @@ In Ansible config, it looks like this:
514519
recreate: true
515520
----
516521
====
522+
// CSANAD: I would add `update_cache: true` to the `Install docker` task back,
523+
// it's a good practice to update the apt cache before installing.
517524

518525
<1> We export the docker image to a `.tar` file by using the `docker_image` module
519526
with the `archive_path` set to temp file, and setting the `delegate_to` attribute
@@ -572,6 +579,7 @@ false, "AttachStdout": true, "Cmd": ["gunicorn", "--bind", ":8888",
572579
"superlists.wsgi:application"], "Domainname": "", "Entrypoint": null, "Env":
573580
[...]
574581
----
582+
// CSANAD: earlier we also added the `PLAY RECAP` line.
575583

576584

577585
For completeness, let's also add a step to explicitly build the image locally.
@@ -675,9 +683,13 @@ Here's what our template for the env file will looks like:
675683
----
676684
DJANGO_DEBUG_FALSE=1
677685
DJANGO_SECRET_KEY="{{ secret_key }}"
678-
DJANGO_ALLOWED_HOST="{{ host }}"
686+
DJANGO_ALLOWED_HOSTS="{{ host }}"
679687
----
680688
====
689+
// CSANAD: we named the allowed hosts' env variable in plural form, as it's
690+
// named in settings.py but we pass one value, so it feels weird.
691+
//
692+
// I'd suggest DJANGO_ALLOWED_HOSTS="{{ hostname }}"
681693

682694
And here's how we use it in the provisioning script:
683695

@@ -742,11 +754,18 @@ rather than specifying a series of steps to get there.
742754
This concept goes along with the idea of "idempotency",
743755
which is wanting to get the same result when you run something for the first time,
744756
vs running it again on later occations.
757+
// CSANAD: I would rephrase it a little:
758+
// "which means doing something multiple times brings the same results as
759+
// doing it for the first time."
745760
746761
An example is the `apt` module that we used to install docker.
747762
It doesn't crash if docker is already installed, and in fact,
748763
Ansible is smart enough to check first before trying to install anything.
749764
765+
// CSANAD: I think adding a counter-example, something that isn't idempotent
766+
// would be helpful. E.g. adding a list item to our superlist, because
767+
// it results in the list getting longer.
768+
750769
There is some subtlety here, for example, our templated env file
751770
will only be writen once, so the step is idempotent in the sense
752771
that it doesn't overwrite the file with a new random secret key every time you run it.
@@ -811,7 +830,7 @@ We run our tests as usual and run into a new problem:
811830

812831
[subs="specialcharacters,macros"]
813832
----
814-
$ pass:quotes[*TEST_SERVER=staging.ottg.co.uk python manage.py test functional_tests*]
833+
$ pass:quotes[*TEST_SERVER=staging.ottg.co.uk python src/manage.py test functional_tests*]
815834
[...]
816835
selenium.common.exceptions.WebDriverException: Message: Reached error page:
817836
about:neterror?e=connectionFailure&u=http%3A//staging.ottg.co.uk/[...]
@@ -828,6 +847,15 @@ $ pass:quotes[*curl -iv staging.ottg.co.uk*]
828847
curl: (7) Failed to connect to staging.ottg.co.uk port 80 after 25 ms: Couldn't
829848
connect to server
830849
----
850+
// CSANAD: my curl output looks a little different, saying "Connection refused"
851+
//
852+
// $ curl -iv 192.168.122.23
853+
// * Trying 192.168.122.23:80...
854+
// * connect to 192.168.122.23 port 80 failed: Connection refused
855+
// * Failed to connect to 192.168.122.23 port 80 after 2 ms: Connection refused
856+
// * Closing connection 0
857+
// curl: (7) Failed to connect to 192.168.122.23 port 80 after 2 ms: Connection refused
858+
831859

832860
Now let's ssh in and try `curl` from the server itself:
833861

@@ -855,6 +883,10 @@ curl: (7) Failed to connect to localhost port 80 after 0 ms: Connection refused
855883
----
856884

857885
Hmm, `curl` fails on the server too.
886+
// CSANAD: Ackchually I'm not sure if it's supposed to work, since we set
887+
// `inventory_hostname` for DJANGO_ALLOWED_HOSTS, so `localhost`
888+
// would not get through.
889+
858890
But all this talk of `port 80`, both locally and on the server, might be giving us a clue.
859891
Let's check `docker ps`:
860892

@@ -869,7 +901,7 @@ minutes superlists
869901

870902
This might be ringing a bell now--we forgot the ports.
871903

872-
We want to expose port 8888 inside the container as port 80 (the default web/http port)
904+
We want to map port 8888 inside the container as port 80 (the default web/http port)
873905
on the server:
874906

875907
[role="sourcecode"]
@@ -888,12 +920,24 @@ on the server:
888920
----
889921
====
890922

923+
// CSANAD: I would remind the reader we need to run ansible-playbook again.
924+
891925
That gets us to
892926

893927
----
894928
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate
895929
element: [id="id_list_table"]; [...]
896930
----
931+
// CSANAD: I have a different error:
932+
// AssertionError: 'To-Do' not found in 'Bad Request(400)'
933+
//
934+
// >>> from django.conf import settings
935+
// >>>
936+
// >>>
937+
// >>> settings.ALLOWED_HOSTS
938+
// ['"192.168.122.23"']
939+
// >>>
940+
//
897941

898942

899943
=== Mounting the database on the server and running migrations
@@ -909,6 +953,8 @@ django.db.utils.OperationalError: no such table: lists_list
909953
----
910954

911955

956+
// CSANAD: I think this `ansible-playbook` output was supposed to be shown after
957+
// the changes in the `ansible-provision.yaml`
912958
[subs="specialcharacters,quotes"]
913959
----
914960
$ *ansible-playbook --user=elspeth -i staging.ottg.co.uk, infra/ansible-provision.yaml -v*
@@ -929,6 +975,9 @@ skipped=0 rescued=0 ignored=0
929975

930976

931977
Here's how
978+
// CSANAD: I think a little more explanation is missing from here. Maybe just
979+
// a sentence, but just showing the changes and the output feels a
980+
// little incomplete.
932981

933982
[role="sourcecode"]
934983
.infra/ansible-provision.yaml (ch11l006)
@@ -981,7 +1030,7 @@ Hooray
9811030
[role="small-code"]
9821031
[subs="specialcharacters,macros"]
9831032
----
984-
$ pass:quotes[*TEST_SERVER=staging.ottg.co.uk python manage.py test functional_tests*]
1033+
$ pass:quotes[*TEST_SERVER=staging.ottg.co.uk python src/manage.py test functional_tests*]
9851034
Found 3 test(s).
9861035
[...]
9871036
@@ -1008,9 +1057,11 @@ and reloads it automatically if it crashes.
10081057
10091058
A few more places to look and things to try, now that we've introduced
10101059
Podman and Systemd into the mix, should things not go according to plan:
1060+
// CSANAD: we did not mention Podman or Systemd in this chapter
10111061
10121062
- You can check the Container logs using
10131063
`docker logs superlists`.
1064+
// CSANAD: we already used this a lot, so this isn't "more debugging tip"
10141065
10151066
- You can get detailed info on the Container using
10161067
`docker inspect superlists`.
@@ -1155,10 +1206,13 @@ which are a fairly typical set of steps for deployment in general
11551206
2. Installing *system dependencies* - in our case, it was mainly Docker,
11561207
but inside the Docker image, we also had some system dependencies too,
11571208
like Python itself.
1209+
// CSANAD: this is not true in the current edition as we are just using the
1210+
// superlists image which is built upon the python:slim
11581211
11591212
3. Getting our *application code* (or "artifacts") onto the server.
11601213
In our case, since we're using Docker, the thing we needed to transfer was a Docker image.
11611214
We used a manual process, but typically you'd push and pull to an image repository.
1215+
// CSANAD: we actually automated this step in this edition
11621216
11631217
4. Setting *environment variables and secrets*.
11641218
Depending on how you need to vary them,
@@ -1181,8 +1235,10 @@ which are a fairly typical set of steps for deployment in general
11811235
In our case, we stop the old container and start a new one.
11821236
In more advanced setups, you might be trying to achieve zero-downtime deploys,
11831237
and looking into techniques like red-green deployments.
1238+
// CSANAD: we haven't mentioned the downtime so far
11841239
11851240
// TODO is there a better word than "switching across"?
1241+
// CSANAD: I can only think of "releasing" or "deploying"
11861242
11871243
Every single aspect of deployment can and probably should be automated.
11881244
Here are a couple of general principles to think about

0 commit comments

Comments
 (0)