def test_list_containers(podman_backend): l = len(podman_backend.list_containers()) assert l >= 0 image = podman_backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG, pull_policy=PodmanImagePullPolicy.NEVER) prb = PodmanRunBuilder(command=["sleep", "1"], additional_opts=[ "-e", "FOO=BAR", ]) container = image.run_via_binary(run_command_instance=prb) try: container_list = podman_backend.list_containers() l = len(container_list) assert l >= 1 print(container_list[0].metadata.identifier) cont_under_test = [ x for x in container_list if x.metadata.identifier == container.get_id() ][0] assert cont_under_test.metadata.image assert cont_under_test.metadata.command assert cont_under_test.metadata.env_variables["FOO"] == "BAR" assert cont_under_test.get_IPv4s() finally: container.delete(force=True)
def podman_run_builder(): prb = PodmanRunBuilder() # there is no journal in a container: # ERRO[0001] unable to write pod event: # "write unixgram @00120->/run/systemd/journal/socket: # sendmsg: no such file or directory" # prb.global_options = ["--events-backend=none"] # alternatively, do this in /etc/containers/libpod.conf return prb
def test_container_create_failed(podman_backend): """ Test podman run with execution non-existing command """ # FIXME: Cleanup containers after run image = podman_backend.ImageClass(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(command=["waldo"]) c = image.run_via_binary_in_foreground(PodmanRunBuilder(command=["waldo"])) c.popen_instance.communicate() try: assert c.popen_instance.returncode > 0 finally: c.delete(force=True)
def test_container_metadata(podman_backend): image = podman_backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) # TODO: add port bindings to the mix once they are supported in rootless mode c = image.run_via_binary( PodmanRunBuilder( command=["cat"], additional_opts=[ '-i', '-t', '--name', 'mycontainer', # '-p', '1234:12345', # '-p', '123:12345', # '-p', '8080', '--hostname', 'my_hostname', '-e', 'ENV1=my_env', '-e', 'ASD=', '-e', 'A=B=C=D', '--label', 'testlabel1=testvalue1' ])) try: container_metadata = c.get_metadata() assert container_metadata.command == ["cat"] assert container_metadata.name == "mycontainer" 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" # FIXME: podman raise an error when you send option '-e XYZ': no such env variable # assert "XYZ" not in list(container_metadata.env_variables.keys()) # assert 12345 in container_metadata.port_mappings # assert container_metadata.port_mappings[12345] == [1234, 123] # assert 8080 in container_metadata.port_mappings # assert set(container_metadata.exposed_ports) == {8080, 12345} assert container_metadata.labels["testlabel1"] == "testvalue1" assert container_metadata.status == ContainerStatus.RUNNING finally: c.delete(force=True)
def test_container(podman_backend): """ Basic tests of interacting with a podman container """ image = podman_backend.ImageClass(FEDORA_MINIMAL_REPOSITORY, tag=FEDORA_MINIMAL_REPOSITORY_TAG) c = image.run_via_binary( PodmanRunBuilder(command=["cat"], additional_opts=["-i", "-t"])) try: assert c.is_running() 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)
def run_via_binary_in_foreground(self, run_command_instance=None, command=None, volumes=None, additional_opts=None, popen_params=None, container_name=None): """ Create a container using this image and run it in foreground; this method is useful to test real user scenarios when users invoke containers using binary and pass input into the container via STDIN. You are also responsible for: * redirecting STDIN when intending to use container.write_to_stdin afterwards by setting popen_params={"stdin": subprocess.PIPE} during run_via_binary_in_foreground * checking whether the container exited successfully via: container.popen_instance.returncode Please consult the documentation for subprocess python module for best practices on how you should work with instance of Popen :param run_command_instance: instance of PodmanRunBuilder :param command: list of str, command to run in the container, examples: - ["ls", "/"] - ["bash", "-c", "ls / | grep bin"] :param volumes: tuple or list of tuples in the form: * `("/path/to/directory", )` * `("/host/path", "/container/path")` * `("/host/path", "/container/path", "mode")` * `(conu.Directory('/host/path'), "/container/path")` (source can be also Directory instance) :param additional_opts: list of str, additional options for `docker run` :param popen_params: dict, keyword arguments passed to Popen constructor :param container_name: str, pretty container identifier :return: instance of PodmanContainer """ logger.info("run container via binary in foreground") if (command is not None or additional_opts is not None) \ and run_command_instance is not None: raise ConuException( "run_command_instance and command parameters cannot be " "passed into method at same time") if run_command_instance is None: command = command or [] additional_opts = additional_opts or [] if (isinstance(command, list) or isinstance(command, tuple) and isinstance(additional_opts, list) or isinstance(additional_opts, tuple)): run_command_instance = PodmanRunBuilder( command=command, additional_opts=additional_opts) else: raise ConuException( "command and additional_opts needs to be list of str or None" ) else: run_command_instance = run_command_instance or PodmanRunBuilder() if not isinstance(run_command_instance, PodmanRunBuilder): raise ConuException("run_command_instance needs to be an " "instance of PodmanRunBuilder") popen_params = popen_params or {} run_command_instance.image_name = self.get_id() if container_name: run_command_instance.options += ["--name", container_name] if volumes: run_command_instance.options += self.get_volume_options( volumes=volumes) def callback(): return subprocess.Popen(run_command_instance.build(), **popen_params) container_id, popen_instance = self._run_container( run_command_instance, callback) actual_name = graceful_get(self._inspect(container_id), "Name") if container_name and container_name != actual_name: raise ConuException( "Unexpected container name value. Expected = " + str(container_name) + " Actual = " + str(actual_name)) if not container_name: container_name = actual_name return PodmanContainer(self, container_id, popen_instance=popen_instance, name=container_name)
def run_via_binary(self, run_command_instance=None, command=None, volumes=None, additional_opts=None, **kwargs): """ create a container using this image and run it in background; this method is useful to test real user scenarios when users invoke containers using binary :param run_command_instance: instance of PodmanRunBuilder :param command: list of str, command to run in the container, examples: - ["ls", "/"] - ["bash", "-c", "ls / | grep bin"] :param volumes: tuple or list of tuples in the form: * `("/path/to/directory", )` * `("/host/path", "/container/path")` * `("/host/path", "/container/path", "mode")` * `(conu.Directory('/host/path'), "/container/path")` (source can be also Directory instance) :param additional_opts: list of str, additional options for `podman run` :return: instance of PodmanContainer """ logger.info("run container via binary in background") if (command is not None or additional_opts is not None) \ and run_command_instance is not None: raise ConuException( "run_command_instance and command parameters cannot be passed " "into method at same time") if run_command_instance is None: command = command or [] additional_opts = additional_opts or [] if (isinstance(command, list) or isinstance(command, tuple) and isinstance(additional_opts, list) or isinstance(additional_opts, tuple)): run_command_instance = PodmanRunBuilder( command=command, additional_opts=additional_opts) else: raise ConuException( "command and additional_opts needs to be list of str or None" ) else: run_command_instance = run_command_instance or PodmanRunBuilder() if not isinstance(run_command_instance, PodmanRunBuilder): raise ConuException( "run_command_instance needs to be an instance of PodmanRunBuilder" ) run_command_instance.image_name = self.get_id() run_command_instance.options += ["-d"] if volumes: run_command_instance.options += self.get_volume_options( volumes=volumes) def callback(): try: # FIXME: catch std{out,err}, print stdout to logger.debug, stderr to logger.error run_cmd(run_command_instance.build()) except subprocess.CalledProcessError as ex: raise ConuException("Container exited with an error: %s" % ex.returncode) container_id, _ = self._run_container(run_command_instance, callback) container_name = graceful_get(self._inspect(container_id), "Name") return PodmanContainer(self, container_id, name=container_name)