Пример #1
0
    def create(self, request):
        """Creates a new Workspace and returns it in JSON form

        :param request: the HTTP POST request
        :type request: :class:`rest_framework.request.Request`
        :rtype: :class:`rest_framework.response.Response`
        :returns: the HTTP response to send back to the user
        """

        name = rest_util.parse_string(request, 'name')
        title = rest_util.parse_string(request, 'title', required=False)
        description = rest_util.parse_string(request, 'description', required=False)
        json_config = rest_util.parse_dict(request, 'json_config')
        base_url = rest_util.parse_string(request, 'base_url', required=False)
        is_active = rest_util.parse_bool(request, 'is_active', default_value=True, required=False)

        try:
            workspace = Workspace.objects.create_workspace(name, title, description, json_config, base_url, is_active)
        except InvalidWorkspaceConfiguration as ex:
            logger.exception('Unable to create new workspace: %s', name)
            raise BadParameter(unicode(ex))

        # Fetch the full workspace with details
        try:
            workspace = Workspace.objects.get_details(workspace.id)
        except Workspace.DoesNotExist:
            raise Http404

        serializer = WorkspaceDetailsSerializer(workspace)
        workspace_url = urlresolvers.reverse('workspace_details_view', args=[workspace.id])
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=workspace_url))
Пример #2
0
    def create(self, request):
        """Creates a new Strike process and returns a link to the detail URL

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

        name = rest_util.parse_string(request, 'name')
        title = rest_util.parse_string(request, 'title', required=False)
        description = rest_util.parse_string(request, 'description', required=False)
        configuration = rest_util.parse_dict(request, 'configuration')

        try:
            strike = Strike.objects.create_strike(name, title, description, configuration)
        except InvalidStrikeConfiguration as ex:
            raise BadParameter('Strike configuration invalid: %s' % unicode(ex))

        # Fetch the full strike process with details
        try:
            strike = Strike.objects.get_details(strike.id)
        except Strike.DoesNotExist:
            raise Http404

        serializer = StrikeDetailsSerializer(strike)
        strike_url = reverse('strike_details_view', args=[strike.id], request=request)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=strike_url))
Пример #3
0
    def post(self, request):
        """Validates a new Strike process and returns any warnings discovered

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

        name = rest_util.parse_string(request, 'name')
        configuration = rest_util.parse_dict(request, 'configuration')

        rest_util.parse_string(request, 'title', required=False)
        rest_util.parse_string(request, 'description', required=False)

        # Validate the Strike configuration
        try:
            config = StrikeConfiguration(configuration)
            warnings = config.validate()
        except InvalidStrikeConfiguration as ex:
            logger.exception('Unable to validate new Strike process: %s', name)
            raise BadParameter(unicode(ex))

        results = [{'id': w.key, 'details': w.details} for w in warnings]
        return Response({'warnings': results})
