This commit is contained in:
parent
9e9d80570c
commit
d070baed0a
@ -21,6 +21,7 @@ The c++ library used, which is contained in this codebase, has two simple functi
|
||||
"user": "username", // Username for SSH connection
|
||||
"key": "path/to/key" // Path to SSH key file or "auto" to use current user's key
|
||||
},
|
||||
"working_directory": "/path", // Optional: Directory to change to before executing the command
|
||||
"env": { // Optional: Environment variables
|
||||
"VAR1": "value1",
|
||||
"VAR2": "value2"
|
||||
|
1
runner/examples/ssh_working_dir.json
Normal file
1
runner/examples/ssh_working_dir.json
Normal file
@ -0,0 +1 @@
|
||||
{"ssh":{"host":"localhost","user":"USERNAME","key":"auto"},"command":"pwd","working_directory":"/tmp"}
|
1
runner/examples/working_dir.json
Normal file
1
runner/examples/working_dir.json
Normal file
@ -0,0 +1 @@
|
||||
{"command":"pwd","working_directory":"/tmp"}
|
@ -33,6 +33,7 @@ private:
|
||||
* Execute a command locally
|
||||
* @param command Command to execute
|
||||
* @param args Command arguments
|
||||
* @param working_dir Working directory to change to before execution
|
||||
* @param env Environment variables
|
||||
* @param silent Whether to suppress output
|
||||
* @param interactive Whether to enable interactive mode
|
||||
@ -43,6 +44,7 @@ private:
|
||||
static int execute_local(
|
||||
const std::string& command,
|
||||
const std::vector<std::string>& args,
|
||||
const std::string& working_dir,
|
||||
const std::map<std::string, std::string>& env,
|
||||
bool silent,
|
||||
bool interactive,
|
||||
@ -55,6 +57,7 @@ private:
|
||||
* @param ssh_config SSH configuration
|
||||
* @param command Command to execute
|
||||
* @param args Command arguments
|
||||
* @param working_dir Working directory to change to on the remote server
|
||||
* @param env Environment variables
|
||||
* @param silent Whether to suppress output
|
||||
* @param interactive Whether to enable interactive mode
|
||||
@ -66,6 +69,7 @@ private:
|
||||
const nlohmann::json& ssh_config,
|
||||
const std::string& command,
|
||||
const std::vector<std::string>& args,
|
||||
const std::string& working_dir,
|
||||
const std::map<std::string, std::string>& env,
|
||||
bool silent,
|
||||
bool interactive,
|
||||
@ -78,6 +82,7 @@ private:
|
||||
* @param run_json JSON specification
|
||||
* @param command Output parameter for command
|
||||
* @param args Output parameter for command arguments
|
||||
* @param working_dir Output parameter for working directory
|
||||
* @param env Output parameter for environment variables
|
||||
* @param silent Output parameter for silent option
|
||||
* @param interactive Output parameter for interactive option
|
||||
@ -87,6 +92,7 @@ private:
|
||||
const nlohmann::json& run_json,
|
||||
std::string& command,
|
||||
std::vector<std::string>& args,
|
||||
std::string& working_dir,
|
||||
std::map<std::string, std::string>& env,
|
||||
bool& silent,
|
||||
bool& interactive
|
||||
|
@ -17,18 +17,19 @@ namespace dropshell {
|
||||
bool Runner::run(const nlohmann::json& run_json) {
|
||||
std::string command;
|
||||
std::vector<std::string> args;
|
||||
std::string working_dir;
|
||||
std::map<std::string, std::string> env;
|
||||
bool silent, interactive;
|
||||
|
||||
if (!parse_json(run_json, command, args, env, silent, interactive)) {
|
||||
if (!parse_json(run_json, command, args, working_dir, env, silent, interactive)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int exit_code;
|
||||
if (run_json.contains("ssh")) {
|
||||
exit_code = execute_ssh(run_json["ssh"], command, args, env, silent, interactive);
|
||||
exit_code = execute_ssh(run_json["ssh"], command, args, working_dir, env, silent, interactive);
|
||||
} else {
|
||||
exit_code = execute_local(command, args, env, silent, interactive);
|
||||
exit_code = execute_local(command, args, working_dir, env, silent, interactive);
|
||||
}
|
||||
|
||||
return exit_code == 0;
|
||||
@ -37,18 +38,19 @@ bool Runner::run(const nlohmann::json& run_json) {
|
||||
bool Runner::run(const nlohmann::json& run_json, std::string& output) {
|
||||
std::string command;
|
||||
std::vector<std::string> args;
|
||||
std::string working_dir;
|
||||
std::map<std::string, std::string> env;
|
||||
bool silent, interactive;
|
||||
|
||||
if (!parse_json(run_json, command, args, env, silent, interactive)) {
|
||||
if (!parse_json(run_json, command, args, working_dir, env, silent, interactive)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int exit_code;
|
||||
if (run_json.contains("ssh")) {
|
||||
exit_code = execute_ssh(run_json["ssh"], command, args, env, silent, interactive, &output, true);
|
||||
exit_code = execute_ssh(run_json["ssh"], command, args, working_dir, env, silent, interactive, &output, true);
|
||||
} else {
|
||||
exit_code = execute_local(command, args, env, silent, interactive, &output, true);
|
||||
exit_code = execute_local(command, args, working_dir, env, silent, interactive, &output, true);
|
||||
}
|
||||
|
||||
return exit_code == 0;
|
||||
@ -58,6 +60,7 @@ bool Runner::parse_json(
|
||||
const nlohmann::json& run_json,
|
||||
std::string& command,
|
||||
std::vector<std::string>& args,
|
||||
std::string& working_dir,
|
||||
std::map<std::string, std::string>& env,
|
||||
bool& silent,
|
||||
bool& interactive
|
||||
@ -86,6 +89,16 @@ bool Runner::parse_json(
|
||||
}
|
||||
}
|
||||
|
||||
// Working directory is optional
|
||||
working_dir = "";
|
||||
if (run_json.contains("working_directory")) {
|
||||
if (!run_json["working_directory"].is_string()) {
|
||||
std::cerr << "Error: 'working_directory' field must be a string" << std::endl;
|
||||
return false;
|
||||
}
|
||||
working_dir = run_json["working_directory"];
|
||||
}
|
||||
|
||||
// Environment variables are optional
|
||||
env.clear();
|
||||
if (run_json.contains("env")) {
|
||||
@ -138,6 +151,7 @@ bool Runner::parse_json(
|
||||
int Runner::execute_local(
|
||||
const std::string& command,
|
||||
const std::vector<std::string>& args,
|
||||
const std::string& working_dir,
|
||||
const std::map<std::string, std::string>& env,
|
||||
bool silent,
|
||||
bool interactive,
|
||||
@ -178,6 +192,14 @@ int Runner::execute_local(
|
||||
}
|
||||
}
|
||||
|
||||
// Change to working directory if specified
|
||||
if (!working_dir.empty()) {
|
||||
if (chdir(working_dir.c_str()) != 0) {
|
||||
std::cerr << "Error changing to directory " << working_dir << ": " << strerror(errno) << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Set environment variables
|
||||
for (const auto& [key, value] : env) {
|
||||
setenv(key.c_str(), value.c_str(), 1);
|
||||
@ -267,6 +289,7 @@ int Runner::execute_ssh(
|
||||
const nlohmann::json& ssh_config,
|
||||
const std::string& command,
|
||||
const std::vector<std::string>& args,
|
||||
const std::string& working_dir,
|
||||
const std::map<std::string, std::string>& env,
|
||||
bool silent,
|
||||
bool interactive,
|
||||
@ -369,6 +392,11 @@ int Runner::execute_ssh(
|
||||
cmd_stream << "export " << key << "=\"" << value << "\"; ";
|
||||
}
|
||||
|
||||
// Add cd command if working_directory is specified
|
||||
if (!working_dir.empty()) {
|
||||
cmd_stream << "cd \"" << working_dir << "\" && ";
|
||||
}
|
||||
|
||||
// Add command and args
|
||||
cmd_stream << command;
|
||||
for (const auto& arg : args) {
|
||||
|
@ -74,26 +74,58 @@ else
|
||||
fi
|
||||
echo
|
||||
|
||||
# Test working directory feature
|
||||
echo "Test 5: Working directory"
|
||||
JSON='{"command":"pwd","working_directory":"/tmp"}'
|
||||
BASE64=$(echo -n "$JSON" | base64)
|
||||
echo "JSON: $JSON"
|
||||
echo "Running command (should show /tmp)..."
|
||||
OUTPUT=$(build/runner "$BASE64")
|
||||
if [ $? -eq 0 ] && [[ "$OUTPUT" == "/tmp"* ]]; then
|
||||
echo "✅ Test 5 passed (command ran in the correct directory)"
|
||||
else
|
||||
echo "❌ Test 5 failed, unexpected output: '$OUTPUT'"
|
||||
exit 1
|
||||
fi
|
||||
echo
|
||||
|
||||
# Optional SSH test (disabled by default)
|
||||
# Set ENABLE_SSH_TEST=1 to enable this test
|
||||
if [ "${ENABLE_SSH_TEST}" = "1" ]; then
|
||||
echo "Test 5: SSH to localhost (make sure SSH server is running and you can connect to localhost)"
|
||||
echo "Test 6: SSH to localhost (make sure SSH server is running and you can connect to localhost)"
|
||||
if [ -f "examples/local_ssh.json" ]; then
|
||||
echo "Using examples/local_ssh.json for the test..."
|
||||
./run.sh examples/local_ssh.json || {
|
||||
echo "❌ Test 5 failed"
|
||||
echo "❌ Test 6 failed"
|
||||
echo "Note: This test requires SSH server running on localhost and proper key-based authentication."
|
||||
echo "Check your SSH configuration or disable this test."
|
||||
exit 1
|
||||
}
|
||||
echo "✅ Test 5 passed"
|
||||
echo "✅ Test 6 passed"
|
||||
else
|
||||
echo "❌ Test 5 failed: examples/local_ssh.json not found"
|
||||
echo "❌ Test 6 failed: examples/local_ssh.json not found"
|
||||
exit 1
|
||||
fi
|
||||
echo
|
||||
|
||||
echo "Test 7: SSH with working directory (make sure SSH server is running and you can connect to localhost)"
|
||||
if [ -f "examples/ssh_working_dir.json" ]; then
|
||||
echo "Using examples/ssh_working_dir.json for the test..."
|
||||
OUTPUT=$(./run.sh examples/ssh_working_dir.json | grep "/tmp")
|
||||
if [[ "$OUTPUT" == *"/tmp"* ]]; then
|
||||
echo "✅ Test 7 passed (SSH command ran in the correct directory)"
|
||||
else
|
||||
echo "❌ Test 7 failed, directory was not changed correctly"
|
||||
echo "Note: This test requires SSH server running on localhost and proper key-based authentication."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "❌ Test 7 failed: examples/ssh_working_dir.json not found"
|
||||
exit 1
|
||||
fi
|
||||
echo
|
||||
else
|
||||
echo "Test 5: SSH test disabled (set ENABLE_SSH_TEST=1 to enable)"
|
||||
echo "Test 6-7: SSH tests disabled (set ENABLE_SSH_TEST=1 to enable)"
|
||||
echo
|
||||
fi
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user