Compare commits
5 Commits
Author | SHA1 | Date |
---|---|---|
jpk | cbb8b7bbfd | |
jpk | 36db6d8034 | |
jpk | 85c847200c | |
jpk | 74e8410af6 | |
jpk | 4c7bd3cf17 |
|
@ -40,9 +40,10 @@ Options:
|
||||||
--help Show this message and exit.
|
--help Show this message and exit.
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
control
|
control run docker-compose commands
|
||||||
edit
|
edit edit the compose file
|
||||||
list
|
list list available services
|
||||||
|
update pull the latest service images and restart
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__version__ = "0.3.3"
|
__version__ = "0.4.0"
|
||||||
|
|
68
doxy/cli.py
68
doxy/cli.py
|
@ -3,6 +3,7 @@ from pathlib import Path
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from rich import print
|
from rich import print
|
||||||
|
from rich.rule import Rule
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
from doxy import services
|
from doxy import services
|
||||||
|
@ -23,9 +24,9 @@ def main(ctx):
|
||||||
ctx.obj["CONFIG"] = CONFIG
|
ctx.obj["CONFIG"] = CONFIG
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command(help="list available services")
|
||||||
@click.pass_context
|
def list():
|
||||||
def list(ctx):
|
print(Rule(f"Listing services"))
|
||||||
tree = Tree("[bold]Available Services")
|
tree = Tree("[bold]Available Services")
|
||||||
for service in services.find_services(Path(CONFIG.root_directory)):
|
for service in services.find_services(Path(CONFIG.root_directory)):
|
||||||
tree.add(service)
|
tree.add(service)
|
||||||
|
@ -40,39 +41,64 @@ def complete_service_name(ctx, param, incomplete):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command(help="edit the compose file")
|
||||||
@click.argument("service", nargs=1, shell_complete=complete_service_name)
|
@click.argument("service", nargs=1, shell_complete=complete_service_name)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
|
@services.only_if_service_exists
|
||||||
def edit(ctx, service):
|
def edit(ctx, service):
|
||||||
try:
|
print(Rule(f"Editing {service}"))
|
||||||
compose_file = services.get_compose_file(
|
compose_file = services.get_compose_file(
|
||||||
Path(ctx.obj["CONFIG"].root_directory) / service
|
Path(ctx.obj["CONFIG"].root_directory) / service
|
||||||
)
|
)
|
||||||
click.edit(filename=Path(compose_file))
|
click.edit(filename=Path(compose_file))
|
||||||
except FileNotFoundError:
|
|
||||||
click.echo(f"Service `{service}' not found", sys.stderr)
|
|
||||||
ctx.abort()
|
|
||||||
|
|
||||||
|
|
||||||
@click.command(
|
@click.command(
|
||||||
context_settings=dict(
|
context_settings=dict(
|
||||||
ignore_unknown_options=True,
|
ignore_unknown_options=True,
|
||||||
)
|
),
|
||||||
|
help="run docker-compose commands",
|
||||||
)
|
)
|
||||||
@click.argument("service", nargs=1, shell_complete=complete_service_name)
|
@click.argument("service", nargs=1, shell_complete=complete_service_name)
|
||||||
@click.argument("command", nargs=-1)
|
@click.argument("command", nargs=-1)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
|
@services.only_if_service_exists
|
||||||
def control(ctx, service, command):
|
def control(ctx, service, command):
|
||||||
try:
|
print(Rule(f"Controlling {service}"))
|
||||||
compose_file = services.get_compose_file(
|
compose_file = services.get_compose_file(
|
||||||
Path(ctx.obj["CONFIG"].root_directory) / service
|
Path(ctx.obj["CONFIG"].root_directory) / service
|
||||||
)
|
)
|
||||||
services.docker_compose_command(command, compose_file)
|
services.docker_compose_command(command, compose_file)
|
||||||
except FileNotFoundError:
|
|
||||||
click.echo(f"Service `{service}' not found", sys.stderr)
|
|
||||||
ctx.abort()
|
@click.command("update", help="pull the latest service images and restart")
|
||||||
|
@click.argument("service", nargs=1, shell_complete=complete_service_name)
|
||||||
|
@click.option(
|
||||||
|
"--remove", "-r", is_flag=True, default=False, help="remove unused volumes"
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
@services.only_if_service_exists
|
||||||
|
def update(ctx, service, remove):
|
||||||
|
compose_file = services.get_compose_file(
|
||||||
|
Path(ctx.obj["CONFIG"].root_directory) / service
|
||||||
|
)
|
||||||
|
print(Rule(f"Updating {service}"))
|
||||||
|
services.docker_compose_command(
|
||||||
|
[
|
||||||
|
["stop", "down"][remove],
|
||||||
|
],
|
||||||
|
compose_file,
|
||||||
|
)
|
||||||
|
services.docker_compose_command(
|
||||||
|
[
|
||||||
|
"pull",
|
||||||
|
],
|
||||||
|
compose_file,
|
||||||
|
)
|
||||||
|
services.docker_compose_command(["up", "-d"], compose_file)
|
||||||
|
|
||||||
|
|
||||||
main.add_command(list)
|
main.add_command(list)
|
||||||
main.add_command(edit)
|
main.add_command(edit)
|
||||||
main.add_command(control)
|
main.add_command(control)
|
||||||
|
main.add_command(update)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from xdg import xdg_config_home
|
from click import get_app_dir
|
||||||
from yamldataclassconfig import create_file_path_field
|
from yamldataclassconfig import create_file_path_field
|
||||||
from yamldataclassconfig.config import YamlDataClassConfig
|
from yamldataclassconfig.config import YamlDataClassConfig
|
||||||
|
|
||||||
|
@ -11,6 +11,4 @@ class Config(YamlDataClassConfig):
|
||||||
root_directory: str = ""
|
root_directory: str = ""
|
||||||
compose_executable: str = ""
|
compose_executable: str = ""
|
||||||
|
|
||||||
FILE_PATH: Path = create_file_path_field(
|
FILE_PATH: Path = create_file_path_field(Path(get_app_dir("doxy")) / "config.yml")
|
||||||
Path(xdg_config_home()) / "doxy/config.yml"
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,11 +1,31 @@
|
||||||
import glob
|
import glob
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from functools import update_wrapper
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
|
||||||
|
def only_if_service_exists(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
ctx = args[0]
|
||||||
|
service = kwargs["service"]
|
||||||
|
try:
|
||||||
|
compose_file = get_compose_file(
|
||||||
|
Path(ctx.obj["CONFIG"].root_directory) / service
|
||||||
|
)
|
||||||
|
if not compose_file.exists():
|
||||||
|
raise FileNotFoundError()
|
||||||
|
except FileNotFoundError:
|
||||||
|
click.echo(f"Service `{service}' not found", sys.stderr)
|
||||||
|
ctx.abort()
|
||||||
|
return ctx.invoke(fn, *args, **kwargs)
|
||||||
|
|
||||||
|
return update_wrapper(wrapper, fn)
|
||||||
|
|
||||||
|
|
||||||
def find_services(root: Path) -> List[str]:
|
def find_services(root: Path) -> List[str]:
|
||||||
return [_.split("/")[0] for _ in glob.glob("*/docker-compose.y*ml", root_dir=root)]
|
return [_.split("/")[0] for _ in glob.glob("*/docker-compose.y*ml", root_dir=root)]
|
||||||
|
|
||||||
|
|
|
@ -314,14 +314,6 @@ category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "xdg"
|
|
||||||
version = "5.1.1"
|
|
||||||
description = "Variables defined by the XDG Base Directory Specification"
|
|
||||||
category = "main"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6,<4.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yamldataclassconfig"
|
name = "yamldataclassconfig"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -337,7 +329,7 @@ pyyaml = "*"
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.10"
|
python-versions = "^3.10"
|
||||||
content-hash = "170eebbe419588237954ba9ca730e93d253a3c4baba92e4a26a88eff89fce121"
|
content-hash = "6bdfca3a7a9351058dae359dae3d4333b91187a9a5535eb3fc49d04ecb771c3c"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
atomicwrites = []
|
atomicwrites = []
|
||||||
|
@ -417,5 +409,4 @@ typing-extensions = []
|
||||||
typing-inspect = []
|
typing-inspect = []
|
||||||
virtualenv = []
|
virtualenv = []
|
||||||
wcwidth = []
|
wcwidth = []
|
||||||
xdg = []
|
|
||||||
yamldataclassconfig = []
|
yamldataclassconfig = []
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "doxy"
|
name = "doxy"
|
||||||
version = "0.3.3"
|
version = "0.4.0"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["jpk <jpk@goatpr0n.de>"]
|
authors = ["jpk <jpk@goatpr0n.de>"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -12,7 +12,6 @@ python = "^3.10"
|
||||||
click = "^8.1.3"
|
click = "^8.1.3"
|
||||||
rich = "^13.0.1"
|
rich = "^13.0.1"
|
||||||
yamldataclassconfig = "^1.5.0"
|
yamldataclassconfig = "^1.5.0"
|
||||||
xdg = "^5.1.1"
|
|
||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
doxy = "doxy.cli:main"
|
doxy = "doxy.cli:main"
|
||||||
|
|
Loading…
Reference in New Issue