diff --git a/defaults/main.yml b/defaults/main.yml index 452e5c7..dd9ef99 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -6,12 +6,7 @@ deploy_haproxy_version: latest deploy_haproxy_env_variables: {} deploy_haproxy_start_service: true deploy_haproxy_cert_dir: "" - -# docker-only options deploy_haproxy_extra_container_volumes: [] - -# Options from the "default" config block in haproxy.cfg -# The default values here are usually set, but you can change any of them. deploy_haproxy_global: - log /dev/log local0 - log /dev/log local1 notice @@ -49,11 +44,6 @@ deploy_haproxy_backends: # - server srv_nginx1 172.17.0.4:80 check inter 5s # - server srv_nginx2 172.17.0.3:80 check inter 5s -# listen configuration blocks -# the default values expose a monitoring listener on all interfaces on port 9000 -# /stats returns the haproxy dashboard (please change the user and password in the configuration) -# /health returns a 200 OK response as long as haproxy is alive and well -# /metrics returns prometheus metrics for the haproxy instance deploy_haproxy_listen: - name: monitoring options: diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml index ec450ea..8d18611 100644 --- a/molecule/default/verify.yml +++ b/molecule/default/verify.yml @@ -4,3 +4,176 @@ gather_facts: true become: true tasks: + - name: "Test: haproxy user and group" + block: + - name: "Getent user haproxy" + ansible.builtin.getent: + database: passwd + key: haproxy + register: haproxy_user + + - name: "Getent group haproxy" + ansible.builtin.getent: + database: group + key: haproxy + register: haproxy_group + + - name: "Verify haproxy user and group" + ansible.builtin.assert: + that: + - not haproxy_user.failed + - not haproxy_group.failed + - "'haproxy' in haproxy_user.ansible_facts.getent_passwd.keys()" + - "'/var/lib/haproxy' in haproxy_user.ansible_facts.getent_passwd['haproxy']" + - "'/bin/false' in haproxy_user.ansible_facts.getent_passwd['haproxy']" + - "'haproxy' in haproxy_group.ansible_facts.getent_group.keys()" + + - name: "Test: directory /etc/haproxy" + block: + - name: "Stat directory /etc/haproxy" + ansible.builtin.stat: + path: "/etc/haproxy" + register: stat_etc_haproxy + + - name: "Stat file /etc/haproxy/haproxy.env" + ansible.builtin.stat: + path: "/etc/haproxy/haproxy.env" + register: stat_etc_haproxy_haproxy_env + + - name: "Stat file /etc/haproxy/haproxy.cfg" + ansible.builtin.stat: + path: "/etc/haproxy/haproxy.cfg" + register: stat_etc_haproxy_haproxy_cfg + + - name: "Slurp file /etc/haproxy/haproxy.cfg" + ansible.builtin.slurp: + src: "/etc/haproxy/haproxy.cfg" + register: slurp_etc_haproxy_haproxy_cfg + + - name: "Verify directory /etc/haproxy" + ansible.builtin.assert: + that: + - stat_etc_haproxy.stat.exists + - stat_etc_haproxy.stat.isdir + - stat_etc_haproxy.stat.pw_name == 'haproxy' + - stat_etc_haproxy.stat.gr_name == 'haproxy' + - stat_etc_haproxy.stat.mode == '0755' + - stat_etc_haproxy_haproxy_env.stat.exists + - stat_etc_haproxy_haproxy_env.stat.isreg + - stat_etc_haproxy_haproxy_env.stat.pw_name == 'haproxy' + - stat_etc_haproxy_haproxy_env.stat.gr_name == 'haproxy' + - stat_etc_haproxy_haproxy_env.stat.mode == '0600' + - stat_etc_haproxy_haproxy_cfg.stat.exists + - stat_etc_haproxy_haproxy_cfg.stat.isreg + - stat_etc_haproxy_haproxy_cfg.stat.pw_name == 'haproxy' + - stat_etc_haproxy_haproxy_cfg.stat.gr_name == 'haproxy' + - stat_etc_haproxy_haproxy_cfg.stat.mode == '0600' + - slurp_etc_haproxy_haproxy_cfg.content != '' + + - name: "Test: directory /var/lib/haproxy" + block: + - name: "Stat directory /var/lib/haproxy" + ansible.builtin.stat: + path: "/var/lib/haproxy" + register: stat_var_lib_haproxy + + - name: "Stat socket /var/lib/haproxy/stats" + ansible.builtin.stat: + path: "/var/lib/haproxy/stats" + register: stat_var_lib_haproxy_stats + + - name: "Verify directory /var/lib/haproxy" + ansible.builtin.assert: + that: + - stat_var_lib_haproxy.stat.exists + - stat_var_lib_haproxy.stat.isdir + - stat_var_lib_haproxy.stat.pw_name == 'haproxy' + - stat_var_lib_haproxy.stat.gr_name == 'haproxy' + - stat_var_lib_haproxy.stat.mode == '0755' + - stat_var_lib_haproxy_stats.stat.exists + - stat_var_lib_haproxy_stats.stat.issock + + - name: "Test: service haproxy" + block: + - name: "Get service haproxy" + ansible.builtin.service_facts: + + - name: "Stat file /etc/systemd/system/haproxy.service" + ansible.builtin.stat: + path: "/etc/systemd/system/haproxy.service" + register: stat_etc_systemd_system_haproxy_service + + - name: "Slurp file /etc/systemd/system/haproxy.service" + ansible.builtin.slurp: + src: "/etc/systemd/system/haproxy.service" + register: slurp_etc_systemd_system_haproxy_service + + - name: "Verify service haproxy" + vars: + haproxy_expected_service_file: | + # Ansible managed: Do NOT edit this file manually! + [Unit] + Description=HAProxy Load Balancer + Documentation=man:haproxy(1) + Documentation=file:/usr/share/doc/haproxy/configuration.txt.gz + ConditionFileNotEmpty=/etc/haproxy/haproxy.cfg + After=network-online.target rsyslog.service + Wants=network-online.target + + [Service] + EnvironmentFile=-/etc/default/haproxy + EnvironmentFile=-/etc/haproxy/haproxy.env + BindReadOnlyPaths=/dev/log:/var/lib/haproxy/dev/log + Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "EXTRAOPTS=-S /run/haproxy-master.sock" + ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE $EXTRAOPTS + ExecReload=/usr/sbin/haproxy -Ws -f $CONFIG -c $EXTRAOPTS + ExecReload=/bin/kill -USR2 $MAINPID + KillMode=mixed + Restart=always + SuccessExitStatus=143 + Type=notify + + [Install] + WantedBy=multi-user.target + ansible.builtin.assert: + that: + - stat_etc_systemd_system_haproxy_service.stat.exists + - stat_etc_systemd_system_haproxy_service.stat.isreg + - stat_etc_systemd_system_haproxy_service.stat.pw_name == 'root' + - stat_etc_systemd_system_haproxy_service.stat.gr_name == 'root' + - stat_etc_systemd_system_haproxy_service.stat.mode == '0644' + - (slurp_etc_systemd_system_haproxy_service.content|b64decode) == haproxy_expected_service_file + - ansible_facts.services['haproxy.service'] is defined + - ansible_facts.services['haproxy.service']['source'] == 'systemd' + - ansible_facts.services['haproxy.service']['state'] == 'running' + - ansible_facts.services['haproxy.service']['status'] == 'enabled' + + - name: "Test: haproxy endpoints" + block: + - name: "Get haproxy /health" + ansible.builtin.uri: + url: "http://127.0.0.1:9000/health" + method: GET + register: haproxy_health_endpoint + + - name: "Get haproxy /stats" + ansible.builtin.uri: + url: "http://127.0.0.1:9000/stats" + method: GET + force_basic_auth: true + url_username: admin + url_password: password + register: haproxy_stats_endpoint + + - name: "Get haproxy /metrics" + ansible.builtin.uri: + url: "http://127.0.0.1:9000/metrics" + method: GET + register: haproxy_metrics_endpoint + + - name: "Verify haproxy endpoints" + ansible.builtin.assert: + that: + - haproxy_health_endpoint.status == 200 + - haproxy_stats_endpoint.status == 200 + - haproxy_metrics_endpoint.status == 200 diff --git a/molecule/default_vagrant/group_vars/all.yml b/molecule/default_vagrant/group_vars/all.yml index 019cbb1..9a4a1df 100644 --- a/molecule/default_vagrant/group_vars/all.yml +++ b/molecule/default_vagrant/group_vars/all.yml @@ -1,15 +1,10 @@ --- deploy_haproxy_deploy_method: docker # deployment method, either host or docker -deploy_haproxy_version: "2.8" - +deploy_haproxy_version: latest deploy_haproxy_env_variables: {} deploy_haproxy_start_service: true - -# docker-only options +deploy_haproxy_cert_dir: "" deploy_haproxy_extra_container_volumes: [] - -# Options from the "default" config block in haproxy.cfg -# The default values here are usually set, but you can change any of them. deploy_haproxy_global: - log stdout format raw daemon debug - stats socket {{ deploy_haproxy_socket }} level admin @@ -26,29 +21,10 @@ deploy_haproxy_defaults: - timeout client 5000 - timeout server 5000 -deploy_haproxy_frontends: - - name: default - options: - - description default frontend - - mode http - - bind :1024 - - default_backend default +deploy_haproxy_frontends: [] -deploy_haproxy_backends: - - name: default - options: - - description default backend - - option forwardfor - - option httpchk - - http-check send meth GET uri / - - server srv_nginx1 172.17.0.2:80 check inter 5s - - server srv_nginx2 172.17.0.3:80 check inter 5s +deploy_haproxy_backends: [] -# listen configuration blocks -# the default values expose a monitoring listener on all interfaces on port 9000 -# /stats returns the haproxy dashboard (please change the user and password in the configuration) -# /health returns a 200 OK response as long as haproxy is alive and well -# /metrics returns prometheus metrics for the haproxy instance deploy_haproxy_listen: - name: monitoring options: diff --git a/molecule/default_vagrant/verify.yml b/molecule/default_vagrant/verify.yml index ec450ea..7323efb 100644 --- a/molecule/default_vagrant/verify.yml +++ b/molecule/default_vagrant/verify.yml @@ -4,3 +4,151 @@ gather_facts: true become: true tasks: + - name: "Test: directory /etc/haproxy" + block: + - name: "Stat directory /etc/haproxy" + ansible.builtin.stat: + path: "/etc/haproxy" + register: stat_etc_haproxy + + - name: "Stat file /etc/default/haproxy" + ansible.builtin.stat: + path: "/etc/default/haproxy" + register: stat_etc_default_haproxy + + - name: "Stat file /etc/haproxy/haproxy.cfg" + ansible.builtin.stat: + path: "/etc/haproxy/haproxy.cfg" + register: stat_etc_haproxy_haproxy_cfg + + - name: "Slurp file /etc/haproxy/haproxy.cfg" + ansible.builtin.slurp: + src: "/etc/haproxy/haproxy.cfg" + register: slurp_etc_haproxy_haproxy_cfg + + - name: "Verify directory /etc/haproxy" + ansible.builtin.assert: + that: + - stat_etc_haproxy.stat.exists + - stat_etc_haproxy.stat.isdir + - (stat_etc_haproxy.stat.uid | int) == 99 + - (stat_etc_haproxy.stat.gid | int) == 99 + - stat_etc_haproxy.stat.mode == '0755' + - stat_etc_default_haproxy.stat.exists + - stat_etc_default_haproxy.stat.isreg + - stat_etc_default_haproxy.stat.pw_name == 'root' + - stat_etc_default_haproxy.stat.gr_name == 'root' + - stat_etc_default_haproxy.stat.mode == '0600' + - stat_etc_haproxy_haproxy_cfg.stat.exists + - stat_etc_haproxy_haproxy_cfg.stat.isreg + - (stat_etc_haproxy_haproxy_cfg.stat.uid | int) == 99 + - (stat_etc_haproxy_haproxy_cfg.stat.gid | int) == 99 + - stat_etc_haproxy_haproxy_cfg.stat.mode == '0600' + - slurp_etc_haproxy_haproxy_cfg.content != '' + + - name: "Test: directory /var/lib/haproxy" + block: + - name: "Stat directory /var/lib/haproxy" + ansible.builtin.stat: + path: "/var/lib/haproxy" + register: stat_var_lib_haproxy + + - name: "Stat socket /var/lib/haproxy/stats" + ansible.builtin.stat: + path: "/var/lib/haproxy/stats" + register: stat_var_lib_haproxy_stats + + - name: "Verify directory /var/lib/haproxy" + ansible.builtin.assert: + that: + - stat_var_lib_haproxy.stat.exists + - stat_var_lib_haproxy.stat.isdir + - (stat_var_lib_haproxy.stat.uid | int) == 99 + - (stat_var_lib_haproxy.stat.gid | int) == 99 + - stat_var_lib_haproxy.stat.mode == '0755' + - stat_var_lib_haproxy_stats.stat.exists + - stat_var_lib_haproxy_stats.stat.issock + + - name: "Test: service haproxy" + block: + - name: "Get service haproxy" + ansible.builtin.service_facts: + + - name: "Stat file /etc/systemd/system/haproxy_container.service" + ansible.builtin.stat: + path: "/etc/systemd/system/haproxy_container.service" + register: stat_etc_systemd_system_haproxy_container_service + + - name: "Slurp file /etc/systemd/system/haproxy_container.service" + ansible.builtin.slurp: + src: "/etc/systemd/system/haproxy_container.service" + register: slurp_etc_systemd_system_haproxy_container_service + + - name: "Verify service haproxy" + vars: + haproxy_expected_service_file: | + # Ansible managed: Do NOT edit this file manually! + [Unit] + After=docker.service + PartOf=docker.service + Requires=docker.service + + [Service] + EnvironmentFile=/etc/default/haproxy + ExecStartPre=-/usr/bin/docker rm -f haproxy + ExecStart=/usr/bin/docker run --name haproxy \ + --rm \ + --env-file /etc/default/haproxy \ + --network "host" \ + --volume "/etc/haproxy:/usr/local/etc/haproxy" \ + --volume "/var/lib/haproxy:/var/lib/haproxy" \ + haproxytech/haproxy-debian:latest + ExecStop=/usr/bin/docker stop haproxy + SyslogIdentifier=haproxy + Restart=always + RestartSec=10s + + [Install] + WantedBy=docker.service + ansible.builtin.assert: + that: + - stat_etc_systemd_system_haproxy_container_service.stat.exists + - stat_etc_systemd_system_haproxy_container_service.stat.isreg + - stat_etc_systemd_system_haproxy_container_service.stat.pw_name == 'root' + - stat_etc_systemd_system_haproxy_container_service.stat.gr_name == 'root' + - stat_etc_systemd_system_haproxy_container_service.stat.mode == '0644' + - (slurp_etc_systemd_system_haproxy_container_service.content|b64decode) == haproxy_expected_service_file + - ansible_facts.services['haproxy_container.service'] is defined + - ansible_facts.services['haproxy_container.service']['source'] == 'systemd' + - ansible_facts.services['haproxy_container.service']['state'] == 'running' + - ansible_facts.services['haproxy_container.service']['status'] == 'enabled' + + - name: "Test: haproxy endpoints" + block: + - name: "Get haproxy /health" + ansible.builtin.uri: + url: "http://127.0.0.1:9000/health" + method: GET + register: haproxy_health_endpoint + + - name: "Get haproxy /stats" + ansible.builtin.uri: + url: "http://127.0.0.1:9000/stats" + method: GET + force_basic_auth: true + url_username: admin + url_password: password + register: haproxy_stats_endpoint + + - name: "Get haproxy /metrics" + ansible.builtin.uri: + url: "http://127.0.0.1:9000/metrics" + method: GET + register: haproxy_metrics_endpoint + + - name: "Verify haproxy endpoints" + ansible.builtin.assert: + that: + - haproxy_health_endpoint.status == 200 + - haproxy_stats_endpoint.status == 200 + - haproxy_metrics_endpoint.status == 200 diff --git a/molecule/with_tls_enabled/converge.yml b/molecule/with_tls_enabled/converge.yml new file mode 100644 index 0000000..433aaa7 --- /dev/null +++ b/molecule/with_tls_enabled/converge.yml @@ -0,0 +1,8 @@ +--- +- name: Converge + hosts: all + become: true + tasks: + - name: "Include ednxzu.deploy_haproxy" + ansible.builtin.include_role: + name: "ednxzu.deploy_haproxy" diff --git a/molecule/with_tls_enabled/group_vars/all.yml b/molecule/with_tls_enabled/group_vars/all.yml new file mode 100644 index 0000000..acfb0a9 --- /dev/null +++ b/molecule/with_tls_enabled/group_vars/all.yml @@ -0,0 +1,43 @@ +--- +deploy_haproxy_deploy_method: host # deployment method, either host or docker +deploy_haproxy_version: "2.8" +deploy_haproxy_env_variables: {} +deploy_haproxy_start_service: true +deploy_haproxy_cert_dir: "/tmp/haproxy-cert" +deploy_haproxy_extra_container_volumes: [] +deploy_haproxy_global: + - log /dev/log local0 + - log /dev/log local1 notice + - stats socket {{ deploy_haproxy_socket }} level admin + - chroot {{ deploy_haproxy_chroot }} + - daemon + - description hashistack haproxy + +deploy_haproxy_defaults: + - log global + - mode http + - option httplog + - option dontlognull + - timeout connect 5000 + - timeout client 5000 + - timeout server 5000 + +deploy_haproxy_frontends: [] +deploy_haproxy_backends: [] +deploy_haproxy_listen: + - name: monitoring + options: + - bind :9000 ssl crt /var/lib/haproxy/certs/cert.pem + - mode http + - option httpchk + - stats enable + - stats uri /stats + - stats refresh 30s + - stats show-desc + - stats show-legends + - stats auth admin:password + - http-check send meth GET uri /health ver HTTP/1.1 hdr Host localhost + - http-check expect status 200 + - acl health_check_ok nbsrv() ge 1 + - monitor-uri /health + - http-request use-service prometheus-exporter if { path /metrics } diff --git a/molecule/with_tls_enabled/molecule.yml b/molecule/with_tls_enabled/molecule.yml new file mode 100644 index 0000000..11708bd --- /dev/null +++ b/molecule/with_tls_enabled/molecule.yml @@ -0,0 +1,37 @@ +--- +dependency: + name: galaxy + options: + requirements-file: ./requirements.yml +driver: + name: docker +platforms: + - name: instance + image: geerlingguy/docker-${MOLECULE_TEST_OS}-ansible + command: "" + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup + cgroupns_mode: host + privileged: true + pre_build_image: true +provisioner: + name: ansible + config_options: + defaults: + remote_tmp: /tmp/.ansible +verifier: + name: ansible +scenario: + name: with_tls_enabled + test_sequence: + - dependency + - cleanup + - destroy + - syntax + - create + - prepare + - converge + - idempotence + - verify + - cleanup + - destroy diff --git a/molecule/with_tls_enabled/prepare.yml b/molecule/with_tls_enabled/prepare.yml new file mode 100644 index 0000000..de4880a --- /dev/null +++ b/molecule/with_tls_enabled/prepare.yml @@ -0,0 +1,38 @@ +--- +- name: Prepare + hosts: all + become: true + tasks: + - name: "Generate self-signed certificates" # noqa: run-once[task] + delegate_to: localhost + run_once: true + block: + - name: "Create temporary cert directory /tmp/haproxy-cert" + ansible.builtin.file: + path: "/tmp/haproxy-cert" + state: directory + owner: "1000" + group: "1000" + mode: "0777" + + - name: "Create private key" + community.crypto.openssl_privatekey: + path: /tmp/haproxy-cert/cert.pem.key + owner: "1000" + group: "1000" + + - name: "Create certificate signing request" + community.crypto.openssl_csr_pipe: + privatekey_path: /tmp/haproxy-cert/cert.pem.key + common_name: haproxy.ansible.test + organization_name: Ansible, Inc. + register: csr + + - name: "Create self-signed certificate from CSR" + community.crypto.x509_certificate: + path: /tmp/haproxy-cert/cert.pem + csr_content: "{{ csr.csr }}" + privatekey_path: /tmp/haproxy-cert/cert.pem.key + provider: selfsigned + owner: "1000" + group: "1000" diff --git a/molecule/with_tls_enabled/requirements.yml b/molecule/with_tls_enabled/requirements.yml new file mode 100644 index 0000000..1316891 --- /dev/null +++ b/molecule/with_tls_enabled/requirements.yml @@ -0,0 +1,6 @@ +--- +# requirements file for molecule +roles: + - name: ednxzu.manage_repositories + - name: ednxzu.manage_apt_packages + - name: ednxzu.install_docker diff --git a/molecule/with_tls_enabled/verify.yml b/molecule/with_tls_enabled/verify.yml new file mode 100644 index 0000000..d16df37 --- /dev/null +++ b/molecule/with_tls_enabled/verify.yml @@ -0,0 +1,182 @@ +--- +- name: Verify + hosts: all + gather_facts: true + become: true + tasks: + - name: "Test: haproxy user and group" + block: + - name: "Getent user haproxy" + ansible.builtin.getent: + database: passwd + key: haproxy + register: haproxy_user + + - name: "Getent group haproxy" + ansible.builtin.getent: + database: group + key: haproxy + register: haproxy_group + + - name: "Verify haproxy user and group" + ansible.builtin.assert: + that: + - not haproxy_user.failed + - not haproxy_group.failed + - "'haproxy' in haproxy_user.ansible_facts.getent_passwd.keys()" + - "'/var/lib/haproxy' in haproxy_user.ansible_facts.getent_passwd['haproxy']" + - "'/bin/false' in haproxy_user.ansible_facts.getent_passwd['haproxy']" + - "'haproxy' in haproxy_group.ansible_facts.getent_group.keys()" + + - name: "Test: directory /etc/haproxy" + block: + - name: "Stat directory /etc/haproxy" + ansible.builtin.stat: + path: "/etc/haproxy" + register: stat_etc_haproxy + + - name: "Stat file /etc/haproxy/haproxy.env" + ansible.builtin.stat: + path: "/etc/haproxy/haproxy.env" + register: stat_etc_haproxy_haproxy_env + + - name: "Stat file /etc/haproxy/haproxy.cfg" + ansible.builtin.stat: + path: "/etc/haproxy/haproxy.cfg" + register: stat_etc_haproxy_haproxy_cfg + + - name: "Slurp file /etc/haproxy/haproxy.cfg" + ansible.builtin.slurp: + src: "/etc/haproxy/haproxy.cfg" + register: slurp_etc_haproxy_haproxy_cfg + + - name: "Verify directory /etc/haproxy" + ansible.builtin.assert: + that: + - stat_etc_haproxy.stat.exists + - stat_etc_haproxy.stat.isdir + - stat_etc_haproxy.stat.pw_name == 'haproxy' + - stat_etc_haproxy.stat.gr_name == 'haproxy' + - stat_etc_haproxy.stat.mode == '0755' + - stat_etc_haproxy_haproxy_env.stat.exists + - stat_etc_haproxy_haproxy_env.stat.isreg + - stat_etc_haproxy_haproxy_env.stat.pw_name == 'haproxy' + - stat_etc_haproxy_haproxy_env.stat.gr_name == 'haproxy' + - stat_etc_haproxy_haproxy_env.stat.mode == '0600' + - stat_etc_haproxy_haproxy_cfg.stat.exists + - stat_etc_haproxy_haproxy_cfg.stat.isreg + - stat_etc_haproxy_haproxy_cfg.stat.pw_name == 'haproxy' + - stat_etc_haproxy_haproxy_cfg.stat.gr_name == 'haproxy' + - stat_etc_haproxy_haproxy_cfg.stat.mode == '0600' + - slurp_etc_haproxy_haproxy_cfg.content != '' + + - name: "Test: directory /var/lib/haproxy" + block: + - name: "Stat directory /var/lib/haproxy" + ansible.builtin.stat: + path: "/var/lib/haproxy" + register: stat_var_lib_haproxy + + - name: "Stat socket /var/lib/haproxy/stats" + ansible.builtin.stat: + path: "/var/lib/haproxy/stats" + register: stat_var_lib_haproxy_stats + + - name: "Verify directory /var/lib/haproxy" + ansible.builtin.assert: + that: + - stat_var_lib_haproxy.stat.exists + - stat_var_lib_haproxy.stat.isdir + - stat_var_lib_haproxy.stat.pw_name == 'haproxy' + - stat_var_lib_haproxy.stat.gr_name == 'haproxy' + - stat_var_lib_haproxy.stat.mode == '0755' + - stat_var_lib_haproxy_stats.stat.exists + - stat_var_lib_haproxy_stats.stat.issock + + - name: "Test: service haproxy" + block: + - name: "Get service haproxy" + ansible.builtin.service_facts: + + - name: "Stat file /etc/systemd/system/haproxy.service" + ansible.builtin.stat: + path: "/etc/systemd/system/haproxy.service" + register: stat_etc_systemd_system_haproxy_service + + - name: "Slurp file /etc/systemd/system/haproxy.service" + ansible.builtin.slurp: + src: "/etc/systemd/system/haproxy.service" + register: slurp_etc_systemd_system_haproxy_service + + - name: "Verify service haproxy" + vars: + haproxy_expected_service_file: | + # Ansible managed: Do NOT edit this file manually! + [Unit] + Description=HAProxy Load Balancer + Documentation=man:haproxy(1) + Documentation=file:/usr/share/doc/haproxy/configuration.txt.gz + ConditionFileNotEmpty=/etc/haproxy/haproxy.cfg + After=network-online.target rsyslog.service + Wants=network-online.target + + [Service] + EnvironmentFile=-/etc/default/haproxy + EnvironmentFile=-/etc/haproxy/haproxy.env + BindReadOnlyPaths=/dev/log:/var/lib/haproxy/dev/log + Environment="CONFIG=/etc/haproxy/haproxy.cfg" "PIDFILE=/run/haproxy.pid" "EXTRAOPTS=-S /run/haproxy-master.sock" + ExecStart=/usr/sbin/haproxy -Ws -f $CONFIG -p $PIDFILE $EXTRAOPTS + ExecReload=/usr/sbin/haproxy -Ws -f $CONFIG -c $EXTRAOPTS + ExecReload=/bin/kill -USR2 $MAINPID + KillMode=mixed + Restart=always + SuccessExitStatus=143 + Type=notify + + [Install] + WantedBy=multi-user.target + ansible.builtin.assert: + that: + - stat_etc_systemd_system_haproxy_service.stat.exists + - stat_etc_systemd_system_haproxy_service.stat.isreg + - stat_etc_systemd_system_haproxy_service.stat.pw_name == 'root' + - stat_etc_systemd_system_haproxy_service.stat.gr_name == 'root' + - stat_etc_systemd_system_haproxy_service.stat.mode == '0644' + - (slurp_etc_systemd_system_haproxy_service.content|b64decode) == haproxy_expected_service_file + - ansible_facts.services['haproxy.service'] is defined + - ansible_facts.services['haproxy.service']['source'] == 'systemd' + - ansible_facts.services['haproxy.service']['state'] == 'running' + - ansible_facts.services['haproxy.service']['status'] == 'enabled' + + - name: "Test: haproxy endpoints" + block: + - name: "Get haproxy /health" + ansible.builtin.uri: + url: "https://127.0.0.1:9000/health" + method: GET + validate_certs: false + register: haproxy_health_endpoint + + - name: "Get haproxy /stats" + ansible.builtin.uri: + url: "https://127.0.0.1:9000/stats" + method: GET + force_basic_auth: true + url_username: admin + url_password: password + validate_certs: false + register: haproxy_stats_endpoint + + - name: "Get haproxy /metrics" + ansible.builtin.uri: + url: "https://127.0.0.1:9000/metrics" + method: GET + validate_certs: false + register: haproxy_metrics_endpoint + + - name: "Verify haproxy endpoints" + ansible.builtin.assert: + that: + - haproxy_health_endpoint.status == 200 + - haproxy_stats_endpoint.status == 200 + - haproxy_metrics_endpoint.status == 200 \ No newline at end of file diff --git a/molecule/with_tls_enabled_vagrant/group_vars/all.yml b/molecule/with_tls_enabled_vagrant/group_vars/all.yml index 2e607c0..c40081a 100644 --- a/molecule/with_tls_enabled_vagrant/group_vars/all.yml +++ b/molecule/with_tls_enabled_vagrant/group_vars/all.yml @@ -1,16 +1,10 @@ --- deploy_haproxy_deploy_method: docker # deployment method, either host or docker deploy_haproxy_version: "2.8" - deploy_haproxy_env_variables: {} deploy_haproxy_start_service: true deploy_haproxy_cert_dir: "/tmp/haproxy-cert" - -# docker-only options deploy_haproxy_extra_container_volumes: [] - -# Options from the "default" config block in haproxy.cfg -# The default values here are usually set, but you can change any of them. deploy_haproxy_global: - log stdout format raw daemon debug - stats socket {{ deploy_haproxy_socket }} level admin @@ -27,29 +21,8 @@ deploy_haproxy_defaults: - timeout client 5000 - timeout server 5000 -deploy_haproxy_frontends: - - name: default - options: - - description default frontend - - mode http - - bind :1024 - - default_backend default - -deploy_haproxy_backends: - - name: default - options: - - description default backend - - option forwardfor - - option httpchk - - http-check send meth GET uri / - - server srv_nginx1 172.17.0.2:80 check inter 5s - - server srv_nginx2 172.17.0.3:80 check inter 5s - -# listen configuration blocks -# the default values expose a monitoring listener on all interfaces on port 9000 -# /stats returns the haproxy dashboard (please change the user and password in the configuration) -# /health returns a 200 OK response as long as haproxy is alive and well -# /metrics returns prometheus metrics for the haproxy instance +deploy_haproxy_frontends: [] +deploy_haproxy_backends: [] deploy_haproxy_listen: - name: monitoring options: diff --git a/molecule/with_tls_enabled_vagrant/prepare.yml b/molecule/with_tls_enabled_vagrant/prepare.yml index 0e11fd8..3d7402a 100644 --- a/molecule/with_tls_enabled_vagrant/prepare.yml +++ b/molecule/with_tls_enabled_vagrant/prepare.yml @@ -24,6 +24,8 @@ - name: "Create private key" community.crypto.openssl_privatekey: path: /tmp/haproxy-cert/cert.pem.key + owner: "1000" + group: "1000" - name: "Create certificate signing request" community.crypto.openssl_csr_pipe: @@ -38,3 +40,5 @@ csr_content: "{{ csr.csr }}" privatekey_path: /tmp/haproxy-cert/cert.pem.key provider: selfsigned + owner: "1000" + group: "1000" \ No newline at end of file diff --git a/molecule/with_tls_enabled_vagrant/verify.yml b/molecule/with_tls_enabled_vagrant/verify.yml index ec450ea..3632fdd 100644 --- a/molecule/with_tls_enabled_vagrant/verify.yml +++ b/molecule/with_tls_enabled_vagrant/verify.yml @@ -4,3 +4,154 @@ gather_facts: true become: true tasks: + - name: "Test: directory /etc/haproxy" + block: + - name: "Stat directory /etc/haproxy" + ansible.builtin.stat: + path: "/etc/haproxy" + register: stat_etc_haproxy + + - name: "Stat file /etc/default/haproxy" + ansible.builtin.stat: + path: "/etc/default/haproxy" + register: stat_etc_default_haproxy + + - name: "Stat file /etc/haproxy/haproxy.cfg" + ansible.builtin.stat: + path: "/etc/haproxy/haproxy.cfg" + register: stat_etc_haproxy_haproxy_cfg + + - name: "Slurp file /etc/haproxy/haproxy.cfg" + ansible.builtin.slurp: + src: "/etc/haproxy/haproxy.cfg" + register: slurp_etc_haproxy_haproxy_cfg + + - name: "Verify directory /etc/haproxy" + ansible.builtin.assert: + that: + - stat_etc_haproxy.stat.exists + - stat_etc_haproxy.stat.isdir + - (stat_etc_haproxy.stat.uid | int) == 99 + - (stat_etc_haproxy.stat.gid | int) == 99 + - stat_etc_haproxy.stat.mode == '0755' + - stat_etc_default_haproxy.stat.exists + - stat_etc_default_haproxy.stat.isreg + - stat_etc_default_haproxy.stat.pw_name == 'root' + - stat_etc_default_haproxy.stat.gr_name == 'root' + - stat_etc_default_haproxy.stat.mode == '0600' + - stat_etc_haproxy_haproxy_cfg.stat.exists + - stat_etc_haproxy_haproxy_cfg.stat.isreg + - (stat_etc_haproxy_haproxy_cfg.stat.uid | int) == 99 + - (stat_etc_haproxy_haproxy_cfg.stat.gid | int) == 99 + - stat_etc_haproxy_haproxy_cfg.stat.mode == '0600' + - slurp_etc_haproxy_haproxy_cfg.content != '' + + - name: "Test: directory /var/lib/haproxy" + block: + - name: "Stat directory /var/lib/haproxy" + ansible.builtin.stat: + path: "/var/lib/haproxy" + register: stat_var_lib_haproxy + + - name: "Stat socket /var/lib/haproxy/stats" + ansible.builtin.stat: + path: "/var/lib/haproxy/stats" + register: stat_var_lib_haproxy_stats + + - name: "Verify directory /var/lib/haproxy" + ansible.builtin.assert: + that: + - stat_var_lib_haproxy.stat.exists + - stat_var_lib_haproxy.stat.isdir + - (stat_var_lib_haproxy.stat.uid | int) == 99 + - (stat_var_lib_haproxy.stat.gid | int) == 99 + - stat_var_lib_haproxy.stat.mode == '0755' + - stat_var_lib_haproxy_stats.stat.exists + - stat_var_lib_haproxy_stats.stat.issock + + - name: "Test: service haproxy" + block: + - name: "Get service haproxy" + ansible.builtin.service_facts: + + - name: "Stat file /etc/systemd/system/haproxy_container.service" + ansible.builtin.stat: + path: "/etc/systemd/system/haproxy_container.service" + register: stat_etc_systemd_system_haproxy_container_service + + - name: "Slurp file /etc/systemd/system/haproxy_container.service" + ansible.builtin.slurp: + src: "/etc/systemd/system/haproxy_container.service" + register: slurp_etc_systemd_system_haproxy_container_service + + - name: "Verify service haproxy" + vars: + haproxy_expected_service_file: | + # Ansible managed: Do NOT edit this file manually! + [Unit] + After=docker.service + PartOf=docker.service + Requires=docker.service + + [Service] + EnvironmentFile=/etc/default/haproxy + ExecStartPre=-/usr/bin/docker rm -f haproxy + ExecStart=/usr/bin/docker run --name haproxy \ + --rm \ + --env-file /etc/default/haproxy \ + --network "host" \ + --volume "/etc/haproxy:/usr/local/etc/haproxy" \ + --volume "/var/lib/haproxy:/var/lib/haproxy" \ + haproxytech/haproxy-debian:latest + ExecStop=/usr/bin/docker stop haproxy + SyslogIdentifier=haproxy + Restart=always + RestartSec=10s + + [Install] + WantedBy=docker.service + ansible.builtin.assert: + that: + - stat_etc_systemd_system_haproxy_container_service.stat.exists + - stat_etc_systemd_system_haproxy_container_service.stat.isreg + - stat_etc_systemd_system_haproxy_container_service.stat.pw_name == 'root' + - stat_etc_systemd_system_haproxy_container_service.stat.gr_name == 'root' + - stat_etc_systemd_system_haproxy_container_service.stat.mode == '0644' + - (slurp_etc_systemd_system_haproxy_container_service.content|b64decode) == haproxy_expected_service_file + - ansible_facts.services['haproxy_container.service'] is defined + - ansible_facts.services['haproxy_container.service']['source'] == 'systemd' + - ansible_facts.services['haproxy_container.service']['state'] == 'running' + - ansible_facts.services['haproxy_container.service']['status'] == 'enabled' + + - name: "Test: haproxy endpoints" + block: + - name: "Get haproxy /health" + ansible.builtin.uri: + url: "https://127.0.0.1:9000/health" + method: GET + validate_certs: false + register: haproxy_health_endpoint + + - name: "Get haproxy /stats" + ansible.builtin.uri: + url: "https://127.0.0.1:9000/stats" + method: GET + force_basic_auth: true + url_username: admin + url_password: password + validate_certs: false + register: haproxy_stats_endpoint + + - name: "Get haproxy /metrics" + ansible.builtin.uri: + url: "https://127.0.0.1:9000/metrics" + method: GET + validate_certs: false + register: haproxy_metrics_endpoint + + - name: "Verify haproxy endpoints" + ansible.builtin.assert: + that: + - haproxy_health_endpoint.status == 200 + - haproxy_stats_endpoint.status == 200 + - haproxy_metrics_endpoint.status == 200 \ No newline at end of file