diff --git a/docs/release-notes/artifacts/pr0646.yaml b/docs/release-notes/artifacts/pr0646.yaml new file mode 100644 index 00000000..2a36b19b --- /dev/null +++ b/docs/release-notes/artifacts/pr0646.yaml @@ -0,0 +1,17 @@ +version_schema: 2 + +changes: + - title: Refactored get-proxied-endpoints action tests + author: minulo + type: minor + description: > + Refactored the get-proxied-endpoints Juju action tests to follow the + same style as the rest of the test suite. No user-facing behavior + changed. + urls: + pr: + - https://github.com/canonical/haproxy-operator/pull/646 + related_doc: + related_issue: + visibility: internal + highlight: false diff --git a/haproxy-operator/tests/unit/test_charm.py b/haproxy-operator/tests/unit/test_charm.py index c1bcd039..afbb4201 100644 --- a/haproxy-operator/tests/unit/test_charm.py +++ b/haproxy-operator/tests/unit/test_charm.py @@ -342,144 +342,150 @@ def test_ca_certificates_removed(monkeypatch: pytest.MonkeyPatch, receive_ca_cer @pytest.mark.usefixtures("systemd_mock", "mocks_external_calls") -class TestGetProxiedEndpointsAction: - """Test "get-proxied-endpoints" Action""" - - def test_no_backend_filter(self) -> None: - """ - arrange: create state with one haproxy-route relation containing - hostname, additional_hostnames, and paths. - act: trigger the get-proxied-endpoints action without a backend filter. - assert: returns a list of all proxied endpoints for every hostname/path combination. - """ - context = ops.testing.Context(HAProxyCharm) - - haproxy_route_relation = ops.testing.Relation( - "haproxy-route", - remote_app_data={ - "hostname": f'"{TEST_EXTERNAL_HOSTNAME_CONFIG}"', - "additional_hostnames": json.dumps( - [ - f"ok2.{TEST_EXTERNAL_HOSTNAME_CONFIG}", - f"ok3.{TEST_EXTERNAL_HOSTNAME_CONFIG}", - ] - ), - "paths": '["/v1", "/v2"]', - "ports": "[443]", - "protocol": '"http"', - "service": '"haproxy-tutorial-ingress-configurator"', - }, - remote_units_data={0: {"address": '"10.75.1.129"'}}, - ) - charm_state = ops.testing.State( - relations=[haproxy_route_relation], - leader=True, - model=ops.testing.Model(name="haproxy-tutorial"), - app_status=ops.testing.ActiveStatus(), - unit_status=ops.testing.ActiveStatus(), - ) - context.run(context.on.action("get-proxied-endpoints"), charm_state) - - out = context.action_results - assert out is not None - - assert set(json.loads(out["endpoints"])) == { - "https://haproxy.internal/v1", - "https://haproxy.internal/v2", - "https://ok2.haproxy.internal/v1", - "https://ok2.haproxy.internal/v2", - "https://ok3.haproxy.internal/v1", - "https://ok3.haproxy.internal/v2", - } - - def test_no_backend_filter_no_endpoints(self) -> None: - """ - arrange: create state with no haproxy-route relations. - act: trigger the get-proxied-endpoints action without a backend filter. - assert: returns an empty list. - """ - context = ops.testing.Context(HAProxyCharm) - charm_state = ops.testing.State( - relations=[], - leader=True, - model=ops.testing.Model(name="haproxy-tutorial"), - app_status=ops.testing.ActiveStatus(), - unit_status=ops.testing.ActiveStatus(), - ) - context.run(context.on.action("get-proxied-endpoints"), charm_state) - - out = context.action_results - - assert out == {"endpoints": "[]"} - - def test_with_backend_filter(self) -> None: - """ - arrange: create state with a haproxy-route relation for a specific backend. - act: trigger the get-proxied-endpoints action with the backend filter. - assert: returns a list containing the endpoint for that backend. - """ - service_name = "haproxy-tutorial-ingress-configurator" - context = ops.testing.Context(HAProxyCharm) - haproxy_route_relation = ops.testing.Relation( - "haproxy-route", - remote_app_data={ - "hostname": f'"{TEST_EXTERNAL_HOSTNAME_CONFIG}"', - "ports": "[443]", - "protocol": '"http"', - "service": f'"{service_name}"', - }, - remote_units_data={0: {"address": '"10.75.1.129"'}}, - ) - charm_state = ops.testing.State( - relations=[haproxy_route_relation], - leader=True, - model=ops.testing.Model(name="haproxy-tutorial"), - app_status=ops.testing.ActiveStatus(), - unit_status=ops.testing.ActiveStatus(), - ) - context.run( - context.on.action("get-proxied-endpoints", params={"backend": service_name}), - charm_state, - ) +def test_get_proxied_endpoints_no_backend_filter() -> None: + """ + arrange: create state with one haproxy-route relation containing + hostname, additional_hostnames, and paths. + act: trigger the get-proxied-endpoints action without a backend filter. + assert: returns a list of all proxied endpoints for every hostname/path combination. + """ + context = ops.testing.Context(HAProxyCharm) - out = context.action_results - - assert out == {"endpoints": f'["https://{TEST_EXTERNAL_HOSTNAME_CONFIG}"]'} - - def test_with_backend_filter_non_existing_backend(self) -> None: - """ - arrange: create state with a haproxy-route relation for a specific backend. - act: trigger the get-proxied-endpoints action with a non-existing backend name. - assert: raises ActionFailed indicating the backend does not exist. - """ - service_name = "haproxy-tutorial-ingress-configurator" - context = ops.testing.Context(HAProxyCharm) - haproxy_route_relation = ops.testing.Relation( - "haproxy-route", - remote_app_data={ - "hostname": f'"{TEST_EXTERNAL_HOSTNAME_CONFIG}"', - "ports": "[443]", - "protocol": '"http"', - "service": f'"{service_name}"', - }, - remote_units_data={0: {"address": '"10.75.1.129"'}}, - ) - charm_state = ops.testing.State( - relations=[haproxy_route_relation], - leader=True, - model=ops.testing.Model(name="haproxy-tutorial"), - app_status=ops.testing.ActiveStatus(), - unit_status=ops.testing.ActiveStatus(), - ) + haproxy_route_relation = ops.testing.Relation( + "haproxy-route", + remote_app_data={ + "hostname": f'"{TEST_EXTERNAL_HOSTNAME_CONFIG}"', + "additional_hostnames": json.dumps( + [ + f"ok2.{TEST_EXTERNAL_HOSTNAME_CONFIG}", + f"ok3.{TEST_EXTERNAL_HOSTNAME_CONFIG}", + ] + ), + "paths": '["/v1", "/v2"]', + "ports": "[443]", + "protocol": '"http"', + "service": '"haproxy-tutorial-ingress-configurator"', + }, + remote_units_data={0: {"address": '"10.75.1.129"'}}, + ) + charm_state = ops.testing.State( + relations=[haproxy_route_relation], + leader=True, + model=ops.testing.Model(name="haproxy-tutorial"), + app_status=ops.testing.ActiveStatus(), + unit_status=ops.testing.ActiveStatus(), + ) - context.run( - context.on.action("get-proxied-endpoints", params={"backend": "random_name"}), - charm_state, - ) + context.run(context.on.action("get-proxied-endpoints"), charm_state) + + out = context.action_results + assert out is not None + + assert set(json.loads(out["endpoints"])) == { + "https://haproxy.internal/v1", + "https://haproxy.internal/v2", + "https://ok2.haproxy.internal/v1", + "https://ok2.haproxy.internal/v2", + "https://ok3.haproxy.internal/v1", + "https://ok3.haproxy.internal/v2", + } + + +@pytest.mark.usefixtures("systemd_mock", "mocks_external_calls") +def test_get_proxied_endpoints_no_backend_filter_no_endpoints() -> None: + """ + arrange: create state with no haproxy-route relations. + act: trigger the get-proxied-endpoints action without a backend filter. + assert: returns an empty list. + """ + context = ops.testing.Context(HAProxyCharm) + charm_state = ops.testing.State( + relations=[], + leader=True, + model=ops.testing.Model(name="haproxy-tutorial"), + app_status=ops.testing.ActiveStatus(), + unit_status=ops.testing.ActiveStatus(), + ) + + context.run(context.on.action("get-proxied-endpoints"), charm_state) + + out = context.action_results + + assert out == {"endpoints": "[]"} + + +@pytest.mark.usefixtures("systemd_mock", "mocks_external_calls") +def test_get_proxied_endpoints_with_backend_filter() -> None: + """ + arrange: create state with a haproxy-route relation for a specific backend. + act: trigger the get-proxied-endpoints action with the backend filter. + assert: returns a list containing the endpoint for that backend. + """ + service_name = "haproxy-tutorial-ingress-configurator" + context = ops.testing.Context(HAProxyCharm) + haproxy_route_relation = ops.testing.Relation( + "haproxy-route", + remote_app_data={ + "hostname": f'"{TEST_EXTERNAL_HOSTNAME_CONFIG}"', + "ports": "[443]", + "protocol": '"http"', + "service": f'"{service_name}"', + }, + remote_units_data={0: {"address": '"10.75.1.129"'}}, + ) + charm_state = ops.testing.State( + relations=[haproxy_route_relation], + leader=True, + model=ops.testing.Model(name="haproxy-tutorial"), + app_status=ops.testing.ActiveStatus(), + unit_status=ops.testing.ActiveStatus(), + ) + + context.run( + context.on.action("get-proxied-endpoints", params={"backend": service_name}), + charm_state, + ) + + out = context.action_results + + assert out == {"endpoints": f'["https://{TEST_EXTERNAL_HOSTNAME_CONFIG}"]'} + + +@pytest.mark.usefixtures("systemd_mock", "mocks_external_calls") +def test_get_proxied_endpoints_with_backend_filter_non_existing_backend() -> None: + """ + arrange: create state with a haproxy-route relation for a specific backend. + act: trigger the get-proxied-endpoints action with a non-existing backend name. + assert: returns an empty list when the backend does not exist. + """ + service_name = "haproxy-tutorial-ingress-configurator" + context = ops.testing.Context(HAProxyCharm) + haproxy_route_relation = ops.testing.Relation( + "haproxy-route", + remote_app_data={ + "hostname": f'"{TEST_EXTERNAL_HOSTNAME_CONFIG}"', + "ports": "[443]", + "protocol": '"http"', + "service": f'"{service_name}"', + }, + remote_units_data={0: {"address": '"10.75.1.129"'}}, + ) + charm_state = ops.testing.State( + relations=[haproxy_route_relation], + leader=True, + model=ops.testing.Model(name="haproxy-tutorial"), + app_status=ops.testing.ActiveStatus(), + unit_status=ops.testing.ActiveStatus(), + ) + + context.run( + context.on.action("get-proxied-endpoints", params={"backend": "random_name"}), + charm_state, + ) - out = context.action_results + out = context.action_results - assert out == {"endpoints": "[]"} + assert out == {"endpoints": "[]"} @pytest.mark.usefixtures("systemd_mock", "mocks_external_calls")