Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/CR-1808-Create SFTP connection and upload file to SFTP directory #74

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.testsigma.addons</groupId>
<artifactId>sftp_upload_file</artifactId>
<version>1.0.1</version>
<packaging>jar</packaging>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<testsigma.sdk.version>1.2.13_cloud</testsigma.sdk.version>
<junit.jupiter.version>5.8.0-M1</junit.jupiter.version>
<testsigma.addon.maven.plugin>1.0.0</testsigma.addon.maven.plugin>
<maven.source.plugin.version>3.2.1</maven.source.plugin.version>
<lombok.version>1.18.20</lombok.version>

</properties>

<dependencies>
<dependency>
<groupId>com.testsigma</groupId>
<artifactId>testsigma-java-sdk</artifactId>
<version>${testsigma.sdk.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.14.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.appium/java-client -->
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>9.0.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<dependency>
<groupId>com.github.mwiede</groupId>
<artifactId>jsch</artifactId>
<version>0.2.16</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>

</dependencies>
<build>
<finalName>sftp_upload_file</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven.source.plugin.version}</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package com.testsigma.addons.web;

import com.jcraft.jsch.*;
import com.testsigma.sdk.ApplicationType;
import com.testsigma.sdk.Result;
import com.testsigma.sdk.WindowsAction;
import com.testsigma.sdk.annotation.Action;
import com.testsigma.sdk.annotation.RunTimeData;
import com.testsigma.sdk.annotation.TestData;
import lombok.Data;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.openqa.selenium.NoSuchElementException;

import java.io.*;
import java.net.URL;
import java.nio.file.Paths;

