コード例 #1
0
ファイル: test_runner.py プロジェクト: xwalls/popper
    def test_clone_repos(self):
        wf_data = {"steps": [{"uses": "popperized/bin/sh@master"}]}
        wf = WorkflowParser.parse(wf_data=wf_data)

        cache_dir = os.path.join(os.environ["HOME"], ".cache/popper/")

        # clone repos in the default cache directory.
        conf = ConfigLoader.load()
        runner = WorkflowRunner(conf)
        runner._clone_repos(wf)
        step_dir = os.path.join(cache_dir, conf.wid,
                                "github.com/popperized/bin")
        self.assertTrue(os.path.exists(step_dir))

        # clone repos in custom cache directory
        os.environ["POPPER_CACHE_DIR"] = "/tmp/smdir"
        conf = ConfigLoader.load()
        runner = WorkflowRunner(conf)
        runner._clone_repos(wf)
        step_dir = os.path.join("/tmp/smdir", conf.wid,
                                "github.com/popperized/bin")
        self.assertTrue(os.path.exists(step_dir))
        os.environ.pop("POPPER_CACHE_DIR")

        # check failure when container is not available and we skip cloning
        shutil.rmtree("/tmp/smdir")
        shutil.rmtree(cache_dir)
        conf = ConfigLoader.load(skip_clone=True)
        runner = WorkflowRunner(conf)
        self.assertRaises(SystemExit, runner._clone_repos, wf)
コード例 #2
0
ファイル: test_runner.py プロジェクト: xwalls/popper
    def test_check_secrets(self):
        wf_data = {
            "steps": [{
                "uses": "docker://alpine:3.9",
                "args": ["ls", "-ltr"],
                "secrets": ["SECRET_ONE", "SECRET_TWO"],
            }]
        }
        wf = WorkflowParser.parse(wf_data=wf_data)

        # in dry-run, secrets are ignored
        runner = WorkflowRunner(ConfigLoader.load(dry_run=True))
        runner._process_secrets(wf)

        # now go back to not dry-running
        runner = WorkflowRunner(ConfigLoader.load())

        # when CI=true it should fail
        os.environ["CI"] = "true"
        self.assertRaises(SystemExit, runner._process_secrets, wf)

        # add one secret
        os.environ["SECRET_ONE"] = "1234"

        # it should fail again, as we're missing one
        self.assertRaises(SystemExit, runner._process_secrets, wf)

        os.environ.pop("CI")

        # now is fine
        with patch("getpass.getpass", return_value="5678"):
            runner._process_secrets(wf)

        # pop the other
        os.environ.pop("SECRET_ONE")
コード例 #3
0
ファイル: test_runner_host.py プロジェクト: zacswolf/popper
    def test_docker_basic_run(self):
        repo = self.mk_repo()
        conf = ConfigLoader.load(workspace_dir=repo.working_dir)
        test_string = "STEP_INFO:popper:Successfully tagged popperized/bin:master"

        with WorkflowRunner(conf) as r:
            wf_data = {
                "steps": [{
                    "uses": "popperized/bin/sh@master",
                    "args": ["ls"],
                }]
            }
            with self.assertLogs(log, level="STEP_INFO") as cm:
                r.run(WorkflowParser.parse(wf_data=wf_data))
            self.assertTrue(test_string in cm.output,
                            f"Got cmd output: {cm.output}")

            wf_data = {
                "steps": [{
                    "uses": "docker://*****:*****@master",
                    "args": ["ls"],
                }]
            }
            with self.assertLogs(log, level="STEP_INFO") as cm:
                r.run(WorkflowParser.parse(wf_data=wf_data))
            self.assertTrue(test_string not in cm.output)

        repo.close()
        shutil.rmtree(repo.working_dir, ignore_errors=True)
