ominfra 0.0.0.dev58__py3-none-any.whl → 0.0.0.dev60__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 CHANGED
@@ -1,4 +1,16 @@
1
1
  [
2
+ {
3
+ "module": ".clouds.aws.__main__",
4
+ "attr": "_CLI_MODULE",
5
+ "file": "ominfra/clouds/aws/__main__.py",
6
+ "line": 4,
7
+ "value": {
8
+ "$omdev.cli.types.CliModule": {
9
+ "cmd_name": "aws",
10
+ "mod_name": "ominfra.clouds.aws.__main__"
11
+ }
12
+ }
13
+ },
2
14
  {
3
15
  "module": ".tailscale.cli",
4
16
  "attr": "_CLI_MODULE",
@@ -0,0 +1,11 @@
1
+ from omdev.cli import CliModule
2
+
3
+
4
+ # @omlish-manifest
5
+ _CLI_MODULE = CliModule('aws', __name__)
6
+
7
+
8
+ if __name__ == '__main__':
9
+ from .cli import _main
10
+
11
+ _main()
@@ -0,0 +1,25 @@
1
+ from omlish import argparse as ap
2
+ from omlish.formats import json
3
+
4
+ from . import metadata
5
+
6
+
7
+ class Cli(ap.Cli):
8
+ @ap.command(
9
+ ap.arg('key', action='append'),
10
+ ap.arg('--url'),
11
+ )
12
+ def metadata(self) -> None:
13
+ md = metadata.read_metadata(
14
+ self.args.keys or metadata.DEFAULT_METADATA_KEYS,
15
+ url=self.args.url or metadata.DEFAULT_METADATA_URL,
16
+ )
17
+ print(json.dumps_pretty(md))
18
+
19
+
20
+ def _main() -> None:
21
+ Cli()()
22
+
23
+
24
+ if __name__ == '__main__':
25
+ _main()
@@ -0,0 +1,99 @@
1
+ """
2
+ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` && \
3
+ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/
4
+ """
5
+ import logging
6
+ import socket
7
+ import typing as ta
8
+ import urllib.error
9
+ import urllib.parse
10
+ import urllib.request
11
+
12
+ from omlish import check
13
+ from omlish import lang
14
+
15
+
16
+ DEFAULT_METADATA_URL = 'http://169.254.169.254/'
17
+
18
+ METADATA_TOKEN_HEADER = 'X-aws-ec2-metadata-token' # noqa
19
+ METADATA_TOKEN_TTL_HEADER = 'X-aws-ec2-metadata-token-ttl-seconds' # noqa
20
+
21
+
22
+ def read_metadata(
23
+ keys: ta.Iterable[str],
24
+ *,
25
+ url: str = DEFAULT_METADATA_URL,
26
+ version: str = 'latest',
27
+ ping_timeout_s: float = 10.,
28
+ token_ttl: int = 60,
29
+ encoding: str = 'utf-8',
30
+ ) -> dict[str, str | None] | None:
31
+ check.not_isinstance(keys, str)
32
+
33
+ if not url.endswith('/'):
34
+ url += '/'
35
+
36
+ parsed: urllib.parse.ParseResult = urllib.parse.urlparse(url)
37
+ if not parsed.scheme:
38
+ url = 'http://' + url
39
+ parsed = urllib.parse.urlparse(url)
40
+ check.arg(bool(parsed.netloc))
41
+
42
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as ping_sock:
43
+ ping_sock.settimeout(ping_timeout_s)
44
+ try:
45
+ ping_sock.connect((parsed.netloc, 80))
46
+ except OSError:
47
+ return None
48
+
49
+ with urllib.request.urlopen(urllib.request.Request( # noqa
50
+ urllib.parse.urljoin(url, f'{version}/api/token'),
51
+ method='PUT',
52
+ headers={
53
+ METADATA_TOKEN_TTL_HEADER: str(token_ttl),
54
+ },
55
+ )) as resp:
56
+ if resp.status != 200:
57
+ raise Exception(f'Failed to get token')
58
+ token = resp.read().decode(encoding).strip()
59
+
60
+ dct = {}
61
+ for key in keys:
62
+ try:
63
+ with urllib.request.urlopen(urllib.request.Request( # noqa
64
+ urllib.parse.urljoin(url, f'{version}/meta-data/{key}/'),
65
+ headers={
66
+ METADATA_TOKEN_HEADER: token,
67
+ },
68
+ )) as resp:
69
+ dct[key] = resp.read().decode(encoding)
70
+ except urllib.error.URLError:
71
+ dct[key] = None
72
+ return dct
73
+
74
+
75
+ DEFAULT_METADATA_KEYS: ta.AbstractSet[str] = {
76
+ 'hostname',
77
+ 'instance-id',
78
+ }
79
+
80
+
81
+ @lang.cached_function
82
+ def metadata() -> ta.Mapping[str, str | None] | None:
83
+ return read_metadata(DEFAULT_METADATA_KEYS)
84
+
85
+
86
+ ##
87
+
88
+
89
+ class MetadataLogFilter(logging.Filter):
90
+
91
+ def filter(self, record):
92
+ md = metadata() or {}
93
+ record.aws_hostname = md.get('hostname', '?')
94
+ record.aws_instance_id = md.get('instance-id', '?')
95
+ return True
96
+
97
+
98
+ def configure_metadata_logging(handler: logging.Handler) -> None:
99
+ handler.addFilter(MetadataLogFilter())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev58
3
+ Version: 0.0.0.dev60
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.dev58
16
- Requires-Dist: omlish ==0.0.0.dev58
15
+ Requires-Dist: omdev ==0.0.0.dev60
16
+ Requires-Dist: omlish ==0.0.0.dev60
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,11 +1,14 @@
1
- ominfra/.manifests.json,sha256=f_sjpvGcLg_qmHDgUvtQ1gPdNfomJNPm75nEKJZziOY,310
1
+ ominfra/.manifests.json,sha256=KjKpu0HX2bG8bASAjq9pt9FLAiDYqS1lZ8x-buseoik,589
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
5
5
  ominfra/ssh.py,sha256=jQpc4WvkMckIfk4vILda8zFaeharRqc_6wxW50b0OjQ,5431
6
6
  ominfra/clouds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  ominfra/clouds/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ ominfra/clouds/aws/__main__.py,sha256=HXMoxEl9KHhv6zOOPQxiJAftfR2SjBqeVTYw-og9aFw,163
8
9
  ominfra/clouds/aws/auth.py,sha256=EW3lK1U0hnjXkTn1KWJeuv9GG0ibbKdvgLD0P6HJtwo,5502
10
+ ominfra/clouds/aws/cli.py,sha256=jCvZIZGLWIkMlb1WYMQ-Gvs4YKPDCiWKjkFTaH9ARMc,517
11
+ ominfra/clouds/aws/metadata.py,sha256=XR1BuMdQheyeFjjA3MN8GCNWVAp5ahoPdbWXEmViutQ,2767
9
12
  ominfra/deploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
13
  ominfra/deploy/_executor.py,sha256=3mUpHetUu9POcV3nLu8NlVnK4-jzRYHVnnT8uyZPfSA,32506
11
14
  ominfra/deploy/configs.py,sha256=qi0kwT7G2NH7dXLOQic-u6R3yeadup_QtvrjwWIggbM,435
@@ -43,9 +46,9 @@ ominfra/tailscale/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
43
46
  ominfra/tailscale/cli.py,sha256=Ltg6RVFsMLLPjLzoGwM6sxjmwjEVEYHAdrqmCc4N1HM,3174
44
47
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
48
  ominfra/tools/listresources.py,sha256=L4t5rszm9ulcdWyr7n48_R9d5Etg4S2a4WQhlbHDtnQ,6106
46
- ominfra-0.0.0.dev58.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
47
- ominfra-0.0.0.dev58.dist-info/METADATA,sha256=nQ34Ifyi87uHjVm71dlIWRX6uwlDYOz8Mgc8g1lOOww,799
48
- ominfra-0.0.0.dev58.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
49
- ominfra-0.0.0.dev58.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
50
- ominfra-0.0.0.dev58.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
51
- ominfra-0.0.0.dev58.dist-info/RECORD,,
49
+ ominfra-0.0.0.dev60.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
50
+ ominfra-0.0.0.dev60.dist-info/METADATA,sha256=Az4lEVQxqpAvug6FZRo4kJy57V6qA3MAHotHEYPUp0g,799
51
+ ominfra-0.0.0.dev60.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
52
+ ominfra-0.0.0.dev60.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
53
+ ominfra-0.0.0.dev60.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
54
+ ominfra-0.0.0.dev60.dist-info/RECORD,,