diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 9f87199e8..062279175 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -95,6 +95,8 @@ jobs: with: report_paths: '**/test*.xml' check_name: Test Report ${{ matrix.os }}:${{ matrix.cfg.python-version }} + detailed_summary: true + include_passed: true docs: name: Documentation diff --git a/ansys/rep/client/jms/api/project_api.py b/ansys/rep/client/jms/api/project_api.py index 298bfa7ae..6737dda6f 100644 --- a/ansys/rep/client/jms/api/project_api.py +++ b/ansys/rep/client/jms/api/project_api.py @@ -2,7 +2,7 @@ import logging import os from pathlib import Path -from typing import Callable, List, Type +from typing import Callable, List, Type, Union from cachetools import TTLCache, cached from marshmallow.utils import missing @@ -105,9 +105,13 @@ def fs_bucket_url(self) -> str: ################################################################ # Project operations (copy, archive) - def copy_project(self, project_target_name: str, wait: bool = True) -> str: + def copy_project(self, wait: bool = True) -> str: """Duplicate project""" - return copy_project(self, self.project_id, project_target_name, wait) + r = copy_projects(self, [self.project_id], wait) + if wait: + return r[0] + else: + return r def archive_project(self, path: str, include_job_files: bool = True): """Archive an existing project and save it to disk @@ -519,10 +523,12 @@ def _download_file( return download_path -def copy_project(project_api: ProjectApi, project_source_id, project_target_name, wait=True) -> str: +def copy_projects( + project_api: ProjectApi, project_source_ids: List[str], wait: bool = True +) -> Union[str, List[str]]: - url = f"{project_api.url}/copy" - r = project_api.client.session.put(url, params={"project_name": project_target_name}) + url = f"{project_api.jms_api_url}/projects:copy" + r = project_api.client.session.post(url, data=json.dumps({"source_ids": project_source_ids})) operation_location = r.headers["location"] operation_id = operation_location.rsplit("/", 1)[-1] @@ -532,8 +538,8 @@ def copy_project(project_api: ProjectApi, project_source_id, project_target_name op = _monitor_operation(JmsApi(project_api.client), operation_id, 1.0) if not op.succeeded: - raise REPError(f"Failed to copy project {project_source_id}.") - return op.result["project_id"] + raise REPError(f"Failed to copy projects {project_source_ids}.") + return op.result["destination_ids"] def archive_project(project_api: ProjectApi, target_path, include_job_files=True) -> str: diff --git a/ansys/rep/client/jms/resource/evaluator.py b/ansys/rep/client/jms/resource/evaluator.py index ca85541de..ba056d0af 100644 --- a/ansys/rep/client/jms/resource/evaluator.py +++ b/ansys/rep/client/jms/resource/evaluator.py @@ -67,6 +67,8 @@ class Evaluator(Object): Name of the evaluator. hostname : str, optional Name of the host on which the evaluator is running. + username : str, optional + REP user the evaluator is connected to JMS as. platform : str, optional Operating system on which the evaluator is running. task_manager_type : str, optional @@ -99,6 +101,7 @@ def __init__(self, host_id=missing, name=missing, hostname=missing, + username=missing, platform=missing, task_manager_type=missing, project_server_select=missing, @@ -114,6 +117,7 @@ def __init__(self, self.host_id = host_id self.name = name self.hostname = hostname + self.username = username self.platform = platform self.task_manager_type = task_manager_type self.project_server_select = project_server_select diff --git a/ansys/rep/client/jms/resource/operation.py b/ansys/rep/client/jms/resource/operation.py index 3f222135f..648db6012 100644 --- a/ansys/rep/client/jms/resource/operation.py +++ b/ansys/rep/client/jms/resource/operation.py @@ -11,6 +11,7 @@ class Operation(Object): id : str, optional Unique ID to access the resource, generated internally by the server on creation. name : str, optional + target : list, optional finished : bool, optional succeeded : bool, optional progress : float, optional @@ -29,6 +30,7 @@ class Meta: def __init__(self, id=missing, name=missing, + target=missing, finished=missing, succeeded=missing, progress=missing, @@ -40,6 +42,7 @@ def __init__(self, ): self.id = id self.name = name + self.target = target self.finished = finished self.succeeded = succeeded self.progress = progress diff --git a/ansys/rep/client/jms/schema/evaluator.py b/ansys/rep/client/jms/schema/evaluator.py index e0a871045..c8724680f 100644 --- a/ansys/rep/client/jms/schema/evaluator.py +++ b/ansys/rep/client/jms/schema/evaluator.py @@ -46,6 +46,10 @@ class Meta: allow_none=True, metadata={"description": "Name of the host on which the evaluator is running."}, ) + username = fields.String( + allow_none=True, + metadata={"description": "REP user the evaluator is connected to JMS as."}, + ) platform = fields.String( allow_none=True, metadata={"description": "Operating system on which the evaluator is running."}, diff --git a/ansys/rep/client/jms/schema/operation.py b/ansys/rep/client/jms/schema/operation.py index bb93ece2c..1ec3533c8 100644 --- a/ansys/rep/client/jms/schema/operation.py +++ b/ansys/rep/client/jms/schema/operation.py @@ -8,6 +8,7 @@ class Meta(ObjectSchema.Meta): pass name = fields.String(allow_none=True) + target = fields.List(fields.String(), allow_none=True) finished = fields.Bool(allow_none=True) succeeded = fields.Bool(allow_none=True) diff --git a/tests/jms/test_evaluators.py b/tests/jms/test_evaluators.py index 5c1a92274..ec42f52c9 100644 --- a/tests/jms/test_evaluators.py +++ b/tests/jms/test_evaluators.py @@ -34,6 +34,7 @@ def test_evaluator_deserialization(self): "name": "dc_evaluator_win10_2019R3_tmp", "project_list": [], "external_access_port": 443, + "username": "repuser", } evaluator = EvaluatorSchema().load(evaluator_dict) @@ -65,11 +66,14 @@ def test_evaluator_integration(self): if evaluators: self.assertTrue(evaluators[0]["id"] is not None) - evaluators = jms_api.get_evaluators(as_objects=False, fields=["hostname", "platform"]) + evaluators = jms_api.get_evaluators( + as_objects=False, fields=["hostname", "platform", "username"] + ) log.info(f"evaluators={evaluators}") if evaluators: self.assertTrue("hostname" in evaluators[0].keys()) self.assertTrue("platform" in evaluators[0].keys()) + self.assertTrue("username" in evaluators[0].keys()) self.assertTrue("project_server_select" not in evaluators[0].keys()) # self.assertEqual(len(evaluators[0].keys()), 2) diff --git a/tests/jms/test_projects.py b/tests/jms/test_projects.py index 08ba16d87..ab319ff1b 100644 --- a/tests/jms/test_projects.py +++ b/tests/jms/test_projects.py @@ -164,16 +164,16 @@ def test_project_copy(self): proj = Project(name=proj_name, active=True, priority=10) proj = jms_api.create_project(proj, replace=True) - tgt_name = proj_name + "_copy1" project_api = ProjectApi(client, proj.id) - proj1_id = project_api.copy_project(tgt_name) + proj1_id = project_api.copy_project() copied_proj1 = jms_api.get_project(id=proj1_id) self.assertIsNotNone(copied_proj1) + self.assertEqual(copied_proj1.name, f"{proj.name} - copy") - tgt_name = proj_name + "_copy2" - proj2_id = project_api.copy_project(tgt_name) + proj2_id = project_api.copy_project() copied_proj2 = jms_api.get_project(id=proj2_id) self.assertIsNotNone(copied_proj2) + self.assertEqual(copied_proj2.name, f"{proj.name} - copy") # Delete projects jms_api.delete_project(copied_proj1)