예제 #1
0
    def test_clone_repos(self):
        wf = YMLWorkflow("""
        version: '1'
        steps:
        - uses: popperized/bin/sh@master
        """)
        wf.parse()

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

        # clone repos in the default cache directory.
        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'
        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 = PopperConfig(skip_clone=True)
        runner = WorkflowRunner(conf)
        self.assertRaises(SystemExit, runner._clone_repos, wf)
예제 #2
0
    def test_check_secrets(self):
        wf = YMLWorkflow("""
        version: '1'
        steps:
        - uses: docker://alpine:3.9
          args: ["ls -ltr"]
          secrets: ["SECRET_ONE", "SECRET_TWO"]
        """)
        wf.parse()

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

        # now go back to not dry-running
        runner = WorkflowRunner(PopperConfig())

        # 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
    def test_submit_job_failure(self, mock_kill):
        self.Popen.set_command(
            'sbatch --wait --job-name popper_1_123abc '
            '--output /tmp/popper/slurm/popper_1_123abc.out '
            '/tmp/popper/slurm/popper_1_123abc.sh',
            returncode=12)

        self.Popen.set_command('tail -f /tmp/popper/slurm/popper_1_123abc.out',
                               returncode=0)

        config_dict = {
            'engine': {
                'name': 'docker',
                'options': {}
            },
            'resource_manager': {
                'name': 'slurm',
                'options': {}
            }
        }

        config = PopperConfig(workspace_dir='/w', config_file=config_dict)
        config.wid = "123abc"

        with WorkflowRunner(config) as r:
            wf = YMLWorkflow("""
            version: '1'
            steps:
            - uses: 'popperized/bin/sh@master'
              runs: [cat]
              args: README.md
            """)
            wf.parse()
            self.assertRaises(SystemExit, r.run, wf)

            call_tail = call.Popen(
                ['tail', '-f', '/tmp/popper/slurm/popper_1_123abc.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', 'popper_1_123abc',
                '--output', '/tmp/popper/slurm/popper_1_123abc.out',
                '/tmp/popper/slurm/popper_1_123abc.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)
예제 #4
0
    def test_run(self, mock_kill):
        self.Popen.set_command(
            'sbatch --wait --job-name popper_1_123abc '
            '--output /tmp/popper/slurm/popper_1_123abc.out '
            '/tmp/popper/slurm/popper_1_123abc.sh',
            returncode=0)

        self.Popen.set_command('tail -f /tmp/popper/slurm/popper_1_123abc.out',
                               returncode=0)

        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 = PopperConfig(workspace_dir='/w', config_file=config_dict)
        config.wid = "123abc"

        with WorkflowRunner(config) as r:
            wf = YMLWorkflow("""
            version: '1'
            steps:
            - uses: 'popperized/bin/sh@master'
              runs: [cat]
              args: README.md
            """)
            wf.parse()
            r.run(wf)

        with open('/tmp/popper/slurm/popper_1_123abc.sh', 'r') as f:
            content = f.read()
            self.assertEqual(
                content, f"""#!/bin/bash
docker rm -f popper_1_123abc || true
docker build -t popperized/bin:master {os.environ['HOME']}/.cache/popper/123abc/github.com/popperized/bin/sh
docker create --name popper_1_123abc --workdir /workspace --entrypoint cat -v /w:/workspace -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 popperized/bin:master README.md
docker start --attach popper_1_123abc""")
예제 #5
0
    def test_dry_run(self):
        repo = self.mk_repo()
        config = PopperConfig(engine_name='docker',
                              resman_name='slurm',
                              dry_run=True,
                              workspace_dir=repo.working_dir)

        with WorkflowRunner(config) as r:
            wf = YMLWorkflow("""
            version: '1'
            steps:
            - uses: 'popperized/bin/sh@master'
              runs: [cat]
              args: README.md
            """)
            wf.parse()
            r.run(wf)

        self.assertEqual(self.Popen.all_calls, [])
예제 #6
0
    def test_run(self, mock_kill):
        self.Popen.set_command(
            'sbatch --wait --job-name popper_1_123abc '
            '--output /tmp/popper/slurm/popper_1_123abc.out '
            '/tmp/popper/slurm/popper_1_123abc.sh',
            returncode=0)

        self.Popen.set_command('tail -f /tmp/popper/slurm/popper_1_123abc.out',
                               returncode=0)

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

        config = PopperConfig(workspace_dir='/w', config_file=config_dict)
        config.wid = "123abc"

        with WorkflowRunner(config) as r:
            wf = YMLWorkflow("""
            version: '1'
            steps:
            - uses: 'popperized/bin/sh@master'
              runs: ls
            """)
            wf.parse()
            r.run(wf)

        with open('/tmp/popper/slurm/popper_1_123abc.sh', 'r') as f:
            content = f.read()
            self.assertEqual(
                content, f"""#!/bin/bash
singularity exec --userns --pwd /workspace --bind /w:/workspace --bind /path/in/host:/path/in/container --hostname popper.local {os.environ['HOME']}/.cache/popper/singularity/123abc/popper_1_123abc.sif ls"""
            )
예제 #7
0
    def test_singularity_start(self):
        repo = self.mk_repo()
        conf = PopperConfig(engine_name='singularity',
                            workspace_dir=repo.working_dir)

        step = {
            'uses': 'docker://*****:*****@master'
              args: 'ls'
            """)
            wf.parse()
            r.run(wf)

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

            wf = YMLWorkflow("""
            version: '1'
            steps:
            - uses: 'docker://alpine:3.9'
              runs: 'nocommandisnamedlikethis'
            """)
            wf.parse()
            self.assertRaises(SystemExit, r.run, wf)

        repo.close()
예제 #8
0
    def test_run(self):

        repo = self.mk_repo()
        conf = PopperConfig(workspace_dir=repo.working_dir)

        with WorkflowRunner(conf) as r:
            wf = YMLWorkflow("""
            version: '1'
            steps:
            - uses: sh
              runs: [cat]
              args: README.md
            """)
            wf.parse()
            r.run(wf)

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

            wf = YMLWorkflow("""
            version: '1'
            steps:
            - uses: 'sh'
              runs: 'nocommandisnamedlikethis'
            """)
            wf.parse()
            self.assertRaises(SystemExit, r.run, wf)

        repo.close()