コード例 #4
0
    def test_create_cmd(self):
        self.maxDiff = None
        config = {"workspace_dir": "/w"}
        with DockerRunner(config=ConfigLoader.load(**config)) as drunner:
            step = Box({"args": ["-two", "-flags"]}, default_box=True)
            cmd = drunner._create_cmd(step, "foo:1.9", "container_name")

            expected = ("docker create"
                        " --name container_name"
                        " --workdir /workspace"
                        " -v /w:/workspace:Z"
                        " -v /var/run/docker.sock:/var/run/docker.sock"
                        "   foo:1.9 -two -flags")

            self.assertEqual(expected, cmd)

        config_dict = {
            "engine": {
                "name": "docker",
                "options": {
                    "privileged": True,
                    "hostname": "popper.local",
                    "domainname": "www.example.org",
                    "volumes": ["/path/in/host:/path/in/container"],
                    "environment": {
                        "FOO": "bar"
                    },
                },
            },
            "resource_manager": {
                "name": "slurm"
            },
        }

        config = {"workspace_dir": "/w", "config_file": config_dict}
        with DockerRunner(config=ConfigLoader.load(**config)) as drunner:
            step = Box({"args": ["-two", "-flags"]}, default_box=True)
            cmd = drunner._create_cmd(step, "foo:1.9", "container_name")

            expected = ("docker create --name container_name "
                        "--workdir /workspace "
                        "-v /w:/workspace:Z "
                        "-v /var/run/docker.sock:/var/run/docker.sock "
                        "-v /path/in/host:/path/in/container "
                        "-e FOO=bar   --privileged --hostname popper.local "
                        "--domainname www.example.org"
                        " foo:1.9 -two -flags")

            self.assertEqual(expected, cmd)
コード例 #5
0
ファイル: test_runner_host.py プロジェクト: zacswolf/popper
    def test_get_container_options(self):
        config_dict = {
            "engine": {
                "name": "singularity",
                "options": {
                    "hostname": "popper.local",
                    "ipc": True,
                    "bind": ["/path/in/host:/path/in/container"],
                },
            }
        }

        config = ConfigLoader.load(config_file=config_dict)
        with SingularityRunner(config=config) as sr:
            sr._setup_singularity_cache()
            options = sr._get_container_options()
            self.assertEqual(
                options,
                [
                    "--userns",
                    "--pwd",
                    "/workspace",
                    "--bind",
                    f"{os.getcwd()}:/workspace",
                    "--bind",
                    "/path/in/host:/path/in/container",
                    "--hostname",
                    "popper.local",
                    "--ipc",
                ],
            )
コード例 #6
0
    def test_exec_mpi_failure(self, mock_kill):
        config_dict = {
            "engine": {
                "name": "singularity",
                "options": {},
            },
            "resource_manager": {
                "name": "slurm",
                "options": {
                    "1": {
                        "nodes": 2,
                        "nodelist": "worker1,worker2",
                        "overcommit": True
                    }
                },
            },
        }

        config = ConfigLoader.load(workspace_dir="/w", config_file=config_dict)

        self.Popen.set_command(
            "sbatch "
            "--wait --overcommit "
            f"popper_1_{config.wid}.sh",
            returncode=12,
        )

        self.Popen.set_command(f"tail -f popper_1_{config.wid}.out",
                               returncode=0)

        with WorkflowRunner(config) as r:
            wf_data = {"steps": [{"uses": "docker://alpine", "args": ["ls"]}]}
            self.assertRaises(SystemExit, r.run,
                              WorkflowParser.parse(wf_data=wf_data))
コード例 #7
0
ファイル: cmd_sh.py プロジェクト: zacswolf/popper
def cli(ctx, file, step, entrypoint, skip_pull, skip_clone, substitution,
        conf):
    """Opens an interactive shell using all the attributes defined in the workflow file
    for the given STEP, but ignoring ``runs`` and ``args``. By default, it invokes
    /bin/bash. If you need to invoke another one, you can specify it in the --entrypoint
    flag.

    NOTE: this command only works for (local) host runner in Docker.
    """
    wf = WorkflowParser.parse(file=file,
                              step=step,
                              immutable=False,
                              substitutions=substitution)

    # override entrypoint
    step = wf.steps[0]
    step.args = []
    step.runs = entrypoint

    # configure runner so containers execute in attached mode and create a tty
    config = ConfigLoader.load(
        engine_name="docker",
        pty=True,
        skip_pull=skip_pull,
        skip_clone=skip_clone,
        config_file=conf,
    )

    with WorkflowRunner(config) as runner:
        try:
            runner.run(wf)
        except Exception as e:
            log.debug(traceback.format_exc())
            log.fail(e)
