~arx10/procustodibus-broker

254872a9c91880475632971a23815857b8318fb5 — Justin Ludwig 9 months ago 1059fb8
update installer tests

* replace Alpine Linux 3.15 with 3.18
* replace AlmaLinux 8 with 9
* replace Amazon Linux 2022 with 2023
* replace Debian 11 with 12
* replace Fedora 35 with 38
* replace Oracle Linux 8 with 9
* replace Rocky Linux 8 with 9
* add openSUSE 15
* add RHEL 9
* add Ubuntu 22.04 and 23.04
31 files changed, 652 insertions(+), 346 deletions(-)

R test_install/{almalinux-8.dockerfile => almalinux-9.dockerfile}
R test_install/{alpine-3.15.dockerfile => alpine-3.18.dockerfile}
R test_install/{fedora-35.dockerfile => amzn-2023.dockerfile}
M test_install/arch-latest.dockerfile
R test_install/{debian-bullseye.dockerfile => debian-bookworm.dockerfile}
M test_install/docker-compose.yml
A test_install/fedora-38.dockerfile
R test_install/{install_almalinux_8.py => install_almalinux_9.py}
R test_install/{install_alpine_315.py => install_alpine_318.py}
A test_install/install_amzn_2023.py
M test_install/install_arch_latest.py
R test_install/{install_debian_bullseye.py => install_debian_bookworm.py}
R test_install/{install_amzn_2022.py => install_fedora_38.py}
R test_install/{install_fedora_35.py => install_opensuse_15.py}
R test_install/{install_oracle_8.py => install_oracle_9.py}
M test_install/install_rhel_8.py
R test_install/{install_rocky_8.py => install_rhel_9.py}
A test_install/install_rocky_9.py
M test_install/install_ubuntu_focal.py
A test_install/install_ubuntu_jammy.py
A test_install/install_ubuntu_lunar.py
R test_install/{install_upgrade_ubuntu_focal.py => install_upgrade_ubuntu_jammy.py}
A test_install/opensuse-15.dockerfile
D test_install/oracle-8.dockerfile
R test_install/{amzn-2022.dockerfile => oracle-9.dockerfile}
M test_install/rhel-8.dockerfile
R test_install/{rocky-8.dockerfile => rhel-9.dockerfile}
A test_install/rocky-9.dockerfile
M test_install/ubuntu-focal.dockerfile
A test_install/ubuntu-jammy.dockerfile
A test_install/ubuntu-lunar.dockerfile
R test_install/almalinux-8.dockerfile => test_install/almalinux-9.dockerfile +2 -1
@@ 1,4 1,5 @@
FROM almalinux:8
FROM almalinux:9
RUN dnf install -y systemd
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

R test_install/alpine-3.15.dockerfile => test_install/alpine-3.18.dockerfile +1 -1
@@ 1,4 1,4 @@
FROM alpine:3.15
FROM alpine:3.18
RUN apk add openrc
WORKDIR /usr/local/src/broker
CMD ["/sbin/init"]

R test_install/fedora-35.dockerfile => test_install/amzn-2023.dockerfile +2 -1
@@ 1,4 1,5 @@
FROM fedora:35
FROM amazonlinux:2023
RUN dnf install -y systemd
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

M test_install/arch-latest.dockerfile => test_install/arch-latest.dockerfile +1 -0
@@ 1,3 1,4 @@
FROM archlinux:latest
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

R test_install/debian-bullseye.dockerfile => test_install/debian-bookworm.dockerfile +2 -1
@@ 1,5 1,6 @@
FROM debian:11
FROM debian:bookworm
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y systemd
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

M test_install/docker-compose.yml => test_install/docker-compose.yml +55 -61
@@ 2,122 2,116 @@ version: '3'

services:

  # tmpfs and /sys mounts needed for systemd
  almalinux_8:
  almalinux_9:
    build:
      context: .
      dockerfile: almalinux-8.dockerfile
    tmpfs:
    - /run
    - /run/lock
      dockerfile: almalinux-9.dockerfile
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # /sys mount not strictly needed
  # but avoids some error messages when starting broker as daemon
  alpine_315:
  alpine_318:
    build:
      context: .
      dockerfile: alpine-3.15.dockerfile
      dockerfile: alpine-3.18.dockerfile
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # tmpfs and /sys mounts needed for systemd
  amzn_2022: # aka Amazon Linux
  amzn_2023: # aka Amazon Linux 2023
    build:
      context: .
      dockerfile: amzn-2022.dockerfile
    tmpfs:
    - /run
    - /run/lock
      dockerfile: amzn-2023.dockerfile
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # tmpfs and /sys mounts needed for systemd
  arch_latest:
    build:
      context: .
      dockerfile: arch-latest.dockerfile
    tmpfs:
    - /run
    - /run/lock
    - /tmp
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # tmpfs and /sys mounts needed for systemd
  debian_bullseye: # aka 11
  debian_bookworm: # aka 12
    build:
      context: .
      dockerfile: debian-bullseye.dockerfile
    tmpfs:
    - /run
    - /run/lock
      dockerfile: debian-bookworm.dockerfile
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # tmpfs and /sys mounts needed for systemd
  fedora_35:
  fedora_38:
    build:
      context: .
      dockerfile: fedora-35.dockerfile
    tmpfs:
    - /run
    - /run/lock
    - /tmp
      dockerfile: fedora-38.dockerfile
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # tmpfs and /sys mounts needed for systemd
  oracle_8: # aka Oracle Linux aka ol
  opensuse_15:
    build:
      context: .
      dockerfile: oracle-8.dockerfile
    tmpfs:
    - /run
    - /run/lock
      dockerfile: opensuse-15.dockerfile
    privileged: true
    volumes:
    - ../:/usr/local/src/broker

  oracle_9: # aka Oracle Linux aka ol
    build:
      context: .
      dockerfile: oracle-9.dockerfile
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # tmpfs and /sys mounts needed for systemd
  rhel_8: # aka Red Hat Enterprise Linux
    build:
      context: .
      dockerfile: rhel-8.dockerfile
    tmpfs:
    - /run
    - /run/lock
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # tmpfs and /sys mounts needed for systemd
  rocky_8:
  rhel_9: # aka Red Hat Enterprise Linux
    build:
      context: .
      dockerfile: rocky-8.dockerfile
    tmpfs:
    - /run
    - /run/lock
      dockerfile: rhel-9.dockerfile
    privileged: true
    volumes:
    - ../:/usr/local/src/broker

  rocky_9:
    build:
      context: .
      dockerfile: rocky-9.dockerfile
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

  # tmpfs and /sys mounts needed for systemd
  ubuntu_focal: # aka 20.04
    build:
      context: .
      dockerfile: ubuntu-focal.dockerfile
    tmpfs:
    - /run
    - /run/lock
    privileged: true
    volumes:
    - ../:/usr/local/src/broker

  ubuntu_jammy: # aka 22.04
    build:
      context: .
      dockerfile: ubuntu-jammy.dockerfile
    privileged: true
    volumes:
    - ../:/usr/local/src/broker

  ubuntu_lunar: # aka 23.04
    build:
      context: .
      dockerfile: ubuntu-lunar.dockerfile
    privileged: true
    volumes:
    - /sys/fs/cgroup:/sys/fs/cgroup:ro
    - ../:/usr/local/src/broker

