mirror of
https://github.com/clearml/clearml-server
synced 2025-06-26 23:15:47 +00:00
Add support for additional task types as well as tasks.get_types to obtain actual types used globally or per project
This commit is contained in:
parent
84a75d9e70
commit
9403942ef7
@ -92,6 +92,10 @@ class PingRequest(TaskRequest):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class GetTypesRequest(models.Base):
|
||||||
|
projects = ListField(items_types=[str])
|
||||||
|
|
||||||
|
|
||||||
class CloneRequest(TaskRequest):
|
class CloneRequest(TaskRequest):
|
||||||
new_task_name = StringField()
|
new_task_name = StringField()
|
||||||
new_task_comment = StringField()
|
new_task_comment = StringField()
|
||||||
|
@ -28,6 +28,7 @@ from database.model.task.task import (
|
|||||||
TaskSystemTags,
|
TaskSystemTags,
|
||||||
ArtifactModes,
|
ArtifactModes,
|
||||||
Artifact,
|
Artifact,
|
||||||
|
external_task_types,
|
||||||
)
|
)
|
||||||
from database.utils import get_company_or_none_constraint, id as create_id
|
from database.utils import get_company_or_none_constraint, id as create_id
|
||||||
from service_repo import APICall
|
from service_repo import APICall
|
||||||
@ -46,6 +47,18 @@ class TaskBLL(object):
|
|||||||
events_es if events_es is not None else es_factory.connect("events")
|
events_es if events_es is not None else es_factory.connect("events")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_types(cls, company, project_ids: Optional[Sequence]) -> set:
|
||||||
|
"""
|
||||||
|
Return the list of unique task types used by company and public tasks
|
||||||
|
If project ids passed then only tasks from these projects are considered
|
||||||
|
"""
|
||||||
|
query = get_company_or_none_constraint(company)
|
||||||
|
if project_ids:
|
||||||
|
query &= Q(project__in=project_ids)
|
||||||
|
res = Task.objects(query).distinct(field="type")
|
||||||
|
return set(res).intersection(external_task_types)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_task_with_access(
|
def get_task_with_access(
|
||||||
task_id, company_id, only=None, allow_public=False, requires_write_access=False
|
task_id, company_id, only=None, allow_public=False, requires_write_access=False
|
||||||
|
@ -100,6 +100,18 @@ class Execution(EmbeddedDocument, ProperDictMixin):
|
|||||||
class TaskType(object):
|
class TaskType(object):
|
||||||
training = "training"
|
training = "training"
|
||||||
testing = "testing"
|
testing = "testing"
|
||||||
|
inference = "inference"
|
||||||
|
data_processing = "data_processing"
|
||||||
|
application = "application"
|
||||||
|
monitor = "monitor"
|
||||||
|
controller = "controller"
|
||||||
|
optimizer = "optimizer"
|
||||||
|
service = "service"
|
||||||
|
qc = "qc"
|
||||||
|
custom = "custom"
|
||||||
|
|
||||||
|
|
||||||
|
external_task_types = set(get_options(TaskType))
|
||||||
|
|
||||||
|
|
||||||
class Task(AttributedDocument):
|
class Task(AttributedDocument):
|
||||||
|
@ -254,6 +254,15 @@ _definitions {
|
|||||||
enum: [
|
enum: [
|
||||||
training
|
training
|
||||||
testing
|
testing
|
||||||
|
inference
|
||||||
|
data_processing
|
||||||
|
application
|
||||||
|
monitor
|
||||||
|
controller
|
||||||
|
optimizer
|
||||||
|
service
|
||||||
|
qc
|
||||||
|
custom
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
last_metrics_event {
|
last_metrics_event {
|
||||||
@ -554,6 +563,31 @@ get_all {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
get_types {
|
||||||
|
"2.8" {
|
||||||
|
description: "Get the list of task types used in the specified projects"
|
||||||
|
request {
|
||||||
|
type: object
|
||||||
|
properties {
|
||||||
|
projects {
|
||||||
|
description: "The list of projects which tasks will be analyzed. If not passed or empty then all the company and public tasks will be analyzed"
|
||||||
|
type: array
|
||||||
|
items: {type: string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response {
|
||||||
|
type: object
|
||||||
|
properties {
|
||||||
|
types {
|
||||||
|
description: "Unique list of the task types used in the requested projects"
|
||||||
|
type: array
|
||||||
|
items: {type: string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
clone {
|
clone {
|
||||||
"2.5" {
|
"2.5" {
|
||||||
description: "Clone an existing task"
|
description: "Clone an existing task"
|
||||||
|
@ -154,9 +154,9 @@ def make_projects_get_all_pipelines(company_id, project_ids, specific_state=None
|
|||||||
# only count run time for these types of tasks
|
# only count run time for these types of tasks
|
||||||
{
|
{
|
||||||
"$match": {
|
"$match": {
|
||||||
"type": {"$in": ["training", "testing", "annotation"]},
|
"type": {"$in": ["training", "testing"]},
|
||||||
"project": {"$in": project_ids},
|
|
||||||
"company": {"$in": [None, "", company_id]},
|
"company": {"$in": [None, "", company_id]},
|
||||||
|
"project": {"$in": project_ids},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ensure_valid_fields(),
|
ensure_valid_fields(),
|
||||||
|
@ -29,6 +29,7 @@ from apimodels.tasks import (
|
|||||||
CloneRequest,
|
CloneRequest,
|
||||||
AddOrUpdateArtifactsRequest,
|
AddOrUpdateArtifactsRequest,
|
||||||
AddOrUpdateArtifactsResponse,
|
AddOrUpdateArtifactsResponse,
|
||||||
|
GetTypesRequest,
|
||||||
)
|
)
|
||||||
from bll.event import EventBLL
|
from bll.event import EventBLL
|
||||||
from bll.organization import OrgBLL
|
from bll.organization import OrgBLL
|
||||||
@ -164,6 +165,13 @@ def get_all(call: APICall, company_id, _):
|
|||||||
call.result.data = {"tasks": tasks}
|
call.result.data = {"tasks": tasks}
|
||||||
|
|
||||||
|
|
||||||
|
@endpoint("tasks.get_types", request_data_model=GetTypesRequest)
|
||||||
|
def get_types(call: APICall, company_id, request: GetTypesRequest):
|
||||||
|
call.result.data = {
|
||||||
|
"types": list(task_bll.get_types(company_id, project_ids=request.projects))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@endpoint(
|
@endpoint(
|
||||||
"tasks.stop", request_data_model=UpdateRequest, response_data_model=UpdateResponse
|
"tasks.stop", request_data_model=UpdateRequest, response_data_model=UpdateResponse
|
||||||
)
|
)
|
||||||
|
@ -54,6 +54,10 @@ class TestService(TestCase, TestServiceInterface):
|
|||||||
)
|
)
|
||||||
return object_id
|
return object_id
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def update_missing(target: dict, **update):
|
||||||
|
target.update({k: v for k, v in update.items() if k not in target})
|
||||||
|
|
||||||
def create_temp(self, service, *, client=None, delete_params=None, **kwargs) -> str:
|
def create_temp(self, service, *, client=None, delete_params=None, **kwargs) -> str:
|
||||||
return self._create_temp_helper(
|
return self._create_temp_helper(
|
||||||
service=service,
|
service=service,
|
||||||
|
@ -208,25 +208,21 @@ class TestTags(TestService):
|
|||||||
self.api.tasks.stopped(task=task_id)
|
self.api.tasks.stopped(task=task_id)
|
||||||
|
|
||||||
def _temp_queue(self, **kwargs):
|
def _temp_queue(self, **kwargs):
|
||||||
self._update_missing(kwargs, name="Test tags")
|
self.update_missing(kwargs, name="Test tags")
|
||||||
return self.create_temp("queues", **kwargs)
|
return self.create_temp("queues", **kwargs)
|
||||||
|
|
||||||
def _temp_project(self, **kwargs):
|
def _temp_project(self, **kwargs):
|
||||||
self._update_missing(kwargs, name="Test tags", description="test")
|
self.update_missing(kwargs, name="Test tags", description="test")
|
||||||
return self.create_temp("projects", **kwargs)
|
return self.create_temp("projects", **kwargs)
|
||||||
|
|
||||||
def _temp_model(self, **kwargs):
|
def _temp_model(self, **kwargs):
|
||||||
self._update_missing(kwargs, name="Test tags", uri="file:///a/b", labels={})
|
self.update_missing(kwargs, name="Test tags", uri="file:///a/b", labels={})
|
||||||
return self.create_temp("models", **kwargs)
|
return self.create_temp("models", **kwargs)
|
||||||
|
|
||||||
def _temp_task(self, **kwargs):
|
def _temp_task(self, **kwargs):
|
||||||
self._update_missing(kwargs, name="Test tags", type="testing", input=dict(view=dict()))
|
self.update_missing(kwargs, name="Test tags", type="testing", input=dict(view=dict()))
|
||||||
return self.create_temp("tasks", **kwargs)
|
return self.create_temp("tasks", **kwargs)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _update_missing(target: dict, **update):
|
|
||||||
target.update({k: v for k, v in update.items() if k not in target})
|
|
||||||
|
|
||||||
def _send(self, service, action, **kwargs):
|
def _send(self, service, action, **kwargs):
|
||||||
api = kwargs.pop("api", self.api)
|
api = kwargs.pop("api", self.api)
|
||||||
return AttrDict(
|
return AttrDict(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from apierrors.errors.bad_request import InvalidModelId
|
from apierrors.errors.bad_request import InvalidModelId, ValidationError
|
||||||
from config import config
|
from config import config
|
||||||
from tests.automated import TestService
|
from tests.automated import TestService
|
||||||
|
|
||||||
@ -11,12 +11,37 @@ class TestTasksEdit(TestService):
|
|||||||
super().setUp(version=2.5)
|
super().setUp(version=2.5)
|
||||||
|
|
||||||
def new_task(self, **kwargs):
|
def new_task(self, **kwargs):
|
||||||
return self.create_temp(
|
self.update_missing(
|
||||||
"tasks", type="testing", name="test", input=dict(view=dict()), **kwargs
|
kwargs, type="testing", name="test", input=dict(view=dict())
|
||||||
)
|
)
|
||||||
|
return self.create_temp("tasks", **kwargs)
|
||||||
|
|
||||||
def new_model(self):
|
def new_model(self, **kwargs):
|
||||||
return self.create_temp("models", name="test", uri="file:///a/b", labels={})
|
self.update_missing(kwargs, name="test", uri="file:///a/b", labels={})
|
||||||
|
return self.create_temp("models", **kwargs)
|
||||||
|
|
||||||
|
def test_task_types(self):
|
||||||
|
with self.api.raises(ValidationError):
|
||||||
|
task = self.new_task(type="Unsupported")
|
||||||
|
|
||||||
|
types = ["controller", "optimizer"]
|
||||||
|
p1 = self.create_temp("projects", name="Test tasks1", description="test")
|
||||||
|
task1 = self.new_task(project=p1, type=types[0])
|
||||||
|
p2 = self.create_temp("projects", name="Test tasks2", description="test")
|
||||||
|
task2 = self.new_task(project=p2, type=types[1])
|
||||||
|
|
||||||
|
# all company types
|
||||||
|
res = self.api.tasks.get_types()
|
||||||
|
self.assertTrue(set(types).issubset(set(res["types"])))
|
||||||
|
|
||||||
|
# projects array
|
||||||
|
res = self.api.tasks.get_types(projects=[p1, p2])
|
||||||
|
self.assertEqual(set(types), set(res["types"]))
|
||||||
|
|
||||||
|
# single project
|
||||||
|
for p, t in zip((p1, p2), types):
|
||||||
|
res = self.api.tasks.get_types(projects=[p])
|
||||||
|
self.assertEqual([t], res["types"])
|
||||||
|
|
||||||
def test_edit_model_ready(self):
|
def test_edit_model_ready(self):
|
||||||
task = self.new_task()
|
task = self.new_task()
|
||||||
|
Loading…
Reference in New Issue
Block a user