mirror of
https://github.com/clearml/clearml-server
synced 2025-06-26 23:15:47 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a2675abe1 | ||
|
|
f0d68b1ce9 | ||
|
|
15db9cdaef | ||
|
|
a45d47f5d7 | ||
|
|
b1a50c1370 | ||
|
|
22a2a02760 | ||
|
|
ab798e4170 | ||
|
|
f09ac672d2 | ||
|
|
2149b76f63 |
@@ -256,6 +256,16 @@ class TaskBLL:
|
||||
not in [TaskSystemTags.development, EntityVisibility.archived.value]
|
||||
]
|
||||
|
||||
def ensure_int_labels(execution: dict) -> dict:
|
||||
if not execution:
|
||||
return execution
|
||||
|
||||
model_labels = execution.get("model_labels")
|
||||
if model_labels:
|
||||
execution["model_labels"] = {k: int(v) for k, v in model_labels.items()}
|
||||
|
||||
return execution
|
||||
|
||||
parent_task = (
|
||||
task.parent
|
||||
if task.parent and not task.parent.startswith(deleted_prefix)
|
||||
@@ -280,7 +290,7 @@ class TaskBLL:
|
||||
output=Output(destination=task.output.destination) if task.output else None,
|
||||
models=Models(input=input_models or task.models.input),
|
||||
container=escape_dict(container) or task.container,
|
||||
execution=execution_dict,
|
||||
execution=ensure_int_labels(execution_dict),
|
||||
configuration=params_dict.get("configuration") or task.configuration,
|
||||
hyperparams=params_dict.get("hyperparams") or task.hyperparams,
|
||||
)
|
||||
|
||||
@@ -60,6 +60,7 @@ def start_pipeline(call: APICall, company_id: str, request: StartPipelineRequest
|
||||
queued, res = enqueue_task(
|
||||
task_id=task.id,
|
||||
company_id=company_id,
|
||||
user_id=call.identity.user,
|
||||
queue_id=request.queue,
|
||||
status_message="Starting pipeline",
|
||||
status_reason="",
|
||||
|
||||
@@ -73,10 +73,6 @@ def update_report(call: APICall, company_id: str, request: UpdateReportRequest):
|
||||
task = _assert_report(
|
||||
task_id=request.task, company_id=company_id, only_fields=("status",),
|
||||
)
|
||||
if task.status != TaskStatus.created:
|
||||
raise errors.bad_request.InvalidTaskStatus(
|
||||
expected=TaskStatus.created, status=task.status
|
||||
)
|
||||
|
||||
partial_update_dict = {
|
||||
field: value for field, value in call.data.items() if field in update_fields
|
||||
@@ -84,14 +80,18 @@ def update_report(call: APICall, company_id: str, request: UpdateReportRequest):
|
||||
if not partial_update_dict:
|
||||
return UpdateResponse(updated=0)
|
||||
|
||||
allowed_for_published = set(partial_update_dict.keys()).issubset({"tags", "name", "comment"})
|
||||
if task.status != TaskStatus.created and not allowed_for_published:
|
||||
raise errors.bad_request.InvalidTaskStatus(
|
||||
expected=TaskStatus.created, status=task.status
|
||||
)
|
||||
|
||||
now = datetime.utcnow()
|
||||
updated = task.update(
|
||||
upsert=False,
|
||||
**partial_update_dict,
|
||||
last_change=now,
|
||||
last_update=now,
|
||||
last_changed_by=call.identity.user,
|
||||
)
|
||||
more_updates = {"last_change": now, "last_changed_by": call.identity.user}
|
||||
if not allowed_for_published:
|
||||
more_updates["last_update"] = now
|
||||
|
||||
updated = task.update(upsert=False, **partial_update_dict, **more_updates)
|
||||
if not updated:
|
||||
return UpdateResponse(updated=0)
|
||||
|
||||
|
||||
50
apiserver/tests/automated/test_pipelines.py
Normal file
50
apiserver/tests/automated/test_pipelines.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from typing import Tuple
|
||||
|
||||
from apiserver.tests.automated import TestService
|
||||
|
||||
|
||||
class TestPipelines(TestService):
|
||||
def test_start_pipeline(self):
|
||||
queue = self.api.queues.get_default().id
|
||||
task_name = "pipelines test"
|
||||
project, task = self._temp_project_and_task(name=task_name)
|
||||
args = [{"name": "hello", "value": "test"}]
|
||||
|
||||
res = self.api.pipelines.start_pipeline(task=task, queue=queue, args=args)
|
||||
pipeline_task = res.pipeline
|
||||
try:
|
||||
self.assertTrue(res.enqueued)
|
||||
pipeline = self.api.tasks.get_all_ex(id=[pipeline_task]).tasks[0]
|
||||
self.assertTrue(pipeline.name.startswith(task_name))
|
||||
self.assertEqual(pipeline.status, "queued")
|
||||
self.assertEqual(pipeline.project.id, project)
|
||||
self.assertEqual(
|
||||
pipeline.hyperparams.Args,
|
||||
{
|
||||
a["name"]: {
|
||||
"section": "Args",
|
||||
"name": a["name"],
|
||||
"value": a["value"],
|
||||
}
|
||||
for a in args
|
||||
},
|
||||
)
|
||||
finally:
|
||||
self.api.tasks.delete(task=pipeline_task, force=True)
|
||||
|
||||
def _temp_project_and_task(self, name) -> Tuple[str, str]:
|
||||
project = self.create_temp(
|
||||
"projects", name=name, description="test", delete_params=dict(force=True),
|
||||
)
|
||||
|
||||
return (
|
||||
project,
|
||||
self.create_temp(
|
||||
"tasks",
|
||||
name=name,
|
||||
type="testing",
|
||||
input=dict(view=dict()),
|
||||
project=project,
|
||||
system_tags=["pipeline"],
|
||||
),
|
||||
)
|
||||
@@ -56,7 +56,16 @@ class TestReports(TestService):
|
||||
self.assertEqual(ret.tags, [])
|
||||
self.api.reports.publish(task=task_id)
|
||||
with self.api.raises(errors.bad_request.InvalidTaskStatus):
|
||||
self.api.reports.update(task=task_id, comment=comment)
|
||||
self.api.reports.update(task=task_id, report="New report text")
|
||||
|
||||
# update on tags or rename can be done for published report too
|
||||
self.api.reports.update(
|
||||
task=task_id, name="new name", tags=["test"], comment="Yet another comment"
|
||||
)
|
||||
task = self.api.tasks.get_all_ex(id=[task_id]).tasks[0]
|
||||
self.assertEqual(task.tags, ["test"])
|
||||
self.assertEqual(task.name, "new name")
|
||||
self.assertEqual(task.comment, "Yet another comment")
|
||||
|
||||
# move under another project autodeletes the empty project
|
||||
new_project_name = "Reports Test"
|
||||
|
||||
@@ -103,7 +103,7 @@ class TestTasksEdit(TestService):
|
||||
|
||||
new_name = "new test"
|
||||
new_tags = ["by"]
|
||||
execution_overrides = dict(framework="Caffe")
|
||||
execution_overrides = dict(framework="Caffe", model_labels={"test": 1.0})
|
||||
new_task_id = self._clone_task(
|
||||
task=task,
|
||||
new_task_name=new_name,
|
||||
@@ -120,6 +120,7 @@ class TestTasksEdit(TestService):
|
||||
self.assertEqual(new_task.parent, task)
|
||||
# self.assertEqual(new_task.execution.parameters, execution["parameters"])
|
||||
self.assertEqual(new_task.execution.framework, execution_overrides["framework"])
|
||||
self.assertEqual(new_task.execution.model_labels, {"test": 1})
|
||||
self.assertEqual(new_task.system_tags, ["test"])
|
||||
|
||||
def test_model_check_in_clone(self):
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "1.9.0"
|
||||
__version__ = "1.9.2"
|
||||
|
||||
@@ -172,7 +172,7 @@ services:
|
||||
CLEARML_API_SECRET_KEY: ${CLEARML_API_SECRET_KEY:-}
|
||||
CLEARML_AGENT_GIT_USER: ${CLEARML_AGENT_GIT_USER}
|
||||
CLEARML_AGENT_GIT_PASS: ${CLEARML_AGENT_GIT_PASS}
|
||||
CLEARML_AGENT_UPDATE_VERSION: ${CLEARML_AGENT_UPDATE_VERSION:-">=0.17.0"}
|
||||
CLEARML_AGENT_UPDATE_VERSION: ${CLEARML_AGENT_UPDATE_VERSION:->=0.17.0}
|
||||
CLEARML_AGENT_DEFAULT_BASE_DOCKER: "ubuntu:18.04"
|
||||
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-}
|
||||
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-}
|
||||
|
||||
Reference in New Issue
Block a user