コード例 #8
0
 def test_prepare_environment_with_git(self):
     repo = self.mk_repo()
     conf = ConfigLoader.load(workspace_dir=repo.working_dir)
     with StepRunner(conf) as r:
         step = Box({
             "name": "a",
             "env": {
                 "FOO": "BAR"
             },
             "secrets": ["A"]
         },
                    default_box=True)
         os.environ["A"] = "BC"
         env = r._prepare_environment(step, {"other": "b"})
         expected = {
             "FOO": "BAR",
             "A": "BC",
             "other": "b",
             "GIT_COMMIT": conf.git_commit,
             "GIT_BRANCH": conf.git_branch,
             "GIT_SHA_SHORT": conf.git_sha_short,
             "GIT_REMOTE_ORIGIN_URL": conf.git_remote_origin_url,
             "GIT_TAG": conf.git_tag,
         }
         self.assertDictEqual(expected, env)
         os.environ.pop("A")
コード例 #9
0
ファイル: test_config.py プロジェクト: vipulchhabra99/popper
 def test_config_with_git_repo(self):
     r = self.mk_repo()
     conf = ConfigLoader.load(workspace_dir=r.working_dir)
     sha = r.head.object.hexsha
     self.assertEqual(r.git.rev_parse(sha), conf.git_commit)
     self.assertEqual(r.git.rev_parse(sha, short=7), conf.git_sha_short)
     self.assertEqual(r.active_branch.name, conf.git_branch)
コード例 #10
0
 def test_create_container(self):
     config = ConfigLoader.load()
     step = Box(
         {
             "uses": "docker://alpine:3.9",
             "runs": ["echo hello"],
             "id": "kontainer_one",
         },
         default_box=True,
     )
     cid = pu.sanitized_name(step.id, config.wid)
     with DockerRunner(init_docker_client=True, config=config) as dr:
         c = dr._create_container(cid, step)
         self.assertEqual(c.status, "created")
         c.remove()
     step = Box(
         {
             "uses": "docker://alpine:3.9",
             "runs": ["echo", "hello_world"],
             "id": "KoNtAiNeR tWo",
         },
         default_box=True,
     )
     cid = pu.sanitized_name(step.id, config.wid)
     with DockerRunner(init_docker_client=True, config=config) as dr:
         c = dr._create_container(cid, step)
         self.assertEqual(c.status, "created")
         c.remove()
コード例 #11
0
ファイル: test_runner_host.py プロジェクト: xwalls/popper
    def test_docker_basic_run(self):
        repo = self.mk_repo()
        conf = ConfigLoader.load(workspace_dir=repo.working_dir)

        with WorkflowRunner(conf) as r:
            wf_data = {"steps": [{"uses": "popperized/bin/sh@master", "args": ["ls"],}]}
            r.run(WorkflowParser.parse(wf_data=wf_data))

            wf_data = {
                "steps": [
                    {
                        "uses": "docker://alpine:3.9",
                        "args": ["sh", "-c", "echo $FOO > hello.txt ; pwd"],
                        "env": {"FOO": "bar"},
                    }
                ]
            }
            r.run(WorkflowParser.parse(wf_data=wf_data))
            with open(os.path.join(repo.working_dir, "hello.txt"), "r") as f:
                self.assertEqual(f.read(), "bar\n")

            wf_data = {
                "steps": [
                    {
                        "uses": "docker://alpine:3.9",
                        "args": ["nocommandisnamedlikethis"],
                    }
                ]
            }
            self.assertRaises(SystemExit, r.run, WorkflowParser.parse(wf_data=wf_data))

        repo.close()
        shutil.rmtree(repo.working_dir, ignore_errors=True)
コード例 #12
0
ファイル: test_runner_host.py プロジェクト: zacswolf/popper
 def test_setup_singularity_cache(self):
     config = ConfigLoader.load()
     with SingularityRunner(config=config) as sr:
         sr._setup_singularity_cache()
         self.assertEqual(
             f'{os.environ["HOME"]}/.cache/popper/singularity/{config.wid}',
             sr._singularity_cache,
         )
