From 5671705cf84a0e47661585d55cd549b108177ef8 Mon Sep 17 00:00:00 2001 From: Emma May Date: Fri, 15 Nov 2024 14:51:20 -0800 Subject: [PATCH 1/3] Add support for honoring the host and port arguments in consul.Consul() --- consul/base.py | 11 +++++-- tests/test_base.py | 81 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/consul/base.py b/consul/base.py index a00aa72..0bbb163 100644 --- a/consul/base.py +++ b/consul/base.py @@ -76,8 +76,8 @@ def close(self): class Consul: def __init__( self, - host: str = "127.0.0.1", - port: int = 8500, + host: str | None = None, + port: int | None = None, token: str | None = None, scheme: str = "http", consistency: str = "default", @@ -106,13 +106,18 @@ def __init__( # TODO: Status - if os.getenv("CONSUL_HTTP_ADDR"): + if os.getenv("CONSUL_HTTP_ADDR") and not (host or port): try: host, port = os.getenv("CONSUL_HTTP_ADDR").split(":") # type: ignore except ValueError as err: raise ConsulException( f"CONSUL_HTTP_ADDR ({os.getenv('CONSUL_HTTP_ADDR')}) invalid, does not match :" ) from err + if not host: + host = "127.0.0.1" + if not port: + port = 8500 + use_ssl = os.getenv("CONSUL_HTTP_SSL") if use_ssl is not None: scheme = "https" if use_ssl == "true" else "http" diff --git a/tests/test_base.py b/tests/test_base.py index c2e2ab6..571b3a6 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -15,7 +15,8 @@ class HTTPClient: def __init__( self, host: Optional[str] = None, port: Optional[int] = None, scheme=None, verify: bool = True, cert=None ) -> None: - pass + self.host = host + self.port = int(port) def get(self, callback, path, params=None, headers=None): # pylint: disable=unused-argument return Request("get", path, params, headers, None) @@ -70,6 +71,84 @@ def _should_support_meta(c: Consul) -> tuple[Callable[..., Any], ...]: ) +class TestBaseInit: + """ + Tests that connection arguments are handled + """ + + @pytest.mark.parametrize( + ("env", "host", "port", "want"), + [ + ( + None, + None, + None, + { + "host": "127.0.0.1", + "port": 8500, + }, + ), + ( + "127.0.0.1:443", + None, + None, + { + "host": "127.0.0.1", + "port": 443, + }, + ), + ( + None, + "consul.domain.tld", + None, + { + "host": "consul.domain.tld", + "port": 8500, + }, + ), + ( + "consul.domain.tld:443", + "127.0.0.1", + None, + { + "host": "127.0.0.1", + "port": 8500, + }, + ), + ( + "consul.domain.tld:443", + "127.0.0.1", + 8080, + { + "host": "127.0.0.1", + "port": 8080, + }, + ), + ( + "bad", + "127.0.0.1", + 8080, + { + "host": "127.0.0.1", + "port": 8080, + }, + ), + ], + ) + def test_base_init(self, monkeypatch, env, host, port, want) -> None: + if env: + monkeypatch.setenv("CONSUL_HTTP_ADDR", env) + else: + try: + monkeypatch.delenv("CONSUL_HTTP_ADDR") + except KeyError: + pass + + c = Consul(host=host, port=port) + assert c.http.host == want["host"] + assert c.http.port == want["port"] + + class TestIndex: """ Tests read requests that should support blocking on an index From 69a1caa93cb00ea193c7b5e339124465e4a43132 Mon Sep 17 00:00:00 2001 From: Emma May Date: Fri, 15 Nov 2024 17:10:00 -0800 Subject: [PATCH 2/3] honor the scheme and verify arguments as well --- consul/base.py | 22 +++++++++---- tests/test_base.py | 80 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 9 deletions(-) diff --git a/consul/base.py b/consul/base.py index 0bbb163..0c9357d 100644 --- a/consul/base.py +++ b/consul/base.py @@ -79,10 +79,10 @@ def __init__( host: str | None = None, port: int | None = None, token: str | None = None, - scheme: str = "http", + scheme: str | None = None, consistency: str = "default", dc=None, - verify: bool = True, + verify: bool | None = None, cert=None, ) -> None: """ @@ -118,11 +118,19 @@ def __init__( if not port: port = 8500 - use_ssl = os.getenv("CONSUL_HTTP_SSL") - if use_ssl is not None: - scheme = "https" if use_ssl == "true" else "http" - if os.getenv("CONSUL_HTTP_SSL_VERIFY") is not None: - verify = os.getenv("CONSUL_HTTP_SSL_VERIFY") == "true" + if scheme is None: + use_ssl = os.getenv("CONSUL_HTTP_SSL") + if use_ssl: + scheme = "https" if use_ssl.lower() == "true" else "http" + else: + scheme = "http" + + if verify is None: + ssl_verify = os.getenv("CONSUL_HTTP_SSL_VERIFY") + if ssl_verify: + verify = ssl_verify.lower() == "true" + else: + verify = True self.http = self.http_connect(host, port, scheme, verify, cert) self.token = os.getenv("CONSUL_HTTP_TOKEN", token) diff --git a/tests/test_base.py b/tests/test_base.py index 571b3a6..4a43d26 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -17,6 +17,8 @@ def __init__( ) -> None: self.host = host self.port = int(port) + self.scheme = scheme + self.verify = verify def get(self, callback, path, params=None, headers=None): # pylint: disable=unused-argument return Request("get", path, params, headers, None) @@ -30,7 +32,7 @@ def delete(self, callback, path, params=None, headers=None): # pylint: disable= class Consul(consul.base.Consul): def http_connect(self, host: str, port: int, scheme, verify: bool = True, cert=None): - return HTTPClient(host, port, scheme, verify=verify, cert=None) + return HTTPClient(host=host, port=port, scheme=scheme, verify=verify, cert=None) def _should_support(c: Consul) -> tuple[Callable[..., Any], ...]: @@ -135,7 +137,7 @@ class TestBaseInit: ), ], ) - def test_base_init(self, monkeypatch, env, host, port, want) -> None: + def test_base_init_addr(self, monkeypatch, env, host, port, want) -> None: if env: monkeypatch.setenv("CONSUL_HTTP_ADDR", env) else: @@ -148,6 +150,80 @@ def test_base_init(self, monkeypatch, env, host, port, want) -> None: assert c.http.host == want["host"] assert c.http.port == want["port"] + @pytest.mark.parametrize( + ("env", "scheme", "want"), + [ + ( + "true", + None, + "https" + ), + ( + "false", + None, + "http" + ), + ( + None, + "https", + "https" + ), + ( + None, + "http", + "http" + ), + ( + "http", + "https", + "https" + ), + ], + ) + def test_base_init_scheme(self, monkeypatch, env, scheme, want) -> None: + if env: + monkeypatch.setenv("CONSUL_HTTP_SSL", env) + else: + try: + monkeypatch.delenv("CONSUL_HTTP_SSL") + except KeyError: + pass + + c = Consul(scheme=scheme) + assert c.http.scheme == want + + @pytest.mark.parametrize( + ("env", "verify", "want"), + [ + ( + "true", + None, + True + ), + ( + None, + True, + True + ), + ( + "false", + True, + True + ), + ], + ) + def test_base_init_verify(self, monkeypatch, env, verify, want) -> None: + if env: + monkeypatch.setenv("CONSUL_HTTP_SSL_VERIFY", env) + else: + try: + monkeypatch.delenv("CONSUL_HTTP_SSL_VERIFY") + except KeyError: + pass + + c = Consul(verify=verify) + assert c.http.verify == want + class TestIndex: """ From 2186512b7cd16a010b1a4af93760afbdd7e5c1ae Mon Sep 17 00:00:00 2001 From: Emma May Date: Mon, 18 Nov 2024 09:40:13 -0800 Subject: [PATCH 3/3] fix lint --- consul/base.py | 10 ++------ tests/test_base.py | 64 ++++++++++------------------------------------ 2 files changed, 16 insertions(+), 58 deletions(-) diff --git a/consul/base.py b/consul/base.py index 0c9357d..4939e85 100644 --- a/consul/base.py +++ b/consul/base.py @@ -120,17 +120,11 @@ def __init__( if scheme is None: use_ssl = os.getenv("CONSUL_HTTP_SSL") - if use_ssl: - scheme = "https" if use_ssl.lower() == "true" else "http" - else: - scheme = "http" + scheme = ("https" if use_ssl.lower() == "true" else "http") if use_ssl else "http" if verify is None: ssl_verify = os.getenv("CONSUL_HTTP_SSL_VERIFY") - if ssl_verify: - verify = ssl_verify.lower() == "true" - else: - verify = True + verify = ssl_verify.lower() == "true" if ssl_verify else True self.http = self.http_connect(host, port, scheme, verify, cert) self.token = os.getenv("CONSUL_HTTP_TOKEN", token) diff --git a/tests/test_base.py b/tests/test_base.py index 4a43d26..714f668 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -1,6 +1,7 @@ from __future__ import annotations import collections +import contextlib import json from typing import Any, Callable, Optional @@ -16,9 +17,10 @@ def __init__( self, host: Optional[str] = None, port: Optional[int] = None, scheme=None, verify: bool = True, cert=None ) -> None: self.host = host - self.port = int(port) + self.port = port if port else None self.scheme = scheme self.verify = verify + self.cert = cert def get(self, callback, path, params=None, headers=None): # pylint: disable=unused-argument return Request("get", path, params, headers, None) @@ -141,10 +143,8 @@ def test_base_init_addr(self, monkeypatch, env, host, port, want) -> None: if env: monkeypatch.setenv("CONSUL_HTTP_ADDR", env) else: - try: + with contextlib.suppress(KeyError): monkeypatch.delenv("CONSUL_HTTP_ADDR") - except KeyError: - pass c = Consul(host=host, port=port) assert c.http.host == want["host"] @@ -153,41 +153,19 @@ def test_base_init_addr(self, monkeypatch, env, host, port, want) -> None: @pytest.mark.parametrize( ("env", "scheme", "want"), [ - ( - "true", - None, - "https" - ), - ( - "false", - None, - "http" - ), - ( - None, - "https", - "https" - ), - ( - None, - "http", - "http" - ), - ( - "http", - "https", - "https" - ), + ("true", None, "https"), + ("false", None, "http"), + (None, "https", "https"), + (None, "http", "http"), + ("http", "https", "https"), ], ) def test_base_init_scheme(self, monkeypatch, env, scheme, want) -> None: if env: monkeypatch.setenv("CONSUL_HTTP_SSL", env) else: - try: + with contextlib.suppress(KeyError): monkeypatch.delenv("CONSUL_HTTP_SSL") - except KeyError: - pass c = Consul(scheme=scheme) assert c.http.scheme == want @@ -195,31 +173,17 @@ def test_base_init_scheme(self, monkeypatch, env, scheme, want) -> None: @pytest.mark.parametrize( ("env", "verify", "want"), [ - ( - "true", - None, - True - ), - ( - None, - True, - True - ), - ( - "false", - True, - True - ), + ("true", None, True), + (None, True, True), + ("false", True, True), ], ) def test_base_init_verify(self, monkeypatch, env, verify, want) -> None: if env: monkeypatch.setenv("CONSUL_HTTP_SSL_VERIFY", env) else: - try: + with contextlib.suppress(KeyError): monkeypatch.delenv("CONSUL_HTTP_SSL_VERIFY") - except KeyError: - pass c = Consul(verify=verify) assert c.http.verify == want