def list(self, request, source_id=None): """Retrieves the products for a given source file ID and returns them in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :param source_id: The id of the source :type source_id: int encoded as a string :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ try: ScaleFile.objects.get(id=source_id, file_type='SOURCE') except ScaleFile.DoesNotExist: raise Http404 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) batch_ids = rest_util.parse_int_list(request, 'batch_id', required=False) job_type_ids = rest_util.parse_int_list(request, 'job_type_id', required=False) job_type_names = rest_util.parse_string_list(request, 'job_type_name', required=False) job_type_categories = rest_util.parse_string_list(request, 'job_type_category', required=False) is_operational = rest_util.parse_bool(request, 'is_operational', required=False) is_published = rest_util.parse_bool(request, 'is_published', required=False) file_name = rest_util.parse_string(request, 'file_name', required=False) order = rest_util.parse_string_list(request, 'order', required=False) products = SourceFile.objects.get_source_products( source_id, started=started, ended=ended, batch_ids=batch_ids, job_type_ids=job_type_ids, job_type_names=job_type_names, job_type_categories=job_type_categories, is_operational=is_operational, is_published=is_published, file_name=file_name, order=order) page = self.paginate_queryset(products) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list(self, request): """Retrieves the list of all job types and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) names = rest_util.parse_string_list(request, 'name', required=False) categories = rest_util.parse_string_list(request, 'category', required=False) is_active = rest_util.parse_bool(request, 'is_active', default_value=True) is_operational = rest_util.parse_bool(request, 'is_operational', required=False) order = rest_util.parse_string_list(request, 'order', ['name', 'version']) job_types = JobType.objects.get_job_types(started=started, ended=ended, names=names, categories=categories, is_active=is_active, is_operational=is_operational, order=order) page = self.paginate_queryset(job_types) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list_v6(self, request): """Retrieves the list of all recipe types returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ keywords = rest_util.parse_string_list(request, 'keyword', required=False) is_active = rest_util.parse_bool(request, 'is_active', required=False) is_system = rest_util.parse_bool(request, 'is_system', required=False) order = ['name'] recipe_types = RecipeType.objects.get_recipe_types_v6( keywords=keywords, is_active=is_active, is_system=is_system, order=order) page = self.paginate_queryset(recipe_types) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list(self, request): """Retrieves the product for a given file name and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) job_type_ids = rest_util.parse_int_list(request, 'job_type_id', required=False) job_type_names = rest_util.parse_string_list(request, 'job_type_name', required=False) job_type_categories = rest_util.parse_string_list(request, 'job_type_category', required=False) is_operational = rest_util.parse_bool(request, 'is_operational', required=False) is_published = rest_util.parse_bool(request, 'is_published', default_value=True) file_name = rest_util.parse_string(request, 'file_name', required=False) order = rest_util.parse_string_list(request, 'order', required=False) products = ProductFile.objects.get_products( started=started, ended=ended, job_type_ids=job_type_ids, job_type_names=job_type_names, job_type_categories=job_type_categories, is_operational=is_operational, is_published=is_published, file_name=file_name, order=order, ) page = self.paginate_queryset(products) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
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)
def patch(self, request, name, version): """Edits an existing seed job type and returns the updated details :param request: the HTTP PATCH request :type request: :class:`rest_framework.request.Request` :param job_type_id: The ID for the job type. :type job_type_id: int encoded as a str :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ auto_update = rest_util.parse_bool(request, 'auto_update', required=False) icon_code = rest_util.parse_string(request, 'icon_code', required=False) is_published = rest_util.parse_string(request, 'is_published', required=False) is_active = rest_util.parse_bool(request, 'is_active', required=False) is_paused = rest_util.parse_bool(request, 'is_paused', required=False) max_scheduled = rest_util.parse_int(request, 'max_scheduled', required=False) # Validate the job configuration and pull out secrets configuration_dict = rest_util.parse_dict(request, 'configuration', required=False) configuration = None try: if configuration_dict: configuration = JobConfigurationV6(configuration_dict).get_configuration() except InvalidJobConfiguration as ex: raise BadParameter('Job type configuration invalid: %s' % unicode(ex)) # Fetch the current job type model try: job_type = JobType.objects.get(name=name, version=version) except JobType.DoesNotExist: raise Http404 # Check for invalid fields fields = {'icon_code', 'is_published', 'is_active', 'is_paused', 'max_scheduled', 'configuration'} for key, value in request.data.iteritems(): if key not in fields: raise InvalidJobField try: with transaction.atomic(): # Edit the job type JobType.objects.edit_job_type_v6(job_type_id=job_type.id, manifest=None, is_published=is_published, docker_image=None, icon_code=icon_code, is_active=is_active, is_paused=is_paused, max_scheduled=max_scheduled, configuration=configuration, auto_update=auto_update) except (InvalidJobField, InvalidSecretsConfiguration, ValueError, InvalidJobConfiguration, InvalidInterfaceDefinition) as ex: logger.exception('Unable to update job type: %i', job_type.id) raise BadParameter(unicode(ex)) return HttpResponse(status=204)
def list(self, request): """Gets jobs and their associated latest execution :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) statuses = rest_util.parse_string_list(request, 'status', required=False) job_ids = rest_util.parse_int_list(request, 'job_id', required=False) job_type_ids = rest_util.parse_int_list(request, 'job_type_id', required=False) job_type_names = rest_util.parse_string_list(request, 'job_type_name', required=False) job_type_categories = rest_util.parse_string_list(request, 'job_type_category', required=False) error_categories = rest_util.parse_string_list(request, 'error_category', required=False) include_superseded = rest_util.parse_bool(request, 'include_superseded', required=False) order = rest_util.parse_string_list(request, 'order', required=False) jobs = Job.objects.get_jobs(started=started, ended=ended, statuses=statuses, job_ids=job_ids, job_type_ids=job_type_ids, job_type_names=job_type_names, job_type_categories=job_type_categories, error_categories=error_categories, include_superseded=include_superseded, order=order) # Add the latest execution for each matching job page = self.paginate_queryset(jobs) job_exes_dict = JobExecution.objects.get_latest(page) for job in page: job.latest_job_exe = job_exes_dict[job.id] if job.id in job_exes_dict else None serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def get(self, request): """Retrieves the job updates for a given time range and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) statuses = rest_util.parse_string_list(request, 'status', required=False) job_type_ids = rest_util.parse_int_list(request, 'job_type_id', required=False) job_type_names = rest_util.parse_string_list(request, 'job_type_name', required=False) job_type_categories = rest_util.parse_string_list(request, 'job_type_category', required=False) include_superseded = rest_util.parse_bool(request, 'include_superseded', required=False) order = rest_util.parse_string_list(request, 'order', required=False) jobs = Job.objects.get_job_updates(started=started, ended=ended, statuses=statuses, job_type_ids=job_type_ids, job_type_names=job_type_names, job_type_categories=job_type_categories, include_superseded=include_superseded, order=order) page = self.paginate_queryset(jobs) Job.objects.populate_input_files(page) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def _get_v6(self, request): """Retrieves the list of all errors and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) is_builtin = rest_util.parse_bool(request, 'is_builtin', required=False) job_type_name = rest_util.parse_string(request, 'job_type_name', required=False) name = rest_util.parse_string(request, 'name', required=False) category = rest_util.parse_string(request, 'category', required=False) order = rest_util.parse_string_list(request, 'order', required=False) errors = Error.objects.get_errors(started=started, ended=ended, order=order, is_builtin=is_builtin, job_type_name=job_type_name, name=name, category=category) page = self.paginate_queryset(errors) serializer = self.serializer_class(page, many=True) return self.get_paginated_response(serializer.data)
def patch(self, request, job_type_id): '''Modify job type info with a subset of fields :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :param job_type_id: The ID for the job type. :type job_type_id: int encoded as a str :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user ''' # Validate that no extra fields are included rest_util.check_update(request, [u'error_mapping', u'is_paused']) # Validate JSON error_mapping = rest_util.parse_dict(request, u'error_mapping', required=False) is_paused = rest_util.parse_bool(request, u'is_paused', required=False) if error_mapping is not None: try: ErrorInterface(error_mapping) except InvalidInterfaceDefinition: return Response(u'Input failed schema validation.', status=status.HTTP_400_BAD_REQUEST) try: if error_mapping is not None: JobType.objects.update_error_mapping(error_mapping, job_type_id) if is_paused is not None: Queue.objects.update_job_type_pause(job_type_id, is_paused) job_type = JobType.objects.get_details(job_type_id) serializer = JobTypeDetailsSerializer(job_type) return Response(serializer.data, status=status.HTTP_200_OK) except JobType.DoesNotExist: raise Http404
def list(self, request): """Retrieves the source file updates for a given time range and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) time_field = rest_util.parse_string( request, 'time_field', required=False, accepted_values=SourceFile.VALID_TIME_FIELDS) is_parsed = rest_util.parse_bool(request, 'is_parsed', required=False) file_name = rest_util.parse_string(request, 'file_name', required=False) order = rest_util.parse_string_list(request, 'order', required=False) sources = SourceFile.objects.get_sources(started, ended, time_field, is_parsed, file_name, order) page = self.paginate_queryset(sources) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def retrieve_v4(self, request, source_id=None, file_name=None): """Retrieves the details for a source file and return them in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :param source_id: The id of the source :type source_id: int encoded as a string :param file_name: The name of the source :type file_name: string :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ # Support retrieving by file name in addition to the usual identifier if file_name: sources = ScaleFile.objects.filter( file_name=file_name, file_type='SOURCE').values('id').order_by('-parsed') if not sources: raise Http404 source_id = sources[0]['id'] include_superseded = rest_util.parse_bool(request, 'include_superseded', required=False) try: source = SourceFile.objects.get_details_v4( source_id, include_superseded=include_superseded) except ScaleFile.DoesNotExist: raise Http404 serializer = self.get_serializer(source) return Response(serializer.data)
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))
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 = reverse('workspace_details_view', args=[workspace.id], request=request) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=workspace_url))
def _post_v5(self, request, scan_id=None): """Launches a scan to ingest from an existing scan model instance :param request: the HTTP POST request :type request: :class:`rest_framework.request.Request` :param scan_id: ID for Scan record to pull configuration from :type scan_id: int :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ ingest = rest_util.parse_bool(request, 'ingest', default_value=False) try: scan = Scan.objects.queue_scan(scan_id, dry_run=not ingest) except Scan.DoesNotExist: raise Http404 serializer = self.get_serializer(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))
def list_impl(self, request): """Retrieves the ingest status information and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ started = rest_util.parse_timestamp(request, 'started', rest_util.get_relative_days(7)) ended = rest_util.parse_timestamp(request, 'ended', required=False) rest_util.check_time_range(started, ended, max_duration=datetime.timedelta(days=31)) use_ingest_time = rest_util.parse_bool(request, 'use_ingest_time', default_value=False) ingests = Ingest.objects.get_status(started, ended, use_ingest_time) page = self.paginate_queryset(ingests) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list(self, request): """Retrieves the list of all nodes and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) include_inactive = rest_util.parse_bool(request, 'include_inactive', False, False) order = rest_util.parse_string_list(request, 'order', required=False) nodes = Node.objects.get_nodes(started, ended, order, include_inactive=include_inactive) page = self.paginate_queryset(nodes) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def retrieve(self, request, source_id=None, file_name=None): """Retrieves the details for a source file and return them in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :param source_id: The id of the source :type source_id: int encoded as a string :param file_name: The name of the source :type file_name: string :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ # Support retrieving by file name in addition to the usual identifier if file_name: sources = SourceFile.objects.filter(file_name=file_name).values('id').order_by('-parsed') if not sources: raise Http404 source_id = sources[0]['id'] include_superseded = rest_util.parse_bool(request, 'include_superseded', required=False) try: source = SourceFile.objects.get_details(source_id, include_superseded=include_superseded) except SourceFile.DoesNotExist: raise Http404 serializer = self.get_serializer(source) return Response(serializer.data)
def get(self, request): '''Retrieves the product updates for a given time range and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user ''' started = rest_util.parse_timestamp(request, u'started', required=False) ended = rest_util.parse_timestamp(request, u'ended', required=False) rest_util.check_time_range(started, ended) job_type_ids = rest_util.parse_int_list(request, u'job_type_id', required=False) job_type_names = rest_util.parse_string_list(request, u'job_type_name', required=False) job_type_categories = rest_util.parse_string_list(request, u'job_type_category', required=False) is_operational = rest_util.parse_bool(request, u'is_operational', required=False) file_name = rest_util.parse_string(request, u'file_name', required=False) order = rest_util.parse_string_list(request, u'order', required=False) products = ProductFile.objects.get_products(started, ended, job_type_ids, job_type_names, job_type_categories, is_operational, file_name, order) page = rest_util.perform_paging(request, products) ProductFile.objects.populate_source_ancestors(page) serializer = ProductFileUpdateListSerializer(page, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK)
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 = reverse("workspace_details_view", args=[workspace.id], request=request) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=workspace_url))
def test_parse_bool_true(self): '''Tests parsing a required bool parameter that is provided via GET.''' request = MagicMock(Request) request.query_params = QueryDict('', mutable=True) request.query_params.update({ 'test1': 'TRUE', 'test2': 'True', 'test3': 'true', 'test4': 't', 'test5': '1', }) self.assertTrue(rest_util.parse_bool(request, 'test1')) self.assertTrue(rest_util.parse_bool(request, 'test2')) self.assertTrue(rest_util.parse_bool(request, 'test3')) self.assertTrue(rest_util.parse_bool(request, 'test4')) self.assertTrue(rest_util.parse_bool(request, 'test5'))
def test_parse_bool_post(self): '''Tests parsing a required bool parameter that is provided via POST.''' request = MagicMock(Request) request.DATA = QueryDict('', mutable=True) request.DATA.update({ 'test': 'true', }) self.assertTrue(rest_util.parse_bool(request, 'test'))
def test_parse_bool_post(self): """Tests parsing a required bool parameter that is provided via POST.""" request = MagicMock(Request) request.data = QueryDict('', mutable=True) request.data.update({ 'test': 'true', }) self.assertTrue(rest_util.parse_bool(request, 'test'))
def test_parse_bool_optional(self): '''Tests parsing an optional bool parameter that is missing.''' request = MagicMock(Request) request.QUERY_PARAMS = QueryDict('', mutable=True) request.QUERY_PARAMS.update({ 'test': 'true', }) self.assertIsNone(rest_util.parse_bool(request, 'test2', required=False))
def test_parse_bool_false(self): """Tests parsing a required bool parameter that is provided via GET.""" request = MagicMock(Request) request.query_params = QueryDict('', mutable=True) request.query_params.update({ 'test1': 'FALSE', 'test2': 'False', 'test3': 'false', 'test4': 'f', 'test5': '0', }) self.assertFalse(rest_util.parse_bool(request, 'test1')) self.assertFalse(rest_util.parse_bool(request, 'test2')) self.assertFalse(rest_util.parse_bool(request, 'test3')) self.assertFalse(rest_util.parse_bool(request, 'test4')) self.assertFalse(rest_util.parse_bool(request, 'test5'))
def test_parse_bool_false(self): '''Tests parsing a required bool parameter that is provided via GET.''' request = MagicMock(Request) request.QUERY_PARAMS = QueryDict('', mutable=True) request.QUERY_PARAMS.update({ 'test1': 'FALSE', 'test2': 'False', 'test3': 'false', 'test4': 'f', 'test5': '0', }) self.assertFalse(rest_util.parse_bool(request, 'test1')) self.assertFalse(rest_util.parse_bool(request, 'test2')) self.assertFalse(rest_util.parse_bool(request, 'test3')) self.assertFalse(rest_util.parse_bool(request, 'test4')) self.assertFalse(rest_util.parse_bool(request, 'test5'))
def test_parse_bool_default(self): """Tests parsing an optional bool parameter that is provided via default value.""" request = MagicMock(Request) request.query_params = QueryDict('', mutable=True) request.query_params.update({ 'test': 'true', }) self.assertFalse(rest_util.parse_bool(request, 'test2', False))
def test_parse_bool_default(self): '''Tests parsing an optional bool parameter that is provided via default value.''' request = MagicMock(Request) request.QUERY_PARAMS = QueryDict('', mutable=True) request.QUERY_PARAMS.update({ 'test': 'true', }) self.assertFalse(rest_util.parse_bool(request, 'test2', False))
def _list_v6(self, request): """Retrieves the list of all recipes and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) source_started = rest_util.parse_timestamp(request, 'source_started', required=False) source_ended = rest_util.parse_timestamp(request, 'source_ended', required=False) rest_util.check_time_range(source_started, source_ended) source_sensor_classes = rest_util.parse_string_list(request, 'source_sensor_class', required=False) source_sensors = rest_util.parse_string_list(request, 'source_sensor', required=False) source_collections = rest_util.parse_string_list(request, 'source_collection', required=False) source_tasks = rest_util.parse_string_list(request, 'source_task', required=False) recipe_ids = rest_util.parse_int_list(request, 'recipe_id', required=False) type_ids = rest_util.parse_int_list(request, 'recipe_type_id', required=False) type_names = rest_util.parse_string_list(request, 'recipe_type_name', required=False) batch_ids = rest_util.parse_int_list(request, 'batch_id', required=False) is_superseded = rest_util.parse_bool(request, 'is_superseded', required=False) is_completed = rest_util.parse_bool(request, 'is_completed', required=False) order = rest_util.parse_string_list(request, 'order', required=False) root_recipe_ids = rest_util.parse_int_list(request, 'root_recipe_id', required=False) recipes = Recipe.objects.get_recipes_v6(started=started, ended=ended, source_started=source_started, source_ended=source_ended, source_sensor_classes=source_sensor_classes, source_sensors=source_sensors, source_collections=source_collections, source_tasks=source_tasks, ids=recipe_ids, type_ids=type_ids, type_names=type_names, batch_ids=batch_ids, is_superseded=is_superseded, is_completed=is_completed, order=order, root_recipe_ids=root_recipe_ids) # additional optimizations not being captured by the existing ones in the manager # see issue #1717 recipes = recipes.select_related('recipe_type_rev__recipe_type').defer(None) page = self.paginate_queryset(recipes) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def test_parse_bool_optional(self): """Tests parsing an optional bool parameter that is missing.""" request = MagicMock(Request) request.query_params = QueryDict('', mutable=True) request.query_params.update({ 'test': 'true', }) self.assertIsNone( rest_util.parse_bool(request, 'test2', required=False))
def _list_v6(self, request): """The v6 version for retrieving batches :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) recipe_type_ids = rest_util.parse_int_list(request, 'recipe_type_id', required=False) is_creation_done = rest_util.parse_bool(request, 'is_creation_done', required=False) is_superseded = rest_util.parse_bool(request, 'is_superseded', required=False) root_batch_ids = rest_util.parse_int_list(request, 'root_batch_id', required=False) order = rest_util.parse_string_list(request, 'order', required=False) batches = Batch.objects.get_batches_v6( started=started, ended=ended, recipe_type_ids=recipe_type_ids, is_creation_done=is_creation_done, is_superseded=is_superseded, root_batch_ids=root_batch_ids, order=order) page = self.paginate_queryset(batches) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list(self, request): """Retrieves jobs and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) source_started = rest_util.parse_timestamp(request, 'source_started', required=False) source_ended = rest_util.parse_timestamp(request, 'source_ended', required=False) rest_util.check_time_range(source_started, source_ended) source_sensor_classes = rest_util.parse_string_list(request, 'source_sensor_class', required=False) source_sensors = rest_util.parse_string_list(request, 'source_sensor', required=False) source_collections = rest_util.parse_string_list(request, 'source_collection', required=False) source_tasks = rest_util.parse_string_list(request, 'source_task', required=False) statuses = rest_util.parse_string_list(request, 'status', required=False) job_ids = rest_util.parse_int_list(request, 'job_id', required=False) job_type_ids = rest_util.parse_int_list(request, 'job_type_id', required=False) job_type_names = rest_util.parse_string_list(request, 'job_type_name', required=False) batch_ids = rest_util.parse_int_list(request, 'batch_id', required=False) recipe_ids = rest_util.parse_int_list(request, 'recipe_id', required=False) error_categories = rest_util.parse_string_list(request, 'error_category', required=False) error_ids = rest_util.parse_int_list(request, 'error_id', required=False) is_superseded = rest_util.parse_bool(request, 'is_superseded', required=False) order = rest_util.parse_string_list(request, 'order', required=False) jobs = Job.objects.get_jobs_v6(started=started, ended=ended, source_started=source_started, source_ended=source_ended, source_sensor_classes=source_sensor_classes, source_sensors=source_sensors, source_collections=source_collections, source_tasks=source_tasks, statuses=statuses, job_ids=job_ids, job_type_ids=job_type_ids, job_type_names=job_type_names, batch_ids=batch_ids, recipe_ids=recipe_ids, error_categories=error_categories, error_ids=error_ids, is_superseded=is_superseded, order=order) page = self.paginate_queryset(jobs) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list(self, request, name): """Retrieves the list of versions for a job type with the given name and return them in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :param name: The name of the job type :type name: string :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ is_active = rest_util.parse_bool(request, 'is_active', required=False) order = ['-version'] job_types = JobType.objects.get_job_type_versions_v6(name, is_active, order) page = self.paginate_queryset(job_types) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
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)
def list(self, request): """Retrieves the list of all job types with status and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ # Get a list of all job type status counts is_active = rest_util.parse_bool(request, 'is_active', required=False) started = rest_util.parse_timestamp(request, 'started', 'PT3H0M0S') ended = rest_util.parse_timestamp(request, 'ended', required=False) job_type_statuses = JobType.objects.get_status(is_active=is_active, started=started, ended=ended) page = self.paginate_queryset(job_type_statuses) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list(self, request): """Retrieves the list of all job types with status and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ # Get a list of all job type status counts started = rest_util.parse_timestamp(request, 'started', 'PT3H0M0S') ended = rest_util.parse_timestamp(request, 'ended', required=False) is_operational = rest_util.parse_bool(request, 'is_operational', required=False) job_type_statuses = JobType.objects.get_status(started=started, ended=ended, is_operational=is_operational) page = self.paginate_queryset(job_type_statuses) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def get(self, request): '''Retrieves the list of all nodes and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) include_inactive = rest_util.parse_bool(request, 'include_inactive', False, False) order = rest_util.parse_string_list(request, 'order', required=False) nodes = Node.objects.get_nodes(started, ended, order, include_inactive=include_inactive) page = rest_util.perform_paging(request, nodes) serializer = NodeListSerializer(page, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK)
def list(self, request): """Retrieves the ingest status information and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ started = rest_util.parse_timestamp(request, 'started', rest_util.get_relative_days(7)) ended = rest_util.parse_timestamp(request, 'ended', required=False) rest_util.check_time_range(started, ended, max_duration=datetime.timedelta(days=31)) use_ingest_time = rest_util.parse_bool(request, 'use_ingest_time', default_value=False) ingests = Ingest.objects.get_status(started, ended, use_ingest_time) page = self.paginate_queryset(ingests) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def get(self, request): '''Retrieves the ingest status information and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user ''' started = rest_util.parse_timestamp(request, 'started', rest_util.get_relative_days(7)) ended = rest_util.parse_timestamp(request, 'ended', required=False) rest_util.check_time_range(started, ended, max_duration=datetime.timedelta(days=31)) use_ingest_time = rest_util.parse_bool(request, 'use_ingest_time', default_value=False) ingests = Ingest.objects.get_status(started, ended, use_ingest_time) page = rest_util.perform_paging(request, ingests) serializer = IngestStatusListSerializer(page, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK)
def get(self, request): '''Retrieves the source file updates for a given time range and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user ''' started = rest_util.parse_timestamp(request, u'started', required=False) ended = rest_util.parse_timestamp(request, u'ended', required=False) rest_util.check_time_range(started, ended) is_parsed = rest_util.parse_bool(request, u'is_parsed', required=False) file_name = rest_util.parse_string(request, u'file_name', required=False) order = rest_util.parse_string_list(request, u'order', required=False) sources = SourceFile.objects.get_sources(started, ended, is_parsed, file_name, order) page = rest_util.perform_paging(request, sources) serializer = SourceFileUpdateListSerializer(page, context={'request': request}) return Response(serializer.data, status=status.HTTP_200_OK)
def list(self, request): """Retrieves the source file updates for a given time range and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) is_parsed = rest_util.parse_bool(request, 'is_parsed', required=False) file_name = rest_util.parse_string(request, 'file_name', required=False) order = rest_util.parse_string_list(request, 'order', required=False) sources = SourceFile.objects.get_sources(started, ended, is_parsed, file_name, order) page = self.paginate_queryset(sources) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list(self, request, product_id=None): """Retrieves the source files for a given product id and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :returns: the HTTP response to send back to the user """ try: ScaleFile.objects.get(id=product_id, file_type='PRODUCT') except ScaleFile.DoesNotExist: raise Http404 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) time_field = rest_util.parse_string( request, 'time_field', required=False, accepted_values=SourceFile.VALID_TIME_FIELDS) is_parsed = rest_util.parse_bool(request, 'is_parsed', required=False) file_name = rest_util.parse_string(request, 'file_name', required=False) order = rest_util.parse_string_list(request, 'order', required=False) sources = ProductFile.objects.get_product_sources( product_id, started, ended, time_field, is_parsed, file_name, order) page = self.paginate_queryset(sources) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
def list(self, request): """Retrieves the list of all recipes and returns it in JSON form :param request: the HTTP GET request :type request: :class:`rest_framework.request.Request` :rtype: :class:`rest_framework.response.Response` :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) type_ids = rest_util.parse_int_list(request, 'type_id', required=False) type_names = rest_util.parse_string_list(request, 'type_name', required=False) batch_ids = rest_util.parse_int_list(request, 'batch_id', required=False) include_superseded = rest_util.parse_bool(request, 'include_superseded', required=False) order = rest_util.parse_string_list(request, 'order', required=False) recipes = Recipe.objects.get_recipes( started=started, ended=ended, type_ids=type_ids, type_names=type_names, batch_ids=batch_ids, include_superseded=include_superseded, order=order) page = self.paginate_queryset(recipes) serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data)
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) priority = rest_util.parse_int(request, 'priority', required=False) try: recipe = Recipe.objects.select_related('recipe_type', 'recipe_type_rev').get(id=recipe_id) except Recipe.DoesNotExist: raise Http404 if recipe.is_superseded: raise BadParameter('Cannot reprocess a superseded recipe') event = TriggerEvent.objects.create_trigger_event('USER', None, {'user': '******'}, now()) root_recipe_id = recipe.root_superseded_recipe_id if recipe.root_superseded_recipe_id else recipe.id recipe_type_name = recipe.recipe_type.name revision_num = recipe.recipe_type_rev.revision_num forced_nodes = ForcedNodes() if all_jobs: forced_nodes.set_all_nodes() elif job_names: for job_name in job_names: forced_nodes.add_node(job_name) # Execute all of the messages to perform the reprocess messages = create_reprocess_messages([root_recipe_id], recipe_type_name, revision_num, event.id, forced_nodes=forced_nodes) while messages: msg = messages.pop(0) result = msg.execute() if not result: raise Exception('Reprocess failed on message type \'%s\'' % msg.type) messages.extend(msg.new_messages) # Update job priorities if priority is not None: Job.objects.filter(event_id=event.id).update(priority=priority) from queue.models import Queue Queue.objects.filter(job__event_id=event.id).update(priority=priority) new_recipe = Recipe.objects.get(root_superseded_recipe_id=root_recipe_id, is_superseded=False) try: # TODO: remove this check when REST API v5 is removed if request.version == 'v6': new_recipe = Recipe.objects.get_details(new_recipe.id) else: new_recipe = Recipe.objects.get_details_v5(new_recipe.id) except Recipe.DoesNotExist: raise Http404 serializer = self.get_serializer(new_recipe) url = reverse('recipe_details_view', args=[new_recipe.id], request=request) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=dict(location=url))
def post(self, request): '''Creates a new JobType 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, u'name') version = rest_util.parse_string(request, u'version') title = rest_util.parse_string(request, u'title', default_value=u'Unknown Job Type') description = rest_util.parse_string(request, u'description') category = rest_util.parse_string(request, u'category', default_value=u'unknown') author_name = rest_util.parse_string(request, u'author_name', required=False) author_url = rest_util.parse_string(request, u'author_url', required=False) is_system = False is_long_running = False is_active = rest_util.parse_bool(request, u'is_active', default_value=True) is_operational = rest_util.parse_bool(request, u'is_operational', default_value=True) is_paused = rest_util.parse_bool(request, u'is_paused', default_value=False) requires_cleanup = True uses_docker = True docker_privileged = rest_util.parse_bool(request, u'docker_privileged', default_value=False) docker_image = rest_util.parse_string(request, u'docker_image') interface = rest_util.parse_dict(request, u'interface') error_mapping = rest_util.parse_dict(request, u'error_mapping', default_value={}) priority = rest_util.parse_int(request, u'priority', default_value=260) timeout = rest_util.parse_int(request, u'timeout', default_value=1800) max_tries = rest_util.parse_int(request, u'max_tries', default_value=3) cpus_required = rest_util.parse_float(request, u'cpus_required', default_value=1) mem_required = rest_util.parse_float(request, u'mem_required', default_value=5120) disk_out_const_required = rest_util.parse_float(request, u'disk_out_const_required', default_value=0) disk_out_mult_required = rest_util.parse_float(request, u'disk_out_mult_required', default_value=0) icon_code = rest_util.parse_string(request, u'icon_code', default_value=u'f013') try: try: job_type = JobType.objects.get(name=name, version=version) job_type.description = description job_type.docker_image = docker_image job_type.interface = interface job_type.priority = priority job_type.timeout = timeout job_type.max_tries = max_tries job_type.cpus_required = cpus_required job_type.mem_required = mem_required job_type.disk_out_const_required = disk_out_const_required except JobType.DoesNotExist: job_type = JobType.objects.create_job_type(name, version, description, docker_image, interface, priority, timeout, max_tries, cpus_required, mem_required, disk_out_const_required, None) job_type.title = title job_type.category = category job_type.author_name = author_name job_type.author_url = author_url job_type.is_system = is_system job_type.is_long_running = is_long_running job_type.is_active = is_active job_type.is_operational = is_operational job_type.is_paused = is_paused job_type.requires_cleanup = requires_cleanup job_type.uses_docker = uses_docker job_type.docker_privileged = docker_privileged job_type.error_mapping = error_mapping job_type.icon_code = icon_code job_type.disk_out_mult_required = disk_out_mult_required job_type.save() except InvalidInterfaceDefinition: raise rest_util.BadParameter('Interface definition failed to validate.') return Response({'job_type_id': job_type.id}, status=status.HTTP_200_OK)