Beispiel #1
0
    def test_init_validation(self):
        """Tests the validation done in __init__"""

        # Try minimal acceptable configuration
        BatchDefinitionV6(do_validate=True)

        # Invalid version
        definition = {'version': 'BAD'}
        self.assertRaises(InvalidDefinition, BatchDefinitionV6, definition,
                          True)

        # Missing root_batch_id
        definition = {'version': '6', 'previous_batch': {'all_jobs': True}}
        self.assertRaises(InvalidDefinition, BatchDefinitionV6, definition,
                          True)

        # Valid previous batch definition
        definition = {
            'version': '6',
            'previous_batch': {
                'root_batch_id': 1234,
                'forced_nodes': {
                    'all': False,
                    'nodes': ['job_a', 'job_b']
                }
            }
        }
        BatchDefinitionV6(definition=definition, do_validate=True)
Beispiel #2
0
    def test_convert_definition_to_v6(self):
        """Tests calling convert_definition_to_v6()"""

        # Try definition with nothing set
        definition = BatchDefinition()
        json = convert_definition_to_v6(definition)
        BatchDefinitionV6(definition=json.get_dict(),
                          do_validate=True)  # Revalidate

        # Try definition with previous batch ID set
        definition = BatchDefinition()
        definition.root_batch_id = 1234
        json = convert_definition_to_v6(definition)
        BatchDefinitionV6(definition=json.get_dict(),
                          do_validate=True)  # Revalidate
        self.assertEqual(json.get_definition().root_batch_id,
                         definition.root_batch_id)
Beispiel #3
0
    def get_definition(self):
        """Returns the definition for this batch

        :returns: The definition for this batch
        :rtype: :class:`batch.definition.definition.BatchDefinition`
        """

        return BatchDefinitionV6(definition=self.definition, do_validate=False).get_definition()
Beispiel #4
0
    def _post_v6(self, request):
        """The v6 version for validating a new batch

        :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
        """

        recipe_type_id = rest_util.parse_int(request, 'recipe_type_id')
        definition_dict = rest_util.parse_dict(request, 'definition')
        configuration_dict = rest_util.parse_dict(request,
                                                  'configuration',
                                                  required=False)

        # Make sure the recipe type exists
        try:
            recipe_type = RecipeType.objects.get(pk=recipe_type_id)
        except RecipeType.DoesNotExist:
            raise BadParameter('Unknown recipe type: %d' % recipe_type_id)

        try:
            definition = BatchDefinitionV6(definition=definition_dict,
                                           do_validate=True).get_definition()
            configuration = BatchConfigurationV6(
                configuration=configuration_dict,
                do_validate=True).get_configuration()
        except InvalidDefinition as ex:
            raise BadParameter(unicode(ex))
        except InvalidConfiguration as ex:
            raise BadParameter(unicode(ex))

        # Validate the batch
        validation = Batch.objects.validate_batch_v6(
            recipe_type, definition, configuration=configuration)
        batch = validation.batch
        recipe_type_serializer = RecipeTypeBaseSerializerV6(batch.recipe_type)
        resp_dict = {
            'is_valid': validation.is_valid,
            'errors': [e.to_dict() for e in validation.errors],
            'warnings': [w.to_dict() for w in validation.warnings],
            'recipes_estimated': definition.estimated_recipes,
            'recipe_type': recipe_type_serializer.data
        }
        if batch.superseded_batch:
            recipe_type_rev_serializer = RecipeTypeRevisionBaseSerializerV6(
                batch.superseded_batch.recipe_type_rev)
            prev_batch_dict = {
                'recipe_type_rev': recipe_type_rev_serializer.data
            }
            resp_dict['prev_batch'] = prev_batch_dict
            if definition.prev_batch_diff:
                diff_v6 = convert_recipe_diff_to_v6_json(
                    definition.prev_batch_diff)
                diff_dict = rest_util.strip_schema_version(diff_v6.get_dict())
                prev_batch_dict['diff'] = diff_dict
        return Response(resp_dict)
Beispiel #5
0
    def _create_v6(self, request):
        """The v6 version for creating batches

        :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
        """

        title = rest_util.parse_string(request, 'title', required=False)
        description = rest_util.parse_string(request,
                                             'description',
                                             required=False)
        recipe_type_id = rest_util.parse_int(request, 'recipe_type_id')
        definition_dict = rest_util.parse_dict(request, 'definition')
        configuration_dict = rest_util.parse_dict(request,
                                                  'configuration',
                                                  required=False)

        # Make sure the recipe type exists
        try:
            recipe_type = RecipeType.objects.get(pk=recipe_type_id)
        except RecipeType.DoesNotExist:
            raise BadParameter('Unknown recipe type: %d' % recipe_type_id)

        # Validate and create the batch
        try:
            definition = BatchDefinitionV6(definition=definition_dict,
                                           do_validate=True).get_definition()
            configuration = BatchConfigurationV6(
                configuration=configuration_dict,
                do_validate=True).get_configuration()
            with transaction.atomic():
                event = TriggerEvent.objects.create_trigger_event(
                    'USER', None, {'user': '******'}, now())
                batch = Batch.objects.create_batch_v6(
                    title,
                    description,
                    recipe_type,
                    event,
                    definition,
                    configuration=configuration)
                CommandMessageManager().send_messages(
                    [create_batch_recipes_message(batch.id)])
        except InvalidDefinition as ex:
            raise BadParameter(unicode(ex))
        except InvalidConfiguration as ex:
            raise BadParameter(unicode(ex))

        # Fetch the full batch with details
        batch = Batch.objects.get_details_v6(batch.id)

        url = reverse('batch_details_view', args=[batch.id], request=request)
        serializer = BatchDetailsSerializerV6(batch)
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers={'Location': url})
Beispiel #6
0
    def test_create_from_json(self):
        """Tests creating a BatchDefinition from a JSON"""

        # Valid previous batch definition
        definition = {
            'version': '6',
            'previous_batch': {
                'root_batch_id': 1234,
                'job_names': ['job_a', 'job_b'],
                'all_jobs': True
            }
        }
        json = BatchDefinitionV6(definition=definition, do_validate=True)
        self.assertIsNotNone(json.get_definition())
