Skip to content
Draft
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
9 changes: 6 additions & 3 deletions .github/workflows/integration_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ on:

jobs:
integration-tests:
uses: canonical/operator-workflows/.github/workflows/integration_test.yaml@main
uses:
canonical/operator-workflows/.github/workflows/integration_test.yaml@main
secrets: inherit
with:
provider: lxd
juju-channel: 3/stable
self-hosted-runner: true
charmcraft-channel: latest/edge
modules: '["test_action.py","test_actions.py","test_charm.py","test_config.py","test_cos.py","test_ha.py","test_haproxy_route.py","test_http_interface.py","test_ingress.py", "test_ingress_per_unit.py", "test_haproxy_route_tcp.py"]'
modules: '["test_action.py","test_actions.py","test_charm.py","test_config.py","test_cos.py","test_ha.py","test_haproxy_route.py","test_http_interface.py","test_ingress.py",
"test_ingress_per_unit.py", "test_haproxy_route_tcp.py"]'
with-uv: true
allure-report:
if: always() && !cancelled()
needs:
- integration-tests
- integration-tests
uses: canonical/operator-workflows/.github/workflows/allure_report.yaml@main
6 changes: 4 additions & 2 deletions .github/workflows/load_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ name: Load tests

on:
schedule:
- cron: "0 12 * * 0"
- cron: "0 12 * * 0"

jobs:
load-tests:
uses: canonical/operator-workflows/.github/workflows/integration_test.yaml@main
uses:
canonical/operator-workflows/.github/workflows/integration_test.yaml@main
with:
load-test-enabled: true
load-test-run-args: "-e LOAD_TEST_HOST=localhost"
with-uv: true
secrets: inherit
1 change: 1 addition & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ jobs:
self-hosted-runner: true
self-hosted-runner-image: "noble"
charmcraft-channel: latest/edge
with-uv: true
1 change: 1 addition & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ header:
- 'src/loki_alert_rules/*.rule'
- 'docs/release-notes/**/*.yaml'
- '**/*.md.j2'
- 'uv.lock'
comment: on-failure
25 changes: 23 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
# Contributing

## Developing

To make contributions to this charm, you'll need a working [development setup](https://documentation.ubuntu.com/juju/3.6/howto/manage-your-juju-deployment/set-up-your-juju-deployment-local-testing-and-development/).

You can create an environment for development with `tox`:
The code for this charm can be downloaded as follows:

```
git clone https://github.com/canonical/haproxy-operator
```

