ominfra 0.0.0.dev52__py3-none-any.whl → 0.0.0.dev53__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.
- ominfra/.manifests.json +17 -1
- ominfra/tailscale/__init__.py +0 -0
- ominfra/tailscale/cli.py +113 -0
- {ominfra-0.0.0.dev52.dist-info → ominfra-0.0.0.dev53.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev52.dist-info → ominfra-0.0.0.dev53.dist-info}/RECORD +9 -7
- {ominfra-0.0.0.dev52.dist-info → ominfra-0.0.0.dev53.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev52.dist-info → ominfra-0.0.0.dev53.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev52.dist-info → ominfra-0.0.0.dev53.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev52.dist-info → ominfra-0.0.0.dev53.dist-info}/top_level.txt +0 -0
ominfra/.manifests.json
CHANGED
@@ -1 +1,17 @@
|
|
1
|
-
[
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"module": ".tailscale.cli",
|
4
|
+
"attr": "_CLI_MODULE",
|
5
|
+
"file": "ominfra/tailscale/cli.py",
|
6
|
+
"line": 104,
|
7
|
+
"value": {
|
8
|
+
"$omdev.cli.types.CliModule": {
|
9
|
+
"cmd_name": [
|
10
|
+
"tailscale",
|
11
|
+
"ts"
|
12
|
+
],
|
13
|
+
"mod_name": "ominfra.tailscale.cli"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
17
|
+
]
|
File without changes
|
ominfra/tailscale/cli.py
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
import re
|
2
|
+
import subprocess
|
3
|
+
import sys
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
from omdev.cli import CliModule
|
7
|
+
from omlish import argparse as ap
|
8
|
+
from omlish import cached
|
9
|
+
from omlish import collections as col
|
10
|
+
from omlish import dataclasses as dc
|
11
|
+
from omlish import lang
|
12
|
+
from omlish import marshal as msh
|
13
|
+
from omlish.formats import json
|
14
|
+
|
15
|
+
|
16
|
+
##
|
17
|
+
|
18
|
+
|
19
|
+
@dc.dataclass(frozen=True)
|
20
|
+
@msh.update_object_metadata(field_naming=msh.Naming.CAMEL, unknown_field='x')
|
21
|
+
class CliNode:
|
22
|
+
id: str = dc.xfield() | msh.update_field_metadata(name='ID')
|
23
|
+
public_key: str = dc.xfield()
|
24
|
+
host_name: str = dc.xfield()
|
25
|
+
dns_name: str | None = dc.xfield(None) | msh.update_field_metadata(name='DNSName')
|
26
|
+
tailscale_ips: ta.Sequence[str] | None = dc.xfield(None) | msh.update_field_metadata(name='TailscaleIPs')
|
27
|
+
allowed_ips: ta.Sequence[str] | None = dc.xfield(None) | msh.update_field_metadata(name='AllowedPs')
|
28
|
+
tags: ta.Sequence[str] | None = None
|
29
|
+
|
30
|
+
x: ta.Mapping[str, ta.Any] | None = None
|
31
|
+
|
32
|
+
|
33
|
+
@dc.dataclass(frozen=True)
|
34
|
+
@msh.update_object_metadata(field_naming=msh.Naming.CAMEL, unknown_field='x')
|
35
|
+
class CliStatus:
|
36
|
+
version: str | None = None
|
37
|
+
backend_state: str | None = None
|
38
|
+
tailscale_ips: ta.Sequence[str] | None = dc.xfield(None) | msh.update_field_metadata(name='TailscaleIPs')
|
39
|
+
self: CliNode | None = None
|
40
|
+
peers: ta.Mapping[str, CliNode] | None = dc.xfield(None) | msh.update_field_metadata(name='Peer')
|
41
|
+
|
42
|
+
@cached.property
|
43
|
+
def nodes(self) -> ta.Sequence[CliNode]:
|
44
|
+
return [
|
45
|
+
*([self.self] if self.self is not None else []),
|
46
|
+
*(self.peers.values() if self.peers else []),
|
47
|
+
]
|
48
|
+
|
49
|
+
@cached.property
|
50
|
+
def nodes_by_host_name(self) -> ta.Mapping[str, CliNode]:
|
51
|
+
return col.make_map(((n.host_name, n) for n in self.nodes if n.host_name), strict=True)
|
52
|
+
|
53
|
+
x: ta.Mapping[str, ta.Any] | None = None
|
54
|
+
|
55
|
+
|
56
|
+
##
|
57
|
+
|
58
|
+
|
59
|
+
_IP_V4_PAT = re.compile(r'\d{1,3}(\.\d{1,3}){3}')
|
60
|
+
|
61
|
+
|
62
|
+
class Cli(ap.Cli):
|
63
|
+
@lang.cached_function
|
64
|
+
def bin(self) -> str:
|
65
|
+
if sys.platform == 'darwin':
|
66
|
+
return '/Applications/Tailscale.app/Contents/MacOS/Tailscale'
|
67
|
+
else:
|
68
|
+
return 'tailscale'
|
69
|
+
|
70
|
+
@ap.command(name='bin')
|
71
|
+
def bin_cmd(self) -> None:
|
72
|
+
print(self.bin())
|
73
|
+
|
74
|
+
def status(self) -> CliStatus:
|
75
|
+
stdout = subprocess.check_output([
|
76
|
+
self.bin(),
|
77
|
+
'status',
|
78
|
+
'--json',
|
79
|
+
])
|
80
|
+
return msh.unmarshal(json.loads(stdout.decode()), CliStatus)
|
81
|
+
|
82
|
+
@ap.command(
|
83
|
+
ap.arg('name', nargs='?'),
|
84
|
+
name='status',
|
85
|
+
)
|
86
|
+
def status_cmd(self) -> None:
|
87
|
+
status = self.status()
|
88
|
+
out: ta.Any
|
89
|
+
if (name := self.args.name):
|
90
|
+
out = status.nodes_by_host_name[name]
|
91
|
+
else:
|
92
|
+
out = status
|
93
|
+
print(json.dumps_pretty(msh.marshal(out)))
|
94
|
+
|
95
|
+
@ap.command(
|
96
|
+
ap.arg('name'),
|
97
|
+
)
|
98
|
+
def ip(self) -> None:
|
99
|
+
node = self.status().nodes_by_host_name[self.args.name]
|
100
|
+
ips = [i for i in node.tailscale_ips or () if _IP_V4_PAT.fullmatch(i)]
|
101
|
+
print(ips[0])
|
102
|
+
|
103
|
+
|
104
|
+
# @omlish-manifest
|
105
|
+
_CLI_MODULE = CliModule(['tailscale', 'ts'], __name__)
|
106
|
+
|
107
|
+
|
108
|
+
def _main() -> None:
|
109
|
+
Cli()()
|
110
|
+
|
111
|
+
|
112
|
+
if __name__ == '__main__':
|
113
|
+
_main()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ominfra
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev53
|
4
4
|
Summary: ominfra
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -12,8 +12,8 @@ Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Operating System :: POSIX
|
13
13
|
Requires-Python: ~=3.12
|
14
14
|
License-File: LICENSE
|
15
|
-
Requires-Dist: omdev ==0.0.0.
|
16
|
-
Requires-Dist: omlish ==0.0.0.
|
15
|
+
Requires-Dist: omdev ==0.0.0.dev53
|
16
|
+
Requires-Dist: omlish ==0.0.0.dev53
|
17
17
|
Provides-Extra: all
|
18
18
|
Requires-Dist: paramiko ~=3.5 ; extra == 'all'
|
19
19
|
Requires-Dist: asyncssh ~=2.17 ; (python_version < "3.13") and extra == 'all'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
ominfra/.manifests.json,sha256=
|
1
|
+
ominfra/.manifests.json,sha256=f_sjpvGcLg_qmHDgUvtQ1gPdNfomJNPm75nEKJZziOY,310
|
2
2
|
ominfra/__about__.py,sha256=iYpUXgOtMUoc5leWMmABMGn81LS_nLzDLZU198aCwWk,730
|
3
3
|
ominfra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
ominfra/cmds.py,sha256=E0AfnvEmnKntXWvmLW5L05_NeDpBET1VBXn7vV6EwBQ,2083
|
@@ -39,11 +39,13 @@ ominfra/pyremote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
|
|
39
39
|
ominfra/pyremote/_runcommands.py,sha256=gxmbQYUwi51ekiVtwciY18_8Vx7pzgeIycAgaZeTxlQ,26342
|
40
40
|
ominfra/pyremote/bootstrap.py,sha256=RvMO3YGaN1E4sgUi1JEtiPak8cjvqtc_vRCq1yqbeZg,3370
|
41
41
|
ominfra/pyremote/runcommands.py,sha256=bviS0_TDIoZVAe4h-_iavbvJtVSFu8lnk7fQ5iasCWE,1571
|
42
|
+
ominfra/tailscale/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
43
|
+
ominfra/tailscale/cli.py,sha256=Ltg6RVFsMLLPjLzoGwM6sxjmwjEVEYHAdrqmCc4N1HM,3174
|
42
44
|
ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
43
45
|
ominfra/tools/listresources.py,sha256=L4t5rszm9ulcdWyr7n48_R9d5Etg4S2a4WQhlbHDtnQ,6106
|
44
|
-
ominfra-0.0.0.
|
45
|
-
ominfra-0.0.0.
|
46
|
-
ominfra-0.0.0.
|
47
|
-
ominfra-0.0.0.
|
48
|
-
ominfra-0.0.0.
|
49
|
-
ominfra-0.0.0.
|
46
|
+
ominfra-0.0.0.dev53.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
47
|
+
ominfra-0.0.0.dev53.dist-info/METADATA,sha256=NJm_tslqMbWChDqviFPBsJJjxr8uFmGRn2ugq38yT4A,799
|
48
|
+
ominfra-0.0.0.dev53.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
49
|
+
ominfra-0.0.0.dev53.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
|
50
|
+
ominfra-0.0.0.dev53.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
|
51
|
+
ominfra-0.0.0.dev53.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|