A test_install/fedora-38.dockerfile => test_install/fedora-38.dockerfile +5 -0
@@ 0,0 1,5 @@
FROM fedora:38
RUN dnf install -y systemd util-linux
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

R test_install/install_almalinux_8.py => test_install/install_almalinux_9.py +2 -4
@@ 9,7 9,7 @@ USER = "procustodibus-broker"

@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("almalinux_8") as proc:
    with exec_docker_shell("almalinux_9") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"


@@ 49,9 49,7 @@ def test_forced_install_with_fake_credentials():
        assert read_until(proc, "added epel repo")[-1] == "added epel repo"
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc) == "WARNING python not found"
        assert read_line(proc) == "OK will install python"
        assert read_until(proc, "installed python")[-1] == "installed python"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "python includes all packages needed for venv"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"

R test_install/install_alpine_315.py => test_install/install_alpine_318.py +3 -3
@@ 1,5 1,5 @@
# -*- coding: utf-8 -*-
"""Install tests for Alpine 3.15."""
"""Install tests for Alpine 3.18."""
import pytest

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf


@@ 9,9 9,9 @@ USER = "procustodibus-broker"

# simpler to keep this long set of test steps together
# rather than break it up into shorter functions
@pytest.mark.timeout(200)
@pytest.mark.timeout(60)
def test_forced_install_and_remove_with_fake_credentials():  # noqa: CFQ001
    with exec_docker_shell("alpine_315") as proc:
    with exec_docker_shell("alpine_318") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"

A test_install/install_amzn_2023.py => test_install/install_amzn_2023.py +47 -0
@@ 0,0 1,47 @@
# -*- coding: utf-8 -*-
"""Install tests for Amazon Linux 2023."""
import pytest

from .util import exec_docker_shell, read_line, write_cmd, write_fake_cnf

USER = "procustodibus-broker"


