def reload(docker: Docker, services: List[str]) -> None: for service in services: containers = docker.get_containers(service) docker.exec_command(containers, user="******", command="/usr/local/bin/reload")
def reload( services: List[str] = typer.Argument( None, help="Services to be reloaded", shell_complete=Application.autocomplete_service, ), ) -> None: Application.print_command(Application.serialize_parameter("", services)) Application.get_controller().controller_init(services) docker = Docker() running_services = docker.get_running_services() if "frontend" in services and len(services) > 1: print_and_exit("Can't reload frontend and other services at once") reloaded = 0 for service in Application.data.services: # Special case: frontend in production mode if Configuration.production and service == "frontend": # Only consider it if explicitly requested in input if "frontend" not in services: log.debug( "Can't reload the frontend if not explicitly requested") else: log.info("Reloading frontend...") # The frontend build stucks in swarm mode... let's start the container # always in compose mode when using the reload comand Configuration.FORCE_COMPOSE_ENGINE = True Application.get_controller().controller_init([service]) docker = Docker() docker.compose.start_containers([service], force=True) reloaded += 1 continue if service not in running_services: continue containers = docker.get_containers(service) if not containers: log.warning("Can't find any container for {}", service) continue try: # get the first container from the containers dict container = containers.get(list(containers.keys())[0]) # Just added for typing purpose if not container: # pragma: no conver log.warning("Can't find any container for {}", service) continue output = docker.exec_command( container, user="******", command="ls /usr/local/bin/reload", force_output_return=True, ) # this is to consume the iterator and raise the exception with exit code if output: [_ for _ in output] except DockerException as e: # fail2ban fails with code 1 if "It returned with code 1" in str(e): log.warning("Service {} does not support the reload command", service) continue # backend fails with code 2 if "It returned with code 2" in str(e): log.warning("Service {} does not support the reload command", service) continue raise docker.exec_command(containers, user="******", command="/usr/local/bin/reload") reloaded += 1 if reloaded == 0: log.info("No service reloaded") else: log.info("Services reloaded")
def ssl( volatile: bool = typer.Option( False, "--volatile", help="Create a volatile proxy service to request the certificate", show_default=False, ), no_tty: bool = typer.Option( False, "--no-tty", help="Disable pseudo-tty allocation (e.g. to execute from a cronjob)", show_default=False, ), chain_file: Optional[Path] = typer.Option( None, "--chain-file", help="Path to existing chain file (.pem format)", show_default=False, ), key_file: Optional[Path] = typer.Option( None, "--key-file", help="Path to existing key file (.pem format)", show_default=False, ), ) -> None: Application.print_command( Application.serialize_parameter("--volatile", volatile, IF=volatile), Application.serialize_parameter("--chain-file", chain_file, IF=chain_file), Application.serialize_parameter("--key-file", key_file, IF=key_file), ) if no_tty: log.warning("--no-tty option is deprecated, you can stop using it") Application.get_controller().controller_init() if chain_file is not None or key_file is not None: if chain_file is None: print_and_exit("Invalid chain file (you provided none)") elif not chain_file.exists(): print_and_exit("Invalid chain file (you provided {})", chain_file) if key_file is None: print_and_exit("Invalid key file (you provided none)") elif not key_file.exists(): print_and_exit("Invalid key file (you provided {})", key_file) service = "proxy" verify_available_images( [service], Application.data.compose_config, Application.data.base_services, ) if chain_file is not None and key_file is not None: log.info("Unable to automatically perform the requested operation") log.info("You can execute the following commands by your-self:") c = f"{Configuration.project}_{service}_1" letsencrypt_path = "/etc/letsencrypt/real" print("") print(f"docker cp {chain_file} {c}:{letsencrypt_path}/fullchain1.pem") print(f"docker cp {key_file} {c}:{letsencrypt_path}/privkey1.pem") print(f"rapydo shell {service} 'nginx -s reload'") print("") return docker = Docker() command = f"/bin/bash updatecertificates {Configuration.hostname}" if volatile: docker.compose.create_volatile_container(service, command=command, publish=[(443, 443), (80, 80)]) else: container = docker.get_container(service) if not container: print_and_exit( "The proxy is not running, start your stack or try with {command}", command=RED("rapydo ssl --volatile"), ) docker.exec_command(container, user="******", command=command) container = docker.get_container("neo4j") if container: # This is not true!! A full restart is needed # log.info("Neo4j is running, but it will reload the certificate by itself") # But not implemented yet... log.info( "Neo4j is running, a full restart is needed. NOT IMPLEMENTED YET.") containers = docker.get_containers("rabbit") if containers: log.info( "RabbitMQ is running, executing command to refresh the certificate" ) # Please note that Erland is able to automatically reload the certificate # But RabbitMQ does not. Probably in the future releases this command will # No longer be required. To test it after the creation of the new cert: # echo -n | openssl s_client -showcerts -connect hostname:5671 # Please note that this command can fail if RabbitMQ is still starting docker.exec_command(containers, user="******", command="/usr/local/bin/reload_certificate") containers = docker.get_containers("swaggerui") if containers: # pragma: no cover log.info( "SwaggerUI is running, executing command to refresh the certificate" ) docker.exec_command(containers, user="******", command="nginx -s reload") log.info("New certificate successfully enabled")
def shell( service: str = typer.Argument( ..., help="Service name", shell_complete=Application.autocomplete_service), command: str = typer.Argument( "bash", help="UNIX command to be executed on selected running service"), user: Optional[str] = typer.Option( None, "--user", "-u", help="User existing in selected service", show_default=False, ), default_command: bool = typer.Option( False, "--default-command", "--default", help="Execute the default command configured for the container", show_default=False, ), no_tty: bool = typer.Option( False, "--no-tty", help= "Disable pseudo-tty allocation (useful for non-interactive script)", show_default=False, ), replica: int = typer.Option( 1, "--replica", "--slot", help="Execute the command on the specified replica", show_default=False, ), broadcast: bool = typer.Option( False, "--broadcast", help="Execute the command on all the replicas", show_default=False, ), ) -> None: Application.print_command( Application.serialize_parameter("--user", user, IF=user), Application.serialize_parameter("--default", default_command, IF=default_command), Application.serialize_parameter("", service), Application.serialize_parameter("", command), ) if no_tty: log.warning("--no-tty option is deprecated, you can stop using it") if replica > 1 and broadcast: print_and_exit("--replica and --broadcast options are not compatible") Application.get_controller().controller_init() docker = Docker() if not user: user = services.get_default_user(service) if default_command: command = services.get_default_command(service) log.debug("Requested command: {} with user: {}", command, user or "default") if broadcast: containers = docker.get_containers(service) if not containers: print_and_exit("No running container found for {} service", service) docker.exec_command(containers, user=user, command=command) else: container = docker.get_container(service, slot=replica) if not container: if replica != 1: print_and_exit("Replica number {} not found for {} service", str(replica), service) print_and_exit("No running container found for {} service", service) docker.exec_command(container, user=user, command=command)