Ejemplo n.º 1
0
    def test_successful(self):
        '''Tests calling RecipeDefinition.get_unqueued_job_statuses() successfully.'''

        recipe_definition = RecipeDefinition(self.definition)
        recipe_definition.validate_job_interfaces()

        recipe_jobs = {
            'job_failed': self.job_failed,
            'job_completed': self.job_completed,
            'job_running': self.job_running,
            'job_queued': self.job_queued,
            'job_canceled': self.job_canceled,
            'job_fa_co_a': self.job_fa_co_a,
            'job_fa_co_b': self.job_fa_co_b,
            'job_co_ru_qu_a': self.job_co_ru_qu_a,
            'job_co_ru_qu_b': self.job_co_ru_qu_b,
            'job_qu_ca_a': self.job_qu_ca_a,
            'job_qu_ca_b': self.job_qu_ca_b,
        }
        results = recipe_definition.get_unqueued_job_statuses(recipe_jobs)

        expected_results = {
            self.job_fa_co_a.id: 'BLOCKED',
            self.job_fa_co_b.id: 'BLOCKED',
            self.job_co_ru_qu_a.id: 'PENDING',
            self.job_co_ru_qu_b.id: 'PENDING',
            self.job_qu_ca_a.id: 'BLOCKED',
            self.job_qu_ca_b.id: 'BLOCKED',
        }

        self.assertDictEqual(results, expected_results)
Ejemplo n.º 2
0
    def test_successful(self):
        '''Tests calling RecipeDefinition.get_unqueued_job_statuses() successfully.'''

        recipe_definition = RecipeDefinition(self.definition)
        recipe_definition.validate_job_interfaces()

        recipe_jobs = {
            'job_failed': self.job_failed,
            'job_completed': self.job_completed,
            'job_running': self.job_running,
            'job_queued': self.job_queued,
            'job_canceled': self.job_canceled,
            'job_fa_co_a': self.job_fa_co_a,
            'job_fa_co_b': self.job_fa_co_b,
            'job_co_ru_qu_a': self.job_co_ru_qu_a,
            'job_co_ru_qu_b': self.job_co_ru_qu_b,
            'job_qu_ca_a': self.job_qu_ca_a,
            'job_qu_ca_b': self.job_qu_ca_b,
        }
        results = recipe_definition.get_unqueued_job_statuses(recipe_jobs)

        expected_results = {
            self.job_fa_co_a.id: 'BLOCKED',
            self.job_fa_co_b.id: 'BLOCKED',
            self.job_co_ru_qu_a.id: 'PENDING',
            self.job_co_ru_qu_b.id: 'PENDING',
            self.job_qu_ca_a.id: 'BLOCKED',
            self.job_qu_ca_b.id: 'BLOCKED',
        }

        self.assertDictEqual(results, expected_results)
Ejemplo n.º 3
0
    def setUp(self):
        django.setup()

        workspace = storage_test_utils.create_workspace()
        source_file = source_test_utils.create_source(workspace=workspace)
        self.event = trigger_test_utils.create_trigger_event()

        interface_1 = {
            "version": "1.0",
            "command": "test_command",
            "command_arguments": "test_arg",
            "input_data": [{"name": "Test Input 1", "type": "file", "media_types": ["text/plain"]}],
            "output_data": [{"name": "Test Output 1", "type": "files", "media_type": "image/png"}],
        }
        self.job_type_1 = job_test_utils.create_job_type(interface=interface_1)

        interface_2 = {
            "version": "1.0",
            "command": "test_command",
            "command_arguments": "test_arg",
            "input_data": [{"name": "Test Input 2", "type": "files", "media_types": ["image/png", "image/tiff"]}],
            "output_data": [{"name": "Test Output 2", "type": "file"}],
        }
        self.job_type_2 = job_test_utils.create_job_type(interface=interface_2)

        definition = {
            "version": "1.0",
            "input_data": [{"name": "Recipe Input", "type": "file", "media_types": ["text/plain"]}],
            "jobs": [
                {
                    "name": "Job 1",
                    "job_type": {"name": self.job_type_1.name, "version": self.job_type_1.version},
                    "recipe_inputs": [{"recipe_input": "Recipe Input", "job_input": "Test Input 1"}],
                },
                {
                    "name": "Job 2",
                    "job_type": {"name": self.job_type_2.name, "version": self.job_type_2.version},
                    "dependencies": [
                        {"name": "Job 1", "connections": [{"output": "Test Output 1", "input": "Test Input 2"}]}
                    ],
                },
            ],
        }

        recipe_definition = RecipeDefinition(definition)
        recipe_definition.validate_job_interfaces()

        self.recipe_type = recipe_test_utils.create_recipe_type(definition=definition)

        self.data = {
            "version": "1.0",
            "input_data": [{"name": "Recipe Input", "file_id": source_file.id}],
            "workspace_id": workspace.id,
        }

        # Register a fake processor
        self.mock_processor = MagicMock(QueueEventProcessor)
        Queue.objects.register_processor(lambda: self.mock_processor)
Ejemplo n.º 4
0
    def test_successful(self, mock_store):
        '''Tests calling RecipeDefinition.validate_data() successfully.'''

        definition = {
            'version':
            '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name':
                'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_1,
                }],
            }, {
                'name':
                'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name':
                    'Job 1',
                    'connections': [{
                        'output': self.output_name_1,
                        'input': self.input_name_2,
                    }],
                }],
            }],
        }
        recipe = RecipeDefinition(definition)
        recipe.validate_job_interfaces()

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': self.file_1.id,
            }],
            'workspace_id': 1,
        }
        recipe_data = RecipeData(data)

        # No exception is success
        recipe.validate_data(recipe_data)