@pytest.mark.timeout(30)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("amzn_2023") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"
        assert read_line(proc).startswith("force install")
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc).startswith("broker credentials found")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "created user"
        assert read_line(proc) == "/etc/procustodibus mode ok (drwxr-xr-x)"
        assert read_line(proc) == "/etc/procustodibus/broker mode ok (drwxr-xr-x)"
        assert read_line(proc).endswith(f"bus/broker owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"bus/broker group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("broker.conf mode ok (-rw-r--r--)")
        assert read_line(proc).endswith(f"broker.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"broker.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("credentials.conf mode should be 640")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"credentials.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"credentials.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc) == "WARNING libsodium not found"
        assert read_line(proc) == "ERROR unable to install libsodium automatically"

M test_install/install_arch_latest.py => test_install/install_arch_latest.py +2 -1
@@ 64,7 64,8 @@ def test_forced_install_with_fake_credentials():
        assert read_until(proc, "started daemon")[-1] == "started daemon"
        assert read_line(proc) == "install SUCCESS"

        # systemd-journald.service fails to start on arch, so no logs available
        write_cmd(proc, "journalctl -u procustodibus-broker -q -g started")
        assert read_line(proc).endswith("Started Pro Custodibus Broker.")

        write_cmd(
            proc, "/opt/venvs/procustodibus-broker/bin/procustodibus-broker --test"

R test_install/install_debian_bullseye.py => test_install/install_debian_bookworm.py +5 -3
@@ 1,5 1,5 @@
# -*- coding: utf-8 -*-
"""Install tests for Debian Bullseye (11)."""
"""Install tests for Debian Bookworm (12)."""
import pytest

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf


@@ 9,7 9,7 @@ USER = "procustodibus-broker"

@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("debian_bullseye") as proc:
    with exec_docker_shell("debian_bookworm") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"


@@ 65,7 65,9 @@ def test_forced_install_with_fake_credentials():
        assert read_line(proc) == "install SUCCESS"

        write_cmd(proc, "journalctl -u procustodibus-broker -q -g started")
        assert read_line(proc).endswith("Started Pro Custodibus Broker.")
        assert read_line(proc).endswith(
            "Started procustodibus-broker.service - Pro Custodibus Broker."
        )

        write_cmd(
            proc, "/opt/venvs/procustodibus-broker/bin/procustodibus-broker --test"

R test_install/install_amzn_2022.py => test_install/install_fedora_38.py +4 -4
@@ 1,5 1,5 @@
# -*- coding: utf-8 -*-
"""Install tests for Amazon Linux 2022."""
"""Install tests for Fedora 38."""
import pytest

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf


@@ 9,7 9,7 @@ USER = "procustodibus-broker"

@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("amzn_2022") as proc:
    with exec_docker_shell("fedora_38") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"


@@ 46,7 46,7 @@ def test_forced_install_with_fake_credentials():
        assert read_line(proc) == "WARNING libsodium not found"
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc) == "python 3.9.8 found at /usr/bin/python3"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "python includes all packages needed for venv"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"


@@ 63,7 63,7 @@ def test_forced_install_with_fake_credentials():
        assert read_line(proc) == "install SUCCESS"

        write_cmd(proc, "journalctl -u procustodibus-broker -q -g started")
        assert read_line(proc).endswith("Started Pro Custodibus Broker.")
        assert "Started procustodibus-broker" in read_line(proc)

        write_cmd(
            proc, "/opt/venvs/procustodibus-broker/bin/procustodibus-broker --test"

R test_install/install_fedora_35.py => test_install/install_opensuse_15.py +2 -2
@@ 1,5 1,5 @@
# -*- coding: utf-8 -*-
"""Install tests for Fedora 35."""
"""Install tests for openSUSE 15."""
import pytest

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf


@@ 9,7 9,7 @@ USER = "procustodibus-broker"

@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("fedora_35") as proc:
    with exec_docker_shell("opensuse_15") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"

R test_install/install_oracle_8.py => test_install/install_oracle_9.py +3 -5
@@ 1,5 1,5 @@
# -*- coding: utf-8 -*-
"""Install tests for Oracle Linux 8."""
"""Install tests for Oracle Linux 9."""
import pytest

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf


@@ 9,7 9,7 @@ USER = "procustodibus-broker"

@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("oracle_8") as proc:
    with exec_docker_shell("oracle_9") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"


@@ 49,9 49,7 @@ def test_forced_install_with_fake_credentials():
        assert read_until(proc, "added epel repo")[-1] == "added epel repo"
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc) == "WARNING python not found"
        assert read_line(proc) == "OK will install python"
        assert read_until(proc, "installed python")[-1] == "installed python"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "python includes all packages needed for venv"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"

M test_install/install_rhel_8.py => test_install/install_rhel_8.py +1 -1
@@ 7,7 7,7 @@ from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fak
USER = "procustodibus-broker"


@pytest.mark.timeout(90)
@pytest.mark.timeout(60)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("rhel_8") as proc:
        write_fake_cnf(proc, credentials=True)

R test_install/install_rocky_8.py => test_install/install_rhel_9.py +3 -5
@@ 1,5 1,5 @@
# -*- coding: utf-8 -*-
"""Install tests for Rocky Linux 8."""
"""Install tests for Red Hat Enterprise Linux 9."""
import pytest

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf


@@ 9,7 9,7 @@ USER = "procustodibus-broker"

@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("rocky_8") as proc:
    with exec_docker_shell("rhel_9") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"


@@ 49,9 49,7 @@ def test_forced_install_with_fake_credentials():
        assert read_until(proc, "added epel repo")[-1] == "added epel repo"
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc) == "WARNING python not found"
        assert read_line(proc) == "OK will install python"
        assert read_until(proc, "installed python")[-1] == "installed python"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "python includes all packages needed for venv"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"

A test_install/install_rocky_9.py => test_install/install_rocky_9.py +77 -0
@@ 0,0 1,77 @@
# -*- coding: utf-8 -*-
"""Install tests for Rocky Linux 9."""
import pytest

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf

USER = "procustodibus-broker"


@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("rocky_9") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"
        assert read_line(proc).startswith("force install")
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc).startswith("broker credentials found")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "created user"
        assert read_line(proc) == "/etc/procustodibus mode ok (drwxr-xr-x)"
        assert read_line(proc) == "/etc/procustodibus/broker mode ok (drwxr-xr-x)"
        assert read_line(proc).endswith(f"bus/broker owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"bus/broker group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("broker.conf mode ok (-rw-r--r--)")
        assert read_line(proc).endswith(f"broker.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"broker.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("credentials.conf mode should be 640")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"credentials.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"credentials.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc) == "WARNING libsodium not found"
        assert read_line(proc).startswith("WARNING epel repo")
        assert read_line(proc) == "OK will add epel repo"
        assert read_until(proc, "added epel repo")[-1] == "added epel repo"
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "python includes all packages needed for venv"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"
        assert read_line(proc) == "created virtualenv"
        assert read_line(proc) == "WARNING broker package not installed"
        assert read_line(proc) == "OK will install broker"
        assert read_until(proc, "installed broker")[-1] == "installed broker"
        assert read_line(proc).startswith("WARNING systemd daemon not found")
        assert read_line(proc) == "OK will install daemon"
        assert read_line(proc) == "installed daemon"
        assert read_line(proc) == "WARNING daemon dead"
        assert read_line(proc) == "OK will start daemon"
        assert read_until(proc, "started daemon")[-1] == "started daemon"
        assert read_line(proc) == "install SUCCESS"

        write_cmd(proc, "journalctl -u procustodibus-broker -q -g started")
        assert read_line(proc).endswith("Started Pro Custodibus Broker.")

        write_cmd(
            proc, "/opt/venvs/procustodibus-broker/bin/procustodibus-broker --test"
        )
        assert read_line(proc).endswith("is pro custodibus ip address ...")
        assert read_line(proc) == "... healthy pro custodibus api ..."
        assert read_line(proc).startswith("!!! cannot access queues")
        assert read_line(proc).startswith("Issues encountered")

M test_install/install_ubuntu_focal.py => test_install/install_ubuntu_focal.py +15 -240
@@ 1,301 1,76 @@
# -*- coding: utf-8 -*-
"""Install tests for Ubuntu Focal (20.04)."""
from datetime import datetime

import pytest

from procustodibus_broker import __version__ as version

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_empty_cnf
from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf

USER = "procustodibus-broker"


@pytest.mark.timeout(15)
def test_dryrun_without_cnf():
    with exec_docker_shell("ubuntu_focal") as proc:
        write_cmd(proc, "./install.sh --dryrun")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "dryrun force install " + version
        assert read_line(proc).startswith("ERROR broker configuration not found")
        assert read_line(proc).startswith("please download broker.conf")
        assert read_line(proc) == "ERROR broker credentials not found"
        assert read_line(proc).startswith("please download broker-setup.conf")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "WARNING libsodium not found"
        assert read_line(proc) == "OK will install libsodium"
        assert read_line(proc) == "python 3.8.10 found at /usr/bin/python3"
        assert read_line(proc) == "WARNING python missing these packages: ensurepip"
        assert read_line(proc) == "OK will install missing packages"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"
        assert read_line(proc) == "WARNING broker package not installed"
        assert read_line(proc) == "OK will install broker"
        assert read_line(proc).startswith("WARNING systemd daemon not found")
        assert read_line(proc) == "OK will install daemon"
        assert read_line(proc) == "WARNING daemon dead"
        assert read_line(proc) == "OK will start daemon"
        assert read_line(proc) == "dryrun complete"


@pytest.mark.timeout(15)
def test_dryrun_remove_without_install():
    with exec_docker_shell("ubuntu_focal") as proc:
        write_cmd(proc, "./install.sh --remove --dryrun")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "dryrun force remove " + version
        assert read_line(proc) == "daemon dead"
        assert read_line(proc).startswith("systemd daemon not found")
        assert read_line(proc).startswith("python virtualenv not found")
        assert read_line(proc).startswith(f"daemon user {USER} not found")
        assert read_line(proc).startswith("broker configuration not found")
        assert read_line(proc).startswith("broker credentials not found")
        assert read_line(proc).startswith("broker setup not found")
        assert read_line(proc) == "dryrun complete"


@pytest.mark.timeout(15)
def test_install_without_cnf():
@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("ubuntu_focal") as proc:
        write_cmd(proc, "./install.sh --install")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "install " + version
        assert read_line(proc).startswith("ERROR broker configuration not found")
        assert read_line(proc).startswith("please download broker.conf")
        assert read_line(proc) == "FAIL"

        write_cmd(proc, "tail -n1 /var/log/procustodibus-install.log")
        assert read_line(proc).endswith("UTC {} FAIL".format(datetime.utcnow().year))


@pytest.mark.timeout(15)
def test_install_without_credentials():
    with exec_docker_shell("ubuntu_focal") as proc:
        write_empty_cnf(proc)
        write_cmd(proc, "./install.sh --install")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "install " + version
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc) == "ERROR broker credentials not found"
        assert read_line(proc).startswith("please download broker-setup.conf")
        assert read_line(proc) == "FAIL"


