REFACTOR(repo): simplify project structure
Some checks failed
Build Docker Image / build-and-push (push) Has been cancelled
Some checks failed
Build Docker Image / build-and-push (push) Has been cancelled
- Move services/backend to langgraph/ - Move deploy/docker/Dockerfile to Dockerfile - Remove deploy/, services/ folders - Update GitHub Actions workflow paths - Remove kustomization update logic (managed by K3S-HOME/applications)
This commit is contained in:
132
langgraph/tools/bash_tool.py
Normal file
132
langgraph/tools/bash_tool.py
Normal file
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
Bash 명령어 실행 도구
|
||||
"""
|
||||
import subprocess
|
||||
import shlex
|
||||
from langchain_core.tools import tool
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@tool
|
||||
def execute_bash(command: str, timeout: int = 30, cwd: Optional[str] = None) -> str:
|
||||
"""
|
||||
Execute a bash command in the container.
|
||||
|
||||
Args:
|
||||
command: Bash command to execute
|
||||
timeout: Command timeout in seconds (default: 30)
|
||||
cwd: Working directory (default: None)
|
||||
|
||||
Returns:
|
||||
Command output or error message
|
||||
|
||||
Examples:
|
||||
- execute_bash("ls -la /app")
|
||||
- execute_bash("python --version")
|
||||
- execute_bash("curl -s http://prometheus:9090/api/v1/query?query=up")
|
||||
"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
command,
|
||||
shell=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=timeout,
|
||||
cwd=cwd
|
||||
)
|
||||
|
||||
# Combine stdout and stderr
|
||||
output = result.stdout
|
||||
if result.stderr:
|
||||
output += f"\n[STDERR]:\n{result.stderr}"
|
||||
|
||||
if result.returncode != 0:
|
||||
return f"❌ Command failed (exit code {result.returncode}):\n{output}"
|
||||
|
||||
return f"✅ Command executed successfully:\n{output}"
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
return f"❌ Command timed out after {timeout} seconds"
|
||||
except Exception as e:
|
||||
return f"❌ Error executing command: {str(e)}"
|
||||
|
||||
|
||||
@tool
|
||||
def execute_host(command: str, timeout: int = 30, use_sudo: bool = False) -> str:
|
||||
"""
|
||||
Execute command on the HOST system using nsenter (NO SSH needed!).
|
||||
|
||||
USE THIS for accessing the host system:
|
||||
- kubectl commands (Kubernetes cluster management)
|
||||
- Accessing /home/ubuntu/Projects/ (Git repositories)
|
||||
- PostgreSQL queries (via psql)
|
||||
- Git operations on host repositories
|
||||
- File system operations on host
|
||||
- ALL host system operations
|
||||
|
||||
This works by entering the host's namespaces directly from the container.
|
||||
Much faster than SSH and no authentication needed!
|
||||
|
||||
NOTE: Projects folder is located at /home/ubuntu/Projects/ on oracle-master server.
|
||||
|
||||
Args:
|
||||
command: Command to run on the host system
|
||||
timeout: Command timeout in seconds (default: 30)
|
||||
use_sudo: Whether to prepend 'sudo' to the command (default: False)
|
||||
|
||||
Returns:
|
||||
Command output or error message
|
||||
|
||||
Examples:
|
||||
- execute_host("kubectl get pods -n mas", use_sudo=True)
|
||||
- execute_host("ls -la /home/ubuntu/Projects")
|
||||
- execute_host("cat /home/ubuntu/Projects/mas/README.md")
|
||||
- execute_host("cd /home/ubuntu/Projects/mas && git log -5 --oneline")
|
||||
- execute_host("psql -U bluemayne -h postgresql-primary.postgresql.svc.cluster.local -d postgres -c 'SELECT version()'")
|
||||
"""
|
||||
try:
|
||||
# Use nsenter to enter host namespaces
|
||||
# -t 1: target PID 1 (init process on host)
|
||||
# -m: mount namespace
|
||||
# -u: UTS namespace (hostname)
|
||||
# -n: network namespace
|
||||
# -i: IPC namespace
|
||||
# Run as ubuntu user to avoid git "dubious ownership" errors
|
||||
# Use 'su ubuntu -c' (without -) to preserve current directory context
|
||||
# This allows commands to work from SSH initial directory
|
||||
if use_sudo:
|
||||
# For sudo commands, run directly with sudo
|
||||
# Use shlex.quote to safely quote the command while preserving shell expansion
|
||||
nsenter_command = f"nsenter -t 1 -m -u -n -i -- sh -c {shlex.quote(f'sudo {command}')}"
|
||||
else:
|
||||
# For regular commands, run as ubuntu user
|
||||
# Use 'su ubuntu -c' (not 'su - ubuntu -c') to preserve current directory
|
||||
# This matches SSH behavior where you start from the initial directory
|
||||
nsenter_command = f"nsenter -t 1 -m -u -n -i -- su ubuntu -c {shlex.quote(command)}"
|
||||
|
||||
result = subprocess.run(
|
||||
nsenter_command,
|
||||
shell=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=timeout
|
||||
)
|
||||
|
||||
# Combine stdout and stderr
|
||||
output = result.stdout
|
||||
if result.stderr:
|
||||
output += f"\n[STDERR]:\n{result.stderr}"
|
||||
|
||||
if result.returncode != 0:
|
||||
return f"❌ Host command failed (exit code {result.returncode}):\n{output}"
|
||||
|
||||
return f"✅ Host command executed successfully:\n{output}"
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
return f"❌ Host command timed out after {timeout} seconds"
|
||||
except Exception as e:
|
||||
return f"❌ Error executing host command: {str(e)}"
|
||||
|
||||
|
||||
# Export both tools
|
||||
bash_tools = [execute_bash, execute_host]
|
||||
Reference in New Issue
Block a user