Skip to content
This repository was archived by the owner on Jul 14, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,22 @@ To add a new backend, perform the following steps:
fragment again, use

haproxy-config remove <fragment_name>

Running the integration test playbook
-------------------------------------

You can run the integration test playbook in `tests/integration.yml` against a
server with a vanilla Ubuntu 16.04 image. You need at least one DNS name
pointing at the server, and DNS changes should already have propagated.

1. Create a Python virtualenv and activate it.

2. Change to the `tests/` directory and run `pip install -r requirements.txt` to
install Ansible and further required packages.

3. Run the playbook using

ansible-playbook -vvv -i test.server.domain, integration.yml

Replace test.server.domain by the DNS name of your test server, but make sure
to keep the trailing comma.
3 changes: 3 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
LOAD_BALANCER_SERVER_IP: "{{ lookup('dig', ansible_host) }}"

LOAD_BALANCER_OPS_EMAIL: [email protected]

LOAD_BALANCER_APT_PACKAGES:
- haproxy
- letsencrypt
- inotify-tools
- python3-openssl
- socat
- ssl-cert

LOAD_BALANCER_CERTS_DIR: /etc/haproxy/certs
LOAD_BALANCER_CONF_DIR: /etc/haproxy/conf.d
Expand Down
10 changes: 7 additions & 3 deletions templates/haproxy-config-watcher
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ update_cert()
# It is important to note that haproxy.conf and backend.map are not contained
# in any of the watched directories, since these files are regenerated upon
# restart. Otherwise each restart immediately triggers another restart.
inotifywait -e close_write -e moved_to -m -q -r \
inotifywait -e close_write -e moved_to -e delete -m -q -r \
{{ LOAD_BALANCER_CERTS_DIR }} {{ LOAD_BALANCER_CONF_DIR }} \
{{ LOAD_BALANCER_BACKENDS_DIR }} {{ LETSENCRYPT_ARCHIVE_DIR }} |
while read path event file; do
case "$path" in
{{ LETSENCRYPT_ARCHIVE_DIR }}/*)
update_cert "$path" "$file";;
if [ "$event" != "delete" ]; then
update_cert "$path" "$file"
fi
;;
{{ LOAD_BALANCER_CERTS_DIR }}/*|{{ LOAD_BALANCER_CONF_DIR }}/*|{{ LOAD_BALANCER_BACKENDS_DIR }}/*)
touch {{ LOAD_BALANCER_RELOAD_FILE }};;
touch {{ LOAD_BALANCER_RELOAD_FILE }}
;;
esac
done
2 changes: 1 addition & 1 deletion templates/manage_certs.conf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
--server-ip {{ LOAD_BALANCER_SERVER_IP }}
--haproxy-backend-map {{ LOAD_BALANCER_BACKEND_MAP }}
--haproxy-certs-dir {{ LOAD_BALANCER_CERTS_DIR }}
--contact-email {{ OPS_EMAIL }}
--contact-email {{ LOAD_BALANCER_OPS_EMAIL }}
--log-level {{ LOAD_BALANCER_MANAGE_CERTS_LOG_LEVEL }}
--keep-certificate {{ LOAD_BALANCER_SNAKE_OIL_CERT }}
{% if LETSENCRYPT_USE_STAGING %}
Expand Down
1 change: 1 addition & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.retry
63 changes: 63 additions & 0 deletions tests/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---

- name: Install Python 2
hosts: all
gather_facts: false
tasks:
- raw: "[ -e /usr/bin/pyton ] || sudo apt-get update -qq && sudo apt-get install -qq python"

- name: Integration test for the load-balancer role
hosts: all
become: true
vars:
TEST_DOMAIN: "{{ inventory_hostname }}"
LETSENCRYPT_USE_STAGING: true
LOAD_BALANCER_MANAGE_CERTS_LOG_LEVEL: debug

pre_tasks:
- assert:
that: "lookup('dig', ansible_host) == lookup('dig', TEST_DOMAIN)"
msg: "The DNS entry for {{ TEST_DOMAIN }} must point to the test server."

roles:
- load-balancer

tasks:
- name: copy load-balancer configuration fragment to the server
copy:
content: |
backend be-load-balancer-test
server srv-pydoc 127.0.0.1:5000
dest: /tmp/config-fragment
- name: copy load-balancer backend map fragment to the server
copy:
content: "{{ TEST_DOMAIN }} be-load-balancer-test\n"
dest: /tmp/backend-map-fragment
- name: apply the new configuration
command: haproxy-config apply test /tmp/config-fragment /tmp/backend-map-fragment
- name: wait for the certificate to be available
wait_for:
path: "{{ LOAD_BALANCER_CERTS_DIR }}/{{ TEST_DOMAIN }}.pem"
timeout: 360
- name: wait for haproxy to be restarted
wait_for:
path: "{{ LOAD_BALANCER_RELOAD_FILE }}"
timeout: 100
state: absent
- name: start pydoc as test backend on the server
become: False
command: nohup pydoc -p 5000
async: 45
poll: 0
Copy link
Contributor

@bdero bdero Nov 5, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think I ran into this bug with ansible==2.0.1.0 on this async task:

fatal: [haproxy-test.bdero.me]: FAILED! => {"changed": false, "failed": true, "msg": "The async task did not return valid JSON: No JSON object could be decoded"}

I was able to steer around the problem by appending become: False. Can you add it in here since escalating to root isn't necessary for this task anyway?

- name: verify that the backend is accessible via HTTPS
become: False
local_action: >
command wget -O- --ca-certificate=../files/lets-encrypt-fake-cert.crt \
"https://{{ TEST_DOMAIN }}/"
- name: Remove configuration fragments again
command: haproxy-config remove test
- name: Wait for the certificate to be deleted again
wait_for:
path: "{{ LOAD_BALANCER_CERTS_DIR }}/{{ TEST_DOMAIN }}.pem"
timeout: 360
state: absent
2 changes: 2 additions & 0 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ansible==2.0.1
dnspython==1.15.0
1 change: 1 addition & 0 deletions tests/roles/load-balancer