def test_networking_scenario(): """ Listen via netcat in one container, send a secret message to the container via another one. """ image = DockerImage(THE_HELPER_IMAGE) r1 = DockerRunBuilder(command=["nc", "-l", "-k", "0.0.0.0", "1234"]) cont = image.run_via_binary(r1) # FIXME: wait time.sleep(0.2) assert cont.is_running() assert cont.get_IPv4s() assert cont.is_port_open(1234) assert not cont.is_port_open(2345) secret_text = b"gardener-did-it" r2 = DockerRunBuilder(command=["nc", cont.get_IPv4s()[0], "1234"]) r2.options = ["-i", "--rm"] cont2 = image.run_via_binary_in_foreground( r2, popen_params={"stdin": subprocess.PIPE}, container_name="test-container") # FIXME: wait time.sleep(1) assert "" == cont.logs().decode("utf-8").strip() assert cont2.is_running() assert cont.is_running() cont2.popen_instance.communicate(input=secret_text + b"\n") # give container time to process time.sleep(1) cont.stop() assert not cont2.is_running() assert not cont.is_running() assert secret_text == cont.logs().strip() cont.delete()
def test_get_port_mappings(): image = DockerImage(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) # the container needs to be running in order to get port mappings command = DockerRunBuilder(additional_opts=["-p", "321:123", "-i"]) container = image.run_via_binary(command) try: mappings = container.get_port_mappings(123) assert len(mappings) == 1 assert mappings == [{"HostIp": '0.0.0.0', "HostPort": '321'}] mappings = container.get_port_mappings() assert len(mappings) == 1 assert mappings == { '123/tcp': [{ 'HostIp': '0.0.0.0', 'HostPort': '321' }] } finally: container.delete(force=True) command = DockerRunBuilder() container = image.run_via_binary(command) try: mappings = container.get_port_mappings(123) assert not mappings finally: container.delete(force=True)
def test_container_create_failed(): image = DockerImage(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) # should raise an exc, there is no such command: waldo; we need to find waldo first with pytest.raises(ConuException): image.run_via_binary(DockerRunBuilder(command=["waldo"])) c = image.run_via_binary_in_foreground(DockerRunBuilder(command=["waldo"])) c.popen_instance.communicate() assert c.popen_instance.returncode > 0
def test_exit_code(): image = DockerImage(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) cmd = DockerRunBuilder(command=['sleep', '2']) cont = image.run_via_binary(cmd) assert cont.is_running() and cont.exit_code() == 0 p = Probe(timeout=5, fnc=cont.get_status, expected_retval='exited') p.run() assert not cont.is_running() and cont.exit_code() == 0 cmd = DockerRunBuilder(command=['bash', '-c', "exit 42"]) cont = image.run_via_binary(cmd) cont.wait() assert cont.exit_code() == 42
def get_container_output(backend, image_name, command, image_tag="latest", additional_opts=None): """ Create a throw-away container based on provided image and tag, run the supplied command in it and return output. The container is stopped and removed after it exits. :param backend: instance of DockerBackend :param image_name: str, name of the container image :param command: list of str, command to run in the container :param image_tag: str, container image tag, defaults to "latest" :param additional_opts: list of str, by default this function creates the container using docker binary and run command; with this argument you can supply addition options to the "docker run" invocation :return: str (unicode), output of the container """ image = backend.ImageClass(image_name, tag=image_tag) # FIXME: use run_via_api and make this a generic function c = image.run_via_binary( DockerRunBuilder(command=command, additional_opts=additional_opts)) try: c.wait() return c.logs_unicode() finally: c.stop() c.wait() c.delete()
def run_container(local_dir): """ serve path `local_dir` using the python http webserver in a docker container :param local_dir: str, path to the directory, it should exist :return: instance of DockerContainer """ image_name = "registry.fedoraproject.org/fedora" image_tag = "27" # we'll run our container using docker engine backend = DockerBackend(logging_level=logging.DEBUG) image = backend.ImageClass(image_name, tag=image_tag) # is the image present? try: image.get_metadata() except Exception: image.pull() # helper class to create `docker run ...` -- we want test the same experience as our users b = DockerRunBuilder( # the command to run in a container command=[ "python3", "-m", "http.server", "--bind", "0.0.0.0", "%d" % port ], # additional options passed to `run` command additional_opts=["-v", "%s:/webroot" % local_dir, "-w", "/webroot"]) # let's run the container (in the background) container = image.run_via_binary(run_command_instance=b) return container
def test_list_containers(): with DockerBackend() as backend: l = len(backend.list_containers()) assert l >= 0 image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG, pull_policy=DockerImagePullPolicy.NEVER) drb = DockerRunBuilder(command=["sleep", "1"], additional_opts=["-e", "FOO=BAR", "-p", "1234"]) container = image.run_via_binary(run_command_instance=drb) try: container_list = backend.list_containers() l = len(container_list) assert l >= 1 cont_under_test = [ x for x in container_list if x.metadata.identifier == container.get_id() ][0] assert cont_under_test.metadata.image # TODO: implement parsing docker_client.containers metadata # assert cont_under_test.metadata.command # assert cont_under_test.metadata.env_variables == {"FOO": "BAR"} # assert cont_under_test.metadata.exposed_ports == ["1234"] # assert cont_under_test.get_IPv4s() finally: container.delete(force=True)
def test_container_metadata(): with DockerBackend(logging_level=10) as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) c = image.run_via_binary( DockerRunBuilder(command=["cat"], additional_opts=[ '-i', '-t', '--name', 'my_container', '-p', '1234:12345', '-p', '123:12345', '-p', '8080', '--hostname', 'my_hostname', '-e', 'ENV1=my_env', '-e', 'ASD=', '-e', 'A=B=C=D', '-e', 'XYZ', '-l', 'testlabel1=testvalue1' ])) try: container_metadata = c.get_metadata() assert container_metadata.command == ["cat"] assert container_metadata.name == "my_container" assert container_metadata.env_variables["ENV1"] == "my_env" assert container_metadata.env_variables["ASD"] == "" assert container_metadata.env_variables["A"] == "B=C=D" assert container_metadata.hostname == "my_hostname" assert "XYZ" not in list(container_metadata.env_variables.keys()) assert '12345/tcp' in container_metadata.port_mappings assert container_metadata.port_mappings['12345/tcp'] == [1234, 123] assert '8080/tcp' in container_metadata.port_mappings assert container_metadata.exposed_ports == [ "12345/tcp", "8080/tcp" ] assert container_metadata.labels["testlabel1"] == "testvalue1" assert container_metadata.status == ContainerStatus.RUNNING finally: c.delete(force=True)
def test_dr_command_class(): simple = DockerRunBuilder() simple.image_name = "voodoo" assert ["docker", "run", "-l", CONU_ARTIFACT_TAG, "voodoo"] == simple.build() complex = DockerRunBuilder(additional_opts=["-a", "--foo"]) complex.image_name = "voodoo" assert ["docker", "run", "-a", "--foo", "-l", CONU_ARTIFACT_TAG, "voodoo"] == complex.build() w_cmd = DockerRunBuilder(command=["x", "y"], additional_opts=["-a", "--foo"]) w_cmd.image_name = "voodoo" assert ["docker", "run", "-a", "--foo", "-l", CONU_ARTIFACT_TAG, "voodoo", "x", "y"] == w_cmd.build() # test whether mutable params are not mutable across instances simple.options += ["spy"] assert "spy" not in DockerRunBuilder().options
def test_run_via_api(): with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) docker_run_builder = DockerRunBuilder(additional_opts=[ '-l', 'hello=there', '-l', 'oh=noo', '--name', 'test', '-d', '--hostname', 'my_hostname', '--rm', '--memory', '1G', '--workdir', '/tmp', '--env', 'ENV1=my_env', '-p', '123:12345', '--cap-add', 'MKNOD', '--cap-add', 'SYS_ADMIN', '--cap-drop', 'SYS_ADMIN', '--dns', 'www.example.com', '--volume', '/tmp:/tmp', '--no-healthcheck' ], command=['sleep', '10']) parameters = docker_run_builder.get_parameters() c = image.run_via_api(parameters) try: assert "Config" in c.inspect() assert c.get_id() == str(c) assert repr(c) assert isinstance(c.get_id(), string_types) finally: c.delete(force=True)
def execute_container_testing_cmd(): with DockerBackend() as backed: image = backed.ImageClass("nginix_rpw", "1.0.0") cmd = DockerRunBuilder(command=["which", "nginx"]) our_container = image.run_via_binary(cmd) assert our_container.exit_code() == 0, "command not found" print("******* ngnix was installed in container *******************8")
def test_run_container(testenv): i = get_image() cmd = DockerRunBuilder(additional_opts=build_variable_list(testenv['options'])) container = i.run_via_binary(cmd) container.wait_for_port(5432) expected_output = b' ?column? \n----------\n 1\n(1 row)\n' make_pg_client_request(container, "SELECT 1;", testenv['options'], expected_output=expected_output)
def test_version(testenv): i = get_image() cmd = DockerRunBuilder( additional_opts=build_variable_list(testenv['options']), command=["psql", "--version"] ) cont = i.run_via_binary(cmd) cont.wait() out = 'b\'psql (PostgreSQL) ' + pg_version + '\\n\'' assert str(cont.logs()) == out
def test_wait_for_status(): image = DockerImage(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) cmd = DockerRunBuilder(command=['sleep', '2']) cont = image.run_via_binary(cmd) start = time.time() p = Probe(timeout=6, fnc=cont.get_status, expected_retval='exited') p.run() end = time.time() - start assert end > 2, "Probe should wait till container status is exited" assert end < 7, "Probe should end when container status is exited"
def test_exit_code(): with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) cmd = DockerRunBuilder(command=['sleep', '2']) cont = image.run_via_binary(cmd) try: assert cont.is_running() and cont.exit_code() == 0 p = Probe(timeout=5, fnc=cont.get_status, expected_retval='exited') p.run() assert not cont.is_running() and cont.exit_code() == 0 finally: cont.delete(force=True) cmd = DockerRunBuilder(command=['bash', '-c', "exit 42"]) cont = image.run_via_binary(cmd) try: cont.wait() assert cont.exit_code() == 42 finally: cont.delete(force=True)
def test_get_port_mappings(): image_name = "registry.fedoraproject.org/fedora" image_tag = "27" image = DockerImage(image_name, image_tag) command = DockerRunBuilder(additional_opts=["-p", "321:123"]) try: image.get_metadata() except Exception: image.pull() container = image.run_via_binary(command) try: mappings = container.get_port_mappings(123) assert len(mappings) == 1 assert mappings == [{"HostIp": '0.0.0.0', "HostPort": '321'}] mappings = container.get_port_mappings() assert len(mappings) == 1 assert mappings == { '123/tcp': [{ 'HostIp': '0.0.0.0', 'HostPort': '321' }] } finally: container.stop() container.delete() command = DockerRunBuilder() container = image.run_via_binary(command) try: mappings = container.get_port_mappings(123) assert not mappings finally: container.stop() container.delete()
def test_nonblocking_execute(): with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) cmd = DockerRunBuilder(command=['sleep', 'infinity']) cont = image.run_via_binary(cmd) stream = cont.execute(["bash", "-c", "exit 0"], blocking=False) list(stream) gen = cont.execute(["printf", "asd"], blocking=False) assert [b"asd"] == list(gen) gen = cont.execute(["printf", "asd\nasd"], blocking=False) assert [b"asd\nasd"] == list(gen) cont.execute(["bash", "-c", "sleep 0.01; exit 110"], blocking=False)
def test_invoking_container(self): image = backend.ImageClass(image_name, tag=image_tag) c = image.run_via_binary(DockerRunBuilder(command=["bash", "-c", "ruby --version"])) try: c.wait() logs = list(c.logs())[0].decode("utf-8") finally: c.stop() c.wait() c.delete() assert "ruby " in logs if os.environ.get("VERSION", None): assert os.environ["VERSION"] in logs
def test_blocking_execute(): with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) cmd = DockerRunBuilder(command=['sleep', 'infinity']) cont = image.run_via_binary(cmd) cont.execute(["bash", "-c", "exit 0"]) assert [b"asd"] == cont.execute(["printf", "asd"]) assert [b"asd\nasd"] == cont.execute(["printf", "asd\nasd"]) with pytest.raises(ConuException) as ex: cont.execute(["bash", "-c", "exit 110"]) assert "exit code 110" in ex.value.message assert "bash" in ex.value.message
def e2e_case(i, results): # run master master = i.run_via_binary() master_started = master.is_running() add_result(master_started, 'It should be possible to start the master.') master.wait_for_port(8080, timeout=15) http_response = master.http_request(path='/json', port=8080) master_http_ok = http_response.ok add_result(master_http_ok, 'Master should start the web ui on port 8080') master_alive = 'ALIVE' in http_response.content.decode('utf-8') add_result(master_alive, 'Master should be alive.') if master_started and master.get_IPv4s(): master_ip = master.get_IPv4s()[0] # run worker run_params_worker = DockerRunBuilder(additional_opts=[ '-e', 'SPARK_MASTER_ADDRESS=' + master_ip + ':7077', '-e', 'SPARK_MASTER_UI_ADDRESS=http://' + master_ip + ':8080' ]) worker = i.run_via_binary(run_params_worker) worker_started = worker.is_running() add_result(worker_started, 'It should be possible to start the worker.') worker.wait_for_port(8081, timeout=15) http_response = worker.http_request(path='/json', port=8081) worker_http_ok = http_response.ok add_result(worker_http_ok, 'Worker should start the web ui on port 8081') worker_registered_web_ui = 'spark://%s:7077' % master_ip in http_response.content.decode( 'utf-8') add_result(worker_registered_web_ui, "Worker web ui should contain the master's ip") worker_registered_logs = 'Registering worker' in (b'\n'.join( master.logs())).decode('utf-8') add_result( worker_registered_logs, "In the master's log file there should be worker registration message" ) master_registered_logs = 'registered with master' in (b'\n'.join( worker.logs())).decode('utf-8') add_result( master_registered_logs, "In the worker's log file master registration should be mentioned")
def test_set_name(): with DockerBackend() as backend: test_name = 'jondoe' image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG, pull_policy=DockerImagePullPolicy.NEVER) cont = image.run_via_binary() assert cont.name cont.delete(force=True) cont = image.run_via_binary_in_foreground() assert cont.name cont.delete(force=True) cmd = DockerRunBuilder(additional_opts=['--name', test_name]) cont = image.run_via_binary(cmd) assert cont.name == test_name cont.delete(force=True) cmd = DockerRunBuilder(additional_opts=['--name', test_name]) cont = image.run_via_binary_in_foreground(cmd) assert cont.name == test_name cont.delete(force=True)
def make_pg_client_request(container, pg_cmd, opts, expected_output=None): cmd = DockerRunBuilder( additional_opts = ["-e", "PGPASSWORD="******"psql", "postgresql://" + opts['POSTGRESQL_USER'] + "@" + container.get_IPv4s()[0] + ":5432/" + opts['POSTGRESQL_DATABASE'], "-c", pg_cmd] ) client_container = get_image().run_via_binary(cmd) assert not expected_output or client_container.logs() == expected_output client_container.wait(timeout=10) assert client_container.exit_code() == 0 assert client_container.logs() == expected_output client_container.delete()
def test_copy_to(tmpdir): content = b"gardener did it" p = tmpdir.join("secret") p.write(content) image = DockerImage(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) c = image.run_via_binary( DockerRunBuilder(command=["cat"], additional_opts=["-i", "-t"])) try: c.copy_to(str(p), "/") assert content == c.execute(["cat", "/secret"]) finally: c.stop() c.delete()
def test_copy_from(tmpdir): with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) c = image.run_via_binary( DockerRunBuilder(command=["cat"], additional_opts=["-i", "-t"])) try: c.copy_from("/etc/fedora-release", str(tmpdir)) with open(os.path.join(str(tmpdir), "fedora-release")) as fd: assert fd.read() == "Fedora release 26 (Twenty Six)\n" c.copy_from("/etc", str(tmpdir)) os.path.exists(os.path.join(str(tmpdir), "passwd")) finally: c.delete(force=True)
def test_copy_to(tmpdir): content = b"gardener did it" p = tmpdir.join("secret") p.write(content) with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) c = image.run_via_binary( DockerRunBuilder(command=["cat"], additional_opts=["-i", "-t"])) try: c.copy_to(str(p), "/") assert [content] == c.execute(["cat", "/secret"]) finally: c.delete(force=True)
def test_s2i_extending(tmpdir): t = str(tmpdir) exec_path = os.path.join(t, "secret-executable") secret_message = "Can I have a cup of cocoa?" with open(exec_path, "w") as fd: fd.write("""\ #!/bin/bash echo "%s" """ % secret_message) os.chmod(exec_path, 0o755) i = S2IDockerImage(S2I_IMAGE) ei = i.extend(t, "extended-punchbag") c = ei.run_via_binary(DockerRunBuilder()) c.wait() assert c.logs().decode("utf-8").strip() == secret_message
def check(self, target): passed = self.all_must_be_present cleanup = False if target.target_type is TargetType.IMAGE: drb = DockerRunBuilder(command=["/bin/sleep", "infinity"], additional_opts=["--entrypoint="]) cont = target.instance.run_via_binary(run_command_instance=drb) cleanup = True elif target.target_type is TargetType.CONTAINER: cont = target.instance else: return CheckResult(ok=False, description=self.description, message=self.message, reference_url=self.reference_url, check_name=self.name, logs=[ "Unsupported target, this check can " "process only containers and images" ]) logs = [] try: for f in self.files: cmd = ["/bin/ls", "-1", f] try: f_present = cont.execute(cmd) logs.append("File '{}' is {}present.".format( f, "" if f_present else "not ")) except ConuException as ex: logger.info("File %s is not present, ex: %s", f, ex) f_present = False logs.append("File {} is not present.".format(f)) if self.all_must_be_present: passed = f_present and passed else: passed = f_present or passed return CheckResult(ok=passed, description=self.description, message=self.message, reference_url=self.reference_url, check_name=self.name, logs=logs) finally: if cleanup: cont.stop() cont.delete()
def test_wait_for_status(): with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) cmd = DockerRunBuilder(command=['sleep', '2']) cont = image.run_via_binary(cmd) try: start = time.time() p = Probe(timeout=6, fnc=cont.get_status, expected_retval='exited') p.run() end = time.time() - start assert end > 2, "Probe should wait till container status is exited" assert end < 7, "Probe should end when container status is exited" finally: cont.delete(force=True)
def test_container_logs(): with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) command = ["bash", "-c", "for x in `seq 1 5`; do echo $x; done"] r = DockerRunBuilder(command=command) cont = image.run_via_binary(r) try: Probe(timeout=5, fnc=cont.get_status, expected_retval='exited').run() assert not cont.is_running() assert list( cont.logs()) == [b"1\n", b"2\n", b"3\n", b"4\n", b"5\n"] assert cont.logs_unicode() == "1\n2\n3\n4\n5\n" assert cont.logs_in_bytes() == b"1\n2\n3\n4\n5\n" finally: cont.delete(force=True)
def test_container(): """ Basic tests of interacting with a container """ with DockerBackend() as backend: image = backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) c = image.run_via_binary( DockerRunBuilder(command=["cat"], additional_opts=["-i", "-t"])) try: assert "Config" in c.inspect() assert "Config" in c.inspect() assert c.get_id() == str(c) assert repr(c) assert isinstance(c.get_id(), string_types) finally: c.delete(force=True)