ominfra 0.0.0.dev205__py3-none-any.whl → 0.0.0.dev206__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ominfra might be problematic. Click here for more details.
- ominfra/clouds/aws/instancetypes/__init__.py +0 -0
- ominfra/clouds/aws/instancetypes/__main__.py +4 -0
- ominfra/clouds/aws/instancetypes/cache.json.gz +0 -0
- ominfra/clouds/aws/instancetypes/cache.py +12 -0
- ominfra/clouds/aws/instancetypes/cli.py +80 -0
- ominfra/clouds/aws/models/base.py +71 -11
- ominfra/clouds/aws/models/gen/gen.py +7 -1
- ominfra/clouds/aws/models/services/ec2.py +570 -7
- ominfra/clouds/aws/models/services/lambda_.py +5 -0
- ominfra/clouds/aws/models/services/s3.py +139 -0
- ominfra/clouds/aws/models/services/services.toml +0 -1
- {ominfra-0.0.0.dev205.dist-info → ominfra-0.0.0.dev206.dist-info}/METADATA +4 -4
- {ominfra-0.0.0.dev205.dist-info → ominfra-0.0.0.dev206.dist-info}/RECORD +17 -12
- {ominfra-0.0.0.dev205.dist-info → ominfra-0.0.0.dev206.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev205.dist-info → ominfra-0.0.0.dev206.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev205.dist-info → ominfra-0.0.0.dev206.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev205.dist-info → ominfra-0.0.0.dev206.dist-info}/top_level.txt +0 -0
File without changes
|
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import gzip
|
2
|
+
import typing as ta
|
3
|
+
|
4
|
+
from omlish import lang
|
5
|
+
from omlish.formats import json
|
6
|
+
|
7
|
+
|
8
|
+
@lang.cached_function()
|
9
|
+
def load_instance_types() -> ta.Mapping[str, ta.Mapping[str, ta.Any]]:
|
10
|
+
raw = lang.get_relative_resources(globals=globals())['cache.json.gz'].read_bytes()
|
11
|
+
data = gzip.decompress(raw)
|
12
|
+
return json.loads(data)
|
@@ -0,0 +1,80 @@
|
|
1
|
+
import datetime
|
2
|
+
import gzip
|
3
|
+
import os.path
|
4
|
+
import typing as ta
|
5
|
+
|
6
|
+
from omdev.secrets import load_secrets
|
7
|
+
from omlish import lang
|
8
|
+
from omlish import secrets as sec
|
9
|
+
from omlish.argparse import all as ap
|
10
|
+
from omlish.formats import json
|
11
|
+
|
12
|
+
from .cache import load_instance_types
|
13
|
+
|
14
|
+
|
15
|
+
if ta.TYPE_CHECKING:
|
16
|
+
import boto3
|
17
|
+
else:
|
18
|
+
boto3 = lang.proxy_import('boto3')
|
19
|
+
|
20
|
+
|
21
|
+
# Use a hardcoded gz mtime to prevent the gz file from changing when the contents don't. We still have the git metadata
|
22
|
+
# to track modifications.
|
23
|
+
FIXED_CACHE_TIMESTAMP = datetime.datetime(2025, 1, 1, tzinfo=datetime.UTC).timestamp()
|
24
|
+
|
25
|
+
|
26
|
+
@lang.cached_function
|
27
|
+
def _get_secrets() -> sec.Secrets:
|
28
|
+
return load_secrets()
|
29
|
+
|
30
|
+
|
31
|
+
def get_ec2_instance_types(session: boto3.Session) -> dict[str, dict[str, ta.Any]]:
|
32
|
+
ec2 = session.client('ec2')
|
33
|
+
next_token = None
|
34
|
+
dct = {}
|
35
|
+
while True:
|
36
|
+
resp = ec2.describe_instance_types(**(dict(NextToken=next_token) if next_token else {}))
|
37
|
+
for instance_type in resp['InstanceTypes']:
|
38
|
+
name = instance_type['InstanceType']
|
39
|
+
dct[name] = instance_type
|
40
|
+
next_token = resp.get('NextToken')
|
41
|
+
if not next_token:
|
42
|
+
break
|
43
|
+
dct = dict(sorted(dct.items(), key=lambda t: t[0]))
|
44
|
+
return dct
|
45
|
+
|
46
|
+
|
47
|
+
class Cli(ap.Cli):
|
48
|
+
@ap.cmd()
|
49
|
+
def fetch(self) -> None:
|
50
|
+
cfg = _get_secrets()
|
51
|
+
|
52
|
+
session = boto3.Session(
|
53
|
+
aws_access_key_id=cfg.get('aws_access_key_id').reveal(),
|
54
|
+
aws_secret_access_key=cfg.get('aws_secret_access_key').reveal(),
|
55
|
+
region_name=cfg.get('aws_region').reveal(),
|
56
|
+
)
|
57
|
+
|
58
|
+
instance_types = get_ec2_instance_types(session)
|
59
|
+
|
60
|
+
cache_file = os.path.join(os.path.dirname(__file__), 'cache.json.gz')
|
61
|
+
with open(cache_file, 'wb') as f:
|
62
|
+
with gzip.GzipFile(
|
63
|
+
fileobj=f,
|
64
|
+
mode='w',
|
65
|
+
mtime=FIXED_CACHE_TIMESTAMP,
|
66
|
+
) as gf:
|
67
|
+
gf.write(json.dumps_compact(instance_types).encode('utf-8'))
|
68
|
+
|
69
|
+
@ap.cmd()
|
70
|
+
def dump(self) -> None:
|
71
|
+
dct = load_instance_types()
|
72
|
+
print(json.dumps_pretty(dct))
|
73
|
+
|
74
|
+
|
75
|
+
def _main() -> None:
|
76
|
+
Cli()()
|
77
|
+
|
78
|
+
|
79
|
+
if __name__ == '__main__':
|
80
|
+
_main()
|
@@ -1,7 +1,9 @@
|
|
1
|
-
import dataclasses as dc
|
2
1
|
import typing as ta
|
3
2
|
|
3
|
+
from omlish import cached
|
4
4
|
from omlish import check
|
5
|
+
from omlish import collections as col
|
6
|
+
from omlish import dataclasses as dc
|
5
7
|
from omlish import lang
|
6
8
|
|
7
9
|
|
@@ -21,17 +23,10 @@ class TagList:
|
|
21
23
|
##
|
22
24
|
|
23
25
|
|
24
|
-
class MEMBER_NAME(lang.Marker): # noqa
|
25
|
-
pass
|
26
|
-
|
27
|
-
|
28
26
|
class SHAPE_NAME(lang.Marker): # noqa
|
29
27
|
pass
|
30
28
|
|
31
29
|
|
32
|
-
##
|
33
|
-
|
34
|
-
|
35
30
|
def common_metadata(
|
36
31
|
*,
|
37
32
|
shape_name: str | None = None,
|
@@ -55,9 +50,58 @@ def shape_metadata(
|
|
55
50
|
return md
|
56
51
|
|
57
52
|
|
53
|
+
class ShapeInfo:
|
54
|
+
def __init__(
|
55
|
+
self,
|
56
|
+
cls: type['Shape'],
|
57
|
+
metadata: ta.Mapping[ta.Any, ta.Any],
|
58
|
+
) -> None:
|
59
|
+
super().__init__()
|
60
|
+
|
61
|
+
self._cls = check.issubclass(cls, Shape)
|
62
|
+
self._metadata = metadata
|
63
|
+
|
64
|
+
@property
|
65
|
+
def cls(self) -> type['Shape']:
|
66
|
+
return self._cls
|
67
|
+
|
68
|
+
@property
|
69
|
+
def metadata(self) -> ta.Mapping[ta.Any, ta.Any]:
|
70
|
+
return self._metadata
|
71
|
+
|
72
|
+
#
|
73
|
+
|
74
|
+
@cached.function
|
75
|
+
def fields(self) -> ta.Sequence[dc.Field]:
|
76
|
+
check.state(dc.is_immediate_dataclass(self._cls))
|
77
|
+
fls = dc.fields(self._cls)
|
78
|
+
return fls # noqa
|
79
|
+
|
80
|
+
@cached.function
|
81
|
+
def fields_by_name(self) -> ta.Mapping[str, dc.Field]:
|
82
|
+
return col.make_map_by(lambda fl: fl.name, self.fields(), strict=True)
|
83
|
+
|
84
|
+
@cached.function
|
85
|
+
def fields_by_member_name(self) -> ta.Mapping[str, dc.Field]:
|
86
|
+
return col.make_map(
|
87
|
+
[(n, f) for f in self.fields() if (n := f.metadata.get(MEMBER_NAME)) is not None],
|
88
|
+
strict=True,
|
89
|
+
)
|
90
|
+
|
91
|
+
@cached.function
|
92
|
+
def fields_by_serialization_name(self) -> ta.Mapping[str, dc.Field]:
|
93
|
+
l = []
|
94
|
+
for f in self.fields():
|
95
|
+
if sn := f.metadata.get(SERIALIZATION_NAME):
|
96
|
+
l.append((sn, f))
|
97
|
+
elif mn := f.metadata.get(MEMBER_NAME):
|
98
|
+
l.append((mn, f))
|
99
|
+
return col.make_map(l, strict=True)
|
100
|
+
|
101
|
+
|
58
102
|
@dc.dataclass(frozen=True)
|
59
103
|
class Shape:
|
60
|
-
|
104
|
+
__shape__: ShapeInfo
|
61
105
|
|
62
106
|
def __init_subclass__(
|
63
107
|
cls,
|
@@ -67,23 +111,39 @@ class Shape:
|
|
67
111
|
) -> None:
|
68
112
|
super().__init_subclass__(**kwargs)
|
69
113
|
|
70
|
-
check.state(not hasattr(cls, '
|
114
|
+
check.state(not hasattr(cls, '__shape__'))
|
71
115
|
|
72
|
-
|
116
|
+
info = ShapeInfo(
|
117
|
+
cls,
|
118
|
+
shape_metadata(**kwargs),
|
119
|
+
)
|
120
|
+
|
121
|
+
cls.__shape__ = info
|
73
122
|
|
74
123
|
|
75
124
|
##
|
76
125
|
|
77
126
|
|
127
|
+
class MEMBER_NAME(lang.Marker): # noqa
|
128
|
+
pass
|
129
|
+
|
130
|
+
|
131
|
+
class SERIALIZATION_NAME(lang.Marker): # noqa
|
132
|
+
pass
|
133
|
+
|
134
|
+
|
78
135
|
def field_metadata(
|
79
136
|
*,
|
80
137
|
member_name: str | None = None,
|
138
|
+
serialization_name: str | None = None,
|
81
139
|
**kwargs: ta.Any,
|
82
140
|
) -> dict[ta.Any, ta.Any]:
|
83
141
|
md = {**common_metadata(**kwargs)}
|
84
142
|
|
85
143
|
if member_name is not None:
|
86
144
|
md[MEMBER_NAME] = member_name
|
145
|
+
if serialization_name is not None:
|
146
|
+
md[SERIALIZATION_NAME] = serialization_name
|
87
147
|
|
88
148
|
return md
|
89
149
|
|
@@ -317,8 +317,10 @@ class ModelGen:
|
|
317
317
|
fn = self.demangle_name(mn)
|
318
318
|
mds = [
|
319
319
|
f'member_name={mn!r}',
|
320
|
-
f'shape_name={ms.name!r}',
|
321
320
|
]
|
321
|
+
if msn := ms.serialization.get('name'):
|
322
|
+
mds.append(f'serialization_name={msn!r}')
|
323
|
+
mds.append(f'shape_name={ms.name!r}')
|
322
324
|
ma = self.get_type_ann(
|
323
325
|
ms.name,
|
324
326
|
unquoted_names=unquoted_names,
|
@@ -508,3 +510,7 @@ class ModelGen:
|
|
508
510
|
self.gen_all_operations(out)
|
509
511
|
|
510
512
|
return out.getvalue()
|
513
|
+
|
514
|
+
|
515
|
+
if __name__ == '__main__':
|
516
|
+
raise RuntimeError('Use cli')
|