1
0
Fork 0

Add FastCGI support for PHP-FPM and backend server protocol configuration

- Introduced `proto` and `socket` options for backend communication, supporting protocols like FastCGI (fcgi) and HTTP/2 (h2).
- Updated HAProxy configuration templates to handle Unix socket paths and protocol-specific settings.
- Enhanced documentation with examples for FastCGI using Unix sockets and TCP connections.
- Added new tests to validate FastCGI support, including expected configuration generation.
This commit is contained in:
Joao Gilberto Magalhaes 2025-11-30 13:23:56 -05:00
parent 51f8cd4659
commit a993025718
4 changed files with 126 additions and 15 deletions

View file

@ -175,13 +175,33 @@ class HaproxyConfigGenerator:
""
)
# Protocol for backend server communication (e.g., fcgi, h2)
proto = self.label.get(
self.label.create([definition, "proto"]),
""
)
# Unix socket path (alternative to host:port)
socket_path = self.label.get(
self.label.create([definition, "socket"]),
""
)
for hostname in sorted(d[host_label].split(",")):
hostname = hostname.strip()
self.serving_hosts.append("%s:%s" % (hostname, port))
easymapping[port]["hosts"].setdefault(hostname, {})
easymapping[port]["hosts"][hostname].setdefault("containers", [])
easymapping[port]["hosts"][hostname].setdefault("certbot", False)
easymapping[port]["hosts"][hostname]["containers"] += ["{}:{}".format(container, ct_port)]
easymapping[port]["hosts"][hostname].setdefault("proto", proto)
# Determine server address: Unix socket or TCP host:port
if socket_path:
server_address = socket_path
else:
server_address = "{}:{}".format(container, ct_port)
easymapping[port]["hosts"][hostname]["containers"] += [server_address]
easymapping[port]["hosts"][hostname]["certbot"] = certbot
easymapping[port]["hosts"][hostname]["redirect_ssl"] = self.label.get_bool(
self.label.create([definition, "redirect_ssl"])

View file

@ -97,7 +97,7 @@ backend srv_{{ host }}
tcp-check connect{{ " ssl" if o["ssl-check"] == "ssl" }}
{% endif %}
{% for c in o["hosts"][k]["containers"] %}
server srv-{{ loop.index0 }} {{ c }} check weight 1{{ " verify none" if o["ssl-check"] == "ssl" }}
server srv-{{ loop.index0 }} {{ c }} check weight 1{{ " verify none" if o["ssl-check"] == "ssl" }}{{ " proto " + o["hosts"][k]["proto"] if o["hosts"][k].get("proto") }}
{% endfor %}
{% endfor %}
{% endfor %}

View file

@ -124,6 +124,7 @@ def test_parser_finds_services_raw():
"my-stack_agent:9001"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
}
@ -143,6 +144,7 @@ def test_parser_finds_services_raw():
"my-stack_cadvisor:8080"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
},
@ -152,6 +154,7 @@ def test_parser_finds_services_raw():
"my-stack_node-exporter:9100"
],
"certbot": True,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
}
@ -171,6 +174,7 @@ def test_parser_finds_services_raw():
"my-stack_node-exporter:9100"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
},
@ -180,6 +184,7 @@ def test_parser_finds_services_raw():
"some-service:80"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
}
@ -204,6 +209,7 @@ def test_parser_finds_services_raw():
"some-service:80"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
}
@ -471,6 +477,7 @@ def test_parser_finds_services_clone_to_ssl_raw():
"10.152.183.215:8080"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
},
@ -480,6 +487,7 @@ def test_parser_finds_services_clone_to_ssl_raw():
"10.152.183.62:8080"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
},
@ -489,6 +497,7 @@ def test_parser_finds_services_clone_to_ssl_raw():
"10.152.183.62:8080"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
}
@ -508,6 +517,7 @@ def test_parser_finds_services_clone_to_ssl_raw():
"10.152.183.215:8080"
],
"certbot": False,
"proto": "",
"redirect_ssl": False,
"plugin_configs": []
}
@ -525,6 +535,37 @@ def test_parser_finds_services_clone_to_ssl_raw():
assert parsed_object == processed
assert [] == cfg.certbot_hosts
def test_parser_fcgi():
"""Test FastCGI support with proto and socket parameters"""
line_list = load_fixture("services-fcgi")
result = {
"customerrors": False,
"stats": {
"port": 0
}
}
cfg = easymapping.HaproxyConfigGenerator(result)
haproxy_config = cfg.generate(line_list)
assert len(haproxy_config) > 0
# Verify proto fcgi is in the output
assert "proto fcgi" in haproxy_config
# Verify Unix socket path is used
assert "/run/php/php-fpm.sock" in haproxy_config
# Verify TCP connection is also present
assert "172.17.0.3:9000" in haproxy_config
path = os.path.dirname(os.path.realpath(__file__))
with open(path + "/expected/services-fcgi.txt", 'r') as expected_file:
assert expected_file.read() == haproxy_config
assert [] == cfg.certbot_hosts
# test_parser_finds_services_raw()
# test_parser_tcp()
# test_parser_multiple_hosts()