Add capability of specifying namespace through --dcs argument (#2926)

This commit changes the `patronictl` application in such a way its
`--dcs` argument is now able to receive a namespace.

Previous to this commit this was the format of that argument's value:
`DCS://HOST:PORT`.

From now on it accepts this format: `DCS://HORT:PORT/NAMESPACE`. As all
previous parts of the argument value, `NAMESPACE` is optional, and if
not given `patronictl` will fallback to the value from the configuration
file, if any, or to `service`.

This change is specifically useful when you are running a cluster in a
custom namespace, and from a machine where you don't have a configuration
file for Patroni or `patronictl`. It can avoid that you would have to
create a configuration file only with `namespace` filed in that case.

Issue reported by: Shaun Thomas <[email protected]>

Signed-off-by: Israel Barth Rubio <[email protected]>
This commit is contained in:
Israel
2023-10-24 12:09:44 +02:00
committed by GitHub
parent d471f1156d
commit 65030c56ee
2 changed files with 19 additions and 8 deletions
+2 -2
View File
@@ -52,9 +52,9 @@ Before jumping into each of the sub-commands of ``patronictl``, be aware that ``
``-d`` / ``--dcs-url`` / ``--dcs``
Provide a connection string to the DCS used by Patroni.
This argument can be used either to override the DCS settings from the ``patronictl`` configuration, or to define it if it's missing in the configuration.
This argument can be used either to override the DCS and ``namespace`` settings from the ``patronictl`` configuration, or to define it if it's missing in the configuration.
The value should be in the format ``DCS://HOST:PORT``, e.g. ``etcd3://localhost:2379`` to connect to etcd v3 running on ``localhost``.
The value should be in the format ``DCS://HOST:PORT/NAMESPACE``, e.g. ``etcd3://localhost:2379/service`` to connect to etcd v3 running on ``localhost`` with Patroni cluster stored under ``service`` namespace. Any part that is missing in the argument value will be replaced with the value present in the configuration or with its default.
``-k`` / ``--insecure``
Flag to bypass validation of REST API server SSL certificate.
+17 -6
View File
@@ -165,7 +165,7 @@ class PatronictlPrettyTable(PrettyTable):
def parse_dcs(dcs: Optional[str]) -> Optional[Dict[str, Any]]:
"""Parse a DCS URL.
:param dcs: the DCS URL in the format ``DCS://HOST:PORT``. ``DCS`` can be one among:
:param dcs: the DCS URL in the format ``DCS://HOST:PORT/NAMESPACE``. ``DCS`` can be one among:
* ``consul``
* ``etcd``
@@ -174,10 +174,12 @@ def parse_dcs(dcs: Optional[str]) -> Optional[Dict[str, Any]]:
* ``zookeeper``
If ``DCS`` is not specified, assume ``etcd`` by default. If ``HOST`` is not specified, assume ``localhost`` by
default. If ``PORT`` is not specified, assume the default port of the given ``DCS``.
default. If ``PORT`` is not specified, assume the default port of the given ``DCS``. If ``NAMESPACE`` is not
specified, use whatever is in config.
:returns: ``None`` if *dcs* is ``None``, otherwise a dictionary. The dictionary represents *dcs* as if it were
parsed from the Patroni configuration file.
parsed from the Patroni configuration file. Additionally, if a namespace is specified in *dcs*, return a
``namespace`` key with the parsed value.
:raises:
:class:`PatroniCtlException`: if the DCS name in *dcs* is not valid.
@@ -195,6 +197,9 @@ def parse_dcs(dcs: Optional[str]) -> Optional[Dict[str, Any]]:
>>> parse_dcs('etcd3://random.com:2399')
{'etcd3': {'host': 'random.com:2399'}}
>>> parse_dcs('etcd3://random.com:2399/customnamespace')
{'etcd3': {'host': 'random.com:2399'}, 'namespace': '/customnamespace'}
"""
if dcs is None:
return None
@@ -211,15 +216,21 @@ def parse_dcs(dcs: Optional[str]) -> Optional[Dict[str, Any]]:
raise PatroniCtlException('Unknown dcs scheme: {}'.format(scheme))
default = DCS_DEFAULTS[scheme]
return yaml.safe_load(default['template'].format(host=parsed.hostname or 'localhost', port=port or default['port']))
ret = yaml.safe_load(default['template'].format(host=parsed.hostname or 'localhost', port=port or default['port']))
if parsed.path and parsed.path.strip() != '/':
ret['namespace'] = parsed.path.strip()
return ret
def load_config(path: str, dcs_url: Optional[str]) -> Dict[str, Any]:
"""Load configuration file from *path* and optionally override its DCS configuration with *dcs_url*.
:param path: path to the configuration file.
:param dcs_url: the DCS URL in the format ``DCS://HOST:PORT``, e.g. ``etcd3://random.com:2399``. If given override
whatever DCS is set in the configuration file.
:param dcs_url: the DCS URL in the format ``DCS://HOST:PORT/NAMESPACE``, e.g. ``etcd3://random.com:2399/service``.
If given, override whatever DCS and ``namespace`` that are set in the configuration file. See :func:`parse_dcs`
for more information.
:returns: a dictionary representing the configuration.