podbench 0.1.0b1__py3-none-any.whl
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.
- podbench/__init__.py +11 -0
- podbench/__main__.py +137 -0
- podbench/_version.py +24 -0
- podbench/agent.py +1034 -0
- podbench/dev.py +1736 -0
- podbench/gdbcmd.py +579 -0
- podbench/kubectl.py +518 -0
- podbench/launcher.py +2082 -0
- podbench/model.py +403 -0
- podbench/patch.py +1977 -0
- podbench/probe.py +714 -0
- podbench/proc.py +413 -0
- podbench/spec.py +805 -0
- podbench/sshcfg.py +501 -0
- podbench-0.1.0b1.dist-info/METADATA +494 -0
- podbench-0.1.0b1.dist-info/RECORD +20 -0
- podbench-0.1.0b1.dist-info/WHEEL +5 -0
- podbench-0.1.0b1.dist-info/entry_points.txt +2 -0
- podbench-0.1.0b1.dist-info/licenses/LICENSE +201 -0
- podbench-0.1.0b1.dist-info/top_level.txt +1 -0
podbench/__init__.py
ADDED
podbench/__main__.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Interface for ``python -m podbench``, and the ``podbench`` console script.
|
|
2
|
+
|
|
3
|
+
One binary serves both halves of the tool. On a developer's machine it is
|
|
4
|
+
reached as ``podbench <verb>`` — canonically ``uvx podbench <verb>``, with nothing
|
|
5
|
+
installed — and drives the cluster; inside the debug container the same binary is
|
|
6
|
+
PID 1 (``podbench agent``) and backs the helpers on
|
|
7
|
+
``PATH`` (``pids``, ``dbg``, ``capreport``, ...). Keeping it as one package means
|
|
8
|
+
the capability logic that decides what a session can do is the same code in both
|
|
9
|
+
places, rather than a launcher's guess and a helper's separate guess.
|
|
10
|
+
|
|
11
|
+
Dispatch is deliberately dumb: each verb names a module, and the module owns its
|
|
12
|
+
own argument parsing. Two of them predate the dispatcher and parse an argv that
|
|
13
|
+
does not include the verb, so those are sliced; the rest are forwarded verbatim.
|
|
14
|
+
Imports are done lazily per verb because ``podbench --version`` runs as the
|
|
15
|
+
image's build-time smoke test, and it should not depend on every module in the
|
|
16
|
+
package importing cleanly.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import sys
|
|
22
|
+
from argparse import REMAINDER, ArgumentParser
|
|
23
|
+
from collections.abc import Callable, Sequence
|
|
24
|
+
|
|
25
|
+
from . import __version__
|
|
26
|
+
|
|
27
|
+
__all__ = ["ENTRY_POINTS", "main"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _agent(args: Sequence[str]) -> int:
|
|
31
|
+
from .agent import main as run
|
|
32
|
+
|
|
33
|
+
return run(args)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _capreport(args: Sequence[str]) -> int:
|
|
37
|
+
from .probe import main as run
|
|
38
|
+
|
|
39
|
+
return run(args)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _gdbcmd(args: Sequence[str]) -> int:
|
|
43
|
+
from .gdbcmd import main as run
|
|
44
|
+
|
|
45
|
+
return run(args)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _dev(args: Sequence[str]) -> int:
|
|
49
|
+
from .dev import main as run
|
|
50
|
+
|
|
51
|
+
return run(args)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _launcher(args: Sequence[str]) -> int:
|
|
55
|
+
from .launcher import main as run
|
|
56
|
+
|
|
57
|
+
return run(args)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _patch(args: Sequence[str]) -> int:
|
|
61
|
+
from .patch import main as run
|
|
62
|
+
|
|
63
|
+
return run(args)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
#: Verb -> (handler, keep_verb). ``keep_verb`` is False for the two modules whose
|
|
67
|
+
#: parsers were written before this dispatcher existed and so do not expect their
|
|
68
|
+
#: own name in argv; the others own a subparser keyed on it and need it kept.
|
|
69
|
+
ENTRY_POINTS: dict[str, tuple[Callable[[Sequence[str]], int], bool]] = {
|
|
70
|
+
# In-pod: PID 1 and the helpers on PATH.
|
|
71
|
+
"agent": (_agent, False),
|
|
72
|
+
"capreport": (_capreport, False),
|
|
73
|
+
"pids": (_gdbcmd, True),
|
|
74
|
+
"dbg": (_gdbcmd, True),
|
|
75
|
+
"dev-bootstrap": (_dev, True),
|
|
76
|
+
"run": (_dev, True),
|
|
77
|
+
"stop": (_dev, True),
|
|
78
|
+
# Laptop side: `podbench ...`.
|
|
79
|
+
"attach": (_launcher, True),
|
|
80
|
+
"ssh-config": (_launcher, True),
|
|
81
|
+
"status": (_launcher, True),
|
|
82
|
+
"list": (_launcher, True),
|
|
83
|
+
"dev": (_dev, True),
|
|
84
|
+
# `patch status` is a *sub*-verb of this parser and does not collide with
|
|
85
|
+
# the launcher's own `status`.
|
|
86
|
+
"patch": (_patch, True),
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
_IN_POD = ("agent", "capreport", "pids", "dbg", "dev-bootstrap", "run", "stop")
|
|
90
|
+
_LAUNCHER = ("attach", "ssh-config", "status", "list", "dev", "patch")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _build_parser() -> ArgumentParser:
|
|
94
|
+
parser = ArgumentParser(
|
|
95
|
+
prog="podbench",
|
|
96
|
+
description=(
|
|
97
|
+
"A development seat inside a Kubernetes pod. Run `podbench <verb> "
|
|
98
|
+
"--help` for a verb's own options."
|
|
99
|
+
),
|
|
100
|
+
epilog=(
|
|
101
|
+
"cluster-side verbs: "
|
|
102
|
+
+ ", ".join(_LAUNCHER)
|
|
103
|
+
+ "; in-pod verbs: "
|
|
104
|
+
+ ", ".join(_IN_POD)
|
|
105
|
+
),
|
|
106
|
+
)
|
|
107
|
+
parser.add_argument("-v", "--version", action="version", version=__version__)
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
"verb",
|
|
110
|
+
nargs="?",
|
|
111
|
+
choices=sorted(ENTRY_POINTS),
|
|
112
|
+
metavar="VERB",
|
|
113
|
+
help="the subcommand to run",
|
|
114
|
+
)
|
|
115
|
+
# REMAINDER hands the verb's own flags through untouched, so that `podbench
|
|
116
|
+
# dbg --launch ./prog --fast` reaches gdbcmd with `--fast` intact instead of
|
|
117
|
+
# being claimed by this parser.
|
|
118
|
+
parser.add_argument("args", nargs=REMAINDER, help="arguments for the verb")
|
|
119
|
+
return parser
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def main(args: Sequence[str] | None = None) -> int:
|
|
123
|
+
"""Dispatch a verb to the module that implements it."""
|
|
124
|
+
parser = _build_parser()
|
|
125
|
+
parsed = parser.parse_args(args)
|
|
126
|
+
verb: str | None = parsed.verb
|
|
127
|
+
if verb is None:
|
|
128
|
+
parser.print_help()
|
|
129
|
+
return 2
|
|
130
|
+
|
|
131
|
+
handler, keep_verb = ENTRY_POINTS[verb]
|
|
132
|
+
rest: list[str] = list(parsed.args)
|
|
133
|
+
return handler([verb, *rest] if keep_verb else rest)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
if __name__ == "__main__":
|
|
137
|
+
sys.exit(main())
|
podbench/_version.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.1.0b1'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 0, 'b1')
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|