Пример #4
0
    def patch(self, request, scan_id):
        """Edits an existing Scan process and returns the updated details

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param scan_id: The ID of the Scan process
        :type scan_id: int encoded as a str
        :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)
        configuration = rest_util.parse_dict(request, 'configuration', required=False)

        try:
            Scan.objects.edit_scan(scan_id, title, description, configuration)

            scan = Scan.objects.get_details(scan_id)
        except Scan.DoesNotExist:
            raise Http404
        except InvalidScanConfiguration as ex:
            logger.exception('Unable to edit Scan process: %s', scan_id)
            raise BadParameter(unicode(ex))

        serializer = self.get_serializer(scan)
        return Response(serializer.data)
Пример #5
0
    def create(self, request):
        """Creates a new Scan process and returns a link to the detail URL

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

        name = rest_util.parse_string(request, 'name')
        title = rest_util.parse_string(request, 'title', required=False)
        description = rest_util.parse_string(request,
                                             'description',
                                             required=False)
        configuration = rest_util.parse_dict(request, 'configuration')

        try:
            scan = Scan.objects.create_scan(name, title, description,
                                            configuration)
        except InvalidScanConfiguration as ex:
            raise BadParameter('Scan configuration invalid: %s' % unicode(ex))

        serializer = ScanDetailsSerializer(scan)
        scan_url = reverse('scans_details_view',
                           args=[scan.id],
                           request=request)
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=dict(location=scan_url))
Пример #6
0
    def patch_impl_v6(self, request, strike_id):
        """Edits an existing Strike process and returns the updated details

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param strike_id: The ID of the Strike process
        :type strike_id: int encoded as a str
        :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)
        configuration = rest_util.parse_dict(request,
                                             'configuration',
                                             required=False)

        try:
            Strike.objects.edit_strike_v6(strike_id, title, description,
                                          configuration)
        except Strike.DoesNotExist:
            raise Http404
        except InvalidStrikeConfiguration as ex:
            logger.exception('Unable to edit Strike process: %s', strike_id)
            raise BadParameter(unicode(ex))

        return Response(status=status.HTTP_204_NO_CONTENT)
Пример #7
0
    def post(self, request):
        """Validates a new workspace and returns any warnings discovered

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

        name = rest_util.parse_string(request, 'name')
        json_config = rest_util.parse_dict(request, 'json_config')

        rest_util.parse_string(request, 'title', required=False)
        rest_util.parse_string(request, 'description', required=False)
        rest_util.parse_string(request, 'base_url', required=False)
        rest_util.parse_string(request, 'is_active', required=False)

        # Validate the workspace configuration
        try:
            warnings = Workspace.objects.validate_workspace(name, json_config)
        except InvalidWorkspaceConfiguration as ex:
            logger.exception('Unable to validate new workspace: %s', name)
            raise BadParameter(unicode(ex))

        results = [{'id': w.key, 'details': w.details} for w in warnings]
        return Response({'warnings': results})
Пример #8
0
    def patch(self, request, workspace_id):
        """Edits an existing workspace and returns the updated details

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param workspace_id: The ID for the workspace.
        :type workspace_id: int encoded as a str
        :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)
        json_config = rest_util.parse_dict(request, 'json_config', required=False)
        base_url = rest_util.parse_string(request, 'base_url', required=False)
        is_active = rest_util.parse_string(request, 'is_active', required=False)

        try:
            Workspace.objects.edit_workspace(workspace_id, title, description, json_config, base_url, is_active)

            workspace = Workspace.objects.get_details(workspace_id)
        except Workspace.DoesNotExist:
            raise Http404
        except InvalidWorkspaceConfiguration as ex:
            logger.exception('Unable to edit workspace: %s', workspace_id)
            raise BadParameter(unicode(ex))

        serializer = self.get_serializer(workspace)
        return Response(serializer.data)
Пример #9
0
    def post(self, request, recipe_id):
        """Schedules a recipe for reprocessing and returns it in JSON form

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param recipe_id: The id of the recipe
        :type recipe_id: int encoded as a str
        :rtype: :class:`rest_framework.response.Response`
        :returns: the HTTP response to send back to the user
        """

        job_names = rest_util.parse_string_list(request, 'job_names', required=False)
        all_jobs = rest_util.parse_bool(request, 'all_jobs', required=False)

        try:
            handler = Recipe.objects.reprocess_recipe(recipe_id, job_names, all_jobs)
        except Recipe.DoesNotExist:
            raise Http404
        except ReprocessError as err:
            raise BadParameter(unicode(err))

        try:
            new_recipe = Recipe.objects.get_details(handler.recipe.id)
        except Recipe.DoesNotExist:
            raise Http404

        url = urlresolvers.reverse('recipe_details_view', args=[new_recipe.id])
        serializer = self.get_serializer(new_recipe)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=url))
Пример #10
0
    def post(self, request):
        """Creates a new error and returns a link to the info URL

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

        name = rest_util.parse_string(request, 'name')
        title = rest_util.parse_string(request, 'title')
        description = rest_util.parse_string(request, 'description')
        category = rest_util.parse_string(
            request,
            'category',
            accepted_values=[c for c, _ in Error.CATEGORIES])

        # Do not allow the creation of SYSTEM level errors
        if category == 'SYSTEM':
            raise BadParameter('System level errors cannot be created.')

        error = Error.objects.create_error(name, title, description, category)

        serializer = ErrorDetailsSerializer(error)
        error_url = urlresolvers.reverse('error_details_view', args=[error.id])
        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=dict(location=error_url))
