from typing import Union
import typer
from glom import glom
from python_on_whales import Service
from python_on_whales.exceptions import NoSuchService
from controller import print_and_exit
from controller.app import Application, Configuration
from controller.deploy.builds import verify_available_images
from controller.deploy.docker import Docker
# RabbitMQ:
# https://www.erlang-solutions.com/blog/scaling-rabbitmq-on-a-coreos-cluster-through-docker/
supported_services = [
"adminer",
"backend",
"celery",
"flower",
"ftp",
# To allow nginx to access the real client IP it is now deployed in global mode
# to be able to map the port directly on the host, instead of being load balanced
# In this way the proxy can no longer be scaled
# "proxy",
"swaggerui",
]
[docs]
@Application.app.command(help="Scale the number of replicas for a service")
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
)