Skip to content

Fix HAProxy peer entries to include name, address, and port#462

Draft
Copilot wants to merge 5 commits intomainfrom
copilot/fix-haproxy-peer-configuration
Draft

Fix HAProxy peer entries to include name, address, and port#462
Copilot wants to merge 5 commits intomainfrom
copilot/fix-haproxy-peer-configuration

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 13, 2026

HAProxy was discarding the entire peers section because entries were rendered as peer <address> instead of the required peer <name> <address>:<port> format.

Changes

  • state/peers.py (new): Add PeersInformation mixin class with HAPROXY_PEER_PORT = 10000 constant and formatted_peer_entries / peer_tcp_port @property methods that pre-render peer lines (e.g. 10-68-79-144 10.68.79.144:10000).
  • State dataclasses: IngressRequirersInformation, IngressPerUnitRequirersInformation, and HaproxyRouteRequirersInformation now subclass PeersInformation, exposing the peer formatting as properties.
  • src/haproxy.py: reconcile_ingress and reconcile_haproxy_route now read formatted_peer_entries and peer_tcp_port directly from the state objects instead of calling a standalone helper.
  • Templates (haproxy_route.cfg.j2, haproxy_ingress.cfg.j2, haproxy_ingress_per_unit.cfg.j2): Add bind *:{{ peer_tcp_port }} and consume pre-rendered peer entries.
  • Tests: Add unit tests for the PeersInformation mixin covering IPv4, IPv6, empty input, and port property.

Before/After

# Before (invalid — HAProxy discards this)
peers haproxy_peers
    peer 10.68.79.144

# After
peers haproxy_peers
    bind *:10000
    peer 10-68-79-144 10.68.79.144:10000

Copilot AI and others added 2 commits April 13, 2026 11:46
Add HAPROXY_PEER_PORT constant (10000) and _format_peer_entries helper
to render peer entries as '<name> <address>:<port>' instead of just
'<address>'. Also add 'bind *:<port>' to the peers section in all
templates. This fixes HAProxy discarding peers due to invalid config.

Agent-Logs-Url: https://github.com/canonical/haproxy-operator/sessions/71b67230-85a7-4437-ba07-80b49a93c036

Co-authored-by: Thanhphan1147 <42444001+Thanhphan1147@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix invalid peer configuration in HAProxy Fix HAProxy peer entries to include name, address, and port Apr 13, 2026
Copilot AI requested a review from Thanhphan1147 April 13, 2026 11:50
Comment thread haproxy-operator/src/haproxy.py Outdated
Comment on lines +290 to +309
def _format_peer_entries(peers: list[IPvAnyAddress]) -> list[str]:
"""Format peer IP addresses into HAProxy peer entry strings.

Each entry is formatted as ``<name> <address>:<port>`` where ``<name>``
is derived from the IP address with non-alphanumeric characters replaced
by hyphens.

Args:
peers: List of peer IP addresses.

Returns:
list[str]: Formatted peer entry strings.
"""
entries: list[str] = []
for addr in peers:
name = str(addr).replace(".", "-").replace(":", "-")
entries.append(f"{name} {addr}:{HAPROXY_PEER_PORT}")
return entries


Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot This should be a @Property of the charmstate dataclass ( ingress_requirers_information and haproxy_route_requirers_information ). In fact we can make a separate dataclass for this and subclass it in each of the mentioned charmstate dataclass.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved HAPROXY_PEER_PORT and the formatting logic into a PeersInformation mixin class in state/peers.py with formatted_peer_entries and peer_tcp_port as @property methods. IngressRequirersInformation, IngressPerUnitRequirersInformation, and HaproxyRouteRequirersInformation all subclass it. src/haproxy.py now reads the properties from the state objects. See d1ac83e.

…ataclasses

Move HAPROXY_PEER_PORT and peer formatting logic from src/haproxy.py
into a PeersInformation mixin class in state/peers.py. All three state
dataclasses (IngressRequirersInformation, IngressPerUnitRequirersInformation,
HaproxyRouteRequirersInformation) now subclass PeersInformation and expose
formatted_peer_entries and peer_tcp_port as @Property methods.

Agent-Logs-Url: https://github.com/canonical/haproxy-operator/sessions/29068634-9a26-492a-a765-4ae185a92429

Co-authored-by: Thanhphan1147 <42444001+Thanhphan1147@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Test results for commit 4301920

