Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions src/haproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import pwd
from pathlib import Path
from subprocess import CalledProcessError, run # nosec

from charms.operator_libs_linux.v0 import apt
from charms.operator_libs_linux.v1 import systemd
Expand All @@ -16,7 +17,7 @@
from state.haproxy_route import HaproxyRouteRequirersInformation
from state.ingress import IngressRequirersInformation

APT_PACKAGE_VERSION = "2.8.5-1ubuntu3"
APT_PACKAGE_VERSION = "2.8.5-1ubuntu3.3"
APT_PACKAGE_NAME = "haproxy"
HAPROXY_CONFIG_DIR = Path("/etc/haproxy")
HAPROXY_CONFIG = Path(HAPROXY_CONFIG_DIR / "haproxy.cfg")
Expand Down Expand Up @@ -48,6 +49,14 @@
logger = logging.getLogger()


class HaproxyPackageVersionPinError(Exception):
"""Error when pinning the version of the haproxy package."""


class HaproxyServiceNotActiveError(Exception):
"""Exception raised when both the reverseproxy and ingress relation are established."""


class HaproxyServiceReloadError(Exception):
"""Error when reloading the haproxy service."""

Expand All @@ -63,16 +72,18 @@ def install(self) -> None:
"""Install the haproxy apt package.

Raises:
RuntimeError: If the service is not running after installation.
HaproxyServiceNotActiveError: If the service is not running after installation.
"""
apt.update()
apt.add_package(package_names=APT_PACKAGE_NAME, version=APT_PACKAGE_VERSION)
apt.add_package(
package_names=APT_PACKAGE_NAME, version=APT_PACKAGE_VERSION, update_cache=True
)
pin_haproxy_package_version()

render_file(HAPROXY_DHCONFIG, HAPROXY_DH_PARAM, 0o644)
self._reload_haproxy_service()

if not self.is_active():
raise RuntimeError("HAProxy service is not running.")
raise HaproxyServiceNotActiveError("HAProxy service is not running.")

def is_active(self) -> bool:
"""Indicate if the haproxy service is active.
Expand Down Expand Up @@ -221,3 +232,17 @@ def file_exists(path: Path) -> bool:
bool: True if the file exists.
"""
return path.exists()


def pin_haproxy_package_version() -> None:
"""Pin the haproxy package version.

Raises:
HaproxyPackageVersionPinError: When pinning the haproxy package version failed.
"""
try:
# We ignore security warning here as we're not parsing inputs
run(["/usr/bin/apt-mark", "hold", "haproxy"], check=True) # nosec
except CalledProcessError as exc:
logger.error("Failed calling apt-mark hold haproxy: %s", exc.stderr)
raise HaproxyPackageVersionPinError("Failed pinning the haproxy package version") from exc
4 changes: 1 addition & 3 deletions tests/unit/test_haproxy_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@ def test_deploy(monkeypatch: pytest.MonkeyPatch):
act: Call haproxy_service.install().
assert: The apt mocks are called once.
"""
apt_update_mock = MagicMock()
monkeypatch.setattr("charms.operator_libs_linux.v0.apt.update", apt_update_mock)
apt_add_package_mock = MagicMock()
monkeypatch.setattr("charms.operator_libs_linux.v0.apt.add_package", apt_add_package_mock)
render_file_mock = MagicMock()
monkeypatch.setattr("haproxy.render_file", render_file_mock)
monkeypatch.setattr("haproxy.run", MagicMock())

haproxy_service = HAProxyService()
haproxy_service.install()

apt_update_mock.assert_called_once()
apt_add_package_mock.assert_called_once()
render_file_mock.assert_called_once_with(HAPROXY_DHCONFIG, HAPROXY_DH_PARAM, 0o644)
Loading