class TestBuildClusterEndpoint: def test_endpoint_strategy_port(self, monkeypatch): monkeypatch.setattr(config, "OPENSEARCH_ENDPOINT_STRATEGY", "port") endpoint = build_cluster_endpoint( DomainKey("my-domain", "us-east-1", TEST_AWS_ACCOUNT_ID)) parts = endpoint.split(":") assert parts[0] == "localhost" assert int(parts[1]) in range(config.EXTERNAL_SERVICE_PORTS_START, config.EXTERNAL_SERVICE_PORTS_END) @pytest.mark.skipif( condition=config.in_docker(), reason="port mapping differs when being run in the container") @pytest.mark.parametrize("engine", [(EngineType.OpenSearch, "opensearch"), (EngineType.Elasticsearch, "es")]) def test_endpoint_strategy_path(self, monkeypatch, engine): monkeypatch.setattr(config, "OPENSEARCH_ENDPOINT_STRATEGY", "path") engine_type = engine[0] engine_path_prefix = engine[1] endpoint = build_cluster_endpoint(DomainKey("my-domain", "us-east-1", TEST_AWS_ACCOUNT_ID), engine_type=engine_type) assert endpoint == f"localhost:4566/{engine_path_prefix}/us-east-1/my-domain" endpoint = build_cluster_endpoint(DomainKey("my-domain-1", "eu-central-1", TEST_AWS_ACCOUNT_ID), engine_type=engine_type) assert endpoint == f"localhost:4566/{engine_path_prefix}/eu-central-1/my-domain-1" @pytest.mark.skipif( condition=config.in_docker(), reason="port mapping differs when being run in the container") @pytest.mark.parametrize("engine", [(EngineType.OpenSearch, "opensearch"), (EngineType.Elasticsearch, "es")]) def test_endpoint_strategy_domain(self, monkeypatch, engine): monkeypatch.setattr(config, "OPENSEARCH_ENDPOINT_STRATEGY", "domain") engine_type = engine[0] engine_path_prefix = engine[1] endpoint = build_cluster_endpoint( domain_key=DomainKey("my-domain", "us-east-1", TEST_AWS_ACCOUNT_ID), engine_type=engine_type, ) assert ( endpoint == f"my-domain.us-east-1.{engine_path_prefix}.localhost.localstack.cloud:4566" ) endpoint = build_cluster_endpoint( domain_key=DomainKey("my-domain-1", "eu-central-1", TEST_AWS_ACCOUNT_ID), engine_type=engine_type, ) assert ( endpoint == f"my-domain-1.eu-central-1.{engine_path_prefix}.localhost.localstack.cloud:4566" )
def traverse_file_tree(root: str) -> List[str]: try: result = [] if config.in_docker(): for root, _, _ in os.walk(root): result.append(root) return result except Exception as e: return ["traversing files failed %s" % e]
def in_docker(): return config.in_docker()
client = docker_utils.SdkDockerClient() yield client try: client.stop_container(config.MAIN_CONTAINER_NAME) except Exception: pass # wait until container has been removed assert poll_condition( lambda: not container_exists(client, config.MAIN_CONTAINER_NAME), timeout=20) @pytest.mark.skipif(condition=in_docker(), reason="cannot run CLI tests in docker") class TestCliContainerLifecycle: def test_start_wait_stop(self, runner, container_client): result = runner.invoke(cli, ["start", "-d"]) assert result.exit_code == 0 assert "starting LocalStack" in result.output result = runner.invoke(cli, ["wait", "-t", "60"]) assert result.exit_code == 0 assert container_client.is_container_running( config.MAIN_CONTAINER_NAME ), "container name was not running after wait" health = requests.get(get_edge_url() + "/health")
class TestDockerClient: def test_container_lifecycle_commands(self, docker_client: ContainerClient): container_name = _random_container_name() output = docker_client.create_container( "alpine", name=container_name, command=[ "sh", "-c", "for i in `seq 30`; do sleep 1; echo $i; done" ], ) container_id = output.strip() assert container_id try: docker_client.start_container(container_id) assert DockerContainerStatus.UP == docker_client.get_container_status( container_name) docker_client.stop_container(container_id) assert DockerContainerStatus.DOWN == docker_client.get_container_status( container_name) finally: docker_client.remove_container(container_id) assert DockerContainerStatus.NON_EXISTENT == docker_client.get_container_status( container_name) def test_create_container_remove_removes_container( self, docker_client: ContainerClient, create_container): info = create_container("alpine", remove=True, command=["echo", "foobar"]) # make sure it was correctly created assert 1 == len( docker_client.list_containers(f"id={info.container_id}")) # start the container output, _ = docker_client.start_container(info.container_id, attach=True) output = output.decode(config.DEFAULT_ENCODING) time.sleep( 1 ) # give the docker daemon some time to remove the container after execution assert 0 == len( docker_client.list_containers(f"id={info.container_id}")) # it takes a while for it to be removed assert "foobar" in output @pytest.mark.skip_offline def test_create_container_non_existing_image( self, docker_client: ContainerClient): with pytest.raises(NoSuchImage): docker_client.create_container( "this_image_does_hopefully_not_exist_42069") def test_exec_in_container(self, docker_client: ContainerClient, dummy_container: ContainerInfo): docker_client.start_container(dummy_container.container_id) output, _ = docker_client.exec_in_container( dummy_container.container_id, command=["echo", "foobar"]) output = output.decode(config.DEFAULT_ENCODING) assert "foobar" == output.strip() def test_exec_in_container_not_running_raises_exception( self, docker_client: ContainerClient, dummy_container): with pytest.raises(ContainerException): # can't exec into a non-running container docker_client.exec_in_container(dummy_container.container_id, command=["echo", "foobar"]) def test_exec_in_container_with_env(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) env = {"MYVAR": "foo_var"} output, _ = docker_client.exec_in_container( dummy_container.container_id, env_vars=env, command=["env"]) output = output.decode(config.DEFAULT_ENCODING) assert "MYVAR=foo_var" in output def test_exec_in_container_with_env_deletion( self, docker_client: ContainerClient, create_container): container_info = create_container( "alpine", command=["sh", "-c", "env; while true; do sleep 1; done"], env_vars={"MYVAR": "SHOULD_BE_OVERWRITTEN"}, ) docker_client.start_container(container_info.container_id) log_output = docker_client.get_container_logs( container_name_or_id=container_info.container_id) assert "MYVAR=SHOULD_BE_OVERWRITTEN" in log_output env = {"MYVAR": None} output, _ = docker_client.exec_in_container( container_info.container_id, env_vars=env, command=["env"]) output = output.decode(config.DEFAULT_ENCODING) assert "MYVAR" not in output def test_exec_error_in_container(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) with pytest.raises(ContainerException) as ex: docker_client.exec_in_container(dummy_container.container_id, command=["./doesnotexist"]) assert ex.match("doesnotexist: no such file or directory") def test_create_container_with_max_env_vars(self, docker_client: ContainerClient, create_container): # default ARG_MAX=131072 in Docker env = {f"IVAR_{i:05d}": f"VAL_{i:05d}" for i in range(2000)} # make sure we're really triggering the relevant code assert len(str(dict(env))) >= Util.MAX_ENV_ARGS_LENGTH info = create_container("alpine", env_vars=env, command=["env"]) output, _ = docker_client.start_container(info.container_id, attach=True) output = output.decode(config.DEFAULT_ENCODING) assert "IVAR_00001=VAL_00001" in output assert "IVAR_01000=VAL_01000" in output assert "IVAR_01999=VAL_01999" in output def test_run_container(self, docker_client: ContainerClient): container_name = _random_container_name() try: output, _ = docker_client.run_container( "alpine", name=container_name, command=["echo", "foobared"], ) output = output.decode(config.DEFAULT_ENCODING) assert "foobared" in output finally: docker_client.remove_container(container_name) def test_run_container_error(self, docker_client: ContainerClient): container_name = _random_container_name() try: with pytest.raises(ContainerException): docker_client.run_container( "alpine", name=container_name, command=["./doesnotexist"], ) finally: docker_client.remove_container(container_name) def test_stop_non_existing_container(self, docker_client: ContainerClient): with pytest.raises(NoSuchContainer): docker_client.stop_container("this_container_does_not_exist") def test_remove_non_existing_container(self, docker_client: ContainerClient): with pytest.raises(NoSuchContainer): docker_client.remove_container("this_container_does_not_exist", force=False) def test_start_non_existing_container(self, docker_client: ContainerClient): with pytest.raises(NoSuchContainer): docker_client.start_container("this_container_does_not_exist") def test_get_network(self, docker_client: ContainerClient, dummy_container): n = docker_client.get_networks(dummy_container.container_name) assert ["bridge"] == n def test_get_network_multiple_networks(self, docker_client: ContainerClient, dummy_container, create_network): network_name = f"test-network-{short_uid()}" network_id = create_network(network_name) safe_run([ "docker", "network", "connect", network_id, dummy_container.container_id ]) docker_client.start_container(dummy_container.container_id) networks = docker_client.get_networks(dummy_container.container_id) assert network_name in networks assert "bridge" in networks assert len(networks) == 2 def test_get_container_ip_for_network(self, docker_client: ContainerClient, dummy_container, create_network): network_name = f"test-network-{short_uid()}" network_id = create_network(network_name) safe_run([ "docker", "network", "connect", network_id, dummy_container.container_id ]) docker_client.start_container(dummy_container.container_id) result_bridge_network = docker_client.get_container_ipv4_for_network( container_name_or_id=dummy_container.container_id, container_network="bridge").strip() assert is_ipv4_address(result_bridge_network) bridge_network = docker_client.inspect_network( "bridge")["IPAM"]["Config"][0]["Subnet"] assert ipaddress.IPv4Address( result_bridge_network) in ipaddress.IPv4Network(bridge_network) result_custom_network = docker_client.get_container_ipv4_for_network( container_name_or_id=dummy_container.container_id, container_network=network_name).strip() assert is_ipv4_address(result_custom_network) assert result_custom_network != result_bridge_network custom_network = docker_client.inspect_network( network_name)["IPAM"]["Config"][0]["Subnet"] assert ipaddress.IPv4Address( result_custom_network) in ipaddress.IPv4Network(custom_network) def test_get_container_ip_for_network_wrong_network( self, docker_client: ContainerClient, dummy_container, create_network): network_name = f"test-network-{short_uid()}" create_network(network_name) docker_client.start_container(dummy_container.container_id) result_bridge_network = docker_client.get_container_ipv4_for_network( container_name_or_id=dummy_container.container_id, container_network="bridge").strip() assert is_ipv4_address(result_bridge_network) with pytest.raises(ContainerException): docker_client.get_container_ipv4_for_network( container_name_or_id=dummy_container.container_id, container_network=network_name) def test_get_container_ip_for_host_network(self, docker_client: ContainerClient, create_container): container = create_container( "alpine", command=["sh", "-c", "while true; do sleep 1; done"], network="host") assert "host" == docker_client.get_networks( container.container_name)[0] # host network containers have no dedicated IP, so it will throw an exception here with pytest.raises(ContainerException): docker_client.get_container_ipv4_for_network( container_name_or_id=container.container_name, container_network="host") def test_get_container_ip_for_network_non_existent_network( self, docker_client: ContainerClient, dummy_container, create_network): network_name = f"invalid-test-network-{short_uid()}" docker_client.start_container(dummy_container.container_id) with pytest.raises(NoSuchNetwork): docker_client.get_container_ipv4_for_network( container_name_or_id=dummy_container.container_id, container_network=network_name) def test_create_with_host_network(self, docker_client: ContainerClient, create_container): info = create_container("alpine", network="host") network = docker_client.get_networks(info.container_name) assert ["host"] == network def test_create_with_port_mapping(self, docker_client: ContainerClient, create_container): ports = PortMappings() ports.add(45122, 22) ports.add(45180, 80) create_container("alpine", ports=ports) @pytest.mark.skipif( condition=in_docker(), reason="cannot test volume mounts from host when in docker") def test_create_with_volume(self, tmpdir, docker_client: ContainerClient, create_container): mount_volumes = [(tmpdir.realpath(), "/tmp/mypath")] c = create_container( "alpine", command=["sh", "-c", "echo 'foobar' > /tmp/mypath/foo.log"], mount_volumes=mount_volumes, ) docker_client.start_container(c.container_id) assert tmpdir.join( "foo.log").isfile(), "foo.log was not created in mounted dir" def test_copy_into_container(self, tmpdir, docker_client: ContainerClient, create_container): local_path = tmpdir.join("myfile.txt") container_path = "/tmp/myfile_differentpath.txt" self._test_copy_into_container( docker_client, create_container, ["cat", container_path], local_path, local_path, container_path, ) def test_copy_into_non_existent_container(self, tmpdir, docker_client: ContainerClient): local_path = tmpdir.mkdir("test_dir") file_path = local_path.join("test_file") with file_path.open(mode="w") as fd: fd.write("foobared\n") with pytest.raises(NoSuchContainer): docker_client.copy_into_container( "hopefully_non_existent_container_%s" % short_uid(), str(file_path), "test_file") def test_copy_into_container_without_target_filename( self, tmpdir, docker_client: ContainerClient, create_container): local_path = tmpdir.join("myfile.txt") container_path = "/tmp" self._test_copy_into_container( docker_client, create_container, ["cat", "/tmp/myfile.txt"], local_path, local_path, container_path, ) def test_copy_directory_into_container(self, tmpdir, docker_client: ContainerClient, create_container): local_path = tmpdir.join("fancy_folder") local_path.mkdir() file_path = local_path.join("myfile.txt") container_path = "/tmp/fancy_other_folder" self._test_copy_into_container( docker_client, create_container, ["cat", "/tmp/fancy_other_folder/myfile.txt"], file_path, local_path, container_path, ) def _test_copy_into_container(self, docker_client, create_container, command, file_path, local_path, container_path): c = create_container("alpine", command=command) with file_path.open(mode="w") as fd: fd.write("foobared\n") docker_client.copy_into_container(c.container_name, str(local_path), container_path) output, _ = docker_client.start_container(c.container_id, attach=True) output = output.decode(config.DEFAULT_ENCODING) assert "foobared" in output def test_copy_into_container_with_existing_target( self, tmpdir, docker_client: ContainerClient, dummy_container): local_path = tmpdir.join("myfile.txt") container_path = "/tmp/myfile.txt" with local_path.open(mode="w") as fd: fd.write("foo\n") docker_client.start_container(dummy_container.container_id) docker_client.exec_in_container( dummy_container.container_id, command=["sh", "-c", f"echo bar > {container_path}"]) out, _ = docker_client.exec_in_container( dummy_container.container_id, command=[ "cat", "/tmp/myfile.txt", ], ) assert "bar" in out.decode(config.DEFAULT_ENCODING) docker_client.copy_into_container(dummy_container.container_id, str(local_path), container_path) out, _ = docker_client.exec_in_container( dummy_container.container_id, command=[ "cat", "/tmp/myfile.txt", ], ) assert "foo" in out.decode(config.DEFAULT_ENCODING) def test_copy_directory_content_into_container( self, tmpdir, docker_client: ContainerClient, dummy_container): local_path = tmpdir.join("fancy_folder") local_path.mkdir() file_path = local_path.join("myfile.txt") with file_path.open(mode="w") as fd: fd.write("foo\n") file_path = local_path.join("myfile2.txt") with file_path.open(mode="w") as fd: fd.write("bar\n") container_path = "/tmp/fancy_other_folder" docker_client.start_container(dummy_container.container_id) docker_client.exec_in_container( dummy_container.container_id, command=["mkdir", "-p", container_path]) docker_client.copy_into_container(dummy_container.container_id, f"{str(local_path)}/.", container_path) out, _ = docker_client.exec_in_container( dummy_container.container_id, command=[ "cat", "/tmp/fancy_other_folder/myfile.txt", "/tmp/fancy_other_folder/myfile2.txt", ], ) assert "foo" in out.decode(config.DEFAULT_ENCODING) assert "bar" in out.decode(config.DEFAULT_ENCODING) def test_get_network_non_existing_container( self, docker_client: ContainerClient): with pytest.raises(ContainerException): docker_client.get_networks("this_container_does_not_exist") def test_list_containers(self, docker_client: ContainerClient, create_container): c1 = create_container("alpine", command=["echo", "1"]) c2 = create_container("alpine", command=["echo", "2"]) c3 = create_container("alpine", command=["echo", "3"]) container_list = docker_client.list_containers() assert len(container_list) >= 3 image_names = [info["name"] for info in container_list] assert c1.container_name in image_names assert c2.container_name in image_names assert c3.container_name in image_names def test_list_containers_filter_non_existing( self, docker_client: ContainerClient): container_list = docker_client.list_containers( filter="id=DOES_NOT_EXST") assert 0 == len(container_list) def test_list_containers_filter_illegal_filter( self, docker_client: ContainerClient): with pytest.raises(ContainerException): docker_client.list_containers(filter="illegalfilter=foobar") def test_list_containers_filter(self, docker_client: ContainerClient, create_container): name_prefix = "filter_tests_" cn1 = name_prefix + _random_container_name() cn2 = name_prefix + _random_container_name() cn3 = name_prefix + _random_container_name() c1 = create_container("alpine", name=cn1, command=["echo", "1"]) c2 = create_container("alpine", name=cn2, command=["echo", "2"]) c3 = create_container("alpine", name=cn3, command=["echo", "3"]) # per id container_list = docker_client.list_containers( filter=f"id={c2.container_id}") assert 1 == len(container_list) assert c2.container_id.startswith(container_list[0]["id"]) assert c2.container_name == container_list[0]["name"] assert "created" == container_list[0]["status"] # per name pattern container_list = docker_client.list_containers( filter=f"name={name_prefix}") assert 3 == len(container_list) image_names = [info["name"] for info in container_list] assert c1.container_name in image_names assert c2.container_name in image_names assert c3.container_name in image_names # multiple patterns container_list = docker_client.list_containers(filter=[ f"id={c1.container_id}", f"name={container_name_prefix}", ]) assert 1 == len(container_list) assert c1.container_name == container_list[0]["name"] def test_get_container_entrypoint(self, docker_client: ContainerClient): entrypoint = docker_client.get_image_entrypoint("alpine") assert "" == entrypoint def test_get_container_entrypoint_non_existing_image( self, docker_client: ContainerClient): with pytest.raises(NoSuchImage): docker_client.get_image_entrypoint("thisdoesnotexist") def test_get_container_entrypoint_not_pulled_image( self, docker_client: ContainerClient): try: docker_client.get_image_cmd("alpine", pull=False) safe_run([config.DOCKER_CMD, "rmi", "alpine"]) except ContainerException: pass entrypoint = docker_client.get_image_entrypoint("alpine") assert "" == entrypoint def test_get_container_command(self, docker_client: ContainerClient): command = docker_client.get_image_cmd("alpine") assert ["/bin/sh"] == command def test_get_container_command_not_pulled_image( self, docker_client: ContainerClient): try: docker_client.get_image_cmd("alpine", pull=False) safe_run([config.DOCKER_CMD, "rmi", "alpine"]) except ContainerException: pass command = docker_client.get_image_cmd("alpine") assert ["/bin/sh"] == command def test_get_container_command_non_existing_image( self, docker_client: ContainerClient): with pytest.raises(NoSuchImage): docker_client.get_image_cmd("thisdoesnotexist") def test_create_start_container_with_stdin_to_stdout( self, docker_client: ContainerClient): container_name = _random_container_name() message = "test_message_stdin" try: docker_client.create_container( "alpine", name=container_name, interactive=True, command=["cat"], ) output, _ = docker_client.start_container( container_name, interactive=True, stdin=message.encode(config.DEFAULT_ENCODING)) assert message == output.decode(config.DEFAULT_ENCODING).strip() finally: docker_client.remove_container(container_name) pass def test_create_start_container_with_stdin_to_file( self, tmpdir, docker_client: ContainerClient): container_name = _random_container_name() message = "test_message_stdin" try: docker_client.create_container( "alpine", name=container_name, interactive=True, command=["sh", "-c", "cat > test_file"], ) output, _ = docker_client.start_container( container_name, interactive=True, stdin=message.encode(config.DEFAULT_ENCODING)) target_path = tmpdir.join("test_file") docker_client.copy_from_container(container_name, str(target_path), "test_file") assert message == target_path.read().strip() finally: docker_client.remove_container(container_name) def test_run_container_with_stdin(self, docker_client: ContainerClient): container_name = _random_container_name() message = "test_message_stdin" try: output, _ = docker_client.run_container( "alpine", name=container_name, interactive=True, stdin=message.encode(config.DEFAULT_ENCODING), command=["cat"], ) assert message == output.decode(config.DEFAULT_ENCODING).strip() finally: docker_client.remove_container(container_name) def test_exec_in_container_with_stdin(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) message = "test_message_stdin" output, _ = docker_client.exec_in_container( dummy_container.container_id, interactive=True, stdin=message.encode(config.DEFAULT_ENCODING), command=["cat"], ) assert message == output.decode(config.DEFAULT_ENCODING).strip() def test_exec_in_container_with_stdin_stdout_stderr( self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) message = "test_message_stdin" output, stderr = docker_client.exec_in_container( dummy_container.container_id, interactive=True, stdin=message.encode(config.DEFAULT_ENCODING), command=["sh", "-c", "cat; >&2 echo stderrtest"], ) assert message == output.decode(config.DEFAULT_ENCODING).strip() assert "stderrtest" == stderr.decode(config.DEFAULT_ENCODING).strip() def test_run_detached_with_logs(self, docker_client: ContainerClient): container_name = _random_container_name() message = "test_message" try: output, _ = docker_client.run_container( "alpine", name=container_name, detach=True, command=["echo", message], ) container_id = output.decode(config.DEFAULT_ENCODING).strip() logs = docker_client.get_container_logs(container_id) assert message == logs.strip() finally: docker_client.remove_container(container_name) def test_get_logs_non_existent_container(self, docker_client: ContainerClient): with pytest.raises(NoSuchContainer): docker_client.get_container_logs( "container_hopefully_does_not_exist", safe=False) assert "" == docker_client.get_container_logs( "container_hopefully_does_not_exist", safe=True) @pytest.mark.skip_offline def test_pull_docker_image(self, docker_client: ContainerClient): try: docker_client.get_image_cmd("alpine", pull=False) safe_run([config.DOCKER_CMD, "rmi", "alpine"]) except ContainerException: pass with pytest.raises(NoSuchImage): docker_client.get_image_cmd("alpine", pull=False) docker_client.pull_image("alpine") assert ["/bin/sh"] == docker_client.get_image_cmd("alpine", pull=False) @pytest.mark.skip_offline def test_pull_non_existent_docker_image(self, docker_client: ContainerClient): with pytest.raises(NoSuchImage): docker_client.pull_image("localstack_non_existing_image_for_tests") @pytest.mark.skip_offline def test_pull_docker_image_with_tag(self, docker_client: ContainerClient): try: docker_client.get_image_cmd("alpine", pull=False) safe_run([config.DOCKER_CMD, "rmi", "alpine"]) except ContainerException: pass with pytest.raises(NoSuchImage): docker_client.get_image_cmd("alpine", pull=False) docker_client.pull_image("alpine:3.13") assert ["/bin/sh"] == docker_client.get_image_cmd("alpine:3.13", pull=False) assert "alpine:3.13" in docker_client.inspect_image( "alpine:3.13", pull=False)["RepoTags"] @pytest.mark.skip_offline def test_pull_docker_image_with_hash(self, docker_client: ContainerClient): try: docker_client.get_image_cmd("alpine", pull=False) safe_run([config.DOCKER_CMD, "rmi", "alpine"]) except ContainerException: pass with pytest.raises(NoSuchImage): docker_client.get_image_cmd("alpine", pull=False) docker_client.pull_image( "alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a" ) assert ["/bin/sh"] == docker_client.get_image_cmd( "alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a", pull=False, ) assert ( "alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a" in docker_client.inspect_image( "alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a", pull=False, )["RepoDigests"]) @pytest.mark.skip_offline def test_run_container_automatic_pull(self, docker_client: ContainerClient): try: safe_run([config.DOCKER_CMD, "rmi", "alpine"]) except CalledProcessError: pass message = "test message" stdout, _ = docker_client.run_container("alpine", command=["echo", message], remove=True) assert message == stdout.decode(config.DEFAULT_ENCODING).strip() @pytest.mark.skip_offline def test_run_container_non_existent_image(self, docker_client: ContainerClient): try: safe_run([config.DOCKER_CMD, "rmi", "alpine"]) except CalledProcessError: pass with pytest.raises(NoSuchImage): stdout, _ = docker_client.run_container( "localstack_non_existing_image_for_tests", command=["echo", "test"], remove=True) def test_running_container_names(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) name = dummy_container.container_name assert name in docker_client.get_running_container_names() docker_client.stop_container(name) assert name not in docker_client.get_running_container_names() def test_is_container_running(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) name = dummy_container.container_name assert docker_client.is_container_running(name) docker_client.stop_container(name) assert not docker_client.is_container_running(name) @pytest.mark.skip_offline def test_docker_image_names(self, docker_client: ContainerClient): try: safe_run([config.DOCKER_CMD, "rmi", "alpine"]) except CalledProcessError: pass assert "alpine:latest" not in docker_client.get_docker_image_names() assert "alpine" not in docker_client.get_docker_image_names() docker_client.pull_image("alpine") assert "alpine:latest" in docker_client.get_docker_image_names() assert "alpine:latest" not in docker_client.get_docker_image_names( include_tags=False) assert "alpine" in docker_client.get_docker_image_names( include_tags=False) assert "alpine" in docker_client.get_docker_image_names() assert "alpine" not in docker_client.get_docker_image_names( strip_latest=False) def test_get_container_name(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) assert dummy_container.container_name == docker_client.get_container_name( dummy_container.container_id) def test_get_container_name_not_existing(self, docker_client: ContainerClient): not_existent_container = "not_existing_container" with pytest.raises(NoSuchContainer): docker_client.get_container_name(not_existent_container) def test_get_container_id(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) assert dummy_container.container_id == docker_client.get_container_id( dummy_container.container_name) def test_get_container_id_not_existing(self, docker_client: ContainerClient): not_existent_container = "not_existing_container" with pytest.raises(NoSuchContainer): docker_client.get_container_id(not_existent_container) def test_inspect_container(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) for identifier in [ dummy_container.container_id, dummy_container.container_name ]: assert dummy_container.container_id == docker_client.inspect_container( identifier)["Id"] assert (f"/{dummy_container.container_name}" == docker_client.inspect_container(identifier)["Name"]) @pytest.mark.skip_offline def test_inspect_image(self, docker_client: ContainerClient): docker_client.pull_image("alpine") assert "alpine" in docker_client.inspect_image("alpine")["RepoTags"][0] def test_inspect_network(self, docker_client: ContainerClient, create_network): network_name = "ls_test_network_%s" % short_uid() network_id = create_network(network_name) assert network_name == docker_client.inspect_network( network_name)["Name"] assert network_id == docker_client.inspect_network(network_name)["Id"] def test_inspect_network_non_existent_network( self, docker_client: ContainerClient): network_name = "ls_test_network_non_existent" with pytest.raises(NoSuchNetwork): docker_client.inspect_network(network_name) def test_copy_from_container(self, tmpdir, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) local_path = tmpdir.join("test_file") self._test_copy_from_container(local_path, local_path, "test_file", docker_client, dummy_container) def test_copy_from_container_to_different_file( self, tmpdir, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) local_path = tmpdir.join("test_file_2") self._test_copy_from_container(local_path, local_path, "test_file", docker_client, dummy_container) def test_copy_from_container_into_directory(self, tmpdir, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) local_path = tmpdir.mkdir("test_dir") file_path = local_path.join("test_file") self._test_copy_from_container(local_path, file_path, "test_file", docker_client, dummy_container) def test_copy_from_non_existent_container(self, tmpdir, docker_client: ContainerClient): local_path = tmpdir.mkdir("test_dir") with pytest.raises(NoSuchContainer): docker_client.copy_from_container( "hopefully_non_existent_container_%s" % short_uid(), str(local_path), "test_file") def _test_copy_from_container( self, local_path, file_path, container_file_name, docker_client: ContainerClient, dummy_container, ): docker_client.exec_in_container( dummy_container.container_id, command=["sh", "-c", f"echo TEST_CONTENT > {container_file_name}"], ) docker_client.copy_from_container( dummy_container.container_id, local_path=str(local_path), container_path=container_file_name, ) assert "TEST_CONTENT" == file_path.read().strip() def test_run_with_additional_arguments(self, docker_client: ContainerClient): env_variable = "TEST_FLAG=test_str" stdout, _ = docker_client.run_container( "alpine", remove=True, command=["env"], additional_flags=f"-e {env_variable}") assert env_variable in stdout.decode(config.DEFAULT_ENCODING) stdout, _ = docker_client.run_container( "alpine", remove=True, command=["env"], additional_flags=f"-e {env_variable}", env_vars={"EXISTING_VAR": "test_var"}, ) stdout = stdout.decode(config.DEFAULT_ENCODING) assert env_variable in stdout assert "EXISTING_VAR=test_var" in stdout def test_run_with_additional_arguments_add_host( self, docker_client: ContainerClient): additional_flags = "--add-host sometest.localstack.cloud:127.0.0.1" stdout, _ = docker_client.run_container( "alpine", remove=True, command=["getent", "hosts", "sometest.localstack.cloud"], additional_flags=additional_flags, ) stdout = stdout.decode(config.DEFAULT_ENCODING) assert "127.0.0.1" in stdout assert "sometest.localstack.cloud" in stdout def test_get_container_ip_non_existing_container( self, docker_client: ContainerClient): with pytest.raises(NoSuchContainer): docker_client.get_container_ip( "hopefully_non_existent_container_%s" % short_uid()) def test_get_container_ip(self, docker_client: ContainerClient, dummy_container): docker_client.start_container(dummy_container.container_id) ip = docker_client.get_container_ip(dummy_container.container_id) assert is_ipv4_address(ip) assert "127.0.0.1" != ip def test_commit_creates_image_from_running_container( self, docker_client: ContainerClient): image_name = "lorem" image_tag = "ipsum" image = f"{image_name}:{image_tag}" container_name = _random_container_name() try: docker_client.run_container( "alpine", name=container_name, command=["sleep", "60"], detach=True, ) docker_client.commit(container_name, image_name, image_tag) assert image in docker_client.get_docker_image_names() finally: docker_client.remove_container(container_name) docker_client.remove_image(image, force=True) def test_commit_image_raises_for_nonexistent_container( self, docker_client: ContainerClient): with pytest.raises(NoSuchContainer): docker_client.commit("nonexistent_container", "image_name", "should_not_matter") def test_remove_image_raises_for_nonexistent_image( self, docker_client: ContainerClient): image_name = "this_image" image_tag = "does_not_exist" image = f"{image_name}:{image_tag}" with pytest.raises(NoSuchImage): docker_client.remove_image(image, force=False) def test_get_container_ip_with_network(self, docker_client: ContainerClient, create_container, create_network): network_name = "ls_test_network_%s" % short_uid() create_network(network_name) container = create_container( "alpine", network=network_name, command=["sh", "-c", "while true; do sleep 1; done"]) docker_client.start_container(container.container_id) ip = docker_client.get_container_ip(container.container_id) assert re.match( r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", ip, ) assert "127.0.0.1" != ip def test_set_container_workdir(self, docker_client: ContainerClient): result = docker_client.run_container("alpine", command=["pwd"], workdir="/tmp", remove=True) assert "/tmp" == to_str(result[0]).strip() def test_connect_container_to_network(self, docker_client: ContainerClient, create_network, create_container): network_name = "ls_test_network_%s" % short_uid() create_network(network_name) container = create_container( "alpine", command=["sh", "-c", "while true; do sleep 1; done"]) docker_client.start_container(container.container_id) docker_client.connect_container_to_network( network_name, container_name_or_id=container.container_id) assert (container.container_id in docker_client.inspect_network( network_name).get("Containers").keys()) def test_connect_container_to_nonexistent_network( self, docker_client: ContainerClient, create_container): container = create_container( "alpine", command=["sh", "-c", "while true; do sleep 1; done"]) docker_client.start_container(container.container_id) with pytest.raises(NoSuchNetwork): docker_client.connect_container_to_network( f"invalid_network_{short_uid()}", container_name_or_id=container.container_id) def test_disconnect_container_from_nonexistent_network( self, docker_client: ContainerClient, create_container): container = create_container( "alpine", command=["sh", "-c", "while true; do sleep 1; done"]) docker_client.start_container(container.container_id) with pytest.raises(NoSuchNetwork): docker_client.disconnect_container_from_network( f"invalid_network_{short_uid()}", container_name_or_id=container.container_id) def test_connect_nonexistent_container_to_network( self, docker_client: ContainerClient, create_network, create_container): network_name = "ls_test_network_%s" % short_uid() create_network(network_name) with pytest.raises(NoSuchContainer): docker_client.connect_container_to_network( network_name, container_name_or_id=f"some-invalid-container-{short_uid()}") def test_disconnect_nonexistent_container_from_network( self, docker_client: ContainerClient, create_network, create_container): network_name = "ls_test_network_%s" % short_uid() create_network(network_name) with pytest.raises(NoSuchContainer): docker_client.disconnect_container_from_network( network_name, container_name_or_id=f"some-invalid-container-{short_uid()}") def test_connect_container_to_network_with_alias_and_disconnect( self, docker_client: ContainerClient, create_network, create_container): network_name = "ls_test_network_%s" % short_uid() container_alias = f"test-container-{short_uid()}.localstack.cloud" create_network(network_name) container = create_container( "alpine", command=["sh", "-c", "while true; do sleep 1; done"]) docker_client.start_container(container.container_id) docker_client.connect_container_to_network( network_name, container_name_or_id=container.container_id, aliases=[container_alias]) container_2 = create_container( "alpine", command=["ping", "-c", "1", container_alias], network=network_name) docker_client.start_container( container_name_or_id=container_2.container_id, attach=True) docker_client.disconnect_container_from_network( network_name, container.container_id) with pytest.raises(ContainerException): docker_client.start_container( container_name_or_id=container_2.container_id, attach=True)
def in_docker() -> bool: from localstack import config return config.in_docker()