diff --git a/addon/flamenco/manager/__init__.py b/addon/flamenco/manager/__init__.py index 135bfb3e..5d1bc200 100644 --- a/addon/flamenco/manager/__init__.py +++ b/addon/flamenco/manager/__init__.py @@ -10,7 +10,7 @@ """ -__version__ = "41b0ee15" +__version__ = "81563c07" # import ApiClient from flamenco.manager.api_client import ApiClient diff --git a/addon/flamenco/manager/api/jobs_api.py b/addon/flamenco/manager/api/jobs_api.py index b2aca016..beac7b35 100644 --- a/addon/flamenco/manager/api/jobs_api.py +++ b/addon/flamenco/manager/api/jobs_api.py @@ -25,6 +25,7 @@ from flamenco.manager.model.available_job_type import AvailableJobType from flamenco.manager.model.available_job_types import AvailableJobTypes from flamenco.manager.model.error import Error from flamenco.manager.model.job import Job +from flamenco.manager.model.job_blocklist import JobBlocklist from flamenco.manager.model.job_status_change import JobStatusChange from flamenco.manager.model.job_tasks_summary import JobTasksSummary from flamenco.manager.model.jobs_query import JobsQuery @@ -94,6 +95,55 @@ class JobsApi(object): }, api_client=api_client ) + self.fetch_job_blocklist_endpoint = _Endpoint( + settings={ + 'response_type': (JobBlocklist,), + 'auth': [], + 'endpoint_path': '/api/jobs/{job_id}/blocklist', + 'operation_id': 'fetch_job_blocklist', + 'http_method': 'GET', + 'servers': None, + }, + params_map={ + 'all': [ + 'job_id', + ], + 'required': [ + 'job_id', + ], + 'nullable': [ + ], + 'enum': [ + ], + 'validation': [ + ] + }, + root_map={ + 'validations': { + }, + 'allowed_values': { + }, + 'openapi_types': { + 'job_id': + (str,), + }, + 'attribute_map': { + 'job_id': 'job_id', + }, + 'location_map': { + 'job_id': 'path', + }, + 'collection_format_map': { + } + }, + headers_map={ + 'accept': [ + 'application/json' + ], + 'content_type': [], + }, + api_client=api_client + ) self.fetch_job_tasks_endpoint = _Endpoint( settings={ 'response_type': (JobTasksSummary,), @@ -383,6 +433,61 @@ class JobsApi(object): }, api_client=api_client ) + self.remove_job_blocklist_endpoint = _Endpoint( + settings={ + 'response_type': None, + 'auth': [], + 'endpoint_path': '/api/jobs/{job_id}/blocklist', + 'operation_id': 'remove_job_blocklist', + 'http_method': 'DELETE', + 'servers': None, + }, + params_map={ + 'all': [ + 'job_id', + 'job_blocklist', + ], + 'required': [ + 'job_id', + ], + 'nullable': [ + ], + 'enum': [ + ], + 'validation': [ + ] + }, + root_map={ + 'validations': { + }, + 'allowed_values': { + }, + 'openapi_types': { + 'job_id': + (str,), + 'job_blocklist': + (JobBlocklist,), + }, + 'attribute_map': { + 'job_id': 'job_id', + }, + 'location_map': { + 'job_id': 'path', + 'job_blocklist': 'body', + }, + 'collection_format_map': { + } + }, + headers_map={ + 'accept': [ + 'application/json' + ], + 'content_type': [ + 'application/json' + ] + }, + api_client=api_client + ) self.set_job_status_endpoint = _Endpoint( settings={ 'response_type': None, @@ -623,6 +728,83 @@ class JobsApi(object): job_id return self.fetch_job_endpoint.call_with_http_info(**kwargs) + def fetch_job_blocklist( + self, + job_id, + **kwargs + ): + """Fetch the list of workers that are blocked from doing certain task types on this job. # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.fetch_job_blocklist(job_id, async_req=True) + >>> result = thread.get() + + Args: + job_id (str): + + Keyword Args: + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (int/float/tuple): timeout setting for this request. If + one number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _content_type (str/None): force body content-type. + Default is None and content-type will be predicted by allowed + content-types and body. + _host_index (int/None): specifies the index of the server + that we want to use. + Default is read from the configuration. + async_req (bool): execute request asynchronously + + Returns: + JobBlocklist + If the method is called asynchronously, returns the request + thread. + """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_spec_property_naming'] = kwargs.get( + '_spec_property_naming', False + ) + kwargs['_content_type'] = kwargs.get( + '_content_type') + kwargs['_host_index'] = kwargs.get('_host_index') + kwargs['job_id'] = \ + job_id + return self.fetch_job_blocklist_endpoint.call_with_http_info(**kwargs) + def fetch_job_tasks( self, job_id, @@ -1080,6 +1262,84 @@ class JobsApi(object): jobs_query return self.query_jobs_endpoint.call_with_http_info(**kwargs) + def remove_job_blocklist( + self, + job_id, + **kwargs + ): + """Remove entries from a job blocklist. # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.remove_job_blocklist(job_id, async_req=True) + >>> result = thread.get() + + Args: + job_id (str): + + Keyword Args: + job_blocklist (JobBlocklist): Tuples (worker, task type) to be removed from the blocklist.. [optional] + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (int/float/tuple): timeout setting for this request. If + one number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _content_type (str/None): force body content-type. + Default is None and content-type will be predicted by allowed + content-types and body. + _host_index (int/None): specifies the index of the server + that we want to use. + Default is read from the configuration. + async_req (bool): execute request asynchronously + + Returns: + None + If the method is called asynchronously, returns the request + thread. + """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_spec_property_naming'] = kwargs.get( + '_spec_property_naming', False + ) + kwargs['_content_type'] = kwargs.get( + '_content_type') + kwargs['_host_index'] = kwargs.get('_host_index') + kwargs['job_id'] = \ + job_id + return self.remove_job_blocklist_endpoint.call_with_http_info(**kwargs) + def set_job_status( self, job_id, diff --git a/addon/flamenco/manager/api_client.py b/addon/flamenco/manager/api_client.py index c4832e14..b54e3470 100644 --- a/addon/flamenco/manager/api_client.py +++ b/addon/flamenco/manager/api_client.py @@ -76,7 +76,7 @@ class ApiClient(object): self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'Flamenco/41b0ee15 (Blender add-on)' + self.user_agent = 'Flamenco/81563c07 (Blender add-on)' def __enter__(self): return self diff --git a/addon/flamenco/manager/configuration.py b/addon/flamenco/manager/configuration.py index f90f6817..ebe47a52 100644 --- a/addon/flamenco/manager/configuration.py +++ b/addon/flamenco/manager/configuration.py @@ -404,7 +404,7 @@ conf = flamenco.manager.Configuration( "OS: {env}\n"\ "Python Version: {pyversion}\n"\ "Version of the API: 1.0.0\n"\ - "SDK Package Version: 41b0ee15".\ + "SDK Package Version: 81563c07".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self): diff --git a/addon/flamenco/manager/docs/JobBlocklist.md b/addon/flamenco/manager/docs/JobBlocklist.md new file mode 100644 index 00000000..028b191b --- /dev/null +++ b/addon/flamenco/manager/docs/JobBlocklist.md @@ -0,0 +1,12 @@ +# JobBlocklist + +List of workers that are not allowed certain task types on a specific job. + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**value** | [**[JobBlocklistEntry]**](JobBlocklistEntry.md) | List of workers that are not allowed certain task types on a specific job. | + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/addon/flamenco/manager/docs/JobBlocklistEntry.md b/addon/flamenco/manager/docs/JobBlocklistEntry.md new file mode 100644 index 00000000..f9e05f77 --- /dev/null +++ b/addon/flamenco/manager/docs/JobBlocklistEntry.md @@ -0,0 +1,13 @@ +# JobBlocklistEntry + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**worker_id** | **str** | | +**task_type** | **str** | | +**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/addon/flamenco/manager/docs/JobsApi.md b/addon/flamenco/manager/docs/JobsApi.md index cc9ec10c..d4e0c936 100644 --- a/addon/flamenco/manager/docs/JobsApi.md +++ b/addon/flamenco/manager/docs/JobsApi.md @@ -5,12 +5,14 @@ All URIs are relative to *http://localhost* Method | HTTP request | Description ------------- | ------------- | ------------- [**fetch_job**](JobsApi.md#fetch_job) | **GET** /api/jobs/{job_id} | Fetch info about the job. +[**fetch_job_blocklist**](JobsApi.md#fetch_job_blocklist) | **GET** /api/jobs/{job_id}/blocklist | Fetch the list of workers that are blocked from doing certain task types on this job. [**fetch_job_tasks**](JobsApi.md#fetch_job_tasks) | **GET** /api/jobs/{job_id}/tasks | Fetch a summary of all tasks of the given job. [**fetch_task**](JobsApi.md#fetch_task) | **GET** /api/tasks/{task_id} | Fetch a single task. [**fetch_task_log_tail**](JobsApi.md#fetch_task_log_tail) | **GET** /api/tasks/{task_id}/logtail | Fetch the last few lines of the task's log. [**get_job_type**](JobsApi.md#get_job_type) | **GET** /api/jobs/type/{typeName} | Get single job type and its parameters. [**get_job_types**](JobsApi.md#get_job_types) | **GET** /api/jobs/types | Get list of job types and their parameters. [**query_jobs**](JobsApi.md#query_jobs) | **POST** /api/jobs/query | Fetch list of jobs. +[**remove_job_blocklist**](JobsApi.md#remove_job_blocklist) | **DELETE** /api/jobs/{job_id}/blocklist | Remove entries from a job blocklist. [**set_job_status**](JobsApi.md#set_job_status) | **POST** /api/jobs/{job_id}/setstatus | [**set_task_status**](JobsApi.md#set_task_status) | **POST** /api/tasks/{task_id}/setstatus | [**submit_job**](JobsApi.md#submit_job) | **POST** /api/jobs | Submit a new job for Flamenco Manager to execute. @@ -81,6 +83,73 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **fetch_job_blocklist** +> JobBlocklist fetch_job_blocklist(job_id) + +Fetch the list of workers that are blocked from doing certain task types on this job. + +### Example + + +```python +import time +import flamenco.manager +from flamenco.manager.api import jobs_api +from flamenco.manager.model.error import Error +from flamenco.manager.model.job_blocklist import JobBlocklist +from pprint import pprint +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = flamenco.manager.Configuration( + host = "http://localhost" +) + + +# Enter a context with an instance of the API client +with flamenco.manager.ApiClient() as api_client: + # Create an instance of the API class + api_instance = jobs_api.JobsApi(api_client) + job_id = "job_id_example" # str | + + # example passing only required values which don't have defaults set + try: + # Fetch the list of workers that are blocked from doing certain task types on this job. + api_response = api_instance.fetch_job_blocklist(job_id) + pprint(api_response) + except flamenco.manager.ApiException as e: + print("Exception when calling JobsApi->fetch_job_blocklist: %s\n" % e) +``` + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **job_id** | **str**| | + +### Return type + +[**JobBlocklist**](JobBlocklist.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | Get tuples (worker, task type) that got blocked on this job. | - | +**0** | Unexpected error. | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **fetch_job_tasks** > JobTasksSummary fetch_job_tasks(job_id) @@ -489,6 +558,87 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **remove_job_blocklist** +> remove_job_blocklist(job_id) + +Remove entries from a job blocklist. + +### Example + + +```python +import time +import flamenco.manager +from flamenco.manager.api import jobs_api +from flamenco.manager.model.error import Error +from flamenco.manager.model.job_blocklist import JobBlocklist +from pprint import pprint +# Defining the host is optional and defaults to http://localhost +# See configuration.py for a list of all supported configuration parameters. +configuration = flamenco.manager.Configuration( + host = "http://localhost" +) + + +# Enter a context with an instance of the API client +with flamenco.manager.ApiClient() as api_client: + # Create an instance of the API class + api_instance = jobs_api.JobsApi(api_client) + job_id = "job_id_example" # str | + job_blocklist = JobBlocklist([ + JobBlocklistEntry( + worker_id="worker_id_example", + task_type="task_type_example", + ), + ]) # JobBlocklist | Tuples (worker, task type) to be removed from the blocklist. (optional) + + # example passing only required values which don't have defaults set + try: + # Remove entries from a job blocklist. + api_instance.remove_job_blocklist(job_id) + except flamenco.manager.ApiException as e: + print("Exception when calling JobsApi->remove_job_blocklist: %s\n" % e) + + # example passing only required values which don't have defaults set + # and optional values + try: + # Remove entries from a job blocklist. + api_instance.remove_job_blocklist(job_id, job_blocklist=job_blocklist) + except flamenco.manager.ApiException as e: + print("Exception when calling JobsApi->remove_job_blocklist: %s\n" % e) +``` + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **job_id** | **str**| | + **job_blocklist** | [**JobBlocklist**](JobBlocklist.md)| Tuples (worker, task type) to be removed from the blocklist. | [optional] + +### Return type + +void (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**204** | Request accepted, entries have been removed. | - | +**0** | Unexpected error. | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **set_job_status** > set_job_status(job_id, job_status_change) diff --git a/addon/flamenco/manager/model/job_blocklist.py b/addon/flamenco/manager/model/job_blocklist.py new file mode 100644 index 00000000..53b68f18 --- /dev/null +++ b/addon/flamenco/manager/model/job_blocklist.py @@ -0,0 +1,283 @@ +""" + Flamenco manager + + Render Farm manager API # noqa: E501 + + The version of the OpenAPI document: 1.0.0 + Generated by: https://openapi-generator.tech +""" + + +import re # noqa: F401 +import sys # noqa: F401 + +from flamenco.manager.model_utils import ( # noqa: F401 + ApiTypeError, + ModelComposed, + ModelNormal, + ModelSimple, + cached_property, + change_keys_js_to_python, + convert_js_args_to_python_args, + date, + datetime, + file_type, + none_type, + validate_get_composed_info, + OpenApiModel +) +from flamenco.manager.exceptions import ApiAttributeError + + +def lazy_import(): + from flamenco.manager.model.job_blocklist_entry import JobBlocklistEntry + globals()['JobBlocklistEntry'] = JobBlocklistEntry + + +class JobBlocklist(ModelSimple): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + + Attributes: + allowed_values (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + with a capitalized key describing the allowed value and an allowed + value. These dicts store the allowed enum values. + validations (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + that stores validations for max_length, min_length, max_items, + min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum, + inclusive_minimum, and regex. + additional_properties_type (tuple): A tuple of classes accepted + as additional properties values. + """ + + allowed_values = { + } + + validations = { + } + + additional_properties_type = None + + _nullable = False + + @cached_property + def openapi_types(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + + Returns + openapi_types (dict): The key is attribute name + and the value is attribute type. + """ + lazy_import() + return { + 'value': ([JobBlocklistEntry],), + } + + @cached_property + def discriminator(): + return None + + + attribute_map = {} + + read_only_vars = set() + + _composed_schemas = None + + required_properties = set([ + '_data_store', + '_check_type', + '_spec_property_naming', + '_path_to_item', + '_configuration', + '_visited_composed_classes', + ]) + + @convert_js_args_to_python_args + def __init__(self, *args, **kwargs): + """JobBlocklist - a model defined in OpenAPI + + Note that value can be passed either in args or in kwargs, but not in both. + + Args: + args[0] ([JobBlocklistEntry]): List of workers that are not allowed certain task types on a specific job.. # noqa: E501 + + Keyword Args: + value ([JobBlocklistEntry]): List of workers that are not allowed certain task types on a specific job.. # noqa: E501 + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + """ + # required up here when default value is not given + _path_to_item = kwargs.pop('_path_to_item', ()) + + if 'value' in kwargs: + value = kwargs.pop('value') + elif args: + args = list(args) + value = args.pop(0) + else: + raise ApiTypeError( + "value is required, but not passed in args or kwargs and doesn't have default", + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + self.value = value + if kwargs: + raise ApiTypeError( + "Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % ( + kwargs, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + @classmethod + @convert_js_args_to_python_args + def _from_openapi_data(cls, *args, **kwargs): + """JobBlocklist - a model defined in OpenAPI + + Note that value can be passed either in args or in kwargs, but not in both. + + Args: + args[0] ([JobBlocklistEntry]): List of workers that are not allowed certain task types on a specific job.. # noqa: E501 + + Keyword Args: + value ([JobBlocklistEntry]): List of workers that are not allowed certain task types on a specific job.. # noqa: E501 + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + """ + # required up here when default value is not given + _path_to_item = kwargs.pop('_path_to_item', ()) + + self = super(OpenApiModel, cls).__new__(cls) + + if 'value' in kwargs: + value = kwargs.pop('value') + elif args: + args = list(args) + value = args.pop(0) + else: + raise ApiTypeError( + "value is required, but not passed in args or kwargs and doesn't have default", + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + self.value = value + if kwargs: + raise ApiTypeError( + "Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % ( + kwargs, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + return self diff --git a/addon/flamenco/manager/model/job_blocklist_entry.py b/addon/flamenco/manager/model/job_blocklist_entry.py new file mode 100644 index 00000000..1793b93c --- /dev/null +++ b/addon/flamenco/manager/model/job_blocklist_entry.py @@ -0,0 +1,267 @@ +""" + Flamenco manager + + Render Farm manager API # noqa: E501 + + The version of the OpenAPI document: 1.0.0 + Generated by: https://openapi-generator.tech +""" + + +import re # noqa: F401 +import sys # noqa: F401 + +from flamenco.manager.model_utils import ( # noqa: F401 + ApiTypeError, + ModelComposed, + ModelNormal, + ModelSimple, + cached_property, + change_keys_js_to_python, + convert_js_args_to_python_args, + date, + datetime, + file_type, + none_type, + validate_get_composed_info, + OpenApiModel +) +from flamenco.manager.exceptions import ApiAttributeError + + + +class JobBlocklistEntry(ModelNormal): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + + Attributes: + allowed_values (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + with a capitalized key describing the allowed value and an allowed + value. These dicts store the allowed enum values. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + discriminator_value_class_map (dict): A dict to go from the discriminator + variable value to the discriminator class name. + validations (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + that stores validations for max_length, min_length, max_items, + min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum, + inclusive_minimum, and regex. + additional_properties_type (tuple): A tuple of classes accepted + as additional properties values. + """ + + allowed_values = { + } + + validations = { + } + + @cached_property + def additional_properties_type(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + """ + return (bool, date, datetime, dict, float, int, list, str, none_type,) # noqa: E501 + + _nullable = False + + @cached_property + def openapi_types(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + + Returns + openapi_types (dict): The key is attribute name + and the value is attribute type. + """ + return { + 'worker_id': (str,), # noqa: E501 + 'task_type': (str,), # noqa: E501 + } + + @cached_property + def discriminator(): + return None + + + attribute_map = { + 'worker_id': 'worker_id', # noqa: E501 + 'task_type': 'task_type', # noqa: E501 + } + + read_only_vars = { + } + + _composed_schemas = {} + + @classmethod + @convert_js_args_to_python_args + def _from_openapi_data(cls, worker_id, task_type, *args, **kwargs): # noqa: E501 + """JobBlocklistEntry - a model defined in OpenAPI + + Args: + worker_id (str): + task_type (str): + + Keyword Args: + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + """ + + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _path_to_item = kwargs.pop('_path_to_item', ()) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + self = super(OpenApiModel, cls).__new__(cls) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + + self.worker_id = worker_id + self.task_type = task_type + for var_name, var_value in kwargs.items(): + if var_name not in self.attribute_map and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + self.additional_properties_type is None: + # discard variable. + continue + setattr(self, var_name, var_value) + return self + + required_properties = set([ + '_data_store', + '_check_type', + '_spec_property_naming', + '_path_to_item', + '_configuration', + '_visited_composed_classes', + ]) + + @convert_js_args_to_python_args + def __init__(self, worker_id, task_type, *args, **kwargs): # noqa: E501 + """JobBlocklistEntry - a model defined in OpenAPI + + Args: + worker_id (str): + task_type (str): + + Keyword Args: + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) + """ + + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _path_to_item = kwargs.pop('_path_to_item', ()) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + + self.worker_id = worker_id + self.task_type = task_type + for var_name, var_value in kwargs.items(): + if var_name not in self.attribute_map and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + self.additional_properties_type is None: + # discard variable. + continue + setattr(self, var_name, var_value) + if var_name in self.read_only_vars: + raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate " + f"class with read only attributes.") diff --git a/addon/flamenco/manager/models/__init__.py b/addon/flamenco/manager/models/__init__.py index a62ee6cf..0be44680 100644 --- a/addon/flamenco/manager/models/__init__.py +++ b/addon/flamenco/manager/models/__init__.py @@ -21,6 +21,8 @@ from flamenco.manager.model.error import Error from flamenco.manager.model.flamenco_version import FlamencoVersion from flamenco.manager.model.job import Job from flamenco.manager.model.job_all_of import JobAllOf +from flamenco.manager.model.job_blocklist import JobBlocklist +from flamenco.manager.model.job_blocklist_entry import JobBlocklistEntry from flamenco.manager.model.job_metadata import JobMetadata from flamenco.manager.model.job_settings import JobSettings from flamenco.manager.model.job_status import JobStatus diff --git a/addon/flamenco/manager_README.md b/addon/flamenco/manager_README.md index 4f845de7..23f1cabd 100644 --- a/addon/flamenco/manager_README.md +++ b/addon/flamenco/manager_README.md @@ -4,7 +4,7 @@ Render Farm manager API The `flamenco.manager` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: - API version: 1.0.0 -- Package version: 41b0ee15 +- Package version: 81563c07 - Build package: org.openapitools.codegen.languages.PythonClientCodegen For more information, please visit [https://flamenco.io/](https://flamenco.io/) @@ -36,6 +36,7 @@ from flamenco.manager.model.available_job_type import AvailableJobType from flamenco.manager.model.available_job_types import AvailableJobTypes from flamenco.manager.model.error import Error from flamenco.manager.model.job import Job +from flamenco.manager.model.job_blocklist import JobBlocklist from flamenco.manager.model.job_status_change import JobStatusChange from flamenco.manager.model.job_tasks_summary import JobTasksSummary from flamenco.manager.model.jobs_query import JobsQuery @@ -72,12 +73,14 @@ All URIs are relative to *http://localhost* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- *JobsApi* | [**fetch_job**](flamenco/manager/docs/JobsApi.md#fetch_job) | **GET** /api/jobs/{job_id} | Fetch info about the job. +*JobsApi* | [**fetch_job_blocklist**](flamenco/manager/docs/JobsApi.md#fetch_job_blocklist) | **GET** /api/jobs/{job_id}/blocklist | Fetch the list of workers that are blocked from doing certain task types on this job. *JobsApi* | [**fetch_job_tasks**](flamenco/manager/docs/JobsApi.md#fetch_job_tasks) | **GET** /api/jobs/{job_id}/tasks | Fetch a summary of all tasks of the given job. *JobsApi* | [**fetch_task**](flamenco/manager/docs/JobsApi.md#fetch_task) | **GET** /api/tasks/{task_id} | Fetch a single task. *JobsApi* | [**fetch_task_log_tail**](flamenco/manager/docs/JobsApi.md#fetch_task_log_tail) | **GET** /api/tasks/{task_id}/logtail | Fetch the last few lines of the task's log. *JobsApi* | [**get_job_type**](flamenco/manager/docs/JobsApi.md#get_job_type) | **GET** /api/jobs/type/{typeName} | Get single job type and its parameters. *JobsApi* | [**get_job_types**](flamenco/manager/docs/JobsApi.md#get_job_types) | **GET** /api/jobs/types | Get list of job types and their parameters. *JobsApi* | [**query_jobs**](flamenco/manager/docs/JobsApi.md#query_jobs) | **POST** /api/jobs/query | Fetch list of jobs. +*JobsApi* | [**remove_job_blocklist**](flamenco/manager/docs/JobsApi.md#remove_job_blocklist) | **DELETE** /api/jobs/{job_id}/blocklist | Remove entries from a job blocklist. *JobsApi* | [**set_job_status**](flamenco/manager/docs/JobsApi.md#set_job_status) | **POST** /api/jobs/{job_id}/setstatus | *JobsApi* | [**set_task_status**](flamenco/manager/docs/JobsApi.md#set_task_status) | **POST** /api/tasks/{task_id}/setstatus | *JobsApi* | [**submit_job**](flamenco/manager/docs/JobsApi.md#submit_job) | **POST** /api/jobs | Submit a new job for Flamenco Manager to execute. @@ -115,6 +118,8 @@ Class | Method | HTTP request | Description - [FlamencoVersion](flamenco/manager/docs/FlamencoVersion.md) - [Job](flamenco/manager/docs/Job.md) - [JobAllOf](flamenco/manager/docs/JobAllOf.md) + - [JobBlocklist](flamenco/manager/docs/JobBlocklist.md) + - [JobBlocklistEntry](flamenco/manager/docs/JobBlocklistEntry.md) - [JobMetadata](flamenco/manager/docs/JobMetadata.md) - [JobSettings](flamenco/manager/docs/JobSettings.md) - [JobStatus](flamenco/manager/docs/JobStatus.md) diff --git a/internal/worker/mocks/client.gen.go b/internal/worker/mocks/client.gen.go index bd359ecf..8231e163 100644 --- a/internal/worker/mocks/client.gen.go +++ b/internal/worker/mocks/client.gen.go @@ -36,6 +36,26 @@ func (m *MockFlamencoClient) EXPECT() *MockFlamencoClientMockRecorder { return m.recorder } +// FetchJobBlocklistWithResponse mocks base method. +func (m *MockFlamencoClient) FetchJobBlocklistWithResponse(arg0 context.Context, arg1 string, arg2 ...api.RequestEditorFn) (*api.FetchJobBlocklistResponse, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "FetchJobBlocklistWithResponse", varargs...) + ret0, _ := ret[0].(*api.FetchJobBlocklistResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchJobBlocklistWithResponse indicates an expected call of FetchJobBlocklistWithResponse. +func (mr *MockFlamencoClientMockRecorder) FetchJobBlocklistWithResponse(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1}, arg2...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchJobBlocklistWithResponse", reflect.TypeOf((*MockFlamencoClient)(nil).FetchJobBlocklistWithResponse), varargs...) +} + // FetchJobTasksWithResponse mocks base method. func (m *MockFlamencoClient) FetchJobTasksWithResponse(arg0 context.Context, arg1 string, arg2 ...api.RequestEditorFn) (*api.FetchJobTasksResponse, error) { m.ctrl.T.Helper() @@ -336,6 +356,46 @@ func (mr *MockFlamencoClientMockRecorder) RegisterWorkerWithResponse(arg0, arg1 return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterWorkerWithResponse", reflect.TypeOf((*MockFlamencoClient)(nil).RegisterWorkerWithResponse), varargs...) } +// RemoveJobBlocklistWithBodyWithResponse mocks base method. +func (m *MockFlamencoClient) RemoveJobBlocklistWithBodyWithResponse(arg0 context.Context, arg1, arg2 string, arg3 io.Reader, arg4 ...api.RequestEditorFn) (*api.RemoveJobBlocklistResponse, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1, arg2, arg3} + for _, a := range arg4 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RemoveJobBlocklistWithBodyWithResponse", varargs...) + ret0, _ := ret[0].(*api.RemoveJobBlocklistResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RemoveJobBlocklistWithBodyWithResponse indicates an expected call of RemoveJobBlocklistWithBodyWithResponse. +func (mr *MockFlamencoClientMockRecorder) RemoveJobBlocklistWithBodyWithResponse(arg0, arg1, arg2, arg3 interface{}, arg4 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1, arg2, arg3}, arg4...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveJobBlocklistWithBodyWithResponse", reflect.TypeOf((*MockFlamencoClient)(nil).RemoveJobBlocklistWithBodyWithResponse), varargs...) +} + +// RemoveJobBlocklistWithResponse mocks base method. +func (m *MockFlamencoClient) RemoveJobBlocklistWithResponse(arg0 context.Context, arg1 string, arg2 api.RemoveJobBlocklistJSONRequestBody, arg3 ...api.RequestEditorFn) (*api.RemoveJobBlocklistResponse, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1, arg2} + for _, a := range arg3 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "RemoveJobBlocklistWithResponse", varargs...) + ret0, _ := ret[0].(*api.RemoveJobBlocklistResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// RemoveJobBlocklistWithResponse indicates an expected call of RemoveJobBlocklistWithResponse. +func (mr *MockFlamencoClientMockRecorder) RemoveJobBlocklistWithResponse(arg0, arg1, arg2 interface{}, arg3 ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{arg0, arg1, arg2}, arg3...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveJobBlocklistWithResponse", reflect.TypeOf((*MockFlamencoClient)(nil).RemoveJobBlocklistWithResponse), varargs...) +} + // RequestWorkerStatusChangeWithBodyWithResponse mocks base method. func (m *MockFlamencoClient) RequestWorkerStatusChangeWithBodyWithResponse(arg0 context.Context, arg1, arg2 string, arg3 io.Reader, arg4 ...api.RequestEditorFn) (*api.RequestWorkerStatusChangeResponse, error) { m.ctrl.T.Helper() diff --git a/pkg/api/openapi_client.gen.go b/pkg/api/openapi_client.gen.go index fa1d4459..058daf73 100644 --- a/pkg/api/openapi_client.gen.go +++ b/pkg/api/openapi_client.gen.go @@ -112,6 +112,14 @@ type ClientInterface interface { // FetchJob request FetchJob(ctx context.Context, jobId string, reqEditors ...RequestEditorFn) (*http.Response, error) + // RemoveJobBlocklist request with any body + RemoveJobBlocklistWithBody(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + RemoveJobBlocklist(ctx context.Context, jobId string, body RemoveJobBlocklistJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // FetchJobBlocklist request + FetchJobBlocklist(ctx context.Context, jobId string, reqEditors ...RequestEditorFn) (*http.Response, error) + // SetJobStatus request with any body SetJobStatusWithBody(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -293,6 +301,42 @@ func (c *Client) FetchJob(ctx context.Context, jobId string, reqEditors ...Reque return c.Client.Do(req) } +func (c *Client) RemoveJobBlocklistWithBody(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRemoveJobBlocklistRequestWithBody(c.Server, jobId, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) RemoveJobBlocklist(ctx context.Context, jobId string, body RemoveJobBlocklistJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewRemoveJobBlocklistRequest(c.Server, jobId, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) FetchJobBlocklist(ctx context.Context, jobId string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFetchJobBlocklistRequest(c.Server, jobId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) SetJobStatusWithBody(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewSetJobStatusRequestWithBody(c.Server, jobId, contentType, body) if err != nil { @@ -867,6 +911,87 @@ func NewFetchJobRequest(server string, jobId string) (*http.Request, error) { return req, nil } +// NewRemoveJobBlocklistRequest calls the generic RemoveJobBlocklist builder with application/json body +func NewRemoveJobBlocklistRequest(server string, jobId string, body RemoveJobBlocklistJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewRemoveJobBlocklistRequestWithBody(server, jobId, "application/json", bodyReader) +} + +// NewRemoveJobBlocklistRequestWithBody generates requests for RemoveJobBlocklist with any type of body +func NewRemoveJobBlocklistRequestWithBody(server string, jobId string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "job_id", runtime.ParamLocationPath, jobId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/jobs/%s/blocklist", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewFetchJobBlocklistRequest generates requests for FetchJobBlocklist +func NewFetchJobBlocklistRequest(server string, jobId string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "job_id", runtime.ParamLocationPath, jobId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/jobs/%s/blocklist", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + // NewSetJobStatusRequest calls the generic SetJobStatus builder with application/json body func NewSetJobStatusRequest(server string, jobId string, body SetJobStatusJSONRequestBody) (*http.Request, error) { var bodyReader io.Reader @@ -1767,6 +1892,14 @@ type ClientWithResponsesInterface interface { // FetchJob request FetchJobWithResponse(ctx context.Context, jobId string, reqEditors ...RequestEditorFn) (*FetchJobResponse, error) + // RemoveJobBlocklist request with any body + RemoveJobBlocklistWithBodyWithResponse(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RemoveJobBlocklistResponse, error) + + RemoveJobBlocklistWithResponse(ctx context.Context, jobId string, body RemoveJobBlocklistJSONRequestBody, reqEditors ...RequestEditorFn) (*RemoveJobBlocklistResponse, error) + + // FetchJobBlocklist request + FetchJobBlocklistWithResponse(ctx context.Context, jobId string, reqEditors ...RequestEditorFn) (*FetchJobBlocklistResponse, error) + // SetJobStatus request with any body SetJobStatusWithBodyWithResponse(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetJobStatusResponse, error) @@ -1986,6 +2119,51 @@ func (r FetchJobResponse) StatusCode() int { return 0 } +type RemoveJobBlocklistResponse struct { + Body []byte + HTTPResponse *http.Response + JSONDefault *Error +} + +// Status returns HTTPResponse.Status +func (r RemoveJobBlocklistResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r RemoveJobBlocklistResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type FetchJobBlocklistResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *JobBlocklist + JSONDefault *Error +} + +// Status returns HTTPResponse.Status +func (r FetchJobBlocklistResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r FetchJobBlocklistResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type SetJobStatusResponse struct { Body []byte HTTPResponse *http.Response @@ -2557,6 +2735,32 @@ func (c *ClientWithResponses) FetchJobWithResponse(ctx context.Context, jobId st return ParseFetchJobResponse(rsp) } +// RemoveJobBlocklistWithBodyWithResponse request with arbitrary body returning *RemoveJobBlocklistResponse +func (c *ClientWithResponses) RemoveJobBlocklistWithBodyWithResponse(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*RemoveJobBlocklistResponse, error) { + rsp, err := c.RemoveJobBlocklistWithBody(ctx, jobId, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRemoveJobBlocklistResponse(rsp) +} + +func (c *ClientWithResponses) RemoveJobBlocklistWithResponse(ctx context.Context, jobId string, body RemoveJobBlocklistJSONRequestBody, reqEditors ...RequestEditorFn) (*RemoveJobBlocklistResponse, error) { + rsp, err := c.RemoveJobBlocklist(ctx, jobId, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseRemoveJobBlocklistResponse(rsp) +} + +// FetchJobBlocklistWithResponse request returning *FetchJobBlocklistResponse +func (c *ClientWithResponses) FetchJobBlocklistWithResponse(ctx context.Context, jobId string, reqEditors ...RequestEditorFn) (*FetchJobBlocklistResponse, error) { + rsp, err := c.FetchJobBlocklist(ctx, jobId, reqEditors...) + if err != nil { + return nil, err + } + return ParseFetchJobBlocklistResponse(rsp) +} + // SetJobStatusWithBodyWithResponse request with arbitrary body returning *SetJobStatusResponse func (c *ClientWithResponses) SetJobStatusWithBodyWithResponse(ctx context.Context, jobId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*SetJobStatusResponse, error) { rsp, err := c.SetJobStatusWithBody(ctx, jobId, contentType, body, reqEditors...) @@ -2997,6 +3201,65 @@ func ParseFetchJobResponse(rsp *http.Response) (*FetchJobResponse, error) { return response, nil } +// ParseRemoveJobBlocklistResponse parses an HTTP response from a RemoveJobBlocklistWithResponse call +func ParseRemoveJobBlocklistResponse(rsp *http.Response) (*RemoveJobBlocklistResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RemoveJobBlocklistResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && true: + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSONDefault = &dest + + } + + return response, nil +} + +// ParseFetchJobBlocklistResponse parses an HTTP response from a FetchJobBlocklistWithResponse call +func ParseFetchJobBlocklistResponse(rsp *http.Response) (*FetchJobBlocklistResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &FetchJobBlocklistResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest JobBlocklist + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && true: + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSONDefault = &dest + + } + + return response, nil +} + // ParseSetJobStatusResponse parses an HTTP response from a SetJobStatusWithResponse call func ParseSetJobStatusResponse(rsp *http.Response) (*SetJobStatusResponse, error) { bodyBytes, err := ioutil.ReadAll(rsp.Body) diff --git a/pkg/api/openapi_server.gen.go b/pkg/api/openapi_server.gen.go index e2031a1c..4869bc4d 100644 --- a/pkg/api/openapi_server.gen.go +++ b/pkg/api/openapi_server.gen.go @@ -31,6 +31,12 @@ type ServerInterface interface { // Fetch info about the job. // (GET /api/jobs/{job_id}) FetchJob(ctx echo.Context, jobId string) error + // Remove entries from a job blocklist. + // (DELETE /api/jobs/{job_id}/blocklist) + RemoveJobBlocklist(ctx echo.Context, jobId string) error + // Fetch the list of workers that are blocked from doing certain task types on this job. + // (GET /api/jobs/{job_id}/blocklist) + FetchJobBlocklist(ctx echo.Context, jobId string) error // (POST /api/jobs/{job_id}/setstatus) SetJobStatus(ctx echo.Context, jobId string) error @@ -173,6 +179,38 @@ func (w *ServerInterfaceWrapper) FetchJob(ctx echo.Context) error { return err } +// RemoveJobBlocklist converts echo context to params. +func (w *ServerInterfaceWrapper) RemoveJobBlocklist(ctx echo.Context) error { + var err error + // ------------- Path parameter "job_id" ------------- + var jobId string + + err = runtime.BindStyledParameterWithLocation("simple", false, "job_id", runtime.ParamLocationPath, ctx.Param("job_id"), &jobId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter job_id: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.RemoveJobBlocklist(ctx, jobId) + return err +} + +// FetchJobBlocklist converts echo context to params. +func (w *ServerInterfaceWrapper) FetchJobBlocklist(ctx echo.Context) error { + var err error + // ------------- Path parameter "job_id" ------------- + var jobId string + + err = runtime.BindStyledParameterWithLocation("simple", false, "job_id", runtime.ParamLocationPath, ctx.Param("job_id"), &jobId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter job_id: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.FetchJobBlocklist(ctx, jobId) + return err +} + // SetJobStatus converts echo context to params. func (w *ServerInterfaceWrapper) SetJobStatus(ctx echo.Context) error { var err error @@ -556,6 +594,8 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/api/jobs/type/:typeName", wrapper.GetJobType) router.GET(baseURL+"/api/jobs/types", wrapper.GetJobTypes) router.GET(baseURL+"/api/jobs/:job_id", wrapper.FetchJob) + router.DELETE(baseURL+"/api/jobs/:job_id/blocklist", wrapper.RemoveJobBlocklist) + router.GET(baseURL+"/api/jobs/:job_id/blocklist", wrapper.FetchJobBlocklist) router.POST(baseURL+"/api/jobs/:job_id/setstatus", wrapper.SetJobStatus) router.GET(baseURL+"/api/jobs/:job_id/tasks", wrapper.FetchJobTasks) router.GET(baseURL+"/api/tasks/:task_id", wrapper.FetchTask) diff --git a/pkg/api/openapi_spec.gen.go b/pkg/api/openapi_spec.gen.go index 1649ae8d..89228336 100644 --- a/pkg/api/openapi_spec.gen.go +++ b/pkg/api/openapi_spec.gen.go @@ -18,144 +18,148 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+R97XIbt7Lgq6DmblWSWoqUJdmOdf6sjx0nyrFjbSSfbNWxSwJnmiSsIcAAGNGMy1X3", - "IfZNdm/V/tj7a18g94220A3MYDgYkrItRyc3PxxJMwM0uhv9he7G+yxX84WSIK3Jjt9nJp/BnOOPj40R", - "UwnFOTdX7vcCTK7Fwgols+PWUyYM48y6n7hhwrrfNeQgrqFg4xWzM2C/KH0FepgNsoVWC9BWAM6Sq/mc", - "ywJ/Fhbm+MN/0TDJjrN/GTXAjTxkoyf0QfZhkNnVArLjjGvNV+73t2rsvvZ/NlYLOfV/v1hoobSwq+gF", - "IS1MQYc36K+JzyWfpx9sHtNYbquty3H4O6M33Yq4ueoHpKpE4R5MlJ5zmx3THwbrL34YZBp+rYSGIjv+", - "R3jJIcevpYYtWsIaliKUxFANGnq9qedV47eQWwfg42suSj4u4Uc1PgNrHTgdzjkTcloCM/ScqQnj7Ec1", - "Zm40k2CQmRI5/dge55cZSDYV1yAHrBRzYZHPrnkpCvdvBYZZ5f5mgPlBhuylLFesMg5GthR2xghpOLmb", - "u2bBDvLXma2ACa9K24XrfAbMPyQ4mJmppfTAsMqAZksHewEW9FxInH8mTEDJkIaPxkxPUf9lZJUqrVj4", - "iYRsJnL8qCc8BxwUCmHd0mlED/+ElwYGXeTaGWgHNC9LtWTu03VAGZ9Y984M2Fs1ZjNu2BhAMlON58Ja", - "KIbsF1WVBRPzRbliBZRAn5Ulg3fC0IDcXBk2UZqGfqvGA8Zl4QSImi9E6d4RdvhaNow+VqoELnFF17zs", - "4ud0ZWdKMni30GCMUIj8MTD3dsUtFA5HShe0wEAHwJW0SVfDVdNm0GWNK1h1YTgpQFoxEaD9IDXLD9i8", - "MtbBU0nxa0WM6In21m+E5DxuY3A9TeyFx3LF4J3VnHE9reZOwgR+Gy9WQ/ehGZ6pOZzS3lp9/Q3LHRkq", - "A4V7M9fALdBS/f5bRTA0W7yRLDdgITGfQyG4hXLFNLihGMelFjARUrgPBk4Q4PRuygHiRFXWQ8S1FXlV", - "cl3ToYcfTDUO4nOT1E0IqjP/Zb3VbzzCuf/8WhjhN9kNR/i7+1KUTgCvS3HHYx6yHSXvWYOKNQFcjffc", - "E8I48VxAK3tSaQ3SliumnKjkYVxk4khYmiG7/OHx2Q/fPb14dvL8u4vTx+c/XJIhUAgNuVV6xRbczth/", - "ZZevs9G/4H+vs0vGFwuQBRREQpDV3K1vIkq4cO9ng6wQOvyIf/ZKa8bNDIqL5s03iT3SR5euDPUYiFYf", - "bUzSENywk6dhy+CyneD4a+ng10P2k2ISjBMnxuoqt5UGw75GDWEGrBC5m4prAeYbxjUwUy0WStv1pXvg", - "B854ODxwiy4Vt9kA+XrXRUasE+/MmhkHKe1pFaqMtoRjl/6by2PGyyVfGXxpyC5RrqM8vTwm9sCvveh6", - "dUK6HBHqNYBmX5fiChgPSGO8KPaU/GbILpcwTg2zhHGjtZDr5lzyKTihNmDjyjKpLClQPwupJeTjIbuc", - "iaIAB6CEa9A49F/WedmLRgcpKRn3IiIHDVg3u+RlW9YEajUIpZkyFDoeL9kgW8J4K83SHBmMoIZPyHgW", - "hr1AFGjSjMKiRORzp7cSFlPJx1DezJL1K93dCk9Zeh0jaU2E+W1M4EVzbpNnDlsJnfdcGBs2MEqkfrx1", - "cRSs249b8XlLUfQst5kitcDgxnSW5R8wDc54QU3OmSGb2Rvfjn/hHeSVhW3uVb/vUjNQ9DiAlyZc9Elq", - "Rd9prXR3Pd+DBC1yBu4x02AWShpIOYJFYk/8cH5+yshbYe6N2kqoB2InbsfmZVWQWeewseCrUvGCGbfP", - "uW0QSNC2cOtsUQRNSPKrhJLD1/KJm+z+/qFTaWgkocRBA5FbPuYG3JNxZVZD5sxxBDQAxZaiLFmupOVC", - "Ms6++hmsXu09dubyV/TqDDianw48IQuRcwvGG9TLmchnzIo5WaSOFGAsy7l0ukmD1cLZ1s+Us8yD9PMD", - "CoPy0bEJdzo4iIyvDKsWQfDlpQBp0fZVzKg5OPtzyjRwoyRKSJTa8I42geAlG/P8Sk0mJAtrBzRorK73", - "Owdj+DTFe2vMhXRv3k9x1rOSz0Hm6u+gjfeHduTy6+aLzVCEF72MTEHxI0UXeFm+nGTH/9gsLc6CC+S+", - "+jBYB5jnVlzXujpm+KfNb8E+K7mxLHzBnDPjHaWkk0CWfEqwuAfoC4k5GMvni5iSBbew556kxhSJ4V69", - "OnkaIPwRYwtbwhK7RkScRqkDItWiSK/mPCzCwYAYoleHOy5qjf4IcEBdM20UKalJ9ubDG+KGF2C5EwZI", - "0KJAN4aXpy1Cd3Cw5rfpsbCa6xWb+8G8jW2G7IXSKPEXJbyLDUwvBubK+dOo6ion3dglH46H+aXb/kTn", - "4HZeAbpy8I67sfzuQa4+zs4WWlhgz7SYzpzJWRnQQ5hzUTqoV2MN8r+Nvb2r9DS8QRsuO8MX2Jn9f//3", - "GspII7Z2zVlkXKTxZHUFPd/WLBPsL6QDRqK4zB0GKCi1KMH6nyUhSyi5N+GC3qh/WHAnzbNB9msFFf7A", - "dT4T19GPZIzT8Hte+OJj/LkCel45nOzFsyXNvnoNT2ZcTqEru0jopmM89CwKQnhFiEMNP8sWW9sHNbt7", - "sHoE4Tk3V+asms+5XqUifPNFKSYCClZ6I42iPME/GLInpBtJ/+LDxrZ3f3LK2L0O3GlCbq66BgN+tbP5", - "hnFWD/AOlpvpW7n57xXQmqP9hOHH7Pi+U2ONTOjbZR8GGcaeLsYrjM+uy5o34acLIVscX7Os5+Y3Hzqm", - "PwHyPpsLKeZuw9xLK+dPllzPROlMlXEjuQZBDj0/+dt3jRhKRpHUZGKgDeh+CtAGT+9vEJo1OwqcvhVF", - "IQFzk1VFVFvfEj+DrbQkP9SxFwWfedjRwit1XEIrDr2zpuxwdD/3/gzGR647TtHuG4oMm4/cSN4ve6Lk", - "REwrzW3SrDMzPufyO7RIi+QBAAUYZ8DO8FU2Ec6711yaCWj2+PQEI1LBcxumQ4ZWaT6F5yrn6Wj70zqe", - "hY6Ak8aOQ3Au//Fwq4GxPstgbXVpLK3+BrD4uZIyeZJyUvsNywgVS3QF2Zyv2BXAgmn6HJ+lJem8M08X", - "S42a6tE5pN9+rtXlBmiDTxZrM1Yr2tpuoYUM2YllZobnCJUhj+iSHjnmh0vmluIt2ziYT16UmwQDPlPl", - "/pXwzg7ZiXcihWGXThRcDthlGwmX7MWrs3NnZ11icPsyHXBeI/IaImus9eEoRfSfYSqMBQ0F+fTdbcGL", - "QoMxNzyrLLl1dnGagmpil1zDBvJuEwe/1BQhcVTHYi7q00NzMyn+SaedPmQRUBWfeAZEDLKcYt0IYRZh", - "oQf6FLXOIK+0sKs6+LG2s3b1gje5vyTbnswgv1JV4sDxDNDEcvLI6xU7A6HZ2Q+PD+4/YLn70FTzATPi", - "Nwxgj1cWDAUGCjAOBFZ6uRQiKLmfrQnmr7kQOBu6wRiKP86ao5zhVJF4y46zw/vj/aNH9/KDh+P9w8PD", - "4t5kfHR/ku8//PYRv3eQ8/0H43vFg6P94uD+g0cPv90ff7v/sID7+0fFw/2DR7DvBhK/QXZ87+jgCP1o", - "mq1U06mQ03iqB4fjhwf5g8Pxo6ODo0lx73D86PDh/mT8YH//waP9b/fzQ37v/sN7D/PJIS+Ojg4eHN4f", - "3/v2Yf6Af/vo/v7DR81UBw8/dE2rgJFTBKBz4sjtzElhTQLK67cgt+LTtTAOyjUMZJXc2XchNuM1WU0A", - "PEPhhuVeV0JBIYB6kiE7kUyVBWjmoxgm+OV+LJx3yQ17Wxk6JX9dL4edPH2dke0djBA/ChN1yIkTFBgU", - "uvRm7Z4pq+nI5CBhz+22ER1m7p08bcvKZoN7ltnRviDYn4kSzhaQbzU1aPBBm0zbd1NjCqW8L/eMnJY1", - "qqTSFD6CPXzAYZ0xzvFXQn0hJhPQGK2bccmWTnU6UtbqcuCYIx4UY48gTaUd4fwRc7ONMVqJ5PwszJci", - "9XqEbzeS1KTuCrgF5GIivIRCeqDx5WWVBzoyxdqkWSRJEiyxsFfiEQPESQ97xhMQtkVtPGZyDJQz77sO", - "CLRldCKyum5WzniQW4NssRuCfxF21sRVdkL1wFtTOYqzcQ/qB0xp5yENWAELkAWm90g8ryL1+yenza62", - "UkSOnihMh6pxcGATeTvhskpeSbWUGNMsFS/ILnUEa9mfzfppsJ8JGswk8fbqRxseaGi0cNdrS9yS0fBF", - "DIQvoN76id+mF51CpbUaUWui1ZxxpqPPgkoZxKT0Pppqb3fQ187ueIZDkTengSGjOU3iX3N/g3f+ZA4n", - "pNOs5gTwS/FAszHr/XA7bBFPVG+3z8wrkfj+VK6hVMy24Fjb4p7+N9W5n0sQbhB6Kr8Ce/LyRzV+hRHU", - "ZKKTAVtnmA6YcXaUugbNwtd0rEtJKxSIMEP2zKkxWGKgbuAMXrgWqjIXBM0lWVjjhrnJCGoj4DMdmQV/", - "vj3QT3weZ2+lcwVbQN8olBjnNdeZRPeTAVoNEw1mdlEH4zfGfKKzZ+8Z+e/pGIBW85WhAwFvB2NmkrQ+", - "E8gYf85nBt6exl+dpYFHBUIW4loUFadTBbbEWaYgQVMcSLE5l6swiM8LXWieW5Hzsjet8OZI7M/ivumR", - "5iecaCbOMX0ed5Tp3abhpr3mNlR/VvIZSDyOrPcWkdo4B+JyZKJvLxlco0uDqZ5W+RSvoHOiN91Dtzc9", - "vYbsSRiTMtOmYOPn5MhiANFRP1A5/F6qKfpKKyYBfBrNohS5sOUqTDsGEgAGD7FyYVeDeiHOJ6OEtfCu", - "G0NJSiX72iqEpzU1BTM5QvkNWkLudffKV8bBwzAU6iiakiJqsVWEJkjzMgREd01mTQ0ScpxCGK5flFHy", - "iFVtrIxYJZs/OPU/3C7w1nhYLTblvG5eemQD12DgsW3zW9L87UNF4viBW3YlHEUnN8JBfZJdlj+qMeYW", - "lCXFT01dqOE4pFTTjTCec3P1XE371N+5Z3mWzyp55bWfVYw3O1QrNWcFkJAu6KFPlXIA4N7k10oU7uOC", - "ltiWoCmudXB3008cEDXLeNCG7AVf1YlS86q0YoHZRxIoiAXvbPKcG8Oy2xjznOK6N+O5MPIga6O/y3du", - "+F1Mj3PEZL/tgcjoGB/+UPzjrI84v+jG2Ty7oY0qhHYK0e9ixvgY/KfaMe1yqo/55kuqZ4/B+rhiY9rR", - "Bk4k4bELL9Kbm7jRHx8GfvwI09afW30W63YZxvpUxuicT33CVxd5ncuz68etk7/bZLMb5Dxu4bwwTpLx", - "4vTGZCJ7cxzUlIM5bRJyOdfc/13yZj49O80/OPz9f7L/+Nff/+33f//9f//+b//xr7//n9///ff/FRvF", - "6O3EaSR+lot8XmTH2Xv/6wc8cKjk1QVFAA7dmqxzJi54VQgVEk2c5+wPrkYavxyZyci5l3SAcu/gcIhD", - "xkQ+/el79+vCZMcHR4Nsovnc7b/s3t69/WyQiTmfgrlQ+uJaFKCcW4Z/yQaZquyislQoA+8sSOKHbLjw", - "h9K4FP9WFy6aqYZslEaXr+jpjKeVshvHi6IWaGPDnsfmHn2SdaIlMXNs8b/qnMxd63a3+LcxD2xz/cKr", - "/c5fOq9+3SNLbbh0EfZ5MKWo7BprKk0I0YTzoJCvPmBiCEM2honSwK65FpjprWFR8hxDgMOb2RGfs3T7", - "NrKWKUvuYry6WHrj+ibJgl6LJWDd0ea5gXnkxPyFVVU+26oRSEvLVdDT+L+izgoPCT67YejuVLbfVpr3", - "IFvWWTS7UnzX1PB16y1VVB+XztebaUsVfYS4G+Q91xnOdZaoURO7t574nPInmwnvUpJyzD8fkaUcJ/x2", - "LZTKWAZSVdNZXPfD+Jhqjr1YDfWRTXG2D05iXvOwxzLe2ey9S9vuY12YHXk/zNRHqU0xDHpWB4LHq9qP", - "cQSikam+njjvdbW/f/CAgn3o9CDFsASKquawyvVxWbKGenhYpRaUKfwXprzBuvaCmEqloWBfoyZVofj0", - "Muxs75xLZRlo7pMV68qdUFcfu7zfbPPe2+h4KWGvFNJX1fvgOiaFfGVYXpduz7DG2oEWjvJIMbCX16CX", - "zqY2LPhP5YrQWoMZClCSiioV2Xmupj5iU8sACh6FSEWo+HZAI1VwQuC6FFSzmAzvnH2MlEgyV5NIuRbB", - "IybSgBk2OWAqDeb4ColREF8vmMhb2JSD+WlSYMMmC5OmNlGzxt0K1LxzWldErEt8sbiI1rh2qnPK/LOO", - "y78x73SNlylUK6fMrIyF+faxPjWndBf5Fa27lSvaFAimc0M/vOnUdvkylrZuCaKrodlzkcqtCNXN3nTt", - "cuBNbdp1gm/GTRi9n9UoT7kvdf8j85Ah11QWctu09zO1SJycYkNBqMeomMqXN8FASDO+6A/UfPblBi5P", - "r7AD0YbVWm6hz0r00TEd1wDsHl1L2njRYDsBVfRB9Rlg2QJB21w3lmtLyVZ8ya9QfJsSwLmvWG/uBBwY", - "/4qaTJwGTVrn/WHERJURVYo7PRzbSL7EoknEc3+89AcKCTPWXJT8t9Xmipt29YY/zifDI+73gzmBTZ8o", - "kiuNseJtM8MmQgozC6cZH3sCvwsVB/X6NtCzz3H4Kzci3yDWP79P8EcHqiMp1UaFr8Z3SioEdcn483wn", - "TCg9+jhPol8YkabAuoszt4RYIV7wKpVR+sqAdhM4qKIiqZOnA7bgxiyVLsIjUg3UWY5xG17Vkb5zVEbk", - "IZM6lmiWOLN2kX1wMDouoc4W0vLcNkqhbmjAzoE7zVPp0n9pjkejSQiRCzXqFl7+TH10nnE992kTWOiW", - "DbJS5ODT/vw8358+vz7sjL9cLodTWQ2Vno78N2Y0XZR7h8P9IcjhzM6pllvYsgWtny6izXF2b7g/3MdS", - "zQVIvhDZcXaIf6LEVaTMiC/EKF+v9ZuSpq+rt04K7BZi20WBjlEoYRCHOtjfDygFid/zxaL0+cqjtz5I", - "QYy9je2TRYhIuTbGpdu7ZZ24SPwXBISDmPKa4mHqNiVRAxrLp4ZKfSzH0t1mjO9ksVDCJzlNfXO9zoA1", - "HepBPwwIt6Fwc6FMAqd0WEMJZ16d/lUVq8+Gx3aviy7+sK+R8sdAWbzzra7gwy1SeANAS26YqfIczKQq", - "y1XoA+VcP+9aR2lkZrjW8fGzQEc1Ywn48AELJWFtdiNkMx4SFJFl1jkjahAUcx6V47aG+zE066I2ieAZ", - "sc1ao19DzXuawbCo2Key3AaDNWX3CWR1KhaoUgGLrCkha/ilea5VZZ0A+ScSKIjVWqwMQsUPzBd2RY0T", - "xIRJRalFc27zGZYKAX14d1jyGdh8Vnd6cIjfwnQvx5ju09TBT7D0HluDyoIZpes2qA0POvU6eu/+/YnP", - "4cMmDRI6dLW7XP3jfSbcUnw9hVeRYcAOjwwilK1bL29ukX+6fcZ6JCo9W1dFPnsrNEXraRi3gTgncqJq", - "o9b4zRX1Je0QxexACpN9QYyZFMrql5p+cQnslZ2ecthuDdNSd8ZgM1Utl982/Y1b+HtPZ0j93Ix7i1T3", - "dl6uD6T6OXlbLtybP0Ybo6mckiqi4cbQ4nG7QqOPZBF1jkyjfWTANv5Vj/WETHxWn298MSrcih5tHfMl", - "iHHe8eytCoVBu+jRo94SEj+cs7t4nsPCQoGb4ejgoO9cMTSEaAPkO9xRo+/QKyKEE0xdr1Kzy5dUk68k", - "vFtA7oDGIM+QDiX62TVEbNa7YYR1kRca1pHg4LrwYqP4wH5NfxIZ0uo9laABakF8LMDEZ22m9sruCF+s", - "Czvu4cYTwroxVlhCxAqb1Y9zakzPipGD8NHovc903qJ8fDbwDpZUnTh9N1kHF9Ij8igKKSfqjrJFk5K/", - "hfiJL/rIPirV1GIq5TbyP1fTc/fi3eECC+/saFFysUaF9ZH6iV0qcjCSKou6dcVNX/GbGXeqB0sqVmDv", - "IqvU7UInsIyqKGZxxdFOHBR/Uo8Xzvl7JcmO9lR0Zv9FWerzW1SdzKk/vUlFMuhPYFNRQgyWmM75is34", - "NTCYTCC3odod2wDSCNywJZSlfz9EyRze5sB93HZWzbk05HM0F5tcC95taz/0ZySGuT2Ch3G4neioAXdV", - "s6kumZDGAsejsbDxolOZPtf773XGwq2p1PXGzB8dPK8d5evmUCmOn28Onz+JyjOpRZwwdOwJ+VXd6Y3n", - "tuJluWK8mc53MqjRSgTYm0/tKMqv6NeOTdXereE4ShJJoPdv2HMhwNof0IjSSAIim7Wmw3Ph08CqdXuH", - "uP3PBsyN3vsTua0mZp3xs10X1EPeWTOzziLu0Cqci+4Y61jWB8pbKeYoXYDFVN9wXllbszuQZxe97aVq", - "96z4S9Pt82vxDeffd0Gd3xFN28t9u+nbwM5tjhxp3+5yr8nT7+M/erEWFrfHCa3Utv6NjHQnoL7oCVOn", - "Q+guavcLslG1xkZrwi6A788wmwrPFp91eKwhiVNKzZdmnaOMmMo9NZlscEHEVL6cTLJd9ubdQ6TPfEFJ", - "28p5+QcmoTY4e8H1VZzswp0RT3lmW7D9hJf+aoGg/K1ipbfVwhmzswewmcZXGthU0V2OOPwwTRK5hSLy", - "Vje1n6J/O9dVhl9yL3ezKv8pNvPOPPi4sjOQluoUfGGG44b6tq8eI+eTGVIDL1buLTce9bptFYuIhuBd", - "drW+FiVpskYky/5ozqDu1usdtHvjWlKx/i/uNkvdnD3I+4s6o2sMdHC56kFCmg/28iixOCm8EknIt22n", - "1hOlsktq1Ujr/Dib9J9Y5vwSd7CgUBeEprqhfyna2E5glFDQCTGVinlZsteOlAVewWRmIZt7vrx8Ab1X", - "qpyXKNp4aT63PLuG1moq02FV6+vDe9RrPoOiKsGf5dxeJkZ8ZXjKd/JFlXVuWp+g+kn58Fn7/tEovZgC", - "nfuHny+LsdXJPQH8KeiQJvcUpCChebT/qLeuzEdVvaaj+l1ipwEzKjzG65WhdacfLR2bXjCplj6me/hl", - "VUvYRVw6KBXFhKLGROPK0nWpdLEClwrlLO22G+5YH3Hi9fgRNrZtJeQp4xlcJzIYk0HV/r0SVaP+CQ4n", - "/Er69qK3h6J6ho/TFuczCGN1TyNSW6Q5dDWMe6kRs9Ey9Cnyl6Y3Y+Oe+UPCI5+oll41hcq+t9pqIXKM", - "SMfFvAutphqMGfi73/zl2JpNuCgrDVt1S9AoBmTRiik6dIfRnRRzFtGWbTKa89We2NNV/0nDC77yUZNK", - "/inyBNZu3flz+WPnUQfm6N7RxP1BwsSqSVeSjXruE2Ivfd18WbfyM4wz6kMRm6JNVwgq8tqFiztWPHp3", - "EWRrMNU9UDbzNTUr2ltoVVT5JuPeicmX+PJpePdOqAVs9jR6u4Bpm6nqQcdCOkymSq/o24W88acdbnxC", - "AJm1pvrbNMhBf2vylv5Ao2+hVe4kls8IP7p37/Z32XOQUzsL7dGLv8SdiwtRoBJC+cqZR8Ge/4Su4fWQ", - "Ht4+pKf+qmOrFCu5noKf+v6XOC5oLtx+AYXg7Jz6+c6AIYsx4qhgQ2KjZaRluKG7fY54dPDo9oE+bwhJ", - "DUXaXU2pVxnFi3xNq51pZW2J5bNQTv6pbI4zq/yVM3NlLNOQU4MQ6rSGbfn5HMgSYD8pNE+4ZQKR09wX", - "3Rx4+Htlwpk6Gu2eypa6kBRiCsaiy7ZGY/akblCCTZRPf/oe8fzj6Xffh7vb3aCLkktZVwLvbOrYWTUf", - "Sy5KM8LeJrAMYkloTGKqpT0j6R8ZQHQX3yjcLTKidk8bHOr2lVy3VFfXniRV+xRfwFGHvPz9RF8uiJ28", - "UimlLcK1Qk7Gh7uPoiK82F243W1VQ8JLChRT6zwvho6+iBjSwJbuH6IehhbkdMheGWCXZg2jzS0dl47O", - "dBcTQ1RitZsKWXl35ZDvCd14xpuLp7xMXc1LIa/qe+3x8jnCABVeWrqgyiOlMnQdMGZnjQEko2s1yPTz", - "l1D4jobOlaptwCYM0IgQQuqaCDnzAHFm4s2EwLQuwuMaeFpYxJeo7CoyYpLeqvhIXeSzqyT5A4RI8h6b", - "FLx1T2NHJIdxKFq32QyCdxNcFX/xCy3xbu0VvCepuWQuxoG/fcttHQ1OQRq/44lSXNcL28rpj53P5Kbx", - "5k90RNIesIm5+kRIypIjKBp5g+8aK8qyASHaHjje6H24BOrD6D3+Rfy2oXYzvg9GaXjimXDN3dr5ei+8", - "SLnrm4VXb1TyOehecv4brN9PVl9ulZg1rH6XWZvb3t7c+o7r3AHUX7DcXN1013ZP3JGmuasoeWtVy6qM", - "NsomqV1z5H9uZhy83+BMtW/68XeHFjABzeqrsEg3IzZQy7/ODva/fZ01Eam6fSI6CGNnI6xXYtDyTG25", - "UfuGVnJqi+B0UsFLo2gMo+agJDAoDY7TdE1MgYncgggkx75B4f/Yo2n2nnC599Stc+8VDpAlcBhdGJ3C", - "odJiKiQvcU43Pl5RTW0ZSxW3cazvaBO2bq8opL9jTcTiGjst1vc2csm4wDcKGFd0d+4Oa3vpAdt75gHL", - "tpbF72LIqNyC3TNWA5//UTGoox1jUP6Q8tttr3t2bDFilF5+dO9hcgTtP3cOAPZ4YGOwS/DM7tEZ1Z6H", - "gnSfzu5vocftrztypzaWAy+je3M/0WW7dSnXll0bdmCzczzj+eiOm30M7sN6/vGqte/IlLjs3ULHDG9l", - "pyYtJF1idPiV3BUNREEWOrzs1ztReKXzEPfnROlcjMsVy0vlW8f+cH5+ynIlJeSY+Oibf9MRmRe8vnGa", - "adELGLzjuWWGz8GbkFZhy1eMYKrKWXf0gRm+loGqX+FNv7SbPC+MIUUBNlbFqleVxmdeGJys3YouWnxA", - "y/1MCpV6VY2yKOmne6tcK1G+0/0mBOpqeYY1I13R+6Mah5w0PBz7tQItwAyijjiDtT4Cw1altEkM+vj0", - "pN2TJ05JUvN5JX3TXifSuy2d1jLmExP4YNyLGib2+PRkUGdbtwqN3KTUZsYtw9FWqzJA1JkMc7sTxgUR", - "rJ4FebzhNo9BjOe43+kqRXJz4zk8g3x48+H/BwAA//+COMxOdZ4AAA==", + "H4sIAAAAAAAC/+R97XIbt7Lgq6DmblWSWoqUJdmOdf6sjx0n8rFjrSWfbNWxSwJnmiSsIcAAGMmMy1X3", + "IfZNdm/V/tj7a18g94220A3MYDgYkrItRSc3PxxJMwM0uhv9he7GxyxX84WSIK3JDj9mJp/BnOOPj40R", + "UwnFKTcX7vcCTK7Fwgols8PWUyYM48y6n7hhwrrfNeQgLqFg4yWzM2C/KH0BepgNsoVWC9BWAM6Sq/mc", + "ywJ/Fhbm+MN/0TDJDrN/GTXAjTxkoyf0QfZpkNnlArLDjGvNl+7392rsvvZ/NlYLOfV/P1toobSwy+gF", + "IS1MQYc36K+JzyWfpx+sH9NYbquNy3H4O6E33Yq4uegHpKpE4R5MlJ5zmx3SHwarL34aZBp+rYSGIjv8", + "R3jJIcevpYYtWsIKliKUxFANGnq9q+dV4/eQWwfg40suSj4u4bkan4C1DpwO55wIOS2BGXrO1IRx9lyN", + "mRvNJBhkpkROP7bH+WUGkk3FJcgBK8VcWOSzS16Kwv1bgWFWub8ZYH6QIXslyyWrjIORXQk7Y4Q0nNzN", + "XbNgB/mrzFbAhFel7cJ1OgPmHxIczMzUlfTAsMqAZlcO9gIs6LmQOP9MmICSIQ0fjZmeov7LyCpVWrHw", + "EwnZTOT4UU94DjgoFMK6pdOIHv4JLw0Musi1M9AOaF6W6oq5T1cBZXxi3TszYO/VmM24YWMAyUw1ngtr", + "oRiyX1RVFkzMF+WSFVACfVaWDD4IQwNyc2HYRGka+r0aDxiXhRMgar4QpXtH2OFb2TD6WKkSuMQVXfKy", + "i5/jpZ0pyeDDQoMxQiHyx8Dc2xW3UDgcKV3QAgMdAFfSJl0NV02bQZc1LmDZheGoAGnFRID2g9QsP2Dz", + "ylgHTyXFrxUxoifae78RkvO4jcH1NLEXHsslgw9Wc8b1tJo7CRP4bbxYDt2HZnii5nBMe2v57Xcsd2So", + "DBTuzVwDt0BL9ftvGcHQbPFGslyDhcR8DoXgFsol0+CGYhyXWsBESOE+GDhBgNO7KQeIE1VZDxHXVuRV", + "yXVNhx5+MNU4iM91UjchqE78l/VWv/YIp/7zS2GE32TXHOHv7ktROgG8KsUdj3nItpS8Jw0qVgRwNd5x", + "TwjjxHMBrexJpTVIWy6ZcqKSh3GRiSNhaYbs/KfHJz/98PTs2dGLH86OH5/+dE6GQCE05FbpJVtwO2P/", + "lZ2/zUb/gv+9zc4ZXyxAFlAQCUFWc7e+iSjhzL2fDbJC6PAj/tkrrRk3MyjOmjffJfZIH126MtRjIFp9", + "tDFJQ3DDjp6GLYPLdoLjr6WDXw/Zz4pJME6cGKur3FYaDPsWNYQZsELkbiquBZjvGNfATLVYKG1Xl+6B", + "HzjjYX/PLbpU3GYD5OttFxmxTrwza2YcpLSnVagy2hKOnftvzg8ZL6/40uBLQ3aOch3l6fkhsQd+7UXX", + "myPS5YhQrwE0+7YUF8B4QBrjRbGj5HdDdn4F49QwVzButBZy3ZxLPgUn1AZsXFkmlSUF6mchtYR8PGTn", + "M1EU4ACUcAkah/7LKi970eggJSXjXkTkoAHrZpe8bMuaQK0GoTRThkLH4yUbZFcw3kizNEcGI6jhEzKe", + "hWEvEQWaNKOwKBH53OmthMVU8jGU17Nk/Uq3t8JTll7HSFoRYX4bE3jRnJvkmcNWQue9EMaGDYwSqR9v", + "XRwF6/bzVnzaUhQ9y22mSC0wuDGdZfkHTIMzXlCTc2bIZvbGt+Nf+AB5ZWGTe9Xvu9QMFD0O4KUJF32S", + "WtEPWivdXc+PIEGLnIF7zDSYhZIGUo5gkdgTP52eHjPyVph7o7YS6oHYkduxeVkVZNY5bCz4slS8YMbt", + "c24bBBK0Ldw6WxRBE5L8KqHk8K184ia7v7vvVBoaSShx0EDklo+5AfdkXJnlkDlzHAENQLErUZYsV9Jy", + "IRln37wGq5c7j525/A29OgOO5qcDT8hC5NyC8Qb11UzkM2bFnCxSRwowluVcOt2kwWrhbOtnylnmQfr5", + "AYVB+ejYhDsdHETGN4ZViyD48lKAtGj7KmbUHJz9OWUauFESJSRKbfhAm0Dwko15fqEmE5KFtQMaNFbX", + "+52DMXya4r0V5kK6N++nOOtZyecgc/V30Mb7Q1ty+WXzxXoowoteRqageE7RBV6WrybZ4T/WS4uT4AK5", + "rz4NVgHmuRWXta6OGf5p81uwz0puLAtfMOfMeEcp6SSQJZ8SLO4B+kJiDsby+SKmZMEt7LgnqTFFYrg3", + "b46eBgifY2xhQ1hi24iI0yh1QKRaFOnVnIZFOBgQQ/TqcMtFrdAfAQ6oa6aNIiU1yd59ekfc8NdS5Rel", + "MLZfN12hWDZeCmnAvYkONRQsB43yAQNnpMGUkxZmAbmYiDyQeCv1FMPzg7R6mYpZdF/qbKX1EShaz9nn", + "hKGaT+OAUs9GewmWOzmLe6Uo0EPk5XEb0lXgVlxiPRZWc71kcz+Yd1/MkL1UGpXpooQPse3uJexcFVCS", + "FVE5xcHO+XA8zM8d9WgLBY/+AtBLhg/cjeWxies4zE4WWlhgz7SYzpw1XxnQQ5hzUTqol2MN8r+NvSuh", + "9DS8QbIsO8EX2In9f//3EsqImC08nUR2WxpPVlfQ8229G4NpiyyOQT4uc4cBivctSrD+Z0nIEkruTLig", + "N+ofFtwpymyQ/VpBhT9wnc/EZfQj+Tk0/I7Xa/gYf66AnlcOJzvxbEmLul7DkxmXU+jyMumzdPiMnkXx", + "HW9j4FDDryK9VjZALUk8WD2sf8rNhTmp5nOul6ng6XxRiomAgpVexlAALbheQ/aEzA4ybfBh4za5Pzk7", + "x70O3BkZ3Fx0bTH8amvLGEPYHuAtjGLTt3Lz3yugNUf7CSO72eF9ZyE0MqFvl30aZBjWOxsvMfS9Ksbf", + "hZ/OhGxxfM2ynpvffep4VQTIx2wupJi7DXMvbfd8seR6JkpnBY4byTUIcujF0d9+aMRQMkCnJhMDbUB3", + "U4A2ePp4jai32VLg9K0oiraY66wqotrqlngNttKSXHzHXhTX52FHC28v4RKuo06jU5lVju7n3tdg/KFA", + "x9/cfkORzfiZG8m7vE+UnIhppblNWsxmxudc/oDGfpE8W6HY7QzYCb7KJqIEZjWXZgKaPT4+wmBfcIqH", + "6WisVZpP4YXKefog42kdKkQfy0ljxyE4l/94uNGyWJ1lsLK6NJaWfwNYvK6kTB5SHdUu2VWECrJh2Jwv", + "2QXAgmn6HJ+lJem8M08XS42a6tE5pN9e1+pyDbTB3Y21GasVbW230EKG7MgyM8MjmsqQs3lOjxzzwzlz", + "S/FOQ3xOQg6qmwRjaVPl/pXwwQ7ZkffPhWHnThScD9h5Gwnn7OWbk1NnZ53jucF5Opa/QuQVRNZY68NR", + "iuivYSqMBQ0FhUu624IXhQZjrnkMXHLrbOE0BdXEXnENa8i7SRz8UlOExFEd5jqr7WhzPSn+RQfJPhoU", + "UBUfJgdEDLKcjhEQwizCQg/0KWqdQF5pYZd1XGllZ20bYFgXWSDZ9mQG+YWqEn7cCaCJ5eSR1yt2BkKz", + "k58e791/wHL3oanmA2bEb3g2MF5aMBRzKcA4EFjp5VIITuV+tuacZMWFwNkwwoCnHIdZc0o2nCoSb9lh", + "tn9/vHvw6F6+93C8u7+/X9ybjA/uT/Ldh98/4vf2cr77YHyveHCwW+zdf/Do4fe74+93HxZwf/egeLi7", + "9wh23UDiN8gO7x3sHWCIgmYr1XQq5DSe6sH++OFe/mB//Ohg72BS3NsfP9p/uDsZP9jdffBo9/vdfJ/f", + "u//w3sN8ss+Lg4O9B/v3x/e+f5g/4N8/ur/78FEz1d7DT13TKmDkGAHoHOZyO3NSWJOA8votyK344DKM", + "g3INY4Qld/ZdCHt5TVYTAI+nuGG515VQUHSlnmTIjiRTZQGa+QCRCSEPPxbOe8UNe18ZSkB4Wy+HHT19", + "m5HtHYwQPwoTdTSPExQYbzv3Zu2OKavpyOQgYcftthGdE+8cPW3LymaDe5bZ0r4g2J+JEk4WkG80NWjw", + "QZtMm3dTYwqlvC/3jJyWFaqkMkA+gz18LGeVMU7xV0J9ISYT0BgInXHJrpzqdKSs1eXAMUc8KIZ1QZpK", + "O8L50/tmG2MgGMn5VZgvRerV4Ol2JKlJ3RVwPtbEQ8CRk/HlZZUHOjLF2qRZJEkSLLGwV+IRA8RJD3vG", + "ExC2RW08ZnIMlDMfuw4ItGV0Imi9albOeJBbg2yxHYJ/EXbWxFW2QvXAW1M5irNxD+oHTGnnIQ1YAQuQ", + "BWZOSTwKJPX7J6fNtrZSRI6eKEyHqnFwYB15O+GySl5IdSUxXFwqXpBd6gjWsj+b9dNgrwkaTNLx9upn", + "Gx5oaLRw12tL3JDRcCsGwi2ot37it+lFB3xprUbUmmg1Z5zp6LOgUgYxKb2PptrbHfSlszue4VD1sQEy", + "mtMk/jX3N/jgDz1xQjoobA5Xb4sHmo1Z74ebYYt4onq7fWVeicT3l3INZbm2BcfKFvf0v67O/VqCcI3Q", + "U/kF2KNXz9X4DUZQkzlkBmydvDtgxtlR6hI0C1/TiTnlA1EgwgzZM6fG4AoDdQNn8MKlUJU5I2jOycIa", + "N8xNRlAbAV/pNDL48+2BfubzODEunYbZAvpaocQ4ZbxO0rqfDNBqmGgws7M6GL825hMd63vPyH9PxwC0", + "mm8MHQh4OxiTvqT1SVbG+CNUM/D2NP7qLA08KhCyEJeiqDidKrArnGUKEjTFgRSbc7kMg/iU24XmuRU5", + "L3szNq+PxP4E+eueFn/BYXHiiNinyEdJ9G0arttrbkP1J3yfgMTjyHpvEamNcyDORyb69pzBJbo0mEVr", + "lc+eCzonetM9dHvT02vInoQxKelvCjZ+To4sBhAd9QOVw++lmqKvtGQSwGcoLUqRC1suw7RjIAFg8BAr", + "F3Y5qBfifDLKBQzvujGUpCy9b61CeFpTUzCTI5TfoSXkXnevfGMcPAxDoY6iKSmiFhtFaII0r0JAdNs8", + "4dQgIX0shOH6RRnl5VjVxsqIVbL5g1P/w80Cb4WH1WJdOvH6pUc2cA0GHts2vyXN3z5UJI4fuGUXwlF0", + "ci0c1CfZZflcjTFtoywpfmrqGhjHIaWaroXxlJuLF2rap/5OPcuzfFbJC6/9rGK82aFaqTkrgIR0QQ99", + "FpoDAPcmv1SicB8XtMS2BE1xrYO7m9njgKhZxoM2ZC/5ss5Bm1elFQtM7JJAQSz4YJPn3BiW3cSYpxTX", + "vR7PhZEHWRv9Xb5zw29jepwiJvttD0RGx/jwh+KfZ33EqVvXTpTaDm1UfLVViH4bM8bH4L/UjmlXqn3O", + "N7epnj0G6+OKtRldaziRhMc2vEhvruNGf3wY+PEzTFt/bvVVrNurMNaXMkbnfOoLvjrL61yebT9unfzd", + "JJtdI510A+eFcZKMF2eOJmsEmuOgptLOaZOQJrvi/m+TN/Pl2Wn+wf7v/5P9x7/+/m+///vv//v3f/uP", + "f/39//z+77//r9goRm8nTiPxs5zl8yI7zD76Xz/hgUMlL84oArDv1mSdM3HGq0KokGjiPGd/cDXS+OXI", + "TEbOvaQDlHt7+0McMiby8c8/ul8XJjvcOxhkE83nbv9l93bu7WaDTMz5FMyZ0meXogDl3DL8SzbIVGUX", + "laUaJPhgQRI/ZMOFP5TGpfi3unDRTDVkozS6fLFUZzytlF07XhS1QBsbdjw2d+iTrBMtiZljg/9V52Ru", + "WxK9wb+NeWCT6xde7Xf+0iULqx5ZasOl69tPgylFFe1YrmpCiCacB4VSgAETQxiyMUyUBnbJtcAkeg2L", + "kucYAhxez474mlXxN5EQTllyZ+Plmc9wvlayoNdiCVi3tHmuYR45MX9mVZXPNmoE0tJyGfQ0/q+oE+5D", + "gs92GLo7TQNuKoM+ZINfh+LbZt2vWm+pfgVxV4J6M21oUBAh7hp5z3WGc50latTE7qwmPqf8yWbCu5Sk", + "HPPPZ2Qpxwm/XQulMpaBVNV0FpdUMT6mcm4vVkPpaVP37oOTmNc87LGMtzZ779K2+1wXZkveDzP1UWpd", + "DIOe1YHg8bL2YxyBaGRqXUCc97ba3d17QME+dHqQYlhdRgWJWED8uCxZQz08rFILyhT+C1PeYF15QUyl", + "0lCwb1GTqlDXex52tnfOpbIMNPfJinVRVGhZELu8323y3tvoeCVhpxTSNyzwwXVMCvnGsLyuip9h+boD", + "LRzlkWJgry5BXzmb2rDgP5VLQmsNZihASSqqVGTnhZr6iE0tAyh4FCIVoZjeAY1UwQmB61JQOWgyvHPy", + "OVIiyVxNIuVKBI+YSANm2OSAqTSY4yskRkF8KWYib2FdDuaXSYE1myxMmtpEzRq3q/3zzmldEbEq8cXi", + "LFrjyqnOMfPPOi7/2rzTFV6mUK2cMrM0Fuabx/rSnNJt5Fe07lauaFN7mc4N/fSuU9vly1jauiWIroZm", + "L7Ypzuty4HVt2lWCr8dNGL2f1ShPuS91/zPzkCHXVBZy07T3M7VInJxiTa2tx6iYylfXwUBIMz7rD9R8", + "9eUGLk+vsAPRmtVabqHPSvTRMR3XAGwfXUvaeNFgWwFV9EH1FWDZAEHbXDeWa0vJVvyKX6D4NiWAc1+x", + "lN8JODD+FTWZOA2atM77w4iJKiMqwnd6OLaRfIlFk4jn/njuDxQSZqw5K/lvy/UVN+3qDX+cT4ZH3EoJ", + "cwKbFlwkVxpjxdtmhk2EFGYWTjM+9wR+GyoO6vWtoWef4/BXbkS+Rqx/fZ/gjw5UR1KqjQrf6MApqRDU", + "JePP850wofTo8zyJfmFEmgLrLk7cEmKFeMarVEbpGwPaTeCgioqkjp4O2IIbc6V0ER6RaqCmfYzb8KqO", + "9J2jMiIPmdSxRLPEmbWL7JOD0XEJNQ2Rlue2UQp1rwh2CtxpnkqX/ktzOBpNQohcqFG38PI1tSh6xvXc", + "p01goVs2yEqRg0/78/P8ePzicr8z/tXV1XAqq6HS05H/xoymi3Jnf7g7BDmc2TnVcgtbtqD100W0Oczu", + "DXeHu1iquQDJFyI7zPbxT5S4ipQZ8YUY5au1flPS9HX11lGBjVhsuyjQMQolDOJQe7u7AaUg8Xu+WJQ+", + "X3n03gcpiLE3sX2yCBEp18a4dHu3rBMXif+CgHAQU15TPEzdASbq7WP51FCpj+VYutuM8YMsFkr4JKep", + "71vYGbCmQz3opwHhNhRuLpRJ4JQOayjhzKvTv6pi+dXw2G4j0sUftoxS/hgoi3e+1RV8ukEKrwHoihtm", + "qjwHM6nKchlabDnXz7vWURqZGa400/wq0FHNWAI+fMBCSVib3QjZjIcERWSZVc6Iei/FnEfluK3hnoc+", + "aNSBEjwjtllr9GuoeU8zGBYV+1SWm2Cwpuw+gaxOxQJVKmCRNSVkDW+b51pV1gmQfyaBglitxcogVPzA", + "fGGX1DhBTJhUlFo05zafYakQ0Id3hyWfgc1ndacHh/gNTPdqjOk+TR38BEvvseuqLJhRuu4w2/CgU6+j", + "j+7fn/kcPq3TIKH5WbuB2D8+ZsItxddTeBUZBuzwyCBC2ar18u4G+afbwq1HotKzVVXks7dCv7meXnxr", + "iHMkJ6o2auMuP77la4coZgtSmOwWMWZSKKtfalrxJbBXdtr1YSc7TEvdGoPNVLVcft+0jm7h7yOdIfVz", + "M+4tUt2bebk+kOrn5E25cO/+GG2MpnJKqoiGG0P3zM0KjT6SRdSUM4320bjdHasEOoNo0+A1zNUltHpp", + "3SY1bkSfNktJUOS0WpRg2LdXPlms7v31nc+X14iRqKinxuMw6+rWg/5ABc9zWGARK0irBRg245dADbr9", + "JLer595I+LCA3EJBDReHK1xJvFBD68uo3PaOUJBg0LWb+4/hq5vb5WuZC/2lNQw245ZNlSV8RpkNuPXv", + "EiuQgMLeh32N9MIakE0KhV5dsp9eq1niGs3i/BXTsFrtZgbkJEScAduEkHocRNTTJ/UR7j+3aGtlMqSk", + "Wyd4aVWofdzGVTjorZLzwznXMgg2pMrB3l5f6kToedMGyPdHpWsiQjucEDE1dUlerRH/+G2xhmlrWb+y", + "yLAuCrSt4eC6tmytEMWWdH8SAdpqr9cjQwnBAkycTmA6EuGOiUvu4cYkiLr3X1hCxArbyMH0ipGD8NHo", + "oy/m2GBf+4KHLZzFujbkbrIOLqRH5NFBi5yoO8oWTdXRBuInvugj+6hUU4vZ4pvI/0JNT92Ld4cLLHyw", + "o0XJxQoVVkfqJ3apKIbSY4HbSsu4ZTh+M+NO9WDV2BLsnTW4uLFsAldRodgsLqrcioPiT+rxQipTryTZ", + "0p6K0pJulaW+vkXVSQ7905tUJIP+BDYV5fxhFf2cL8m1hskEchsaemCnUxqBG3YFZenfDwcBDm9z4P5o", + "albNuTQUVmmuxboUvHspytAfAxvm9gjmG+B2Ih8Jd1Wzqc6ZkMYCx9P/sPGig+e+6OLf66SsG1Opq239", + "P/t8sI4FXjbn5vER4foTwidRBTp1wRSGMjsgv6ibWfLcVrwsl4w30/lmLTVaiQA786kdRSlk/dqxKUy+", + "MRxHeXAJ9P4N28oEWPtjtlGmXEBks9b0CUT4NLBq3cEm7nC2BnOjj3XD+E/bYHErXRD3oL+bZmZdKNGh", + "VUj92DKce1XnzGykmKN0ARarGUJKRm3NbkGebfS2l6rddJjbptvX1+JrUnzugjq/I5q2l/u207eBndsc", + "OdK+o+9OU4rUx3/0Yi0sbo4TWtm7/RsZ6U5A3eoheqcJ8jZq9xbZqFpho84pAYHv0zSaIvYWn3V4rCGJ", + "U0rNl2aVo4yYyh01maxxQcRUvppMsm325t1DpE/uQ0nbSuv7B+bZNzh7yfVFnM/HnRFPqbQbsP2El/72", + "lKD8rWKlt9VCGo2zB7Bf0Dca2FTRTcA4/DBNErmBIvJGN7Wfon8714XUt7mXu4nj/xSbeWsefFzZGUhL", + "pVi+9sxxQ31XZI+R88UMqYEXS/eWG4/aebfq4URD8C67Wl9ulzRZI5JlfzRnUAP/1UsCeuNaUrH+L+42", + "S12fPcj7iy5/0Bjo4HLZg4Q0H+zkUe1EUngl6ixu2k6tJ0ol0NWqkdb5eTbpP7HM+SVu0kOhLgh9w0OL", + "ZrSxncAooaAkGKqG9bJkpx0pC7yC9RpCNrdEevkCeqdUOS9RtPHSfG15dgmt1VSmw6rWt8DoUa/5DIqq", + "BH+Wc3PJZsYhAIreoxZfN16n3/YJqp+VD5+1b6+OKigo0Lm7//UStVuXVSSAPwYdMoGfghQkNA92H/WW", + "zvqoqtd01KKA2GnAjAqPw12C0Y2wtHTs68OkuvIx3f3bVS1hF3HpoFQUE4p6r40rS5dt090xXCqUs7Tb", + "rrljfcSJ1+NH2Ni0lZCnjGdwnUjSTgZV+/dKVHD/Jzic8Cvp24veHopKtj5PW5zOIIzVPY1IbZHm0NUw", + "7qVGzEYh+clQuDEaG/fMHxIe+UK19KbpxeDbRy4XIseIdNyvYKHVVIMxA3+9pZsc9c6Ei7LSsFG3BI1i", + "QBatmKJDdxjdSTFnEW3YJqM5X+6IHV31nzS85EsfNanknyJPYOVisT+XP3YaNZmPbq1OXJEmTKyadCXZ", + "qOfKNPbKtwYp626lhnFGrXZiU7RpfEN1rNtwcceKR+8ugmwFprrN03q+pn5sOwutiipfZ9w7MfkKXz4O", + "794JtYD97EbvFzBtM1U96FhIh8lUdSl9u5DX/rTDjU8IILNyb8gmDbLXf/tCS3+g0bfQKncSyxe9HNy7", + "d/O77AXIqZ2FGyCKv8TN2QtRoBJC+cqZR8GO/4QucfeQ7t88pMf+onyrFCu5noKf+v5tHBfULRPYSygE", + "Z6fUsnwGDFmMEUcFGxJ7ySMtyfVZPUc82Ht080CfNoSknkntxs3UjpHiRb5s3860srbEDgFQTv6pbI4T", + "q/ytWnNlLNOQUw8kaiaJydd8DmQJsJ8VmifcMoHIqRbhtLc58PBXZ4UzdTTaPZUtNVoqxBSMRZdthcbs", + "Sd2DCfvEH//8I+L5+fEPPzLPSm7QRcmlrJsdbG3q2Fk1H0suSjPC9k1wFcSS0JjEVEt7RtI/MoDoutFR", + "uD5pRB3t1jjU7VsHb6h0uD1JqrwzvmOoDnn5K9huL4idvDUupS3CzWlOxofr3aI649hduNltVUPCSwoU", + "U3dQL4YObkUMaWBX7h+iHoYW5HTI3hhg52YFo81FROeOznTdHENUYkGvCll5d+WQ7wld6sibu/W8TF3O", + "SyEv/GVHxKAeA1RbbukOPo+UytCN503hE90cRKafv2fHN211rlRtAzZhgEaEEFJXRMiJB4gzE28mBKZ1", + "1yfXwNPCIr4naluREZP0RsVH6q6ybSXJHyBEkld1peCt27Y7IjmMQ9G6sGsQvJvgqvi7rWiJd2uv4FVw", + "zT2aMQ78BYNu62hwCtL4HU+U4rpe2EZOf+x8JjeNN3+iI5L2gE3M1SdCUpYcQdHIG3zXWFGWDQjR9sDx", + "Rh/DPXefRh/xL+K3NeXp8ZVXSsMTz4Qr7tbWNxjiXfFd3yy8eq2q9kFnXvEbrF7BWN/fl5g1rH6bWZsL", + "Ld/d+I7rXHPW35OhuZ3uru2euOlWcx1b8mK+llUZbZR1UrvmyP/czDj4uMaZal9m5q9HLmACmtW3/ZFu", + "Rmygln+b7e1+/zZrIlJ1h1h0ELCYerUSg5ZnasuNOtS0klNbBKeTCl4aRWMYNQclgUFpcJymMWwKTOQW", + "RCA59g0K/8cOTbPzhMudp26dO29wgCyBw+hO/BQOlRZTIXmJc7rx8RZ+6jxbqrhTbX0NpbB1B1kh/TWS", + "IhbX2Ey2vpqWS8YFvlHAuKLrwbdY2ysP2M4zD1i2sfPHNoaMyi3YHWM18PkfFYM62DIG5Q8pv9/0umfH", + "FiNG6eUH9x4mR9D+c+cAYBsbNgZ7BZ7ZPTqj9hqh54ZPZycA8P5YpTtypzaWAy+je3M/cZFA697BDbs2", + "7MBm53jG89EdN/sY3If1/ONla9+RKXHeu4UOmaPZOfWhIukSo8Ov5K5oIAqy0OFlv96Jwiudh7g/J0rn", + "YlwuWV4q3x37p9PTY5YrKSHHxEd/vwEdkXnB63tDmha9gMEHnltm+By8CWkVdrXGCKaqnHVHH5jhWxmo", + "+g1eZk67yfPCGFIUYGNVLHtVaXzmhcHJ2q3oosUHtNzPpFCpHd8oi5J+uhdnthLlOw2+QqCulmdYM9IV", + "vc/VOOSk4eHYrxVoAWYQNf0arLRKGbYqpU1i0MfHR+22Y3FKkprPK+n7kjuR3u1at5Ixn5jAB+Ne1jCx", + "x8dHgzrbulVo5CalTlpuGY62WpUBos5kmNudMC6IYPUsyOMNt3kMYjzH/U63xZKbG8/hGeTTu0//PwAA", + "///7VfgJs6QAAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/pkg/api/openapi_types.gen.go b/pkg/api/openapi_types.gen.go index c29147a9..227e32ea 100644 --- a/pkg/api/openapi_types.gen.go +++ b/pkg/api/openapi_types.gen.go @@ -241,6 +241,15 @@ type Job struct { Updated time.Time `json:"updated"` } +// List of workers that are not allowed certain task types on a specific job. +type JobBlocklist []JobBlocklistEntry + +// JobBlocklistEntry defines model for JobBlocklistEntry. +type JobBlocklistEntry struct { + TaskType string `json:"task_type"` + WorkerId string `json:"worker_id"` +} + // Arbitrary metadata strings. More complex structures can be modeled by using `a.b.c` notation for the key. type JobMetadata struct { AdditionalProperties map[string]string `json:"-"` @@ -611,6 +620,9 @@ type SubmitJobJSONBody SubmittedJob // QueryJobsJSONBody defines parameters for QueryJobs. type QueryJobsJSONBody JobsQuery +// RemoveJobBlocklistJSONBody defines parameters for RemoveJobBlocklist. +type RemoveJobBlocklistJSONBody JobBlocklist + // SetJobStatusJSONBody defines parameters for SetJobStatus. type SetJobStatusJSONBody JobStatusChange @@ -653,6 +665,9 @@ type SubmitJobJSONRequestBody SubmitJobJSONBody // QueryJobsJSONRequestBody defines body for QueryJobs for application/json ContentType. type QueryJobsJSONRequestBody QueryJobsJSONBody +// RemoveJobBlocklistJSONRequestBody defines body for RemoveJobBlocklist for application/json ContentType. +type RemoveJobBlocklistJSONRequestBody RemoveJobBlocklistJSONBody + // SetJobStatusJSONRequestBody defines body for SetJobStatus for application/json ContentType. type SetJobStatusJSONRequestBody SetJobStatusJSONBody diff --git a/web/app/src/manager-api/ApiClient.js b/web/app/src/manager-api/ApiClient.js index 482fc957..aad56431 100644 --- a/web/app/src/manager-api/ApiClient.js +++ b/web/app/src/manager-api/ApiClient.js @@ -55,7 +55,7 @@ class ApiClient { * @default {} */ this.defaultHeaders = { - 'User-Agent': 'Flamenco/41b0ee15 / webbrowser' + 'User-Agent': 'Flamenco/81563c07 / webbrowser' }; /** diff --git a/web/app/src/manager-api/index.js b/web/app/src/manager-api/index.js index bfd1b457..1612f064 100644 --- a/web/app/src/manager-api/index.js +++ b/web/app/src/manager-api/index.js @@ -25,6 +25,7 @@ import Error from './model/Error'; import FlamencoVersion from './model/FlamencoVersion'; import Job from './model/Job'; import JobAllOf from './model/JobAllOf'; +import JobBlocklistEntry from './model/JobBlocklistEntry'; import JobStatus from './model/JobStatus'; import JobStatusChange from './model/JobStatusChange'; import JobTasksSummary from './model/JobTasksSummary'; @@ -183,6 +184,12 @@ export { */ JobAllOf, + /** + * The JobBlocklistEntry model constructor. + * @property {module:model/JobBlocklistEntry} + */ + JobBlocklistEntry, + /** * The JobStatus model constructor. * @property {module:model/JobStatus} diff --git a/web/app/src/manager-api/manager/JobsApi.js b/web/app/src/manager-api/manager/JobsApi.js index dd114755..e84bb7f8 100644 --- a/web/app/src/manager-api/manager/JobsApi.js +++ b/web/app/src/manager-api/manager/JobsApi.js @@ -17,6 +17,7 @@ import AvailableJobType from '../model/AvailableJobType'; import AvailableJobTypes from '../model/AvailableJobTypes'; import Error from '../model/Error'; import Job from '../model/Job'; +import JobBlocklistEntry from '../model/JobBlocklistEntry'; import JobStatusChange from '../model/JobStatusChange'; import JobTasksSummary from '../model/JobTasksSummary'; import JobsQuery from '../model/JobsQuery'; @@ -91,6 +92,52 @@ export default class JobsApi { } + /** + * Fetch the list of workers that are blocked from doing certain task types on this job. + * @param {String} jobId + * @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link Array.} and HTTP response + */ + fetchJobBlocklistWithHttpInfo(jobId) { + let postBody = null; + // verify the required parameter 'jobId' is set + if (jobId === undefined || jobId === null) { + throw new Error("Missing the required parameter 'jobId' when calling fetchJobBlocklist"); + } + + let pathParams = { + 'job_id': jobId + }; + let queryParams = { + }; + let headerParams = { + }; + let formParams = { + }; + + let authNames = []; + let contentTypes = []; + let accepts = ['application/json']; + let returnType = [JobBlocklistEntry]; + return this.apiClient.callApi( + '/api/jobs/{job_id}/blocklist', 'GET', + pathParams, queryParams, headerParams, formParams, postBody, + authNames, contentTypes, accepts, returnType, null + ); + } + + /** + * Fetch the list of workers that are blocked from doing certain task types on this job. + * @param {String} jobId + * @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link Array.} + */ + fetchJobBlocklist(jobId) { + return this.fetchJobBlocklistWithHttpInfo(jobId) + .then(function(response_and_data) { + return response_and_data.data; + }); + } + + /** * Fetch a summary of all tasks of the given job. * @param {String} jobId @@ -359,6 +406,57 @@ export default class JobsApi { } + /** + * Remove entries from a job blocklist. + * @param {String} jobId + * @param {Object} opts Optional parameters + * @param {Array.} opts.jobBlocklistEntry Tuples (worker, task type) to be removed from the blocklist. + * @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing HTTP response + */ + removeJobBlocklistWithHttpInfo(jobId, opts) { + opts = opts || {}; + let postBody = opts['jobBlocklistEntry']; + // verify the required parameter 'jobId' is set + if (jobId === undefined || jobId === null) { + throw new Error("Missing the required parameter 'jobId' when calling removeJobBlocklist"); + } + + let pathParams = { + 'job_id': jobId + }; + let queryParams = { + }; + let headerParams = { + }; + let formParams = { + }; + + let authNames = []; + let contentTypes = ['application/json']; + let accepts = ['application/json']; + let returnType = null; + return this.apiClient.callApi( + '/api/jobs/{job_id}/blocklist', 'DELETE', + pathParams, queryParams, headerParams, formParams, postBody, + authNames, contentTypes, accepts, returnType, null + ); + } + + /** + * Remove entries from a job blocklist. + * @param {String} jobId + * @param {Object} opts Optional parameters + * @param {Array.} opts.jobBlocklistEntry Tuples (worker, task type) to be removed from the blocklist. + * @return {Promise} a {@link https://www.promisejs.org/|Promise} + */ + removeJobBlocklist(jobId, opts) { + return this.removeJobBlocklistWithHttpInfo(jobId, opts) + .then(function(response_and_data) { + return response_and_data.data; + }); + } + + /** * @param {String} jobId * @param {module:model/JobStatusChange} jobStatusChange The status change to request. diff --git a/web/app/src/manager-api/model/JobBlocklistEntry.js b/web/app/src/manager-api/model/JobBlocklistEntry.js new file mode 100644 index 00000000..02d5f7b1 --- /dev/null +++ b/web/app/src/manager-api/model/JobBlocklistEntry.js @@ -0,0 +1,83 @@ +/** + * Flamenco manager + * Render Farm manager API + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + * + */ + +import ApiClient from '../ApiClient'; + +/** + * The JobBlocklistEntry model module. + * @module model/JobBlocklistEntry + * @version 0.0.0 + */ +class JobBlocklistEntry { + /** + * Constructs a new JobBlocklistEntry. + * @alias module:model/JobBlocklistEntry + * @param workerId {String} + * @param taskType {String} + */ + constructor(workerId, taskType) { + + JobBlocklistEntry.initialize(this, workerId, taskType); + } + + /** + * Initializes the fields of this object. + * This method is used by the constructors of any subclasses, in order to implement multiple inheritance (mix-ins). + * Only for internal use. + */ + static initialize(obj, workerId, taskType) { + obj['worker_id'] = workerId; + obj['task_type'] = taskType; + } + + /** + * Constructs a JobBlocklistEntry from a plain JavaScript object, optionally creating a new instance. + * Copies all relevant properties from data to obj if supplied or a new instance if not. + * @param {Object} data The plain JavaScript object bearing properties of interest. + * @param {module:model/JobBlocklistEntry} obj Optional instance to populate. + * @return {module:model/JobBlocklistEntry} The populated JobBlocklistEntry instance. + */ + static constructFromObject(data, obj) { + if (data) { + obj = obj || new JobBlocklistEntry(); + + if (data.hasOwnProperty('worker_id')) { + obj['worker_id'] = ApiClient.convertToType(data['worker_id'], 'String'); + } + if (data.hasOwnProperty('task_type')) { + obj['task_type'] = ApiClient.convertToType(data['task_type'], 'String'); + } + } + return obj; + } + + +} + +/** + * @member {String} worker_id + */ +JobBlocklistEntry.prototype['worker_id'] = undefined; + +/** + * @member {String} task_type + */ +JobBlocklistEntry.prototype['task_type'] = undefined; + + + + + + +export default JobBlocklistEntry; +