@namewta/speculo 1.0.6 → 1.0.8

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.
Files changed (57) hide show
  1. package/dist/src/ops-resources.js +1 -1
  2. package/dist/src/ops-resources.js.map +1 -1
  3. package/package.json +1 -1
  4. package/template/workflows/ops/D-project-deploy/D-project-deploy.md +1 -1
  5. package/template/workflows/ops/H-host-manage/H-host-manage.md +5 -1
  6. package/template/workflows/ops/I-initialize/I-initialize.md +2 -2
  7. package/template/workflows/ops/README.md +8 -5
  8. package/template/workflows/ops/common/CAPABILITIES.md +2 -2
  9. package/template/workflows/ops/common/USAGE.md +25 -25
  10. package/template/workflows/ops/common/examples/README.md +1 -1
  11. package/template/workflows/ops/common/examples/register.example.json +1 -1
  12. package/template/workflows/ops/common/rules/persistence-and-secrets.md +1 -1
  13. package/template/workflows/ops/common/schemas/host.schema.json +65 -2
  14. package/template/workflows/ops/common/schemas/plan.schema.json +315 -3
  15. package/template/workflows/ops/common/schemas/spec.schema.json +137 -1
  16. package/template/workflows/ops/common/schemas/status.schema.json +143 -1
  17. package/template/workflows/ops/common/service-profiles/elasticsearch.md +13 -0
  18. package/template/workflows/ops/common/service-profiles/redis.md +4 -0
  19. package/template/workflows/ops/common/templates/CONTROLLER-RECORD.md +16 -2
  20. package/template/workflows/ops/common/templates/HOST-README.md +12 -2
  21. package/template/workflows/ops/common/tests/test_ops.mjs +982 -0
  22. package/template/workflows/ops/common/tools/bootstrap.ps1 +2 -2
  23. package/template/workflows/ops/common/tools/bootstrap.sh +2 -2
  24. package/template/workflows/ops/common/tools/demo-local.mjs +101 -0
  25. package/template/workflows/ops/common/tools/ops.mjs +4 -0
  26. package/template/workflows/ops/common/tools/opslib/agent.mjs +904 -0
  27. package/template/workflows/ops/common/tools/opslib/cli.mjs +311 -0
  28. package/template/workflows/ops/common/tools/opslib/control_files.mjs +57 -0
  29. package/template/workflows/ops/common/tools/opslib/core.mjs +393 -0
  30. package/template/workflows/ops/common/tools/opslib/docs.mjs +436 -0
  31. package/template/workflows/ops/common/tools/opslib/execution.mjs +396 -0
  32. package/template/workflows/ops/common/tools/opslib/host_recipes.mjs +109 -0
  33. package/template/workflows/ops/common/tools/opslib/model.mjs +272 -0
  34. package/template/workflows/ops/common/tools/opslib/{native_windows.py → native_windows.mjs} +16 -12
  35. package/template/workflows/ops/common/tools/opslib/planner.mjs +781 -0
  36. package/template/workflows/ops/common/tools/opslib/services.mjs +76 -0
  37. package/template/workflows/ops/common/tools/opslib/sources.mjs +56 -0
  38. package/template/workflows/ops/common/tools/opslib/transport.mjs +127 -0
  39. package/template/workflows/ops/common/tools/validate-ops.mjs +43 -30
  40. package/template/workflows/ops/common/tests/test_ops.py +0 -392
  41. package/template/workflows/ops/common/tools/demo-local.py +0 -64
  42. package/template/workflows/ops/common/tools/ops.py +0 -7
  43. package/template/workflows/ops/common/tools/opslib/__init__.py +0 -2
  44. package/template/workflows/ops/common/tools/opslib/__pycache__/__init__.cpython-312.pyc +0 -0
  45. package/template/workflows/ops/common/tools/opslib/__pycache__/core.cpython-312.pyc +0 -0
  46. package/template/workflows/ops/common/tools/opslib/__pycache__/model.cpython-312.pyc +0 -0
  47. package/template/workflows/ops/common/tools/opslib/agent.py +0 -510
  48. package/template/workflows/ops/common/tools/opslib/cli.py +0 -172
  49. package/template/workflows/ops/common/tools/opslib/core.py +0 -199
  50. package/template/workflows/ops/common/tools/opslib/docs.py +0 -199
  51. package/template/workflows/ops/common/tools/opslib/execution.py +0 -248
  52. package/template/workflows/ops/common/tools/opslib/host_recipes.py +0 -67
  53. package/template/workflows/ops/common/tools/opslib/model.py +0 -199
  54. package/template/workflows/ops/common/tools/opslib/planner.py +0 -497
  55. package/template/workflows/ops/common/tools/opslib/services.py +0 -47
  56. package/template/workflows/ops/common/tools/opslib/sources.py +0 -27
  57. 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)