def start_infra_in_docker_detached(console): """ An alternative to start_infra_in_docker where the terminal is not blocked by the follow on the logfile. """ console.log("preparing environment") try: prepare_docker_start() except ContainerExists as e: console.print(str(e)) return # create and prepare container console.log("configuring container") container = LocalstackContainer() configure_container(container) container.truncate_log() # start the Localstack container as a Server console.log("starting container") server = LocalstackContainerServer(container) server.start() server.wait_is_container_running() console.log("detaching")
def validate_localstack_config(name): # TODO: separate functionality from CLI output # (use exceptions to communicate errors, and return list of warnings) from subprocess import CalledProcessError from localstack.cli import console dirname = os.getcwd() compose_file_name = name if os.path.isabs(name) else os.path.join( dirname, name) warns = [] # validating docker-compose file cmd = ["docker-compose", "-f", compose_file_name, "config"] try: run(cmd, shell=False, print_error=False) except CalledProcessError as e: msg = f"{e}\n{to_str(e.output)}".strip() raise ValueError(msg) # validating docker-compose variable import yaml # keep import here to avoid issues in test Lambdas with open(compose_file_name) as file: compose_content = yaml.full_load(file) services_config = compose_content.get("services", {}) ls_service_name = [ name for name, svc in services_config.items() if "localstack" in svc.get("image", "") ] if not ls_service_name: raise Exception( 'No LocalStack service found in config (looking for image names containing "localstack")' ) if len(ls_service_name) > 1: warns.append( f"Multiple candidates found for LocalStack service: {ls_service_name}" ) ls_service_name = ls_service_name[0] ls_service_details = services_config[ls_service_name] image_name = ls_service_details.get("image", "") if image_name.split(":")[0] not in constants.OFFICIAL_IMAGES: warns.append( 'Using custom image "%s", we recommend using an official image: %s' % (image_name, constants.OFFICIAL_IMAGES)) # prepare config options network_mode = ls_service_details.get("network_mode") image_name = ls_service_details.get("image") container_name = ls_service_details.get("container_name") or "" docker_ports = (port.split(":")[-2] for port in ls_service_details.get("ports", [])) docker_env = dict((env.split("=")[0], env.split("=")[1]) for env in ls_service_details.get("environment", {})) edge_port = str(docker_env.get("EDGE_PORT") or config.EDGE_PORT) main_container = config.MAIN_CONTAINER_NAME # docker-compose file validation cases if (docker_env.get("PORT_WEB_UI") not in ["${PORT_WEB_UI- }", None, ""] and image_name == "localstack/localstack"): warns.append( '"PORT_WEB_UI" Web UI is now deprecated, ' 'and requires to use the "localstack/localstack-full" image.') if not docker_env.get("HOST_TMP_FOLDER"): warns.append( 'Please configure the "HOST_TMP_FOLDER" environment variable to point to the ' + "absolute path of a temp folder on your host system (e.g., HOST_TMP_FOLDER=${TMPDIR})" ) if (main_container not in container_name ) and not docker_env.get("MAIN_CONTAINER_NAME"): warns.append( 'Please use "container_name: %s" or add "MAIN_CONTAINER_NAME" in "environment".' % main_container) def port_exposed(port): for exposed in docker_ports: if re.match(r"^([0-9]+-)?%s(-[0-9]+)?$" % port, exposed): return True if not port_exposed(edge_port): warns.append( ("Edge port %s is not exposed. You may have to add the entry " 'to the "ports" section of the docker-compose file.') % edge_port) if network_mode != "bridge" and not docker_env.get( "LAMBDA_DOCKER_NETWORK"): warns.append( 'Network mode is not set to "bridge" which may cause networking issues in Lambda containers. ' 'Consider adding "network_mode: bridge" to your docker-compose file, or configure ' "LAMBDA_DOCKER_NETWORK with the name of the Docker network of your compose stack." ) # print warning/info messages for warning in warns: console.print("[yellow]:warning:[/yellow]", warning) if not warns: return True return False