feat: publish CodexPi contest snapshot
Some checks are pending
Qualité / tests (push) Waiting to run
Some checks are pending
Qualité / tests (push) Waiting to run
This commit is contained in:
103
scripts/codexpi-remote
Normal file
103
scripts/codexpi-remote
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from codexpi.remote_ipc import remote_channel_request
|
||||
from codexpi.remote_service import RemoteError, enqueue_remote_job
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="Accès fichier limité à une machine associée à CodexPi")
|
||||
parser.add_argument("--machine", help="identifiant de machine ; facultatif si une seule est associée")
|
||||
subparsers = parser.add_subparsers(dest="operation", required=True)
|
||||
subparsers.add_parser("machines")
|
||||
listing = subparsers.add_parser("list")
|
||||
listing.add_argument("path", nargs="?", default="")
|
||||
reading = subparsers.add_parser("read")
|
||||
reading.add_argument("path")
|
||||
writing = subparsers.add_parser("write")
|
||||
writing.add_argument("path")
|
||||
writing.add_argument("--expected", help="SHA-256 obtenu lors de la lecture, pour empêcher un écrasement concurrent")
|
||||
executing = subparsers.add_parser("exec")
|
||||
executing.add_argument("argv", nargs=argparse.REMAINDER)
|
||||
args = parser.parse_args()
|
||||
database = os.environ.get("CODEXPI_DATABASE", "/app/data/codexpi.db")
|
||||
remote_channel = os.environ.get("CODEXPI_REMOTE_CHANNEL")
|
||||
project_id = os.environ.get("CODEXPI_PROJECT_ID", "")
|
||||
if not project_id:
|
||||
print("Cette commande doit être lancée depuis une session de projet CodexPi.", file=sys.stderr)
|
||||
return 2
|
||||
try:
|
||||
if remote_channel:
|
||||
payload = None
|
||||
expected = None
|
||||
if args.operation == "write":
|
||||
if sys.stdin.isatty():
|
||||
raise RemoteError("Le contenu du fichier doit être fourni sur l’entrée standard")
|
||||
payload = {"content": sys.stdin.read()}
|
||||
expected = args.expected
|
||||
elif args.operation == "exec":
|
||||
if not args.argv:
|
||||
raise RemoteError("Indiquez la commande distante après exec")
|
||||
payload = {"argv": args.argv, "timeout": 120}
|
||||
result = remote_channel_request(remote_channel, {
|
||||
"operation": args.operation,
|
||||
"path": getattr(args, "path", ""),
|
||||
"payload": payload,
|
||||
"expected_hash": expected,
|
||||
"machine_id": args.machine,
|
||||
})
|
||||
if args.operation == "machines":
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
elif args.operation == "machines":
|
||||
import sqlite3
|
||||
connection = sqlite3.connect(database)
|
||||
connection.row_factory = sqlite3.Row
|
||||
rows = connection.execute(
|
||||
"SELECT id,name,folder_name,platform,last_seen FROM remote_machines WHERE project_id=? AND revoked_at IS NULL ORDER BY last_seen DESC",
|
||||
(project_id,),
|
||||
).fetchall()
|
||||
print(json.dumps([dict(row) for row in rows], ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
else:
|
||||
payload = None
|
||||
expected = None
|
||||
if args.operation == "write":
|
||||
if sys.stdin.isatty():
|
||||
raise RemoteError("Le contenu du fichier doit être fourni sur l’entrée standard")
|
||||
content = sys.stdin.read()
|
||||
payload = {"content": content}
|
||||
expected = args.expected
|
||||
elif args.operation == "exec":
|
||||
if not args.argv:
|
||||
raise RemoteError("Indiquez la commande distante après exec")
|
||||
payload = {"argv": args.argv, "timeout": 120}
|
||||
result = enqueue_remote_job(
|
||||
database,
|
||||
project_id,
|
||||
args.operation,
|
||||
args.path,
|
||||
payload,
|
||||
expected,
|
||||
args.machine,
|
||||
)
|
||||
if args.operation == "read":
|
||||
sys.stdout.write(str(result.get("content", "")))
|
||||
if result.get("content") and not str(result["content"]).endswith("\n"):
|
||||
sys.stdout.write("\n")
|
||||
print(f"[sha256:{result.get('sha256','')}]", file=sys.stderr)
|
||||
else:
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
except (RemoteError, OSError, ValueError) as exc:
|
||||
print(f"Erreur distante : {exc}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user