diff --git a/addon/flamenco/manager/__init__.py b/addon/flamenco/manager/__init__.py index 775e21f8..37348c6a 100644 --- a/addon/flamenco/manager/__init__.py +++ b/addon/flamenco/manager/__init__.py @@ -10,7 +10,7 @@ """ -__version__ = "a3752f31" +__version__ = "adba7217" # 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 34082009..a1a5d724 100644 --- a/addon/flamenco/manager/api/jobs_api.py +++ b/addon/flamenco/manager/api/jobs_api.py @@ -30,6 +30,7 @@ from flamenco.manager.model.job_tasks_summary import JobTasksSummary from flamenco.manager.model.jobs_query import JobsQuery from flamenco.manager.model.jobs_query_result import JobsQueryResult from flamenco.manager.model.submitted_job import SubmittedJob +from flamenco.manager.model.task import Task class JobsApi(object): @@ -141,6 +142,55 @@ class JobsApi(object): }, api_client=api_client ) + self.fetch_task_endpoint = _Endpoint( + settings={ + 'response_type': (Task,), + 'auth': [], + 'endpoint_path': '/api/tasks/{task_id}', + 'operation_id': 'fetch_task', + 'http_method': 'GET', + 'servers': None, + }, + params_map={ + 'all': [ + 'task_id', + ], + 'required': [ + 'task_id', + ], + 'nullable': [ + ], + 'enum': [ + ], + 'validation': [ + ] + }, + root_map={ + 'validations': { + }, + 'allowed_values': { + }, + 'openapi_types': { + 'task_id': + (str,), + }, + 'attribute_map': { + 'task_id': 'task_id', + }, + 'location_map': { + 'task_id': 'path', + }, + 'collection_format_map': { + } + }, + headers_map={ + 'accept': [ + 'application/json' + ], + 'content_type': [], + }, + api_client=api_client + ) self.get_job_type_endpoint = _Endpoint( settings={ 'response_type': (AvailableJobType,), @@ -543,6 +593,83 @@ class JobsApi(object): job_id return self.fetch_job_tasks_endpoint.call_with_http_info(**kwargs) + def fetch_task( + self, + task_id, + **kwargs + ): + """Fetch a single task. # 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_task(task_id, async_req=True) + >>> result = thread.get() + + Args: + task_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: + Task + 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['task_id'] = \ + task_id + return self.fetch_task_endpoint.call_with_http_info(**kwargs) + def get_job_type( self, type_name, diff --git a/addon/flamenco/manager/api_client.py b/addon/flamenco/manager/api_client.py index 297aff0c..58aa2d2a 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/a3752f31 (Blender add-on)' + self.user_agent = 'Flamenco/adba7217 (Blender add-on)' def __enter__(self): return self diff --git a/addon/flamenco/manager/configuration.py b/addon/flamenco/manager/configuration.py index 9fff19cd..a0df5a4a 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: a3752f31".\ + "SDK Package Version: adba7217".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self): diff --git a/addon/flamenco/manager/docs/JobsApi.md b/addon/flamenco/manager/docs/JobsApi.md index 9889a680..f3f90f4b 100644 --- a/addon/flamenco/manager/docs/JobsApi.md +++ b/addon/flamenco/manager/docs/JobsApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**fetch_job**](JobsApi.md#fetch_job) | **GET** /api/jobs/{job_id} | Fetch info about the 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. [**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. @@ -145,6 +146,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_task** +> Task fetch_task(task_id) + +Fetch a single task. + +### Example + + +```python +import time +import flamenco.manager +from flamenco.manager.api import jobs_api +from flamenco.manager.model.task import Task +from flamenco.manager.model.error import Error +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) + task_id = "task_id_example" # str | + + # example passing only required values which don't have defaults set + try: + # Fetch a single task. + api_response = api_instance.fetch_task(task_id) + pprint(api_response) + except flamenco.manager.ApiException as e: + print("Exception when calling JobsApi->fetch_task: %s\n" % e) +``` + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **task_id** | **str**| | + +### Return type + +[**Task**](Task.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + + +### HTTP response details + +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | The task info. | - | +**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) + # **get_job_type** > AvailableJobType get_job_type(type_name) diff --git a/addon/flamenco/manager/docs/Task.md b/addon/flamenco/manager/docs/Task.md new file mode 100644 index 00000000..87e43973 --- /dev/null +++ b/addon/flamenco/manager/docs/Task.md @@ -0,0 +1,23 @@ +# Task + +The task as it exists in the Manager database, i.e. before variable replacement. + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | | +**created** | **datetime** | Creation timestamp | +**updated** | **datetime** | Timestamp of last update. | +**job_id** | **str** | | +**name** | **str** | | +**status** | [**TaskStatus**](TaskStatus.md) | | +**priority** | **int** | | +**task_type** | **str** | | +**activity** | **str** | | +**commands** | [**[Command]**](Command.md) | | +**worker** | [**TaskWorker**](TaskWorker.md) | | [optional] +**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/TaskWorker.md b/addon/flamenco/manager/docs/TaskWorker.md new file mode 100644 index 00000000..f22aa1f0 --- /dev/null +++ b/addon/flamenco/manager/docs/TaskWorker.md @@ -0,0 +1,14 @@ +# TaskWorker + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **str** | | +**name** | **str** | | +**address** | **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/model/task.py b/addon/flamenco/manager/model/task.py new file mode 100644 index 00000000..02a2783f --- /dev/null +++ b/addon/flamenco/manager/model/task.py @@ -0,0 +1,329 @@ +""" + 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.command import Command + from flamenco.manager.model.task_status import TaskStatus + from flamenco.manager.model.task_worker import TaskWorker + globals()['Command'] = Command + globals()['TaskStatus'] = TaskStatus + globals()['TaskWorker'] = TaskWorker + + +class Task(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 + """ + lazy_import() + 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. + """ + lazy_import() + return { + 'id': (str,), # noqa: E501 + 'created': (datetime,), # noqa: E501 + 'updated': (datetime,), # noqa: E501 + 'job_id': (str,), # noqa: E501 + 'name': (str,), # noqa: E501 + 'status': (TaskStatus,), # noqa: E501 + 'priority': (int,), # noqa: E501 + 'task_type': (str,), # noqa: E501 + 'activity': (str,), # noqa: E501 + 'commands': ([Command],), # noqa: E501 + 'worker': (TaskWorker,), # noqa: E501 + } + + @cached_property + def discriminator(): + return None + + + attribute_map = { + 'id': 'id', # noqa: E501 + 'created': 'created', # noqa: E501 + 'updated': 'updated', # noqa: E501 + 'job_id': 'job_id', # noqa: E501 + 'name': 'name', # noqa: E501 + 'status': 'status', # noqa: E501 + 'priority': 'priority', # noqa: E501 + 'task_type': 'task_type', # noqa: E501 + 'activity': 'activity', # noqa: E501 + 'commands': 'commands', # noqa: E501 + 'worker': 'worker', # noqa: E501 + } + + read_only_vars = { + } + + _composed_schemas = {} + + @classmethod + @convert_js_args_to_python_args + def _from_openapi_data(cls, id, created, updated, job_id, name, status, priority, task_type, activity, commands, *args, **kwargs): # noqa: E501 + """Task - a model defined in OpenAPI + + Args: + id (str): + created (datetime): Creation timestamp + updated (datetime): Timestamp of last update. + job_id (str): + name (str): + status (TaskStatus): + priority (int): + task_type (str): + activity (str): + commands ([Command]): + + 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,) + worker (TaskWorker): [optional] # noqa: E501 + """ + + _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.id = id + self.created = created + self.updated = updated + self.job_id = job_id + self.name = name + self.status = status + self.priority = priority + self.task_type = task_type + self.activity = activity + self.commands = commands + 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, id, created, updated, job_id, name, status, priority, task_type, activity, commands, *args, **kwargs): # noqa: E501 + """Task - a model defined in OpenAPI + + Args: + id (str): + created (datetime): Creation timestamp + updated (datetime): Timestamp of last update. + job_id (str): + name (str): + status (TaskStatus): + priority (int): + task_type (str): + activity (str): + commands ([Command]): + + 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,) + worker (TaskWorker): [optional] # noqa: E501 + """ + + _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.id = id + self.created = created + self.updated = updated + self.job_id = job_id + self.name = name + self.status = status + self.priority = priority + self.task_type = task_type + self.activity = activity + self.commands = commands + 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/model/task_worker.py b/addon/flamenco/manager/model/task_worker.py new file mode 100644 index 00000000..f3e72f32 --- /dev/null +++ b/addon/flamenco/manager/model/task_worker.py @@ -0,0 +1,273 @@ +""" + 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 TaskWorker(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 { + 'id': (str,), # noqa: E501 + 'name': (str,), # noqa: E501 + 'address': (str,), # noqa: E501 + } + + @cached_property + def discriminator(): + return None + + + attribute_map = { + 'id': 'id', # noqa: E501 + 'name': 'name', # noqa: E501 + 'address': 'address', # noqa: E501 + } + + read_only_vars = { + } + + _composed_schemas = {} + + @classmethod + @convert_js_args_to_python_args + def _from_openapi_data(cls, id, name, address, *args, **kwargs): # noqa: E501 + """TaskWorker - a model defined in OpenAPI + + Args: + id (str): + name (str): + address (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.id = id + self.name = name + self.address = address + 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, id, name, address, *args, **kwargs): # noqa: E501 + """TaskWorker - a model defined in OpenAPI + + Args: + id (str): + name (str): + address (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.id = id + self.name = name + self.address = address + 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 277bcf82..a1163f2e 100644 --- a/addon/flamenco/manager/models/__init__.py +++ b/addon/flamenco/manager/models/__init__.py @@ -44,9 +44,11 @@ from flamenco.manager.model.socket_io_subscription_operation import SocketIOSubs from flamenco.manager.model.socket_io_subscription_type import SocketIOSubscriptionType from flamenco.manager.model.socket_io_task_update import SocketIOTaskUpdate from flamenco.manager.model.submitted_job import SubmittedJob +from flamenco.manager.model.task import Task from flamenco.manager.model.task_status import TaskStatus from flamenco.manager.model.task_summary import TaskSummary from flamenco.manager.model.task_update import TaskUpdate +from flamenco.manager.model.task_worker import TaskWorker from flamenco.manager.model.worker_registration import WorkerRegistration from flamenco.manager.model.worker_sign_on import WorkerSignOn from flamenco.manager.model.worker_state_change import WorkerStateChange diff --git a/addon/flamenco/manager_README.md b/addon/flamenco/manager_README.md index 9c09e6ef..9fa36242 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: a3752f31 +- Package version: adba7217 - Build package: org.openapitools.codegen.languages.PythonClientCodegen For more information, please visit [https://flamenco.io/](https://flamenco.io/) @@ -41,6 +41,7 @@ from flamenco.manager.model.job_tasks_summary import JobTasksSummary from flamenco.manager.model.jobs_query import JobsQuery from flamenco.manager.model.jobs_query_result import JobsQueryResult from flamenco.manager.model.submitted_job import SubmittedJob +from flamenco.manager.model.task import Task # 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( @@ -71,6 +72,7 @@ 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_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* | [**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. @@ -128,9 +130,11 @@ Class | Method | HTTP request | Description - [SocketIOSubscriptionType](flamenco/manager/docs/SocketIOSubscriptionType.md) - [SocketIOTaskUpdate](flamenco/manager/docs/SocketIOTaskUpdate.md) - [SubmittedJob](flamenco/manager/docs/SubmittedJob.md) + - [Task](flamenco/manager/docs/Task.md) - [TaskStatus](flamenco/manager/docs/TaskStatus.md) - [TaskSummary](flamenco/manager/docs/TaskSummary.md) - [TaskUpdate](flamenco/manager/docs/TaskUpdate.md) + - [TaskWorker](flamenco/manager/docs/TaskWorker.md) - [WorkerRegistration](flamenco/manager/docs/WorkerRegistration.md) - [WorkerSignOn](flamenco/manager/docs/WorkerSignOn.md) - [WorkerStateChange](flamenco/manager/docs/WorkerStateChange.md) diff --git a/internal/worker/mocks/client.gen.go b/internal/worker/mocks/client.gen.go index e93109f4..3992d85c 100644 --- a/internal/worker/mocks/client.gen.go +++ b/internal/worker/mocks/client.gen.go @@ -76,6 +76,26 @@ func (mr *MockFlamencoClientMockRecorder) FetchJobWithResponse(arg0, arg1 interf return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchJobWithResponse", reflect.TypeOf((*MockFlamencoClient)(nil).FetchJobWithResponse), varargs...) } +// FetchTaskWithResponse mocks base method. +func (m *MockFlamencoClient) FetchTaskWithResponse(arg0 context.Context, arg1 string, arg2 ...api.RequestEditorFn) (*api.FetchTaskResponse, error) { + m.ctrl.T.Helper() + varargs := []interface{}{arg0, arg1} + for _, a := range arg2 { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "FetchTaskWithResponse", varargs...) + ret0, _ := ret[0].(*api.FetchTaskResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchTaskWithResponse indicates an expected call of FetchTaskWithResponse. +func (mr *MockFlamencoClientMockRecorder) FetchTaskWithResponse(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, "FetchTaskWithResponse", reflect.TypeOf((*MockFlamencoClient)(nil).FetchTaskWithResponse), varargs...) +} + // GetConfigurationWithResponse mocks base method. func (m *MockFlamencoClient) GetConfigurationWithResponse(arg0 context.Context, arg1 ...api.RequestEditorFn) (*api.GetConfigurationResponse, error) { m.ctrl.T.Helper() diff --git a/pkg/api/openapi_client.gen.go b/pkg/api/openapi_client.gen.go index 6ba7adb8..423a805f 100644 --- a/pkg/api/openapi_client.gen.go +++ b/pkg/api/openapi_client.gen.go @@ -120,6 +120,9 @@ type ClientInterface interface { // FetchJobTasks request FetchJobTasks(ctx context.Context, jobId string, reqEditors ...RequestEditorFn) (*http.Response, error) + // FetchTask request + FetchTask(ctx context.Context, taskId string, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetVersion request GetVersion(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -301,6 +304,18 @@ func (c *Client) FetchJobTasks(ctx context.Context, jobId string, reqEditors ... return c.Client.Do(req) } +func (c *Client) FetchTask(ctx context.Context, taskId string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFetchTaskRequest(c.Server, taskId) + 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) GetVersion(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewGetVersionRequest(c.Server) if err != nil { @@ -800,6 +815,40 @@ func NewFetchJobTasksRequest(server string, jobId string) (*http.Request, error) return req, nil } +// NewFetchTaskRequest generates requests for FetchTask +func NewFetchTaskRequest(server string, taskId string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "task_id", runtime.ParamLocationPath, taskId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/api/tasks/%s", 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 +} + // NewGetVersionRequest generates requests for GetVersion func NewGetVersionRequest(server string) (*http.Request, error) { var err error @@ -1334,6 +1383,9 @@ type ClientWithResponsesInterface interface { // FetchJobTasks request FetchJobTasksWithResponse(ctx context.Context, jobId string, reqEditors ...RequestEditorFn) (*FetchJobTasksResponse, error) + // FetchTask request + FetchTaskWithResponse(ctx context.Context, taskId string, reqEditors ...RequestEditorFn) (*FetchTaskResponse, error) + // GetVersion request GetVersionWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetVersionResponse, error) @@ -1562,6 +1614,29 @@ func (r FetchJobTasksResponse) StatusCode() int { return 0 } +type FetchTaskResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *Task + JSONDefault *Error +} + +// Status returns HTTPResponse.Status +func (r FetchTaskResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r FetchTaskResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type GetVersionResponse struct { Body []byte HTTPResponse *http.Response @@ -1932,6 +2007,15 @@ func (c *ClientWithResponses) FetchJobTasksWithResponse(ctx context.Context, job return ParseFetchJobTasksResponse(rsp) } +// FetchTaskWithResponse request returning *FetchTaskResponse +func (c *ClientWithResponses) FetchTaskWithResponse(ctx context.Context, taskId string, reqEditors ...RequestEditorFn) (*FetchTaskResponse, error) { + rsp, err := c.FetchTask(ctx, taskId, reqEditors...) + if err != nil { + return nil, err + } + return ParseFetchTaskResponse(rsp) +} + // GetVersionWithResponse request returning *GetVersionResponse func (c *ClientWithResponses) GetVersionWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*GetVersionResponse, error) { rsp, err := c.GetVersion(ctx, reqEditors...) @@ -2317,6 +2401,39 @@ func ParseFetchJobTasksResponse(rsp *http.Response) (*FetchJobTasksResponse, err return response, nil } +// ParseFetchTaskResponse parses an HTTP response from a FetchTaskWithResponse call +func ParseFetchTaskResponse(rsp *http.Response) (*FetchTaskResponse, error) { + bodyBytes, err := ioutil.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &FetchTaskResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest Task + 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 +} + // ParseGetVersionResponse parses an HTTP response from a GetVersionWithResponse call func ParseGetVersionResponse(rsp *http.Response) (*GetVersionResponse, error) { bodyBytes, err := ioutil.ReadAll(rsp.Body) diff --git a/pkg/api/openapi_server.gen.go b/pkg/api/openapi_server.gen.go index 4c13d3fc..d12756ca 100644 --- a/pkg/api/openapi_server.gen.go +++ b/pkg/api/openapi_server.gen.go @@ -37,6 +37,9 @@ type ServerInterface interface { // Fetch a summary of all tasks of the given job. // (GET /api/jobs/{job_id}/tasks) FetchJobTasks(ctx echo.Context, jobId string) error + // Fetch a single task. + // (GET /api/tasks/{task_id}) + FetchTask(ctx echo.Context, taskId string) error // Get the Flamenco version of this Manager // (GET /api/version) GetVersion(ctx echo.Context) error @@ -181,6 +184,22 @@ func (w *ServerInterfaceWrapper) FetchJobTasks(ctx echo.Context) error { return err } +// FetchTask converts echo context to params. +func (w *ServerInterfaceWrapper) FetchTask(ctx echo.Context) error { + var err error + // ------------- Path parameter "task_id" ------------- + var taskId string + + err = runtime.BindStyledParameterWithLocation("simple", false, "task_id", runtime.ParamLocationPath, ctx.Param("task_id"), &taskId) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter task_id: %s", err)) + } + + // Invoke the callback with all the unmarshalled arguments + err = w.Handler.FetchTask(ctx, taskId) + return err +} + // GetVersion converts echo context to params. func (w *ServerInterfaceWrapper) GetVersion(ctx echo.Context) error { var err error @@ -409,6 +428,7 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/api/jobs/:job_id", wrapper.FetchJob) 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) router.GET(baseURL+"/api/version", wrapper.GetVersion) router.POST(baseURL+"/api/worker/register-worker", wrapper.RegisterWorker) router.POST(baseURL+"/api/worker/sign-off", wrapper.SignOff) diff --git a/pkg/api/openapi_spec.gen.go b/pkg/api/openapi_spec.gen.go index cbe97cdf..532f3b60 100644 --- a/pkg/api/openapi_spec.gen.go +++ b/pkg/api/openapi_spec.gen.go @@ -18,117 +18,119 @@ import ( // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", - "TtOa39Pr6s3V/wQAAP//F69kymh0AAA=", + "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", } // 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 95345689..7136f158 100644 --- a/pkg/api/openapi_types.gen.go +++ b/pkg/api/openapi_types.gen.go @@ -425,6 +425,25 @@ type SubmittedJob struct { Type string `json:"type"` } +// The task as it exists in the Manager database, i.e. before variable replacement. +type Task struct { + Activity string `json:"activity"` + Commands []Command `json:"commands"` + + // Creation timestamp + Created time.Time `json:"created"` + Id string `json:"id"` + JobId string `json:"job_id"` + Name string `json:"name"` + Priority int `json:"priority"` + Status TaskStatus `json:"status"` + TaskType string `json:"task_type"` + + // Timestamp of last update. + Updated time.Time `json:"updated"` + Worker *TaskWorker `json:"worker,omitempty"` +} + // TaskStatus defines model for TaskStatus. type TaskStatus string @@ -448,6 +467,13 @@ type TaskUpdate struct { TaskStatus *TaskStatus `json:"taskStatus,omitempty"` } +// TaskWorker defines model for TaskWorker. +type TaskWorker struct { + Address string `json:"address"` + Id string `json:"id"` + Name string `json:"name"` +} + // WorkerRegistration defines model for WorkerRegistration. type WorkerRegistration struct { Nickname string `json:"nickname"` diff --git a/web/app/src/manager-api/ApiClient.js b/web/app/src/manager-api/ApiClient.js index 0cd4f3ff..a34c9fb3 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/a3752f31 / webbrowser' + 'User-Agent': 'Flamenco/adba7217 / webbrowser' }; /** diff --git a/web/app/src/manager-api/index.js b/web/app/src/manager-api/index.js index 9ba5a4f3..860b6f17 100644 --- a/web/app/src/manager-api/index.js +++ b/web/app/src/manager-api/index.js @@ -46,9 +46,11 @@ import SocketIOSubscriptionOperation from './model/SocketIOSubscriptionOperation import SocketIOSubscriptionType from './model/SocketIOSubscriptionType'; import SocketIOTaskUpdate from './model/SocketIOTaskUpdate'; import SubmittedJob from './model/SubmittedJob'; +import Task from './model/Task'; import TaskStatus from './model/TaskStatus'; import TaskSummary from './model/TaskSummary'; import TaskUpdate from './model/TaskUpdate'; +import TaskWorker from './model/TaskWorker'; import WorkerRegistration from './model/WorkerRegistration'; import WorkerSignOn from './model/WorkerSignOn'; import WorkerStateChange from './model/WorkerStateChange'; @@ -296,6 +298,12 @@ export { */ SubmittedJob, + /** + * The Task model constructor. + * @property {module:model/Task} + */ + Task, + /** * The TaskStatus model constructor. * @property {module:model/TaskStatus} @@ -314,6 +322,12 @@ export { */ TaskUpdate, + /** + * The TaskWorker model constructor. + * @property {module:model/TaskWorker} + */ + TaskWorker, + /** * The WorkerRegistration model constructor. * @property {module:model/WorkerRegistration} diff --git a/web/app/src/manager-api/manager/JobsApi.js b/web/app/src/manager-api/manager/JobsApi.js index 217f1baa..8378f744 100644 --- a/web/app/src/manager-api/manager/JobsApi.js +++ b/web/app/src/manager-api/manager/JobsApi.js @@ -22,6 +22,7 @@ import JobTasksSummary from '../model/JobTasksSummary'; import JobsQuery from '../model/JobsQuery'; import JobsQueryResult from '../model/JobsQueryResult'; import SubmittedJob from '../model/SubmittedJob'; +import Task from '../model/Task'; /** * Jobs service. @@ -135,6 +136,52 @@ export default class JobsApi { } + /** + * Fetch a single task. + * @param {String} taskId + * @return {Promise} a {@link https://www.promisejs.org/|Promise}, with an object containing data of type {@link module:model/Task} and HTTP response + */ + fetchTaskWithHttpInfo(taskId) { + let postBody = null; + // verify the required parameter 'taskId' is set + if (taskId === undefined || taskId === null) { + throw new Error("Missing the required parameter 'taskId' when calling fetchTask"); + } + + let pathParams = { + 'task_id': taskId + }; + let queryParams = { + }; + let headerParams = { + }; + let formParams = { + }; + + let authNames = []; + let contentTypes = []; + let accepts = ['application/json']; + let returnType = Task; + return this.apiClient.callApi( + '/api/tasks/{task_id}', 'GET', + pathParams, queryParams, headerParams, formParams, postBody, + authNames, contentTypes, accepts, returnType, null + ); + } + + /** + * Fetch a single task. + * @param {String} taskId + * @return {Promise} a {@link https://www.promisejs.org/|Promise}, with data of type {@link module:model/Task} + */ + fetchTask(taskId) { + return this.fetchTaskWithHttpInfo(taskId) + .then(function(response_and_data) { + return response_and_data.data; + }); + } + + /** * Get single job type and its parameters. * @param {String} typeName diff --git a/web/app/src/manager-api/model/Task.js b/web/app/src/manager-api/model/Task.js new file mode 100644 index 00000000..f00f1e89 --- /dev/null +++ b/web/app/src/manager-api/model/Task.js @@ -0,0 +1,177 @@ +/** + * 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'; +import Command from './Command'; +import TaskStatus from './TaskStatus'; +import TaskWorker from './TaskWorker'; + +/** + * The Task model module. + * @module model/Task + * @version 0.0.0 + */ +class Task { + /** + * Constructs a new Task. + * The task as it exists in the Manager database, i.e. before variable replacement. + * @alias module:model/Task + * @param id {String} + * @param created {Date} Creation timestamp + * @param updated {Date} Timestamp of last update. + * @param jobId {String} + * @param name {String} + * @param status {module:model/TaskStatus} + * @param priority {Number} + * @param taskType {String} + * @param activity {String} + * @param commands {Array.} + */ + constructor(id, created, updated, jobId, name, status, priority, taskType, activity, commands) { + + Task.initialize(this, id, created, updated, jobId, name, status, priority, taskType, activity, commands); + } + + /** + * 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, id, created, updated, jobId, name, status, priority, taskType, activity, commands) { + obj['id'] = id; + obj['created'] = created; + obj['updated'] = updated; + obj['job_id'] = jobId; + obj['name'] = name; + obj['status'] = status; + obj['priority'] = priority; + obj['task_type'] = taskType; + obj['activity'] = activity; + obj['commands'] = commands; + } + + /** + * Constructs a Task 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/Task} obj Optional instance to populate. + * @return {module:model/Task} The populated Task instance. + */ + static constructFromObject(data, obj) { + if (data) { + obj = obj || new Task(); + + if (data.hasOwnProperty('id')) { + obj['id'] = ApiClient.convertToType(data['id'], 'String'); + } + if (data.hasOwnProperty('created')) { + obj['created'] = ApiClient.convertToType(data['created'], 'Date'); + } + if (data.hasOwnProperty('updated')) { + obj['updated'] = ApiClient.convertToType(data['updated'], 'Date'); + } + if (data.hasOwnProperty('job_id')) { + obj['job_id'] = ApiClient.convertToType(data['job_id'], 'String'); + } + if (data.hasOwnProperty('name')) { + obj['name'] = ApiClient.convertToType(data['name'], 'String'); + } + if (data.hasOwnProperty('status')) { + obj['status'] = TaskStatus.constructFromObject(data['status']); + } + if (data.hasOwnProperty('priority')) { + obj['priority'] = ApiClient.convertToType(data['priority'], 'Number'); + } + if (data.hasOwnProperty('task_type')) { + obj['task_type'] = ApiClient.convertToType(data['task_type'], 'String'); + } + if (data.hasOwnProperty('activity')) { + obj['activity'] = ApiClient.convertToType(data['activity'], 'String'); + } + if (data.hasOwnProperty('commands')) { + obj['commands'] = ApiClient.convertToType(data['commands'], [Command]); + } + if (data.hasOwnProperty('worker')) { + obj['worker'] = TaskWorker.constructFromObject(data['worker']); + } + } + return obj; + } + + +} + +/** + * @member {String} id + */ +Task.prototype['id'] = undefined; + +/** + * Creation timestamp + * @member {Date} created + */ +Task.prototype['created'] = undefined; + +/** + * Timestamp of last update. + * @member {Date} updated + */ +Task.prototype['updated'] = undefined; + +/** + * @member {String} job_id + */ +Task.prototype['job_id'] = undefined; + +/** + * @member {String} name + */ +Task.prototype['name'] = undefined; + +/** + * @member {module:model/TaskStatus} status + */ +Task.prototype['status'] = undefined; + +/** + * @member {Number} priority + */ +Task.prototype['priority'] = undefined; + +/** + * @member {String} task_type + */ +Task.prototype['task_type'] = undefined; + +/** + * @member {String} activity + */ +Task.prototype['activity'] = undefined; + +/** + * @member {Array.} commands + */ +Task.prototype['commands'] = undefined; + +/** + * @member {module:model/TaskWorker} worker + */ +Task.prototype['worker'] = undefined; + + + + + + +export default Task; + diff --git a/web/app/src/manager-api/model/TaskWorker.js b/web/app/src/manager-api/model/TaskWorker.js new file mode 100644 index 00000000..d0a64a87 --- /dev/null +++ b/web/app/src/manager-api/model/TaskWorker.js @@ -0,0 +1,93 @@ +/** + * 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 TaskWorker model module. + * @module model/TaskWorker + * @version 0.0.0 + */ +class TaskWorker { + /** + * Constructs a new TaskWorker. + * @alias module:model/TaskWorker + * @param id {String} + * @param name {String} + * @param address {String} + */ + constructor(id, name, address) { + + TaskWorker.initialize(this, id, name, address); + } + + /** + * 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, id, name, address) { + obj['id'] = id; + obj['name'] = name; + obj['address'] = address; + } + + /** + * Constructs a TaskWorker 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/TaskWorker} obj Optional instance to populate. + * @return {module:model/TaskWorker} The populated TaskWorker instance. + */ + static constructFromObject(data, obj) { + if (data) { + obj = obj || new TaskWorker(); + + if (data.hasOwnProperty('id')) { + obj['id'] = ApiClient.convertToType(data['id'], 'String'); + } + if (data.hasOwnProperty('name')) { + obj['name'] = ApiClient.convertToType(data['name'], 'String'); + } + if (data.hasOwnProperty('address')) { + obj['address'] = ApiClient.convertToType(data['address'], 'String'); + } + } + return obj; + } + + +} + +/** + * @member {String} id + */ +TaskWorker.prototype['id'] = undefined; + +/** + * @member {String} name + */ +TaskWorker.prototype['name'] = undefined; + +/** + * @member {String} address + */ +TaskWorker.prototype['address'] = undefined; + + + + + + +export default TaskWorker; +