コード例 #13
0
    def test_create_cmd(self):
        config = ConfigLoader.load(workspace_dir="/w")
        with SingularityRunner(config=config) as sr:
            step = Box({"args": ["-two", "-flags"]}, default_box=True)
            sr._setup_singularity_cache()
            sr._container = os.path.join(sr._singularity_cache, "c1.sif")
            cmd = sr._create_cmd(step, "c1.sif")

            expected = (
                "singularity run"
                " --userns --pwd /workspace"
                " --bind /w:/workspace"
                f' {os.environ["HOME"]}/.cache/popper/singularity/{config.wid}/c1.sif'
                " -two -flags")

            self.assertEqual(expected, cmd)

        config_dict = {
            "engine": {
                "name": "singularity",
                "options": {
                    "hostname": "popper.local",
                    "ipc": True,
                    "bind": ["/path/in/host:/path/in/container"],
                },
            },
            "resource_manager": {
                "name": "slurm"
            },
        }

        config = ConfigLoader.load(workspace_dir="/w", config_file=config_dict)

        with SingularityRunner(config=config) as sr:
            step = Box({"args": ["-two", "-flags"]}, default_box=True)
            sr._setup_singularity_cache()
            sr._container = os.path.join(sr._singularity_cache, "c2.sif")
            cmd = sr._create_cmd(step, "c2.sif")

            # fmt: off
            expected = f"singularity run --userns --pwd /workspace --bind /w:/workspace --bind /path/in/host:/path/in/container --hostname popper.local --ipc {os.environ['HOME']}/.cache/popper/singularity/{config.wid}/c2.sif -two -flags"
            # fmt: on

            self.assertEqual(expected, cmd)
コード例 #14
0
    def test_submit_batch_job(self, mock_kill):
        config = ConfigLoader.load(workspace_dir="/w")
        self.Popen.set_command(
            "sbatch --wait "
            f"--job-name popper_sample_{config.wid} "
            f"--output {slurm_cache_dir}/popper_sample_{config.wid}.out "
            f"{slurm_cache_dir}/popper_sample_{config.wid}.sh",
            returncode=0,
        )
        self.Popen.set_command(
            f"tail -f {slurm_cache_dir}/popper_sample_{config.wid}.out",
            returncode=0)
        step = Box({"id": "sample"}, default_box=True)
        with SlurmRunner(config=config) as sr:
            sr._submit_batch_job(["ls -la"], step)
            with open(f"{slurm_cache_dir}/popper_sample_{config.wid}.sh",
                      "r") as f:
                content = f.read()

            self.assertEqual(content, "#!/bin/bash\nls -la")
            self.assertEqual(len(sr._spawned_jobs), 0)
            self.assertEqual(sr._out_stream_thread.is_alive(), False)

        call_tail = call.Popen(
            [
                "tail", "-f",
                f"{slurm_cache_dir}/popper_sample_{config.wid}.out"
            ],
            cwd=os.getcwd(),
            env=None,
            preexec_fn=os.setsid,
            stderr=-2,
            stdout=-1,
            universal_newlines=True,
        )

        call_sbatch = call.Popen(
            [
                "sbatch",
                "--wait",
                "--job-name",
                f"popper_sample_{config.wid}",
                "--output",
                f"{slurm_cache_dir}/popper_sample_{config.wid}.out",
                f"{slurm_cache_dir}/popper_sample_{config.wid}.sh",
            ],
            cwd=os.getcwd(),
            env=None,
            preexec_fn=os.setsid,
            stderr=-2,
            stdout=-1,
            universal_newlines=True,
        )

        self.assertEqual(call_tail in self.Popen.all_calls, True)
        self.assertEqual(call_sbatch in self.Popen.all_calls, True)
