Cover etcd3 in parse_dcs function (#2639)

Previous to this commit the `parse_dcs` function would fail with a `PatroniCtlException` if the user ever passed an `etcd3` URL through `--dcs-url` command-line option.

As a consequence, the only way of using `etcd3` in `patronictl` was by using a configuration file passed through `-c` command-line option.

This commit fixes that issue and allows `etcd3` to be used in `--dcs-url`.

References: PAT-91
Close #2638
This commit is contained in:
Israel
2023-04-12 09:02:32 +02:00
committed by GitHub
parent e30d96a468
commit 6ffc73946a
2 changed files with 37 additions and 2 deletions
+36 -2
View File
@@ -21,6 +21,8 @@ import tempfile
import time
import yaml
from typing import Any, Dict, Union
from click import ClickException
from collections import defaultdict
from contextlib import contextmanager
@@ -44,7 +46,8 @@ CONFIG_FILE_PATH = os.path.join(CONFIG_DIR_PATH, 'patronictl.yaml')
DCS_DEFAULTS = {'zookeeper': {'port': 2181, 'template': "zookeeper:\n hosts: ['{host}:{port}']"},
'exhibitor': {'port': 8181, 'template': "exhibitor:\n hosts: [{host}]\n port: {port}"},
'consul': {'port': 8500, 'template': "consul:\n host: '{host}:{port}'"},
'etcd': {'port': 2379, 'template': "etcd:\n host: '{host}:{port}'"}}
'etcd': {'port': 2379, 'template': "etcd:\n host: '{host}:{port}'"},
'etcd3': {'port': 2379, 'template': "etcd3:\n host: '{host}:{port}'"}}
class PatroniCtlException(ClickException):
@@ -90,7 +93,38 @@ class PatronictlPrettyTable(PrettyTable):
_hrule = property(_get_hline, _set_hline)
def parse_dcs(dcs):
def parse_dcs(dcs: str) -> Union[Dict[str, Any], None]:
"""Parse a DCS URL.
:param dcs: the DCS URL in the format ``DCS://HOST:PORT``. ``DCS`` can be one among
* ``consul``
* ``etcd``
* ``etcd3``
* ``exhibitor``
* ``zookeeper``
If ``DCS`` is not specified, it assumes ``etcd`` by default. If ``HOST`` is not specified, it assumes
``localhost`` by default. If ``PORT`` is not specified, it assumes the default port of the given ``DCS``.
:returns: ``None`` if *dcs* is ``None``, otherwise a dictionary. The dictionary represents *dcs* as if it were
parsed from the Patroni configuration file.
:raises PatroniCtlException: if the DCS name in *dcs* is not valid.
:Example:
>>> parse_dcs('')
{'etcd': {'host': 'localhost:2379'}}
>>> parse_dcs('etcd://:2399')
{'etcd': {'host': 'localhost:2399'}}
>>> parse_dcs('etcd://test')
{'etcd': {'host': 'test:2379'}}
>>> parse_dcs('etcd3://random.com:2399')
{'etcd3': {'host': 'random.com:2399'}}
"""
if dcs is None:
return None
elif '//' not in dcs:
+1
View File
@@ -76,6 +76,7 @@ class TestCtl(unittest.TestCase):
assert parse_dcs('zookeeper://localhost') == {'zookeeper': {'hosts': ['localhost:2181']}}
assert parse_dcs('exhibitor://dummy') == {'exhibitor': {'hosts': ['dummy'], 'port': 8181}}
assert parse_dcs('consul://localhost') == {'consul': {'host': 'localhost:8500'}}
assert parse_dcs('etcd3://random.com:2399') == {'etcd3': {'host': 'random.com:2399'}}
self.assertRaises(PatroniCtlException, parse_dcs, 'invalid://test')
def test_output_members(self):