# simpler to keep this long set of test steps together
# rather than break it up into shorter functions
@pytest.mark.timeout(120)  # noqa: CFQ001
def test_install_and_remove_with_empty_credentials():  # noqa: CFQ001
    with exec_docker_shell("ubuntu_focal") as proc:
        write_empty_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install")
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "install " + version
        assert read_line(proc).startswith("force install")
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc).startswith("broker credentials found")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        # prompt "create user? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "created user"
        assert read_line(proc) == "/etc/procustodibus mode ok (drwxr-xr-x)"
        assert read_line(proc) == "/etc/procustodibus/broker mode ok (drwxr-xr-x)"
        assert read_line(proc).endswith(f"bus/broker owner should be {USER}")
        # prompt "fix owner? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"bus/broker group should be {USER}")
        # prompt "fix group? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("broker.conf mode should be 644")
        # prompt "fix mode? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith("broker.conf mode ok (-rw-r--r--)")
        assert read_line(proc).endswith(f"broker.conf owner should be {USER}")
        # prompt "fix owner? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"broker.conf group should be {USER}")
        # prompt "fix group? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("credentials.conf mode should be 640")
        # prompt "fix mode? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"credentials.conf owner should be {USER}")
        # prompt "fix owner? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"credentials.conf group should be {USER}")
        # prompt "fix group? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc) == "WARNING libsodium not found"
        # prompt "install libsodium? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc) == "python 3.8.10 found at /usr/bin/python3"
        assert read_line(proc) == "WARNING python missing these packages: ensurepip"
        # prompt "install missing packages? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will install missing packages"
        assert read_until(proc, "installed missing")[-1] == "installed missing packages"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        # prompt "create virtualenv? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will create virtualenv"
        assert read_line(proc) == "created virtualenv"
        assert read_line(proc) == "WARNING broker package not installed"
        # prompt "install broker from /usr/local/src/broker? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will install broker"
        assert read_until(proc, "installed broker")[-1] == "installed broker"
        assert read_line(proc).startswith("WARNING systemd daemon not found")
        # prompt "install daemon? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will install daemon"
        assert read_line(proc) == "installed daemon"
        assert read_line(proc) == "WARNING daemon dead"
        # prompt "start daemon? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will start daemon"
        assert read_until(proc, "started daemon")[-1] == "started daemon"
        assert read_line(proc) == "install SUCCESS"

        write_cmd(proc, "journalctl -u procustodibus-broker -q | head -n1")
        write_cmd(proc, "journalctl -u procustodibus-broker -q -g started")
        assert read_line(proc).endswith("Started Pro Custodibus Broker.")

        write_cmd(proc, "./install.sh --remove --dryrun")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "dryrun force remove " + version
        assert read_line(proc).startswith("daemon failed")
        assert read_line(proc).startswith("WARNING systemd daemon found")
        assert read_line(proc) == "OK will remove daemon"
        assert read_line(proc).startswith("WARNING python virtualenv found")
        assert read_line(proc) == "OK will delete virtualenv"
        assert read_line(proc) == f"WARNING daemon user {USER} found"
        assert read_line(proc) == "OK will delete user"
        assert read_line(proc).startswith("WARNING broker configuration found")
        assert read_line(proc) == "OK will delete configuration"
        assert read_line(proc).startswith("WARNING broker credentials found")
        assert read_line(proc) == "OK will delete credentials"
        assert read_line(proc).startswith("broker setup not found")
        assert read_line(proc) == "dryrun complete"

        write_cmd(proc, "./install.sh --remove")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "remove " + version
        assert read_line(proc).startswith("daemon failed")
        assert read_line(proc).startswith("WARNING systemd daemon found")
        # prompt "remove daemon? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will remove daemon"
        assert read_line(proc) == "removed daemon"
        assert read_line(proc).startswith("WARNING python virtualenv found")
        # prompt "delete virtualenv? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will delete virtualenv"
        assert read_line(proc) == "deleted virtualenv"
        assert read_line(proc) == f"WARNING daemon user {USER} found"
        # prompt "delete user? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will delete user"
        assert read_line(proc) == "deleted user"
        assert read_line(proc).startswith("WARNING broker configuration found")
        # prompt "delete configuration? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will delete configuration"
        assert read_line(proc) == "deleted configuration"
        assert read_line(proc).startswith("WARNING broker credentials found")
        # prompt "delete credentials? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will delete credentials"
        assert read_line(proc) == "deleted credentials"
        assert read_line(proc).startswith("broker setup not found")
        assert read_line(proc) == "remove SUCCESS"

        write_cmd(proc, "./install.sh --remove --dryrun")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "dryrun force remove " + version
        assert read_line(proc) == "daemon failed"
        assert read_line(proc).startswith("systemd daemon not found")
        assert read_line(proc).startswith("python virtualenv not found")
        assert read_line(proc).startswith(f"daemon user {USER} not found")
        assert read_line(proc).startswith("broker configuration not found")
        assert read_line(proc).startswith("broker credentials not found")
        assert read_line(proc).startswith("broker setup not found")
        assert read_line(proc) == "dryrun complete"