Пример #11
0
    def patch_impl_v6(self, request, strike_id):
        """Edits an existing Strike process and returns the updated details

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param strike_id: The ID of the Strike process
        :type strike_id: int encoded as a str
        :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)
        configuration = rest_util.parse_dict(request, 'configuration', required=False)

        config = None
        try:
            if configuration:
                config = StrikeConfigurationV6(configuration, do_validate=True).get_configuration()
        except InvalidStrikeConfiguration as ex:
            raise BadParameter('Strike configuration invalid: %s' % unicode(ex))

        try:
            # must collect old config before editing strike
            if config:
                new_config = config.get_dict()
                old_config = Strike.objects.get_details(strike_id)

            Strike.objects.edit_strike(strike_id, title, description, config)

            # if workspace has changed strike job must be restarted for changes to take effect
            if config and old_config.configuration["workspace"] != new_config["workspace"]:
                strike_job = old_config.job
                Job.objects.update_jobs_to_canceled([strike_job], timezone.now())

                requeue_jobs = []
                requeue_jobs.append(QueuedJob(strike_job.id, strike_job.num_exes))
                msg = create_requeue_jobs_messages(requeue_jobs)
                CommandMessageManager().send_messages(msg)
            
        except Strike.DoesNotExist:
            raise Http404
        except InvalidStrikeConfiguration as ex:
            logger.exception('Unable to edit Strike process: %s', strike_id)
            raise BadParameter(unicode(ex))

        return Response(status=status.HTTP_204_NO_CONTENT)
Пример #12
0
    def patch_v6(self, request, name):
        """Edits an existing recipe type and returns the updated details

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param name: The name of the recipe type
        :type name: string
        :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)
        definition_dict = rest_util.parse_dict(request,
                                               'definition',
                                               required=False)
        auto_update = rest_util.parse_bool(request,
                                           'auto_update',
                                           required=False,
                                           default_value=True)
        is_active = rest_util.parse_bool(request, 'is_active', required=False)

        # Fetch the current recipe type model
        try:
            recipe_type = RecipeType.objects.filter(name=name).first()
        except RecipeType.DoesNotExist:
            raise Http404

        try:
            with transaction.atomic():
                # Validate the recipe definition
                recipe_def = None
                if definition_dict:
                    recipe_def = RecipeDefinitionV6(
                        definition=definition_dict,
                        do_validate=True).get_definition()

                # Edit the recipe type
                validation = RecipeType.objects.edit_recipe_type_v6(
                    recipe_type_id=recipe_type.id,
                    title=title,
                    description=description,
                    definition=recipe_def,
                    auto_update=auto_update,
                    is_active=is_active)
        except InvalidDefinition as ex:
            logger.exception('Unable to update recipe type: %s', name)
            raise BadParameter(unicode(ex))

        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],
            'diff': validation.diff
        }
        return Response(resp_dict)
