Plugin rename is denied

Plugin name is uses as identifier in sync operations. Plugins data
on the file system can be found only by it's name, so renaming of
the plugin must be denied.

Change-Id: I2864537770f27d3b95d0d093900c1a787fef107c
Closes-Bug: #1649568
This commit is contained in:
Alexander Kislitsky 2016-12-22 18:47:09 +03:00
parent 93c6a8f47a
commit f7debcb38d
5 changed files with 37 additions and 1 deletions

View File

@ -24,6 +24,7 @@ import six
from nailgun import consts
from nailgun.db import db
from nailgun.db.sqlalchemy import models
from nailgun import errors
from nailgun.objects import DeploymentGraph
from nailgun.objects import NailgunCollection
from nailgun.objects import NailgunObject
@ -114,6 +115,14 @@ class Plugin(NailgunObject):
@classmethod
def update(cls, instance, data):
# Plugin name can't be changed. Plugins sync operation uses
# name for searching plugin data on the file system.
new_name = data.get('name')
if new_name is not None and instance.name != new_name:
raise errors.InvalidData(
"Plugin can't be renamed. Trying to change name "
"of the plugin {0} to {1}".format(instance.name, new_name))
graphs = {}
data_graphs = data.pop("graphs", [])
for graph in data_graphs:

View File

@ -657,6 +657,8 @@ class PluginManager(object):
plugin_adapter = wrap_plugin(plugin)
metadata = plugin_adapter.get_metadata()
Plugin.update(plugin, metadata)
except errors.InvalidData:
raise
except Exception as e:
logger.error("cannot update plugin {0} in DB. Reason: {1}"
.format(plugin.name, str(e)))

View File

@ -189,11 +189,23 @@ class TestPluginManager(base.BaseIntegrationTest):
@mock.patch.object(PluginAdapterV3, 'get_metadata')
def test_sync_metadata_for_all_plugins(self, sync_mock, list_fs_m):
list_fs_m.return_value = ['test_plugin_1-0.1', 'test_plugin_2-0.1']
sync_mock.side_effect = [{'name': 'test_plugin_1', 'title': 'T1'},
{'name': 'test_plugin_2', 'title': 'T2'}]
PluginManager.sync_plugins_metadata()
self.assertEqual(sync_mock.call_count, 2)
@mock.patch.object(PluginManager, '_list_plugins_on_fs')
@mock.patch.object(PluginAdapterV3, 'get_metadata')
def test_changing_plugin_name_denied(self, sync_mock, list_fs_m):
list_fs_m.return_value = ['test_plugin_1-0.1']
sync_mock.side_effect = [{'name': 'new_name_1', 'title': 'T1'}]
self.assertRaises(errors.InvalidData,
PluginManager.sync_plugins_metadata)
@mock.patch.object(PluginAdapterV3, 'get_metadata')
def test_sync_metadata_for_specific_plugin(self, sync_mock):
sync_mock.side_effect = [{'name': self.env.plugins[0].name,
'title': 'T1'}]
PluginManager.sync_plugins_metadata([self.env.plugins[0].id])
self.assertEqual(sync_mock.call_count, 1)

View File

@ -311,7 +311,7 @@ class TestPluginsApi(BasePluginTest):
def test_sync_specific_plugins(self, wrap_m):
plugin_ids = self._create_new_and_old_version_plugins_for_sync()
ids = plugin_ids[:1]
wrap_m.get_metadata.return_value = {}
wrap_m.return_value.get_metadata.return_value = {}
resp = self.sync_plugins(params={'ids': ids})
self.assertEqual(resp.status_code, 200)

View File

@ -2167,3 +2167,16 @@ class TestNodeStatus(BaseTestCase):
self.assertEqual(
consts.NODE_STATUSES.error, objects.Node.get_status(node)
)
class TestPlugin(BaseTestCase):
def test_name_unchangeable(self):
self.env.create_plugin(
name='name',
package_version='4.0.0',
fuel_version=['9.2']
)
plugin = objects.PluginCollection.all()[0]
self.assertRaises(errors.InvalidData, objects.Plugin.update,
plugin, {'name': 'new_name'})