コード例 #1
0
    def test_recreate_job_as_project_member(self):
        from pillar.api.projects.utils import get_admin_group_id
        import pillar.auth
        from flamenco.jobs import routes

        with self.app.test_request_context():
            groups = self.create_standard_groups()
            admin_gid = get_admin_group_id(self.proj_id)

        self.create_user(24 * 'd',
                         roles={'subscriber'},
                         groups=[groups['subscriber'], admin_gid],
                         token='user-token')

        old_task_ids = self._pre_test()

        # Test we're able to get the job itself.
        self.get(f'/api/flamenco/jobs/{self.job_id}', auth_token='user-token')

        # The user should also be allowed to recreate the job.
        with self.app.test_request_context():
            pillar.auth.login_user('user-token', load_from_db=True)
            routes.recreate_job(self.project['url'], self.job_id)

        self._post_test(old_task_ids)
コード例 #2
0
    def test_set_job_valid_status_as_projmember_subscriber(
            self, mock_handle_job_status_change):
        """Subscribers member of the project should be allowed to do this."""

        from pillar.api.projects.utils import get_admin_group_id

        with self.app.test_request_context():
            admin_group_id = get_admin_group_id(self.proj_id)

        self.create_user(user_id=24 * 'e',
                         roles={'subscriber'},
                         groups=[admin_group_id],
                         token='flamuser-token')

        self.assert_job_status('queued')
        mock_handle_job_status_change.return_value = None
        self.patch(
            '/api/flamenco/jobs/%s' % self.job_id,
            json={
                'op': 'set-job-status',
                'status': 'completed'
            },
            auth_token='flamuser-token',
            expected_status=204,
        )

        mock_handle_job_status_change.assert_called_with(
            self.job_id, 'queued', 'completed')
        self.assert_job_status('completed')