Пример #13
0
    def create_v6(self, request):
        """Creates or edits a dataset and returns a link to the detail URL

        :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)
        definition = rest_util.parse_dict(request, 'definition', required=True)

        # validate the definition
        try:
            dataset_def = DataSetDefinitionV6(
                definition=definition, do_validate=True).get_definition()
        except InvalidDataSetDefinition as ex:
            message = 'DataSet definition is invalid'
            logger.exception(message)
            raise BadParameter('%s: %s' % (message, unicode(ex)))

        try:
            dataset = DataSet.objects.create_dataset_v6(
                dataset_def, title=title, description=description)
        except Exception as ex:
            message = 'Unable to create new dataset'
            logger.exception(message)
            raise BadParameter('%s: %s' % (message, unicode(ex)))

        try:
            dataset = DataSet.objects.get_details_v6(dataset.id)
        except DataSet.DoesNotExist:
            raise Http404

        url = reverse('dataset_details_view',
                      args=[dataset.id],
                      request=request)
        serializer = DataSetDetailsSerializerV6(dataset)

        return Response(serializer.data,
                        status=status.HTTP_201_CREATED,
                        headers=dict(location=url))
Пример #14
0
    def _create_v6(self, request):
        """Creates a new recipe type and returns a link to the detail URL

        :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=True)
        description = rest_util.parse_string(request, 'description', required=False)
        definition_dict = rest_util.parse_dict(request, 'definition', required=True)

        basename = title_to_basename(title)
        if basename == 'validation':
            logger.exception('Unable to create recipe type named "validation"')
            raise BadParameter(unicode('Unable to create recipe type named "validation"'))
            
        existing_recipes = RecipeType.objects.filter(name=basename)
        if existing_recipes.count() > 0:
            logger.exception('Existing recipe types found for %s - will not re-create.', basename)
            raise BadParameter(unicode('Existing recipe types found for %s - will not re-create. Please change the title or patch the existing recipe type.' % basename))
            
        name = title_to_name(self.queryset, title)
        try:
            with transaction.atomic():
                # Validate the recipe definition
                recipe_def = RecipeDefinitionV6(definition=definition_dict, do_validate=True).get_definition()
                
                # Create the recipe type
                recipe_type = RecipeType.objects.create_recipe_type_v6(name, title, description, recipe_def)
        except InvalidDefinition as ex:
            logger.exception('Unable to create new recipe type: %s', name)
            raise BadParameter(unicode(ex))

        # Fetch the full recipe type with details
        try:
            recipe_type = RecipeType.objects.get_details_v6(recipe_type.name)
        except RecipeType.DoesNotExist:
            raise Http404

        url = reverse('recipe_type_details_view', args=[recipe_type.name], request=request)
        serializer = RecipeTypeDetailsSerializerV6(recipe_type)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=url))
Пример #15
0
    def _post_v6(self, request):
        """Queue a recipe and returns the new job information in JSON form

        :param request: the HTTP POST request
        :type request: :class:`rest_framework.request.Request`
        :rtype: :class:`rest_framework.response.Response`
        :returns: the HTTP response to send back to the user
        """

        recipe_type_id = rest_util.parse_int(request, 'recipe_type_id')
        recipe_data = rest_util.parse_dict(request, 'input', {})
        configuration_dict = rest_util.parse_dict(request, 'configuration', required=False)
        configuration = None

        try:
            recipeData = DataV6(recipe_data, do_validate=True)
        except InvalidData as ex:
            logger.exception('Unable to queue new recipe. Invalid input: %s', recipe_data)
            raise BadParameter(unicode(ex))

        try:
            recipe_type = RecipeType.objects.get(pk=recipe_type_id)
        except RecipeType.DoesNotExist:
            raise Http404

        if configuration_dict:
            try:
                configuration = RecipeConfigurationV6(configuration_dict, do_validate=True).get_configuration()
            except InvalidRecipeConfiguration as ex:
                message = 'Recipe configuration invalid'
                logger.exception(message)
                raise BadParameter('%s: %s' % (message, unicode(ex)))

        try:
            recipe = Queue.objects.queue_new_recipe_for_user_v6(recipe_type, recipeData.get_data(),
                                                                recipe_config=configuration)
        except (InvalidData, InvalidRecipeData) as err:
            return Response('Invalid recipe data: ' + unicode(err), status=status.HTTP_400_BAD_REQUEST)
        except InactiveRecipeType as err:
            return Response('Inactive recipe type: ' + unicode(err), status=status.HTTP_400_BAD_REQUEST)

        serializer = RecipeSerializerV6(recipe)
        recipe_url = reverse('recipe_details_view', args=[recipe.id], request=request)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=recipe_url))
