mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-10-26 17:21:58 -06:00
Persist assemblies as base64 and decode for execution
This commit is contained in:
@@ -7,6 +7,7 @@ import time
|
||||
import json
|
||||
import socket
|
||||
import subprocess
|
||||
import base64
|
||||
from typing import Optional
|
||||
|
||||
try:
|
||||
@@ -39,6 +40,39 @@ def _project_root():
|
||||
return os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
|
||||
def _decode_base64_text(value):
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
stripped = value.strip()
|
||||
if not stripped:
|
||||
return ""
|
||||
cleaned = ''.join(stripped.split())
|
||||
if not cleaned:
|
||||
return ""
|
||||
try:
|
||||
decoded = base64.b64decode(cleaned, validate=True)
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
return decoded.decode('utf-8')
|
||||
except Exception:
|
||||
return decoded.decode('utf-8', errors='replace')
|
||||
|
||||
|
||||
def _decode_playbook_content(raw_content, encoding_hint):
|
||||
if isinstance(raw_content, str):
|
||||
encoding = str(encoding_hint or '').strip().lower()
|
||||
if encoding in ('base64', 'b64', 'base-64'):
|
||||
decoded = _decode_base64_text(raw_content)
|
||||
if decoded is not None:
|
||||
return decoded
|
||||
decoded = _decode_base64_text(raw_content)
|
||||
if decoded is not None:
|
||||
return decoded
|
||||
return raw_content
|
||||
return ''
|
||||
|
||||
|
||||
def _agent_root():
|
||||
# Resolve Agent root at runtime.
|
||||
# Typical runtime: <ProjectRoot>/Agent/Borealis/Roles/<this_file>
|
||||
@@ -801,7 +835,7 @@ try {{
|
||||
return
|
||||
# Accept provided run_id or generate one
|
||||
run_id = (payload.get('run_id') or '').strip() or uuid.uuid4().hex
|
||||
content = payload.get('playbook_content') or ''
|
||||
content = _decode_playbook_content(payload.get('playbook_content'), payload.get('playbook_encoding'))
|
||||
p_name = payload.get('playbook_name') or ''
|
||||
act_id = payload.get('activity_job_id')
|
||||
sched_job_id = payload.get('scheduled_job_id')
|
||||
@@ -874,7 +908,7 @@ try {{
|
||||
if target and target != hostname.lower():
|
||||
return
|
||||
run_id = uuid.uuid4().hex
|
||||
content = payload.get('script_content') or ''
|
||||
content = _decode_playbook_content(payload.get('script_content'), payload.get('script_encoding'))
|
||||
p_name = payload.get('script_name') or ''
|
||||
self._runs[run_id] = {'cancel': False, 'proc': None}
|
||||
asyncio.create_task(self._run_playbook(run_id, content, playbook_name=p_name, activity_job_id=payload.get('job_id'), connection='local'))
|
||||
|
||||
@@ -4,7 +4,8 @@ import re
|
||||
import asyncio
|
||||
import tempfile
|
||||
import uuid
|
||||
from typing import Dict, List
|
||||
import base64
|
||||
from typing import Dict, List, Optional
|
||||
from PyQt5 import QtWidgets, QtGui
|
||||
|
||||
|
||||
@@ -65,6 +66,40 @@ def _apply_variable_aliases(env_map: Dict[str, str], variables: List[Dict[str, s
|
||||
return env_map
|
||||
|
||||
|
||||
def _decode_base64_text(value: str) -> Optional[str]:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
stripped = value.strip()
|
||||
if not stripped:
|
||||
return ""
|
||||
try:
|
||||
cleaned = re.sub(r"\s+", "", stripped)
|
||||
except Exception:
|
||||
cleaned = stripped
|
||||
try:
|
||||
decoded = base64.b64decode(cleaned, validate=True)
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
return decoded.decode("utf-8")
|
||||
except Exception:
|
||||
return decoded.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def _decode_script_content(raw_content, encoding_hint) -> str:
|
||||
if isinstance(raw_content, str):
|
||||
encoding = str(encoding_hint or "").strip().lower()
|
||||
if encoding in ("base64", "b64", "base-64"):
|
||||
decoded = _decode_base64_text(raw_content)
|
||||
if decoded is not None:
|
||||
return decoded
|
||||
decoded = _decode_base64_text(raw_content)
|
||||
if decoded is not None:
|
||||
return decoded
|
||||
return raw_content
|
||||
return ""
|
||||
|
||||
|
||||
def _ps_literal(value: str) -> str:
|
||||
return "'" + value.replace("'", "''") + "'"
|
||||
|
||||
@@ -242,7 +277,7 @@ class Role:
|
||||
job_id = payload.get('job_id')
|
||||
script_type = (payload.get('script_type') or '').lower()
|
||||
run_mode = (payload.get('run_mode') or 'current_user').lower()
|
||||
content = payload.get('script_content') or ''
|
||||
content = _decode_script_content(payload.get('script_content'), payload.get('script_encoding'))
|
||||
raw_env = payload.get('environment')
|
||||
env_map = _sanitize_env_map(raw_env)
|
||||
variables = payload.get('variables') if isinstance(payload.get('variables'), list) else []
|
||||
|
||||
@@ -5,7 +5,8 @@ import tempfile
|
||||
import uuid
|
||||
import time
|
||||
import subprocess
|
||||
from typing import Dict, List
|
||||
import base64
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
|
||||
ROLE_NAME = 'script_exec_system'
|
||||
@@ -67,6 +68,40 @@ def _apply_variable_aliases(env_map: Dict[str, str], variables: List[Dict[str, s
|
||||
return env_map
|
||||
|
||||
|
||||
def _decode_base64_text(value: str) -> Optional[str]:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
stripped = value.strip()
|
||||
if not stripped:
|
||||
return ""
|
||||
try:
|
||||
cleaned = re.sub(r"\s+", "", stripped)
|
||||
except Exception:
|
||||
cleaned = stripped
|
||||
try:
|
||||
decoded = base64.b64decode(cleaned, validate=True)
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
return decoded.decode("utf-8")
|
||||
except Exception:
|
||||
return decoded.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def _decode_script_content(raw_content, encoding_hint) -> str:
|
||||
if isinstance(raw_content, str):
|
||||
encoding = str(encoding_hint or "").strip().lower()
|
||||
if encoding in ("base64", "b64", "base-64"):
|
||||
decoded = _decode_base64_text(raw_content)
|
||||
if decoded is not None:
|
||||
return decoded
|
||||
decoded = _decode_base64_text(raw_content)
|
||||
if decoded is not None:
|
||||
return decoded
|
||||
return raw_content
|
||||
return ""
|
||||
|
||||
|
||||
def _ps_literal(value: str) -> str:
|
||||
return "'" + value.replace("'", "''") + "'"
|
||||
|
||||
@@ -236,7 +271,7 @@ class Role:
|
||||
return
|
||||
job_id = payload.get('job_id')
|
||||
script_type = (payload.get('script_type') or '').lower()
|
||||
content = payload.get('script_content') or ''
|
||||
content = _decode_script_content(payload.get('script_content'), payload.get('script_encoding'))
|
||||
raw_env = payload.get('environment')
|
||||
env_map = _sanitize_env_map(raw_env)
|
||||
variables = payload.get('variables') if isinstance(payload.get('variables'), list) else []
|
||||
|
||||
@@ -156,6 +156,39 @@ def _log_agent(message: str, fname: str = 'agent.log'):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _decode_base64_text(value):
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
stripped = value.strip()
|
||||
if not stripped:
|
||||
return ""
|
||||
cleaned = ''.join(stripped.split())
|
||||
if not cleaned:
|
||||
return ""
|
||||
try:
|
||||
decoded = base64.b64decode(cleaned, validate=True)
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
return decoded.decode('utf-8')
|
||||
except Exception:
|
||||
return decoded.decode('utf-8', errors='replace')
|
||||
|
||||
|
||||
def _decode_script_payload(content, encoding_hint):
|
||||
if isinstance(content, str):
|
||||
encoding = str(encoding_hint or '').strip().lower()
|
||||
if encoding in ('base64', 'b64', 'base-64'):
|
||||
decoded = _decode_base64_text(content)
|
||||
if decoded is not None:
|
||||
return decoded
|
||||
decoded = _decode_base64_text(content)
|
||||
if decoded is not None:
|
||||
return decoded
|
||||
return content
|
||||
return ''
|
||||
|
||||
def _resolve_config_path():
|
||||
"""
|
||||
Resolve the path for agent settings json in the centralized location:
|
||||
@@ -1520,7 +1553,7 @@ if __name__=='__main__':
|
||||
return
|
||||
job_id = payload.get('job_id')
|
||||
script_type = (payload.get('script_type') or '').lower()
|
||||
content = payload.get('script_content') or ''
|
||||
content = _decode_script_payload(payload.get('script_content'), payload.get('script_encoding'))
|
||||
run_mode = (payload.get('run_mode') or 'current_user').lower()
|
||||
if script_type != 'powershell':
|
||||
await sio.emit('quick_job_result', { 'job_id': job_id, 'status': 'Failed', 'stdout': '', 'stderr': f"Unsupported type: {script_type}" })
|
||||
|
||||
@@ -198,6 +198,61 @@ function normalizeVariablesFromServer(vars = []) {
|
||||
}));
|
||||
}
|
||||
|
||||
function decodeBase64String(data = "") {
|
||||
if (typeof data !== "string") {
|
||||
return { success: false, value: "" };
|
||||
}
|
||||
if (!data.trim()) {
|
||||
return { success: true, value: "" };
|
||||
}
|
||||
try {
|
||||
if (typeof window !== "undefined" && typeof window.atob === "function") {
|
||||
const binary = window.atob(data);
|
||||
if (typeof TextDecoder !== "undefined") {
|
||||
const decoder = new TextDecoder("utf-8", { fatal: false });
|
||||
return { success: true, value: decoder.decode(Uint8Array.from(binary, (c) => c.charCodeAt(0))) };
|
||||
}
|
||||
return { success: true, value: binary };
|
||||
}
|
||||
} catch (err) {
|
||||
// fall through to Buffer fallback
|
||||
}
|
||||
try {
|
||||
if (typeof Buffer !== "undefined") {
|
||||
return { success: true, value: Buffer.from(data, "base64").toString("utf-8") };
|
||||
}
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
return { success: false, value: "" };
|
||||
}
|
||||
|
||||
function encodeBase64String(text = "") {
|
||||
if (typeof text !== "string") {
|
||||
text = text == null ? "" : String(text);
|
||||
}
|
||||
if (!text) return "";
|
||||
try {
|
||||
if (typeof TextEncoder !== "undefined" && typeof window !== "undefined" && typeof window.btoa === "function") {
|
||||
const encoder = new TextEncoder();
|
||||
const bytes = encoder.encode(text);
|
||||
let binary = "";
|
||||
bytes.forEach((b) => { binary += String.fromCharCode(b); });
|
||||
return window.btoa(binary);
|
||||
}
|
||||
} catch (err) {
|
||||
// fall through to Buffer fallback
|
||||
}
|
||||
try {
|
||||
if (typeof Buffer !== "undefined") {
|
||||
return Buffer.from(text, "utf-8").toString("base64");
|
||||
}
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function normalizeFilesFromServer(files = []) {
|
||||
return (Array.isArray(files) ? files : []).map((f, idx) => ({
|
||||
id: `${Date.now()}_${idx}_${Math.random().toString(36).slice(2, 8)}`,
|
||||
@@ -219,7 +274,20 @@ function fromServerDocument(doc = {}, defaultType = "powershell") {
|
||||
? doc.script_lines.map((line) => (line == null ? "" : String(line))).join("\n")
|
||||
: "";
|
||||
const script = doc.script ?? doc.content ?? legacyScript;
|
||||
assembly.script = typeof script === "string" ? script : legacyScript;
|
||||
if (typeof script === "string") {
|
||||
const encoding = (doc.script_encoding || doc.scriptEncoding || "").toLowerCase();
|
||||
if (["base64", "b64", "base-64"].includes(encoding)) {
|
||||
const decoded = decodeBase64String(script);
|
||||
assembly.script = decoded.success ? decoded.value : "";
|
||||
} else if (!encoding) {
|
||||
const decoded = decodeBase64String(script);
|
||||
assembly.script = decoded.success ? decoded.value : script;
|
||||
} else {
|
||||
assembly.script = script;
|
||||
}
|
||||
} else {
|
||||
assembly.script = legacyScript;
|
||||
}
|
||||
const timeout = doc.timeout_seconds ?? doc.timeout ?? assembly.timeoutSeconds;
|
||||
assembly.timeoutSeconds = Number.isFinite(Number(timeout))
|
||||
? Number(timeout)
|
||||
@@ -241,13 +309,15 @@ function toServerDocument(assembly) {
|
||||
: "";
|
||||
const timeoutNumeric = Number(assembly.timeoutSeconds);
|
||||
const timeoutSeconds = Number.isFinite(timeoutNumeric) ? Math.max(0, Math.round(timeoutNumeric)) : 3600;
|
||||
const encodedScript = encodeBase64String(normalizedScript);
|
||||
return {
|
||||
version: 1,
|
||||
name: assembly.name?.trim() || "",
|
||||
description: assembly.description || "",
|
||||
category: assembly.category || "script",
|
||||
type: assembly.type || "powershell",
|
||||
script: normalizedScript,
|
||||
script: encodedScript,
|
||||
script_encoding: "base64",
|
||||
timeout_seconds: timeoutSeconds,
|
||||
sites: {
|
||||
mode: assembly.sites?.mode === "specific" ? "specific" : "all",
|
||||
|
||||
@@ -2,6 +2,7 @@ import os
|
||||
import time
|
||||
import json
|
||||
import os
|
||||
import base64
|
||||
import re
|
||||
import sqlite3
|
||||
from typing import Any, Dict, List, Optional, Tuple, Callable
|
||||
@@ -33,6 +34,53 @@ def _env_string(value: Any) -> str:
|
||||
return str(value)
|
||||
|
||||
|
||||
def _decode_base64_text(value: Any) -> Optional[str]:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
stripped = value.strip()
|
||||
if not stripped:
|
||||
return ""
|
||||
try:
|
||||
cleaned = re.sub(r"\s+", "", stripped)
|
||||
except Exception:
|
||||
cleaned = stripped
|
||||
try:
|
||||
decoded = base64.b64decode(cleaned, validate=True)
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
return decoded.decode("utf-8")
|
||||
except Exception:
|
||||
return decoded.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def _decode_script_content(value: Any, encoding_hint: str = "") -> str:
|
||||
encoding = (encoding_hint or "").strip().lower()
|
||||
if isinstance(value, str):
|
||||
if encoding in ("base64", "b64", "base-64"):
|
||||
decoded = _decode_base64_text(value)
|
||||
if decoded is not None:
|
||||
return decoded.replace("\r\n", "\n")
|
||||
decoded = _decode_base64_text(value)
|
||||
if decoded is not None:
|
||||
return decoded.replace("\r\n", "\n")
|
||||
return value.replace("\r\n", "\n")
|
||||
return ""
|
||||
|
||||
|
||||
def _encode_script_content(script_text: Any) -> str:
|
||||
if not isinstance(script_text, str):
|
||||
if script_text is None:
|
||||
script_text = ""
|
||||
else:
|
||||
script_text = str(script_text)
|
||||
normalized = script_text.replace("\r\n", "\n")
|
||||
if not normalized:
|
||||
return ""
|
||||
encoded = base64.b64encode(normalized.encode("utf-8"))
|
||||
return encoded.decode("ascii")
|
||||
|
||||
|
||||
def _canonical_env_key(name: Any) -> str:
|
||||
try:
|
||||
return re.sub(r"[^A-Za-z0-9_]", "_", str(name or "").strip()).upper()
|
||||
@@ -338,6 +386,7 @@ class JobScheduler:
|
||||
if typ in ("powershell", "batch", "bash", "ansible"):
|
||||
doc["type"] = typ
|
||||
script_val = data.get("script")
|
||||
content_val = data.get("content")
|
||||
script_lines = data.get("script_lines")
|
||||
if isinstance(script_lines, list):
|
||||
try:
|
||||
@@ -347,11 +396,24 @@ class JobScheduler:
|
||||
elif isinstance(script_val, str):
|
||||
doc["script"] = script_val
|
||||
else:
|
||||
content_val = data.get("content")
|
||||
if isinstance(content_val, str):
|
||||
doc["script"] = content_val
|
||||
normalized_script = (doc["script"] or "").replace("\r\n", "\n")
|
||||
doc["script"] = normalized_script
|
||||
encoding_hint = str(data.get("script_encoding") or data.get("scriptEncoding") or "").strip().lower()
|
||||
doc["script"] = _decode_script_content(doc.get("script"), encoding_hint)
|
||||
if encoding_hint in ("base64", "b64", "base-64"):
|
||||
doc["script_encoding"] = "base64"
|
||||
else:
|
||||
probe_source = ""
|
||||
if isinstance(script_val, str) and script_val:
|
||||
probe_source = script_val
|
||||
elif isinstance(content_val, str) and content_val:
|
||||
probe_source = content_val
|
||||
decoded_probe = _decode_base64_text(probe_source) if probe_source else None
|
||||
if decoded_probe is not None:
|
||||
doc["script_encoding"] = "base64"
|
||||
doc["script"] = decoded_probe.replace("\r\n", "\n")
|
||||
else:
|
||||
doc["script_encoding"] = "plain"
|
||||
try:
|
||||
timeout_raw = data.get("timeout_seconds", data.get("timeout"))
|
||||
if timeout_raw is None:
|
||||
@@ -423,6 +485,7 @@ class JobScheduler:
|
||||
return
|
||||
doc = self._load_assembly_document(abs_path, "ansible")
|
||||
content = doc.get("script") or ""
|
||||
encoded_content = _encode_script_content(content)
|
||||
variables = doc.get("variables") or []
|
||||
files = doc.get("files") or []
|
||||
|
||||
@@ -457,7 +520,8 @@ class JobScheduler:
|
||||
"run_id": uuid.uuid4().hex,
|
||||
"target_hostname": str(hostname),
|
||||
"playbook_name": os.path.basename(abs_path),
|
||||
"playbook_content": content,
|
||||
"playbook_content": encoded_content,
|
||||
"playbook_encoding": "base64",
|
||||
"activity_job_id": act_id,
|
||||
"scheduled_job_id": int(scheduled_job_id),
|
||||
"scheduled_run_id": int(scheduled_run_id),
|
||||
@@ -517,6 +581,7 @@ class JobScheduler:
|
||||
|
||||
env_map, variables, literal_lookup = _prepare_variable_context(doc_variables, overrides)
|
||||
content = _rewrite_powershell_script(content, literal_lookup)
|
||||
encoded_content = _encode_script_content(content)
|
||||
timeout_seconds = 0
|
||||
try:
|
||||
timeout_seconds = max(0, int(doc.get("timeout_seconds") or 0))
|
||||
@@ -557,7 +622,8 @@ class JobScheduler:
|
||||
"script_type": stype,
|
||||
"script_name": os.path.basename(abs_path),
|
||||
"script_path": path_norm,
|
||||
"script_content": content,
|
||||
"script_content": encoded_content,
|
||||
"script_encoding": "base64",
|
||||
"environment": env_map,
|
||||
"variables": variables,
|
||||
"timeout_seconds": timeout_seconds,
|
||||
|
||||
@@ -689,6 +689,64 @@ def _empty_assembly_document(default_type: str = "powershell") -> Dict[str, Any]
|
||||
}
|
||||
|
||||
|
||||
def _decode_base64_text(value: Any) -> Optional[str]:
|
||||
if not isinstance(value, str):
|
||||
return None
|
||||
stripped = value.strip()
|
||||
if not stripped:
|
||||
return ""
|
||||
try:
|
||||
cleaned = re.sub(r"\s+", "", stripped)
|
||||
except Exception:
|
||||
cleaned = stripped
|
||||
try:
|
||||
decoded = base64.b64decode(cleaned, validate=True)
|
||||
except Exception:
|
||||
return None
|
||||
try:
|
||||
return decoded.decode("utf-8")
|
||||
except Exception:
|
||||
return decoded.decode("utf-8", errors="replace")
|
||||
|
||||
|
||||
def _decode_script_content(value: Any, encoding_hint: str = "") -> str:
|
||||
encoding = (encoding_hint or "").strip().lower()
|
||||
if isinstance(value, str):
|
||||
if encoding in ("base64", "b64", "base-64"):
|
||||
decoded = _decode_base64_text(value)
|
||||
if decoded is not None:
|
||||
return decoded.replace("\r\n", "\n")
|
||||
decoded = _decode_base64_text(value)
|
||||
if decoded is not None:
|
||||
return decoded.replace("\r\n", "\n")
|
||||
return value.replace("\r\n", "\n")
|
||||
return ""
|
||||
|
||||
|
||||
def _encode_script_content(script_text: Any) -> str:
|
||||
if not isinstance(script_text, str):
|
||||
if script_text is None:
|
||||
script_text = ""
|
||||
else:
|
||||
script_text = str(script_text)
|
||||
normalized = script_text.replace("\r\n", "\n")
|
||||
if not normalized:
|
||||
return ""
|
||||
encoded = base64.b64encode(normalized.encode("utf-8"))
|
||||
return encoded.decode("ascii")
|
||||
|
||||
|
||||
def _prepare_assembly_storage(doc: Dict[str, Any]) -> Dict[str, Any]:
|
||||
stored: Dict[str, Any] = {}
|
||||
for key, value in (doc or {}).items():
|
||||
if key == "script":
|
||||
stored[key] = _encode_script_content(value)
|
||||
else:
|
||||
stored[key] = value
|
||||
stored["script_encoding"] = "base64"
|
||||
return stored
|
||||
|
||||
|
||||
def _normalize_assembly_document(obj: Any, default_type: str, base_name: str) -> Dict[str, Any]:
|
||||
doc = _empty_assembly_document(default_type)
|
||||
if not isinstance(obj, dict):
|
||||
@@ -703,6 +761,7 @@ def _normalize_assembly_document(obj: Any, default_type: str, base_name: str) ->
|
||||
if typ in ("powershell", "batch", "bash", "ansible"):
|
||||
doc["type"] = typ
|
||||
script_val = obj.get("script")
|
||||
content_val = obj.get("content")
|
||||
script_lines = obj.get("script_lines")
|
||||
if isinstance(script_lines, list):
|
||||
try:
|
||||
@@ -712,11 +771,24 @@ def _normalize_assembly_document(obj: Any, default_type: str, base_name: str) ->
|
||||
elif isinstance(script_val, str):
|
||||
doc["script"] = script_val
|
||||
else:
|
||||
content_val = obj.get("content")
|
||||
if isinstance(content_val, str):
|
||||
doc["script"] = content_val
|
||||
normalized_script = (doc["script"] or "").replace("\r\n", "\n")
|
||||
doc["script"] = normalized_script
|
||||
encoding_hint = str(obj.get("script_encoding") or obj.get("scriptEncoding") or "").strip().lower()
|
||||
doc["script"] = _decode_script_content(doc.get("script"), encoding_hint)
|
||||
if encoding_hint in ("base64", "b64", "base-64"):
|
||||
doc["script_encoding"] = "base64"
|
||||
else:
|
||||
probe_source = ""
|
||||
if isinstance(script_val, str) and script_val:
|
||||
probe_source = script_val
|
||||
elif isinstance(content_val, str) and content_val:
|
||||
probe_source = content_val
|
||||
decoded_probe = _decode_base64_text(probe_source) if probe_source else None
|
||||
if decoded_probe is not None:
|
||||
doc["script_encoding"] = "base64"
|
||||
doc["script"] = decoded_probe.replace("\r\n", "\n")
|
||||
else:
|
||||
doc["script_encoding"] = "plain"
|
||||
timeout_val = obj.get("timeout_seconds", obj.get("timeout"))
|
||||
if timeout_val is not None:
|
||||
try:
|
||||
@@ -853,7 +925,7 @@ def assembly_create():
|
||||
base_name,
|
||||
)
|
||||
with open(abs_path, "w", encoding="utf-8") as fh:
|
||||
json.dump(normalized, fh, indent=2)
|
||||
json.dump(_prepare_assembly_storage(normalized), fh, indent=2)
|
||||
rel_new = os.path.relpath(abs_path, root).replace(os.sep, "/")
|
||||
return jsonify({"status": "ok", "rel_path": rel_new})
|
||||
else:
|
||||
@@ -902,7 +974,7 @@ def assembly_edit():
|
||||
base_name,
|
||||
)
|
||||
with open(target_abs, "w", encoding="utf-8") as fh:
|
||||
json.dump(normalized, fh, indent=2)
|
||||
json.dump(_prepare_assembly_storage(normalized), fh, indent=2)
|
||||
if target_abs != abs_path:
|
||||
try:
|
||||
os.remove(abs_path)
|
||||
@@ -2993,6 +3065,7 @@ def scripts_quick_run():
|
||||
|
||||
env_map, variables, literal_lookup = _prepare_variable_context(doc_variables, overrides)
|
||||
content = _rewrite_powershell_script(content, literal_lookup)
|
||||
encoded_content = _encode_script_content(content)
|
||||
timeout_seconds = 0
|
||||
try:
|
||||
timeout_seconds = max(0, int(doc.get("timeout_seconds") or 0))
|
||||
@@ -3034,7 +3107,8 @@ def scripts_quick_run():
|
||||
"script_type": script_type,
|
||||
"script_name": _safe_filename(rel_path),
|
||||
"script_path": rel_path.replace(os.sep, "/"),
|
||||
"script_content": content,
|
||||
"script_content": encoded_content,
|
||||
"script_encoding": "base64",
|
||||
"environment": env_map,
|
||||
"variables": variables,
|
||||
"timeout_seconds": timeout_seconds,
|
||||
@@ -3070,6 +3144,7 @@ def ansible_quick_run():
|
||||
return jsonify({"error": "Playbook not found"}), 404
|
||||
doc = _load_assembly_document(abs_path, 'ansible')
|
||||
content = doc.get('script') or ''
|
||||
encoded_content = _encode_script_content(content)
|
||||
variables = doc.get('variables') if isinstance(doc.get('variables'), list) else []
|
||||
files = doc.get('files') if isinstance(doc.get('files'), list) else []
|
||||
|
||||
@@ -3112,7 +3187,8 @@ def ansible_quick_run():
|
||||
"run_id": run_id,
|
||||
"target_hostname": str(host),
|
||||
"playbook_name": os.path.basename(abs_path),
|
||||
"playbook_content": content,
|
||||
"playbook_content": encoded_content,
|
||||
"playbook_encoding": "base64",
|
||||
"connection": "winrm",
|
||||
"variables": variables,
|
||||
"files": files,
|
||||
|
||||
Reference in New Issue
Block a user