@pytest.mark.timeout(120)
def test_forced_install_with_empty_setup():
    with exec_docker_shell("ubuntu_focal") as proc:
        write_empty_cnf(proc, setup=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"
        assert read_line(proc).startswith("force install")
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc).startswith("broker setup found")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "created user"
        assert read_line(proc) == "/etc/procustodibus mode ok (drwxr-xr-x)"
        assert read_line(proc) == "/etc/procustodibus/broker mode ok (drwxr-xr-x)"
        assert read_line(proc).endswith(f"bus/broker owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"bus/broker group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("broker.conf mode should be 644")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"broker.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"broker.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("setup.conf mode should be 640")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"setup.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"setup.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc) == "WARNING libsodium not found"
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc) == "python 3.8.10 found at /usr/bin/python3"
        assert read_line(proc) == "WARNING python missing these packages: ensurepip"
        assert read_line(proc) == "OK will install missing packages"
        assert read_until(proc, "installed missing")[-1] == "installed missing packages"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"
        assert read_line(proc) == "created virtualenv"
        assert read_line(proc) == "WARNING broker package not installed"
        assert read_line(proc) == "OK will install broker"
        assert read_until(proc, "installed broker")[-1] == "installed broker"
        assert read_line(proc).startswith("WARNING systemd daemon not found")
        assert read_line(proc) == "OK will install daemon"
        assert read_line(proc) == "installed daemon"
        assert read_line(proc) == "WARNING daemon dead"
        assert read_line(proc) == "OK will start daemon"
        assert read_until(proc, "started daemon")[-1] == "started daemon"
        assert read_line(proc) == "install SUCCESS"

        write_cmd(proc, "journalctl -u procustodibus-broker -q | head -n1")
        assert read_line(proc).endswith("Started Pro Custodibus Broker.")
        write_cmd(
            proc, "/opt/venvs/procustodibus-broker/bin/procustodibus-broker --test"
        )
        assert read_line(proc).endswith("is pro custodibus ip address ...")
        assert read_line(proc) == "... healthy pro custodibus api ..."
        assert read_line(proc).startswith("!!! cannot access queues")
        assert read_line(proc).startswith("Issues encountered")

A test_install/install_ubuntu_jammy.py => test_install/install_ubuntu_jammy.py +306 -0
@@ 0,0 1,306 @@
# -*- coding: utf-8 -*-
"""Install tests for Ubuntu Jammy (22.04)."""
from datetime import datetime

import pytest

from procustodibus_broker import __version__ as version

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_empty_cnf

USER = "procustodibus-broker"