Пример #16
0
    def post(self, request):
        """Submit command message to re-queue jobs that fit the given filter criteria

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :returns: the HTTP response to send back to the user
        """

        started = rest_util.parse_timestamp(request, 'started', required=False)
        ended = rest_util.parse_timestamp(request, 'ended', required=False)
        rest_util.check_time_range(started, ended)

        error_categories = rest_util.parse_string_list(request, 'error_categories', required=False)
        error_ids = rest_util.parse_int_list(request, 'error_ids', required=False)
        job_ids = rest_util.parse_int_list(request, 'job_ids', required=False)
        job_status = rest_util.parse_string(request, 'status', required=False)
        job_type_ids = rest_util.parse_int_list(request, 'job_type_ids', required=False)
        priority = rest_util.parse_int(request, 'priority', required=False)

        job_type_names = rest_util.parse_string_list(request, 'job_type_names', required=False)
        batch_ids = rest_util.parse_int_list(request, 'batch_ids', required=False)
        recipe_ids = rest_util.parse_int_list(request, 'recipe_ids', required=False)
        is_superseded = rest_util.parse_bool(request, 'is_superseded', required=False)

        job_types = rest_util.parse_dict_list(request, 'job_types', required=False)

        for jt in job_types:
            if 'name' not in jt or 'version' not in jt:
                raise BadParameter('Job types argument invalid: %s' % job_types)
            existing_job_type = JobType.objects.filter(name=jt['name'], version=jt['version']).first()
            if not existing_job_type:
                raise BadParameter(
                    'Job Type with name: %s and version: %s does not exist' % (jt['name'], jt['version']))
            job_type_ids.append(existing_job_type.id)

        # Create and send message
        msg = create_requeue_jobs_bulk_message(started=started, ended=ended, error_categories=error_categories,
                                               error_ids=error_ids, job_ids=job_ids, job_type_ids=job_type_ids,
                                               priority=priority, status=job_status, job_type_names=job_type_names,
                                               batch_ids=batch_ids, recipe_ids=recipe_ids, is_superseded=is_superseded)
        CommandMessageManager().send_messages([msg])

        return Response(status=status.HTTP_202_ACCEPTED)
Пример #17
0
    def _patch_v6(self, request, workspace_id):
        """Edits an existing workspace and returns the updated details

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param workspace_id: The ID for the workspace.
        :type workspace_id: int encoded as a str
        :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)
        json = rest_util.parse_dict(request, 'configuration', required=False)
        base_url = rest_util.parse_string(request, 'base_url', required=False)
        is_active = rest_util.parse_string(request,
                                           'is_active',
                                           required=False)

        configuration = None
        if json:
            try:
                configuration = WorkspaceConfigurationV6(
                    json, do_validate=True).get_configuration()
            except InvalidWorkspaceConfiguration as ex:
                message = 'Workspace configuration invalid'
                logger.exception(message)
                raise BadParameter('%s: %s' % (message, unicode(ex)))

        try:
            Workspace.objects.edit_workspace(workspace_id, title, description,
                                             configuration, base_url,
                                             is_active)
        except Workspace.DoesNotExist:
            raise Http404
        except InvalidWorkspaceConfiguration as ex:
            logger.exception('Unable to edit workspace: %s', workspace_id)
            raise BadParameter(unicode(ex))

        return HttpResponse(status=204)
Пример #18
0
    def create(self, request):
        """Creates a new batch and returns a link to the detail URL

        :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')
        title = rest_util.parse_string(request, 'title', required=False)
        description = rest_util.parse_string(request, 'description', 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: %i' % recipe_type_id)

        # Validate the batch definition
        definition_dict = rest_util.parse_dict(request, 'definition')
        definition = None
        try:
            if definition_dict:
                definition = BatchDefinition(definition_dict)
                definition.validate(recipe_type)
        except InvalidDefinition as ex:
            raise BadParameter('Batch definition invalid: %s' % unicode(ex))

        # Create the batch
        batch = Batch.objects.create_batch(recipe_type, definition, title=title, description=description)

        # Fetch the full batch with details
        try:
            batch = Batch.objects.get_details(batch.id)
        except Batch.DoesNotExist:
            raise Http404

        url = reverse('batch_details_view', args=[batch.id], request=request)
        serializer = BatchDetailsSerializer(batch)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=url))
