diff --git a/mistral/api/controllers/v2/resources.py b/mistral/api/controllers/v2/resources.py index 78c2dadd9..4358a22d2 100644 --- a/mistral/api/controllers/v2/resources.py +++ b/mistral/api/controllers/v2/resources.py @@ -33,6 +33,7 @@ class Workbook(resource.Resource): tags = [wtypes.text] scope = SCOPE_TYPES "'private' or 'public'" + project_id = wsme.wsattr(wtypes.text, readonly=True) created_at = wtypes.text updated_at = wtypes.text @@ -45,6 +46,7 @@ class Workbook(resource.Resource): 'WORKBOOK DEFINITION IN MISTRAL DSL v2', tags=['large', 'expensive'], scope='private', + project_id='a7eb669e9819420ea4bd1453e672c0a7', created_at='1970-01-01T00:00:00.000000', updated_at='1970-01-01T00:00:00.000000') @@ -167,6 +169,7 @@ class Action(resource.Resource): tags = [wtypes.text] definition = wtypes.text scope = SCOPE_TYPES + project_id = wsme.wsattr(wtypes.text, readonly=True) created_at = wtypes.text updated_at = wtypes.text @@ -179,6 +182,7 @@ class Action(resource.Resource): definition='HERE GOES ACTION DEFINITION IN MISTRAL DSL v2', tags=['large', 'expensive'], scope='private', + project_id='a7eb669e9819420ea4bd1453e672c0a7', created_at='1970-01-01T00:00:00.000000', updated_at='1970-01-01T00:00:00.000000' ) @@ -252,6 +256,8 @@ class Execution(resource.Resource): created_at = wtypes.text updated_at = wtypes.text + project_id = wsme.wsattr(wtypes.text, readonly=True) + @classmethod def sample(cls): return cls(id='123e4567-e89b-12d3-a456-426655440000', @@ -259,6 +265,7 @@ class Execution(resource.Resource): workflow_namespace='some_namespace', workflow_id='123e4567-e89b-12d3-a456-426655441111', description='this is the first execution.', + project_id='40a908dbddfe48ad80a87fb30fa70a03', state='SUCCESS', input={}, output={}, @@ -309,6 +316,8 @@ class Task(resource.Resource): state_info = wtypes.text "an optional state information string" + project_id = wsme.wsattr(wtypes.text, readonly=True) + runtime_context = types.jsontype result = wtypes.text @@ -332,6 +341,7 @@ class Task(resource.Resource): workflow_execution_id='123e4567-e89b-12d3-a456-426655440000', name='task', state=states.SUCCESS, + project_id='40a908dbddfe48ad80a87fb30fa70a03', runtime_context={ 'triggered_by': [ { @@ -380,6 +390,7 @@ class ActionExecution(resource.Resource): tags = [wtypes.text] name = wtypes.text description = wtypes.text + project_id = wsme.wsattr(wtypes.text, readonly=True) accepted = bool input = types.jsontype output = types.jsontype @@ -400,6 +411,7 @@ class ActionExecution(resource.Resource): tags=['foo', 'fee'], name='std.echo', description='My running action', + project_id='40a908dbddfe48ad80a87fb30fa70a03', accepted=True, input={'first_name': 'John', 'last_name': 'Doe'}, output={'some_output': 'Hello, John Doe!'}, @@ -433,6 +445,7 @@ class CronTrigger(resource.Resource): workflow_id = wtypes.text workflow_input = types.jsontype workflow_params = types.jsontype + project_id = wsme.wsattr(wtypes.text, readonly=True) scope = SCOPE_TYPES @@ -453,6 +466,7 @@ class CronTrigger(resource.Resource): workflow_id='123e4567-e89b-12d3-a456-426655441111', workflow_input={}, workflow_params={}, + project_id='40a908dbddfe48ad80a87fb30fa70a03', scope='private', pattern='* * * * *', remaining_executions=42, @@ -484,6 +498,7 @@ class Environment(resource.Resource): description = wtypes.text variables = types.jsontype scope = SCOPE_TYPES + project_id = wsme.wsattr(wtypes.text, readonly=True) created_at = wtypes.text updated_at = wtypes.text @@ -500,6 +515,7 @@ class Environment(resource.Resource): 'verbose': True }, scope='private', + project_id='40a908dbddfe48ad80a87fb30fa70a03', created_at='1970-01-01T00:00:00.000000', updated_at='1970-01-01T00:00:00.000000' ) diff --git a/mistral/tests/unit/api/v2/test_action_executions.py b/mistral/tests/unit/api/v2/test_action_executions.py index 25b07038c..a6e08bc7e 100644 --- a/mistral/tests/unit/api/v2/test_action_executions.py +++ b/mistral/tests/unit/api/v2/test_action_executions.py @@ -206,6 +206,9 @@ MOCK_EMPTY = mock.MagicMock(return_value=[]) MOCK_NOT_FOUND = mock.MagicMock(side_effect=exc.DBEntityNotFoundError()) MOCK_DELETE = mock.MagicMock(return_value=None) +ACTION_EX_DB_WITH_PROJECT_ID = AD_HOC_ACTION_EX_DB.get_clone() +ACTION_EX_DB_WITH_PROJECT_ID.project_id = '' + @mock.patch.object(rpc_base, '_IMPL_CLIENT', mock.Mock()) class TestActionExecutionsController(base.APITest): @@ -236,6 +239,14 @@ class TestActionExecutionsController(base.APITest): self.assertEqual(404, resp.status_int) + @mock.patch.object(db_api, 'get_action_execution', + return_value=ACTION_EX_DB_WITH_PROJECT_ID) + def test_get_within_project_id(self, mock_get): + resp = self.app.get('/v2/action_executions/123') + + self.assertEqual(200, resp.status_int) + self.assertTrue('project_id' in resp.json) + @mock.patch.object(rpc_clients.EngineClient, 'start_action') def test_post(self, f): f.return_value = ACTION_EX_DB.to_dict() diff --git a/mistral/tests/unit/api/v2/test_actions.py b/mistral/tests/unit/api/v2/test_actions.py index 7c5843160..62b122b86 100644 --- a/mistral/tests/unit/api/v2/test_actions.py +++ b/mistral/tests/unit/api/v2/test_actions.py @@ -95,6 +95,9 @@ ACTION_DB.update(ACTION) SYSTEM_ACTION_DB = models.ActionDefinition() SYSTEM_ACTION_DB.update(SYSTEM_ACTION) +PROJECT_ID_ACTION_DB = ACTION_DB.get_clone() +PROJECT_ID_ACTION_DB.project_id = '' + UPDATED_ACTION_DEFINITION = """ --- version: '2.0' @@ -155,6 +158,14 @@ class TestActionsController(base.APITest): self.assertEqual(404, resp.status_int) + @mock.patch.object( + db_api, "get_action_definition", return_value=PROJECT_ID_ACTION_DB) + def test_get_within_project_id(self, mock_get): + url = '/v2/actions/1234' + resp = self.app.get(url, expect_errors=True) + self.assertEqual(200, resp.status_int) + self.assertTrue('project_id' in resp.json) + @mock.patch.object( db_api, "get_action_definition", MOCK_ACTION) @mock.patch.object( diff --git a/mistral/tests/unit/api/v2/test_cron_triggers.py b/mistral/tests/unit/api/v2/test_cron_triggers.py index dbad26837..21ed0796c 100644 --- a/mistral/tests/unit/api/v2/test_cron_triggers.py +++ b/mistral/tests/unit/api/v2/test_cron_triggers.py @@ -57,6 +57,8 @@ trigger_values['workflow_params'] = json.loads( TRIGGER_DB = models.CronTrigger() TRIGGER_DB.update(trigger_values) +TRIGGER_DB_WITH_PROJECT_ID = TRIGGER_DB.get_clone() +TRIGGER_DB_WITH_PROJECT_ID.project_id = '' MOCK_WF = mock.MagicMock(return_value=WF) MOCK_TRIGGER = mock.MagicMock(return_value=TRIGGER_DB) @@ -75,6 +77,14 @@ class TestCronTriggerController(base.APITest): self.assertEqual(200, resp.status_int) self.assertDictEqual(TRIGGER, resp.json) + @mock.patch.object(db_api, "get_cron_trigger", + return_value=TRIGGER_DB_WITH_PROJECT_ID) + def test_get_within_project_id(self, mock_get): + resp = self.app.get('/v2/cron_triggers/my_cron_trigger') + + self.assertEqual(200, resp.status_int) + self.assertTrue('project_id' in resp.json) + @mock.patch.object(db_api, "get_cron_trigger", MOCK_NOT_FOUND) def test_get_not_found(self): resp = self.app.get( diff --git a/mistral/tests/unit/api/v2/test_environment.py b/mistral/tests/unit/api/v2/test_environment.py index d5d8148c3..f23369934 100644 --- a/mistral/tests/unit/api/v2/test_environment.py +++ b/mistral/tests/unit/api/v2/test_environment.py @@ -66,6 +66,7 @@ ENVIRONMENT = { 'description': 'my test settings', 'variables': VARIABLES, 'scope': 'private', + 'project_id': '', 'created_at': str(datetime.datetime.utcnow()), 'updated_at': str(datetime.datetime.utcnow()) } @@ -85,12 +86,16 @@ ENVIRONMENT_DB = db.Environment( description=ENVIRONMENT['description'], variables=copy.deepcopy(VARIABLES), scope=ENVIRONMENT['scope'], + project_id=ENVIRONMENT['project_id'], created_at=datetime.datetime.strptime(ENVIRONMENT['created_at'], DATETIME_FORMAT), updated_at=datetime.datetime.strptime(ENVIRONMENT['updated_at'], DATETIME_FORMAT) ) +ENVIRONMENT_DB_WITH_PROJECT_ID = ENVIRONMENT_DB.get_clone() +ENVIRONMENT_DB_WITH_PROJECT_ID.project_id = '' + ENVIRONMENT_DB_DICT = {k: v for k, v in ENVIRONMENT_DB.items()} UPDATED_VARIABLES = copy.deepcopy(VARIABLES) @@ -168,6 +173,14 @@ class TestEnvironmentController(base.APITest): self.assertEqual(200, resp.status_int) self._assert_dict_equal(ENVIRONMENT, resp.json) + @mock.patch.object(db_api, 'get_environment', + return_value=ENVIRONMENT_DB_WITH_PROJECT_ID) + def test_get_within_project_id(self, mock_get): + resp = self.app.get('/v2/environments/123') + + self.assertEqual(200, resp.status_int) + self.assertEqual('', resp.json['project_id']) + @mock.patch.object(db_api, "get_environment", MOCK_NOT_FOUND) def test_get_not_found(self): resp = self.app.get('/v2/environments/123', expect_errors=True) diff --git a/mistral/tests/unit/api/v2/test_executions.py b/mistral/tests/unit/api/v2/test_executions.py index 16c748f53..bc86aa9ba 100644 --- a/mistral/tests/unit/api/v2/test_executions.py +++ b/mistral/tests/unit/api/v2/test_executions.py @@ -121,6 +121,8 @@ UPDATED_WF_EX_ENV_DESC['params'] = {'env': {'k1': 'def'}} WF_EX_JSON_WITH_DESC = copy.deepcopy(WF_EX_JSON) WF_EX_JSON_WITH_DESC['description'] = WF_EX.description +WF_EX_WITH_PROJECT_ID = WF_EX.get_clone() +WF_EX_WITH_PROJECT_ID.project_id = '' MOCK_WF_EX = mock.MagicMock(return_value=WF_EX) MOCK_SUB_WF_EX = mock.MagicMock(return_value=SUB_WF_EX) @@ -154,6 +156,13 @@ class TestExecutionsController(base.APITest): self.assertEqual(404, resp.status_int) + @mock.patch.object(db_api, 'get_workflow_execution', + return_value=WF_EX_WITH_PROJECT_ID) + def test_get_within_project_id(self, mock_get): + resp = self.app.get('/v2/executions/123', expect_errors=True) + self.assertEqual(200, resp.status_int) + self.assertTrue('project_id' in resp.json) + @mock.patch.object( db_api, 'ensure_workflow_execution_exists', diff --git a/mistral/tests/unit/api/v2/test_tasks.py b/mistral/tests/unit/api/v2/test_tasks.py index efe71c7c3..eac38356e 100644 --- a/mistral/tests/unit/api/v2/test_tasks.py +++ b/mistral/tests/unit/api/v2/test_tasks.py @@ -143,6 +143,9 @@ MOCK_NOT_FOUND = mock.MagicMock(side_effect=exc.DBEntityNotFoundError()) MOCK_ERROR_TASK = mock.MagicMock(return_value=ERROR_TASK_EX) MOCK_ERROR_ITEMS_TASK = mock.MagicMock(return_value=ERROR_ITEMS_TASK_EX) +TASK_EX_WITH_PROJECT_ID = TASK_EX.get_clone() +TASK_EX_WITH_PROJECT_ID.project_id = '' + @mock.patch.object( data_flow, @@ -171,6 +174,14 @@ class TestTasksController(base.APITest): self.assertEqual(1, len(resp.json['tasks'])) self.assertDictEqual(TASK_WITHOUT_RESULT, resp.json['tasks'][0]) + @mock.patch.object(db_api, 'get_task_execution', + return_value=TASK_EX_WITH_PROJECT_ID) + def test_get_within_project_id(self, mock_get): + resp = self.app.get('/v2/tasks/123') + + self.assertEqual(200, resp.status_int) + self.assertTrue('project_id' in resp.json) + @mock.patch.object(db_api, 'get_task_executions', MOCK_EMPTY) def test_get_all_empty(self): resp = self.app.get('/v2/tasks') diff --git a/mistral/tests/unit/api/v2/test_workbooks.py b/mistral/tests/unit/api/v2/test_workbooks.py index 83e0b37ee..2021cc665 100644 --- a/mistral/tests/unit/api/v2/test_workbooks.py +++ b/mistral/tests/unit/api/v2/test_workbooks.py @@ -55,6 +55,9 @@ WORKBOOK = { 'updated_at': '1970-01-01 00:00:00' } +WORKBOOK_DB_PROJECT_ID = WORKBOOK_DB.get_clone() +WORKBOOK_DB_PROJECT_ID.project_id = '' + UPDATED_WORKBOOK_DB = copy.copy(WORKBOOK_DB) UPDATED_WORKBOOK_DB['definition'] = UPDATED_WORKBOOK_DEF UPDATED_WORKBOOK = copy.deepcopy(WORKBOOK) @@ -115,6 +118,14 @@ class TestWorkbooksController(base.APITest): self.assertEqual(404, resp.status_int) + @mock.patch.object(db_api, "get_workbook", + return_value=WORKBOOK_DB_PROJECT_ID) + def test_get_within_project_id(self, mock_get): + resp = self.app.get('/v2/workbooks/123') + + self.assertEqual(200, resp.status_int) + self.assertTrue('project_id' in resp.json) + @mock.patch.object(workbooks, "update_workbook_v2", MOCK_UPDATED_WORKBOOK) def test_put(self): resp = self.app.put( diff --git a/mistral/tests/unit/api/v2/test_workflows.py b/mistral/tests/unit/api/v2/test_workflows.py index dde85afc0..5b853e2c2 100644 --- a/mistral/tests/unit/api/v2/test_workflows.py +++ b/mistral/tests/unit/api/v2/test_workflows.py @@ -111,6 +111,9 @@ WF_WITH_DEFAULT_INPUT = { 'input': 'param1, param2=2' } +WF_DB_PROJECT_ID = WF_DB.get_clone() +WF_DB_PROJECT_ID.project_id = '' + UPDATED_WF_DEFINITION = """ --- version: '2.0' @@ -666,3 +669,11 @@ class TestWorkflowsController(base.APITest): namespace='abc' ) self.assertDictEqual(WF_WITH_NAMESPACE, resp.json) + + @mock.patch.object(db_api, "get_workflow_definition") + def test_workflow_within_project_id(self, mock_get): + mock_get.return_value = WF_DB_PROJECT_ID + resp = self.app.get( + '/v2/workflows/123e4567-e89b-12d3-a456-426655440000') + self.assertEqual(200, resp.status_int) + self.assertTrue('project_id' in resp.json)