pglift-cli 2.1.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/PKG-INFO +2 -2
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/pyproject.toml +4 -1
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/database.py +5 -3
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/instance.py +8 -5
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/model.py +2 -22
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/pghba.py +7 -4
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/util.py +22 -14
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-cli-walkthrough.t +45 -23
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-help.t +65 -36
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/conftest.py +1 -1
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/test_cli.py +8 -1
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/test_main.py +2 -2
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/test_model.py +1 -11
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/test_util.py +2 -2
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/.gitignore +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/README.md +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/hatch.toml +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/pytest.ini +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/__init__.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/__main__.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/_settings.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/_site.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/base.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/console.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/hookspecs.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/main.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/patroni.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/pgbackrest/__init__.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/pgbackrest/repo_path.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/pgconf.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/pm.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/postgres.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/prometheus.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/py.typed +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/src/pglift_cli/role.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/.gitignore +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-base.t +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-demote.t +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-port-validation.t +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-prometheus.t +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-standby-pgbackrest.t +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-transactions.t +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/expect/test-upgrade.t +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/__init__.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/test__site.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/test_audit.py +0 -0
- {pglift_cli-2.1.0 → pglift_cli-2.3.0}/tests/unit/test_pm.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pglift_cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Command-line interface for pglift
|
|
5
5
|
Project-URL: Documentation, https://pglift.readthedocs.io/
|
|
6
6
|
Project-URL: Source, https://gitlab.com/dalibo/pglift/
|
|
@@ -23,7 +23,7 @@ Classifier: Topic :: Database
|
|
|
23
23
|
Classifier: Topic :: System :: Systems Administration
|
|
24
24
|
Classifier: Typing :: Typed
|
|
25
25
|
Requires-Python: <4,>=3.10
|
|
26
|
-
Requires-Dist: click
|
|
26
|
+
Requires-Dist: click>=8.2.0
|
|
27
27
|
Requires-Dist: filelock!=3.12.1,>=3.9.0
|
|
28
28
|
Requires-Dist: pluggy
|
|
29
29
|
Requires-Dist: psycopg>=3.1
|
|
@@ -39,7 +39,7 @@ dynamic = ["version"]
|
|
|
39
39
|
|
|
40
40
|
dependencies = [
|
|
41
41
|
"PyYAML >= 6.0.1",
|
|
42
|
-
"click >= 8.
|
|
42
|
+
"click >= 8.2.0",
|
|
43
43
|
"filelock >= 3.9.0, != 3.12.1",
|
|
44
44
|
"pluggy",
|
|
45
45
|
"psycopg >= 3.1",
|
|
@@ -75,3 +75,6 @@ Tracker = "https://gitlab.com/dalibo/pglift/-/issues/"
|
|
|
75
75
|
"pglift_cli.pgbackrest" = "pglift_cli.pgbackrest"
|
|
76
76
|
"pglift_cli.pgbackrest.repo_path" = "pglift_cli.pgbackrest.repo_path"
|
|
77
77
|
"pglift_cli.prometheus" = "pglift_cli.prometheus"
|
|
78
|
+
|
|
79
|
+
[project.scripts]
|
|
80
|
+
pglift = "pglift_cli.main:cli"
|
|
@@ -325,9 +325,10 @@ async def dumps(
|
|
|
325
325
|
@click.argument("dump_id")
|
|
326
326
|
@click.argument("targetdbname", required=False)
|
|
327
327
|
@pass_postgresql_instance
|
|
328
|
+
@dry_run_option
|
|
328
329
|
@async_command
|
|
329
330
|
async def restore(
|
|
330
|
-
instance: PostgreSQLInstance, dump_id: str, targetdbname: str | None
|
|
331
|
+
instance: PostgreSQLInstance, dump_id: str, targetdbname: str | None, dry_run: bool
|
|
331
332
|
) -> None:
|
|
332
333
|
"""Restore a database dump
|
|
333
334
|
|
|
@@ -340,5 +341,6 @@ async def restore(
|
|
|
340
341
|
name that appears in the dump. In this case, the restore command will
|
|
341
342
|
create the database so it needs to be dropped before running the command.
|
|
342
343
|
"""
|
|
343
|
-
|
|
344
|
-
|
|
344
|
+
with system_configure(dry_run=dry_run):
|
|
345
|
+
async with postgresql.running(instance):
|
|
346
|
+
await databases.restore(instance, dump_id, targetdbname)
|
|
@@ -25,8 +25,11 @@ from pglift import (
|
|
|
25
25
|
task,
|
|
26
26
|
)
|
|
27
27
|
from pglift.models import Instance, PostgreSQLInstance, interface
|
|
28
|
-
from pglift.settings import
|
|
29
|
-
|
|
28
|
+
from pglift.settings import (
|
|
29
|
+
POSTGRESQL_VERSIONS,
|
|
30
|
+
PostgreSQLVersion,
|
|
31
|
+
default_postgresql_version,
|
|
32
|
+
)
|
|
30
33
|
from pglift.types import Operation, Status, validation_context
|
|
31
34
|
|
|
32
35
|
from . import _site, model
|
|
@@ -279,7 +282,7 @@ async def get(instance: Instance, output_format: OutputFormat | None) -> None:
|
|
|
279
282
|
@cli.command("list")
|
|
280
283
|
@click.option(
|
|
281
284
|
"--version",
|
|
282
|
-
type=click.Choice(
|
|
285
|
+
type=click.Choice(POSTGRESQL_VERSIONS),
|
|
283
286
|
help="Only list instances of specified version.",
|
|
284
287
|
)
|
|
285
288
|
@output_format_option
|
|
@@ -403,7 +406,7 @@ async def restart(
|
|
|
403
406
|
@instance_identifier(nargs=1, required=True)
|
|
404
407
|
@click.argument("command", required=True, nargs=-1, type=click.UNPROCESSED)
|
|
405
408
|
def exec(instance: Instance, command: tuple[str, ...]) -> None:
|
|
406
|
-
"""Execute
|
|
409
|
+
"""Execute COMMAND in the libpq environment for PostgreSQL INSTANCE.
|
|
407
410
|
|
|
408
411
|
COMMAND parts may need to be prefixed with -- to separate them from
|
|
409
412
|
options when confusion arises.
|
|
@@ -526,7 +529,7 @@ async def list_privileges(
|
|
|
526
529
|
@click.option(
|
|
527
530
|
"--version",
|
|
528
531
|
"newversion",
|
|
529
|
-
type=click.Choice(
|
|
532
|
+
type=click.Choice(POSTGRESQL_VERSIONS),
|
|
530
533
|
help="PostgreSQL version of the new instance (default to site-configured value).",
|
|
531
534
|
)
|
|
532
535
|
@click.option(
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
-
import enum
|
|
8
7
|
import functools
|
|
9
8
|
import inspect
|
|
10
9
|
import typing
|
|
@@ -24,7 +23,6 @@ from pglift.models.helpers import is_optional, optional_type
|
|
|
24
23
|
from pglift.models.interface import PresenceState
|
|
25
24
|
from pglift.types import (
|
|
26
25
|
Operation,
|
|
27
|
-
StrEnum,
|
|
28
26
|
field_annotation,
|
|
29
27
|
validation_context,
|
|
30
28
|
)
|
|
@@ -106,7 +104,7 @@ def as_parameters(model_type: ModelType, operation: Operation) -> ClickDecorator
|
|
|
106
104
|
)
|
|
107
105
|
|
|
108
106
|
@functools.wraps(f)
|
|
109
|
-
def callback(**kwargs: Any) -> Any:
|
|
107
|
+
def callback(**kwargs: Any) -> Any:
|
|
110
108
|
args = params_to_modelargs(kwargs)
|
|
111
109
|
with (
|
|
112
110
|
catch_validationerror(*paramspecs),
|
|
@@ -358,14 +356,6 @@ def _paramspecs_from_model(
|
|
|
358
356
|
choices = config.choices
|
|
359
357
|
attrs["type"] = click.Choice(choices)
|
|
360
358
|
|
|
361
|
-
elif lenient_issubclass(ftype, enum.Enum):
|
|
362
|
-
if config:
|
|
363
|
-
assert isinstance(config, cli.Choices)
|
|
364
|
-
choices = config.choices
|
|
365
|
-
else:
|
|
366
|
-
choices = choices_from_enum(ftype)
|
|
367
|
-
attrs["type"] = click.Choice(choices)
|
|
368
|
-
|
|
369
359
|
elif lenient_issubclass(origin_type or ftype, list):
|
|
370
360
|
attrs["multiple"] = True
|
|
371
361
|
try:
|
|
@@ -373,10 +363,7 @@ def _paramspecs_from_model(
|
|
|
373
363
|
except ValueError:
|
|
374
364
|
pass
|
|
375
365
|
else:
|
|
376
|
-
|
|
377
|
-
attrs["type"] = click.Choice(choices_from_enum(itemtype))
|
|
378
|
-
else:
|
|
379
|
-
attrs["metavar"] = metavar
|
|
366
|
+
attrs["metavar"] = metavar
|
|
380
367
|
if not _parents and operation == "update" and is_editable(itemtype):
|
|
381
368
|
# List fields for the "update" operation are mapped to
|
|
382
369
|
# --add-<fname>, --remove-<fname> options; built and yield
|
|
@@ -460,13 +447,6 @@ def _paramspecs_from_model(
|
|
|
460
447
|
)
|
|
461
448
|
|
|
462
449
|
|
|
463
|
-
def choices_from_enum(e: type[enum.Enum]) -> list[Any]:
|
|
464
|
-
if lenient_issubclass(e, StrEnum):
|
|
465
|
-
return list(e)
|
|
466
|
-
else:
|
|
467
|
-
return [v.value for v in e]
|
|
468
|
-
|
|
469
|
-
|
|
470
450
|
@contextmanager
|
|
471
451
|
def catch_validationerror(*paramspec: ParamSpec) -> Iterator[None]:
|
|
472
452
|
try:
|
|
@@ -16,6 +16,7 @@ from .console import console
|
|
|
16
16
|
from .util import (
|
|
17
17
|
Group,
|
|
18
18
|
Obj,
|
|
19
|
+
async_command,
|
|
19
20
|
audit,
|
|
20
21
|
diff_options,
|
|
21
22
|
dry_run_option,
|
|
@@ -38,7 +39,8 @@ def cli(**kwargs: Any) -> None:
|
|
|
38
39
|
@diff_options["unified"]
|
|
39
40
|
@diff_options["ansible"]
|
|
40
41
|
@click.pass_obj
|
|
41
|
-
|
|
42
|
+
@async_command
|
|
43
|
+
async def add(
|
|
42
44
|
obj: Obj,
|
|
43
45
|
instance: PostgreSQLInstance,
|
|
44
46
|
hbarecord: interface.HbaRecord,
|
|
@@ -56,7 +58,7 @@ def add(
|
|
|
56
58
|
system_configure(dry_run=dry_run),
|
|
57
59
|
manager.from_instance(instance),
|
|
58
60
|
):
|
|
59
|
-
hba.add(instance, hbarecord)
|
|
61
|
+
await hba.add(instance, hbarecord)
|
|
60
62
|
if (diffvalue := diff.get()) is not None:
|
|
61
63
|
for diffitem in diffvalue:
|
|
62
64
|
console.print(diffitem)
|
|
@@ -69,7 +71,8 @@ def add(
|
|
|
69
71
|
@diff_options["unified"]
|
|
70
72
|
@diff_options["ansible"]
|
|
71
73
|
@click.pass_obj
|
|
72
|
-
|
|
74
|
+
@async_command
|
|
75
|
+
async def remove(
|
|
73
76
|
obj: Obj,
|
|
74
77
|
instance: PostgreSQLInstance,
|
|
75
78
|
hbarecord: interface.HbaRecord,
|
|
@@ -87,7 +90,7 @@ def remove(
|
|
|
87
90
|
system_configure(dry_run=dry_run),
|
|
88
91
|
manager.from_instance(instance),
|
|
89
92
|
):
|
|
90
|
-
hba.remove(instance, hbarecord)
|
|
93
|
+
await hba.remove(instance, hbarecord)
|
|
91
94
|
if (diffvalue := diff.get()) is not None:
|
|
92
95
|
for diffitem in diffvalue:
|
|
93
96
|
console.print(diffitem)
|
|
@@ -37,7 +37,7 @@ from rich.table import Table
|
|
|
37
37
|
|
|
38
38
|
from pglift import exceptions, instances, system
|
|
39
39
|
from pglift.models import Instance, PostgreSQLInstance, helpers, interface
|
|
40
|
-
from pglift.settings import Settings
|
|
40
|
+
from pglift.settings import PostgreSQLVersion, Settings
|
|
41
41
|
from pglift.system import install
|
|
42
42
|
from pglift.types import ByteSizeType
|
|
43
43
|
|
|
@@ -116,7 +116,6 @@ def print_table_for(
|
|
|
116
116
|
**kwargs: Any,
|
|
117
117
|
) -> None:
|
|
118
118
|
"""Render a list of items as a table."""
|
|
119
|
-
table = None
|
|
120
119
|
headers: list[str] = []
|
|
121
120
|
rows = []
|
|
122
121
|
for item in items:
|
|
@@ -139,7 +138,13 @@ def print_table_for(
|
|
|
139
138
|
rows.append(row)
|
|
140
139
|
if not rows:
|
|
141
140
|
return
|
|
142
|
-
table = Table(
|
|
141
|
+
table = Table(title=title, **kwargs)
|
|
142
|
+
# https://github.com/Textualize/rich/issues/3761
|
|
143
|
+
overflow: Literal["ellipsis", "fold"] = (
|
|
144
|
+
"fold" if console.options.ascii_only else "ellipsis"
|
|
145
|
+
)
|
|
146
|
+
for header in headers:
|
|
147
|
+
table.add_column(header, overflow=overflow)
|
|
143
148
|
for row in rows:
|
|
144
149
|
table.add_row(*row)
|
|
145
150
|
console.print(table)
|
|
@@ -219,13 +224,13 @@ def pass_postgresql_instance(f: Callable[P, None]) -> Callable[P, None]:
|
|
|
219
224
|
|
|
220
225
|
|
|
221
226
|
def get_postgresql_instance(
|
|
222
|
-
name: str, version:
|
|
227
|
+
name: str, version: PostgreSQLVersion | None, settings: Settings
|
|
223
228
|
) -> PostgreSQLInstance:
|
|
224
229
|
"""Return a PostgreSQLInstance from name/version, possibly guessing version if unspecified."""
|
|
225
230
|
if version is None:
|
|
226
231
|
found = None
|
|
227
232
|
for v in settings.postgresql.versions:
|
|
228
|
-
version = v.version
|
|
233
|
+
version = v.version
|
|
229
234
|
try:
|
|
230
235
|
instance = PostgreSQLInstance.system_lookup(name, version, settings)
|
|
231
236
|
except exceptions.InstanceNotFound:
|
|
@@ -249,19 +254,21 @@ def get_postgresql_instance(
|
|
|
249
254
|
raise click.BadParameter(str(e)) from None
|
|
250
255
|
|
|
251
256
|
|
|
252
|
-
def get_instance(
|
|
257
|
+
def get_instance(
|
|
258
|
+
name: str, version: PostgreSQLVersion | None, settings: Settings
|
|
259
|
+
) -> Instance:
|
|
253
260
|
"""Return an Instance from name/version, possibly guessing version if unspecified."""
|
|
254
261
|
pg_instance = get_postgresql_instance(name, version, settings)
|
|
255
262
|
return Instance.from_postgresql(pg_instance)
|
|
256
263
|
|
|
257
264
|
|
|
258
|
-
def nameversion_from_id(instance_id: str) -> tuple[str,
|
|
265
|
+
def nameversion_from_id(instance_id: str) -> tuple[str, PostgreSQLVersion | None]:
|
|
259
266
|
version = None
|
|
260
267
|
try:
|
|
261
268
|
version, name = instance_id.split("/", 1)
|
|
262
269
|
except ValueError:
|
|
263
270
|
name = instance_id
|
|
264
|
-
return name, version
|
|
271
|
+
return name, typing.cast(PostgreSQLVersion, version)
|
|
265
272
|
|
|
266
273
|
|
|
267
274
|
def postgresql_instance_lookup(
|
|
@@ -732,12 +739,13 @@ class Group(click.Group):
|
|
|
732
739
|
super().add_command(command, name)
|
|
733
740
|
|
|
734
741
|
def invoke(self, ctx: click.Context) -> Any:
|
|
735
|
-
if
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
742
|
+
if set(ctx.help_option_names) - set(ctx.args):
|
|
743
|
+
if is_root():
|
|
744
|
+
raise click.ClickException("pglift cannot be used as root")
|
|
745
|
+
if not install.check(_site.SETTINGS):
|
|
746
|
+
raise click.ClickException(
|
|
747
|
+
"broken installation; did you run 'site-configure install'?",
|
|
748
|
+
)
|
|
741
749
|
return super().invoke(ctx)
|
|
742
750
|
|
|
743
751
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Site settings:
|
|
6
6
|
|
|
7
|
+
$ export PYTHONIOENCODING=ascii
|
|
7
8
|
$ cat > $TMPDIR/passwords.json << 'EOF'
|
|
8
9
|
> {
|
|
9
10
|
> "main": {
|
|
@@ -249,8 +250,8 @@ Stop, alter, (re)start an instance:
|
|
|
249
250
|
--- $TMPDIR/etc/prometheus/postgres_exporter-1*-main.conf (glob)
|
|
250
251
|
+++ $TMPDIR/etc/prometheus/postgres_exporter-1*-main.conf (glob)
|
|
251
252
|
@@ -1,2 +1,2 @@
|
|
252
|
-
DATA_SOURCE_NAME=postgresql://prometheus@:*/postgres?host
|
|
253
|
-
|
|
253
|
+
DATA_SOURCE_NAME=postgresql://prometheus@:*/postgres?host=* (glob)
|
|
254
|
+
*%2Fpostgresql&sslmode=disable (glob)
|
|
254
255
|
-POSTGRES_EXPORTER_OPTS='--web.listen-address :\d+ --log.level info' (re)
|
|
255
256
|
\+POSTGRES_EXPORTER_OPTS='--web.listen-address :\d+ --log.level info' (re)
|
|
256
257
|
--- /dev/null
|
|
@@ -293,7 +294,7 @@ Stop, alter, (re)start an instance:
|
|
|
293
294
|
INFO reloading PostgreSQL configuration for 1\d\/main (re)
|
|
294
295
|
INFO starting Prometheus postgres_exporter 1\d-main (re)
|
|
295
296
|
INFO creating role 'arole'
|
|
296
|
-
INFO
|
|
297
|
+
INFO HBA configuration updated
|
|
297
298
|
INFO reloading PostgreSQL configuration for 1\d\/main (re)
|
|
298
299
|
--- $TMPDIR/srv/pgsql/1*/main/data/postgresql.conf (glob)
|
|
299
300
|
+++ $TMPDIR/srv/pgsql/1*/main/data/postgresql.conf (glob)
|
|
@@ -390,7 +391,7 @@ PostgreSQL configuration
|
|
|
390
391
|
port: \d+ -> 1234 (re)
|
|
391
392
|
DRY RUN: no changes made
|
|
392
393
|
|
|
393
|
-
|
|
394
|
+
HBA configuration management:
|
|
394
395
|
|
|
395
396
|
$ pglift pghba add --user bob --method trust
|
|
396
397
|
INFO entry added to HBA configuration
|
|
@@ -500,8 +501,14 @@ Add and manipulate roles:
|
|
|
500
501
|
\*:\d+:\*:dba:qwerty (re)
|
|
501
502
|
|
|
502
503
|
$ pglift role get dba
|
|
503
|
-
|
|
504
|
-
|
|
504
|
+
conne
|
|
505
|
+
has_p repl ction vali membe
|
|
506
|
+
asswo inher super creat creat icat _limi d_un rship pgpa
|
|
507
|
+
name rd it login user edb erole ion t til s ss
|
|
508
|
+
dba True True True False False False Fals pg_re True
|
|
509
|
+
e ad_al
|
|
510
|
+
l_sta
|
|
511
|
+
ts
|
|
505
512
|
|
|
506
513
|
$ pglift role -i main create dba --dry-run
|
|
507
514
|
Error: role already exists
|
|
@@ -576,7 +583,7 @@ Add and manipulate roles:
|
|
|
576
583
|
> EOF
|
|
577
584
|
$ pglift role apply -f $TMPDIR/role.yaml --dry-run
|
|
578
585
|
INFO creating role 'test'
|
|
579
|
-
INFO
|
|
586
|
+
INFO HBA configuration updated
|
|
580
587
|
INFO reloading PostgreSQL configuration for 1\d\/main (re)
|
|
581
588
|
DRY RUN: no changes made
|
|
582
589
|
$ grep 'test' $TMPDIR/srv/pgsql/${version}/main/data/pg_hba.conf
|
|
@@ -586,7 +593,7 @@ Add and manipulate roles:
|
|
|
586
593
|
[1]
|
|
587
594
|
$ pglift role apply -f $TMPDIR/role.yaml --diff
|
|
588
595
|
INFO creating role 'test'
|
|
589
|
-
INFO
|
|
596
|
+
INFO HBA configuration updated
|
|
590
597
|
INFO reloading PostgreSQL configuration for 1\d\/main (re)
|
|
591
598
|
--- $TMPDIR/srv/pgsql/1*/main/data/pg_hba.conf (glob)
|
|
592
599
|
+++ $TMPDIR/srv/pgsql/1*/main/data/pg_hba.conf (glob)
|
|
@@ -822,11 +829,11 @@ Databases
|
|
|
822
829
|
INFO SELECT 1
|
|
823
830
|
Database
|
|
824
831
|
other
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
832
|
+
+--------+
|
|
833
|
+
| exists |
|
|
834
|
+
|--------|
|
|
835
|
+
| False |
|
|
836
|
+
+--------+
|
|
830
837
|
$ pglift database apply -f $TMPDIR/other.yaml -o json --diff
|
|
831
838
|
INFO altering 'other' database on instance 1\d\/main (re)
|
|
832
839
|
INFO creating extension 'pg_stat_statements' in database other
|
|
@@ -839,11 +846,11 @@ Databases
|
|
|
839
846
|
INFO SELECT 1
|
|
840
847
|
Database
|
|
841
848
|
other
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
849
|
+
+--------+
|
|
850
|
+
| exists |
|
|
851
|
+
|--------|
|
|
852
|
+
| True |
|
|
853
|
+
+--------+
|
|
847
854
|
$ cat > $TMPDIR/other.yaml <<EOF
|
|
848
855
|
> name: other
|
|
849
856
|
> state: absent
|
|
@@ -855,8 +862,11 @@ Databases
|
|
|
855
862
|
INFO dropping 'other' database
|
|
856
863
|
DRY RUN: no changes made
|
|
857
864
|
$ pglift database get other
|
|
858
|
-
|
|
859
|
-
|
|
865
|
+
setting extensio publica subscrip tablesp
|
|
866
|
+
name owner s schemas ns locale tions tions ace
|
|
867
|
+
other postgre public pg_stat_ C pg_defa
|
|
868
|
+
s statemen ult
|
|
869
|
+
ts
|
|
860
870
|
$ pglift database create other
|
|
861
871
|
Error: database already exists
|
|
862
872
|
[1]
|
|
@@ -1040,6 +1050,18 @@ Databases
|
|
|
1040
1050
|
$ pglift database drop myapp
|
|
1041
1051
|
INFO dropping 'myapp' database
|
|
1042
1052
|
|
|
1053
|
+
$ pglift database restore doesnt_exist_id --dry-run
|
|
1054
|
+
Error: dump 'doesnt_exist_id' not found
|
|
1055
|
+
[1]
|
|
1056
|
+
|
|
1057
|
+
$ pglift database restore doesnt_exist_id
|
|
1058
|
+
Error: dump 'doesnt_exist_id' not found
|
|
1059
|
+
[1]
|
|
1060
|
+
|
|
1061
|
+
$ pglift database restore $DUMP_ID --dry-run
|
|
1062
|
+
INFO restoring dump for 'myapp' on instance 1\d\/main (re)
|
|
1063
|
+
DRY RUN: no changes made
|
|
1064
|
+
|
|
1043
1065
|
$ pglift database restore $DUMP_ID
|
|
1044
1066
|
INFO restoring dump for 'myapp' on instance 1\d\/main (re)
|
|
1045
1067
|
|
|
@@ -1080,7 +1102,7 @@ Databases
|
|
|
1080
1102
|
|
|
1081
1103
|
$ pglift role drop test --dry-run
|
|
1082
1104
|
INFO dropping role 'test'
|
|
1083
|
-
INFO removing entries from
|
|
1105
|
+
INFO removing entries from HBA configuration
|
|
1084
1106
|
DRY RUN: no changes made
|
|
1085
1107
|
$ pglift role drop test
|
|
1086
1108
|
INFO dropping role 'test'
|
|
@@ -1095,11 +1117,11 @@ Databases
|
|
|
1095
1117
|
[2]
|
|
1096
1118
|
$ pglift role drop test --drop-owned --dry-run
|
|
1097
1119
|
INFO dropping role 'test'
|
|
1098
|
-
INFO removing entries from
|
|
1120
|
+
INFO removing entries from HBA configuration
|
|
1099
1121
|
DRY RUN: no changes made
|
|
1100
1122
|
$ pglift role drop test --drop-owned
|
|
1101
1123
|
INFO dropping role 'test'
|
|
1102
|
-
INFO removing entries from
|
|
1124
|
+
INFO removing entries from HBA configuration
|
|
1103
1125
|
|
|
1104
1126
|
Profiles
|
|
1105
1127
|
$ pglift role -i main create dba1 --password mySup3rS3cr3t1377 --login
|
|
@@ -6,53 +6,77 @@ Tests for --help options of all commands
|
|
|
6
6
|
|
|
7
7
|
Site settings
|
|
8
8
|
|
|
9
|
-
$ PATRONI_CMD=$(command -v patroni)
|
|
10
|
-
$ PATRONICTL=$(command -v patronictl)
|
|
11
|
-
$ POSTGRES_EXPORTER=$(command -v postgres_exporter || command -v prometheus-postgres-exporter)
|
|
12
9
|
$ export PGLIFT_CLI__LOG_FORMAT="%(levelname)-4s %(message)s"
|
|
13
10
|
$ export PGLIFT_CONFIG_DIR=$TMPDIR
|
|
14
11
|
$ export PGLIFT_PREFIX=$TMPDIR
|
|
15
12
|
$ export PGLIFT_RUN_PREFIX=$TMPDIR/run
|
|
16
|
-
|
|
17
|
-
$
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
>
|
|
23
|
-
|
|
24
|
-
$ export
|
|
13
|
+
|
|
14
|
+
$ bindir=$TMPDIR/$TESTFILE/bin
|
|
15
|
+
$ mkdir -p $bindir/pgsql/17/bin
|
|
16
|
+
$ touch $bindir/pgsql/17/bin/pg_ctl
|
|
17
|
+
$ chmod +x $bindir/pgsql/17/bin/pg_ctl
|
|
18
|
+
$ export PGLIFT_POSTGRESQL__BINDIR=$bindir/pgsql/{version}/bin \
|
|
19
|
+
> PGLIFT_POSTGRESQL__AUTH__PASSFILE="null" \
|
|
20
|
+
> PGLIFT_POSTGRESQL__REPLROLE="replication"
|
|
21
|
+
$ export PGLIFT_PATRONI__EXECPATH=$bindir/patroni \
|
|
22
|
+
> PGLIFT_PATRONI__CTLPATH=$bindir/patronictl \
|
|
23
|
+
> PGLIFT_PGBACKREST__EXECPATH=$bindir/pgbackrest \
|
|
24
|
+
> PGLIFT_PROMETHEUS__EXECPATH=$bindir/postgres_exporter
|
|
25
|
+
$ touch $PGLIFT_PATRONI__EXECPATH \
|
|
26
|
+
> $PGLIFT_PATRONI__CTLPATH \
|
|
27
|
+
> $PGLIFT_PGBACKREST__EXECPATH \
|
|
28
|
+
> $PGLIFT_PROMETHEUS__EXECPATH
|
|
29
|
+
$ export PGLIFT_PGBACKREST__REPOSITORY__MODE=path \
|
|
30
|
+
> PGLIFT_PGBACKREST__REPOSITORY__PATH=$TMPDIR/$TESTFILE/backups
|
|
31
|
+
$ mkdir $PGLIFT_PGBACKREST__REPOSITORY__PATH
|
|
25
32
|
$ export PGLIFT_POWA='{}'
|
|
26
|
-
|
|
33
|
+
|
|
27
34
|
$ pglift site-settings --no-defaults -o json \
|
|
28
|
-
> | jq '.pgbackrest, .prometheus, .prefix, .run_prefix'
|
|
35
|
+
> | jq '.postgresql, .pgbackrest, .prometheus, .prefix, .run_prefix'
|
|
29
36
|
{
|
|
37
|
+
"bindir": "$TMPDIR/*/bin/pgsql/{version}/bin", (glob)
|
|
38
|
+
"versions": [
|
|
39
|
+
{
|
|
40
|
+
"version": "17",
|
|
41
|
+
"bindir": "$TMPDIR/*/bin/pgsql/17/bin" (glob)
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"auth": {
|
|
45
|
+
"passfile": null
|
|
46
|
+
},
|
|
47
|
+
"replrole": "replication",
|
|
48
|
+
"datadir": "$TMPDIR/srv/pgsql/{version}/{name}/data",
|
|
49
|
+
"waldir": "$TMPDIR/srv/pgsql/{version}/{name}/wal",
|
|
50
|
+
"logpath": "$TMPDIR/log/postgresql",
|
|
51
|
+
"socket_directory": "$TMPDIR/run/postgresql",
|
|
52
|
+
"dumps_directory": "$TMPDIR/srv/dumps/{version}-{name}"
|
|
53
|
+
}
|
|
54
|
+
{
|
|
55
|
+
"execpath": "$TMPDIR/*/bin/pgbackrest", (glob)
|
|
30
56
|
"configpath": "$TMPDIR/etc/pgbackrest",
|
|
31
57
|
"repository": {
|
|
32
58
|
"mode": "path",
|
|
33
|
-
"path": "$TMPDIR
|
|
59
|
+
"path": "$TMPDIR/*/backups" (glob)
|
|
34
60
|
},
|
|
35
61
|
"logpath": "$TMPDIR/log/pgbackrest",
|
|
36
62
|
"spoolpath": "$TMPDIR/srv/pgbackrest/spool",
|
|
37
63
|
"lockpath": "$TMPDIR/run/pgbackrest/lock"
|
|
38
64
|
}
|
|
39
65
|
{
|
|
40
|
-
"execpath": "
|
|
66
|
+
"execpath": "$TMPDIR/*/bin/postgres_exporter", (glob)
|
|
41
67
|
"configpath": "$TMPDIR/etc/prometheus/postgres_exporter-{name}.conf",
|
|
42
68
|
"pid_file": "$TMPDIR/run/prometheus/{name}.pid"
|
|
43
69
|
}
|
|
44
70
|
"$TMPDIR"
|
|
45
71
|
"$TMPDIR/run"
|
|
46
72
|
|
|
47
|
-
$ trap "pglift --non-interactive --log-level=INFO site-configure uninstall" EXIT
|
|
48
|
-
|
|
49
73
|
$ pglift --help
|
|
50
74
|
Usage: pglift [OPTIONS] COMMAND [ARGS]...
|
|
51
75
|
|
|
52
76
|
Deploy production-ready instances of PostgreSQL
|
|
53
77
|
|
|
54
78
|
Options:
|
|
55
|
-
-L, --log-level [
|
|
79
|
+
-L, --log-level [debug|info|warning|error|critical]
|
|
56
80
|
Set log threshold (default to INFO when
|
|
57
81
|
logging to stderr or WARNING when logging to
|
|
58
82
|
a file).
|
|
@@ -81,23 +105,17 @@ Site configuration
|
|
|
81
105
|
$ pglift site-configure list
|
|
82
106
|
$TMPDIR/etc/pgbackrest/conf.d
|
|
83
107
|
$TMPDIR/etc/pgbackrest/pgbackrest.conf
|
|
84
|
-
$TMPDIR
|
|
108
|
+
$TMPDIR/*/backups (glob)
|
|
85
109
|
$TMPDIR/log/pgbackrest
|
|
86
110
|
$TMPDIR/srv/pgbackrest/spool
|
|
87
111
|
$TMPDIR/log/postgresql
|
|
88
|
-
$ pglift --log-level=INFO site-configure install
|
|
89
|
-
INFO creating base pgBackRest configuration directory: $TMPDIR/etc/pgbackrest
|
|
90
|
-
INFO installing base pgBackRest configuration
|
|
91
|
-
INFO creating pgBackRest include directory
|
|
92
|
-
INFO creating pgBackRest repository backups and archive directory: $TMPDIR/test-help/backups
|
|
93
|
-
INFO creating pgBackRest log directory: $TMPDIR/log/pgbackrest
|
|
94
|
-
INFO creating pgBackRest spool directory: $TMPDIR/srv/pgbackrest/spool
|
|
95
|
-
INFO creating PostgreSQL log directory: $TMPDIR/log/postgresql
|
|
96
112
|
$ env PGLIFT_LOGGERS='pglift_cli,pglift,filelock' \
|
|
97
113
|
> pglift --log-level=debug --log-file=$TMPDIR/check.log site-configure check
|
|
114
|
+
[1]
|
|
98
115
|
$ cat $TMPDIR/check.log
|
|
99
116
|
DEBUG Attempting to acquire lock \d+ on \$TMPDIR\/run\/.pglift.lock (re)
|
|
100
117
|
DEBUG Lock \d+ acquired on \$TMPDIR\/run\/.pglift.lock (re)
|
|
118
|
+
ERROR pgBackRest configuration path $TMPDIR/etc/pgbackrest/conf.d missing
|
|
101
119
|
DEBUG Attempting to release lock \d+ on \$TMPDIR\/run\/.pglift.lock (re)
|
|
102
120
|
DEBUG Lock \d+ released on \$TMPDIR\/run\/.pglift.lock (re)
|
|
103
121
|
|
|
@@ -120,7 +138,7 @@ Instance commands
|
|
|
120
138
|
demote Demote PostgreSQL INSTANCE as standby of specified source...
|
|
121
139
|
drop Drop PostgreSQL INSTANCE
|
|
122
140
|
env Output environment variables suitable to handle to...
|
|
123
|
-
exec Execute
|
|
141
|
+
exec Execute COMMAND in the libpq environment for PostgreSQL...
|
|
124
142
|
get Get the description of PostgreSQL INSTANCE.
|
|
125
143
|
list List the available instances
|
|
126
144
|
logs Output PostgreSQL logs of INSTANCE.
|
|
@@ -313,7 +331,7 @@ Instance commands
|
|
|
313
331
|
$ pglift instance exec --help
|
|
314
332
|
Usage: pglift instance exec [OPTIONS] INSTANCE COMMAND...
|
|
315
333
|
|
|
316
|
-
Execute
|
|
334
|
+
Execute COMMAND in the libpq environment for PostgreSQL INSTANCE.
|
|
317
335
|
|
|
318
336
|
COMMAND parts may need to be prefixed with -- to separate them from options
|
|
319
337
|
when confusion arises.
|
|
@@ -774,6 +792,23 @@ Database commands
|
|
|
774
792
|
Options:
|
|
775
793
|
-o, --output-format [json] Specify the output format.
|
|
776
794
|
--help Show this message and exit.
|
|
795
|
+
$ pglift database restore --help
|
|
796
|
+
Usage: pglift database restore [OPTIONS] DUMP_ID [TARGETDBNAME]
|
|
797
|
+
|
|
798
|
+
Restore a database dump
|
|
799
|
+
|
|
800
|
+
DUMP_ID identifies the dump id.
|
|
801
|
+
|
|
802
|
+
TARGETDBNAME identifies the (optional) name of the database in which the
|
|
803
|
+
dump is reloaded. If provided, the database needs to be created beforehand.
|
|
804
|
+
|
|
805
|
+
If TARGETDBNAME is not provided, the dump is reloaded using the database
|
|
806
|
+
name that appears in the dump. In this case, the restore command will create
|
|
807
|
+
the database so it needs to be dropped before running the command.
|
|
808
|
+
|
|
809
|
+
Options:
|
|
810
|
+
--dry-run Simulate change operations.
|
|
811
|
+
--help Show this message and exit.
|
|
777
812
|
$ pglift database get --help
|
|
778
813
|
Usage: pglift database get [OPTIONS] NAME
|
|
779
814
|
|
|
@@ -1023,9 +1058,3 @@ Patroni commands:
|
|
|
1023
1058
|
Options:
|
|
1024
1059
|
--help Show this message and exit.
|
|
1025
1060
|
|
|
1026
|
-
(Cleanup)
|
|
1027
|
-
INFO deleting pgBackRest include directory
|
|
1028
|
-
INFO uninstalling base pgBackRest configuration
|
|
1029
|
-
INFO deleting pgBackRest log directory
|
|
1030
|
-
INFO deleting pgBackRest spool directory
|
|
1031
|
-
INFO deleting PostgreSQL log directory (no-eol)
|
|
@@ -259,7 +259,7 @@ def test_command_as_root(runner: CliRunner, obj: Obj) -> None:
|
|
|
259
259
|
|
|
260
260
|
@app.command
|
|
261
261
|
def cmd(instance: system.Instance) -> None:
|
|
262
|
-
|
|
262
|
+
"""Something for testing."""
|
|
263
263
|
|
|
264
264
|
with patch("pglift_cli.util.is_root", autospec=True, return_value=True) as is_root:
|
|
265
265
|
result = runner.invoke(app, ["cmd"], obj=obj)
|
|
@@ -267,6 +267,13 @@ def test_command_as_root(runner: CliRunner, obj: Obj) -> None:
|
|
|
267
267
|
assert result.exit_code == 1
|
|
268
268
|
assert "Error: pglift cannot be used as root" in result.stderr
|
|
269
269
|
|
|
270
|
+
# Invocation with --help is allowed though.
|
|
271
|
+
with patch("pglift_cli.util.is_root", autospec=True, return_value=True) as is_root:
|
|
272
|
+
result = runner.invoke(app, ["cmd", "myinstance", "--help"], obj=obj)
|
|
273
|
+
assert not is_root.called
|
|
274
|
+
assert result.exit_code == 0
|
|
275
|
+
assert "Something for testing." in result.stdout
|
|
276
|
+
|
|
270
277
|
|
|
271
278
|
@pytest.mark.usefixtures("site_settings")
|
|
272
279
|
def test_instance_commands_completion(obj: Obj) -> None:
|
|
@@ -24,8 +24,8 @@ def obj() -> Obj:
|
|
|
24
24
|
def test_cli(runner: CliRunner, obj: Obj) -> None:
|
|
25
25
|
# invoke the CLI with no option, sanity check
|
|
26
26
|
result = runner.invoke(main.cli, obj=obj)
|
|
27
|
-
assert result.exit_code ==
|
|
28
|
-
assert result.
|
|
27
|
+
assert result.exit_code == 2
|
|
28
|
+
assert result.stderr.splitlines()[0] == "Usage: cli [OPTIONS] COMMAND [ARGS]..."
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def test_non_interactive(runner: CliRunner) -> None:
|
|
@@ -52,7 +52,7 @@ def test_as_parameters_typeerror() -> None:
|
|
|
52
52
|
pass
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def test_as_parameters() -> None:
|
|
55
|
+
def test_as_parameters(runner: CliRunner) -> None:
|
|
56
56
|
@click.command("add-person")
|
|
57
57
|
@click.option("--exclude-none", is_flag=True, default=False)
|
|
58
58
|
@model.as_parameters(models.Person, "create")
|
|
@@ -66,7 +66,6 @@ def test_as_parameters() -> None:
|
|
|
66
66
|
err=True,
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
-
runner = CliRunner(mix_stderr=False)
|
|
70
69
|
result = runner.invoke(add_person, ["--help"])
|
|
71
70
|
assert result.exit_code == 0, click_result_traceback(result)
|
|
72
71
|
assert result.stdout == (
|
|
@@ -77,7 +76,6 @@ def test_as_parameters() -> None:
|
|
|
77
76
|
"Options:\n"
|
|
78
77
|
" --exclude-none\n"
|
|
79
78
|
" --nickname TEXT Your secret nickname. [required]\n"
|
|
80
|
-
" --gender [M|F]\n"
|
|
81
79
|
" --age AGE Age.\n"
|
|
82
80
|
" --address-street STREET Street lines. (Can be used multiple times.)\n"
|
|
83
81
|
" --address-zip-code ZIP_CODE ZIP code.\n"
|
|
@@ -104,7 +102,6 @@ def test_as_parameters() -> None:
|
|
|
104
102
|
"friend",
|
|
105
103
|
"--exclude-none",
|
|
106
104
|
"--age=42",
|
|
107
|
-
"--gender=F",
|
|
108
105
|
"--address-street=bd montparnasse",
|
|
109
106
|
"--address-street=far far away",
|
|
110
107
|
"--address-town=paris",
|
|
@@ -131,7 +128,6 @@ def test_as_parameters() -> None:
|
|
|
131
128
|
},
|
|
132
129
|
"age": 42,
|
|
133
130
|
"birth": {"date": "1981-02-18"},
|
|
134
|
-
"gender": "F",
|
|
135
131
|
"name": "alice",
|
|
136
132
|
"nickname": "**********",
|
|
137
133
|
"relation": "friend",
|
|
@@ -174,7 +170,6 @@ def test_as_parameters_update() -> None:
|
|
|
174
170
|
"\n"
|
|
175
171
|
"Options:\n"
|
|
176
172
|
" --nickname TEXT Your secret nickname. [required]\n"
|
|
177
|
-
" --gender [M|F]\n"
|
|
178
173
|
" --age AGE Age.\n"
|
|
179
174
|
" --address-zip-code ZIP_CODE ZIP code.\n"
|
|
180
175
|
" --address-town CITY City.\n"
|
|
@@ -279,7 +274,6 @@ def test_unnest() -> None:
|
|
|
279
274
|
params = {
|
|
280
275
|
"name": "alice",
|
|
281
276
|
"age": 42,
|
|
282
|
-
"gender": "F",
|
|
283
277
|
"address_city": "paris",
|
|
284
278
|
"address_country": "fr",
|
|
285
279
|
"address_street": ["bd montparnasse"],
|
|
@@ -291,7 +285,6 @@ def test_unnest() -> None:
|
|
|
291
285
|
assert model.unnest(models.Person, params) == {
|
|
292
286
|
"name": "alice",
|
|
293
287
|
"age": 42,
|
|
294
|
-
"gender": "F",
|
|
295
288
|
"address": {
|
|
296
289
|
"city": "paris",
|
|
297
290
|
"coords": {"long": 0, "lat": 1.2},
|
|
@@ -330,7 +323,6 @@ def test_parse_params_as() -> None:
|
|
|
330
323
|
"relation": "other",
|
|
331
324
|
"nickname": "la malice",
|
|
332
325
|
"age": 42,
|
|
333
|
-
"gender": "F",
|
|
334
326
|
"address": address_params,
|
|
335
327
|
"birth": {"date": "1976-05-04"},
|
|
336
328
|
}
|
|
@@ -339,7 +331,6 @@ def test_parse_params_as() -> None:
|
|
|
339
331
|
nickname="la malice",
|
|
340
332
|
relation="other",
|
|
341
333
|
age=42,
|
|
342
|
-
gender=models.Gender.female,
|
|
343
334
|
address=address,
|
|
344
335
|
birth=models.BirthInformation(date=date(1976, 5, 4)), # type: ignore[call-arg]
|
|
345
336
|
)
|
|
@@ -350,7 +341,6 @@ def test_parse_params_as() -> None:
|
|
|
350
341
|
"relation": "other",
|
|
351
342
|
"nickname": "la malice",
|
|
352
343
|
"age": 42,
|
|
353
|
-
"gender": "F",
|
|
354
344
|
"birth_date": "1976-05-04",
|
|
355
345
|
}
|
|
356
346
|
params_nested.update({f"address_{k}": v for k, v in address_params.items()})
|
|
@@ -21,7 +21,7 @@ from rich.console import Console
|
|
|
21
21
|
|
|
22
22
|
from pglift import exceptions
|
|
23
23
|
from pglift.models import interface, system
|
|
24
|
-
from pglift.settings import Settings
|
|
24
|
+
from pglift.settings import PostgreSQLVersion, Settings
|
|
25
25
|
from pglift.types import ByteSizeType
|
|
26
26
|
from pglift_cli import util
|
|
27
27
|
|
|
@@ -346,7 +346,7 @@ def test_asynccommand(runner: CliRunner) -> None:
|
|
|
346
346
|
|
|
347
347
|
|
|
348
348
|
def test_get_instance(
|
|
349
|
-
settings: Settings, pg_version:
|
|
349
|
+
settings: Settings, pg_version: PostgreSQLVersion, instance: system.Instance
|
|
350
350
|
) -> None:
|
|
351
351
|
assert util.get_instance(instance.name, pg_version, settings) == instance
|
|
352
352
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|