pglift-cli 3.0.0__tar.gz → 3.2.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-3.0.0 → pglift_cli-3.2.0}/PKG-INFO +1 -1
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/main.py +42 -28
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/model.py +26 -15
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/pgconf.py +1 -1
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/util.py +2 -2
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-cli-walkthrough.t +26 -23
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-demote.t +8 -6
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-help.t +9 -7
- pglift_cli-3.2.0/tests/expect/test-instance-name.t +45 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-port-validation.t +18 -15
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-prometheus.t +3 -3
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-standby-pgbackrest.t +20 -17
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-standby.t +8 -6
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-transactions.t +0 -1
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-upgrade.t +6 -4
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/test_model.py +82 -4
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/.gitignore +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/README.md +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/hatch.toml +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/pyproject.toml +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/pytest.ini +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/__init__.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/__main__.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/_settings.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/_site.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/base.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/console.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/database.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/hookspecs.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/instance.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/patroni.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/pgbackrest/__init__.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/pgbackrest/repo_path.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/pghba.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/pm.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/postgres.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/prometheus.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/py.typed +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/role.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/src/pglift_cli/wal.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/.gitignore +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/expect/test-base.t +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/__init__.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/conftest.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/test__site.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/test_audit.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/test_cli.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/test_main.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/test_pm.py +0 -0
- {pglift_cli-3.0.0 → pglift_cli-3.2.0}/tests/unit/test_util.py +0 -0
|
@@ -11,7 +11,7 @@ import warnings
|
|
|
11
11
|
from functools import partial
|
|
12
12
|
from importlib.metadata import version
|
|
13
13
|
from pathlib import Path
|
|
14
|
-
from typing import Literal
|
|
14
|
+
from typing import Any, Literal
|
|
15
15
|
|
|
16
16
|
import click
|
|
17
17
|
import click.exceptions
|
|
@@ -24,7 +24,6 @@ from rich.highlighter import NullHighlighter
|
|
|
24
24
|
from rich.syntax import Syntax
|
|
25
25
|
|
|
26
26
|
from pglift import ui
|
|
27
|
-
from pglift._compat import assert_never
|
|
28
27
|
from pglift.system import install
|
|
29
28
|
from pglift.types import LogLevel
|
|
30
29
|
|
|
@@ -234,35 +233,50 @@ def site_settings(
|
|
|
234
233
|
console.print(syntax)
|
|
235
234
|
|
|
236
235
|
|
|
237
|
-
@cli.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
"
|
|
243
|
-
|
|
244
|
-
|
|
236
|
+
@cli.group(hidden=True)
|
|
237
|
+
def site_configure(**kwargs: Any) -> None:
|
|
238
|
+
"""Manage installation of extra data files for pglift.
|
|
239
|
+
|
|
240
|
+
This is an INTERNAL command.
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
@site_configure.command("install")
|
|
245
|
+
@click.option(
|
|
246
|
+
"--force",
|
|
247
|
+
is_flag=True,
|
|
248
|
+
default=False,
|
|
249
|
+
help="Force the overwrite of installed files",
|
|
245
250
|
)
|
|
246
251
|
@click.pass_obj
|
|
252
|
+
@async_command
|
|
253
|
+
async def site_configure_install(obj: Obj, force: bool) -> None:
|
|
254
|
+
with obj.lock, audit():
|
|
255
|
+
await install.do(_site.SETTINGS, force=force)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@site_configure.command("uninstall")
|
|
259
|
+
@click.pass_obj
|
|
260
|
+
@async_command
|
|
261
|
+
async def site_configure_uninstall(obj: Obj) -> None:
|
|
262
|
+
with obj.lock, audit():
|
|
263
|
+
await install.undo(_site.SETTINGS)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@site_configure.command("check")
|
|
267
|
+
@click.pass_obj
|
|
247
268
|
@click.pass_context
|
|
248
269
|
@async_command
|
|
249
|
-
async def
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
270
|
+
async def site_configure_check(context: click.Context, obj: Obj) -> None:
|
|
271
|
+
with obj.lock, audit():
|
|
272
|
+
if not install.check(_site.SETTINGS):
|
|
273
|
+
context.exit(1)
|
|
253
274
|
|
|
254
|
-
|
|
255
|
-
|
|
275
|
+
|
|
276
|
+
@site_configure.command("list")
|
|
277
|
+
@click.pass_obj
|
|
278
|
+
@async_command
|
|
279
|
+
async def site_configure_list(obj: Obj) -> None:
|
|
256
280
|
with obj.lock, audit():
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
elif action == "uninstall":
|
|
260
|
-
await install.undo(_site.SETTINGS)
|
|
261
|
-
elif action == "check":
|
|
262
|
-
if not install.check(_site.SETTINGS):
|
|
263
|
-
context.exit(1)
|
|
264
|
-
elif action == "list":
|
|
265
|
-
for p in install.ls(_site.SETTINGS):
|
|
266
|
-
click.echo(p)
|
|
267
|
-
else:
|
|
268
|
-
assert_never(action)
|
|
281
|
+
for p in install.ls(_site.SETTINGS):
|
|
282
|
+
click.echo(p)
|
|
@@ -18,10 +18,11 @@ import pydantic
|
|
|
18
18
|
from pydantic.fields import FieldInfo
|
|
19
19
|
from pydantic_core import ErrorDetails
|
|
20
20
|
|
|
21
|
-
from pglift.annotations import cli
|
|
21
|
+
from pglift.annotations import CreateOnly, cli
|
|
22
22
|
from pglift.exceptions import MutuallyExclusiveError
|
|
23
23
|
from pglift.models.helpers import is_optional, optional_type
|
|
24
24
|
from pglift.models.interface import PresenceState
|
|
25
|
+
from pglift.settings import Settings
|
|
25
26
|
from pglift.types import (
|
|
26
27
|
Operation,
|
|
27
28
|
field_annotation,
|
|
@@ -33,6 +34,7 @@ from . import _site, logger
|
|
|
33
34
|
|
|
34
35
|
ModelType = type[pydantic.BaseModel]
|
|
35
36
|
T = TypeVar("T", bound=pydantic.BaseModel)
|
|
37
|
+
V = TypeVar("V")
|
|
36
38
|
Callback = Callable[..., Any]
|
|
37
39
|
ClickDecorator = Callable[[Callback], Callback]
|
|
38
40
|
DEFAULT = object()
|
|
@@ -167,7 +169,7 @@ class ParamSpec(ABC):
|
|
|
167
169
|
loc: tuple[str, ...]
|
|
168
170
|
description: str | None = None
|
|
169
171
|
|
|
170
|
-
objtype: ClassVar[type[click.Parameter]]
|
|
172
|
+
objtype: ClassVar[type[click.Parameter]]
|
|
171
173
|
|
|
172
174
|
@property
|
|
173
175
|
def param(self) -> click.Parameter:
|
|
@@ -296,6 +298,15 @@ def _paramspecs_from_model(
|
|
|
296
298
|
return DEFAULT
|
|
297
299
|
return value
|
|
298
300
|
|
|
301
|
+
def default_factory(
|
|
302
|
+
_ctx: click.Context,
|
|
303
|
+
_param: click.Argument,
|
|
304
|
+
value: V,
|
|
305
|
+
*,
|
|
306
|
+
callback: Callable[[Settings, V], V],
|
|
307
|
+
) -> V:
|
|
308
|
+
return callback(_site.SETTINGS, value)
|
|
309
|
+
|
|
299
310
|
def add_state_field_callback(
|
|
300
311
|
ctx: click.Context,
|
|
301
312
|
_param: click.Argument,
|
|
@@ -329,11 +340,7 @@ def _paramspecs_from_model(
|
|
|
329
340
|
for fname, field in model_type.model_fields.items():
|
|
330
341
|
if field_annotation(field, cli.Hidden):
|
|
331
342
|
continue
|
|
332
|
-
if (
|
|
333
|
-
operation == "update"
|
|
334
|
-
and isinstance(field.json_schema_extra, dict)
|
|
335
|
-
and field.json_schema_extra.get("readOnly")
|
|
336
|
-
):
|
|
343
|
+
if field_annotation(field, CreateOnly) and operation == "update":
|
|
337
344
|
continue
|
|
338
345
|
|
|
339
346
|
modelname = argname = field.alias or fname
|
|
@@ -361,9 +368,6 @@ def _paramspecs_from_model(
|
|
|
361
368
|
if not _parents and required:
|
|
362
369
|
if origin_type is typing.Literal:
|
|
363
370
|
choices = list(typing.get_args(ftype))
|
|
364
|
-
if config is not None:
|
|
365
|
-
assert isinstance(config, cli.Choices)
|
|
366
|
-
choices = config.choices
|
|
367
371
|
attrs["type"] = click.Choice(choices)
|
|
368
372
|
if config is not None and isinstance(config, cli.Option):
|
|
369
373
|
attrs["required"] = True
|
|
@@ -377,6 +381,17 @@ def _paramspecs_from_model(
|
|
|
377
381
|
),
|
|
378
382
|
)
|
|
379
383
|
|
|
384
|
+
elif config is not None and isinstance(config, cli.OptionalArgument):
|
|
385
|
+
attrs["required"] = False
|
|
386
|
+
attrs["callback"] = functools.partial(
|
|
387
|
+
default_factory,
|
|
388
|
+
callback=config.default_factory,
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
yield (
|
|
392
|
+
(modelname, argname),
|
|
393
|
+
ArgumentSpec((argname,), field, attrs, loc=(modelname,)),
|
|
394
|
+
)
|
|
380
395
|
else:
|
|
381
396
|
yield (
|
|
382
397
|
(modelname, argname),
|
|
@@ -386,11 +401,7 @@ def _paramspecs_from_model(
|
|
|
386
401
|
)
|
|
387
402
|
|
|
388
403
|
else:
|
|
389
|
-
if (
|
|
390
|
-
config
|
|
391
|
-
and isinstance(config, cli.Argument | cli.Option)
|
|
392
|
-
and config.metavar is not None
|
|
393
|
-
):
|
|
404
|
+
if config and isinstance(config, cli.Option) and config.metavar is not None:
|
|
394
405
|
metavar = config.metavar
|
|
395
406
|
else:
|
|
396
407
|
metavar = argname
|
|
@@ -58,7 +58,7 @@ def show_configuration_changes(
|
|
|
58
58
|
@cli.command("show")
|
|
59
59
|
@click.argument("parameter", nargs=-1)
|
|
60
60
|
@pass_postgresql_instance
|
|
61
|
-
def show(instance: PostgreSQLInstance, parameter: tuple[str]) -> None:
|
|
61
|
+
def show(instance: PostgreSQLInstance, parameter: tuple[str, ...]) -> None:
|
|
62
62
|
"""Show configuration (all parameters or specified ones).
|
|
63
63
|
|
|
64
64
|
Only uncommented parameters are shown when no PARAMETER is specified. When
|
|
@@ -273,7 +273,7 @@ def nameversion_from_id(instance_id: str) -> tuple[str, PostgreSQLVersion | None
|
|
|
273
273
|
|
|
274
274
|
|
|
275
275
|
def postgresql_instance_lookup(
|
|
276
|
-
context: click.Context, param: click.Parameter, value: None | str | tuple[str]
|
|
276
|
+
context: click.Context, param: click.Parameter, value: None | str | tuple[str, ...]
|
|
277
277
|
) -> PostgreSQLInstance | tuple[PostgreSQLInstance, ...]:
|
|
278
278
|
"""Return one or more PostgreSQLInstance, possibly guessed if there
|
|
279
279
|
is only one on system, depending on 'param' variadic flag (nargs).
|
|
@@ -764,7 +764,7 @@ class PluggableCommandGroup(abc.ABC, Group):
|
|
|
764
764
|
if obj is None:
|
|
765
765
|
obj = context.ensure_object(Obj)
|
|
766
766
|
if obj is None:
|
|
767
|
-
return
|
|
767
|
+
return # type: ignore[unreachable]
|
|
768
768
|
self.register_plugin_commands(obj)
|
|
769
769
|
self._plugin_commands_loaded = True
|
|
770
770
|
|
|
@@ -26,7 +26,7 @@ Site settings:
|
|
|
26
26
|
> postgresql:
|
|
27
27
|
> auth:
|
|
28
28
|
> local: md5
|
|
29
|
-
> passfile: '$TMPDIR/.pgpass'
|
|
29
|
+
> passfile: '$TMPDIR/pgpass/.pgpass'
|
|
30
30
|
> password_command:
|
|
31
31
|
> - jq
|
|
32
32
|
> - -r
|
|
@@ -65,7 +65,7 @@ Make sure password_command works:
|
|
|
65
65
|
"local": "md5",
|
|
66
66
|
"host": "trust",
|
|
67
67
|
"hostssl": "trust",
|
|
68
|
-
"passfile": "$TMPDIR/.pgpass",
|
|
68
|
+
"passfile": "$TMPDIR/pgpass/.pgpass",
|
|
69
69
|
"password_command": [
|
|
70
70
|
"jq",
|
|
71
71
|
"-r",
|
|
@@ -89,10 +89,11 @@ Make sure password_command works:
|
|
|
89
89
|
$ pglift site-configure install
|
|
90
90
|
INFO creating base pgBackRest configuration directory: $TMPDIR/etc/pgbackrest
|
|
91
91
|
INFO installing base pgBackRest configuration
|
|
92
|
-
INFO creating pgBackRest include directory
|
|
92
|
+
INFO creating pgBackRest include directory: $TMPDIR/etc/pgbackrest/conf.d
|
|
93
93
|
INFO creating pgBackRest repository backups and archive directory: $TMPDIR/pgbackrest
|
|
94
94
|
INFO creating pgBackRest log directory: $TMPDIR/log/pgbackrest
|
|
95
95
|
INFO creating pgBackRest spool directory: $TMPDIR/srv/pgbackrest/spool
|
|
96
|
+
INFO creating pgpass file directory: $TMPDIR/pgpass
|
|
96
97
|
INFO creating PostgreSQL log directory: $TMPDIR/log/postgresql
|
|
97
98
|
|
|
98
99
|
$ trap "pglift --non-interactive instance drop main; \
|
|
@@ -116,10 +117,11 @@ Audit log:
|
|
|
116
117
|
DEBUG - pglift.util - using 'pgbackrest/pgbackrest.conf' configuration file from distribution
|
|
117
118
|
INFO - pglift.util - creating base pgBackRest configuration directory: $TMPDIR/etc/pgbackrest
|
|
118
119
|
INFO - pglift.pgbackrest - installing base pgBackRest configuration
|
|
119
|
-
INFO - pglift.
|
|
120
|
+
INFO - pglift.util - creating pgBackRest include directory: $TMPDIR/etc/pgbackrest/conf.d
|
|
120
121
|
INFO - pglift.util - creating pgBackRest repository backups and archive directory: $TMPDIR/pgbackrest
|
|
121
122
|
INFO - pglift.util - creating pgBackRest log directory: $TMPDIR/log/pgbackrest
|
|
122
123
|
INFO - pglift.util - creating pgBackRest spool directory: $TMPDIR/srv/pgbackrest/spool
|
|
124
|
+
INFO - pglift.util - creating pgpass file directory: $TMPDIR/pgpass
|
|
123
125
|
INFO - pglift.util - creating PostgreSQL log directory: $TMPDIR/log/postgresql
|
|
124
126
|
INFO - pglift_cli.audit - command completed \(\d+.\d+ seconds\) (re)
|
|
125
127
|
|
|
@@ -166,13 +168,13 @@ Error cases for instance operations
|
|
|
166
168
|
Error: instance already exists
|
|
167
169
|
[1]
|
|
168
170
|
$ pglift instance create 'in/va/lid' --pgbackrest-stanza=xxx --surole-password=s3per
|
|
169
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
171
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
170
172
|
Try 'pglift instance create --help' for help.
|
|
171
173
|
|
|
172
|
-
Error: Invalid value for 'NAME': String should match pattern '^[^/-]+$'
|
|
174
|
+
Error: Invalid value for '[NAME]': String should match pattern '^[^/-]+$'
|
|
173
175
|
[2]
|
|
174
176
|
$ pglift instance create stdby --standby-for='port 1234' --pgbackrest-stanza=stddy --surole-password=s3per
|
|
175
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
177
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
176
178
|
Try 'pglift instance create --help' for help.
|
|
177
179
|
|
|
178
180
|
Error: Invalid value for '--standby-for': missing "=" after "port" in connection info string
|
|
@@ -240,7 +242,6 @@ Reload, restart:
|
|
|
240
242
|
INFO stopping Prometheus postgres_exporter 1\d-main (re)
|
|
241
243
|
$ pglift instance restart
|
|
242
244
|
INFO restarting instance 1\d\/main (re)
|
|
243
|
-
INFO stopping Prometheus postgres_exporter 1\d-main (re)
|
|
244
245
|
INFO restarting PostgreSQL
|
|
245
246
|
INFO stopping PostgreSQL 1\d\/main (re)
|
|
246
247
|
INFO starting PostgreSQL 1\d\/main (re)
|
|
@@ -341,7 +342,7 @@ Stop, alter, (re)start an instance:
|
|
|
341
342
|
Instance environment, and program execution:
|
|
342
343
|
|
|
343
344
|
$ pglift instance env | grep PASSFILE
|
|
344
|
-
PGPASSFILE=$TMPDIR/.pgpass
|
|
345
|
+
PGPASSFILE=$TMPDIR/pgpass/.pgpass
|
|
345
346
|
$ pglift instance env -o json | jq '.PGBACKREST_STANZA, .PGHOST, .PGPASSWORD'
|
|
346
347
|
"main"
|
|
347
348
|
"$TMPDIR/run/postgresql"
|
|
@@ -518,14 +519,14 @@ Add and manipulate roles:
|
|
|
518
519
|
|
|
519
520
|
$ pglift role -i main create dba --login --pgpass --password=qwerty --in-role=pg_read_all_stats --dry-run
|
|
520
521
|
INFO creating role 'dba'
|
|
521
|
-
INFO adding an entry for 'dba' in \$TMPDIR\/.pgpass \(port=\d+\) (re)
|
|
522
|
+
INFO adding an entry for 'dba' in \$TMPDIR\/pgpass\/.pgpass \(port=\d+\) (re)
|
|
522
523
|
DRY RUN: no changes made
|
|
523
524
|
|
|
524
525
|
$ pglift role -i main create dba --login --pgpass --password=qwerty --in-role=pg_read_all_stats
|
|
525
526
|
INFO creating role 'dba'
|
|
526
|
-
INFO adding an entry for 'dba' in \$TMPDIR\/.pgpass \(port=\d+\) (re)
|
|
527
|
+
INFO adding an entry for 'dba' in \$TMPDIR\/pgpass\/.pgpass \(port=\d+\) (re)
|
|
527
528
|
|
|
528
|
-
$ cat $TMPDIR/.pgpass
|
|
529
|
+
$ cat $TMPDIR/pgpass/.pgpass
|
|
529
530
|
\*:\d+:\*:dba:qwerty (re)
|
|
530
531
|
|
|
531
532
|
$ pglift role get dba
|
|
@@ -555,8 +556,8 @@ Add and manipulate roles:
|
|
|
555
556
|
|
|
556
557
|
$ pglift role alter dba --connection-limit=10 --inherit --no-pgpass --no-login --revoke=pg_read_all_stats --grant=pg_monitor --valid-until=2026-01-01 --dry-run
|
|
557
558
|
INFO altering role 'dba'
|
|
558
|
-
INFO removing entry for 'dba' in \$TMPDIR\/.pgpass \(port=\d+\) (re)
|
|
559
|
-
INFO removing now empty $TMPDIR/.pgpass
|
|
559
|
+
INFO removing entry for 'dba' in \$TMPDIR\/pgpass\/.pgpass \(port=\d+\) (re)
|
|
560
|
+
INFO removing now empty $TMPDIR/pgpass/.pgpass
|
|
560
561
|
DRY RUN: no changes made
|
|
561
562
|
|
|
562
563
|
$ pglift role -i main create dba --password=qwerty --encrypted-password=md5azerty
|
|
@@ -568,8 +569,8 @@ Add and manipulate roles:
|
|
|
568
569
|
|
|
569
570
|
$ pglift role alter dba --connection-limit=10 --inherit --no-pgpass --no-login --revoke=pg_read_all_stats --grant=pg_monitor --valid-until=2026-01-01
|
|
570
571
|
INFO altering role 'dba'
|
|
571
|
-
INFO removing entry for 'dba' in \$TMPDIR\/.pgpass \(port=\d+\) (re)
|
|
572
|
-
INFO removing now empty $TMPDIR/.pgpass
|
|
572
|
+
INFO removing entry for 'dba' in \$TMPDIR\/pgpass\/.pgpass \(port=\d+\) (re)
|
|
573
|
+
INFO removing now empty $TMPDIR/pgpass/.pgpass
|
|
573
574
|
|
|
574
575
|
$ pglift role get dba -o json
|
|
575
576
|
{
|
|
@@ -1289,11 +1290,13 @@ Cleanup.
|
|
|
1289
1290
|
INFO deconfiguring Prometheus postgres_exporter 1\d-main (re)
|
|
1290
1291
|
INFO deleting pgBackRest stanza 'main'
|
|
1291
1292
|
INFO deconfiguring pgBackRest stanza 'main'
|
|
1292
|
-
INFO removing entries matching port=\d+ from \$TMPDIR\/.pgpass (re)
|
|
1293
|
-
INFO deleting PostgreSQL data
|
|
1294
|
-
INFO deleting
|
|
1293
|
+
INFO removing entries matching port=\d+ from \$TMPDIR\/pgpass\/.pgpass (re)
|
|
1294
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/srv\/pgsql\/1\d\/main/data (re)
|
|
1295
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/srv\/pgsql\/1\d\/main/wal (re)
|
|
1296
|
+
INFO deleting pgBackRest include directory: $TMPDIR/etc/pgbackrest/conf.d
|
|
1295
1297
|
INFO uninstalling base pgBackRest configuration
|
|
1296
|
-
INFO deleting pgBackRest log directory
|
|
1297
|
-
INFO deleting pgBackRest spool directory
|
|
1298
|
-
INFO deleting
|
|
1299
|
-
INFO deleting PostgreSQL
|
|
1298
|
+
INFO deleting pgBackRest log directory: $TMPDIR/log/pgbackrest
|
|
1299
|
+
INFO deleting pgBackRest spool directory: $TMPDIR/srv/pgbackrest/spool
|
|
1300
|
+
INFO deleting pgpass file parent directory
|
|
1301
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/log/postgresql
|
|
1302
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/run/postgresql (no-eol)
|
|
@@ -220,11 +220,13 @@ And finally check replication is functional
|
|
|
220
220
|
|
|
221
221
|
INFO dropping instance 1\d\/pg1 (re)
|
|
222
222
|
INFO stopping PostgreSQL 1\d\/pg1 (re)
|
|
223
|
-
INFO deleting PostgreSQL data
|
|
223
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/1\/srv\/pgsql\/1\d\/pg1\/data (re)
|
|
224
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/1\/srv\/pgsql\/1\d\/pg1\/wal (re)
|
|
224
225
|
INFO dropping instance 1\d\/pg2 (re)
|
|
225
226
|
INFO stopping PostgreSQL 1\d\/pg2 (re)
|
|
226
|
-
INFO deleting PostgreSQL data
|
|
227
|
-
INFO deleting PostgreSQL
|
|
228
|
-
INFO deleting PostgreSQL
|
|
229
|
-
INFO deleting PostgreSQL
|
|
230
|
-
INFO deleting PostgreSQL
|
|
227
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/2\/srv\/pgsql\/1\d\/pg2\/data (re)
|
|
228
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/2\/srv\/pgsql\/1\d\/pg2\/wal (re)
|
|
229
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/1/log/postgresql
|
|
230
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/1/run/postgresql
|
|
231
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/2/log/postgresql
|
|
232
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/2/run/postgresql (no-eol)
|
|
@@ -228,7 +228,7 @@ Instance commands
|
|
|
228
228
|
-o, --output-format [json] Specify the output format.
|
|
229
229
|
--help Show this message and exit.
|
|
230
230
|
$ pglift instance create --help
|
|
231
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
231
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
232
232
|
|
|
233
233
|
Initialize a PostgreSQL instance
|
|
234
234
|
|
|
@@ -249,13 +249,13 @@ Instance commands
|
|
|
249
249
|
--locale LOCALE Default locale.
|
|
250
250
|
--encoding ENCODING Character encoding of the PostgreSQL
|
|
251
251
|
instance.
|
|
252
|
-
--auth-local [trust|reject|md5|password|scram-sha-256|sspi|ident|
|
|
252
|
+
--auth-local [trust|reject|md5|password|scram-sha-256|sspi|ident|pam|ldap|radius|peer]
|
|
253
253
|
Authentication method for local-socket
|
|
254
254
|
connections.
|
|
255
|
-
--auth-host [trust|reject|md5|password|scram-sha-256|
|
|
255
|
+
--auth-host [trust|reject|md5|password|scram-sha-256|sspi|ident|pam|ldap|radius|gss]
|
|
256
256
|
Authentication method for local TCP/IP
|
|
257
257
|
connections.
|
|
258
|
-
--auth-hostssl [trust|reject|md5|password|scram-sha-256|
|
|
258
|
+
--auth-hostssl [trust|reject|md5|password|scram-sha-256|sspi|ident|pam|ldap|radius|gss|cert]
|
|
259
259
|
Authentication method for SSL-encrypted
|
|
260
260
|
TCP/IP connections.
|
|
261
261
|
--surole-password PASSWORD Super-user role password.
|
|
@@ -912,7 +912,7 @@ PostgreSQL configuration commands
|
|
|
912
912
|
Options:
|
|
913
913
|
--help Show this message and exit.
|
|
914
914
|
|
|
915
|
-
|
|
915
|
+
HBA configuration management commands
|
|
916
916
|
|
|
917
917
|
$ pglift pghba --help
|
|
918
918
|
Usage: pglift pghba [OPTIONS] COMMAND [ARGS]...
|
|
@@ -947,7 +947,8 @@ pg_hba.conf management commands
|
|
|
947
947
|
--database DATABASE Database name(s). Multiple database names
|
|
948
948
|
can be supplied by separating them with
|
|
949
949
|
commas.
|
|
950
|
-
--method
|
|
950
|
+
--method [trust|reject|md5|password|scram-sha-256|sspi|ident|pam|ldap|radius|peer|gss|cert]
|
|
951
|
+
Authentication method. [required]
|
|
951
952
|
--user USER User name(s). Multiple user names can be
|
|
952
953
|
supplied by separating them with commas.
|
|
953
954
|
--dry-run Simulate change operations.
|
|
@@ -970,7 +971,8 @@ pg_hba.conf management commands
|
|
|
970
971
|
--database DATABASE Database name(s). Multiple database names
|
|
971
972
|
can be supplied by separating them with
|
|
972
973
|
commas.
|
|
973
|
-
--method
|
|
974
|
+
--method [trust|reject|md5|password|scram-sha-256|sspi|ident|pam|ldap|radius|peer|gss|cert]
|
|
975
|
+
Authentication method. [required]
|
|
974
976
|
--user USER User name(s). Multiple user names can be
|
|
975
977
|
supplied by separating them with commas.
|
|
976
978
|
--dry-run Simulate change operations.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Dalibo
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
Site settings and configuration
|
|
6
|
+
|
|
7
|
+
$ export PGLIFT_CLI__LOG_FORMAT="%(levelname)-4s %(message)s"
|
|
8
|
+
$ export PGLIFT_CLI__LOG_LEVEL=info
|
|
9
|
+
$ export PGLIFT_POSTGRESQL__AUTH__PASSFILE=$TMPDIR/pgpass/.pgpass
|
|
10
|
+
$ export PGLIFT_INSTANCE_DEFAULT_NAME=myinstance
|
|
11
|
+
$ export PGLIFT_PREFIX=$TMPDIR
|
|
12
|
+
$ export PGLIFT_RUN_PREFIX=$TMPDIR/run
|
|
13
|
+
$ alias pglift="pglift --log-level=INFO --non-interactive"
|
|
14
|
+
|
|
15
|
+
$ pglift site-configure install
|
|
16
|
+
INFO creating pgpass file directory: $TMPDIR/pgpass
|
|
17
|
+
INFO creating PostgreSQL log directory: $TMPDIR/log/postgresql
|
|
18
|
+
|
|
19
|
+
(Cleanup steps)
|
|
20
|
+
$ trap "pglift --non-interactive instance drop; \
|
|
21
|
+
> pglift --non-interactive site-configure uninstall; \
|
|
22
|
+
> port-for -u postgres" \
|
|
23
|
+
> EXIT
|
|
24
|
+
|
|
25
|
+
Define ports:
|
|
26
|
+
$ PGPORT=$(port-for pg1)
|
|
27
|
+
|
|
28
|
+
Create an instance without a name
|
|
29
|
+
$ pglift instance create --port=$PGPORT
|
|
30
|
+
INFO initializing PostgreSQL
|
|
31
|
+
INFO configuring PostgreSQL authentication
|
|
32
|
+
INFO configuring PostgreSQL
|
|
33
|
+
INFO creating PostgreSQL socket directory directory: $TMPDIR/run/postgresql
|
|
34
|
+
INFO starting PostgreSQL 1\d\/myinstance (re)
|
|
35
|
+
INFO creating instance dumps directory: \$TMPDIR\/srv\/dumps\/1\d-myinstance (re)
|
|
36
|
+
|
|
37
|
+
Cleanup.
|
|
38
|
+
INFO dropping instance 1\d\/myinstance (re)
|
|
39
|
+
INFO stopping PostgreSQL 1\d\/myinstance (re)
|
|
40
|
+
INFO removing entries matching port=\d+ from \$TMPDIR\/pgpass/.pgpass (re)
|
|
41
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/srv\/pgsql\/1\d\/myinstance/data (re)
|
|
42
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/srv\/pgsql\/1\d\/myinstance/wal (re)
|
|
43
|
+
INFO deleting pgpass file parent directory
|
|
44
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/log/postgresql
|
|
45
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/run/postgresql (no-eol)
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
$ pglift site-configure install
|
|
28
28
|
INFO creating base pgBackRest configuration directory: $TMPDIR/etc/pgbackrest
|
|
29
29
|
INFO installing base pgBackRest configuration
|
|
30
|
-
INFO creating pgBackRest include directory
|
|
30
|
+
INFO creating pgBackRest include directory: $TMPDIR/etc/pgbackrest/conf.d
|
|
31
31
|
INFO creating pgBackRest repository backups and archive directory: $TMPDIR/pgbackrest-not-used
|
|
32
32
|
INFO creating pgBackRest log directory: $TMPDIR/log/pgbackrest
|
|
33
33
|
INFO creating pgBackRest spool directory: $TMPDIR/srv/pgbackrest/spool
|
|
@@ -57,19 +57,19 @@ With custom ports
|
|
|
57
57
|
INFO creating instance dumps directory: \$TMPDIR\/srv\/dumps\/1\d-main (re)
|
|
58
58
|
INFO starting Prometheus postgres_exporter 1\d-main (re)
|
|
59
59
|
$ pglift instance create other --port=$PG2PORT --prometheus-port=$PGE1PORT
|
|
60
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
60
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
61
61
|
Try 'pglift instance create --help' for help.
|
|
62
62
|
|
|
63
63
|
Error: Invalid value for '--prometheus-port': port \d+ already in use (re)
|
|
64
64
|
[2]
|
|
65
65
|
$ pglift instance create other --port=$PG1PORT --prometheus-port=$PGE2PORT
|
|
66
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
66
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
67
67
|
Try 'pglift instance create --help' for help.
|
|
68
68
|
|
|
69
69
|
Error: Invalid value for '--port': port \d+ already in use (re)
|
|
70
70
|
[2]
|
|
71
71
|
$ pglift instance create other --port=$PG1PORT --prometheus-port=$PGE1PORT
|
|
72
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
72
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
73
73
|
Try 'pglift instance create --help' for help.
|
|
74
74
|
|
|
75
75
|
Error: Invalid value for '--prometheus-port': port \d+ already in use (re)
|
|
@@ -79,7 +79,8 @@ With custom ports
|
|
|
79
79
|
INFO stopping PostgreSQL 1\d\/main (re)
|
|
80
80
|
INFO stopping Prometheus postgres_exporter 1\d-main (re)
|
|
81
81
|
INFO deconfiguring Prometheus postgres_exporter 1\d-main (re)
|
|
82
|
-
INFO deleting PostgreSQL data
|
|
82
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/srv\/pgsql\/1\d\/main\/data (re)
|
|
83
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/srv\/pgsql\/1\d\/main\/wal (re)
|
|
83
84
|
|
|
84
85
|
With a port set in postgresql.conf template
|
|
85
86
|
|
|
@@ -99,13 +100,13 @@ With a port set in postgresql.conf template
|
|
|
99
100
|
INFO creating instance dumps directory: \$TMPDIR\/srv\/dumps\/1\d-main (re)
|
|
100
101
|
INFO starting Prometheus postgres_exporter 1\d-main (re)
|
|
101
102
|
$ pglift instance create other --prometheus-port=$PGE2PORT
|
|
102
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
103
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
103
104
|
Try 'pglift instance create --help' for help.
|
|
104
105
|
|
|
105
106
|
Error: Invalid value for '--port': port \d+ already in use (re)
|
|
106
107
|
[2]
|
|
107
108
|
$ pglift instance create other --port=$PG2PORT --prometheus-port=$PGE1PORT
|
|
108
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
109
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
109
110
|
Try 'pglift instance create --help' for help.
|
|
110
111
|
|
|
111
112
|
Error: Invalid value for '--prometheus-port': port \d+ already in use (re)
|
|
@@ -116,7 +117,8 @@ With a port set in postgresql.conf template
|
|
|
116
117
|
INFO stopping PostgreSQL 1\d\/main (re)
|
|
117
118
|
INFO stopping Prometheus postgres_exporter 1\d-main (re)
|
|
118
119
|
INFO deconfiguring Prometheus postgres_exporter 1\d-main (re)
|
|
119
|
-
INFO deleting PostgreSQL data
|
|
120
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/srv\/pgsql\/1\d\/main\/data (re)
|
|
121
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/srv\/pgsql\/1\d\/main\/wal (re)
|
|
120
122
|
$ rm -rf $PGLIFT_CONFIG_DIR/postgresql
|
|
121
123
|
|
|
122
124
|
With default ports
|
|
@@ -131,7 +133,7 @@ With default ports
|
|
|
131
133
|
INFO creating instance dumps directory: \$TMPDIR\/srv\/dumps\/1\d-main (re)
|
|
132
134
|
INFO starting Prometheus postgres_exporter 1\d-main (re)
|
|
133
135
|
$ pglift instance create other
|
|
134
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
136
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
135
137
|
Try 'pglift instance create --help' for help.
|
|
136
138
|
|
|
137
139
|
Error: Invalid value for '--port': port 5432 already in use
|
|
@@ -142,12 +144,13 @@ With default ports
|
|
|
142
144
|
INFO stopping PostgreSQL 1\d\/main (re)
|
|
143
145
|
INFO stopping Prometheus postgres_exporter 1\d-main (re)
|
|
144
146
|
INFO deconfiguring Prometheus postgres_exporter 1\d-main (re)
|
|
145
|
-
INFO deleting PostgreSQL data
|
|
147
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/srv\/pgsql\/1\d\/main\/data (re)
|
|
148
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/srv\/pgsql\/1\d\/main\/wal (re)
|
|
146
149
|
|
|
147
150
|
(cleanup)
|
|
148
|
-
INFO deleting pgBackRest include directory
|
|
151
|
+
INFO deleting pgBackRest include directory: $TMPDIR/etc/pgbackrest/conf.d
|
|
149
152
|
INFO uninstalling base pgBackRest configuration
|
|
150
|
-
INFO deleting pgBackRest log directory
|
|
151
|
-
INFO deleting pgBackRest spool directory
|
|
152
|
-
INFO deleting PostgreSQL log directory
|
|
153
|
-
INFO deleting PostgreSQL socket directory (no-eol)
|
|
153
|
+
INFO deleting pgBackRest log directory: $TMPDIR/log/pgbackrest
|
|
154
|
+
INFO deleting pgBackRest spool directory: $TMPDIR/srv/pgbackrest/spool
|
|
155
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/log/postgresql
|
|
156
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/run/postgresql (no-eol)
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
{
|
|
45
45
|
"before_header": "$TMPDIR/etc/prometheus/postgres_exporter-test.conf",
|
|
46
46
|
"after_header": "$TMPDIR/etc/prometheus/postgres_exporter-test.conf",
|
|
47
|
-
"before": "DATA_SOURCE_NAME=postgresql://:5432/monitoring\nPOSTGRES_EXPORTER_OPTS='--web.listen-address :* --log.level info'", (glob)
|
|
48
|
-
"after": "DATA_SOURCE_NAME=postgresql://prometheus@:5432/monitoring\nPOSTGRES_EXPORTER_OPTS='--web.listen-address :* --log.level info'" (glob)
|
|
47
|
+
"before": "DATA_SOURCE_NAME=postgresql://:5432/monitoring\nPOSTGRES_EXPORTER_OPTS='--web.listen-address :* --log.level info'\n", (glob)
|
|
48
|
+
"after": "DATA_SOURCE_NAME=postgresql://prometheus@:5432/monitoring\nPOSTGRES_EXPORTER_OPTS='--web.listen-address :* --log.level info'\n" (glob)
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"before_header": "$TMPDIR/run/prometheus/test.pid deleted",
|
|
@@ -100,4 +100,4 @@ Check port conflicts
|
|
|
100
100
|
INFO deconfiguring Prometheus postgres_exporter test
|
|
101
101
|
|
|
102
102
|
(cleanup)
|
|
103
|
-
INFO deleting PostgreSQL log directory (no-eol)
|
|
103
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/log/postgresql (no-eol)
|
|
@@ -60,7 +60,7 @@ Site settings and configuration
|
|
|
60
60
|
$ pglift1 site-configure install
|
|
61
61
|
INFO creating base pgBackRest configuration directory: $TMPDIR/1/etc/pgbackrest
|
|
62
62
|
INFO installing base pgBackRest configuration
|
|
63
|
-
INFO creating pgBackRest include directory
|
|
63
|
+
INFO creating pgBackRest include directory: $TMPDIR/1/etc/pgbackrest/conf.d
|
|
64
64
|
INFO creating pgBackRest repository backups and archive directory: $TMPDIR/test-standby-pgbackrest/backups
|
|
65
65
|
INFO creating pgBackRest log directory: $TMPDIR/1/log/pgbackrest
|
|
66
66
|
INFO creating pgBackRest spool directory: $TMPDIR/1/srv/pgbackrest/spool
|
|
@@ -68,7 +68,7 @@ Site settings and configuration
|
|
|
68
68
|
$ pglift2 site-configure install
|
|
69
69
|
INFO creating base pgBackRest configuration directory: $TMPDIR/2/etc/pgbackrest
|
|
70
70
|
INFO installing base pgBackRest configuration
|
|
71
|
-
INFO creating pgBackRest include directory
|
|
71
|
+
INFO creating pgBackRest include directory: $TMPDIR/2/etc/pgbackrest/conf.d
|
|
72
72
|
INFO creating pgBackRest log directory: $TMPDIR/2/log/pgbackrest
|
|
73
73
|
INFO creating pgBackRest spool directory: $TMPDIR/2/srv/pgbackrest/spool
|
|
74
74
|
INFO creating PostgreSQL log directory: $TMPDIR/2/log/postgresql
|
|
@@ -143,7 +143,7 @@ Cannot create a standby with --slot option
|
|
|
143
143
|
> --pgbackrest-stanza=stnz \
|
|
144
144
|
> --standby-for="host=hst" \
|
|
145
145
|
> --slot=slt
|
|
146
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
146
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
147
147
|
Try 'pglift instance create --help' for help.
|
|
148
148
|
|
|
149
149
|
Error: Invalid value for '--slot': replication slots cannot be set on a standby instance
|
|
@@ -184,7 +184,7 @@ Try to create primary instance with same stanza
|
|
|
184
184
|
$ pglift1 instance create err \
|
|
185
185
|
> --port=$PG3PORT --pgbackrest-stanza=app \
|
|
186
186
|
> --surole-password=s3per --pgbackrest-password=b@ckUp
|
|
187
|
-
Usage: pglift instance create [OPTIONS] NAME
|
|
187
|
+
Usage: pglift instance create [OPTIONS] [NAME]
|
|
188
188
|
Try 'pglift instance create --help' for help.
|
|
189
189
|
|
|
190
190
|
Error: Invalid value for '--pgbackrest-stanza': Stanza 'app' already bound to another instance \(datadir=\$TMPDIR\/1\/srv\/pgsql\/1\d\/pg1\/data\) (re)
|
|
@@ -301,7 +301,8 @@ new slot on the new primary
|
|
|
301
301
|
INFO dropping instance 1\d\/pg1 (re)
|
|
302
302
|
WARNING instance 1\d\/pg1 is already stopped (re)
|
|
303
303
|
INFO deconfiguring pgBackRest stanza 'app'
|
|
304
|
-
INFO deleting PostgreSQL data
|
|
304
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/1\/srv\/pgsql\/1\d\/pg1\/data (re)
|
|
305
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/1\/srv\/pgsql\/1\d\/pg1\/wal (re)
|
|
305
306
|
$ pglift1 instance create pg3 \
|
|
306
307
|
> --standby-for="host=$RUN_PREFIX2/postgresql port=$PG2PORT user=replication" \
|
|
307
308
|
> --standby-password=r3pl \
|
|
@@ -352,20 +353,22 @@ Restore on (new) primary:
|
|
|
352
353
|
INFO dropping instance 1\d\/pg3 (re)
|
|
353
354
|
INFO stopping PostgreSQL 1\d\/pg3 (re)
|
|
354
355
|
INFO deconfiguring pgBackRest stanza 'app'
|
|
355
|
-
INFO deleting PostgreSQL data
|
|
356
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/1\/srv\/pgsql\/1\d\/pg3\/data (re)
|
|
357
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/1\/srv\/pgsql\/1\d\/pg3\/wal (re)
|
|
356
358
|
INFO dropping instance 1\d\/pg2 (re)
|
|
357
359
|
WARNING instance 1\d\/pg2 is already stopped (re)
|
|
358
360
|
INFO deconfiguring pgBackRest stanza 'app'
|
|
359
|
-
INFO deleting PostgreSQL data
|
|
360
|
-
INFO deleting
|
|
361
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/2\/srv\/pgsql\/1\d\/pg2\/data (re)
|
|
362
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/2\/srv\/pgsql\/1\d\/pg2\/wal (re)
|
|
363
|
+
INFO deleting pgBackRest include directory: $TMPDIR/1/etc/pgbackrest/conf.d
|
|
361
364
|
INFO uninstalling base pgBackRest configuration
|
|
362
|
-
INFO deleting pgBackRest log directory
|
|
363
|
-
INFO deleting pgBackRest spool directory
|
|
364
|
-
INFO deleting PostgreSQL log directory
|
|
365
|
-
INFO deleting PostgreSQL socket directory
|
|
366
|
-
INFO deleting pgBackRest include directory
|
|
365
|
+
INFO deleting pgBackRest log directory: $TMPDIR/1/log/pgbackrest
|
|
366
|
+
INFO deleting pgBackRest spool directory: $TMPDIR/1/srv/pgbackrest/spool
|
|
367
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/1/log/postgresql
|
|
368
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/1/run/postgresql
|
|
369
|
+
INFO deleting pgBackRest include directory: $TMPDIR/2/etc/pgbackrest/conf.d
|
|
367
370
|
INFO uninstalling base pgBackRest configuration
|
|
368
|
-
INFO deleting pgBackRest log directory
|
|
369
|
-
INFO deleting pgBackRest spool directory
|
|
370
|
-
INFO deleting PostgreSQL log directory
|
|
371
|
-
INFO deleting PostgreSQL socket directory (no-eol)
|
|
371
|
+
INFO deleting pgBackRest log directory: $TMPDIR/2/log/pgbackrest
|
|
372
|
+
INFO deleting pgBackRest spool directory: $TMPDIR/2/srv/pgbackrest/spool
|
|
373
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/2/log/postgresql
|
|
374
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/2/run/postgresql (no-eol)
|
|
@@ -111,11 +111,13 @@ Try to pause/resume WAL replay on primary
|
|
|
111
111
|
|
|
112
112
|
INFO dropping instance 1\d\/pg1 (re)
|
|
113
113
|
INFO stopping PostgreSQL 1\d\/pg1 (re)
|
|
114
|
-
INFO deleting PostgreSQL data
|
|
114
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/primary\/srv\/pgsql\/1\d\/pg1\/data (re)
|
|
115
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/primary\/srv\/pgsql\/1\d\/pg1\/wal (re)
|
|
115
116
|
INFO dropping instance 1\d\/pg2 (re)
|
|
116
117
|
INFO stopping PostgreSQL 1\d\/pg2 (re)
|
|
117
|
-
INFO deleting PostgreSQL data
|
|
118
|
-
INFO deleting PostgreSQL
|
|
119
|
-
INFO deleting PostgreSQL
|
|
120
|
-
INFO deleting PostgreSQL
|
|
121
|
-
INFO deleting PostgreSQL
|
|
118
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/secondary\/srv\/pgsql\/1\d\/pg2\/data (re)
|
|
119
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/secondary\/srv\/pgsql\/1\d\/pg2\/wal (re)
|
|
120
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/primary/log/postgresql
|
|
121
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/primary/run/postgresql
|
|
122
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/secondary/log/postgresql
|
|
123
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/secondary/run/postgresql (no-eol)
|
|
@@ -41,7 +41,6 @@ Try to create an instance with a non-existing encoding, triggering a failure in
|
|
|
41
41
|
INFO initializing PostgreSQL
|
|
42
42
|
WARNING Command '['*/bin/pg_ctl', 'init', '-D', '$TMPDIR/srv/pgsql/test/data', '-o', '--auth-host=trust --auth-local=trust --encoding=notanencoding --locale=C --username=postgres --waldir=$TMPDIR/srv/pgsql/test/wal']' returned non-zero exit status 1. (glob)
|
|
43
43
|
WARNING reverting: initializing PostgreSQL
|
|
44
|
-
INFO deleting PostgreSQL data and WAL directories
|
|
45
44
|
Error: Command '['*/bin/pg_ctl', 'init', '-D', '$TMPDIR/srv/pgsql/test/data', '-o', '--auth-host=trust --auth-local=trust --encoding=notanencoding --locale=C --username=postgres --waldir=$TMPDIR/srv/pgsql/test/wal']' returned non-zero exit status 1. (glob)
|
|
46
45
|
initdb: error: "notanencoding" is not a valid server encoding name
|
|
47
46
|
pg_ctl: database system initialization failed
|
|
@@ -66,9 +66,11 @@ Create an instance with "password" local authentication method, and upgrade it:
|
|
|
66
66
|
(cleanup)
|
|
67
67
|
INFO dropping instance 1\d\/old (re)
|
|
68
68
|
WARNING instance 1\d\/old is already stopped (re)
|
|
69
|
-
INFO deleting PostgreSQL data
|
|
69
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/srv\/pgsql\/1\d\/old\/data (re)
|
|
70
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/srv\/pgsql\/1\d\/old\/wal (re)
|
|
70
71
|
INFO dropping instance 1\d\/new (re)
|
|
71
72
|
INFO stopping PostgreSQL 1\d\/new (re)
|
|
72
|
-
INFO deleting PostgreSQL data
|
|
73
|
-
INFO deleting PostgreSQL
|
|
74
|
-
INFO deleting PostgreSQL
|
|
73
|
+
INFO deleting PostgreSQL data directory: \$TMPDIR\/srv\/pgsql\/1\d\/new\/data (re)
|
|
74
|
+
INFO deleting PostgreSQL WAL directory: \$TMPDIR\/srv\/pgsql\/1\d\/new\/wal (re)
|
|
75
|
+
INFO deleting PostgreSQL log directory: $TMPDIR/log/postgresql
|
|
76
|
+
INFO deleting PostgreSQL socket directory: $TMPDIR/run/postgresql (no-eol)
|
|
@@ -76,6 +76,8 @@ def test_as_parameters(runner: CliRunner) -> None:
|
|
|
76
76
|
"Options:\n"
|
|
77
77
|
" --exclude-none\n"
|
|
78
78
|
" --nickname TEXT Your secret nickname. [required]\n"
|
|
79
|
+
" --gender [female|male|nonbinary|prefer not to say]\n"
|
|
80
|
+
" Gender. [required]\n"
|
|
79
81
|
" --age AGE Age.\n"
|
|
80
82
|
" --address-street STREET Street lines. (Can be used multiple times.)\n"
|
|
81
83
|
" --address-zip-code ZIP_CODE ZIP code.\n"
|
|
@@ -102,6 +104,7 @@ def test_as_parameters(runner: CliRunner) -> None:
|
|
|
102
104
|
"alice",
|
|
103
105
|
"friend",
|
|
104
106
|
"--exclude-none",
|
|
107
|
+
"--gender=female",
|
|
105
108
|
"--age=42",
|
|
106
109
|
"--address-street=bd montparnasse",
|
|
107
110
|
"--address-street=far far away",
|
|
@@ -115,7 +118,6 @@ def test_as_parameters(runner: CliRunner) -> None:
|
|
|
115
118
|
"--nickname=aaa",
|
|
116
119
|
"--phone-numbers=12345",
|
|
117
120
|
],
|
|
118
|
-
input="alc\nalc\n",
|
|
119
121
|
)
|
|
120
122
|
assert result.exit_code == 0, click_result_traceback(result)
|
|
121
123
|
assert json.loads(result.stderr) == {
|
|
@@ -127,6 +129,7 @@ def test_as_parameters(runner: CliRunner) -> None:
|
|
|
127
129
|
"zip_code": 0,
|
|
128
130
|
"primary": True,
|
|
129
131
|
},
|
|
132
|
+
"gender": "female",
|
|
130
133
|
"age": 42,
|
|
131
134
|
"birth": {"date": "1981-02-18"},
|
|
132
135
|
"is_dead": False,
|
|
@@ -158,6 +161,7 @@ def test_as_parameters(runner: CliRunner) -> None:
|
|
|
158
161
|
[
|
|
159
162
|
"foo",
|
|
160
163
|
"friend",
|
|
164
|
+
"--gender=female",
|
|
161
165
|
"--age=17",
|
|
162
166
|
"--birth-date=1987-06-05",
|
|
163
167
|
"--nickname=aaa",
|
|
@@ -187,6 +191,8 @@ def test_as_parameters_update() -> None:
|
|
|
187
191
|
"\n"
|
|
188
192
|
"Options:\n"
|
|
189
193
|
" --nickname TEXT Your secret nickname. [required]\n"
|
|
194
|
+
" --gender [female|male|nonbinary|prefer not to say]\n"
|
|
195
|
+
" Gender. [required]\n"
|
|
190
196
|
" --age AGE Age.\n"
|
|
191
197
|
" --address-zip-code ZIP_CODE ZIP code.\n"
|
|
192
198
|
" --address-town CITY City.\n"
|
|
@@ -210,16 +216,24 @@ def test_as_parameters_update() -> None:
|
|
|
210
216
|
["alice", "--age=5", "--birthdate=2042-02-31"],
|
|
211
217
|
)
|
|
212
218
|
assert result.exit_code == 2, result.output
|
|
213
|
-
assert "Error: No such option
|
|
219
|
+
assert "Error: No such option '--birthdate'" in result.output
|
|
214
220
|
|
|
215
221
|
result = runner.invoke(
|
|
216
222
|
update_person,
|
|
217
|
-
[
|
|
223
|
+
[
|
|
224
|
+
"alice",
|
|
225
|
+
"other",
|
|
226
|
+
"--nickname=a",
|
|
227
|
+
"--gender=female",
|
|
228
|
+
"--age=5",
|
|
229
|
+
"--birth-date=1987-06-05",
|
|
230
|
+
],
|
|
218
231
|
)
|
|
219
232
|
assert result.exit_code == 0, result.output
|
|
220
233
|
assert json.loads(result.output) == {
|
|
221
234
|
"name": "alice",
|
|
222
235
|
"nickname": "**********",
|
|
236
|
+
"gender": "female",
|
|
223
237
|
"relation": "other",
|
|
224
238
|
"age": 5,
|
|
225
239
|
"birth": {"date": "1987-06-05"},
|
|
@@ -229,7 +243,14 @@ def test_as_parameters_update() -> None:
|
|
|
229
243
|
|
|
230
244
|
result = runner.invoke(
|
|
231
245
|
update_person,
|
|
232
|
-
[
|
|
246
|
+
[
|
|
247
|
+
"alice",
|
|
248
|
+
"friend",
|
|
249
|
+
"--nickname=a",
|
|
250
|
+
"--gender=female",
|
|
251
|
+
"--age=abc",
|
|
252
|
+
"--birth-date=2010-02-03",
|
|
253
|
+
],
|
|
233
254
|
)
|
|
234
255
|
assert result.exit_code == 2
|
|
235
256
|
assert (
|
|
@@ -243,6 +264,7 @@ def test_as_parameters_update() -> None:
|
|
|
243
264
|
"bob",
|
|
244
265
|
"family",
|
|
245
266
|
"--nickname=b",
|
|
267
|
+
"--gender=male",
|
|
246
268
|
"--birth-date=1987-06-05",
|
|
247
269
|
"--address-town=laville",
|
|
248
270
|
"--address-country=be",
|
|
@@ -263,6 +285,7 @@ def test_as_parameters_update() -> None:
|
|
|
263
285
|
"marcel",
|
|
264
286
|
"other",
|
|
265
287
|
"--nickname=a",
|
|
288
|
+
"--gender=male",
|
|
266
289
|
"--age=46",
|
|
267
290
|
"--birth-date=1978-03-09",
|
|
268
291
|
"--add-pet=snoopy",
|
|
@@ -276,6 +299,7 @@ def test_as_parameters_update() -> None:
|
|
|
276
299
|
"name": "marcel",
|
|
277
300
|
"nickname": "**********",
|
|
278
301
|
"relation": "other",
|
|
302
|
+
"gender": "male",
|
|
279
303
|
"age": 46,
|
|
280
304
|
"birth": {"date": "1978-03-09"},
|
|
281
305
|
"pets": [
|
|
@@ -340,6 +364,7 @@ def test_parse_params_as() -> None:
|
|
|
340
364
|
"name": "alice",
|
|
341
365
|
"relation": "other",
|
|
342
366
|
"nickname": "la malice",
|
|
367
|
+
"gender": "female",
|
|
343
368
|
"age": 42,
|
|
344
369
|
"address": address_params,
|
|
345
370
|
"birth": {"date": "1976-05-04"},
|
|
@@ -348,6 +373,7 @@ def test_parse_params_as() -> None:
|
|
|
348
373
|
name="alice",
|
|
349
374
|
nickname="la malice",
|
|
350
375
|
relation="other",
|
|
376
|
+
gender="female",
|
|
351
377
|
age=42,
|
|
352
378
|
address=address,
|
|
353
379
|
birth=models.BirthInformation(date=date(1976, 5, 4)), # type: ignore[call-arg]
|
|
@@ -358,8 +384,60 @@ def test_parse_params_as() -> None:
|
|
|
358
384
|
"name": "alice",
|
|
359
385
|
"relation": "other",
|
|
360
386
|
"nickname": "la malice",
|
|
387
|
+
"gender": "female",
|
|
361
388
|
"age": 42,
|
|
362
389
|
"birth_date": "1976-05-04",
|
|
363
390
|
}
|
|
364
391
|
params_nested.update({f"address_{k}": v for k, v in address_params.items()})
|
|
365
392
|
assert model.parse_params_as(models.Person, params_nested) == person
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def test_as_parameters_unrequired_argument(runner: CliRunner) -> None:
|
|
396
|
+
@click.command("add-product")
|
|
397
|
+
@model.as_parameters(models.Product, "create")
|
|
398
|
+
@click.option("--indent", type=int)
|
|
399
|
+
def add_product(product: models.Product, indent: int) -> None:
|
|
400
|
+
"""Add a new product."""
|
|
401
|
+
click.echo(
|
|
402
|
+
product.model_dump_json(by_alias=True, indent=indent),
|
|
403
|
+
err=True,
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
result = runner.invoke(add_product, ["--help"])
|
|
407
|
+
assert result.exit_code == 0, click_result_traceback(result)
|
|
408
|
+
assert result.stdout == (
|
|
409
|
+
"Usage: add-product [OPTIONS] [NAME]\n"
|
|
410
|
+
"\n"
|
|
411
|
+
" Add a new product.\n"
|
|
412
|
+
"\n"
|
|
413
|
+
"Options:\n"
|
|
414
|
+
" --price TEXT Price. [required]\n"
|
|
415
|
+
" --description DESCRIPTION Description for the product.\n"
|
|
416
|
+
" --indent INTEGER\n"
|
|
417
|
+
" --help Show this message and exit.\n"
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
result = runner.invoke(
|
|
421
|
+
add_product,
|
|
422
|
+
[
|
|
423
|
+
"--price=19.5",
|
|
424
|
+
"--description=useless stuff",
|
|
425
|
+
],
|
|
426
|
+
)
|
|
427
|
+
assert result.exit_code == 0, click_result_traceback(result)
|
|
428
|
+
assert json.loads(result.stderr) == {
|
|
429
|
+
"description": "useless stuff",
|
|
430
|
+
"name": "Unnamed product",
|
|
431
|
+
"price": 19.5,
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
result = runner.invoke(
|
|
435
|
+
add_product,
|
|
436
|
+
["--price=19.5", "--description=useless stuff", "The Product Name"],
|
|
437
|
+
)
|
|
438
|
+
assert result.exit_code == 0, click_result_traceback(result)
|
|
439
|
+
assert json.loads(result.stderr) == {
|
|
440
|
+
"description": "useless stuff",
|
|
441
|
+
"name": "The Product Name",
|
|
442
|
+
"price": 19.5,
|
|
443
|
+
}
|
|
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
|
|
File without changes
|