コード例 #15
0
    def test_pod_create_delete_exitcode(self):
        repo = self.mk_repo()
        conf = ConfigLoader.load(workspace_dir=repo.working_dir)
        with KubernetesRunner(config=conf) as kr:
            kr._vol_claim_create()
            step = Box(
                {
                    "id": "test",
                    "uses": "docker://alpine:3.9",
                    "runs": ("echo", "hello"),
                },
                default_box=True,
            )
            kr._pod_name = kr._base_pod_name + f"-{step.id}"
            kr._pod_create(step, "alpine:3.9")
            self.assertEqual(kr._pod_exit_code(), 0)
            response = self._kclient.read_namespaced_pod(kr._pod_name,
                                                         namespace="default")
            self.assertEqual(response.status.phase, "Succeeded")
            kr._pod_delete()
            self.assertRaises(
                Exception,
                self._kclient.read_namespaced_pod,
                **{
                    "name": kr._pod_name,
                    "namespace": "default"
                },
            )

            time.sleep(5)

            step = Box(
                {
                    "id": "test",
                    "uses": "docker://alpine:3.9",
                    "runs": ("ecdho", "hello"),
                },
                default_box=True,
            )
            kr._pod_name = kr._base_pod_name + f"-{step.id}"
            kr._pod_create(step, "alpine:3.9")
            self.assertEqual(kr._pod_exit_code(), 1)
            response = self._kclient.read_namespaced_pod(kr._pod_name,
                                                         namespace="default")
            self.assertEqual(response.status.phase, "Failed")
            kr._pod_delete()
            kr._vol_claim_delete()

            self.assertRaises(
                Exception,
                self._kclient.read_namespaced_pod,
                **{
                    "name": kr._pod_name,
                    "namespace": "default"
                },
            )
コード例 #16
0
ファイル: test_config.py プロジェクト: vipulchhabra99/popper
 def test_config_non_defaults(self):
     expected = {
         "skip_clone": True,
         "skip_pull": True,
         "dry_run": True,
         "workspace_dir": os.path.realpath("/tmp/foo"),
         "quiet": True,
         "reuse": True,
     }
     conf = ConfigLoader.load(**expected)
     self.assertEqual(expected,
                      TestPopperConfig.extract_dict(expected, conf))
コード例 #17
0
    def test_run(self, mock_kill):
        config_dict = {
            "engine": {
                "name": "podman",
                "options": {
                    "privileged": True,
                    "hostname": "popper.local",
                    "domainname": "www.example.org",
                    "volumes": ["/path/in/host:/path/in/container"],
                    "environment": {
                        "FOO": "bar"
                    },
                },
            },
            "resource_manager": {
                "name": "slurm"
            },
        }

        config = ConfigLoader.load(workspace_dir="/w", config_file=config_dict)

        self.Popen.set_command(
            f"sbatch --wait --job-name popper_1_{config.wid} "
            f"--output {slurm_cache_dir}/popper_1_{config.wid}.out "
            f"{slurm_cache_dir}/popper_1_{config.wid}.sh",
            returncode=0,
        )

        self.Popen.set_command(
            f"tail -f {slurm_cache_dir}/popper_1_{config.wid}.out",
            returncode=0)

        with WorkflowRunner(config) as r:
            wf_data = {
                "steps": [{
                    "uses": "popperized/bin/sh@master",
                    "runs": ["cat"],
                    "args": ["README.md"],
                }]
            }
            r.run(WorkflowParser.parse(wf_data=wf_data))

        with open(f"{slurm_cache_dir}/popper_1_{config.wid}.sh", "r") as f:
            # fmt: off
            expected = f"""#!/bin/bash
podman rm -f popper_1_{config.wid} || true
podman build -t popperized/bin:master {os.environ['HOME']}/.cache/popper/{config.wid}/github.com/popperized/bin/sh
podman create --name popper_1_{config.wid} --workdir /workspace --entrypoint cat -v /w:/workspace:Z -v /path/in/host:/path/in/container -e FOO=bar   --privileged --hostname popper.local --domainname www.example.org popperized/bin:master README.md
podman start --attach popper_1_{config.wid}"""
            # fmt: on
            actual = f.read()
            self.maxDiff = None
            self.assertEqual(expected, actual)
コード例 #18
0
    def test_create_cmd(self):
        config = ConfigLoader.load(workspace_dir="/w")
        with SingularityRunner(config=config) as sr:
            step = Box({"args": ["-two", "-flags"]}, default_box=True)
            sr._container = "c1.sif"
            cmd = sr._create_cmd(step, "c1.sif")

            expected = ("singularity run"
                        " --userns --pwd /workspace"
                        " --bind /w:/workspace"
                        " c1.sif"
                        " -two -flags")

            self.assertEqual(expected.split(" "), cmd)

        config_dict = {
            "engine": {
                "name": "singularity",
                "options": {
                    "hostname": "popper.local",
                    "ipc": True,
                    "bind": ["/path/in/host:/path/in/container"],
                },
            },
            "resource_manager": {
                "name": "slurm"
            },
        }

        config = ConfigLoader.load(workspace_dir="/w", config_file=config_dict)

        with SingularityRunner(config=config) as sr:
            step = Box({"args": ["-two", "-flags"]}, default_box=True)
            sr._container = "c2.sif"
            cmd = sr._create_cmd(step, "c2.sif")

            # fmt: off
            expected = f"singularity run --userns --pwd /workspace --bind /w:/workspace --bind /path/in/host:/path/in/container --hostname popper.local --ipc c2.sif -two -flags"
            # fmt: on
            self.assertEqual(expected.split(" "), cmd)
