Esempio n. 1
0
def scale(
    scaling: str = typer.Argument(..., help="scale SERVICE to NUM_REPLICA"),
    wait: bool = typer.Option(
        False,
        "--wait",
        help="Wait service convergence",
        show_default=False,
    ),
) -> None:
    Application.print_command(
        Application.serialize_parameter("--wait", wait, IF=wait),
        Application.serialize_parameter("", scaling),
    )
    Application.get_controller().controller_init()

    options = scaling.split("=")
    if len(options) == 2:
        service, nreplicas = options
    else:
        scale_var = f"DEFAULT_SCALE_{scaling.upper()}"
        nreplicas = glom(Configuration.specs, f"variables.env.{scale_var}", default="1")
        service = scaling

    docker = Docker()

    service_name = docker.get_service(service)
    scales: Dict[Union[str, Service], int] = {}
    try:
        scales[service_name] = int(nreplicas)
    except ValueError:
        print_and_exit("Invalid number of replicas: {}", nreplicas)

    # Stop core services non compatible with scale with 2+ instances
    if scales[service_name] >= 2:
        core_services = list(Application.data.base_services.keys())
        if service in core_services and service not in supported_services:
            print_and_exit(
                "Service {} is not guaranteed to support the scale, "
                "can't accept the request",
                service,
            )

    docker.registry.ping()

    verify_available_images(
        [service],
        Application.data.compose_config,
        Application.data.base_services,
    )

    try:
        docker.client.service.scale(scales, detach=not wait)
    # Can happens in case of scale before start
    except NoSuchService:
        print_and_exit(
            "No such service: {}, have you started your stack?", service_name
        )
Esempio n. 2
0
def remove(
    services: List[str] = typer.Argument(
        None,
        help="Services to be removed",
        shell_complete=Application.autocomplete_service,
    ),
) -> None:

    Application.print_command(Application.serialize_parameter("", services))

    remove_extras: List[str] = []
    for extra in (
            REGISTRY,
            "adminer",
            "swaggerui",
    ):
        if services and extra in services:
            # services is a tuple, even if defined as List[str] ...
            services = list(services)
            services.pop(services.index(extra))
            remove_extras.append(extra)

    Application.get_controller().controller_init(services)

    docker = Docker()
    if remove_extras:
        for extra_service in remove_extras:
            if not docker.client.container.exists(extra_service):
                log.error("Service {} is not running", extra_service)
                continue
            docker.client.container.remove(extra_service, force=True)
            log.info("Service {} removed", extra_service)

        # Nothing more to do
        if not services:
            return

    all_services = Application.data.services == Application.data.active_services

    if all_services:
        docker.swarm.remove()
        # This is needed because docker stack remove does not support a --wait flag
        # To make the remove command sync and chainable with a start command
        engine = Application.env.get("DEPLOY_ENGINE", "swarm")
        network_name = f"{Configuration.project}_{engine}_default"
        wait_network_removal(docker, network_name)
        log.info("Stack removed")
    else:

        if not docker.swarm.stack_is_running():
            print_and_exit(
                "Stack {} is not running, deploy it with {command}",
                Configuration.project,
                command=RED("rapydo start"),
            )

        scales: Dict[Union[str, Service], int] = {}
        for service in Application.data.services:
            service_name = Docker.get_service(service)
            scales[service_name] = 0

        docker.client.service.scale(scales, detach=False)

        log.info("Services removed")