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
|
"user": "username", // Username for SSH connection
|
||||||
"key": "path/to/key" // Path to SSH key file or "auto" to use current user's key
|
"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
|
"env": { // Optional: Environment variables
|
||||||
"VAR1": "value1",
|
"VAR1": "value1",
|
||||||
"VAR2": "value2"
|
"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
|
* Execute a command locally
|
||||||
* @param command Command to execute
|
* @param command Command to execute
|
||||||
* @param args Command arguments
|
* @param args Command arguments
|
||||||
|
* @param working_dir Working directory to change to before execution
|
||||||
* @param env Environment variables
|
* @param env Environment variables
|
||||||
* @param silent Whether to suppress output
|
* @param silent Whether to suppress output
|
||||||
* @param interactive Whether to enable interactive mode
|
* @param interactive Whether to enable interactive mode
|
||||||
@ -43,6 +44,7 @@ private:
|
|||||||
static int execute_local(
|
static int execute_local(
|
||||||
const std::string& command,
|
const std::string& command,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
|
const std::string& working_dir,
|
||||||
const std::map<std::string, std::string>& env,
|
const std::map<std::string, std::string>& env,
|
||||||
bool silent,
|
bool silent,
|
||||||
bool interactive,
|
bool interactive,
|
||||||
@ -55,6 +57,7 @@ private:
|
|||||||
* @param ssh_config SSH configuration
|
* @param ssh_config SSH configuration
|
||||||
* @param command Command to execute
|
* @param command Command to execute
|
||||||
* @param args Command arguments
|
* @param args Command arguments
|
||||||
|
* @param working_dir Working directory to change to on the remote server
|
||||||
* @param env Environment variables
|
* @param env Environment variables
|
||||||
* @param silent Whether to suppress output
|
* @param silent Whether to suppress output
|
||||||
* @param interactive Whether to enable interactive mode
|
* @param interactive Whether to enable interactive mode
|
||||||
@ -66,6 +69,7 @@ private:
|
|||||||
const nlohmann::json& ssh_config,
|
const nlohmann::json& ssh_config,
|
||||||
const std::string& command,
|
const std::string& command,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
|
const std::string& working_dir,
|
||||||
const std::map<std::string, std::string>& env,
|
const std::map<std::string, std::string>& env,
|
||||||
bool silent,
|
bool silent,
|
||||||
bool interactive,
|
bool interactive,
|
||||||
@ -78,6 +82,7 @@ private:
|
|||||||
* @param run_json JSON specification
|
* @param run_json JSON specification
|
||||||
* @param command Output parameter for command
|
* @param command Output parameter for command
|
||||||
* @param args Output parameter for command arguments
|
* @param args Output parameter for command arguments
|
||||||
|
* @param working_dir Output parameter for working directory
|
||||||
* @param env Output parameter for environment variables
|
* @param env Output parameter for environment variables
|
||||||
* @param silent Output parameter for silent option
|
* @param silent Output parameter for silent option
|
||||||
* @param interactive Output parameter for interactive option
|
* @param interactive Output parameter for interactive option
|
||||||
@ -87,6 +92,7 @@ private:
|
|||||||
const nlohmann::json& run_json,
|
const nlohmann::json& run_json,
|
||||||
std::string& command,
|
std::string& command,
|
||||||
std::vector<std::string>& args,
|
std::vector<std::string>& args,
|
||||||
|
std::string& working_dir,
|
||||||
std::map<std::string, std::string>& env,
|
std::map<std::string, std::string>& env,
|
||||||
bool& silent,
|
bool& silent,
|
||||||
bool& interactive
|
bool& interactive
|
||||||
|
@ -17,18 +17,19 @@ namespace dropshell {
|
|||||||
bool Runner::run(const nlohmann::json& run_json) {
|
bool Runner::run(const nlohmann::json& run_json) {
|
||||||
std::string command;
|
std::string command;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
std::string working_dir;
|
||||||
std::map<std::string, std::string> env;
|
std::map<std::string, std::string> env;
|
||||||
bool silent, interactive;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exit_code;
|
int exit_code;
|
||||||
if (run_json.contains("ssh")) {
|
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 {
|
} 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;
|
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) {
|
bool Runner::run(const nlohmann::json& run_json, std::string& output) {
|
||||||
std::string command;
|
std::string command;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
std::string working_dir;
|
||||||
std::map<std::string, std::string> env;
|
std::map<std::string, std::string> env;
|
||||||
bool silent, interactive;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exit_code;
|
int exit_code;
|
||||||
if (run_json.contains("ssh")) {
|
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 {
|
} 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;
|
return exit_code == 0;
|
||||||
@ -58,6 +60,7 @@ bool Runner::parse_json(
|
|||||||
const nlohmann::json& run_json,
|
const nlohmann::json& run_json,
|
||||||
std::string& command,
|
std::string& command,
|
||||||
std::vector<std::string>& args,
|
std::vector<std::string>& args,
|
||||||
|
std::string& working_dir,
|
||||||
std::map<std::string, std::string>& env,
|
std::map<std::string, std::string>& env,
|
||||||
bool& silent,
|
bool& silent,
|
||||||
bool& interactive
|
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
|
// Environment variables are optional
|
||||||
env.clear();
|
env.clear();
|
||||||
if (run_json.contains("env")) {
|
if (run_json.contains("env")) {
|
||||||
@ -138,6 +151,7 @@ bool Runner::parse_json(
|
|||||||
int Runner::execute_local(
|
int Runner::execute_local(
|
||||||
const std::string& command,
|
const std::string& command,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
|
const std::string& working_dir,
|
||||||
const std::map<std::string, std::string>& env,
|
const std::map<std::string, std::string>& env,
|
||||||
bool silent,
|
bool silent,
|
||||||
bool interactive,
|
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
|
// Set environment variables
|
||||||
for (const auto& [key, value] : env) {
|
for (const auto& [key, value] : env) {
|
||||||
setenv(key.c_str(), value.c_str(), 1);
|
setenv(key.c_str(), value.c_str(), 1);
|
||||||
@ -267,6 +289,7 @@ int Runner::execute_ssh(
|
|||||||
const nlohmann::json& ssh_config,
|
const nlohmann::json& ssh_config,
|
||||||
const std::string& command,
|
const std::string& command,
|
||||||
const std::vector<std::string>& args,
|
const std::vector<std::string>& args,
|
||||||
|
const std::string& working_dir,
|
||||||
const std::map<std::string, std::string>& env,
|
const std::map<std::string, std::string>& env,
|
||||||
bool silent,
|
bool silent,
|
||||||
bool interactive,
|
bool interactive,
|
||||||
@ -369,6 +392,11 @@ int Runner::execute_ssh(
|
|||||||
cmd_stream << "export " << key << "=\"" << value << "\"; ";
|
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
|
// Add command and args
|
||||||
cmd_stream << command;
|
cmd_stream << command;
|
||||||
for (const auto& arg : args) {
|
for (const auto& arg : args) {
|
||||||
|
@ -74,26 +74,58 @@ else
|
|||||||
fi
|
fi
|
||||||
echo
|
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)
|
# Optional SSH test (disabled by default)
|
||||||
# Set ENABLE_SSH_TEST=1 to enable this test
|
# Set ENABLE_SSH_TEST=1 to enable this test
|
||||||
if [ "${ENABLE_SSH_TEST}" = "1" ]; then
|
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
|
if [ -f "examples/local_ssh.json" ]; then
|
||||||
echo "Using examples/local_ssh.json for the test..."
|
echo "Using examples/local_ssh.json for the test..."
|
||||||
./run.sh examples/local_ssh.json || {
|
./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 "Note: This test requires SSH server running on localhost and proper key-based authentication."
|
||||||
echo "Check your SSH configuration or disable this test."
|
echo "Check your SSH configuration or disable this test."
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
echo "✅ Test 5 passed"
|
echo "✅ Test 6 passed"
|
||||||
else
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo
|
echo
|
||||||
else
|
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
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user