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

yasith pushed a commit to branch feat/airavata-service-layer
in repository https://gitbox.apache.org/repos/asf/airavata.git

commit e355a731c004f727ee5b3b0b49a45319e8b0bc45
Author: yasithdev <[email protected]>
AuthorDate: Thu Mar 26 12:51:36 2026 -0500

    feat: add SSHAccountService for SSH account management
    
    Extracted doesUserHaveSSHAccount, 
isSSHSetupCompleteForUserComputeResourcePreference,
    and setupUserComputeResourcePreferencesForSSH from AiravataServerHandler 
into a dedicated
    SSHAccountService. Handler methods are now ThriftAdapter one-liners. 
Includes 6 unit tests
    covering all methods and error paths.
---
 .../airavata/service/ssh/SSHAccountService.java    |  81 ++++++++++++++
 .../service/ssh/SSHAccountServiceTest.java         | 121 +++++++++++++++++++++
 2 files changed, 202 insertions(+)

diff --git 
a/airavata-api/src/main/java/org/apache/airavata/service/ssh/SSHAccountService.java
 
b/airavata-api/src/main/java/org/apache/airavata/service/ssh/SSHAccountService.java
new file mode 100644
index 0000000000..8deafaa5b0
--- /dev/null
+++ 
b/airavata-api/src/main/java/org/apache/airavata/service/ssh/SSHAccountService.java
@@ -0,0 +1,81 @@
+package org.apache.airavata.service.ssh;
+
+import org.apache.airavata.accountprovisioning.SSHAccountManager;
+import 
org.apache.airavata.credential.store.server.CredentialStoreServerHandler;
+import 
org.apache.airavata.model.appcatalog.userresourceprofile.UserComputeResourcePreference;
+import org.apache.airavata.model.credential.store.SSHCredential;
+import org.apache.airavata.service.context.RequestContext;
+import org.apache.airavata.service.exception.ServiceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SSHAccountService {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(SSHAccountService.class);
+
+    private final CredentialStoreServerHandler credentialHandler;
+
+    public SSHAccountService(CredentialStoreServerHandler credentialHandler) {
+        this.credentialHandler = credentialHandler;
+    }
+
+    public boolean doesUserHaveSSHAccount(RequestContext ctx, String 
computeResourceId, String userId)
+            throws ServiceException {
+        String gatewayId = ctx.getGatewayId();
+        try {
+            return SSHAccountManager.doesUserHaveSSHAccount(gatewayId, 
computeResourceId, userId);
+        } catch (Exception e) {
+            String msg = "Error occurred while checking if [" + userId + "] 
has an SSH Account on ["
+                    + computeResourceId + "].";
+            logger.error(msg, e);
+            throw new ServiceException(msg + " More info: " + e.getMessage(), 
e);
+        }
+    }
+
+    public boolean isSSHSetupCompleteForUserComputeResourcePreference(
+            RequestContext ctx, String computeResourceId, String 
airavataCredStoreToken)
+            throws ServiceException {
+        String gatewayId = ctx.getGatewayId();
+        String userId = ctx.getUserId();
+
+        SSHCredential sshCredential;
+        try {
+            sshCredential = 
credentialHandler.getSSHCredential(airavataCredStoreToken, gatewayId);
+        } catch (Exception e) {
+            String msg = "Error occurred while retrieving SSH Credential.";
+            logger.error(msg, e);
+            throw new ServiceException(msg + " More info: " + e.getMessage(), 
e);
+        }
+
+        try {
+            return SSHAccountManager.isSSHAccountSetupComplete(gatewayId, 
computeResourceId, userId, sshCredential);
+        } catch (Exception e) {
+            String msg = "Error occurred while checking if setup of SSH 
account is complete for user [" + userId + "].";
+            logger.error(msg, e);
+            throw new ServiceException(msg + " More info: " + e.getMessage(), 
e);
+        }
+    }
+
+    public UserComputeResourcePreference 
setupUserComputeResourcePreferencesForSSH(
+            RequestContext ctx, String computeResourceId, String userId, 
String airavataCredStoreToken)
+            throws ServiceException {
+        String gatewayId = ctx.getGatewayId();
+
+        SSHCredential sshCredential;
+        try {
+            sshCredential = 
credentialHandler.getSSHCredential(airavataCredStoreToken, gatewayId);
+        } catch (Exception e) {
+            String msg = "Error occurred while retrieving SSH Credential.";
+            logger.error(msg, e);
+            throw new ServiceException(msg + " More info: " + e.getMessage(), 
e);
+        }
+
+        try {
+            return SSHAccountManager.setupSSHAccount(gatewayId, 
computeResourceId, userId, sshCredential);
+        } catch (Exception e) {
+            String msg = "Error occurred while automatically setting up SSH 
account for user [" + userId + "].";
+            logger.error(msg, e);
+            throw new ServiceException(msg + " More info: " + e.getMessage(), 
e);
+        }
+    }
+}
diff --git 
a/airavata-api/src/test/java/org/apache/airavata/service/ssh/SSHAccountServiceTest.java
 
b/airavata-api/src/test/java/org/apache/airavata/service/ssh/SSHAccountServiceTest.java
new file mode 100644
index 0000000000..bdeab25a00
--- /dev/null
+++ 
b/airavata-api/src/test/java/org/apache/airavata/service/ssh/SSHAccountServiceTest.java
@@ -0,0 +1,121 @@
+package org.apache.airavata.service.ssh;
+
+import 
org.apache.airavata.credential.store.server.CredentialStoreServerHandler;
+import org.apache.airavata.model.credential.store.SSHCredential;
+import org.apache.airavata.service.context.RequestContext;
+import org.apache.airavata.service.exception.ServiceException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import org.apache.airavata.accountprovisioning.SSHAccountManager;
+import 
org.apache.airavata.model.appcatalog.userresourceprofile.UserComputeResourcePreference;
+
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+class SSHAccountServiceTest {
+
+    @Mock CredentialStoreServerHandler credentialHandler;
+
+    SSHAccountService sshAccountService;
+    RequestContext ctx;
+
+    @BeforeEach
+    void setUp() {
+        sshAccountService = new SSHAccountService(credentialHandler);
+        ctx = new RequestContext("testUser", "testGateway", "token123",
+                Map.of("userName", "testUser", "gatewayId", "testGateway"));
+    }
+
+    @Test
+    void doesUserHaveSSHAccount_delegatesToSSHAccountManager() throws 
Exception {
+        try (MockedStatic<SSHAccountManager> mock = 
mockStatic(SSHAccountManager.class)) {
+            mock.when(() -> 
SSHAccountManager.doesUserHaveSSHAccount("testGateway", "cr-001", "testUser"))
+                    .thenReturn(true);
+
+            boolean result = sshAccountService.doesUserHaveSSHAccount(ctx, 
"cr-001", "testUser");
+
+            assertTrue(result);
+            mock.verify(() -> 
SSHAccountManager.doesUserHaveSSHAccount("testGateway", "cr-001", "testUser"));
+        }
+    }
+
+    @Test
+    void doesUserHaveSSHAccount_wrapsException() {
+        try (MockedStatic<SSHAccountManager> mock = 
mockStatic(SSHAccountManager.class)) {
+            mock.when(() -> SSHAccountManager.doesUserHaveSSHAccount(any(), 
any(), any()))
+                    .thenThrow(new RuntimeException("connection failed"));
+
+            assertThrows(ServiceException.class,
+                    () -> sshAccountService.doesUserHaveSSHAccount(ctx, 
"cr-001", "testUser"));
+        }
+    }
+
+    @Test
+    void isSSHSetupComplete_fetchesCredentialAndDelegates() throws Exception {
+        SSHCredential cred = new SSHCredential();
+        when(credentialHandler.getSSHCredential("tok-123", 
"testGateway")).thenReturn(cred);
+
+        try (MockedStatic<SSHAccountManager> mock = 
mockStatic(SSHAccountManager.class)) {
+            mock.when(() -> 
SSHAccountManager.isSSHAccountSetupComplete("testGateway", "cr-001", 
"testUser", cred))
+                    .thenReturn(false);
+
+            boolean result = 
sshAccountService.isSSHSetupCompleteForUserComputeResourcePreference(
+                    ctx, "cr-001", "tok-123");
+
+            assertFalse(result);
+            verify(credentialHandler).getSSHCredential("tok-123", 
"testGateway");
+        }
+    }
+
+    @Test
+    void isSSHSetupComplete_wrapsCredentialException() throws Exception {
+        when(credentialHandler.getSSHCredential(any(), any())).thenThrow(new 
RuntimeException("store error"));
+
+        assertThrows(ServiceException.class,
+                () -> 
sshAccountService.isSSHSetupCompleteForUserComputeResourcePreference(ctx, 
"cr-001", "tok-bad"));
+    }
+
+    @Test
+    void setupSSHAccount_fetchesCredentialAndDelegates() throws Exception {
+        SSHCredential cred = new SSHCredential();
+        when(credentialHandler.getSSHCredential("tok-123", 
"testGateway")).thenReturn(cred);
+
+        UserComputeResourcePreference pref = new 
UserComputeResourcePreference();
+        pref.setComputeResourceId("cr-001");
+
+        try (MockedStatic<SSHAccountManager> mock = 
mockStatic(SSHAccountManager.class)) {
+            mock.when(() -> SSHAccountManager.setupSSHAccount("testGateway", 
"cr-001", "testUser", cred))
+                    .thenReturn(pref);
+
+            UserComputeResourcePreference result = 
sshAccountService.setupUserComputeResourcePreferencesForSSH(
+                    ctx, "cr-001", "testUser", "tok-123");
+
+            assertNotNull(result);
+            assertEquals("cr-001", result.getComputeResourceId());
+            verify(credentialHandler).getSSHCredential("tok-123", 
"testGateway");
+        }
+    }
+
+    @Test
+    void setupSSHAccount_wrapsSSHAccountManagerException() throws Exception {
+        SSHCredential cred = new SSHCredential();
+        when(credentialHandler.getSSHCredential("tok-123", 
"testGateway")).thenReturn(cred);
+
+        try (MockedStatic<SSHAccountManager> mock = 
mockStatic(SSHAccountManager.class)) {
+            mock.when(() -> SSHAccountManager.setupSSHAccount(any(), any(), 
any(), any()))
+                    .thenThrow(new RuntimeException("setup failed"));
+
+            assertThrows(ServiceException.class,
+                    () -> 
sshAccountService.setupUserComputeResourcePreferencesForSSH(
+                            ctx, "cr-001", "testUser", "tok-123"));
+        }
+    }
+}

Reply via email to