Ejemplo n.º 5
0
    def test_missing_workspace(self, mock_store):
        '''Tests calling RecipeDefinition.validate_data() with a missing required workspace.'''

        definition = {
            'version':
            '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name':
                'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_1,
                }],
            }, {
                'name':
                'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name':
                    'Job 1',
                    'connections': [{
                        'output': self.output_name_1,
                        'input': self.input_name_2,
                    }],
                }],
            }],
        }
        recipe = RecipeDefinition(definition)
        recipe.validate_job_interfaces()

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': self.file_1.id,
            }],
        }
        recipe_data = RecipeData(data)

        self.assertRaises(InvalidRecipeData, recipe.validate_data, recipe_data)
Ejemplo n.º 6
0
    def test_successful(self, mock_store):
        """Tests calling RecipeDefinition.validate_data() successfully."""

        definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_1,
                }],
            }, {
                'name': 'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name': 'Job 1',
                    'connections': [{
                        'output': self.output_name_1,
                        'input': self.input_name_2,
                    }],
                }],
            }],
        }
        recipe = RecipeDefinition(definition)
        recipe.validate_job_interfaces()

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': self.file_1.id,
            }],
            'workspace_id': 1,
        }
        recipe_data = RecipeData(data)

        # No exception is success
        recipe.validate_data(recipe_data)
Ejemplo n.º 7
0
    def test_missing_workspace(self, mock_store):
        """Tests calling RecipeDefinition.validate_data() with a missing required workspace."""

        definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_1,
                }],
            }, {
                'name': 'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name': 'Job 1',
                    'connections': [{
                        'output': self.output_name_1,
                        'input': self.input_name_2,
                    }],
                }],
            }],
        }
        recipe = RecipeDefinition(definition)
        recipe.validate_job_interfaces()

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': self.file_1.id,
            }],
        }
        recipe_data = RecipeData(data)

        self.assertRaises(InvalidRecipeData, recipe.validate_data, recipe_data)
Ejemplo n.º 8
0
    def test_successful(self):
        '''Tests calling RecipeDefinition.validate_job_interfaces() successfully.'''

        definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_1,
                }],
            }, {
                'name': 'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name': 'Job 1',
                    'connections': [{
                        'output': self.output_name_1,
                        'input': self.input_name_2,
                    }],
                }],
            }],
        }
        recipe = RecipeDefinition(definition)

        # No exception is success
        recipe.validate_job_interfaces()
Ejemplo n.º 9
0
    def test_successful_no_workspace(self, mock_store):
        '''Tests calling RecipeDefinition.validate_data() successfully with no workspace.'''

        definition = {
            'version':
            '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name':
                'Job 3',
                'job_type': {
                    'name': self.job_type_3.name,
                    'version': self.job_type_3.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_3,
                }],
            }],
        }
        recipe = RecipeDefinition(definition)
        recipe.validate_job_interfaces()

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': self.file_1.id,
            }],
        }
        recipe_data = RecipeData(data)

        # No exception is success
        recipe.validate_data(recipe_data)
Ejemplo n.º 10
0
    def test_successful_no_workspace(self, mock_store):
        """Tests calling RecipeDefinition.validate_data() successfully with no workspace."""

        definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 3',
                'job_type': {
                    'name': self.job_type_3.name,
                    'version': self.job_type_3.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_3,
                }],
            }],
        }
        recipe = RecipeDefinition(definition)
        recipe.validate_job_interfaces()

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': self.file_1.id,
            }],
        }
        recipe_data = RecipeData(data)

        # No exception is success
        recipe.validate_data(recipe_data)
