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 )
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")