Added many tools
This commit is contained in:
225
tools/docker.py
225
tools/docker.py
@@ -0,0 +1,225 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from core.tools.base import BaseTool, ToolContext
|
||||
from core.tools.registry import registry
|
||||
from core.events import bus
|
||||
from core.subprocess import run_command
|
||||
|
||||
|
||||
class DockerTool(BaseTool):
|
||||
name = "docker"
|
||||
description = "Docker container and image management"
|
||||
|
||||
# =========================================================
|
||||
# EXECUTE ROUTER
|
||||
# =========================================================
|
||||
|
||||
def execute(self, payload: dict[str, Any], ctx: ToolContext):
|
||||
action = str(payload.get("action", "")).strip()
|
||||
|
||||
bus.log(
|
||||
"DOCKER",
|
||||
"docker_execute",
|
||||
"INFO",
|
||||
{"action": action}
|
||||
)
|
||||
|
||||
match action:
|
||||
case "ps":
|
||||
return self.ps(payload)
|
||||
|
||||
case "run":
|
||||
return self.run_container(payload, ctx)
|
||||
|
||||
case "stop":
|
||||
return self.stop_container(payload)
|
||||
|
||||
case "start":
|
||||
return self.start_container(payload)
|
||||
|
||||
case "restart":
|
||||
return self.restart_container(payload)
|
||||
|
||||
case "logs":
|
||||
return self.logs(payload)
|
||||
|
||||
case "images":
|
||||
return self.images(payload)
|
||||
|
||||
case "build":
|
||||
return self.build_image(payload, ctx)
|
||||
|
||||
case _:
|
||||
raise ValueError(f"Unknown docker action: {action}")
|
||||
|
||||
# =========================================================
|
||||
# CONTAINERS LIST
|
||||
# =========================================================
|
||||
|
||||
def ps(self, payload: dict[str, Any]):
|
||||
all_containers = payload.get("all", False)
|
||||
|
||||
cmd = ["docker", "ps"]
|
||||
if all_containers:
|
||||
cmd.append("-a")
|
||||
|
||||
result = run_command(cmd=cmd)
|
||||
|
||||
return {
|
||||
"action": "ps",
|
||||
"status": "ok" if result.get("return_code") == 0 else "error",
|
||||
"output": result.get("stdout", ""),
|
||||
"error": result.get("stderr", "")
|
||||
}
|
||||
|
||||
# =========================================================
|
||||
# RUN CONTAINER
|
||||
# =========================================================
|
||||
|
||||
def run_container(self, payload: dict[str, Any], ctx: ToolContext):
|
||||
image = payload.get("image")
|
||||
name = payload.get("name")
|
||||
args = payload.get("args", [])
|
||||
|
||||
if not isinstance(image, str):
|
||||
raise ValueError("image must be string")
|
||||
|
||||
if not isinstance(args, list):
|
||||
raise ValueError("args must be list")
|
||||
|
||||
cmd = ["docker", "run"]
|
||||
|
||||
if name:
|
||||
if not isinstance(name, str):
|
||||
raise ValueError("name must be string")
|
||||
cmd += ["--name", name]
|
||||
|
||||
cmd += args
|
||||
cmd.append(image)
|
||||
|
||||
if ctx.dry_run:
|
||||
return {
|
||||
"dry_run": True,
|
||||
"command": cmd
|
||||
}
|
||||
|
||||
result = run_command(cmd=cmd)
|
||||
|
||||
return {
|
||||
"action": "run",
|
||||
"image": image,
|
||||
"status": "ok" if result.get("return_code") == 0 else "error",
|
||||
"stdout": result.get("stdout", ""),
|
||||
"stderr": result.get("stderr", "")
|
||||
}
|
||||
|
||||
# =========================================================
|
||||
# STOP / START / RESTART
|
||||
# =========================================================
|
||||
|
||||
def stop_container(self, payload: dict[str, Any]):
|
||||
return self._simple_container_action("stop", payload)
|
||||
|
||||
def start_container(self, payload: dict[str, Any]):
|
||||
return self._simple_container_action("start", payload)
|
||||
|
||||
def restart_container(self, payload: dict[str, Any]):
|
||||
return self._simple_container_action("restart", payload)
|
||||
|
||||
def _simple_container_action(self, action: str, payload: dict[str, Any]):
|
||||
container = payload.get("container")
|
||||
|
||||
if not isinstance(container, str):
|
||||
raise ValueError("container must be string")
|
||||
|
||||
result = run_command(
|
||||
cmd=["docker", action, container]
|
||||
)
|
||||
|
||||
return {
|
||||
"action": action,
|
||||
"container": container,
|
||||
"status": "ok" if result.get("return_code") == 0 else "error",
|
||||
"stdout": result.get("stdout", ""),
|
||||
"stderr": result.get("stderr", "")
|
||||
}
|
||||
|
||||
# =========================================================
|
||||
# LOGS
|
||||
# =========================================================
|
||||
|
||||
def logs(self, payload: dict[str, Any]):
|
||||
container = payload.get("container")
|
||||
tail = payload.get("tail", 100)
|
||||
|
||||
if not isinstance(container, str):
|
||||
raise ValueError("container must be string")
|
||||
|
||||
cmd = ["docker", "logs", "--tail", str(tail), container]
|
||||
|
||||
result = run_command(cmd=cmd)
|
||||
|
||||
return {
|
||||
"action": "logs",
|
||||
"container": container,
|
||||
"output": result.get("stdout", ""),
|
||||
"error": result.get("stderr", "")
|
||||
}
|
||||
|
||||
# =========================================================
|
||||
# IMAGES
|
||||
# =========================================================
|
||||
|
||||
def images(self, payload: dict[str, Any]):
|
||||
result = run_command(cmd=["docker", "images"])
|
||||
|
||||
return {
|
||||
"action": "images",
|
||||
"output": result.get("stdout", ""),
|
||||
"error": result.get("stderr", "")
|
||||
}
|
||||
|
||||
# =========================================================
|
||||
# BUILD IMAGE
|
||||
# =========================================================
|
||||
|
||||
def build_image(self, payload: dict[str, Any], ctx: ToolContext):
|
||||
path = payload.get("path", ".")
|
||||
tag = payload.get("tag")
|
||||
|
||||
if not isinstance(path, str):
|
||||
raise ValueError("path must be string")
|
||||
|
||||
cmd = ["docker", "build", "-t"]
|
||||
|
||||
if isinstance(tag, str):
|
||||
cmd.append(tag)
|
||||
else:
|
||||
cmd.append("untagged-image")
|
||||
|
||||
cmd.append(path)
|
||||
|
||||
if ctx.dry_run:
|
||||
return {
|
||||
"dry_run": True,
|
||||
"command": cmd
|
||||
}
|
||||
|
||||
result = run_command(cmd=cmd)
|
||||
|
||||
return {
|
||||
"action": "build",
|
||||
"path": path,
|
||||
"status": "ok" if result.get("return_code") == 0 else "error",
|
||||
"stdout": result.get("stdout", ""),
|
||||
"stderr": result.get("stderr", "")
|
||||
}
|
||||
|
||||
|
||||
# =========================================================
|
||||
# REGISTER TOOL
|
||||
# =========================================================
|
||||
|
||||
registry.register(DockerTool())
|
||||
Reference in New Issue
Block a user