Beispiel #7
0
def create_batch(title=None, description=None, recipe_type=None, definition=None, configuration=None,
                 is_creation_done=False, recipes_total=None):
    """Creates a batch model for unit testing

    :returns: The batch model
    :rtype: :class:`batch.models.Batch`
    """

    if not recipe_type:
        recipe_type = recipe_test_utils.create_recipe_type_v6()
    if not definition:
        definition = BatchDefinition()
        # Create a previous batch so we can create a valid definition
        # TODO: this can be replaced by a DataSet once they are implemented
        prev_batch = Batch()
        prev_batch.recipe_type = recipe_type
        prev_batch.recipe_type_rev = RecipeTypeRevision.objects.get_revision(recipe_type.name, recipe_type.revision_num)
        prev_batch.event = TriggerEvent.objects.create_trigger_event('USER', None, {'user': '******'}, now())
        prev_batch.is_creation_done = True
        prev_batch.recipes_total = 10
        prev_batch.save()
        prev_batch.root_batch_id = prev_batch.id
        prev_batch.save()
        definition.root_batch_id = prev_batch.root_batch_id
    if not isinstance(definition, BatchDefinition):
        definition = BatchDefinitionV6(definition).get_definition()
    if not configuration:
        configuration = BatchConfiguration()
    if not title:
        global BATCH_TITLE_COUNTER
        title = 'Test Batch Title %i' % BATCH_TITLE_COUNTER
        BATCH_TITLE_COUNTER += 1
    if not description:
        global BATCH_DESCRIPTION_COUNTER
        description = 'Test Batch Description %i' % BATCH_DESCRIPTION_COUNTER
        BATCH_DESCRIPTION_COUNTER += 1
    event = TriggerEvent.objects.create_trigger_event('USER', None, {'user': '******'}, now())

    batch = Batch.objects.create_batch_v6(title, description, recipe_type, event, definition, configuration)
    if is_creation_done:
        batch.is_creation_done = True
    if recipes_total is not None:
        batch.recipes_total = recipes_total
    batch.save()
    return batch
Beispiel #8
0
    def test_validate(self):
        """Tests calling BatchDefinition.validate()"""

        recipe_type_1 = recipe_test_utils.create_recipe_type()
        recipe_type_2 = recipe_test_utils.create_recipe_type()

        bad_recipe_type_prev_batch = batch_test_utils.create_batch(
            recipe_type=recipe_type_1)
        still_creating_prev_batch = batch_test_utils.create_batch(
            recipe_type=recipe_type_2)
        prev_batch = batch_test_utils.create_batch(recipe_type=recipe_type_2,
                                                   is_creation_done=True,
                                                   recipes_total=10)
        batch = batch_test_utils.create_batch(recipe_type=recipe_type_2)

        # No recipes would be created
        json_dict = {'version': '6'}
        json = BatchDefinitionV6(definition=json_dict)
        definition = json.get_definition()
        batch.superseded_batch = None
        self.assertRaises(InvalidDefinition, definition.validate, batch)

        # Mismatched recipe types
        json_dict = {
            'version': '6',
            'previous_batch': {
                'root_batch_id': bad_recipe_type_prev_batch.root_batch_id
            }
        }
        json = BatchDefinitionV6(definition=json_dict)
        definition = json.get_definition()
        batch.superseded_batch = bad_recipe_type_prev_batch
        self.assertRaises(InvalidDefinition, definition.validate, batch)

        # Previous batch not done creating recipes
        json_dict = {
            'version': '6',
            'previous_batch': {
                'root_batch_id': still_creating_prev_batch.root_batch_id
            }
        }
        json = BatchDefinitionV6(definition=json_dict)
        definition = json.get_definition()
        batch.superseded_batch = still_creating_prev_batch
        self.assertRaises(InvalidDefinition, definition.validate, batch)

        # Previous batch cannot be reprocessed
        json_dict = {
            'version': '6',
            'previous_batch': {
                'root_batch_id': prev_batch.root_batch_id
            }
        }
        json = BatchDefinitionV6(definition=json_dict)
        definition = json.get_definition()
        batch.superseded_batch = prev_batch

        with patch('batch.definition.definition.RecipeDiff') as mock_delta:
            instance = mock_delta.return_value
            instance.can_be_reprocessed = False
            self.assertRaises(InvalidDefinition, definition.validate, batch)

        # Valid definition with previous batch
        json_dict = {
            'version': '6',
            'previous_batch': {
                'root_batch_id': prev_batch.root_batch_id
            }
        }
        json = BatchDefinitionV6(definition=json_dict)
        definition = json.get_definition()
        batch.superseded_batch = prev_batch
        definition.validate(batch)