def add_pipeline(self, args): """ Register/add a new plugin to the system. """ timeout = 30 if args.storetimeout: timeout = args.storetimeout plg_repr = self.get_plugin_representation_from_store(args.name, args.storeurl, args.storeusername, args.storepassword, timeout) parameters_data = plg_repr['parameters'] del plg_repr['parameters'] plg_serializer = PluginSerializer(data=plg_repr) plg_serializer.is_valid(raise_exception=True) (compute_resource, tf) = ComputeResource.objects.get_or_create( compute_resource_identifier=args.computeresource) plugin = plg_serializer.save(compute_resource=compute_resource) # collect parameters and validate and save them to the DB for parameter in parameters_data: default = parameter['default'] if 'default' in parameter else None del parameter['default'] parameter_serializer = PluginParameterSerializer(data=parameter) parameter_serializer.is_valid(raise_exception=True) param = parameter_serializer.save(plugin=plugin) if default is not None: default_param_serializer = DEFAULT_PARAMETER_SERIALIZERS[param.type]( data={'value': default}) default_param_serializer.is_valid(raise_exception=True) default_param_serializer.save(plugin_param=param)
def test_create_does_not_create_meta_after_first_time_plugin_name_is_used( self): """ Test whether overriden create does not create a new plugin meta when creating a plugin version with a name that already exists in the system. """ user = User.objects.get(username=self.username) validated_data = self.plg_repr.copy() validated_data['parameters'][0]['type'] = 'string' validated_data['version'] = '0.2.2' validated_data['meta'] = { 'name': self.plugin_name, 'public_repo': 'https://github.com/FNNDSC' } validated_data['dock_image'] = 'fnndsc/pl-testapp' f = ContentFile(json.dumps(self.plg_repr).encode()) f.name = 'testapp.json' validated_data['descriptor_file'] = f validated_data['owner'] = [user] plg_serializer = PluginSerializer() n_plg_meta = PluginMeta.objects.count() plg_meta = PluginMeta.objects.get(name=self.plugin_name) plugin = plg_serializer.create(validated_data) self.assertEqual(n_plg_meta, PluginMeta.objects.count()) self.assertEqual(plugin.meta, plg_meta)
def _create_plugin(self, plg_repr, compute_resource): """ Private utility method to register/add a new plugin into the system. """ meta_data = { 'name': plg_repr.pop('name'), 'stars': plg_repr.pop('stars', 0), 'public_repo': plg_repr.pop('public_repo', ''), 'license': plg_repr.pop('license', ''), 'type': plg_repr.pop('type'), 'icon': plg_repr.pop('icon', ''), 'category': plg_repr.pop('category', ''), 'authors': plg_repr.pop('authors', '') } parameters_data = plg_repr.pop('parameters') # check whether plugin_name does not exist and validate the plugin meta data try: meta = PluginMeta.objects.get(name=meta_data['name']) meta_serializer = PluginMetaSerializer(meta, data=meta_data) except PluginMeta.DoesNotExist: meta_serializer = PluginMetaSerializer(data=meta_data) meta_serializer.is_valid(raise_exception=True) # validate the plugin's versioned data plg_serializer = PluginSerializer(data=plg_repr) plg_serializer.is_valid(raise_exception=True) # collect and validate parameters parameters_serializers = [] for parameter in parameters_data: default = parameter.pop('default', None) parameter_serializer = PluginParameterSerializer(data=parameter) parameter_serializer.is_valid(raise_exception=True) serializer_dict = { 'serializer': parameter_serializer, 'default_serializer': None } if default is not None: param_type = parameter['type'] default_param_serializer = DEFAULT_PARAMETER_SERIALIZERS[ param_type](data={ 'value': default }) default_param_serializer.is_valid(raise_exception=True) serializer_dict[ 'default_serializer'] = default_param_serializer parameters_serializers.append(serializer_dict) # if no validation errors at this point then save to the DB pl_meta = meta_serializer.save() plugin = plg_serializer.save(meta=pl_meta, compute_resources=[compute_resource]) for param_serializer_dict in parameters_serializers: param = param_serializer_dict['serializer'].save(plugin=plugin) if param_serializer_dict['default_serializer'] is not None: param_serializer_dict['default_serializer'].save( plugin_param=param) return plugin
def test_validate_app_cpu_descriptor(self): """ Test whether custom validate_app_cpu_descriptor method raises a ValidationError when the app cpu descriptor cannot be converted to a fields.CPUInt. """ with self.assertRaises(serializers.ValidationError): PluginSerializer.validate_app_cpu_descriptor('100me') self.assertEqual(100, PluginSerializer.validate_app_cpu_descriptor('100m'))
def test_check_required_descriptor(self): """ Test whether custom check_required_descriptor method raises a ValidationError when a required descriptor is missing from the plugin app representation. """ del self.plg_repr['execshell'] with self.assertRaises(serializers.ValidationError): PluginSerializer.check_required_descriptor(self.plg_repr, 'execshell')
def test_validate_meta_image(self): """ Test whether custom validate_meta_image method raises a ValidationError when plugin meta and docker image are not unique together. """ (meta, tf) = PluginMeta.objects.get_or_create(name=self.plugin_name) plg_serializer = PluginSerializer() with self.assertRaises(serializers.ValidationError): plg_serializer.validate_meta_image(meta, self.plugin_dock_image)
def test_validate_name_image(self): """ Test whether custom validate_name_image method raises a ValidationError when plugin name and docker image are not unique together. """ plg_serializer = PluginSerializer() with self.assertRaises(serializers.ValidationError): plg_serializer.validate_name_image(self.plugin_dock_image, self.plugin_name)
def test_validate_name_version(self): """ Test whether custom validate_name_version method raises a ValidationError when plugin name and version are not unique together. """ plg_serializer = PluginSerializer() with self.assertRaises(serializers.ValidationError): plg_serializer.validate_name_version(self.plg_repr['version'], self.plugin_name)
def test_validate_app_gpu_descriptor(self): """ Test whether custom validate_app_gpu_descriptor method raises a ValidationError when the gpu descriptor cannot be converted to a non-negative integer. """ with self.assertRaises(serializers.ValidationError): PluginSerializer.validate_app_gpu_descriptor('one') with self.assertRaises(serializers.ValidationError): PluginSerializer.validate_app_gpu_descriptor(-1)
def test_validate_app_workers_descriptor(self): """ Test whether custom validate_app_workers_descriptor method raises a ValidationError when the app worker descriptor cannot be converted to a positive integer. """ with self.assertRaises(serializers.ValidationError): PluginSerializer.validate_app_workers_descriptor('one') with self.assertRaises(serializers.ValidationError): PluginSerializer.validate_app_workers_descriptor(0)
def test_validate_app_cpu_descriptor(self): """ Test whether custom validate_app_cpu_descriptor method raises a ValidationError when the app cpu descriptor cannot be converted to a fields.CPUInt. """ with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'min_cpu_limit', 'value': '100me'} PluginSerializer.validate_app_cpu_descriptor(descriptor_dict) descriptor_dict = {'name': 'max_cpu_limit', 'value': '100m'} self.assertEqual(100, PluginSerializer.validate_app_cpu_descriptor(descriptor_dict))
def test_validate_app_descriptor_limits(self): """ Test whether custom validate_app_descriptor_limit method raises a ValidationError when the max limit is smaller than the min limit. """ self.plugin_repr['min_cpu_limit'] = 200 self.plugin_repr['max_cpu_limit'] = 100 with self.assertRaises(serializers.ValidationError): PluginSerializer.validate_app_descriptor_limits( self.plugin_repr, 'min_cpu_limit', 'max_cpu_limit')
def modify_plugin(self, args): """ Modify an existing/registered plugin and add the current date as a new plugin modification date. """ plugin = self.get_plugin(args.name, args.version) compute_resource = None plg_repr = None if args.computeresource: (compute_resource, tf) = ComputeResource.objects.get_or_create( compute_resource_identifier=args.computeresource) if args.storeurl: plg_repr = self.get_plugin_representation_from_store( args.name, args.storeurl, args.version, args.storeusername, args.storepassword, args.storetimeout) if plg_repr: del plg_repr['parameters'] plg_serializer = PluginSerializer(plugin, data=plg_repr) plg_serializer.is_valid(raise_exception=True) if compute_resource: plugin = plg_serializer.save(compute_resource=compute_resource) else: plugin = plg_serializer.save() elif compute_resource: plg_serializer = PluginSerializer(plugin) plugin = plg_serializer.save(compute_resource=compute_resource) if plg_repr or compute_resource: plugin.modification_date = timezone.now() plugin.save()
def test_validate_app_gpu_descriptor(self): """ Test whether custom validate_app_gpu_descriptor method raises a ValidationError when the gpu descriptor cannot be converted to a non-negative integer. """ with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'min_gpu_limit', 'value': 'one'} PluginSerializer.validate_app_gpu_descriptor(descriptor_dict) with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'max_gpu_limit', 'value': -1} PluginSerializer.validate_app_gpu_descriptor(descriptor_dict)
def test_validate_app_workers_descriptor(self): """ Test whether custom validate_app_workers_descriptor method raises a ValidationError when the app worker descriptor cannot be converted to a positive integer. """ with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'min_number_of_workers', 'value': 'one'} PluginSerializer.validate_app_workers_descriptor(descriptor_dict) with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'max_number_of_workers', 'value': 0} PluginSerializer.validate_app_workers_descriptor(descriptor_dict)
def test_validate_app_descriptor_limits(self): """ Test whether custom validate_app_descriptor_limit method raises a ValidationError when the max limit is smaller than the min limit. """ self.plugin_repr['min_cpu_limit'] = 200 self.plugin_repr['max_cpu_limit'] = 100 with self.assertRaises(serializers.ValidationError): PluginSerializer.validate_app_descriptor_limits(self.plugin_repr, 'min_cpu_limit', 'max_cpu_limit')
def test_validate_app_parameters_default(self): """ Test whether custom validate_app_parameters method raises a ValidationError when an optional plugin parameter doesn't have a default value specified. """ plugin = Plugin.objects.get(meta__name=self.plugin_name) plg_serializer = PluginSerializer(plugin) parameter_list = self.plugin_parameters parameter_list[0]['default'] = None with self.assertRaises(serializers.ValidationError): plg_serializer.validate_app_parameters(parameter_list)
def test_validate_validate_app_parameters(self): """ Test whether custom validate method validates submitted plugin's parameters. """ plg_serializer = PluginSerializer() parameter_list = self.plg_repr['parameters'] parameter_list[0]['type'] = 'booleano' with io.BytesIO(json.dumps(self.plg_repr).encode()) as f: data = {'descriptor_file': f} with self.assertRaises(serializers.ValidationError): plg_serializer.validate(data)
def test_validate_remove_empty_max_memory_limit(self): """ Test whether the custom validate method removes 'max_memory_limit' descriptor from the validated data when it is the empty string. """ plugin = Plugin.objects.get(meta__name=self.plugin_name) plg_serializer = PluginSerializer(plugin) self.plg_repr['max_memory_limit'] = '' with io.BytesIO(json.dumps(self.plg_repr).encode()) as f: data = {'descriptor_file': f} self.assertNotIn('max_memory_limit', plg_serializer.validate(data))
def test_validate_check_required_parameters(self): """ Test whether the custom validate method raises a ValidationError when required 'parameters' descriptor is missing from the plugin app representation. """ plg_serializer = PluginSerializer() del self.plg_repr['parameters'] # remove required 'parameters' from representation with io.BytesIO(json.dumps(self.plg_repr).encode()) as f: data = {'descriptor_file': f} with self.assertRaises(serializers.ValidationError): plg_serializer.validate(data)
def test_validate_app_parameters_type(self): """ Test whether custom validate_app_parameters method raises a ValidationError when a plugin parameter has an unsupported type. """ plugin = Plugin.objects.get(meta__name=self.plugin_name) plg_serializer = PluginSerializer(plugin) parameter_list = self.plugin_parameters parameter_list[0]['type'] = 'booleano' with self.assertRaises(serializers.ValidationError): plg_serializer.validate_app_parameters(parameter_list)
def test_validate_app_cpu_descriptor(self): """ Test whether custom validate_app_cpu_descriptor method raises a ValidationError when the app cpu descriptor cannot be converted to a fields.CPUInt. """ with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'min_cpu_limit', 'value': '100me'} PluginSerializer.validate_app_cpu_descriptor(descriptor_dict) descriptor_dict = {'name': 'max_cpu_limit', 'value': '100m'} self.assertEqual( 100, PluginSerializer.validate_app_cpu_descriptor(descriptor_dict))
def test_validate_gpu_limits(self): """ Test whether custom validate method raises a ValidationError when the 'max_gpu_limit' is smaller than the 'max_gpu_limit'. """ plg_serializer = PluginSerializer() self.plg_repr['min_gpu_limit'] = 2 self.plg_repr['max_gpu_limit'] = 1 with io.BytesIO(json.dumps(self.plg_repr).encode()) as f: data = {'descriptor_file': f} with self.assertRaises(serializers.ValidationError): plg_serializer.validate(data)
def test_validate_app_parameters_not_ui_exposed_and_not_optional(self): """ Test whether custom validate_app_parameters method raises a ValidationError when a plugin parameter that is not optional is not exposed to the ui. """ plugin = Plugin.objects.get(meta__name=self.plugin_name) plg_serializer = PluginSerializer(plugin) parameter_list = self.plugin_parameters parameter_list[0]['optional'] = False parameter_list[0]['ui_exposed'] = False with self.assertRaises(serializers.ValidationError): plg_serializer.validate_app_parameters(parameter_list)
def test_validate_app_int_descriptor(self): """ Test whether custom validate_app_int_descriptor method raises a ValidationError when the descriptor cannot be converted to a non-negative integer. """ error_msg = "This field must be a non-negative integer." with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'field_name', 'value': 'one'} PluginSerializer.validate_app_int_descriptor(descriptor_dict, error_msg) with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'field_name', 'value': -1} PluginSerializer.validate_app_int_descriptor(descriptor_dict, error_msg)
def test_validate_meta_collaborator(self): """ Test whether custom validate_meta_collaborator method raises a ValidationError when the user is not a collaborator for the already existing plugin meta. """ (meta, tf) = PluginMeta.objects.get_or_create(name=self.plugin_name) another_user = User.objects.create_user(username='******', email='*****@*****.**', password='******') plg_serializer = PluginSerializer() with self.assertRaises(serializers.ValidationError): plg_serializer.validate_meta_collaborator(meta, another_user)
def test_validate_gpu_limits(self): """ Test whether custom validate method raises a ValidationError when the 'max_gpu_limit' is smaller than the 'max_gpu_limit'. """ plugin = Plugin.objects.get(name=self.plugin_name) plg_serializer = PluginSerializer(plugin) self.plugin_repr['min_gpu_limit'] = 2 self.plugin_repr['max_gpu_limit'] = 1 data = self.plugin_repr.copy() del data['parameters'] with self.assertRaises(serializers.ValidationError): plg_serializer.validate(data)
def test_validate_update_validated_data(self): """ Test whether custom validate method updates validated data with the plugin app representation. """ plg_serializer = PluginSerializer() with io.BytesIO(json.dumps(self.plg_repr).encode()) as f: data = {'descriptor_file': f} new_data = plg_serializer.validate(data) self.assertIn('execshell', new_data) self.assertIn('selfpath', new_data) self.assertIn('selfexec', new_data) self.assertIn('parameters', new_data)
def test_validate_validates_max_number_of_workers(self): """ Test whether custom validate method validates the 'max_number_of_workers' descriptor. """ plugin = Plugin.objects.get(name=self.plugin_name) plg_serializer = PluginSerializer(plugin) data = self.plugin_repr.copy() del data['parameters'] data['max_number_of_workers'] = 5 plg_serializer.validate_app_workers_descriptor = mock.Mock() plg_serializer.validate(data) plg_serializer.validate_app_workers_descriptor.assert_called_with(5)
def test_validate_validates_min_memory_limit(self): """ Test whether custom validate method validates the 'min_memory_limit' descriptor. """ plugin = Plugin.objects.get(name=self.plugin_name) plg_serializer = PluginSerializer(plugin) data = self.plugin_repr.copy() del data['parameters'] data['min_memory_limit'] = 10000 plg_serializer.validate_app_memory_descriptor = mock.Mock() plg_serializer.validate(data) plg_serializer.validate_app_memory_descriptor.assert_called_with(10000)
def test_validate_app_int_descriptor(self): """ Test whether custom validate_app_int_descriptor method raises a ValidationError when the descriptor cannot be converted to a non-negative integer. """ error_msg = "This field must be a non-negative integer." with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'field_name', 'value': 'one'} PluginSerializer.validate_app_int_descriptor( descriptor_dict, error_msg) with self.assertRaises(serializers.ValidationError): descriptor_dict = {'name': 'field_name', 'value': -1} PluginSerializer.validate_app_int_descriptor( descriptor_dict, error_msg)
def test_validate_validates_max_memory_limit(self): """ Test whether custom validate method validates the 'max_memory_limit' descriptor. """ plugin = Plugin.objects.get(name=self.plugin_name) plg_serializer = PluginSerializer(plugin) data = self.plugin_repr.copy() del data['parameters'] data['max_memory_limit'] = 100000 plg_serializer.validate_app_memory_descriptor = mock.Mock() plg_serializer.validate(data) plg_serializer.validate_app_memory_descriptor.assert_called_with( {'name': 'max_memory_limit', 'value': 100000})
def test_validate_validates_max_number_of_workers(self): """ Test whether custom validate method validates the 'max_number_of_workers' descriptor. """ plugin = Plugin.objects.get(name=self.plugin_name) plg_serializer = PluginSerializer(plugin) data = self.plugin_repr.copy() del data['parameters'] data['max_number_of_workers'] = 5 plg_serializer.validate_app_workers_descriptor = mock.Mock() plg_serializer.validate(data) plg_serializer.validate_app_workers_descriptor.assert_called_with( {'name': 'max_number_of_workers', 'value': 5})
def test_read_app_representation(self): """ Test whether custom read_app_representation method returns an appropriate plugin representation dictionary from an uploaded json representation file. """ with io.BytesIO(json.dumps(self.plg_repr).encode()) as f: self.assertEqual(PluginSerializer.read_app_representation(f), self.plg_repr)
def modify_plugin(self, args): """ Modify an existing/registered plugin and add the current date as a new plugin modification date. """ plugin = self.get_plugin(args.name, args.version) compute_resource = None plg_repr = None if args.computeresource: (compute_resource, tf) = ComputeResource.objects.get_or_create( compute_resource_identifier=args.computeresource) if args.storeurl: plg_repr = self.get_plugin_representation_from_store(args.name, args.storeurl, args.version, args.storeusername, args.storepassword, args.storetimeout) if plg_repr: del plg_repr['parameters'] plg_serializer = PluginSerializer(plugin, data=plg_repr) plg_serializer.is_valid(raise_exception=True) if compute_resource: plugin = plg_serializer.save(compute_resource=compute_resource) else: plugin = plg_serializer.save() elif compute_resource: plg_serializer = PluginSerializer(plugin) plugin = plg_serializer.save(compute_resource=compute_resource) if plg_repr or compute_resource: plugin.modification_date = timezone.now() plugin.save()
def test_validate_validates_max_cpu_limit(self): """ Test whether custom validate method validates the 'max_cpu_limit' descriptor. """ plugin = Plugin.objects.get(meta__name=self.plugin_name) plg_serializer = PluginSerializer(plugin) data = self.plugin_repr.copy() del data['parameters'] data['max_cpu_limit'] = 200 plg_serializer.validate_app_cpu_descriptor = mock.Mock() plg_serializer.validate(data) plg_serializer.validate_app_cpu_descriptor.assert_called_with({ 'name': 'max_cpu_limit', 'value': 200 })
def add_plugin(self, args): """ Register/add a new plugin to the system. """ plg_repr = self.get_plugin_representation_from_store( args.name, args.storeurl, args.version, args.storeusername, args.storepassword, args.storetimeout) parameters_data = plg_repr['parameters'] del plg_repr['parameters'] plg_serializer = PluginSerializer(data=plg_repr) plg_serializer.is_valid(raise_exception=True) # collect and validate parameters parameters_serializers = [] for parameter in parameters_data: default = parameter.pop('default', None) parameter_serializer = PluginParameterSerializer(data=parameter) parameter_serializer.is_valid(raise_exception=True) serializer_dict = { 'serializer': parameter_serializer, 'default_serializer': None } if default is not None: param_type = parameter['type'] default_param_serializer = DEFAULT_PARAMETER_SERIALIZERS[ param_type](data={ 'value': default }) default_param_serializer.is_valid(raise_exception=True) serializer_dict[ 'default_serializer'] = default_param_serializer parameters_serializers.append(serializer_dict) # if no validation errors at this point then save to the DB (compute_resource, tf) = ComputeResource.objects.get_or_create( compute_resource_identifier=args.computeresource) plugin = plg_serializer.save(compute_resource=compute_resource) for param_serializer_dict in parameters_serializers: param = param_serializer_dict['serializer'].save(plugin=plugin) if param_serializer_dict['default_serializer'] is not None: param_serializer_dict['default_serializer'].save( plugin_param=param)
def add_plugin(self, args): """ Register/add a new plugin to the system. """ plg_repr = self.get_plugin_representation_from_store(args.name, args.storeurl, args.version, args.storeusername, args.storepassword, args.storetimeout) parameters_data = plg_repr['parameters'] del plg_repr['parameters'] plg_serializer = PluginSerializer(data=plg_repr) plg_serializer.is_valid(raise_exception=True) # collect parameters and validate and save them to the DB parameters_serializers = [] for parameter in parameters_data: default = None if 'default' in parameter: default = parameter['default'] del parameter['default'] parameter_serializer = PluginParameterSerializer(data=parameter) parameter_serializer.is_valid(raise_exception=True) serializer_dict = {'serializer': parameter_serializer, 'default_serializer': None} if default is not None: param_type = parameter['type'] default_param_serializer = DEFAULT_PARAMETER_SERIALIZERS[param_type]( data={'value': default}) default_param_serializer.is_valid(raise_exception=True) serializer_dict['default_serializer'] = default_param_serializer parameters_serializers.append(serializer_dict) # if no validation errors at this point then save to the DB (compute_resource, tf) = ComputeResource.objects.get_or_create( compute_resource_identifier=args.computeresource) plugin = plg_serializer.save(compute_resource=compute_resource) for param_serializer_dict in parameters_serializers: param = param_serializer_dict['serializer'].save(plugin=plugin) if param_serializer_dict['default_serializer'] is not None: param_serializer_dict['default_serializer'].save(plugin_param=param)
def modify_pipeline(self, args): """ Modify an existing/registered plugin and add the current date as a new plugin modification date. """ plugin = self.get_plugin(args.name) compute_resource = None plg_repr = None if args.computeresource: (compute_resource, tf) = ComputeResource.objects.get_or_create( compute_resource_identifier=args.computeresource) if args.storeurl: timeout = 30 if args.storetimeout: timeout = args.storetimeout plg_repr = self.get_plugin_representation_from_store(args.name, args.storeurl, args.storeusername, args.storepassword, timeout) if plg_repr: parameters_data = plg_repr['parameters'] del plg_repr['parameters'] plg_serializer = PluginSerializer(plugin, data=plg_repr) plg_serializer.is_valid(raise_exception=True) plugin = plg_serializer.save(compute_resource=compute_resource) # collect existing and new parameters and validate and save them to the DB db_parameters = plugin.parameters.all() for parameter in parameters_data: default = parameter['default'] if 'default' in parameter else None del parameter['default'] db_param = [p for p in db_parameters if p.name == parameter['name']] if db_param: parameter_serializer = PluginParameterSerializer(db_param[0], data=parameter) else: parameter_serializer = PluginParameterSerializer(data=parameter) parameter_serializer.is_valid(raise_exception=True) param = parameter_serializer.save(plugin=plugin) if default is not None: db_default = param.get_default() if db_default is not None: # check if there is already a default in DB default_param_serializer = DEFAULT_PARAMETER_SERIALIZERS[ param.type](db_default, data={'value': default}) else: default_param_serializer = DEFAULT_PARAMETER_SERIALIZERS[ param.type](data={'value': default}) default_param_serializer.is_valid(raise_exception=True) default_param_serializer.save(plugin_param=param) elif compute_resource: plg_serializer = PluginSerializer(plugin) plugin = plg_serializer.save(compute_resource=compute_resource) if plg_repr or compute_resource: plugin.modification_date = timezone.now() plugin.save()