コード例 #3
0
    def setUp(self, **kwargs):
        AbstractFlamencoTest.setUp(self, **kwargs)

        from pillar.api.utils.authentication import force_cli_user
        from pillar.api.projects.utils import get_admin_group_id

        mngr_doc, account, token = self.create_manager_service_account()
        self.mngr_id = mngr_doc['_id']
        self.mngr_token = token['token']

        self.assign_manager_to_project(self.mngr_id, self.proj_id)

        with self.app.test_request_context():
            group_id = get_admin_group_id(self.proj_id)

        self.create_user(user_id=24 * 'f', roles={'flamenco-admin'}, groups=[group_id])
        self.create_valid_auth_token(24 * 'f', 'fladmin-token')

        with self.app.test_request_context():
            force_cli_user()
            job = self.jmngr.api_create_job(
                'test job',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.job_id = job['_id']
コード例 #4
0
    def setUp(self, **kwargs):
        AbstractFlamencoTest.setUp(self, **kwargs)

        from pillar.api.utils.authentication import force_cli_user
        from pillar.api.projects.utils import get_admin_group_id

        mngr_doc, account, token = self.create_manager_service_account()
        self.mngr_id = mngr_doc['_id']
        self.mngr_token = token['token']

        self.assign_manager_to_project(self.mngr_id, self.proj_id)

        with self.app.test_request_context():
            group_id = get_admin_group_id(self.proj_id)

        self.create_user(user_id=24 * 'f', roles={'flamenco-admin'}, groups=[group_id])
        self.create_valid_auth_token(24 * 'f', 'fladmin-token')

        with self.app.test_request_context():
            force_cli_user()
            job = self.jmngr.api_create_job(
                'test job',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.job_id = job['_id']
コード例 #5
0
    def test_set_job_valid_status_as_projmember_subscriber(self, mock_handle_job_status_change):
        """Subscribers member of the project should be allowed to do this."""

        from pillar.api.projects.utils import get_admin_group_id

        with self.app.test_request_context():
            admin_group_id = get_admin_group_id(self.proj_id)

        self.create_user(user_id=24 * 'e', roles={'subscriber'},
                         groups=[admin_group_id],
                         token='flamuser-token')

        self.assert_job_status('queued')
        mock_handle_job_status_change.return_value = None
        self.patch(
            '/api/flamenco/jobs/%s' % self.job_id,
            json={'op': 'set-job-status',
                  'status': 'completed'},
            auth_token='flamuser-token',
            expected_status=204,
        )

        mock_handle_job_status_change.assert_called_with(
            self.job_id, 'queued', 'completed')
        self.assert_job_status('completed')
コード例 #6
0
    def setUp(self, **kwargs):
        AbstractFlamencoTest.setUp(self, **kwargs)

        from pillar.api.utils.authentication import force_cli_user
        from pillar.api.projects.utils import get_admin_group_id

        mngr_doc, account, token = self.create_manager_service_account()
        self.mngr_id = mngr_doc['_id']
        self.mngr_token = token['token']

        self.assign_manager_to_project(self.mngr_id, self.proj_id)

        with self.app.test_request_context():
            group_id = get_admin_group_id(self.proj_id)

        self.create_user(user_id=24 * 'f',
                         roles={'flamenco-admin'},
                         groups=[group_id])
        self.create_valid_auth_token(24 * 'f', 'fladmin-token')

        with self.app.test_request_context():
            force_cli_user()
            job = self.jmngr.api_create_job(
                'test job',
                'Wörk wørk w°rk.',
                'blender-render-progressive',
                {
                    'frames': '1-5',
                    'chunk_size': 2,
                    'render_output': '/render/out/frames-######',
                    'format': 'EXR',
                    'filepath': '/agent327/scenes/someshot/somefile.blend',
                    'blender_cmd': '/path/to/blender --enable-new-depsgraph',
                    'cycles_sample_count': 30,
                    'cycles_num_chunks': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.job_id = job['_id']
コード例 #7
0
    def setUp(self, **kwargs):
        AbstractFlamencoTest.setUp(self, **kwargs)

        from pillar.api.utils.authentication import force_cli_user
        from pillar.api.projects.utils import get_admin_group_id

        mngr_doc, account, token = self.create_manager_service_account()
        self.mngr_id = mngr_doc['_id']
        self.mngr_token = token['token']

        self.assign_manager_to_project(self.mngr_id, self.proj_id)

        with self.app.test_request_context():
            group_id = get_admin_group_id(self.proj_id)

        self.create_user(user_id=24 * 'f', roles={'flamenco-admin'}, groups=[group_id])
        self.create_valid_auth_token(24 * 'f', 'fladmin-token')

        with self.app.test_request_context():
            force_cli_user()
            job = self.jmngr.api_create_job(
                'test job',
                'Wörk wørk w°rk.',
                'blender-render-progressive',
                {
                    'frames': '1-5',
                    'chunk_size': 2,
                    'render_output': '/render/out/frames-######',
                    'format': 'OPEN_EXR',
                    'fps': 44,
                    'filepath': '/agent327/scenes/someshot/somefile.blend',
                    'blender_cmd': '/path/to/blender --enable-new-depsgraph',
                    'cycles_sample_count': 30,
                    'cycles_sample_cap': 30,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.job_id = job['_id']
コード例 #8
0
ファイル: __init__.py プロジェクト: BlenderCN-Org/flamenco
    def api_assign_to_project(self, manager_id: bson.ObjectId,
                              project_id: bson.ObjectId, action: str) -> bool:
        """Assigns the manager to the given project.

        Does NOT check whether the project actually exists or not.

        :param action: either 'assign' or 'remove'
        :returns: True iff the action was successful.
        """

        from collections import defaultdict
        from pymongo.results import UpdateResult
        from flamenco import current_flamenco
        from pillar.api.projects import utils as project_utils

        if action not in {'assign', 'remove'}:
            raise ValueError("Action must be either 'assign' or 'remove'")

        assert isinstance(manager_id, bson.ObjectId)
        assert isinstance(project_id, bson.ObjectId)

        mngr_coll = current_flamenco.db('managers')
        manager_doc = mngr_coll.find_one({'_id': manager_id}, {
            'projects': 1,
            'user_groups': 1
        })

        if not manager_doc:
            self._log.warning(
                'api_assign_to_project(%s, %s): no manager with id=%s (user=%s)',
                manager_id, project_id, manager_id, current_user.user_id)
            return False

        mngr_projects = set(manager_doc.get('projects', []))
        mngr_user_groups = set(manager_doc.get('user_groups', []))

        admin_group_id = project_utils.get_admin_group_id(project_id)

        if action == 'assign':
            mngr_projects.add(project_id)
            mngr_user_groups.add(admin_group_id)
        else:
            mngr_projects.discard(project_id)
            mngr_user_groups.discard(admin_group_id)

        # Convert to list because JSON/BSON doesn't do sets, and sort to get predictable output.
        projects = sorted(mngr_projects)
        user_groups = sorted(mngr_user_groups)

        if self._log.isEnabledFor(logging.INFO):
            self._log.info(
                'Updating Manager %s projects to [%s] and user_groups to [%s]',
                manager_id,
                ', '.join(f"'{pid}'" for pid in projects),
                ', '.join(f"'{gid}'" for gid in user_groups),
            )

        update = defaultdict(dict)  # type: typing.DefaultDict[str, typing.Any]
        if projects:
            update['$set']['projects'] = projects
        else:
            update['$unset']['projects'] = 1

        if user_groups:
            update['$set']['user_groups'] = user_groups
        else:
            update['$unset']['user_groups'] = 1

        res: UpdateResult = mngr_coll.update_one({'_id': manager_id}, update)

        if res.matched_count < 1:
            self._log.error(
                'Unable to update projects on Manager %s to %s: %s',
                manager_id, ', '.join(f"'{pid}'" for pid in projects), res)
            return False
        return True
コード例 #9
0
    def setUp(self, **kwargs):
        super().setUp(**kwargs)

        # Create multiple projects:
        # 1) user is member, owned manager assigned to it.
        # 2) user is member, non-owned manager assigned to it.
        # 3) user is member, no manager assigned to it.
        # 4) user is not member, both non-owned and owned manager assigned to it.
        # 5) user is not member, only non-owned manager assigned to it.
        # 6) user is GET-only member, owned manager assigned to it.
        # 7) user is GET-only member, non-owned manager assigned to it.

        from pillar.api.projects.utils import get_admin_group_id
        from pillar.api.utils import remove_private_keys

        # Create the projects
        self.project: typing.MutableMapping[int, dict] = {}
        self.prid: typing.MutableMapping[int, bson.ObjectId] = {}

        for idx in range(1, 8):
            admin_id = 24 * str(idx)
            proj = self._create_user_and_project(
                user_id=admin_id,
                roles={'subscriber'},
                project_name=f'Prøject {idx}',
                token=f'token-proj{idx}-admin')
            self.project[idx] = proj
            self.prid[idx] = bson.ObjectId(proj['_id'])

        # For projects 6 and 7, add GET access group
        self.group_map = self.create_standard_groups(
            additional_groups=['get-only-6', 'get-only-7'])
        for idx in (6, 7):
            self.project[idx]['permissions']['groups'].append({
                'group':
                self.group_map[f'get-only-{idx}'],
                'methods': ['GET'],
            })
            self.put(f'/api/projects/{self.prid[idx]}',
                     json=remove_private_keys(self.project[idx]),
                     etag=self.project[idx]['_etag'],
                     auth_token=f'token-proj{idx}-admin')

        # Create the managers
        self.owned_mngr, _, self.owned_mngr_token = self.create_manager_service_account(
        )
        self.owned_mngr_id = bson.ObjectId(self.owned_mngr['_id'])
        self.nonowned_mngr, _, self.nonowned_mngr_token = self.create_manager_service_account(
        )
        self.nonowned_mngr_id = bson.ObjectId(self.nonowned_mngr['_id'])

        self.assign_manager_to_project(self.owned_mngr_id, self.prid[1])
        self.assign_manager_to_project(self.nonowned_mngr_id, self.prid[2])
        self.assign_manager_to_project(self.owned_mngr_id, self.prid[4])
        self.assign_manager_to_project(self.nonowned_mngr_id, self.prid[5])
        self.assign_manager_to_project(self.owned_mngr_id, self.prid[6])
        self.assign_manager_to_project(self.nonowned_mngr_id, self.prid[7])

        # Create the test user.
        self.admin_gid: typing.MutableMapping[int, bson.ObjectId] = {}
        with self.app.test_request_context():
            for idx, prid in self.prid.items():
                self.admin_gid[idx] = get_admin_group_id(prid)
        self.create_user(roles={'subscriber', 'flamenco-user'},
                         groups=[
                             self.admin_gid[1],
                             self.admin_gid[2],
                             self.admin_gid[3],
                             self.owned_mngr['owner'],
                             self.group_map['get-only-6'],
                             self.group_map['get-only-7'],
                         ],
                         token='user-token')

        # Make some assertions about the access rights on the projects.
        for idx in (1, 2, 3):
            p = self.get(f'/api/projects/{self.prid[idx]}',
                         auth_token='user-token').json()
            self.assertEqual({
                'GET', 'PUT', 'DELETE', 'POST'
            }, set(
                p['allowed_methods']
            ), f'Unexpected methods {p["allowed_methods"]} in project nr {idx}'
                             )
        for idx in (4, 5):
            self.get(f'/api/projects/{self.prid[idx]}',
                     auth_token='user-token',
                     expected_status=403)
        for idx in (6, 7):
            p = self.get(f'/api/projects/{self.prid[idx]}',
                         auth_token='user-token').json()
            self.assertEqual({'GET'}, set(
                p['allowed_methods']
            ), f'Unexpected methods {p["allowed_methods"]} in project nr {idx}'
                             )
コード例 #10
0
    def setUp(self, **kwargs):
        AbstractFlamencoTest.setUp(self, **kwargs)

        from pillar.api.utils.authentication import force_cli_user

        mngr_doc, account, token = self.create_manager_service_account(
            assign_to_project_id=self.proj_id)
        self.mngr_id = mngr_doc['_id']
        self.mngr_token = token['token']

        with self.app.app_context():
            project_gid = get_admin_group_id(self.proj_id)

        self.user = self.create_user(roles={'subscriber'},
                                     groups=[project_gid, mngr_doc['owner']],
                                     token='user-token')

        # Create three test jobs, one of which is completed and two are queued.
        with self.app.test_request_context():
            force_cli_user()
            job = self.jmngr.api_create_job(
                'test job 1',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.jobid1 = job['_id']
            job = self.jmngr.api_create_job(
                'test job 2',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.jobid2 = job['_id']
            job = self.jmngr.api_create_job(
                'test job 3',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.jobid3 = job['_id']
            job = self.jmngr.api_create_job(
                'test job 4',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
                start_paused=True,
            )
            self.jobid4 = job['_id']
            assert isinstance(self.jobid1, ObjectId)
            assert isinstance(self.jobid2, ObjectId)
            assert isinstance(self.jobid3, ObjectId)
            assert isinstance(self.jobid4, ObjectId)

            self.set_job_status('completed', job_id=self.jobid3)

            self.tasks = list(self.flamenco.db('tasks').find({
                'job': {'$in': [self.jobid1, self.jobid2]}
            }))
            self.task_ids = [t['_id'] for t in self.tasks]
コード例 #11
0
    def setUp(self, **kwargs):
        AbstractFlamencoTest.setUp(self, **kwargs)

        from pillar.api.utils.authentication import force_cli_user

        mngr_doc, account, token = self.create_manager_service_account(
            assign_to_project_id=self.proj_id)
        self.mngr_id = mngr_doc['_id']
        self.mngr_token = token['token']

        with self.app.app_context():
            project_gid = get_admin_group_id(self.proj_id)

        self.user = self.create_user(roles={'subscriber'},
                                     groups=[project_gid, mngr_doc['owner']],
                                     token='user-token')

        # Create three test jobs, one of which is completed and two are queued.
        with self.app.test_request_context():
            force_cli_user()
            job = self.jmngr.api_create_job(
                'test job 1',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.jobid1 = job['_id']
            job = self.jmngr.api_create_job(
                'test job 2',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.jobid2 = job['_id']
            job = self.jmngr.api_create_job(
                'test job 3',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
            )
            self.jobid3 = job['_id']
            job = self.jmngr.api_create_job(
                'test job 4',
                'Wörk wørk w°rk.',
                'sleep',
                {
                    'frames': '12-18, 20-22',
                    'chunk_size': 3,
                    'time_in_seconds': 3,
                },
                self.proj_id,
                ctd.EXAMPLE_PROJECT_OWNER_ID,
                self.mngr_id,
                start_paused=True,
            )
            self.jobid4 = job['_id']
            assert isinstance(self.jobid1, ObjectId)
            assert isinstance(self.jobid2, ObjectId)
            assert isinstance(self.jobid3, ObjectId)
            assert isinstance(self.jobid4, ObjectId)

            self.set_job_status('completed', job_id=self.jobid3)

            self.tasks = list(
                self.flamenco.db('tasks').find(
                    {'job': {
                        '$in': [self.jobid1, self.jobid2]
                    }}))
            self.task_ids = [t['_id'] for t in self.tasks]
コード例 #12
0
ファイル: test_access.py プロジェクト: armadillica/flamenco
    def setUp(self, **kwargs):
        super().setUp(**kwargs)

        # Create multiple projects:
        # 1) user is member, owned manager assigned to it.
        # 2) user is member, non-owned manager assigned to it.
        # 3) user is member, no manager assigned to it.
        # 4) user is not member, both non-owned and owned manager assigned to it.
        # 5) user is not member, only non-owned manager assigned to it.
        # 6) user is GET-only member, owned manager assigned to it.
        # 7) user is GET-only member, non-owned manager assigned to it.

        from pillar.api.projects.utils import get_admin_group_id
        from pillar.api.utils import remove_private_keys

        # Create the projects
        self.project: typing.MutableMapping[int, dict] = {}
        self.prid: typing.MutableMapping[int, bson.ObjectId] = {}

        for idx in range(1, 8):
            admin_id = 24 * str(idx)
            proj = self._create_user_and_project(user_id=admin_id,
                                                 roles={'subscriber'},
                                                 project_name=f'Prøject {idx}',
                                                 token=f'token-proj{idx}-admin')
            self.project[idx] = proj
            self.prid[idx] = bson.ObjectId(proj['_id'])

        # For projects 6 and 7, add GET access group
        self.group_map = self.create_standard_groups(additional_groups=['get-only-6', 'get-only-7'])
        for idx in (6, 7):
            self.project[idx]['permissions']['groups'].append({
                'group': self.group_map[f'get-only-{idx}'],
                'methods': ['GET'],
            })
            self.put(f'/api/projects/{self.prid[idx]}',
                     json=remove_private_keys(self.project[idx]),
                     etag=self.project[idx]['_etag'],
                     auth_token=f'token-proj{idx}-admin')

        # Create the managers
        self.owned_mngr, _, self.owned_mngr_token = self.create_manager_service_account()
        self.owned_mngr_id = bson.ObjectId(self.owned_mngr['_id'])
        self.nonowned_mngr, _, self.nonowned_mngr_token = self.create_manager_service_account()
        self.nonowned_mngr_id = bson.ObjectId(self.nonowned_mngr['_id'])

        self.assign_manager_to_project(self.owned_mngr_id, self.prid[1])
        self.assign_manager_to_project(self.nonowned_mngr_id, self.prid[2])
        self.assign_manager_to_project(self.owned_mngr_id, self.prid[4])
        self.assign_manager_to_project(self.nonowned_mngr_id, self.prid[5])
        self.assign_manager_to_project(self.owned_mngr_id, self.prid[6])
        self.assign_manager_to_project(self.nonowned_mngr_id, self.prid[7])

        # Create the test user.
        self.admin_gid: typing.MutableMapping[int, bson.ObjectId] = {}
        with self.app.test_request_context():
            for idx, prid in self.prid.items():
                self.admin_gid[idx] = get_admin_group_id(prid)
        self.create_user(
            roles={'subscriber'},
            groups=[
                self.admin_gid[1],
                self.admin_gid[2],
                self.admin_gid[3],
                self.owned_mngr['owner'],
                self.group_map['get-only-6'],
                self.group_map['get-only-7'],
            ], token='user-token')

        # Make some assertions about the access rights on the projects.
        for idx in (1, 2, 3):
            p = self.get(f'/api/projects/{self.prid[idx]}', auth_token='user-token').json
            self.assertEqual({'GET', 'PUT', 'DELETE', 'POST'}, set(p['allowed_methods']),
                             f'Unexpected methods {p["allowed_methods"]} in project nr {idx}')
        for idx in (4, 5):
            self.get(f'/api/projects/{self.prid[idx]}', auth_token='user-token',
                     expected_status=403)
        for idx in (6, 7):
            p = self.get(f'/api/projects/{self.prid[idx]}', auth_token='user-token').json
            self.assertEqual({'GET'}, set(p['allowed_methods']),
                             f'Unexpected methods {p["allowed_methods"]} in project nr {idx}')