Ejemplo n.º 11
0
def _import_recipe_type(recipe_type_dict, recipe_type=None):
    '''Attempts to apply the given recipe types configuration to the system.

    Note that proper model locking must be performed before calling this method.

    :param recipe_type_dict: A dictionary of recipe type configuration changes to import.
    :type recipe_type_dict: dict
    :param recipe_type: The existing recipe type model to update if applicable.
    :type recipe_type: :class:`recipe.models.RecipeType`
    :returns: A list of warnings discovered during import.
    :rtype: list[:class:`port.schema.ValidationWarning`]

    :raises :class:`port.schema.InvalidConfiguration`: If any part of the configuration violates the specification.
    '''
    warnings = []

    # Parse the JSON content into validated model fields
    recipe_type_serializer = serializers.ConfigurationRecipeTypeSerializer(recipe_type, data=recipe_type_dict)
    if not recipe_type_serializer.is_valid():
        raise InvalidConfiguration('Invalid recipe type schema: %s -> %s' % (recipe_type_dict['name'],
                                                                             recipe_type_serializer.errors))
    result = recipe_type_serializer.validated_data

    # Validate the recipe definition
    try:
        definition_dict = None
        if 'definition' in result:
            definition_dict = result.get('definition')
        elif recipe_type:
            definition_dict = recipe_type.definition
        definition = RecipeDefinition(definition_dict)
        warnings.extend(definition.validate_job_interfaces())
    except (InvalidDefinition, InvalidRecipeConnection) as ex:
        raise InvalidConfiguration('Recipe type definition invalid: %s -> %s' % (result.get('name'), unicode(ex)))

    # Validate the trigger rule
    trigger_rule = None
    if 'trigger_rule' in result and result.get('trigger_rule'):
        trigger_rule = TriggerRule(**result.get('trigger_rule'))
    if trigger_rule:
        trigger_config = trigger_rule.get_configuration()
        if not isinstance(trigger_config, RecipeTriggerRuleConfiguration):
            logger.exception('Recipe type trigger rule type invalid')
            raise InvalidConfiguration('Recipe type trigger type invalid: %s -> %s' % (result.get('name'),
                                                                                       trigger_rule.type))
        try:
            warnings.extend(trigger_config.validate_trigger_for_recipe(definition))

            # Create a new rule when the trigger content was provided
            if recipe_type_dict.get('trigger_rule'):
                rule_handler = trigger_handler.get_trigger_rule_handler(trigger_rule.type)
                trigger_rule = rule_handler.create_trigger_rule(trigger_rule.configuration, trigger_rule.name,
                                                                trigger_rule.is_active)
        except (InvalidDefinition, InvalidTriggerType, InvalidTriggerRule, InvalidRecipeConnection) as ex:
            logger.exception('Recipe type trigger rule invalid')
            raise InvalidConfiguration('Recipe type trigger rule invalid: %s -> %s' % (result.get('name'), unicode(ex)))
    remove_trigger_rule = 'trigger_rule' in recipe_type_dict and not recipe_type_dict['trigger_rule']

    # Edit or create the associated recipe type model
    if recipe_type:
        try:
            RecipeType.objects.edit_recipe_type(recipe_type.id, result.get('title'), result.get('description'),
                                                definition, trigger_rule, remove_trigger_rule)
        except (InvalidDefinition, InvalidTriggerType, InvalidTriggerRule, InvalidRecipeConnection) as ex:
            logger.exception('Recipe type edit failed')
            raise InvalidConfiguration('Unable to edit recipe type: %s -> %s' % (result.get('name'), unicode(ex)))
    else:
        try:
            RecipeType.objects.create_recipe_type(result.get('name'), result.get('version'), result.get('title'),
                                                  result.get('description'), definition, trigger_rule)
        except (InvalidDefinition, InvalidTriggerType, InvalidTriggerRule, InvalidRecipeConnection) as ex:
            logger.exception('Recipe type create failed')
            raise InvalidConfiguration('Unable to create new recipe type: %s -> %s' % (result.get('name'), unicode(ex)))
    return warnings
Ejemplo n.º 12
0
def _import_recipe_type(recipe_type_dict, recipe_type=None):
    """Attempts to apply the given recipe types configuration to the system.

    Note that proper model locking must be performed before calling this method.

    :param recipe_type_dict: A dictionary of recipe type configuration changes to import.
    :type recipe_type_dict: dict
    :param recipe_type: The existing recipe type model to update if applicable.
    :type recipe_type: :class:`recipe.models.RecipeType`
    :returns: A list of warnings discovered during import.
    :rtype: list[:class:`port.schema.ValidationWarning`]

    :raises :class:`port.schema.InvalidConfiguration`: If any part of the configuration violates the specification.
    """
    warnings = []

    # Parse the JSON content into validated model fields
    recipe_type_serializer = serializers.ConfigurationRecipeTypeSerializer(
        recipe_type, data=recipe_type_dict)
    if not recipe_type_serializer.is_valid():
        raise InvalidConfiguration(
            'Invalid recipe type schema: %s -> %s' %
            (recipe_type_dict['name'], recipe_type_serializer.errors))
    result = recipe_type_serializer.validated_data

    # Validate the recipe definition
    try:
        definition_dict = None
        if 'definition' in result:
            definition_dict = result.get('definition')
        elif recipe_type:
            definition_dict = recipe_type.definition
        definition = RecipeDefinition(definition_dict)
        warnings.extend(definition.validate_job_interfaces())
    except (InvalidDefinition, InvalidRecipeConnection) as ex:
        raise InvalidConfiguration('Recipe type definition invalid: %s -> %s' %
                                   (result.get('name'), unicode(ex)))

    # Validate the trigger rule
    trigger_rule = None
    if 'trigger_rule' in result and result.get('trigger_rule'):
        trigger_rule = TriggerRule(**result.get('trigger_rule'))
    if trigger_rule:
        trigger_config = trigger_rule.get_configuration()
        if not isinstance(trigger_config, RecipeTriggerRuleConfiguration):
            logger.exception('Recipe type trigger rule type invalid')
            raise InvalidConfiguration(
                'Recipe type trigger type invalid: %s -> %s' %
                (result.get('name'), trigger_rule.type))
        try:
            warnings.extend(
                trigger_config.validate_trigger_for_recipe(definition))

            # Create a new rule when the trigger content was provided
            if recipe_type_dict.get('trigger_rule'):
                rule_handler = trigger_handler.get_trigger_rule_handler(
                    trigger_rule.type)
                trigger_rule = rule_handler.create_trigger_rule(
                    trigger_rule.configuration, trigger_rule.name,
                    trigger_rule.is_active)
        except (InvalidDefinition, InvalidTriggerType, InvalidTriggerRule,
                InvalidRecipeConnection) as ex:
            logger.exception('Recipe type trigger rule invalid')
            raise InvalidConfiguration(
                'Recipe type trigger rule invalid: %s -> %s' %
                (result.get('name'), unicode(ex)))
    remove_trigger_rule = 'trigger_rule' in recipe_type_dict and not recipe_type_dict[
        'trigger_rule']

    # Edit or create the associated recipe type model
    if recipe_type:
        try:
            RecipeType.objects.edit_recipe_type(recipe_type.id,
                                                result.get('title'),
                                                result.get('description'),
                                                definition, trigger_rule,
                                                remove_trigger_rule)
        except (InvalidDefinition, InvalidTriggerType, InvalidTriggerRule,
                InvalidRecipeConnection) as ex:
            logger.exception('Recipe type edit failed')
            raise InvalidConfiguration('Unable to edit recipe type: %s -> %s' %
                                       (result.get('name'), unicode(ex)))
    else:
        try:
            RecipeType.objects.create_recipe_type(result.get('name'),
                                                  result.get('version'),
                                                  result.get('title'),
                                                  result.get('description'),
                                                  definition, trigger_rule)
        except (InvalidDefinition, InvalidTriggerType, InvalidTriggerRule,
                InvalidRecipeConnection) as ex:
            logger.exception('Recipe type create failed')
            raise InvalidConfiguration(
                'Unable to create new recipe type: %s -> %s' %
                (result.get('name'), unicode(ex)))
    return warnings