Пример #19
0
    def _patch_v5(self, request, error_id):
        """Edits an existing error and returns the updated model

        :param request: the HTTP PATCH request
        :type request: :class:`rest_framework.request.Request`
        :param error_id: The id of the error
        :type error_id: int encoded as a str
        :rtype: :class:`rest_framework.response.Response`
        :returns: the HTTP response to send back to the user
        """
        try:
            error = Error.objects.get(pk=error_id)
        except Error.DoesNotExist:
            raise Http404

        # Do not allow editing of SYSTEM level errors
        if error.category == 'SYSTEM':
            raise BadParameter('System level errors cannot be edited.')

        title = rest_util.parse_string(request, 'title', required=False)
        description = rest_util.parse_string(request,
                                             'description',
                                             required=False)
        category = rest_util.parse_string(
            request,
            'category',
            required=False,
            accepted_values=[c for c, _ in Error.CATEGORIES])

        # Do not allow editing of SYSTEM level errors
        if category == 'SYSTEM':
            raise BadParameter('Errors cannot be changed to system level.')

        error.title = title or error.title
        error.description = description or error.description
        error.category = category or error.category
        error.save()

        serializer = self.get_serializer(error)
        return Response(serializer.data)
Пример #20
0
    def patch_impl(self, request, strike_id):
        """Edits an existing Strike process and returns the updated details

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param strike_id: The ID of the Strike process
        :type strike_id: int encoded as a str
        :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)
        configuration = rest_util.parse_dict(request,
                                             'configuration',
                                             required=False)

        config = None
        try:
            if configuration:
                config = StrikeConfigurationV2(
                    configuration, do_validate=True).get_configuration()
        except InvalidStrikeConfiguration as ex:
            raise BadParameter('Strike configuration invalid: %s' %
                               unicode(ex))

        try:
            Strike.objects.edit_strike(strike_id, title, description, config)

            strike = Strike.objects.get_details(strike_id)
        except Strike.DoesNotExist:
            raise Http404
        except InvalidStrikeConfiguration as ex:
            logger.exception('Unable to edit Strike process: %s', strike_id)
            raise BadParameter(unicode(ex))

        serializer = self.get_serializer(strike)
        return Response(serializer.data)
Пример #21
0
    def _create_v6(self, request):
        """Creates a new Workspace and returns it in JSON form

        :param request: the HTTP POST request
        :type request: :class:`rest_framework.request.Request`
        :rtype: :class:`rest_framework.response.Response`
        :returns: the HTTP response to send back to the user
        """

        title = rest_util.parse_string(request, 'title', required=True)
        name = title_to_name(self.queryset, title)
        description = rest_util.parse_string(request, 'description', required=False)
        json = rest_util.parse_dict(request, 'configuration')
        base_url = rest_util.parse_string(request, 'base_url', required=False)
        is_active = rest_util.parse_bool(request, 'is_active', default_value=True, required=False)

        configuration = None
        if json:
            try:
                configuration = WorkspaceConfigurationV6(json, do_validate=True).get_configuration()
            except InvalidWorkspaceConfiguration as ex:
                message = 'Workspace configuration invalid'
                logger.exception(message)
                raise BadParameter('%s: %s' % (message, unicode(ex)))

        try:
            workspace = Workspace.objects.create_workspace(name, title, description, configuration, base_url, is_active)
        except InvalidWorkspaceConfiguration as ex:
            logger.exception('Unable to create new workspace: %s', name)
            raise BadParameter(unicode(ex))

        # Fetch the full workspace with details
        try:
            workspace = Workspace.objects.get_details(workspace.id)
        except Workspace.DoesNotExist:
            raise Http404

        serializer = WorkspaceDetailsSerializerV6(workspace)
        workspace_url = reverse('workspace_details_view', args=[workspace.id], request=request)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=workspace_url))
Пример #22
0
    def _post_v5(self, request):
        """The v5 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')

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

        # Validate the batch definition
        definition_dict = rest_util.parse_dict(request, 'definition')
        definition = None
        warnings = []
        try:
            if definition_dict:
                definition = OldBatchDefinition(definition_dict)
                warnings = definition.validate(recipe_type)
        except InvalidDefinition as ex:
            raise BadParameter('Batch definition invalid: %s' % unicode(ex))

        # Get a rough estimate of how many recipes/files will be affected
        old_recipes = Batch.objects.get_matched_recipes(
            recipe_type, definition)
        old_files = Batch.objects.get_matched_files(recipe_type, definition)

        return Response({
            'recipe_count': old_recipes.count(),
            'file_count': old_files.count(),
            'warnings': warnings,
        })