コード例 #19
0
ファイル: test_config.py プロジェクト: vipulchhabra99/popper
    def test_config_from_file(self):
        config = {
            "engine": {
                "options": {
                    "privileged": True
                }
            },
            "resource_manager": {
                "options": {
                    "foo": "bar"
                }
            },
        }
        kwargs = {"config_file": config}

        # engine name missing
        with self.assertLogs("popper", level="INFO") as cm:
            self.assertRaises(SystemExit, ConfigLoader.load, **kwargs)
            self.assertEqual(len(cm.output), 1)
            self.assertTrue("No engine name given" in cm.output[0])

        # resman name missing
        config.update({"engine": {"name": "foo"}})
        with self.assertLogs("popper", level="INFO") as cm:
            self.assertRaises(SystemExit, ConfigLoader.load, **kwargs)
            self.assertEqual(len(cm.output), 1)
            self.assertTrue("No resource manager name given" in cm.output[0])

        # now all OK
        config.update({"resource_manager": {"name": "bar"}})
        conf = ConfigLoader.load(**kwargs)
        self.assertEqual(conf.engine_name, "foo")
        self.assertEqual(conf.resman_name, "bar")
        self.assertEqual(conf.engine_opts, {})
        self.assertEqual(conf.resman_opts, {})

        config.update({"engine": {"name": "bar", "options": {"foo": "baz"}}})
        conf = ConfigLoader.load(**kwargs)
        self.assertEqual(conf.engine_opts, {"foo": "baz"})
コード例 #20
0
    def test_exec_srun(self, mock_kill):
        config_dict = {
            "engine": {
                "name": "singularity",
                "options": {},
            },
            "resource_manager": {
                "name": "slurm",
                "options": {
                    "sample": {
                        "gpus-per-task": 2,
                        "overcommit": True
                    }
                },
            },
        }

        config = ConfigLoader.load(workspace_dir="/w", config_file=config_dict)
        self.Popen.set_command(
            "srun --nodes 1 --ntasks 1 --ntasks-per-node 1 --gpus-per-task 2 --overcommit ls -la",
            returncode=0,
        )
        step = Box({"id": "sample"}, default_box=True)
        with SlurmRunner(config=config) as sr:
            e = sr._exec_srun(["ls", "-la"], step, logging=True)
            self.assertEqual(e, 0)

        call_srun = call.Popen(
            [
                "srun",
                "--nodes",
                "1",
                "--ntasks",
                "1",
                "--ntasks-per-node",
                "1",
                "--gpus-per-task",
                "2",
                "--overcommit",
                "ls",
                "-la",
            ],
            cwd=os.getcwd(),
            env=None,
            preexec_fn=os.setsid,
            stderr=-2,
            stdout=-1,
            universal_newlines=True,
        )

        self.assertEqual(call_srun in self.Popen.all_calls, True)
コード例 #21
0
ファイル: test_runner.py プロジェクト: xwalls/popper
 def test_prepare_environment_without_git(self):
     with StepRunner(ConfigLoader.load(workspace_dir="/tmp/foo")) as r:
         step = Box({
             "name": "a",
             "env": {
                 "FOO": "BAR"
             },
             "secrets": ["A"]
         },
                    default_box=True)
         os.environ["A"] = "BC"
         env = r._prepare_environment(step, {"other": "b"})
         self.assertDictEqual({"FOO": "BAR", "A": "BC", "other": "b"}, env)
         os.environ.pop("A")
