basic "kiwi list" command
This commit is contained in:
parent
1dcf542c6d
commit
a5a0ca9a63
5 changed files with 65 additions and 33 deletions
|
@ -12,7 +12,7 @@
|
|||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="kiwi_scp.scripts.kiwi_next" />
|
||||
<option name="PARAMETERS" value="list" />
|
||||
<option name="PARAMETERS" value="list hello-world.project web" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="true" />
|
||||
|
|
|
@ -10,20 +10,20 @@ networks:
|
|||
name: ${KIWI_HUB_NAME}
|
||||
|
||||
services:
|
||||
# simple loop producing (rather boring) logs
|
||||
greeter:
|
||||
# simple loop producing (rather boring) logs
|
||||
image: alpine:latest
|
||||
command: sh -c 'LOOP=1; while :; do echo Hello World "$$LOOP"; LOOP=$$(($$LOOP + 1)); sleep 10; done'
|
||||
|
||||
# basic webserver listening on localhost:8080
|
||||
web:
|
||||
# basic webserver listening on localhost:8080
|
||||
build: web
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8080:80"
|
||||
|
||||
# internal mariadb (mysql) instance with persistent storage
|
||||
db:
|
||||
# internal mariadb (mysql) instance with persistent storage
|
||||
image: mariadb:10
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
@ -33,8 +33,8 @@ services:
|
|||
volumes:
|
||||
- "${TARGETDIR}/db:/var/lib/mysql"
|
||||
|
||||
# admin interface for databases
|
||||
adminer:
|
||||
# admin interface for databases
|
||||
image: adminer:standalone
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
@ -45,8 +45,8 @@ services:
|
|||
ports:
|
||||
- "8081:8080"
|
||||
|
||||
# Another webserver just to show off the ${CONFDIR} variable
|
||||
another-web:
|
||||
# Another webserver just to show off the ${CONFDIR} variable
|
||||
image: nginx:stable-alpine
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
import click
|
||||
|
||||
from kiwi_scp.misc import service_command
|
||||
from ..instance import Instance, pass_instance
|
||||
from ..misc import service_command
|
||||
|
||||
|
||||
@click.command(
|
||||
"list",
|
||||
short_help="Inspect a kiwi-scp instance",
|
||||
)
|
||||
@pass_instance
|
||||
@service_command
|
||||
def cmd(project: str, service: str):
|
||||
def cmd(ctx: Instance, project: str, service: str):
|
||||
"""List projects in this instance, services inside a project or service(s) inside a project"""
|
||||
print(f"project: {project!r}, service: {service!r}")
|
||||
if project is not None:
|
||||
if service is not None:
|
||||
print(f"{ctx.get_service(project, service)}")
|
||||
else:
|
||||
print(f"services: {ctx.get_services(project)}")
|
||||
else:
|
||||
print(f"projects: {ctx.config.projects}")
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import functools
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import List, Dict, Any, Generator
|
||||
from typing import Generator, List
|
||||
|
||||
import attr
|
||||
import click
|
||||
from ruamel.yaml.comments import CommentedMap
|
||||
|
||||
from ._constants import COMPOSE_FILE_NAME
|
||||
from .config import KiwiConfig
|
||||
|
@ -16,27 +17,40 @@ _RE_CONFDIR = re.compile(r"^\s*\$(?:CONFDIR|{CONFDIR})/+(.*)$", flags=re.UNICODE
|
|||
@attr.s
|
||||
class Service:
|
||||
name: str = attr.ib()
|
||||
configs: List[Path] = attr.ib()
|
||||
description: CommentedMap = attr.ib()
|
||||
|
||||
@classmethod
|
||||
def from_description(cls, name: str, description: Dict[str, Any]):
|
||||
configs: List[Path] = []
|
||||
def __str__(self) -> str:
|
||||
return YAML().dump({
|
||||
"service": {
|
||||
self.name: self.description
|
||||
}
|
||||
})
|
||||
|
||||
if "volumes" in description:
|
||||
volumes: List[str] = description["volumes"]
|
||||
@property
|
||||
def configs(self) -> Generator[Path, None, None]:
|
||||
if "volumes" not in self.description:
|
||||
return
|
||||
|
||||
for volume in volumes:
|
||||
for volume in self.description["volumes"]:
|
||||
host_part = volume.split(":")[0]
|
||||
confdir = _RE_CONFDIR.match(host_part)
|
||||
cd_match = _RE_CONFDIR.match(host_part)
|
||||
|
||||
if confdir:
|
||||
configs.append(Path(confdir.group(1)))
|
||||
if cd_match:
|
||||
yield cd_match.group(1)
|
||||
|
||||
return cls(
|
||||
name=name,
|
||||
configs=configs,
|
||||
)
|
||||
|
||||
@attr.s
|
||||
class Services:
|
||||
project_name: str = attr.ib()
|
||||
content: List[Service] = attr.ib()
|
||||
|
||||
def __str__(self) -> str:
|
||||
return YAML().dump({
|
||||
"services": {
|
||||
service.name: service.description
|
||||
for service in self.content
|
||||
}
|
||||
})
|
||||
|
||||
@attr.s
|
||||
class Instance:
|
||||
|
@ -48,19 +62,24 @@ class Instance:
|
|||
|
||||
return KiwiConfig.from_directory(self.directory)
|
||||
|
||||
@classmethod
|
||||
@staticmethod
|
||||
@functools.lru_cache(maxsize=10)
|
||||
def _parse_compose_file(cls, directory: Path):
|
||||
def _parse_compose_file(directory: Path):
|
||||
with open(directory.joinpath(COMPOSE_FILE_NAME), "r") as cf:
|
||||
return YAML().load(cf)
|
||||
|
||||
def get_services(self, project_name: str) -> Generator[Service, None, None]:
|
||||
def get_services(self, project_name: str) -> Services:
|
||||
yml = Instance._parse_compose_file(self.directory.joinpath(project_name))
|
||||
|
||||
return (
|
||||
Service.from_description(name, description)
|
||||
return Services(project_name, [
|
||||
Service(name, description)
|
||||
for name, description in yml["services"].items()
|
||||
)
|
||||
])
|
||||
|
||||
def get_service(self, project_name: str, service_name: str) -> Service:
|
||||
yml = Instance._parse_compose_file(self.directory.joinpath(project_name))
|
||||
|
||||
return Service(service_name, yml["services"][service_name])
|
||||
|
||||
|
||||
pass_instance = click.make_pass_decorator(Instance, ensure=True)
|
||||
|
|
|
@ -14,9 +14,14 @@ class TestDefault:
|
|||
|
||||
assert p.name == "hello-world.project"
|
||||
|
||||
s = list(i.get_services(p.name))
|
||||
ss = list(i.get_services(p.name))
|
||||
|
||||
assert len(s) == 5
|
||||
assert len(ss) == 5
|
||||
|
||||
s = ss[0]
|
||||
|
||||
assert s.name == "greeter"
|
||||
assert s == i.get_service(p.name, s.name)
|
||||
|
||||
def test_empty(self):
|
||||
i = Instance()
|
||||
|
|
Loading…
Reference in a new issue