This is an automated email from the ASF dual-hosted git repository.

yasithdev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airavata-portals.git


The following commit(s) were added to refs/heads/main by this push:
     new 91cf66b9d feat(portal): repoint application deployment reads to gRPC 
(Track D, D2) (#166)
91cf66b9d is described below

commit 91cf66b9d58da88d0ebd9d098735d48c660daa3b
Author: Yasith Jayawardana <[email protected]>
AuthorDate: Mon Jun 8 19:29:14 2026 -0400

    feat(portal): repoint application deployment reads to gRPC (Track D, D2) 
(#166)
    
    Migrate ApplicationDeploymentViewSet.get_list/get_instance from the
    Thrift client to the gRPC research facade (get_accessible_application_
    deployments / get_application_deployments_for_app_module_and_group_
    resource_profile / get_application_deployment). Write actions and the
    queues action stay on Thrift: queues reads a ComputeResource, so it
    moves with the compute-resources family.
    
    New application_deployment adapter recursively adapts the nested command
    lists (moduleLoadCmds/preJobCommands/postJobCommands -> CommandObject)
    and env-path lists (libPrependPaths/libAppendPaths/setEnvironment ->
    SetEnvPaths). The serializer renders parallelism as a raw integer (the
    auto-generated field is an IntegerField, not a ThriftEnumField), and the
    proto/Thrift ApplicationParallelismType integers differ per name (proto
    SERIAL=1 vs Thrift SERIAL=0), so the adapter bridges by NAME via the
    shared _thrift_enum helper to emit the Thrift integer the frontend
    expects -- passing the raw proto int would shift every value by one. The
    queue-default cluster (defaultQueueName/NodeCount/CPUCount/Walltime) maps
    the proto-zero 'unset' sentinels back to None so the serializer renders
    null as Thrift did. userHasWriteAccess migrates to the gRPC sharing
    helper.
    
    Verified: manage.py check clean; accessible list returns 200 against the
    live backend; offline serializer render with real nested protobuf
    confirms command/env lists adapt, parallelism maps to the correct Thrift
    int for every value, queue-defaults render null, and userHasWriteAccess
    resolves via sharing. (The dev backend has no compute resources to seed a
    full deployment, so nested live data was validated via the offline render
    against real protobuf.)
---
 .../django_airavata/apps/api/grpc_adapters.py      | 43 ++++++++++++++++++++++
 .../django_airavata/apps/api/serializers.py        |  6 +--
 .../django_airavata/apps/api/views.py              | 13 ++++---
 3 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py 
b/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
index 30761dadf..e806d8ec4 100644
--- a/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
+++ b/airavata-django-portal/django_airavata/apps/api/grpc_adapters.py
@@ -13,6 +13,9 @@ serializers are made protobuf-native.
 
 from types import SimpleNamespace
 
+from airavata.model.appcatalog.parallelism.ttypes import (
+    ApplicationParallelismType as _ThriftParallelismType,
+)
 from airavata.model.application.io.ttypes import DataType as _ThriftDataType
 from airavata.model.credential.store.ttypes import SummaryType as 
_ThriftSummaryType
 
@@ -164,3 +167,43 @@ def application_interface(pb):
         archiveWorkingDirectory=pb.archive_working_directory,
         hasOptionalFileInputs=pb.has_optional_file_inputs,
     )
+
+
+def _command_object(pb):
+    """gRPC ``CommandObject`` -> ``CommandObjectSerializer`` shape."""
+    return SimpleNamespace(command=pb.command, commandOrder=pb.command_order)
+
+
+def _set_env_paths(pb):
+    """gRPC ``SetEnvPaths`` -> ``SetEnvPathsSerializer`` shape."""
+    return SimpleNamespace(
+        name=pb.name, value=pb.value, envPathOrder=pb.env_path_order)
+
+
+def application_deployment(pb):
+    """gRPC ``ApplicationDeploymentDescription`` -> 
``ApplicationDeploymentDescriptionSerializer`` shape.
+
+    Recursively adapts the nested command/env-path lists. ``parallelism`` is an
+    enum with the proto/Thrift integer mismatch (proto SERIAL=1 vs Thrift
+    SERIAL=0) -> bridged by name. The queue-default cluster maps the proto-zero
+    "unset" sentinels back to None so the serializer renders null as Thrift 
did.
+    """
+    return SimpleNamespace(
+        appDeploymentId=pb.app_deployment_id,
+        appModuleId=pb.app_module_id,
+        computeHostId=pb.compute_host_id,
+        executablePath=pb.executable_path,
+        parallelism=_thrift_enum(pb, 'parallelism', _ThriftParallelismType),
+        appDeploymentDescription=pb.app_deployment_description,
+        moduleLoadCmds=[_command_object(c) for c in pb.module_load_cmds],
+        libPrependPaths=[_set_env_paths(p) for p in pb.lib_prepend_paths],
+        libAppendPaths=[_set_env_paths(p) for p in pb.lib_append_paths],
+        setEnvironment=[_set_env_paths(p) for p in pb.set_environment],
+        preJobCommands=[_command_object(c) for c in pb.pre_job_commands],
+        postJobCommands=[_command_object(c) for c in pb.post_job_commands],
+        defaultQueueName=pb.default_queue_name or None,
+        defaultNodeCount=pb.default_node_count or None,
+        defaultCPUCount=pb.default_cpu_count or None,
+        defaultWalltime=pb.default_walltime or None,
+        editableByUser=pb.editable_by_user,
+    )
diff --git a/airavata-django-portal/django_airavata/apps/api/serializers.py 
b/airavata-django-portal/django_airavata/apps/api/serializers.py
index 901f99969..6d99f5c48 100644
--- a/airavata-django-portal/django_airavata/apps/api/serializers.py
+++ b/airavata-django-portal/django_airavata/apps/api/serializers.py
@@ -515,10 +515,8 @@ class ApplicationDeploymentDescriptionSerializer(
         allow_null=True)
 
     def get_userHasWriteAccess(self, appDeployment):
-        request = self.context['request']
-        return request.airavata_client.userHasAccess(
-            request.authz_token, appDeployment.appDeploymentId,
-            ResourcePermissionType.WRITE)
+        return user_has_access(
+            self.context['request'], appDeployment.appDeploymentId)
 
 
 class ComputeResourceDescriptionSerializer(
diff --git a/airavata-django-portal/django_airavata/apps/api/views.py 
b/airavata-django-portal/django_airavata/apps/api/views.py
index 078c9d4f8..7b48b955f 100644
--- a/airavata-django-portal/django_airavata/apps/api/views.py
+++ b/airavata-django-portal/django_airavata/apps/api/views.py
@@ -630,15 +630,16 @@ class ApplicationDeploymentViewSet(APIBackedViewSet):
             raise ParseError("Query params appModuleId and "
                              "groupResourceProfileId are required together.")
         if app_module_id and group_resource_profile_id:
-            return 
self.request.airavata_client.getApplicationDeploymentsForAppModuleAndGroupResourceProfile(
-                self.authz_token, app_module_id, group_resource_profile_id)
+            deployments = 
self.request.airavata.research.get_application_deployments_for_app_module_and_group_resource_profile(
+                app_module_id, group_resource_profile_id)
         else:
-            return 
self.request.airavata_client.getAccessibleApplicationDeployments(
-                self.authz_token, self.gateway_id, ResourcePermissionType.READ)
+            deployments = 
self.request.airavata.research.get_accessible_application_deployments(
+                self.gateway_id)
+        return [grpc_adapters.application_deployment(d) for d in deployments]
 
     def get_instance(self, lookup_value):
-        return self.request.airavata_client.getApplicationDeployment(
-            self.authz_token, lookup_value)
+        return grpc_adapters.application_deployment(
+            
self.request.airavata.research.get_application_deployment(lookup_value))
 
     def perform_create(self, serializer):
         application_deployment = serializer.save()

Reply via email to