def test_convert_config_to_v6_json(self): """Tests calling convert_config_to_v6_json()""" # Try configuration with nothing set config = RecipeConfiguration() json = convert_config_to_v6_json(config) RecipeConfigurationV6(config=json.get_dict(), do_validate=True) # Revalidate # Try configuration with a variety of values config = RecipeConfiguration() config.add_mount(HostMountConfig('mount_1', '/the/host/path')) config.add_mount( VolumeMountConfig('mount_2', 'driver', { 'opt_1': 'foo', 'opt_2': 'bar' })) config.default_output_workspace = 'workspace_1' config.add_output_workspace('output_2', 'workspace_2') config.priority = 999 config.add_setting('setting_1', 'Hello') config.add_setting('setting_2', 'Scale!') json = convert_config_to_v6_json(config) RecipeConfigurationV6(config=json.get_dict(), do_validate=True) # Revalidate self.assertSetEqual(set(json.get_dict()['mounts'].keys()), {'mount_1', 'mount_2'}) self.assertEqual(json.get_dict()['priority'], 999) self.assertSetEqual(set(json.get_dict()['settings'].keys()), {'setting_1', 'setting_2'})
def _create_new_recipes(self): """Creates the recipe models for a new recipe run """ rt = RecipeType.objects.get(name=self.recipe_type_name) if not rt.is_active: raise InactiveRecipeType("Recipe Type %s is inactive" % rt.name) recipe_type_rev = RecipeTypeRevision.objects.get_revision( self.recipe_type_name, self.recipe_type_rev_num) config = None if self.configuration: config = RecipeConfigurationV6(self.configuration) with transaction.atomic(): recipe_input_data = DataV6(self.recipe_input_data).get_data() recipe = Recipe.objects.create_recipe_v6( recipe_type_rev=recipe_type_rev, event_id=self.event_id, ingest_id=self.ingest_event_id, input_data=recipe_input_data, batch_id=self.batch_id, recipe_config=config) recipe.save() self.new_recipes.append(recipe.id) recipes = [] if recipe: recipes.append(recipe) return recipes
def post(self, request): """Queue a recipe and returns the new job information in JSON form :param request: the HTTP POST request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ if request.version != 'v6': raise Http404 recipe_type_id = rest_util.parse_int(request, 'recipe_type_id') recipe_data = rest_util.parse_dict(request, 'input', {}) configuration_dict = rest_util.parse_dict(request, 'configuration', required=False) configuration = None try: recipeData = DataV6(recipe_data, do_validate=True) except InvalidData as ex: logger.exception('Unable to queue new recipe. Invalid input: %s', recipe_data) raise BadParameter(unicode(ex)) try: recipe_type = RecipeType.objects.get(pk=recipe_type_id) except RecipeType.DoesNotExist: raise Http404 if configuration_dict: try: configuration = RecipeConfigurationV6( configuration_dict, do_validate=True).get_configuration() except InvalidRecipeConfiguration as ex: message = 'Recipe configuration invalid' logger.exception(message) raise BadParameter('%s: %s' % (message, unicode(ex))) try: recipe = Queue.objects.queue_new_recipe_for_user_v6( recipe_type, recipeData.get_data(), recipe_config=configuration) except (InvalidData, InvalidRecipeData) as err: return Response('Invalid recipe data: ' + unicode(err), status=status.HTTP_400_BAD_REQUEST) except InactiveRecipeType as err: return Response('Inactive recipe type: ' + unicode(err), status=status.HTTP_400_BAD_REQUEST) serializer = RecipeSerializerV6(recipe) recipe_url = reverse('recipe_details_view', args=[recipe.id], request=request) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=recipe_url))
def merge_recipe_config(self, recipe_config): """Merges a recipe configuration object values into this job configuration, overriding any common fields :param recipe_config: The recipe config dictionary :type recipe_config: dict :raises :class:`recipe.configuration.exceptions.InvalidRecipeConfiguration`: If the recipe_config is invalid """ config_to_merge = RecipeConfigurationV6( recipe_config).get_configuration() if config_to_merge.default_output_workspace: self.default_output_workspace = config_to_merge.default_output_workspace self.output_workspaces.update(config_to_merge.output_workspaces) if config_to_merge.priority: self.priority = config_to_merge.priority self.mounts.update(config_to_merge.mounts) self.settings.update(config_to_merge.settings)
def test_init_validation(self): """Tests the validation done in __init__""" # Try minimal acceptable configuration RecipeConfigurationV6(do_validate=True) # Invalid version config_dict = {'version': 'BAD'} with self.assertRaises(InvalidRecipeConfiguration) as context: RecipeConfigurationV6(config_dict, do_validate=True) self.assertEqual(context.exception.error.name, 'INVALID_VERSION') # Valid v6 configuration config_dict = { 'version': '6', 'mounts': { 'mount_1': { 'type': 'host', 'host_path': '/the/host/path' }, 'mount_2': { 'type': 'volume', 'driver': 'driver', 'driver_opts': { 'opt_1': 'foo', 'opt_2': 'bar' } } }, 'output_workspaces': { 'default': 'workspace_1', 'outputs': { 'output': 'workspace_2' } }, 'priority': 999, 'settings': { 'setting_1': '1234', 'setting_2': '5678' } } existing = RecipeConfigurationV6(config=config_dict, do_validate=True) jc = existing.get_configuration() vol1 = jc.get_mount_volume('mount_1', 'test1', '/test/path', 'ro') self.assertEqual(vol1.name, 'test1') self.assertEqual(vol1.container_path, '/test/path') self.assertEqual(vol1.mode, 'ro') self.assertEqual(vol1.is_host, True) self.assertEqual(vol1.host_path, '/the/host/path') vol2 = jc.get_mount_volume('mount_2', 'test2', '/test/path', 'ro') self.assertEqual(vol2.name, 'test2') self.assertEqual(vol2.container_path, '/test/path') self.assertEqual(vol2.mode, 'ro') self.assertEqual(vol2.is_host, False) self.assertEqual(vol2.host_path, None) self.assertEqual(vol2.driver, 'driver') self.assertDictEqual(vol2.driver_opts, { 'opt_1': 'foo', 'opt_2': 'bar' }) self.assertEqual(jc.get_output_workspace('test'), 'workspace_1') self.assertEqual(jc.get_output_workspace('output'), 'workspace_2') self.assertEqual(jc.priority, 999) self.assertEqual(jc.get_setting_value('setting_1'), '1234') self.assertEqual(jc.get_setting_value('setting_2'), '5678') # Overriding some settings from an existing config config_dict = { 'version': '6', 'priority': 888, 'settings': { 'setting_1': '123', 'setting_2': '678' } } jc = RecipeConfigurationV6(config=config_dict, existing=existing, do_validate=True).get_configuration() vol1 = jc.get_mount_volume('mount_1', 'test1', '/test/path', 'ro') self.assertEqual(vol1.name, 'test1') self.assertEqual(vol1.container_path, '/test/path') self.assertEqual(vol1.mode, 'ro') self.assertEqual(vol1.is_host, True) self.assertEqual(vol1.host_path, '/the/host/path') vol2 = jc.get_mount_volume('mount_2', 'test2', '/test/path', 'ro') self.assertEqual(vol2.name, 'test2') self.assertEqual(vol2.container_path, '/test/path') self.assertEqual(vol2.mode, 'ro') self.assertEqual(vol2.is_host, False) self.assertEqual(vol2.host_path, None) self.assertEqual(vol2.driver, 'driver') self.assertDictEqual(vol2.driver_opts, { 'opt_1': 'foo', 'opt_2': 'bar' }) self.assertEqual(jc.get_output_workspace('test'), 'workspace_1') self.assertEqual(jc.get_output_workspace('output'), 'workspace_2') self.assertEqual(jc.priority, 888) self.assertEqual(jc.get_setting_value('setting_1'), '123') self.assertEqual(jc.get_setting_value('setting_2'), '678')