@namewta/speculo 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/ops-resources.js +1 -1
- package/dist/src/ops-resources.js.map +1 -1
- package/package.json +1 -1
- package/template/workflows/ops/D-project-deploy/D-project-deploy.md +1 -1
- package/template/workflows/ops/H-host-manage/H-host-manage.md +1 -1
- package/template/workflows/ops/I-initialize/I-initialize.md +2 -2
- package/template/workflows/ops/README.md +2 -2
- package/template/workflows/ops/common/CAPABILITIES.md +2 -2
- package/template/workflows/ops/common/USAGE.md +24 -24
- package/template/workflows/ops/common/examples/README.md +1 -1
- package/template/workflows/ops/common/examples/register.example.json +1 -1
- package/template/workflows/ops/common/schemas/host.schema.json +1 -1
- package/template/workflows/ops/common/schemas/plan.schema.json +3 -3
- package/template/workflows/ops/common/schemas/spec.schema.json +1 -1
- package/template/workflows/ops/common/schemas/status.schema.json +1 -1
- package/template/workflows/ops/common/tests/test_ops.mjs +752 -0
- package/template/workflows/ops/common/tools/bootstrap.ps1 +2 -2
- package/template/workflows/ops/common/tools/bootstrap.sh +2 -2
- package/template/workflows/ops/common/tools/demo-local.mjs +101 -0
- package/template/workflows/ops/common/tools/ops.mjs +4 -0
- package/template/workflows/ops/common/tools/opslib/agent.mjs +873 -0
- package/template/workflows/ops/common/tools/opslib/cli.mjs +311 -0
- package/template/workflows/ops/common/tools/opslib/core.mjs +393 -0
- package/template/workflows/ops/common/tools/opslib/docs.mjs +252 -0
- package/template/workflows/ops/common/tools/opslib/execution.mjs +378 -0
- package/template/workflows/ops/common/tools/opslib/host_recipes.mjs +109 -0
- package/template/workflows/ops/common/tools/opslib/model.mjs +272 -0
- package/template/workflows/ops/common/tools/opslib/{native_windows.py → native_windows.mjs} +16 -12
- package/template/workflows/ops/common/tools/opslib/planner.mjs +687 -0
- package/template/workflows/ops/common/tools/opslib/services.mjs +76 -0
- package/template/workflows/ops/common/tools/opslib/sources.mjs +56 -0
- package/template/workflows/ops/common/tools/opslib/transport.mjs +127 -0
- package/template/workflows/ops/common/tools/validate-ops.mjs +43 -30
- package/template/workflows/ops/common/tests/test_ops.py +0 -392
- package/template/workflows/ops/common/tools/demo-local.py +0 -64
- package/template/workflows/ops/common/tools/ops.py +0 -7
- package/template/workflows/ops/common/tools/opslib/__init__.py +0 -2
- package/template/workflows/ops/common/tools/opslib/__pycache__/__init__.cpython-312.pyc +0 -0
- package/template/workflows/ops/common/tools/opslib/__pycache__/core.cpython-312.pyc +0 -0
- package/template/workflows/ops/common/tools/opslib/__pycache__/model.cpython-312.pyc +0 -0
- package/template/workflows/ops/common/tools/opslib/agent.py +0 -510
- package/template/workflows/ops/common/tools/opslib/cli.py +0 -172
- package/template/workflows/ops/common/tools/opslib/core.py +0 -199
- package/template/workflows/ops/common/tools/opslib/docs.py +0 -199
- package/template/workflows/ops/common/tools/opslib/execution.py +0 -248
- package/template/workflows/ops/common/tools/opslib/host_recipes.py +0 -67
- package/template/workflows/ops/common/tools/opslib/model.py +0 -199
- package/template/workflows/ops/common/tools/opslib/planner.py +0 -497
- package/template/workflows/ops/common/tools/opslib/services.py +0 -47
- package/template/workflows/ops/common/tools/opslib/sources.py +0 -27
- package/template/workflows/ops/common/tools/opslib/transport.py +0 -55
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"""Strict host-key SSH and subprocess local transport. No passwords in argv."""
|
|
2
|
-
from __future__ import annotations
|
|
3
|
-
import base64, json, shlex, subprocess, sys
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from .core import *
|
|
6
|
-
|
|
7
|
-
AGENT=Path(__file__).with_name("agent.py")
|
|
8
|
-
|
|
9
|
-
def host_transport_digest(host: dict) -> str:
|
|
10
|
-
c=host["connection"]
|
|
11
|
-
kh=None
|
|
12
|
-
if host["transport"]=="ssh":
|
|
13
|
-
p=Path(c["known_hosts"])
|
|
14
|
-
no_symlinks(p,allow_missing=False)
|
|
15
|
-
kh=digest(p.read_bytes())
|
|
16
|
-
return digest({"host":host,"known_hosts_digest":kh})
|
|
17
|
-
|
|
18
|
-
def call(host: dict, request: dict, *, timeout: int=1800) -> dict:
|
|
19
|
-
request={"identity":host["identity"],**request}
|
|
20
|
-
content="import base64,json\nOPS_REQUEST=json.loads(base64.b64decode("+repr(base64.b64encode(canonical(request)).decode())+"))\n"+AGENT.read_text(encoding="utf-8").replace("from __future__ import annotations\n", "")
|
|
21
|
-
code="import sys;exec(compile(sys.stdin.buffer.read(),'<ops-target-agent>','exec'))"
|
|
22
|
-
if host["transport"]=="local":
|
|
23
|
-
argv=[sys.executable,"-c",code]
|
|
24
|
-
else:
|
|
25
|
-
c=host["connection"];kh=Path(c["known_hosts"]).absolute();no_symlinks(kh,allow_missing=False)
|
|
26
|
-
argv=["ssh","-T","-o","BatchMode=yes","-o","StrictHostKeyChecking=yes","-o",f"UserKnownHostsFile={kh}",
|
|
27
|
-
"-o","ConnectTimeout=15","-o","ServerAliveInterval=15","-o","ServerAliveCountMax=3","-p",str(c.get("port",22))]
|
|
28
|
-
if c.get("identity_file"):argv += ["-i",c["identity_file"],"-o","IdentitiesOnly=yes"]
|
|
29
|
-
remote=[c["python"],"-c",code]
|
|
30
|
-
if c.get("sudo"):remote=["sudo","-n","--",*remote]
|
|
31
|
-
if c.get("shell","posix")=="powershell":
|
|
32
|
-
if c.get("sudo"):raise OpsError("sudo not valid for PowerShell transport")
|
|
33
|
-
remote_command="& "+" ".join("'"+x.replace("'","''")+"'" for x in remote)
|
|
34
|
-
ps=base64.b64encode(remote_command.encode("utf-16le")).decode()
|
|
35
|
-
remote_command="powershell -NoProfile -NonInteractive -EncodedCommand "+ps
|
|
36
|
-
else:remote_command=shlex.join(remote)
|
|
37
|
-
argv += ["--",c["username"]+"@"+c["hostname"],remote_command]
|
|
38
|
-
try:
|
|
39
|
-
p=subprocess.run(argv,input=content.encode(),stdout=subprocess.PIPE,stderr=subprocess.PIPE,timeout=timeout)
|
|
40
|
-
except (OSError,subprocess.TimeoutExpired) as e:
|
|
41
|
-
if request["action"] in ("step","lock","unlock"):raise UnknownResult("target transport interrupted; inspect receipts before retry") from e
|
|
42
|
-
raise OpsError("target read unavailable: "+str(e)) from e
|
|
43
|
-
if p.returncode!=0:
|
|
44
|
-
text=redact(p.stderr.decode("utf8","replace"),request.get("secrets",[]))[-2000:]
|
|
45
|
-
if request["action"] in ("step","lock","unlock"):raise UnknownResult("target transport failed: "+text)
|
|
46
|
-
raise OpsError("target read failed: "+text)
|
|
47
|
-
try:value=json.loads(p.stdout)
|
|
48
|
-
except ValueError as e:raise UnknownResult("invalid target response; stdout noise or interrupted operation") from e
|
|
49
|
-
if not value.get("ok"):raise OpsError("target blocked: "+value.get("error","unknown"))
|
|
50
|
-
return value["result"]
|
|
51
|
-
|
|
52
|
-
def probe_local() -> dict:
|
|
53
|
-
from .agent import fingerprint
|
|
54
|
-
host={"host_id":"probe-local","platform":"windows" if os.name=="nt" else "linux","transport":"local","connection":{},"identity":fingerprint()}
|
|
55
|
-
return call(host,{"action":"probe"},timeout=120)
|