コード例 #22
0
ファイル: test_runner_host.py プロジェクト: zacswolf/popper
 def test_create_container(self):
     config = ConfigLoader.load()
     step = Box(
         {
             "uses": "docker://alpine:3.9",
             "runs": ["echo hello"],
             "id": "kontainer_one",
         },
         default_box=True,
     )
     cid = pu.sanitized_name(step.id, config.wid)
     with PodmanRunner(init_podman_client=True, config=config) as pr:
         c = pr._create_container(cid, step)
         c_status_cmd = [
             "podman",
             "container",
             "inspect",
             "-f",
             str("{{.State.Status}}"),
             c,
         ]
         __, _, c_status = HostRunner._exec_cmd(c_status_cmd, logging=False)
         self.assertEqual(c_status, "configured")
         cmd = ["podman", "container", "rm", c]
         HostRunner._exec_cmd(cmd, logging=False)
     step = Box(
         {
             "uses": "docker://alpine:3.9",
             "runs": ["echo", "hello_world"],
             "id": "KoNtAiNeR tWo",
         },
         default_box=True,
     )
     cid = pu.sanitized_name(step.id, config.wid)
     with PodmanRunner(init_podman_client=True, config=config) as pr:
         c = pr._create_container(cid, step)
         c_status_cmd = [
             "podman",
             "container",
             "inspect",
             "-f",
             str("{{.State.Status}}"),
             c,
         ]
         __, _, c_status = HostRunner._exec_cmd(c_status_cmd, logging=False)
         self.assertEqual(c_status, "configured")
         cmd = ["podman", "container", "rm", c]
         HostRunner._exec_cmd(cmd, logging=False)
コード例 #23
0
    def test_copy_ctx(self):
        repo = self.mk_repo()
        conf = ConfigLoader.load(workspace_dir=repo.working_dir)
        with KubernetesRunner(config=conf) as kr:
            kr._vol_claim_create()
            kr._init_pod_create()
            time.sleep(5)
            response = self._kclient.read_namespaced_pod(kr._init_pod_name,
                                                         namespace="default")
            self.assertEqual(response.status.phase, "Running")
            kr._copy_ctx()
            kr._init_pod_delete()
            kr._vol_claim_delete()

        repo.close()
        shutil.rmtree(repo.working_dir, ignore_errors=True)
コード例 #24
0
    def test_dry_run(self):
        config = ConfigLoader.load(engine_name="singularity",
                                   resman_name="slurm",
                                   dry_run=True)

        with WorkflowRunner(config) as r:
            wf_data = {
                "steps": [{
                    "uses": "docker://alpine",
                    "runs": ["cat"],
                    "args": ["README.md"],
                }]
            }
            r.run(WorkflowParser.parse(wf_data=wf_data))

        self.assertEqual(self.Popen.all_calls, [])
コード例 #25
0
 def test_stop_running_tasks(self):
     self.Popen.set_command("scancel --name job_a", returncode=0)
     with SlurmRunner(config=ConfigLoader.load()) as sr:
         sr._spawned_jobs.add("job_a")
         sr.stop_running_tasks()
         compare(
             call.Popen(
                 ["scancel", "--name", "job_a"],
                 cwd=os.getcwd(),
                 env=None,
                 preexec_fn=os.setsid,
                 stderr=-2,
                 stdout=-1,
                 universal_newlines=True,
             ),
             self.Popen.all_calls[0],
         )
コード例 #26
0
    def test_slurm_singularity_run(self, mock_kill):
        config_dict = {
            "engine": {
                "name": "singularity",
                "options": {
                    "hostname": "popper.local",
                    "bind": ["/path/in/host:/path/in/container"],
                },
            },
            "resource_manager": {
                "name": "slurm"
            },
        }

        config = ConfigLoader.load(workspace_dir="/w", config_file=config_dict)

        # fmt: off
        self.Popen.set_command(
            f"sbatch --wait --job-name popper_1_{config.wid} --output {slurm_cache_dir}/popper_1_{config.wid}.out {slurm_cache_dir}/popper_1_{config.wid}.sh",
            returncode=0,
        )
        # fmt: on

        self.Popen.set_command(
            f"tail -f {slurm_cache_dir}/popper_1_{config.wid}.out",
            returncode=0)

        with WorkflowRunner(config) as r:
            wf_data = {
                "steps": [{
                    "uses": "popperized/bin/sh@master",
                    "args": ["ls"],
                }]
            }
            r.run(WorkflowParser.parse(wf_data=wf_data))

        with open(f"{slurm_cache_dir}/popper_1_{config.wid}.sh", "r") as f:
            # fmt: off
            expected = f"""#!/bin/bash
singularity run --userns --pwd /workspace --bind /w:/workspace --bind /path/in/host:/path/in/container --hostname popper.local {os.environ['HOME']}/.cache/popper/singularity/{config.wid}/popper_1_{config.wid}.sif ls"""
            # fmt: on
            actual = f.read()
        self.assertEqual(expected, actual)