@Data
@Action(actionText = "SFTP: Connect to SFTP server and upload a file. SFTP server details: Host: Host-Name, UserName: User-Name, Password: User-Password, Upload from Local-File-Path to Remote-Directory(ex: /C:/Users/username/Downloads) with file name Remote-File-Name. Uploaded file path will be stored in runtime variable: variable-name",
description = "Uploads a file from local system or URL to remote server using SFTP, and stores the uploaded file path in a runtime variable, ensuring matching extensions.",
applicationType = ApplicationType.WEB,
useCustomScreenshot = false)
public class SFTPUploadFile extends WindowsAction {

@TestData(reference = "Host-Name")
private com.testsigma.sdk.TestData hostName;

@TestData(reference = "User-Name")
private com.testsigma.sdk.TestData userName;

@TestData(reference = "User-Password")
private com.testsigma.sdk.TestData userPassword;

@TestData(reference = "Local-File-Path")
private com.testsigma.sdk.TestData localFilePath; // Local file path or URL

@TestData(reference = "Remote-Directory")
private com.testsigma.sdk.TestData remoteDirectory; // Remote directory to upload to

@TestData(reference = "Remote-File-Name")
private com.testsigma.sdk.TestData remoteFileName; // Remote file name after upload

@TestData(reference = "variable-name", isRuntimeVariable = true)
private com.testsigma.sdk.TestData uploadedFilePath; // Runtime variable for storing uploaded file path

@RunTimeData
private com.testsigma.sdk.RunTimeData runTimeData;

// Method to convert Windows path to SFTP compatible format
private String convertToSFTPPath(String path) {
String os = System.getProperty("os.name").toLowerCase();

if (os.contains("win")) {
// For Windows, convert the path to SFTP style
// Example: "C:\\Users\\sam.isaac\\Downloads" -> "/C:/Users/sam.isaac/Downloads"
path = path.replace("\\", "/");
if (path.matches("^[a-zA-Z]:.*")) {
path = "/" + path.substring(0, 1).toUpperCase() + path.substring(2);
}
}
return path;
}

@Override
public com.testsigma.sdk.Result execute() throws NoSuchElementException {
com.testsigma.sdk.Result result = com.testsigma.sdk.Result.SUCCESS;
logger.info("Initiating execution for SFTP file upload");

String user = userName.getValue().toString();
String host = hostName.getValue().toString();
String password = userPassword.getValue().toString();
String localFile = localFilePath.getValue().toString();
String remoteDir = remoteDirectory.getValue().toString();
String remoteFile = remoteFileName.getValue().toString();
File localFileToUpload = null;

logger.info("remoteDir: " + remoteDir);

// Convert paths to SFTP format (handles both local and remote paths)
remoteDir = convertToSFTPPath(remoteDir);
logger.info("Remote-Directory: " + remoteDir);

JSch jsch = new JSch();
ChannelSftp channelSftp = null;
Session session = null;

try {
// Determine if the localFile is a URL or a local path
if (localFile.startsWith("http://") || localFile.startsWith("https://") || localFile.startsWith("file://")) {
localFileToUpload = downloadFile(localFile);
} else {
localFile = convertToSFTPPath(localFile);
localFileToUpload = new File(localFile);
}

logger.info("Local-File-Path: " + localFileToUpload.getAbsolutePath());


if (!localFileToUpload.exists()) {
setErrorMessage("Local file not found: " + localFile);
return Result.FAILED;
}

String localFileName = localFileToUpload.getName();
String fileExtension = "";
int dotIndex = localFileName.lastIndexOf('.');
if (dotIndex > 0) {
fileExtension = localFileName.substring(dotIndex);
}

// Append extension if remote file name has no extension
if (!remoteFile.contains(".")) {
remoteFile += fileExtension;
logger.info("Remote file name updated to include extension: " + remoteFile);
}else{
//check if extensions match
int remoteDotIndex = remoteFile.lastIndexOf('.');
String remoteFileExtension = "";
if(remoteDotIndex >0 ){
remoteFileExtension = remoteFile.substring(remoteDotIndex);
if(!remoteFileExtension.equalsIgnoreCase(fileExtension)){
setErrorMessage("Input and output file extensions do not match: " + fileExtension + " and "+ remoteFileExtension);
return Result.FAILED;
}

}
}


// Setting up the session for SFTP connection
session = jsch.getSession(user, host);
session.setPassword(password);

// Avoid host key checking (for simplicity)
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
logger.info("Session connected.");

// Setting up the SFTP channel
channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
logger.info("SFTP channel connected.");

// Check if the remote directory exists
try {
channelSftp.cd(remoteDir);
logger.info("Remote directory exists: " + remoteDir);
} catch (SftpException e) {
// If the directory does not exist, create it
logger.warn("Remote directory does not exist, creating: " + remoteDir);
channelSftp.mkdir(remoteDir);
channelSftp.cd(remoteDir);
}

// Upload the file from the local machine to the remote server
String FilePath = null;
// Correct concatenation of remote directory and file name
FilePath = remoteDir.endsWith("/") ? remoteDir + remoteFile : remoteDir + "/" + remoteFile;
channelSftp.put(localFileToUpload.getAbsolutePath(), FilePath);
logger.info("File uploaded successfully to: " + FilePath);

// Set success message and runtime data
setSuccessMessage("File uploaded successfully to: " + FilePath);
runTimeData.setKey(uploadedFilePath.getValue().toString());
runTimeData.setValue(FilePath);

} catch (Exception e) {
String errorStack = ExceptionUtils.getStackTrace(e);
logger.warn("Error occurred while uploading file: " + errorStack);
result = com.testsigma.sdk.Result.FAILED;
setErrorMessage("Error occurred during SFTP file upload: " + e.getMessage());
} finally {
// Clean up and close connections
if (channelSftp != null && channelSftp.isConnected()) {
channelSftp.disconnect();
}
if (session != null && session.isConnected()) {
session.disconnect();
}
if (localFileToUpload != null && localFile.startsWith("http")) {
localFileToUpload.delete(); // delete temp file if it was a download
}
}

return result;
}


private File downloadFile(String fileUrl) throws IOException {
URL url = new URL(fileUrl);
String fileName = Paths.get(url.getPath()).getFileName().toString();
File tempFile = File.createTempFile("downloaded-", fileName);
try (InputStream in = url.openStream();
OutputStream out = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
return tempFile;
}
}
Loading