Test coverage for 4301920

Name                                       Stmts   Miss Branch BrPart  Cover   Missing
--------------------------------------------------------------------------------------
lib/charms/haproxy/v0/ddos_protection.py     154     51     34      8    64%   157-174, 183-187, 288, 316-318, 323, 326-330, 342-344, 381, 387, 393, 396, 424, 495-498, 510-529
src/charm.py                                  21      0      0      0   100%
src/state.py                                  43      0      0      0   100%
--------------------------------------------------------------------------------------
TOTAL                                        218     51     34      8    73%

Static code analysis report

Run started:2026-05-07 09:30:13.131434+00:00

Test results:
  No issues identified.

Code scanned:
  Total lines of code: 333
  Total lines skipped (#nosec): 0
  Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0

Run metrics:
  Total issues (by severity):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
  Total issues (by confidence):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
Files skipped (0):

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Test results for commit 4301920

Test coverage for 4301920

Name                                         Stmts   Miss Branch BrPart  Cover   Missing
----------------------------------------------------------------------------------------
lib/charms/haproxy/v0/ddos_protection.py       154     42     34      3    72%   157-174, 183-187, 265, 284, 415-418, 422-424, 459-478, 514-529
lib/charms/haproxy/v0/spoe_auth.py             158     55     32      2    59%   203, 304-306, 315, 354-381, 392-402, 441-442, 459-472, 484-501, 522-525, 529-531
lib/charms/haproxy/v1/haproxy_route_tcp.py     385    153     78      8    56%   209, 212, 281, 290-293, 297-300, 318-321, 336, 342-347, 447, 452, 829-832, 836, 863-874, 897-900, 904-906, 926-928, 1042-1083, 1087-1093, 1097, 1166-1195, 1266-1305, 1335-1337, 1362-1364, 1386-1390, 1409-1411, 1429-1431, 1438-1444, 1452-1454, 1462-1463, 1474-1481, 1494-1505, 1513-1534, 1546-1547, 1558-1559, 1570-1573, 1584-1585, 1614-1623, 1639-1642, 1658-1669, 1685-1688, 1706-1717, 1728-1729, 1737-1738, 1746-1747, 1758-1761
lib/charms/haproxy/v2/haproxy_route.py         386     54     98     27    82%   181, 202, 257, 266-269, 294-297, 318-323, 673-674, 867->exit, 874, 900-911, 934-937, 941-943, 962-964, 1136-1142, 1146, 1343->1345, 1347->1349, 1349->1351, 1351->1353, 1353->1355, 1355->1358, 1393, 1401, 1406, 1409, 1434, 1462, 1466, 1470, 1493, 1513, 1522-1523, 1525->exit, 1561-1563, 1583, 1597, 1602-1604
src/charm.py                                   293     71     84     13    71%   102, 228, 236-252, 257, 262, 280, 291, 297-298, 332-352, 371, 471, 478-486, 514-527, 540-545, 554, 567-568, 575, 585, 595, 601-607, 623, 674-677, 683->682, 696-699
src/haproxy.py                                 125     31      6      2    75%   108-114, 134-157, 268-269, 272, 280-286, 314, 344-355, 367-369, 379-380
src/http_interface.py                           73     25      4      0    62%   74, 83, 92, 106-108, 126, 138, 150, 162, 170-175, 187, 194, 202, 217-227
src/state/charm_state.py                        78     15     14      4    79%   94-96, 101-102, 105, 150-155, 164, 216-218, 230-231
src/state/ddos_protection.py                    39      0      2      0   100%
src/state/exception.py                           1      0      0      0   100%
src/state/ha.py                                 30      1      2      1    94%   50
src/state/haproxy_route.py                     284     46     76      8    82%   162, 191-200, 257, 282, 333-361, 370, 379, 388, 397, 409, 447-473, 529, 569, 585-586, 603, 823-836
src/state/haproxy_route_tcp.py                 120     17     42      1    80%   92-94, 109->112, 147-160
src/state/ingress.py                            39      0      4      0   100%
src/state/ingress_per_unit.py                   33      0      4      0   100%
src/state/peers.py                              14      0      2      0   100%
src/state/spoe_auth.py                          26      2      2      0    93%   63-64
src/state/tls.py                                39      7     12      4    78%   74, 77-78, 127-135, 141-142
src/state/validation.py                         46     23      8      1    44%   66-67, 71-98
src/tls_relation.py                             62      3     14      3    92%   87->86, 119-129, 141->143
----------------------------------------------------------------------------------------
TOTAL                                         2385    545    518     77    74%

Static code analysis report

Working... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
Run started:2026-05-07 09:30:22.562906+00:00

Test results:
  No issues identified.

Code scanned:
  Total lines of code: 10557
  Total lines skipped (#nosec): 13
  Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 9

Run metrics:
  Total issues (by severity):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
  Total issues (by confidence):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
Files skipped (0):

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Test results for commit 4301920

Test coverage for 4301920

Name                      Stmts   Miss Branch BrPart  Cover   Missing
---------------------------------------------------------------------
src/charm.py                 88     29     14      3    63%   97-98, 108-113, 138, 145-157, 161-176, 184-199
src/policy.py                66     37      2      0    43%   30-32, 37-38, 43-53, 58-59, 64-65, 78-92, 115-117, 140-141, 159-176, 187-197, 208-211
src/state/database.py        32      2      6      2    89%   76, 79
src/state/policy.py          62      2     10      2    94%   94, 106
src/state/validation.py      44     18      0      0    59%   57-59, 61-63, 74-87
---------------------------------------------------------------------
TOTAL                       292     88     32      7    68%

Static code analysis report

Run started:2026-05-07 09:30:03.142006+00:00

Test results:
  No issues identified.

Code scanned:
  Total lines of code: 1152
  Total lines skipped (#nosec): 10
  Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0

Run metrics:
  Total issues (by severity):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
  Total issues (by confidence):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
Files skipped (0):

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Test results for commit 4301920

Test coverage for 4301920

Name                                        Stmts   Miss  Cover
---------------------------------------------------------------
haproxy_route_policy/__init__.py                0      0   100%
haproxy_route_policy/settings.py               30      1    97%
haproxy_route_policy/test_settings.py           4      0   100%
haproxy_route_policy/urls.py                    5      0   100%
manage.py                                      11      2    82%
policy/__init__.py                              0      0   100%
policy/admin.py                                22      5    77%
policy/apps.py                                  3      0   100%
policy/db_models.py                            50      2    96%
policy/management/__init__.py                   0      0   100%
policy/management/commands/__init__.py          0      0   100%
policy/middleware.py                           16      4    75%
policy/migrations/0001_initial.py               7      0   100%
policy/migrations/0002_rule.py                  5      0   100%
policy/migrations/0003_alter_rule_kind.py       4      0   100%
policy/migrations/__init__.py                   0      0   100%
policy/rule_engine.py                          42      6    86%
policy/serializers.py                          30      4    87%
policy/tests/__init__.py                        0      0   100%
policy/tests/test_auth.py                      36     20    44%
policy/tests/test_models.py                    85      0   100%
policy/tests/test_rule_engine.py              117      0   100%
policy/tests/test_views.py                    201      0   100%
policy/urls.py                                  3      0   100%
policy/views.py                                95     16    83%
---------------------------------------------------------------
TOTAL                                         766     60    92%

Static code analysis report

Run started:2026-05-07 09:30:05.165421+00:00

Test results:
  No issues identified.

Code scanned:
  Total lines of code: 1680
  Total lines skipped (#nosec): 1
  Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0

Run metrics:
  Total issues (by severity):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
  Total issues (by confidence):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
Files skipped (0):

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 7, 2026

Test results for commit 4301920

Test coverage for 4301920

Name                               Stmts   Miss Branch BrPart  Cover   Missing
------------------------------------------------------------------------------
src/charm.py                          45      9      2      0    77%   65-91, 96-98
src/haproxy_spoe_auth_service.py      44     16      2      0    61%   56-64, 76-82, 93-117
src/state.py                          55     15      6      1    67%   64-66, 79, 125-146
------------------------------------------------------------------------------
TOTAL                                144     40     10      1    68%

Static code analysis report

Run started:2026-05-07 09:30:12.961200

Test results:
  No issues identified.

Code scanned:
  Total lines of code: 409
  Total lines skipped (#nosec): 1
  Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 1

Run metrics:
  Total issues (by severity):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
  Total issues (by confidence):
  	Undefined: 0
  	Low: 0
  	Medium: 0
  	High: 0
Files skipped (0):

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Peers discarded in HAProxy due to invalid configuration

2 participants