@pytest.mark.timeout(15)
def test_dryrun_without_cnf():
    with exec_docker_shell("ubuntu_jammy") as proc:
        write_cmd(proc, "./install.sh --dryrun")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "dryrun force install " + version
        assert read_line(proc).startswith("ERROR broker configuration not found")
        assert read_line(proc).startswith("please download broker.conf")
        assert read_line(proc) == "ERROR broker credentials not found"
        assert read_line(proc).startswith("please download broker-setup.conf")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "WARNING libsodium not found"
        assert read_line(proc) == "OK will install libsodium"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "WARNING python missing these packages: ensurepip"
        assert read_line(proc) == "OK will install missing packages"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"
        assert read_line(proc) == "WARNING broker package not installed"
        assert read_line(proc) == "OK will install broker"
        assert read_line(proc).startswith("WARNING systemd daemon not found")
        assert read_line(proc) == "OK will install daemon"
        assert read_line(proc) == "WARNING daemon dead"
        assert read_line(proc) == "OK will start daemon"
        assert read_line(proc) == "dryrun complete"


@pytest.mark.timeout(15)
def test_dryrun_remove_without_install():
    with exec_docker_shell("ubuntu_jammy") as proc:
        write_cmd(proc, "./install.sh --remove --dryrun")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "dryrun force remove " + version
        assert read_line(proc) == "daemon dead"
        assert read_line(proc).startswith("systemd daemon not found")
        assert read_line(proc).startswith("python virtualenv not found")
        assert read_line(proc).startswith(f"daemon user {USER} not found")
        assert read_line(proc).startswith("broker configuration not found")
        assert read_line(proc).startswith("broker credentials not found")
        assert read_line(proc).startswith("broker setup not found")
        assert read_line(proc) == "dryrun complete"


@pytest.mark.timeout(15)
def test_install_without_cnf():
    with exec_docker_shell("ubuntu_jammy") as proc:
        write_cmd(proc, "./install.sh --install")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "install " + version
        assert read_line(proc).startswith("ERROR broker configuration not found")
        assert read_line(proc).startswith("please download broker.conf")
        assert read_line(proc) == "FAIL"

        write_cmd(proc, "tail -n1 /var/log/procustodibus-install.log")
        assert read_line(proc).endswith("UTC {} FAIL".format(datetime.utcnow().year))


@pytest.mark.timeout(15)
def test_install_without_credentials():
    with exec_docker_shell("ubuntu_jammy") as proc:
        write_empty_cnf(proc)
        write_cmd(proc, "./install.sh --install")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "install " + version
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc) == "ERROR broker credentials not found"
        assert read_line(proc).startswith("please download broker-setup.conf")
        assert read_line(proc) == "FAIL"


# simpler to keep this long set of test steps together
# rather than break it up into shorter functions
@pytest.mark.timeout(120)  # noqa: CFQ001
def test_install_and_remove_with_empty_credentials():  # noqa: CFQ001
    with exec_docker_shell("ubuntu_jammy") as proc:
        write_empty_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "install " + version
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc).startswith("broker credentials found")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        # prompt "create user? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "created user"
        assert read_line(proc) == "/etc/procustodibus mode ok (drwxr-xr-x)"
        assert read_line(proc) == "/etc/procustodibus/broker mode ok (drwxr-xr-x)"
        assert read_line(proc).endswith(f"bus/broker owner should be {USER}")
        # prompt "fix owner? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"bus/broker group should be {USER}")
        # prompt "fix group? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("broker.conf mode should be 644")
        # prompt "fix mode? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"broker.conf owner should be {USER}")
        # prompt "fix owner? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"broker.conf group should be {USER}")
        # prompt "fix group? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("credentials.conf mode should be 640")
        # prompt "fix mode? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"credentials.conf owner should be {USER}")
        # prompt "fix owner? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"credentials.conf group should be {USER}")
        # prompt "fix group? ([y]es, [n]o)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc) == "WARNING libsodium not found"
        # prompt "install libsodium? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "WARNING python missing these packages: ensurepip"
        # prompt "install missing packages? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will install missing packages"
        assert read_until(proc, "installed missing")[-1] == "installed missing packages"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        # prompt "create virtualenv? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will create virtualenv"
        assert read_line(proc) == "created virtualenv"
        assert read_line(proc) == "WARNING broker package not installed"
        # prompt "install broker from /usr/local/src/broker? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will install broker"
        assert read_until(proc, "installed broker")[-1] == "installed broker"
        assert read_line(proc).startswith("WARNING systemd daemon not found")
        # prompt "install daemon? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will install daemon"
        assert read_line(proc) == "installed daemon"
        assert read_line(proc) == "WARNING daemon dead"
        # prompt "start daemon? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will start daemon"
        assert read_until(proc, "started daemon")[-1] == "started daemon"
        assert read_line(proc) == "install SUCCESS"

        write_cmd(proc, "journalctl -u procustodibus-broker -q -g started")
        assert read_line(proc).endswith("Started Pro Custodibus Broker.")

        write_cmd(proc, "./install.sh --remove --dryrun")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "dryrun force remove " + version
        assert read_line(proc).startswith("WARNING daemon running")
        assert read_line(proc) == "OK will stop daemon"
        assert read_line(proc).startswith("WARNING systemd daemon found")
        assert read_line(proc) == "OK will remove daemon"
        assert read_line(proc).startswith("WARNING python virtualenv found")
        assert read_line(proc) == "OK will delete virtualenv"
        assert read_line(proc) == f"WARNING daemon user {USER} found"
        assert read_line(proc) == "OK will delete user"
        assert read_line(proc).startswith("WARNING broker configuration found")
        assert read_line(proc) == "OK will delete configuration"
        assert read_line(proc).startswith("WARNING broker credentials found")
        assert read_line(proc) == "OK will delete credentials"
        assert read_line(proc).startswith("broker setup not found")
        assert read_line(proc) == "dryrun complete"

        write_cmd(proc, "./install.sh --remove")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "remove " + version
        assert read_line(proc).startswith("WARNING daemon running")
        # prompt "stop daemon? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will stop daemon"
        assert read_until(proc, "stopped daemon")[-1] == "stopped daemon"
        assert read_line(proc).startswith("WARNING systemd daemon found")
        # prompt "remove daemon? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will remove daemon"
        assert read_line(proc) == "removed daemon"
        assert read_line(proc).startswith("WARNING python virtualenv found")
        # prompt "delete virtualenv? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will delete virtualenv"
        assert read_line(proc) == "deleted virtualenv"
        assert read_line(proc) == f"WARNING daemon user {USER} found"
        # prompt "delete user? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will delete user"
        assert read_line(proc) == "deleted user"
        assert read_line(proc).startswith("WARNING broker configuration found")
        # prompt "delete configuration? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will delete configuration"
        assert read_line(proc) == "deleted configuration"
        assert read_line(proc).startswith("WARNING broker credentials found")
        # prompt "delete credentials? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will delete credentials"
        assert read_line(proc) == "deleted credentials"
        assert read_line(proc).startswith("broker setup not found")
        assert read_line(proc) == "remove SUCCESS"

        write_cmd(proc, "./install.sh --remove --dryrun")
        assert read_line(proc) == "running as root"
        assert read_line(proc) == "dryrun force remove " + version
        assert read_line(proc) == "daemon dead"
        assert read_line(proc).startswith("systemd daemon not found")
        assert read_line(proc).startswith("python virtualenv not found")
        assert read_line(proc).startswith(f"daemon user {USER} not found")
        assert read_line(proc).startswith("broker configuration not found")
        assert read_line(proc).startswith("broker credentials not found")
        assert read_line(proc).startswith("broker setup not found")
        assert read_line(proc) == "dryrun complete"