コード例 #27
0
ファイル: test_runner_host.py プロジェクト: zacswolf/popper
 def test_find_container(self):
     config = ConfigLoader.load()
     step = Box(
         {
             "uses": "docker://alpine:3.9",
             "runs": ["echo hello"],
             "id": "kontainer_one",
         },
         default_box=True,
     )
     cid = pu.sanitized_name(step.id, config.wid)
     with PodmanRunner(init_podman_client=True, config=config) as pr:
         c = pr._find_container(cid)
         self.assertEqual(c, None)
     with PodmanRunner(init_podman_client=True, config=config) as pr:
         container = pr._create_container(cid, step)
         c = pr._find_container(cid)
         self.assertEqual(c, container)
         cmd = ["podman", "container", "rm", "-f", cid]
         HostRunner._exec_cmd(cmd, logging=False)
コード例 #28
0
    def test_vol_claim_create_delete(self):
        repo = self.mk_repo()
        conf = ConfigLoader.load(workspace_dir=repo.working_dir)
        with KubernetesRunner(config=conf) as kr:
            kr._vol_claim_create()
            response = self._kclient.read_namespaced_persistent_volume_claim(
                kr._vol_claim_name, namespace="default")
            self.assertEqual(response.status.phase, "Bound")
            kr._vol_claim_delete()
            self.assertRaises(
                Exception,
                self._kclient.read_namespaced_persistent_volume_claim,
                {
                    "name": kr._vol_claim_name,
                    "namespace": "default"
                },
            )

        repo.close()
        shutil.rmtree(repo.working_dir, ignore_errors=True)
コード例 #29
0
    def test_host_run(self):

        repo = self.mk_repo()
        conf = ConfigLoader.load(workspace_dir=repo.working_dir)

        with WorkflowRunner(conf) as r:
            wf_data = {
                "steps": [{"uses": "sh", "runs": ["cat"], "args": ["README.md"],}]
            }
            r.run(WorkflowParser.parse(wf_data=wf_data))

            wf_data = {
                "steps": [
                    {
                        "uses": "sh",
                        "runs": ["bash", "-c", "echo $FOO > hello.txt ; pwd"],
                        "env": {"FOO": "bar"},
                    }
                ]
            }
            r.run(WorkflowParser.parse(wf_data=wf_data))
            with open(os.path.join(repo.working_dir, "hello.txt"), "r") as f:
                self.assertEqual(f.read(), "bar\n")

            wf_data = {"steps": [{"uses": "sh", "runs": ["nocommandisnamedlikethis"]}]}
            self.assertRaises(SystemExit, r.run, WorkflowParser.parse(wf_data=wf_data))

            # check exit code 78
            wf_data = {
                "steps": [
                    {"uses": "sh", "runs": ["touch", "one.txt"]},
                    {"uses": "sh", "runs": ["bash", "-c", "exit 78"]},
                    {"uses": "sh", "runs": ["touch", "two.txt"]},
                ]
            }
            r.run(WorkflowParser.parse(wf_data=wf_data))
            self.assertTrue(os.path.isfile(os.path.join(repo.working_dir, "one.txt")))
            self.assertFalse(os.path.isfile(os.path.join(repo.working_dir, "two.txt")))

        repo.close()
        shutil.rmtree(repo.working_dir, ignore_errors=True)
コード例 #30
0
    def test_config_defaults(self):
        conf = ConfigLoader.load()
        expected = Box(
            {
                "skip_clone": False,
                "engine_name": "docker",
                "engine_opts": {},
                "resman_name": "host",
                "resman_opts": {},
                "skip_pull": False,
                "dry_run": False,
                "workspace_dir": os.getcwd(),
                "quiet": False,
                "reuse": False,
                "pty": False,
                "allow_undefined_secrets_in_ci": False,
            },
            default_box=True,
        )

        self.assertEqual(expected,
                         TestPopperConfig.extract_dict(expected, conf))