Ejemplo n.º 13
0
class TestRecipeTypeManagerEditRecipeType(TransactionTestCase):

    def setUp(self):
        django.setup()

        self.workspace = storage_test_utils.create_workspace()

        interface_1 = {
            'version': '1.0',
            'command': 'my_command',
            'command_arguments': 'args',
            'input_data': [{
                'name': 'Test Input 1',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'output_data': [{
                'name': 'Test Output 1',
                'type': 'files',
                'media_type': 'image/png',
            }]}
        self.job_type_1 = job_test_utils.create_job_type(interface=interface_1)

        interface_2 = {
            'version': '1.0',
            'command': 'my_command',
            'command_arguments': 'args',
            'input_data': [{
                'name': 'Test Input 2',
                'type': 'files',
                'media_types': ['image/png', 'image/tiff'],
            }],
            'output_data': [{
                'name': 'Test Output 2',
                'type': 'file',
            }]}
        self.job_type_2 = job_test_utils.create_job_type(interface=interface_2)

        self.definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': 'Test Input 1',
                }]
            }, {
                'name': 'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name': 'Job 1',
                    'connections': [{
                        'output': 'Test Output 1',
                        'input': 'Test Input 2',
                    }]
                }]
            }]
        }
        self.recipe_def = RecipeDefinition(self.definition)
        self.recipe_def.validate_job_interfaces()

        self.new_definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': 'Test Input 1',
                }]
            }]
        }
        self.new_recipe_def = RecipeDefinition(self.new_definition)
        self.new_recipe_def.validate_job_interfaces()

        self.configuration = {
            'version': '1.0',
            'condition': {
                'media_type': 'text/plain'
            },
            'data': {
                'input_data_name': 'Recipe Input',
                'workspace_name': self.workspace.name
            }
        }
        self.trigger_config = recipe_test_utils.MockTriggerRuleConfiguration(recipe_test_utils.MOCK_TYPE,
                                                                             self.configuration)

        self.new_configuration = {
            'version': '1.0',
            'condition': {
                'media_type': 'application/json'
            },
            'data': {
                'input_data_name': 'Recipe Input',
                'workspace_name': self.workspace.name
            }
        }
        self.new_trigger_config = recipe_test_utils.MockTriggerRuleConfiguration(recipe_test_utils.MOCK_TYPE,
                                                                                 self.new_configuration)

    def test_change_simple_no_trigger(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with only basic attributes and no previous trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        recipe_type = RecipeType.objects.create_recipe_type(name, version, title, desc, self.recipe_def, None)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(pk=recipe_type.id)
            # Edit the recipe
            new_title = 'New title'
            new_desc = 'New description'
            RecipeType.objects.edit_recipe_type(recipe_type.id, new_title, new_desc, None, None, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, new_title)
        self.assertEqual(recipe_type.description, new_desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(), self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertIsNone(recipe_type.trigger_rule)
        num_of_revs = RecipeTypeRevision.objects.filter(recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)

    def test_change_simple_with_trigger(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with only basic attributes and a previous trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_TYPE,
                                                              configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(pk=recipe_type.id)
            # Edit the recipe
            new_title = 'New title'
            new_desc = 'New description'
            RecipeType.objects.edit_recipe_type(recipe_type.id, new_title, new_desc, None, None, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, new_title)
        self.assertEqual(recipe_type.description, new_desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(), self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertEqual(recipe_type.trigger_rule_id, trigger_rule_id)
        num_of_revs = RecipeTypeRevision.objects.filter(recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)

    def test_change_to_definition(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with a change to the definition"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_TYPE,
                                                              configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(pk=recipe_type.id)
            # Edit the recipe
            RecipeType.objects.edit_recipe_type(recipe_type.id, None, None, self.new_recipe_def, None, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(), self.new_recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 2)
        self.assertEqual(recipe_type.trigger_rule_id, trigger_rule_id)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertTrue(trigger_rule.is_active)
        # New revision due to definition change
        num_of_revs = RecipeTypeRevision.objects.filter(recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 2)

    def test_change_to_trigger_rule(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with a change to the trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_TYPE,
                                                              configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        new_trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_TYPE,
                                                                  configuration=self.new_trigger_config.get_dict())
        new_trigger_rule_id = new_trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(pk=recipe_type.id)
            # Edit the recipe
            RecipeType.objects.edit_recipe_type(recipe_type.id, None, None, None, new_trigger_rule, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(), self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertEqual(recipe_type.trigger_rule_id, new_trigger_rule_id)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertFalse(trigger_rule.is_active)
        new_trigger_rule = TriggerRule.objects.get(pk=new_trigger_rule_id)
        self.assertTrue(new_trigger_rule.is_active)
        num_of_revs = RecipeTypeRevision.objects.filter(recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)

    def test_remove_trigger_rule(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() that removes the trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_TYPE,
                                                              configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(pk=recipe_type.id)
            # Edit the recipe
            RecipeType.objects.edit_recipe_type(recipe_type.id, None, None, None, None, True)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(), self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertIsNone(recipe_type.trigger_rule)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertFalse(trigger_rule.is_active)
        num_of_revs = RecipeTypeRevision.objects.filter(recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)

    def test_change_to_both(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with a change to both the definition and trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_TYPE,
                                                              configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        new_trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_TYPE,
                                                                  configuration=self.new_trigger_config.get_dict())
        new_trigger_rule_id = new_trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(pk=recipe_type.id)
            # Edit the recipe
            RecipeType.objects.edit_recipe_type(recipe_type.id, None, None, self.new_recipe_def, new_trigger_rule,
                                                False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(), self.new_recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 2)
        self.assertEqual(recipe_type.trigger_rule_id, new_trigger_rule_id)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertFalse(trigger_rule.is_active)
        new_trigger_rule = TriggerRule.objects.get(pk=new_trigger_rule_id)
        self.assertTrue(new_trigger_rule.is_active)
        # New revision due to definition change
        num_of_revs = RecipeTypeRevision.objects.filter(recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 2)

    def test_invalid_trigger_rule(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with a new invalid trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_TYPE,
                                                              configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        new_trigger_rule = trigger_test_utils.create_trigger_rule(trigger_type=recipe_test_utils.MOCK_ERROR_TYPE,
                                                                  configuration=self.new_trigger_config.get_dict())
        recipe_type = RecipeType.objects.create_recipe_type(name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(pk=recipe_type.id)
            # Edit the recipe
            self.assertRaises(InvalidRecipeConnection, RecipeType.objects.edit_recipe_type, recipe_type.id, None, None,
                              self.new_recipe_def, new_trigger_rule, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(), self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertEqual(recipe_type.trigger_rule_id, trigger_rule_id)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertTrue(trigger_rule.is_active)
        num_of_revs = RecipeTypeRevision.objects.filter(recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)
Ejemplo n.º 14
0
class TestRecipeTypeManagerCreateRecipeType(TransactionTestCase):

    def setUp(self):
        django.setup()

        self.workspace = storage_test_utils.create_workspace()

        interface_1 = {
            'version': '1.0',
            'command': 'my_command',
            'command_arguments': 'args',
            'input_data': [{
                'name': 'Test Input 1',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'output_data': [{
                'name': 'Test Output 1',
                'type': 'files',
                'media_type': 'image/png',
            }]}
        self.job_type_1 = job_test_utils.create_job_type(interface=interface_1)

        interface_2 = {
            'version': '1.0',
            'command': 'my_command',
            'command_arguments': 'args',
            'input_data': [{
                'name': 'Test Input 2',
                'type': 'files',
                'media_types': ['image/png', 'image/tiff'],
            }],
            'output_data': [{
                'name': 'Test Output 2',
                'type': 'file',
            }]}
        self.job_type_2 = job_test_utils.create_job_type(interface=interface_2)

        self.definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': 'Test Input 1',
                }]
            }, {
                'name': 'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name': 'Job 1',
                    'connections': [{
                        'output': 'Test Output 1',
                        'input': 'Test Input 2',
                    }]
                }]
            }]
        }
        self.recipe_def = RecipeDefinition(self.definition)
        self.recipe_def.validate_job_interfaces()

    def test_successful(self):
        """Tests calling RecipeTypeManager.create_recipe_type() successfully."""

        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        recipe_type = RecipeType.objects.create_recipe_type(name, version, title, desc, self.recipe_def, None)

        results_recipe_type = RecipeType.objects.get(pk=recipe_type.id)
        self.assertEqual(results_recipe_type.name, name)
        self.assertEqual(results_recipe_type.version, version)
        self.assertEqual(results_recipe_type.title, title)
        self.assertEqual(results_recipe_type.description, desc)
        self.assertDictEqual(results_recipe_type.definition, self.definition)

        results_recipe_type_rev = RecipeTypeRevision.objects.get(recipe_type_id=recipe_type.id, revision_num=1)
        self.assertDictEqual(results_recipe_type_rev.definition, self.definition)
Ejemplo n.º 15
0
    def setUp(self):
        django.setup()

        workspace = storage_test_utils.create_workspace()
        source_file = source_test_utils.create_source(workspace=workspace)
        self.event = trigger_test_utils.create_trigger_event()

        interface_1 = {
            'version':
            '1.0',
            'command':
            'test_command',
            'command_arguments':
            'test_arg',
            'input_data': [{
                'name': 'Test Input 1',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'output_data': [{
                'name': 'Test Output 1',
                'type': 'files',
                'media_type': 'image/png',
            }]
        }
        self.job_type_1 = job_test_utils.create_job_type(interface=interface_1)

        interface_2 = {
            'version':
            '1.0',
            'command':
            'test_command',
            'command_arguments':
            'test_arg',
            'input_data': [{
                'name': 'Test Input 2',
                'type': 'files',
                'media_types': ['image/png', 'image/tiff'],
            }],
            'output_data': [{
                'name': 'Test Output 2',
                'type': 'file',
            }]
        }
        self.job_type_2 = job_test_utils.create_job_type(interface=interface_2)

        definition = {
            'version':
            '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name':
                'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': 'Test Input 1',
                }]
            }, {
                'name':
                'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name':
                    'Job 1',
                    'connections': [{
                        'output': 'Test Output 1',
                        'input': 'Test Input 2',
                    }]
                }]
            }]
        }

        recipe_definition = RecipeDefinition(definition)
        recipe_definition.validate_job_interfaces()

        self.recipe_type = recipe_test_utils.create_recipe_type(
            definition=definition)

        self.data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': source_file.id,
            }],
            'workspace_id': workspace.id,
        }

        # Register a fake processor
        self.mock_processor = MagicMock(QueueEventProcessor)
        Queue.objects.register_processor(lambda: self.mock_processor)