Пример #23
0
    def _patch_v6(self, request, scan_id):
        """Edits an existing Scan process and returns the updated details

        :param request: the HTTP GET request
        :type request: :class:`rest_framework.request.Request`
        :param scan_id: The ID of the Scan process
        :type scan_id: int encoded as a str
        :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)
        configuration = rest_util.parse_dict(request,
                                             'configuration',
                                             required=False)

        config = None
        try:
            if configuration:
                config = ScanConfigurationV6(
                    configuration, do_validate=True).get_configuration()
        except InvalidScanConfiguration as ex:
            raise BadParameter('Scan configuration invalid: %s' % unicode(ex))

        try:
            Scan.objects.edit_scan(scan_id, title, description, config)
        except Scan.DoesNotExist:
            raise Http404
        except InvalidScanConfiguration as ex:
            logger.exception('Unable to edit Scan process: %s', scan_id)
            raise BadParameter(unicode(ex))

        return Response(status=status.HTTP_204_NO_CONTENT)
Пример #24
0
    def post(self, request, *args, **kwargs):
        if request.version != 'v5':
            raise Http404()

        file_name = None
        file_content = None

        # Check whether AJAX or a standard encoded form was used
        if request.is_ajax():

            # File name must be provided by an HTTP header
            if 'HTTP_X_FILE_NAME' not in request.META:
                return Response('Missing HTTP header for file name.',
                                status=status.HTTP_400_BAD_REQUEST)
            file_name = request.META['HTTP_X_FILE_NAME']
            file_content = request
        else:

            # File content must be already processed by the request
            if len(request.data) != 1:
                return Response('Missing embedded file content.',
                                status=status.HTTP_400_BAD_REQUEST)
            file_handle = request.data.values()[0]
            file_name = file_handle.name
            file_content = file_handle

        # Make sure the file type is supported
        if not file_name or not file_content:
            return Response('Missing file attachment.',
                            status=status.HTTP_400_BAD_REQUEST)
        if os.path.splitext(file_name)[1] not in ['.json']:
            return Response('Unsupported file type.',
                            status=status.HTTP_400_BAD_REQUEST)

        # Attempt to parse the file content
        # TODO: Add buffer overflow protection
        import_dict = json.loads(file_content.read())

        # Attempt to apply the configuration
        try:
            warnings = importer.import_config(import_dict)
        except InvalidConfiguration as ex:
            logger.exception('Unable to import configuration.')
            raise BadParameter(unicode(ex))

        results = [{'id': w.key, 'details': w.details} for w in warnings]
        return Response({'warnings': results})
Пример #25
0
    def post(self, request):
        """Imports job and recipe configuration and updates the corresponding models.

        :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
        """
        import_dict = rest_util.parse_dict(request, 'import')

        try:
            warnings = importer.import_config(import_dict)
        except InvalidConfiguration as ex:
            logger.exception('Unable to import configuration.')
            raise BadParameter(unicode(ex))

        results = [{'id': w.key, 'details': w.details} for w in warnings]
        return Response({'warnings': results})
Пример #26
0
    def post(self, request):
        """Creates and queues the specified number of Scale Roulette jobs

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

        num = rest_util.parse_int(request, 'num')

        if num < 1:
            raise BadParameter('num must be at least 1')

        # TODO: in the future, send command message to do this asynchronously
        job_type = JobType.objects.get(name='scale-roulette', version='1.0')
        for _ in xrange(num):
            Queue.objects.queue_new_job_for_user(job_type, {})

        return Response(status=status.HTTP_202_ACCEPTED)
