KiwiCommand API
This commit is contained in:
parent
52f0e9b8a3
commit
2e37291a68
4 changed files with 71 additions and 62 deletions
|
@ -5,7 +5,7 @@ from typing import List, Tuple, Iterable, Any, Type
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from ..instance import Instance
|
from ..instance import Instance, Project, Services
|
||||||
|
|
||||||
|
|
||||||
class KiwiCLI(click.MultiCommand):
|
class KiwiCLI(click.MultiCommand):
|
||||||
|
@ -42,8 +42,8 @@ class KiwiCommand:
|
||||||
click.secho(header, fg="green", bold=True)
|
click.secho(header, fg="green", bold=True)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def print_error(header: str):
|
def print_error(error: str):
|
||||||
click.secho(header, file=sys.stderr, fg="red", bold=True)
|
click.secho(error, file=sys.stderr, fg="red", bold=True)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def print_list(content: Iterable[str]):
|
def print_list(content: Iterable[str]):
|
||||||
|
@ -77,24 +77,22 @@ class KiwiCommand:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_for_instance(cls, instance: Instance, **kwargs) -> None:
|
def run_for_instance(cls, instance: Instance, **kwargs) -> None:
|
||||||
for project in instance.config.projects:
|
for project_config in instance.config.projects:
|
||||||
cls.run_for_project(instance, project.name, **kwargs)
|
project = instance.get_project(project_config.name)
|
||||||
|
cls.run_for_existing_project(instance, project, **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_for_project(cls, instance: Instance, project_name: str, **kwargs) -> None:
|
def run_for_new_project(cls, instance: Instance, project_name: str, **kwargs) -> None:
|
||||||
project = instance.get_project(project_name)
|
raise Exception
|
||||||
|
|
||||||
if project is None:
|
|
||||||
click.secho(f"No project '{project_name}' in kiwi-scp instance at '{instance.directory}'.", fg="red", bold=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
service_names = [service.name for service in project.get_services().content]
|
|
||||||
|
|
||||||
cls.run_for_services(instance, project_name, service_names, **kwargs)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_for_services(cls, instance: Instance, project_name: str, service_names: List[str], **kwargs) -> None:
|
def run_for_existing_project(cls, instance: Instance, project: Project, **kwargs) -> None:
|
||||||
pass
|
service_names = [service.name for service in project.services.content]
|
||||||
|
cls.run_for_services(instance, project, service_names, **kwargs)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def run_for_services(cls, instance: Instance, project: Project, service_names: List[str], **kwargs) -> None:
|
||||||
|
raise Exception
|
||||||
|
|
||||||
|
|
||||||
class KiwiCommandType(Enum):
|
class KiwiCommandType(Enum):
|
||||||
|
|
|
@ -4,7 +4,7 @@ import click
|
||||||
|
|
||||||
from .cli import KiwiCommandType, KiwiCommand
|
from .cli import KiwiCommandType, KiwiCommand
|
||||||
from .decorators import kiwi_command
|
from .decorators import kiwi_command
|
||||||
from ..instance import Instance
|
from ..instance import Instance, Project
|
||||||
|
|
||||||
|
|
||||||
@click.option(
|
@click.option(
|
||||||
|
@ -34,37 +34,29 @@ class CMD(KiwiCommand):
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_for_project(cls, instance: Instance, project_name: str, show: bool = None, **kwargs) -> None:
|
def run_for_existing_project(cls, instance: Instance, project: Project, show: bool = None, **kwargs) -> None:
|
||||||
project = instance.get_project(project_name)
|
|
||||||
|
|
||||||
if project is None:
|
|
||||||
KiwiCommand.print_error(f"No project '{project_name}' in kiwi-scp instance at '{instance.directory}'.")
|
|
||||||
return
|
|
||||||
|
|
||||||
services = project.get_services()
|
|
||||||
if show:
|
if show:
|
||||||
KiwiCommand.print_header(f"Showing config for all services in project '{project_name}'.")
|
KiwiCommand.print_header(f"Showing config for all services in project '{project.name}'.")
|
||||||
click.echo_via_pager(str(services))
|
click.echo_via_pager(str(project.services))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
KiwiCommand.print_header(f"Services in project '{project_name}':")
|
KiwiCommand.print_header(f"Services in project '{project.name}':")
|
||||||
KiwiCommand.print_list(service.name for service in services.content)
|
KiwiCommand.print_list(service.name for service in project.services.content)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run_for_services(cls, instance: Instance, project_name: str, service_names: List[str], show: bool = None,
|
def run_for_new_project(cls, instance: Instance, project_name: str, **kwargs) -> None:
|
||||||
|
KiwiCommand.print_error(f"Project '{project_name}' not in kiwi-scp instance at '{instance.directory}'!")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def run_for_services(cls, instance: Instance, project: Project, service_names: List[str], show: bool = None,
|
||||||
**kwargs) -> None:
|
**kwargs) -> None:
|
||||||
project = instance.get_project(project_name)
|
services = project.services.filter_existing(service_names)
|
||||||
|
|
||||||
if project is None:
|
|
||||||
KiwiCommand.print_error(f"No project '{project_name}' in kiwi-scp instance at '{instance.directory}'.")
|
|
||||||
return
|
|
||||||
|
|
||||||
services = project.get_services(service_names)
|
|
||||||
if show:
|
if show:
|
||||||
|
service_names = [service.name for service in services.content]
|
||||||
KiwiCommand.print_header(
|
KiwiCommand.print_header(
|
||||||
f"Showing config for services '{', '.join(service_names)}' in project '{project_name}'.")
|
f"Showing config for matching services '{', '.join(service_names)}' in project '{project.name}'.")
|
||||||
click.echo_via_pager(str(services))
|
click.echo_via_pager(str(services))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
KiwiCommand.print_header(f"Matching services in project '{project_name}':")
|
KiwiCommand.print_header(f"Matching services in project '{project.name}':")
|
||||||
KiwiCommand.print_list(service.name for service in services.content)
|
KiwiCommand.print_list(service.name for service in services.content)
|
||||||
|
|
|
@ -12,13 +12,14 @@ _pass_instance = click.make_pass_decorator(
|
||||||
)
|
)
|
||||||
|
|
||||||
_project_arg = click.argument(
|
_project_arg = click.argument(
|
||||||
"project",
|
"project_name",
|
||||||
|
metavar="[PROJECT]",
|
||||||
required=False,
|
required=False,
|
||||||
type=str,
|
type=str,
|
||||||
)
|
)
|
||||||
|
|
||||||
_services_arg = click.argument(
|
_services_arg = click.argument(
|
||||||
"services",
|
"service_names",
|
||||||
metavar="[SERVICE]...",
|
metavar="[SERVICE]...",
|
||||||
nargs=-1,
|
nargs=-1,
|
||||||
type=str,
|
type=str,
|
||||||
|
@ -40,24 +41,35 @@ def kiwi_command(
|
||||||
**decorator_kwargs,
|
**decorator_kwargs,
|
||||||
)
|
)
|
||||||
@_pass_instance
|
@_pass_instance
|
||||||
def cmd(ctx: Instance, project: Optional[str] = None, services: Optional[Tuple[str]] = None,
|
def cmd(ctx: Instance, project_name: Optional[str] = None, service_names: Optional[Tuple[str]] = None,
|
||||||
**kwargs) -> None:
|
**kwargs) -> None:
|
||||||
|
|
||||||
_logger.debug(f"{ctx.directory!r}: {project!r}, {services!r}")
|
_logger.debug(f"{ctx.directory!r}: {project_name!r}, {service_names!r}")
|
||||||
if project is None:
|
if project_name is None:
|
||||||
# run for whole instance
|
# run for whole instance
|
||||||
_logger.debug(f"running for instance, kwargs={kwargs}")
|
_logger.debug(f"running for instance, kwargs={kwargs}")
|
||||||
command_cls.run_for_instance(ctx, **kwargs)
|
command_cls.run_for_instance(ctx, **kwargs)
|
||||||
|
|
||||||
elif not services:
|
elif not service_names:
|
||||||
# run for one entire project
|
# run for one entire project
|
||||||
_logger.debug(f"running for project {project}, kwargs={kwargs}")
|
project = ctx.get_project(project_name)
|
||||||
command_cls.run_for_project(ctx, project, **kwargs)
|
if project is not None:
|
||||||
|
_logger.debug(f"running for existing project {project}, kwargs={kwargs}")
|
||||||
|
command_cls.run_for_existing_project(ctx, project, **kwargs)
|
||||||
|
|
||||||
|
else:
|
||||||
|
_logger.debug(f"running for new project {project_name}, kwargs={kwargs}")
|
||||||
|
command_cls.run_for_new_project(ctx, project_name, **kwargs)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# run for some services
|
# run for some services
|
||||||
_logger.debug(f"running for services {services} in project {project}, kwargs={kwargs}")
|
project = ctx.get_project(project_name)
|
||||||
command_cls.run_for_services(ctx, project, list(services), **kwargs)
|
if project is not None:
|
||||||
|
_logger.debug(f"running for services {service_names} in project {project}, kwargs={kwargs}")
|
||||||
|
command_cls.run_for_services(ctx, project, list(service_names), **kwargs)
|
||||||
|
|
||||||
|
else:
|
||||||
|
KiwiCommand.print_error(f"Project '{project_name}' not in kiwi-scp instance at '{ctx.directory}'!")
|
||||||
|
|
||||||
if command_type is KiwiCommandType.PROJECT:
|
if command_type is KiwiCommandType.PROJECT:
|
||||||
cmd = _project_arg(cmd)
|
cmd = _project_arg(cmd)
|
||||||
|
|
|
@ -43,6 +43,16 @@ class Services:
|
||||||
}
|
}
|
||||||
}).strip()
|
}).strip()
|
||||||
|
|
||||||
|
def __bool__(self) -> bool:
|
||||||
|
return bool(self.content)
|
||||||
|
|
||||||
|
def filter_existing(self, service_names: List[str]):
|
||||||
|
return Services([
|
||||||
|
service
|
||||||
|
for service in self.content
|
||||||
|
if service.name in service_names
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class Project:
|
class Project:
|
||||||
|
@ -54,20 +64,17 @@ class Project:
|
||||||
with open(directory.joinpath(COMPOSE_FILE_NAME), "r") as cf:
|
with open(directory.joinpath(COMPOSE_FILE_NAME), "r") as cf:
|
||||||
return YAML().load(cf)
|
return YAML().load(cf)
|
||||||
|
|
||||||
def get_services(self, service_names: Optional[List[str]] = None) -> Services:
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return self.directory.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def services(self) -> Services:
|
||||||
yml = Project._parse_compose_file(self.directory)
|
yml = Project._parse_compose_file(self.directory)
|
||||||
services = [
|
|
||||||
|
return Services([
|
||||||
Service(name, description)
|
Service(name, description)
|
||||||
for name, description in yml["services"].items()
|
for name, description in yml["services"].items()
|
||||||
]
|
|
||||||
|
|
||||||
if not service_names:
|
|
||||||
return Services(services)
|
|
||||||
else:
|
|
||||||
return Services([
|
|
||||||
service
|
|
||||||
for service in services
|
|
||||||
if service.name in service_names
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue