diff --git a/magnum/db/sqlalchemy/api.py b/magnum/db/sqlalchemy/api.py index e54ce04396..6e2f88c3c4 100644 --- a/magnum/db/sqlalchemy/api.py +++ b/magnum/db/sqlalchemy/api.py @@ -325,12 +325,18 @@ class Connection(api.Connection): except NoResultFound: raise exception.BayModelNotFound(baymodel=baymodel_name) - def is_baymodel_referenced(self, session, baymodel_uuid): + def _is_baymodel_referenced(self, session, baymodel_uuid): """Checks whether the baymodel is referenced by bay(s).""" query = model_query(models.Bay, session=session) query = self._add_bays_filters(query, {'baymodel_id': baymodel_uuid}) return query.count() != 0 + def _is_publishing_baymodel(self, values): + if (len(values) == 1 and + 'public' in values and values['public'] is True): + return True + return False + def destroy_baymodel(self, baymodel_id): session = get_session() with session.begin(): @@ -342,7 +348,7 @@ class Connection(api.Connection): except NoResultFound: raise exception.BayModelNotFound(baymodel=baymodel_id) - if self.is_baymodel_referenced(session, baymodel_ref['uuid']): + if self._is_baymodel_referenced(session, baymodel_ref['uuid']): raise exception.BayModelReferenced(baymodel=baymodel_id) query.delete() @@ -365,8 +371,10 @@ class Connection(api.Connection): except NoResultFound: raise exception.BayModelNotFound(baymodel=baymodel_id) - if self.is_baymodel_referenced(session, ref['uuid']): - raise exception.BayModelReferenced(baymodel=baymodel_id) + if self._is_baymodel_referenced(session, ref['uuid']): + # we only allow to update baymodel to be public + if not self._is_publishing_baymodel(values): + raise exception.BayModelReferenced(baymodel=baymodel_id) ref.update(values) return ref diff --git a/magnum/tests/unit/api/controllers/v1/test_baymodel.py b/magnum/tests/unit/api/controllers/v1/test_baymodel.py index 6770d4aa73..7219e31577 100644 --- a/magnum/tests/unit/api/controllers/v1/test_baymodel.py +++ b/magnum/tests/unit/api/controllers/v1/test_baymodel.py @@ -259,6 +259,28 @@ class TestPatch(api_base.FunctionalTest): [{'path': '/public', 'value': True, 'op': 'replace'}]) + def test_update_baymodel_with_bay_allow_update(self): + baymodel = obj_utils.create_test_baymodel(self.context) + obj_utils.create_test_bay(self.context, baymodel_id=baymodel.uuid) + response = self.patch_json('/baymodels/%s' % baymodel.uuid, + [{'path': '/public', + 'value': True, + 'op': 'replace'}], + expect_errors=True) + self.assertEqual(200, response.status_int) + response = self.get_json('/baymodels/%s' % self.baymodel.uuid) + self.assertEqual(response['public'], True) + + def test_update_baymodel_with_bay_not_allow_update(self): + baymodel = obj_utils.create_test_baymodel(self.context) + obj_utils.create_test_bay(self.context, baymodel_id=baymodel.uuid) + response = self.patch_json('/baymodels/%s' % baymodel.uuid, + [{'path': '/name', + 'value': 'new_name', + 'op': 'replace'}], + expect_errors=True) + self.assertEqual(400, response.status_code) + @mock.patch('oslo_utils.timeutils.utcnow') def test_replace_singular(self, mock_utcnow): name = 'bay_model_example_B'