@pytest.mark.timeout(120)
def test_forced_install_with_empty_setup():
    with exec_docker_shell("ubuntu_jammy") as proc:
        write_empty_cnf(proc, setup=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"
        assert read_line(proc).startswith("force install")
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc).startswith("broker setup found")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "created user"
        assert read_line(proc) == "/etc/procustodibus mode ok (drwxr-xr-x)"
        assert read_line(proc) == "/etc/procustodibus/broker mode ok (drwxr-xr-x)"
        assert read_line(proc).endswith(f"bus/broker owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"bus/broker group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("broker.conf mode should be 644")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"broker.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"broker.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("setup.conf mode should be 640")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"setup.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"setup.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc) == "WARNING libsodium not found"
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "WARNING python missing these packages: ensurepip"
        assert read_line(proc) == "OK will install missing packages"
        assert read_until(proc, "installed missing")[-1] == "installed missing packages"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"
        assert read_line(proc) == "created virtualenv"
        assert read_line(proc) == "WARNING broker package not installed"
        assert read_line(proc) == "OK will install broker"
        assert read_until(proc, "installed broker")[-1] == "installed broker"
        assert read_line(proc).startswith("WARNING systemd daemon not found")
        assert read_line(proc) == "OK will install daemon"
        assert read_line(proc) == "installed daemon"
        assert read_line(proc) == "WARNING daemon dead"
        assert read_line(proc) == "OK will start daemon"
        assert read_until(proc, "started daemon")[-1] == "started daemon"
        assert read_line(proc) == "install SUCCESS"

        write_cmd(proc, "journalctl -u procustodibus-broker -q -g started")
        assert read_line(proc).endswith("Started Pro Custodibus Broker.")

A test_install/install_ubuntu_lunar.py => test_install/install_ubuntu_lunar.py +78 -0
@@ 0,0 1,78 @@
# -*- coding: utf-8 -*-
"""Install tests for Ubuntu Lunar (23.04)."""
import pytest

from .util import exec_docker_shell, read_line, read_until, write_cmd, write_fake_cnf

USER = "procustodibus-broker"


