arcsecond 4.0.0__tar.gz → 4.2.1__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.
- {arcsecond-4.0.0 → arcsecond-4.2.1}/PKG-INFO +3 -2
- {arcsecond-4.0.0 → arcsecond-4.2.1}/README.md +2 -1
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cli.py +8 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/docgen.py +48 -2
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/__init__.py +7 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/backups.py +34 -26
- arcsecond-4.2.1/arcsecond/hosting/check.py +764 -0
- arcsecond-4.2.1/arcsecond/hosting/composedoc.py +411 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/lifecycle.py +1 -1
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/local.py +44 -4
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/stack.py +1 -2
- arcsecond-4.2.1/arcsecond/hosting/token.py +184 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/pyproject.toml +1 -1
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_docgen.py +13 -0
- arcsecond-4.2.1/tests/test_hosting_backups_install_dir.py +89 -0
- arcsecond-4.2.1/tests/test_hosting_check.py +447 -0
- arcsecond-4.2.1/tests/test_hosting_composedoc.py +110 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_hosting_local.py +3 -1
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_hosting_stack.py +1 -1
- arcsecond-4.2.1/tests/test_hosting_token.py +163 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/uv.lock +1 -1
- {arcsecond-4.0.0 → arcsecond-4.2.1}/.docker/Dockerfile_postgres +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/.docker/Dockerfile_redis +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/.flake8 +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/.gitattributes +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/.github/dependabot.yml +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/.github/workflows/pythonpublish.yml +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/.github/workflows/tests.yml +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/.gitignore +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/LICENSE +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/Makefile +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/__version__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/alpaca/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/alpaca/commands.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/alpaca/dome_probe.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/alpaca/probe.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/alpaca/telescope_probe.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/api/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/api/config.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/api/constants.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/api/endpoint.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/api/main.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/api/resources.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/auth.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/resources.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/constants.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/context.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/datafiles/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/datafiles/context.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/datafiles/errors.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/datafiles/uploader.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/datafiles/utils.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/errors.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/logger.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/uploader.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/utils.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploader/walker.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/cloud/uploads.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/errors.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/database.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/docker/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/docker/docker-compose.yml +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/hosting/utils.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/autostart.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/commands.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/detection.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/proxy.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/registry.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/runtime.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/sources/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/sources/base.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/sources/filewatch.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/sources/mdns.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/sources/network.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/sources/opencv.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/imagesources/store.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/options.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/arcsecond/targets.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/examples/example_upload_files.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/requirements.txt +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/setup.cfg +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/setup.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/sonar-project.properties +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/api/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/api/test_api.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/api/test_api_endpoint.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/api/test_config.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/api/test_config_pointer.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/api/test_targets.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/cloud/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/cloud/uploader/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/cloud/uploader/datafiles/__init__.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/cloud/uploader/datafiles/test_uploader_errors.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/cloud/uploader/datafiles/test_uploader_full_process.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/cloud/uploader/datafiles/test_uploader_init.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/cloud/uploader/datafiles/test_uploader_prepare.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/cloud/uploader/datafiles/test_uploader_upload.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/conftest.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/fixtures/file1.fits +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_alpaca_probe.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_cli.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_cli_api_commands.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_hosting_backups_restore.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_hosting_database.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_hosting_lifecycle.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_hosting_utils_secret_key.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_imagesources_autostart.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_imagesources_commands.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_imagesources_detection.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_imagesources_mdns.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_imagesources_network.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_imagesources_proxy.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_imagesources_store.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_imagesources_webcam.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/test_targets_planning.py +0 -0
- {arcsecond-4.0.0 → arcsecond-4.2.1}/tests/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: arcsecond
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.2.1
|
|
4
4
|
Summary: CLI for arcsecond.io
|
|
5
5
|
Project-URL: Homepage, https://github.com/arcsecond-io/cli
|
|
6
6
|
Project-URL: Issues, https://github.com/arcsecond-io/cli/issues
|
|
@@ -56,7 +56,7 @@ The Command-line interface (CLI) for Arcsecond. It can be used as Python
|
|
|
56
56
|
module too. The CLI makes it easy to login/register and access Arcsecond resources,
|
|
57
57
|
public and private ones.
|
|
58
58
|
|
|
59
|
-
[Read the docs](https://docs.arcsecond.io/cli)
|
|
59
|
+
[Read the docs](https://docs.arcsecond.io/reference/cli)
|
|
60
60
|
|
|
61
61
|
## Running Arcsecond.local
|
|
62
62
|
|
|
@@ -65,6 +65,7 @@ The CLI owns the whole lifecycle of a self-hosted installation; there is no
|
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
$ arcsecond setup --lan-host 192.168.1.42 # writes .env and docker-compose.yml
|
|
68
|
+
$ arcsecond token set # the access token Arcsecond gave you, once per machine (setup asks too)
|
|
68
69
|
$ arcsecond start # first run downloads the images
|
|
69
70
|
$ arcsecond status
|
|
70
71
|
$ arcsecond logs backend -f
|
|
@@ -7,7 +7,7 @@ The Command-line interface (CLI) for Arcsecond. It can be used as Python
|
|
|
7
7
|
module too. The CLI makes it easy to login/register and access Arcsecond resources,
|
|
8
8
|
public and private ones.
|
|
9
9
|
|
|
10
|
-
[Read the docs](https://docs.arcsecond.io/cli)
|
|
10
|
+
[Read the docs](https://docs.arcsecond.io/reference/cli)
|
|
11
11
|
|
|
12
12
|
## Running Arcsecond.local
|
|
13
13
|
|
|
@@ -16,6 +16,7 @@ The CLI owns the whole lifecycle of a self-hosted installation; there is no
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
$ arcsecond setup --lan-host 192.168.1.42 # writes .env and docker-compose.yml
|
|
19
|
+
$ arcsecond token set # the access token Arcsecond gave you, once per machine (setup asks too)
|
|
19
20
|
$ arcsecond start # first run downloads the images
|
|
20
21
|
$ arcsecond status
|
|
21
22
|
$ arcsecond logs backend -f
|
|
@@ -12,6 +12,7 @@ from arcsecond.cloud import (
|
|
|
12
12
|
from arcsecond.docgen import docs
|
|
13
13
|
from arcsecond.hosting import (
|
|
14
14
|
backups,
|
|
15
|
+
check_cmd,
|
|
15
16
|
db,
|
|
16
17
|
logs,
|
|
17
18
|
restart,
|
|
@@ -19,6 +20,7 @@ from arcsecond.hosting import (
|
|
|
19
20
|
start,
|
|
20
21
|
status,
|
|
21
22
|
stop,
|
|
23
|
+
token_group,
|
|
22
24
|
update,
|
|
23
25
|
)
|
|
24
26
|
from arcsecond.imagesources import commands as imagesources
|
|
@@ -72,6 +74,12 @@ main.add_command(status)
|
|
|
72
74
|
main.add_command(logs)
|
|
73
75
|
main.add_command(update)
|
|
74
76
|
|
|
77
|
+
# Is it reachable from the rest of the observatory, and if not, why not.
|
|
78
|
+
main.add_command(check_cmd)
|
|
79
|
+
|
|
80
|
+
# The access token Arcsecond gave the observatory, once per machine.
|
|
81
|
+
main.add_command(token_group)
|
|
82
|
+
|
|
75
83
|
# Browse and restore Arcsecond.local DB backups.
|
|
76
84
|
main.add_command(backups)
|
|
77
85
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""The command reference, generated from the command tree itself.
|
|
2
2
|
|
|
3
|
-
`arcsecond docs commands --out
|
|
3
|
+
`arcsecond docs commands --out docs/reference/commands` writes one Markdown page per top-level
|
|
4
4
|
command — usage, help, arguments, options, subcommands — plus an index and a
|
|
5
5
|
machine-readable `commands.json`, every page carrying the documentation
|
|
6
6
|
site's frontmatter with `source: generated`.
|
|
@@ -22,6 +22,7 @@ committed copy honest.
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
24
|
import html
|
|
25
|
+
import inspect
|
|
25
26
|
import json
|
|
26
27
|
import textwrap
|
|
27
28
|
from pathlib import Path
|
|
@@ -54,8 +55,13 @@ def _render_help(text: Optional[str]) -> List[str]:
|
|
|
54
55
|
Click marks a paragraph it must not rewrap with a backspace character —
|
|
55
56
|
that is how command examples are written in a docstring — and such a
|
|
56
57
|
paragraph is exactly what belongs in a code fence here."""
|
|
58
|
+
# Dedented the way click dedents it for --help. Python 3.13 strips a
|
|
59
|
+
# docstring's indentation at compile time and 3.12 does not, so without
|
|
60
|
+
# this the same source generated two different pages depending on the
|
|
61
|
+
# interpreter that ran it.
|
|
62
|
+
text = inspect.cleandoc(text or "")
|
|
57
63
|
lines: List[str] = []
|
|
58
|
-
for paragraph in
|
|
64
|
+
for paragraph in text.split("\n\n"):
|
|
59
65
|
if not paragraph.strip():
|
|
60
66
|
continue
|
|
61
67
|
if paragraph.lstrip().startswith("\b"):
|
|
@@ -293,3 +299,43 @@ def docs_commands(ctx, out, check):
|
|
|
293
299
|
)
|
|
294
300
|
written = write(files, Path(out))
|
|
295
301
|
click.echo(f"Wrote {len(written)} files to {out}")
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
@docs.command(
|
|
305
|
+
name="compose",
|
|
306
|
+
help="Write the services and environment reference from the packaged compose template.",
|
|
307
|
+
)
|
|
308
|
+
@click.option(
|
|
309
|
+
"--out",
|
|
310
|
+
"out",
|
|
311
|
+
type=click.Path(file_okay=False),
|
|
312
|
+
default=None,
|
|
313
|
+
help="Folder to write into.",
|
|
314
|
+
)
|
|
315
|
+
@click.option(
|
|
316
|
+
"--check",
|
|
317
|
+
"check",
|
|
318
|
+
type=click.Path(file_okay=False, exists=True),
|
|
319
|
+
default=None,
|
|
320
|
+
help="Compare against this folder instead of writing; exit 1 if it is out of date.",
|
|
321
|
+
)
|
|
322
|
+
def docs_compose(out, check):
|
|
323
|
+
from arcsecond.hosting import composedoc
|
|
324
|
+
|
|
325
|
+
files = composedoc.generate(__version__.__version__)
|
|
326
|
+
if check:
|
|
327
|
+
changed = differences(files, Path(check))
|
|
328
|
+
if changed:
|
|
329
|
+
click.echo("The services/environment reference is out of date:")
|
|
330
|
+
for name in changed:
|
|
331
|
+
click.echo(f" {name}")
|
|
332
|
+
click.echo("\nRegenerate it: arcsecond docs compose --out " + check)
|
|
333
|
+
raise SystemExit(1)
|
|
334
|
+
click.echo(f"The services/environment reference in {check} is up to date.")
|
|
335
|
+
return
|
|
336
|
+
if not out:
|
|
337
|
+
raise click.UsageError(
|
|
338
|
+
"Give --out FOLDER to write, or --check FOLDER to verify."
|
|
339
|
+
)
|
|
340
|
+
written = write(files, Path(out))
|
|
341
|
+
click.echo(f"Wrote {len(written)} files to {out}")
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
from .backups import backups
|
|
2
|
+
|
|
3
|
+
# check_cmd, not check: `check` is also this package's module of that name,
|
|
4
|
+
# and re-exporting the command under it would shadow the module for tests.
|
|
5
|
+
from .check import check_cmd
|
|
2
6
|
from .database import db
|
|
3
7
|
from .lifecycle import logs, restart, start, status, stop, update
|
|
4
8
|
from .local import setup
|
|
9
|
+
from .token import token_group
|
|
5
10
|
|
|
6
11
|
# Re-exported: the command groups `arcsecond.cli` mounts.
|
|
7
12
|
__all__ = [
|
|
8
13
|
"backups",
|
|
14
|
+
"check_cmd",
|
|
9
15
|
"db",
|
|
10
16
|
"setup",
|
|
17
|
+
"token_group",
|
|
11
18
|
"start",
|
|
12
19
|
"stop",
|
|
13
20
|
"restart",
|
|
@@ -10,9 +10,13 @@ from pathlib import Path
|
|
|
10
10
|
|
|
11
11
|
import click
|
|
12
12
|
|
|
13
|
+
from arcsecond.errors import ArcsecondError
|
|
13
14
|
from arcsecond.options import basic_options
|
|
14
15
|
|
|
15
|
-
from .
|
|
16
|
+
from . import stack
|
|
17
|
+
from .lifecycle import dir_option
|
|
18
|
+
from .utils import _container_running
|
|
19
|
+
from .utils import _read_env_value as _read_env_value_from
|
|
16
20
|
|
|
17
21
|
DB_CONTAINER = "arcsecond-db"
|
|
18
22
|
API_CONTAINER = "arcsecond-api"
|
|
@@ -44,8 +48,16 @@ STATUS_BROKEN = "broken"
|
|
|
44
48
|
GZIP_MAGIC = b"\x1f\x8b"
|
|
45
49
|
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
# The installation the current command works on, resolved once by
|
|
52
|
+
# _ensure_install_dir: --dir, else the current folder, else the folder
|
|
53
|
+
# `arcsecond setup` last ran in (see stack.resolve_install_dir).
|
|
54
|
+
_install = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _read_env_value(key):
|
|
58
|
+
"""A value from the installation's .env — the resolved one, not whatever
|
|
59
|
+
happens to be in the current folder."""
|
|
60
|
+
return _read_env_value_from(key, _install.env_path if _install else None)
|
|
49
61
|
|
|
50
62
|
|
|
51
63
|
def _backups_dir():
|
|
@@ -55,18 +67,13 @@ def _backups_dir():
|
|
|
55
67
|
return Path(shared) / "db_backups"
|
|
56
68
|
|
|
57
69
|
|
|
58
|
-
def
|
|
59
|
-
click.echo(
|
|
60
|
-
"Could not find an Arcsecond.local installation in the current directory.\n"
|
|
61
|
-
"Run `arcsecond backups ...` from the directory that contains your "
|
|
62
|
-
"docker-compose.yml and .env files (the one you used for `arcsecond setup`)."
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def _ensure_install_dir():
|
|
70
|
+
def _ensure_install_dir(directory=None):
|
|
67
71
|
"""Return the backups dir, or None after printing a clear error."""
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
global _install
|
|
73
|
+
try:
|
|
74
|
+
_install = stack.resolve_install_dir(directory)
|
|
75
|
+
except ArcsecondError as e:
|
|
76
|
+
click.echo(str(e))
|
|
70
77
|
return None
|
|
71
78
|
backups_dir = _backups_dir()
|
|
72
79
|
if backups_dir is None:
|
|
@@ -78,9 +85,8 @@ def _ensure_install_dir():
|
|
|
78
85
|
if not backups_dir.exists():
|
|
79
86
|
click.echo(
|
|
80
87
|
f"No backups directory found at: {backups_dir.resolve()}\n"
|
|
81
|
-
"Make sure
|
|
82
|
-
"
|
|
83
|
-
"started at least once — the boot-time backup is the first to appear."
|
|
88
|
+
"Make sure the backend has been started at least once — the boot-time "
|
|
89
|
+
"backup is the first to appear."
|
|
84
90
|
)
|
|
85
91
|
return None
|
|
86
92
|
return backups_dir
|
|
@@ -569,9 +575,10 @@ def _print_destination_section(items):
|
|
|
569
575
|
@backups.command(
|
|
570
576
|
name="list", help="List available DB backups with compatibility status."
|
|
571
577
|
)
|
|
578
|
+
@dir_option
|
|
572
579
|
@basic_options
|
|
573
|
-
def list_cmd():
|
|
574
|
-
backups_dir = _ensure_install_dir()
|
|
580
|
+
def list_cmd(directory):
|
|
581
|
+
backups_dir = _ensure_install_dir(directory)
|
|
575
582
|
if backups_dir is None:
|
|
576
583
|
sys.exit(1)
|
|
577
584
|
|
|
@@ -624,9 +631,10 @@ def list_cmd():
|
|
|
624
631
|
|
|
625
632
|
@backups.command(name="inspect", help="Show detailed info about a backup.")
|
|
626
633
|
@click.argument("ref", required=True)
|
|
634
|
+
@dir_option
|
|
627
635
|
@basic_options
|
|
628
|
-
def inspect_cmd(ref):
|
|
629
|
-
backups_dir = _ensure_install_dir()
|
|
636
|
+
def inspect_cmd(directory, ref):
|
|
637
|
+
backups_dir = _ensure_install_dir(directory)
|
|
630
638
|
if backups_dir is None:
|
|
631
639
|
sys.exit(1)
|
|
632
640
|
|
|
@@ -1085,9 +1093,8 @@ def _stop_services(dry_run):
|
|
|
1085
1093
|
|
|
1086
1094
|
def _start_services(dry_run):
|
|
1087
1095
|
"""Bring the stack back. Compose restarts dependents; by name if it is absent."""
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
_run(["docker", "compose", "up", "-d"], dry_run)
|
|
1096
|
+
if _install is not None and _install.compose_path.exists():
|
|
1097
|
+
_run(stack.compose_command(_install, "up", "-d", "--remove-orphans"), dry_run)
|
|
1091
1098
|
else:
|
|
1092
1099
|
for name in reversed(SERVICES_TO_STOP):
|
|
1093
1100
|
_run(["docker", "start", name], dry_run, capture_output=True, text=True)
|
|
@@ -1149,9 +1156,10 @@ def _perform_restore(path, backups_dir, dry_run, no_safety_backup):
|
|
|
1149
1156
|
@click.option(
|
|
1150
1157
|
"--no-safety-backup", is_flag=True, help="Skip the pre-restore safety snapshot."
|
|
1151
1158
|
)
|
|
1159
|
+
@dir_option
|
|
1152
1160
|
@basic_options
|
|
1153
|
-
def restore_cmd(ref, force, dry_run, no_safety_backup):
|
|
1154
|
-
backups_dir = _ensure_install_dir()
|
|
1161
|
+
def restore_cmd(directory, ref, force, dry_run, no_safety_backup):
|
|
1162
|
+
backups_dir = _ensure_install_dir(directory)
|
|
1155
1163
|
if backups_dir is None:
|
|
1156
1164
|
sys.exit(1)
|
|
1157
1165
|
|