Example #1
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)
Example #2
0
    def get_v6_definition_json(self):
        """Returns the batch definition in v6 of the JSON schema

        :returns: The batch definition in v6 of the JSON schema
        :rtype: dict
        """

        # Handle batches with old (pre-v6) definitions
        if 'version' in self.definition and self.definition['version'] == '1.0':
            return {}

        return rest_utils.strip_schema_version(convert_definition_to_v6(self.get_definition()).get_dict())
Example #3
0
    def validate_batch_v6(self, recipe_type, definition, configuration=None):
        """Validates the given recipe type, definition, and configuration for creating a new batch

        :param recipe_type: The type of recipes that will be created for this batch
        :type recipe_type: :class:`recipe.models.RecipeType`
        :param definition: The definition for running the batch
        :type definition: :class:`batch.definition.definition.BatchDefinition`
        :param configuration: The batch configuration
        :type configuration: :class:`batch.configuration.configuration.BatchConfiguration`
        :returns: The batch validation
        :rtype: :class:`batch.models.BatchValidation`
        """

        is_valid = True
        errors = []
        warnings = []

        try:
            batch = Batch()
            batch.recipe_type = recipe_type
            batch.recipe_type_rev = RecipeTypeRevision.objects.get_revision(
                recipe_type.name, recipe_type.revision_num)
            batch.definition = convert_definition_to_v6(definition).get_dict()
            batch.configuration = convert_configuration_to_v6(
                configuration).get_dict()

            if definition.root_batch_id is not None:
                # Find latest batch with the root ID
                try:
                    superseded_batch = Batch.objects.get_batch_from_root(
                        definition.root_batch_id)
                except Batch.DoesNotExist:
                    raise InvalidDefinition(
                        'PREV_BATCH_NOT_FOUND',
                        'No batch with that root ID exists')
                batch.root_batch_id = superseded_batch.root_batch_id
                batch.superseded_batch = superseded_batch

            warnings.extend(definition.validate(batch))
            warnings.extend(configuration.validate(batch))
        except ValidationException as ex:
            is_valid = False
            errors.append(ex.error)

        batch.recipes_estimated = definition.estimated_recipes
        return BatchValidation(is_valid, errors, warnings, batch)
Example #4
0
    def create_batch_v6(self,
                        title,
                        description,
                        recipe_type,
                        event,
                        definition,
                        configuration=None):
        """Creates a new batch that will contain a collection of recipes to process. The definition and configuration
        will be stored in version 6 of their respective schemas. This method will only create the batch, not its
        recipes. To create the batch's recipes, a CreateBatchRecipes message needs to be sent to the messaging backend.

        :param title: The human-readable name of the batch
        :type title: string
        :param description: A human-readable description of the batch
        :type description: string
        :param recipe_type: The type of recipes that will be created for this batch
        :type recipe_type: :class:`recipe.models.RecipeType`
        :param event: The event that created this batch
        :type event: :class:`trigger.models.TriggerEvent`
        :param definition: The definition for running the batch
        :type definition: :class:`batch.definition.definition.BatchDefinition`
        :param configuration: The batch configuration
        :type configuration: :class:`batch.configuration.configuration.BatchConfiguration`
        :returns: The newly created batch
        :rtype: :class:`batch.models.Batch`

        :raises :class:`batch.configuration.exceptions.InvalidConfiguration`: If the configuration is invalid
        :raises :class:`batch.definition.exceptions.InvalidDefinition`: If the definition is invalid
        """

        batch = Batch()
        batch.title = title
        batch.description = description
        batch.recipe_type = recipe_type
        batch.recipe_type_rev = RecipeTypeRevision.objects.get_revision(
            recipe_type.name, recipe_type.revision_num)
        batch.event = event
        batch.definition = convert_definition_to_v6(definition).get_dict()
        batch.configuration = convert_configuration_to_v6(
            configuration).get_dict()

        with transaction.atomic():
            if definition.root_batch_id is not None:
                # Find latest batch with the root ID and supersede it
                try:
                    superseded_batch = Batch.objects.get_locked_batch_from_root(
                        definition.root_batch_id)
                except Batch.DoesNotExist:
                    raise InvalidDefinition(
                        'PREV_BATCH_NOT_FOUND',
                        'No batch with that root ID exists')
                batch.root_batch_id = superseded_batch.root_batch_id
                batch.superseded_batch = superseded_batch
                self.supersede_batch(superseded_batch.id, now())

            definition.validate(batch)
            configuration.validate(batch)

            batch.recipes_estimated = definition.estimated_recipes
            batch.save()
            if batch.root_batch_id is None:  # Batches with no superseded batch are their own root
                batch.root_batch_id = batch.id
                Batch.objects.filter(id=batch.id).update(
                    root_batch_id=batch.id)

            # Create models for batch metrics
            batch_metrics_models = []
            for job_name in recipe_type.get_definition().get_topological_order(
            ):
                batch_metrics_model = BatchMetrics()
                batch_metrics_model.batch_id = batch.id
                batch_metrics_model.job_name = job_name
                batch_metrics_models.append(batch_metrics_model)
            BatchMetrics.objects.bulk_create(batch_metrics_models)

        return batch