diff --git a/.idea/runConfigurations/kiwi_next.xml b/.idea/runConfigurations/kiwi_next.xml
index fe75345..49cad48 100644
--- a/.idea/runConfigurations/kiwi_next.xml
+++ b/.idea/runConfigurations/kiwi_next.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/example/hello-world.project/docker-compose.yml b/example/hello-world.project/docker-compose.yml
index 9a7ea1e..cdb4328 100644
--- a/example/hello-world.project/docker-compose.yml
+++ b/example/hello-world.project/docker-compose.yml
@@ -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:
diff --git a/kiwi_scp/commands/cmd_list.py b/kiwi_scp/commands/cmd_list.py
index 819b6da..0918b0c 100644
--- a/kiwi_scp/commands/cmd_list.py
+++ b/kiwi_scp/commands/cmd_list.py
@@ -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}")
diff --git a/kiwi_scp/instance.py b/kiwi_scp/instance.py
index bcc2c6f..4eda01f 100644
--- a/kiwi_scp/instance.py
+++ b/kiwi_scp/instance.py
@@ -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:
- host_part = volume.split(":")[0]
- confdir = _RE_CONFDIR.match(host_part)
+ for volume in self.description["volumes"]:
+ host_part = volume.split(":")[0]
+ 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)
diff --git a/tests/test_instance.py b/tests/test_instance.py
index 68799a5..8e4f47e 100644
--- a/tests/test_instance.py
+++ b/tests/test_instance.py
@@ -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()