Пример #27
0
    def _post_v5(self, request):
        """Validates a new Scan process and returns any warnings discovered

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

        configuration = rest_util.parse_dict(request, 'configuration')

        # Validate the Scan configuration
        try:
            config = ScanConfigurationV1(configuration).get_configuration()
            warnings = config.validate()
        except InvalidScanConfiguration as ex:
            logger.exception('Unable to validate Scan configuration.')
            raise BadParameter(unicode(ex))

        results = [{'id': w.key, 'details': w.details} for w in warnings]
        return Response({'warnings': results})
Пример #28
0
    def _update_v6(self, request, batch_id):
        """The v6 version for updating a batch

        :param request: the HTTP PATCH request
        :type request: :class:`rest_framework.request.Request`
        :param batch_id: the batch id
        :type batch_id: int
        :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)
        configuration_dict = rest_util.parse_dict(request,
                                                  'configuration',
                                                  required=False)

        try:
            batch = Batch.objects.get(id=batch_id)
        except Batch.DoesNotExist:
            raise Http404()

        # Validate and create the batch
        try:
            configuration = None
            if configuration_dict:
                configuration_json = BatchConfigurationV6(
                    configuration=configuration_dict, do_validate=True)
                configuration = configuration_json.get_configuration()
            Batch.objects.edit_batch_v6(batch,
                                        title=title,
                                        description=description,
                                        configuration=configuration)
        except InvalidConfiguration as ex:
            raise BadParameter('Batch configuration invalid: %s' % unicode(ex))

        return Response(status=status.HTTP_204_NO_CONTENT)
Пример #29
0
    def post(self, request):
        '''Creates a new Strike process and returns its ID in JSON form

        :param request: the HTTP POST request
        :type request: :class:`rest_framework.request.Request`
        :rtype: :class:`rest_framework.response.Response`
        :returns: the HTTP response to send back to the user
        '''

        name = rest_util.parse_string(request, 'name')
        title = rest_util.parse_string(request, 'title', required=False)
        description = rest_util.parse_string(request,
                                             'description',
                                             required=False)
        configuration = rest_util.parse_dict(request, 'configuration')

        try:
            strike = Strike.objects.create_strike_process(
                name, title, description, configuration)
        except InvalidStrikeConfiguration:
            raise BadParameter('Configuration failed to validate.')
        return Response({'strike_id': strike.id})
Пример #30
0
    def queue_casino_recipes(self, request):
        """Creates and queues the specified number of Scale Casino recipes

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

        num = rest_util.parse_int(request, 'num')

        if num < 1:
            raise BadParameter('num must be at least 1')

        # TODO: in the future, send command message to do this asynchronously
        recipe_type = RecipeType.objects.get(name='scale-casino',
                                             version='1.0')
        for _ in xrange(num):
            Queue.objects.queue_new_recipe_for_user(recipe_type,
                                                    LegacyRecipeData())

        return Response(status=status.HTTP_202_ACCEPTED)