Ejemplo n.º 16
0
    def setUp(self):
        django.setup()

        workspace = storage_test_utils.create_workspace()
        source_file = source_test_utils.create_source(workspace=workspace)
        self.event = trigger_test_utils.create_trigger_event()

        interface_1 = {
            'version': '1.0',
            'command': 'test_command',
            'command_arguments': 'test_arg',
            'input_data': [{
                'name': 'Test Input 1',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'output_data': [{
                'name': 'Test Output 1',
                'type': 'files',
                'media_type': 'image/png',
            }]
        }
        self.job_type_1 = job_test_utils.create_job_type(interface=interface_1)

        interface_2 = {
            'version': '1.0',
            'command': 'test_command',
            'command_arguments': 'test_arg',
            'input_data': [{
                'name': 'Test Input 2',
                'type': 'files',
                'media_types': ['image/png', 'image/tiff'],
            }],
            'output_data': [{
                'name': 'Test Output 2',
                'type': 'file',
            }]
        }
        self.job_type_2 = job_test_utils.create_job_type(interface=interface_2)

        definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': 'Test Input 1',
                }]
            }, {
                'name': 'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name': 'Job 1',
                    'connections': [{
                        'output': 'Test Output 1',
                        'input': 'Test Input 2',
                    }]
                }]
            }]
        }

        recipe_definition = RecipeDefinition(definition)
        recipe_definition.validate_job_interfaces()

        self.recipe_type = recipe_test_utils.create_recipe_type(definition=definition)

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': source_file.id,
            }],
            'workspace_id': workspace.id,
        }
        self.data = RecipeData(data)

        # Register a fake processor
        self.mock_processor = MagicMock(QueueEventProcessor)
        Queue.objects.register_processor(lambda: self.mock_processor)