Make sure to install [uv](https://docs.astral.sh/uv/), for example:

```sh
sudo snap install astral-uv --classic
```

Then install `tox` with extensions, as well as a range of Python versions:

```sh
uv tool install tox --with tox-uv
uv tool update-shell
```

To create an environment for development, use:

```shell
tox devenv -e integration
uv sync --all-groups
source venv/bin/activate
```

Expand Down
44 changes: 22 additions & 22 deletions charmcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,23 @@ platforms:

parts:
charm:
build-packages:
- build-essential
- python3-dev
- pkg-config
- libffi-dev
- libssl-dev
- git
source: .
plugin: uv
build-snaps:
- rustup
override-build: |
rustup default stable
craftctl default

- astral-uv
build-packages:
- git
templates:
plugin: dump
source: .
stage:
- templates
name: haproxy
title: HAProxy charm.
description: |
A [Juju](https://juju.is/) [charm](https://juju.is/docs/olm/charmed-operators)
deploying and managing [HAProxy](https://www.haproxy.org/) on machines.

HAProxy is a TCP/HTTP reverse proxy which is particularly suited for high
availability environments. It features connection persistence through HTTP
cookies, load balancing, header addition, modification, deletion both ways. It
Expand All @@ -38,14 +36,15 @@ description: |
VMs and bare metal.
summary: Fast and reliable load balancing reverse proxy.
links:
documentation: https://discourse.charmhub.io/t/haproxy-documentation-overview/17216
documentation:
https://discourse.charmhub.io/t/haproxy-documentation-overview/17216
issues: https://github.com/canonical/haproxy-operator/issues
source: https://github.com/canonical/haproxy-operator
contact:
- https://launchpad.net/~canonical-is-devops
- https://launchpad.net/~canonical-is-devops

assumes:
- juju >= 3.3
- juju >= 3.3
requires:
certificates:
interface: tls-certificates
Expand Down Expand Up @@ -85,21 +84,22 @@ config:
default: 4096
type: int
description: |
Sets the maximum per-process number of concurrent connections to
<number>. Must be greater than 0.
Sets the maximum per-process number of concurrent connections to
<number>. Must be greater than 0.
vip:
type: string
description: Virtual IP address, used in active-passive ha mode.

actions:
get-certificate:
description: Returns the TLS Certificate. Intended for testing and debugging purposes.
description: Returns the TLS Certificate. Intended for testing and debugging
purposes.
params:
hostname:
type: string
description: Hostname to extract certs from.
required:
- hostname
- hostname
get-proxied-endpoints:
description: |
Return a list of endpoints
Expand All @@ -113,5 +113,5 @@ actions:
If no backend with this name is present, an empty list is returned.

charm-libs:
- lib: traefik_k8s.ingress_per_unit
version: "1"
- lib: traefik_k8s.ingress_per_unit
version: "1"
4 changes: 4 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

Each revision is versioned by the date of the revision.

## 2025-11-12

- Migrated development tooling to uv and ruff for faster dependency management and linting.

## 2025-10-14

- Added action `get-proxied-endpoints`.
Expand Down
18 changes: 7 additions & 11 deletions lib/charms/haproxy/v0/haproxy_route_tcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def _on_haproxy_route_data_available(self, event: EventBase) -> None:

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 1
LIBPATCH = 2

logger = logging.getLogger(__name__)
HAPROXY_ROUTE_TCP_RELATION_NAME = "haproxy-route-tcp"
Expand Down Expand Up @@ -575,7 +575,7 @@ class TcpRequirerApplicationData(_DatabagModel):
port: int = Field(description="The port exposed on the provider.", gt=0, le=65535)
backend_port: Optional[int] = Field(
description=(
"The port where the backend service is listening. " "Defaults to the provider port."
"The port where the backend service is listening. Defaults to the provider port."
),
default=None,
gt=0,
Expand Down Expand Up @@ -1162,7 +1162,7 @@ def provide_haproxy_route_tcp_requirements(
self.update_relation_data()

# pylint: disable=too-many-arguments,too-many-positional-arguments,too-many-locals
def _generate_application_data( # noqa: C901
def _generate_application_data(
self,
*,
port: Optional[int] = None,
Expand Down Expand Up @@ -1625,10 +1625,8 @@ def configure_bandwidth_limit(
"""
if not upload_bytes_per_second and not download_bytes_per_second:
logger.error(
(
"At least one of `upload_bytes_per_second` "
"or `upload_bytes_per_second` must be set."
)
"At least one of `upload_bytes_per_second` "
"or `upload_bytes_per_second` must be set."
)
return self
self._application_data["bandwidth_limit"] = {
Expand Down Expand Up @@ -1677,10 +1675,8 @@ def configure_timeout(
server_timeout_in_seconds or connect_timeout_in_seconds or queue_timeout_in_seconds
):
logger.error(
(
"At least one of `server_timeout_in_seconds`, `connect_timeout_in_seconds` "
"or `queue_timeout_in_seconds` must be set."
)
"At least one of `server_timeout_in_seconds`, `connect_timeout_in_seconds` "
"or `queue_timeout_in_seconds` must be set."
)
return self
self._application_data["timeout"] = self._generate_timeout_configuration(
Expand Down
8 changes: 4 additions & 4 deletions lib/charms/haproxy/v1/haproxy_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def _on_haproxy_route_data_available(self, event: EventBase) -> None:

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 7
LIBPATCH = 8

logger = logging.getLogger(__name__)
HAPROXY_ROUTE_RELATION_NAME = "haproxy-route"
Expand Down Expand Up @@ -875,9 +875,9 @@ def publish_proxied_endpoints(self, endpoints: list[str], relation: Relation) ->
endpoints: The list of proxied endpoints to publish.
relation: The relation with the requirer application.
"""
HaproxyRouteProviderAppData(
endpoints=list(map(lambda x: cast(AnyHttpUrl, x), endpoints))
).dump(relation.data[self.charm.app], clear=True)
HaproxyRouteProviderAppData(endpoints=[cast(AnyHttpUrl, e) for e in endpoints]).dump(
relation.data[self.charm.app], clear=True
)


class HaproxyRouteEnpointsReadyEvent(EventBase):
Expand Down
Loading