summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--test/test-manager/src/vm/provision.rs53
1 files changed, 41 insertions, 12 deletions
diff --git a/test/test-manager/src/vm/provision.rs b/test/test-manager/src/vm/provision.rs
index 7bda85f2a4..1ca962cbfb 100644
--- a/test/test-manager/src/vm/provision.rs
+++ b/test/test-manager/src/vm/provision.rs
@@ -4,7 +4,7 @@ use crate::{
tests::config::BOOTSTRAP_SCRIPT,
};
use anyhow::{bail, Context, Result};
-use ssh2::Session;
+use ssh2::{File, Session};
use std::{
io::{self, Read},
net::{IpAddr, SocketAddr, TcpStream},
@@ -115,27 +115,27 @@ fn blocking_ssh(
let temp_dir = Path::new(remote_temp_dir);
// Transfer a test runner
let source = local_runner_dir.join("test-runner");
- ssh_send_file(&session, &source, temp_dir)
+ ssh_send_file_with_opts(&session, &source, temp_dir, FileOpts { executable: true })
.with_context(|| format!("Failed to send '{source:?}' to remote"))?;
// Transfer connection-checker
let source = local_runner_dir.join("connection-checker");
- ssh_send_file(&session, &source, temp_dir)
+ ssh_send_file_with_opts(&session, &source, temp_dir, FileOpts { executable: true })
.with_context(|| format!("Failed to send '{source:?}' to remote"))?;
// Transfer app packages
let source = &local_app_manifest.app_package_path;
- ssh_send_file(&session, source, temp_dir)
+ ssh_send_file_with_opts(&session, source, temp_dir, FileOpts { executable: true })
.with_context(|| format!("Failed to send '{source:?}' to remote"))?;
if let Some(source) = &local_app_manifest.app_package_to_upgrade_from_path {
- ssh_send_file(&session, source, temp_dir)
+ ssh_send_file_with_opts(&session, source, temp_dir, FileOpts { executable: true })
.with_context(|| format!("Failed to send '{source:?}' to remote"))?;
} else {
log::warn!("No previous app package to upgrade from to send to remote")
}
if let Some(source) = &local_app_manifest.gui_package_path {
- ssh_send_file(&session, source, temp_dir)
+ ssh_send_file_with_opts(&session, source, temp_dir, FileOpts { executable: true })
.with_context(|| format!("Failed to send '{source:?}' to remote"))?;
} else {
log::warn!("No UI e2e test to send to remote")
@@ -182,13 +182,14 @@ fn blocking_ssh(
Ok(remote_dir.to_string())
}
-/// Copy a `source` file to `dest_dir` in the test runner.
+/// Copy a `source` file to `dest_dir` in the test runner with opts.
///
-/// Returns the aboslute path in the test runner where the file is stored.
-fn ssh_send_file<P: AsRef<Path> + Copy>(
+/// Returns the absolute path in the test runner where the file is stored.
+fn ssh_send_file_with_opts<P: AsRef<Path> + Copy>(
session: &Session,
source: P,
dest_dir: &Path,
+ opts: FileOpts,
) -> Result<PathBuf> {
let dest = dest_dir.join(
source
@@ -206,18 +207,46 @@ fn ssh_send_file<P: AsRef<Path> + Copy>(
let source = std::fs::read(source)
.with_context(|| format!("Failed to open file at {}", source.as_ref().display()))?;
- ssh_write(session, &dest, &source[..])?;
+ ssh_write_with_opts(session, &dest, &source[..], opts)?;
Ok(dest)
}
-/// Analogues to [`std::fs::write`], but over ssh!
-fn ssh_write<P: AsRef<Path>>(session: &Session, dest: P, mut source: impl Read) -> Result<()> {
+/// Create a new file with opts at location `dest` and write the content of `source` into it.
+/// Returns a handle to the newly created file.
+fn ssh_write_with_opts<P: AsRef<Path>>(
+ session: &Session,
+ dest: P,
+ mut source: impl Read,
+ opts: FileOpts,
+) -> Result<File> {
let sftp = session.sftp()?;
let mut remote_file = sftp.create(dest.as_ref())?;
io::copy(&mut source, &mut remote_file).context("failed to write file")?;
+ if opts.executable {
+ make_executable(&mut remote_file)?;
+ };
+
+ Ok(remote_file)
+}
+
+/// Extra options that may be necessary to configure for files written to the test runner VM.
+/// Used in conjunction with the `ssh_*_with_opts` functions.
+#[derive(Clone, Copy, Debug, Default)]
+struct FileOpts {
+ /// If file should be executable.
+ executable: bool,
+}
+
+fn make_executable(file: &mut File) -> Result<()> {
+ // Make sure that the script is executable!
+ let mut file_stat = file.stat()?;
+ // 0x111 is the executable bit for Owner/Group/Public
+ let perm = file_stat.perm.map(|perm| perm | 0x111).unwrap_or(0x111);
+ file_stat.perm = Some(perm);
+ file.setstat(file_stat)?;
Ok(())
}