@pytest.mark.timeout(90)
def test_forced_install_with_fake_credentials():
    with exec_docker_shell("ubuntu_lunar") as proc:
        write_fake_cnf(proc, credentials=True)
        write_cmd(proc, "./install.sh --install --force")
        assert read_line(proc) == "running as root"
        assert read_line(proc).startswith("force install")
        assert read_line(proc).startswith("broker configuration found")
        assert read_line(proc).startswith("broker credentials found")
        assert read_line(proc) == f"WARNING daemon user {USER} not found"
        assert read_line(proc) == "OK will create user"
        assert read_line(proc) == "created user"
        assert read_line(proc) == "/etc/procustodibus mode ok (drwxr-xr-x)"
        assert read_line(proc) == "/etc/procustodibus/broker mode ok (drwxr-xr-x)"
        assert read_line(proc).endswith(f"bus/broker owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"bus/broker group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("broker.conf mode ok (-rw-r--r--)")
        assert read_line(proc).endswith(f"broker.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"broker.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc).endswith("credentials.conf mode should be 640")
        assert read_line(proc) == "OK will fix mode"
        assert read_line(proc) == "fixed mode"
        assert read_line(proc).endswith(f"credentials.conf owner should be {USER}")
        assert read_line(proc) == "OK will fix owner"
        assert read_line(proc) == "fixed owner"
        assert read_line(proc).endswith(f"credentials.conf group should be {USER}")
        assert read_line(proc) == "OK will fix group"
        assert read_line(proc) == "fixed group"
        assert read_line(proc) == "WARNING libsodium not found"
        assert read_line(proc) == "OK will install libsodium"
        assert read_until(proc, "installed libsodium")[-1] == "installed libsodium"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "WARNING python missing these packages: ensurepip"
        assert read_line(proc) == "OK will install missing packages"
        assert read_until(proc, "installed missing")[-1] == "installed missing packages"
        assert read_line(proc).startswith("WARNING python virtualenv not found")
        assert read_line(proc) == "OK will create virtualenv"
        assert read_line(proc) == "created virtualenv"
        assert read_line(proc) == "WARNING broker package not installed"
        assert read_line(proc) == "OK will install broker"
        assert read_until(proc, "installed broker")[-1] == "installed broker"
        assert read_line(proc).startswith("WARNING systemd daemon not found")
        assert read_line(proc) == "OK will install daemon"
        assert read_line(proc) == "installed daemon"
        assert read_line(proc) == "WARNING daemon dead"
        assert read_line(proc) == "OK will start daemon"
        assert read_until(proc, "started daemon")[-1] == "started daemon"
        assert read_line(proc) == "install SUCCESS"

        write_cmd(proc, "journalctl -u procustodibus-broker -q -g started")
        assert read_line(proc).endswith(
            "Started procustodibus-broker.service - Pro Custodibus Broker."
        )

        write_cmd(
            proc, "/opt/venvs/procustodibus-broker/bin/procustodibus-broker --test"
        )
        assert read_line(proc).endswith("is pro custodibus ip address ...")
        assert read_line(proc) == "... healthy pro custodibus api ..."
        assert read_line(proc).startswith("!!! cannot access queues")
        assert read_line(proc).startswith("Issues encountered")

R test_install/install_upgrade_ubuntu_focal.py => test_install/install_upgrade_ubuntu_jammy.py +6 -6
@@ 1,5 1,5 @@
# -*- coding: utf-8 -*-
"""Upgrade tests for Ubuntu Focal (20.04)."""
"""Upgrade tests for Ubuntu Jammy (22.04)."""
import pytest

from procustodibus_broker import __version__ as version


@@ 13,7 13,7 @@ OLD_DOWNLOAD_URL = "https://ad.custodib.us/brokers/{}.tar.gz".format(OLD_DIR)

@pytest.mark.timeout(120)
def test_upgrade():
    with exec_docker_shell("ubuntu_focal") as proc:
    with exec_docker_shell("ubuntu_jammy") as proc:
        write_empty_cnf(proc, credentials=True)

        # install old version from download site


@@ 43,7 43,7 @@ def test_upgrade():
        assert read_line(proc).endswith("owner is procustodibus-broker")
        assert read_line(proc).endswith("group is procustodibus-broker")
        assert read_line(proc).startswith("libsodium found")
        assert read_line(proc) == "python 3.8.10 found at /usr/bin/python3"
        assert read_line(proc).endswith("found at /usr/bin/python3")
        assert read_line(proc) == "python includes all packages needed for venv"
        assert read_line(proc).startswith("python virtualenv found")
        assert (


@@ 59,9 59,9 @@ def test_upgrade():
        assert read_line(proc) == "OK will upgrade broker"
        assert read_until(proc, "upgraded broker")[-1] == "upgraded broker"
        assert read_line(proc).startswith("systemd daemon found")
        assert read_line(proc) == "WARNING daemon failed"
        assert read_line(proc) == "WARNING daemon requires restart"
        # prompt "start daemon? ([y]es, [q]uit)"
        write_cmd(proc, "y")
        assert read_line(proc) == "OK will start daemon"
        assert read_until(proc, "started daemon")[-1] == "started daemon"
        assert read_line(proc) == "OK will restart daemon"
        assert read_until(proc, "started daemon")[-1] == "restarted daemon"
        assert read_line(proc) == "install SUCCESS"

A test_install/opensuse-15.dockerfile => test_install/opensuse-15.dockerfile +5 -0
@@ 0,0 1,5 @@
FROM opensuse/leap:15
RUN zypper install -y systemd
RUN /bin/sh -c 'cd /usr/lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/usr/lib/systemd/systemd"]

D test_install/oracle-8.dockerfile => test_install/oracle-8.dockerfile +0 -4
@@ 1,4 0,0 @@
FROM oraclelinux:8
RUN yum install -y systemd
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

R test_install/amzn-2022.dockerfile => test_install/oracle-9.dockerfile +3 -1
@@ 1,4 1,6 @@
FROM amazonlinux:2022
FROM oraclelinux:9
RUN yum install -y systemd
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
RUN ldconfig
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

M test_install/rhel-8.dockerfile => test_install/rhel-8.dockerfile +1 -0
@@ 1,4 1,5 @@
FROM registry.access.redhat.com/ubi8/ubi-init:latest
RUN dnf install -y systemd
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

R test_install/rocky-8.dockerfile => test_install/rhel-9.dockerfile +2 -1
@@ 1,4 1,5 @@
FROM rockylinux:8
FROM registry.access.redhat.com/ubi9/ubi-init:latest
RUN dnf install -y systemd
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

A test_install/rocky-9.dockerfile => test_install/rocky-9.dockerfile +5 -0
@@ 0,0 1,5 @@
FROM rockylinux:9
RUN dnf install -y systemd
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

M test_install/ubuntu-focal.dockerfile => test_install/ubuntu-focal.dockerfile +2 -1
@@ 1,5 1,6 @@
FROM ubuntu:20.04
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y systemd wget
RUN apt-get update && apt-get install -y systemd
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

A test_install/ubuntu-jammy.dockerfile => test_install/ubuntu-jammy.dockerfile +6 -0
@@ 0,0 1,6 @@
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y systemd wget
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]

A test_install/ubuntu-lunar.dockerfile => test_install/ubuntu-lunar.dockerfile +6 -0
@@ 0,0 1,6 @@
FROM ubuntu:23.04
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get install -y systemd wget
RUN /bin/sh -c 'cd /lib/systemd/system/sysinit.target.wants/ && rm $(ls | grep -v systemd-tmpfiles-setup)'
WORKDIR /usr/local/src/broker
CMD ["/lib/systemd/systemd"]