Ejemplo n.º 17
0
class TestRecipeTypeManagerEditRecipeType(TransactionTestCase):
    def setUp(self):
        django.setup()

        self.workspace = storage_test_utils.create_workspace()

        interface_1 = {
            'version':
            '1.0',
            'command':
            'my_command',
            'command_arguments':
            'args',
            'input_data': [{
                'name': 'Test Input 1',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'output_data': [{
                'name': 'Test Output 1',
                'type': 'files',
                'media_type': 'image/png',
            }]
        }
        self.job_type_1 = job_test_utils.create_job_type(interface=interface_1)

        interface_2 = {
            'version':
            '1.0',
            'command':
            'my_command',
            'command_arguments':
            'args',
            'input_data': [{
                'name': 'Test Input 2',
                'type': 'files',
                'media_types': ['image/png', 'image/tiff'],
            }],
            'output_data': [{
                'name': 'Test Output 2',
                'type': 'file',
            }]
        }
        self.job_type_2 = job_test_utils.create_job_type(interface=interface_2)

        self.definition = {
            'version':
            '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name':
                'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': 'Test Input 1',
                }]
            }, {
                'name':
                'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name':
                    'Job 1',
                    'connections': [{
                        'output': 'Test Output 1',
                        'input': 'Test Input 2',
                    }]
                }]
            }]
        }
        self.recipe_def = RecipeDefinition(self.definition)
        self.recipe_def.validate_job_interfaces()

        self.new_definition = {
            'version':
            '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name':
                'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': 'Test Input 1',
                }]
            }]
        }
        self.new_recipe_def = RecipeDefinition(self.new_definition)
        self.new_recipe_def.validate_job_interfaces()

        self.configuration = {
            'version': '1.0',
            'condition': {
                'media_type': 'text/plain'
            },
            'data': {
                'input_data_name': 'Recipe Input',
                'workspace_name': self.workspace.name
            }
        }
        self.trigger_config = recipe_test_utils.MockTriggerRuleConfiguration(
            recipe_test_utils.MOCK_TYPE, self.configuration)

        self.new_configuration = {
            'version': '1.0',
            'condition': {
                'media_type': 'application/json'
            },
            'data': {
                'input_data_name': 'Recipe Input',
                'workspace_name': self.workspace.name
            }
        }
        self.new_trigger_config = recipe_test_utils.MockTriggerRuleConfiguration(
            recipe_test_utils.MOCK_TYPE, self.new_configuration)

    def test_change_simple_no_trigger(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with only basic attributes and no previous trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        recipe_type = RecipeType.objects.create_recipe_type(
            name, version, title, desc, self.recipe_def, None)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(
                pk=recipe_type.id)
            # Edit the recipe
            new_title = 'New title'
            new_desc = 'New description'
            RecipeType.objects.edit_recipe_type(recipe_type.id, new_title,
                                                new_desc, None, None, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(
            pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, new_title)
        self.assertEqual(recipe_type.description, new_desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(),
                             self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertIsNone(recipe_type.trigger_rule)
        num_of_revs = RecipeTypeRevision.objects.filter(
            recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)

    def test_change_simple_with_trigger(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with only basic attributes and a previous trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_TYPE,
            configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(
            name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(
                pk=recipe_type.id)
            # Edit the recipe
            new_title = 'New title'
            new_desc = 'New description'
            RecipeType.objects.edit_recipe_type(recipe_type.id, new_title,
                                                new_desc, None, None, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(
            pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, new_title)
        self.assertEqual(recipe_type.description, new_desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(),
                             self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertEqual(recipe_type.trigger_rule_id, trigger_rule_id)
        num_of_revs = RecipeTypeRevision.objects.filter(
            recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)

    def test_change_to_definition(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with a change to the definition"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_TYPE,
            configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(
            name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(
                pk=recipe_type.id)
            # Edit the recipe
            RecipeType.objects.edit_recipe_type(recipe_type.id, None, None,
                                                self.new_recipe_def, None,
                                                False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(
            pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(),
                             self.new_recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 2)
        self.assertEqual(recipe_type.trigger_rule_id, trigger_rule_id)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertTrue(trigger_rule.is_active)
        # New revision due to definition change
        num_of_revs = RecipeTypeRevision.objects.filter(
            recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 2)

    def test_change_to_trigger_rule(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with a change to the trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_TYPE,
            configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        new_trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_TYPE,
            configuration=self.new_trigger_config.get_dict())
        new_trigger_rule_id = new_trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(
            name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(
                pk=recipe_type.id)
            # Edit the recipe
            RecipeType.objects.edit_recipe_type(recipe_type.id, None, None,
                                                None, new_trigger_rule, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(
            pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(),
                             self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertEqual(recipe_type.trigger_rule_id, new_trigger_rule_id)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertFalse(trigger_rule.is_active)
        new_trigger_rule = TriggerRule.objects.get(pk=new_trigger_rule_id)
        self.assertTrue(new_trigger_rule.is_active)
        num_of_revs = RecipeTypeRevision.objects.filter(
            recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)

    def test_remove_trigger_rule(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() that removes the trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_TYPE,
            configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(
            name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(
                pk=recipe_type.id)
            # Edit the recipe
            RecipeType.objects.edit_recipe_type(recipe_type.id, None, None,
                                                None, None, True)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(
            pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(),
                             self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertIsNone(recipe_type.trigger_rule)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertFalse(trigger_rule.is_active)
        num_of_revs = RecipeTypeRevision.objects.filter(
            recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)

    def test_change_to_both(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with a change to both the definition and the trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_TYPE,
            configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        new_trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_TYPE,
            configuration=self.new_trigger_config.get_dict())
        new_trigger_rule_id = new_trigger_rule.id
        recipe_type = RecipeType.objects.create_recipe_type(
            name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(
                pk=recipe_type.id)
            # Edit the recipe
            RecipeType.objects.edit_recipe_type(recipe_type.id, None, None,
                                                self.new_recipe_def,
                                                new_trigger_rule, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(
            pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(),
                             self.new_recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 2)
        self.assertEqual(recipe_type.trigger_rule_id, new_trigger_rule_id)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertFalse(trigger_rule.is_active)
        new_trigger_rule = TriggerRule.objects.get(pk=new_trigger_rule_id)
        self.assertTrue(new_trigger_rule.is_active)
        # New revision due to definition change
        num_of_revs = RecipeTypeRevision.objects.filter(
            recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 2)

    def test_invalid_trigger_rule(self):
        """Tests calling RecipeTypeManager.edit_recipe_type() with a new invalid trigger rule"""

        # Create recipe_type
        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_TYPE,
            configuration=self.trigger_config.get_dict())
        trigger_rule_id = trigger_rule.id
        new_trigger_rule = trigger_test_utils.create_trigger_rule(
            trigger_type=recipe_test_utils.MOCK_ERROR_TYPE,
            configuration=self.new_trigger_config.get_dict())
        recipe_type = RecipeType.objects.create_recipe_type(
            name, version, title, desc, self.recipe_def, trigger_rule)
        with transaction.atomic():
            recipe_type = RecipeType.objects.select_for_update().get(
                pk=recipe_type.id)
            # Edit the recipe
            self.assertRaises(InvalidRecipeConnection,
                              RecipeType.objects.edit_recipe_type,
                              recipe_type.id, None, None, self.new_recipe_def,
                              new_trigger_rule, False)
        recipe_type = RecipeType.objects.select_related('trigger_rule').get(
            pk=recipe_type.id)

        # Check results
        self.assertEqual(recipe_type.title, title)
        self.assertEqual(recipe_type.description, desc)
        self.assertDictEqual(recipe_type.get_recipe_definition().get_dict(),
                             self.recipe_def.get_dict())
        self.assertEqual(recipe_type.revision_num, 1)
        self.assertEqual(recipe_type.trigger_rule_id, trigger_rule_id)
        trigger_rule = TriggerRule.objects.get(pk=trigger_rule_id)
        self.assertTrue(trigger_rule.is_active)
        num_of_revs = RecipeTypeRevision.objects.filter(
            recipe_type_id=recipe_type.id).count()
        self.assertEqual(num_of_revs, 1)
Ejemplo n.º 18
0
class TestRecipeTypeManagerCreateRecipeType(TransactionTestCase):
    def setUp(self):
        django.setup()

        self.workspace = storage_test_utils.create_workspace()

        interface_1 = {
            'version':
            '1.0',
            'command':
            'my_command',
            'command_arguments':
            'args',
            'input_data': [{
                'name': 'Test Input 1',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'output_data': [{
                'name': 'Test Output 1',
                'type': 'files',
                'media_type': 'image/png',
            }]
        }
        self.job_type_1 = job_test_utils.create_job_type(interface=interface_1)

        interface_2 = {
            'version':
            '1.0',
            'command':
            'my_command',
            'command_arguments':
            'args',
            'input_data': [{
                'name': 'Test Input 2',
                'type': 'files',
                'media_types': ['image/png', 'image/tiff'],
            }],
            'output_data': [{
                'name': 'Test Output 2',
                'type': 'file',
            }]
        }
        self.job_type_2 = job_test_utils.create_job_type(interface=interface_2)

        self.definition = {
            'version':
            '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name':
                'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': 'Test Input 1',
                }]
            }, {
                'name':
                'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name':
                    'Job 1',
                    'connections': [{
                        'output': 'Test Output 1',
                        'input': 'Test Input 2',
                    }]
                }]
            }]
        }
        self.recipe_def = RecipeDefinition(self.definition)
        self.recipe_def.validate_job_interfaces()

    def test_successful(self):
        """Tests calling RecipeTypeManager.create_recipe_type() successfully."""

        name = 'test-recipe'
        version = '1.0'
        title = 'Test Recipe'
        desc = 'Test description'
        recipe_type = RecipeType.objects.create_recipe_type(
            name, version, title, desc, self.recipe_def, None)

        results_recipe_type = RecipeType.objects.get(pk=recipe_type.id)
        self.assertEqual(results_recipe_type.name, name)
        self.assertEqual(results_recipe_type.version, version)
        self.assertEqual(results_recipe_type.title, title)
        self.assertEqual(results_recipe_type.description, desc)
        self.assertDictEqual(results_recipe_type.definition, self.definition)

        results_recipe_type_rev = RecipeTypeRevision.objects.get(
            recipe_type_id=recipe_type.id, revision_num=1)
        self.assertDictEqual(results_recipe_type_rev.definition,
                             self.definition)
Ejemplo n.º 19
0
    def test_successful_job_1_completed(self, mock_store):
        '''Tests calling RecipeDefinition.get_next_jobs_to_queue() successfully when job 1 has been completed.'''

        definition = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name': 'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_1,
                }]
            }, {
                'name': 'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name': 'Job 1',
                    'connections': [{
                        'output': self.output_name_1,
                        'input': self.input_name_2,
                    }],
                }],
            }],
        }
        recipe_definition = RecipeDefinition(definition)
        recipe_definition.validate_job_interfaces()

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': self.file_1.id,
            }],
            'workspace_id': 1,
        }
        recipe_data = RecipeData(data)
        recipe_definition.validate_data(recipe_data)

        png_file_ids = [98, 99, 100]
        job_results = JobResults()
        job_results.add_file_list_parameter(self.output_name_1, png_file_ids)
        job_1 = Job.objects.select_related('job_type').get(pk=self.job_1.id)
        job_1.results = job_results.get_dict()
        job_1.save()
        job_2 = Job.objects.select_related('job_type').get(pk=self.job_2.id)

        results = recipe_definition.get_next_jobs_to_queue(recipe_data, {'Job 2': job_2}, {'Job 1': job_1})

        # Make sure only Job 2 is returned and that its job data is correct
        self.assertListEqual([self.job_2.id], results.keys())
        self.assertDictEqual(results[self.job_2.id].get_dict(), {
            'version': '1.0',
            'input_data': [{
                'name': self.input_name_2,
                'file_ids': png_file_ids,
            }],
            'output_data': [{
                'name': self.output_name_2,
                'workspace_id': 1,
            }],
        })
Ejemplo n.º 20
0
    def test_successful_job_1_completed(self, mock_store):
        '''Tests calling RecipeDefinition.get_next_jobs_to_queue() successfully when job 1 has been completed.'''

        definition = {
            'version':
            '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'type': 'file',
                'media_types': ['text/plain'],
            }],
            'jobs': [{
                'name':
                'Job 1',
                'job_type': {
                    'name': self.job_type_1.name,
                    'version': self.job_type_1.version,
                },
                'recipe_inputs': [{
                    'recipe_input': 'Recipe Input',
                    'job_input': self.input_name_1,
                }]
            }, {
                'name':
                'Job 2',
                'job_type': {
                    'name': self.job_type_2.name,
                    'version': self.job_type_2.version,
                },
                'dependencies': [{
                    'name':
                    'Job 1',
                    'connections': [{
                        'output': self.output_name_1,
                        'input': self.input_name_2,
                    }],
                }],
            }],
        }
        recipe_definition = RecipeDefinition(definition)
        recipe_definition.validate_job_interfaces()

        data = {
            'version': '1.0',
            'input_data': [{
                'name': 'Recipe Input',
                'file_id': self.file_1.id,
            }],
            'workspace_id': 1,
        }
        recipe_data = RecipeData(data)
        recipe_definition.validate_data(recipe_data)

        png_file_ids = [98, 99, 100]
        job_results = JobResults()
        job_results.add_file_list_parameter(self.output_name_1, png_file_ids)
        job_1 = Job.objects.select_related('job_type').get(pk=self.job_1.id)
        job_1.results = job_results.get_dict()
        job_1.save()
        job_2 = Job.objects.select_related('job_type').get(pk=self.job_2.id)

        results = recipe_definition.get_next_jobs_to_queue(
            recipe_data, {'Job 2': job_2}, {'Job 1': job_1})

        # Make sure only Job 2 is returned and that its job data is correct
        self.assertListEqual([self.job_2.id], results.keys())
        self.assertDictEqual(
            results[self.job_2.id].get_dict(), {
                'version':
                '1.0',
                'input_data': [{
                    'name': self.input_name_2,
                    'file_ids': png_file_ids,
                }],
                'output_data': [{
                    'name': self.output_name_2,
                    'workspace_id': 1,
                }],
            })