c2client 0.25__tar.gz → 0.26__tar.gz

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.
@@ -1,14 +1,13 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: c2client
3
- Version: 0.25
4
- Summary: CROC Cloud Platform - API Client
3
+ Version: 0.26
4
+ Summary: RockitCloud Platform - API Client
5
5
  Home-page: https://github.com/c2devel/c2-client
6
- Author: CROC Cloud Team
7
- Author-email: devel@croc.ru
6
+ Author: RockitCLoud Team
7
+ Author-email: devel@k2.cloud
8
8
  Maintainer: Andrey Kulaev
9
9
  Maintainer-email: adkulaev@gmail.com
10
10
  License: GPL3
11
- Platform: UNKNOWN
12
11
  Classifier: Development Status :: 5 - Production/Stable
13
12
  Classifier: Environment :: Console
14
13
  Classifier: Intended Audience :: Developers
@@ -23,6 +22,19 @@ Classifier: Programming Language :: Python :: 3.10
23
22
  Classifier: Programming Language :: Python :: 3.11
24
23
  Classifier: Programming Language :: Python :: 3.12
25
24
  Classifier: Programming Language :: Python :: 3.13
25
+ Requires-Dist: boto3
26
+ Requires-Dist: botocore
27
+ Requires-Dist: inflection==0.3.1
28
+ Dynamic: author
29
+ Dynamic: author-email
30
+ Dynamic: classifier
31
+ Dynamic: description
32
+ Dynamic: home-page
33
+ Dynamic: license
34
+ Dynamic: maintainer
35
+ Dynamic: maintainer-email
36
+ Dynamic: requires-dist
37
+ Dynamic: summary
26
38
 
27
39
  K2 Cloud API Client
28
40
  =====================
@@ -35,11 +47,27 @@ Use https://github.com/c2devel/boto3.git and python scripts instead.**
35
47
  Installation
36
48
  ------------
37
49
 
38
- Using pip:
50
+ C2client package relies on forked versions of boto3 and botocore from the `C2Devel/boto3 <https://github.com/c2Devel/boto3>`_ and `C2Devel/botocore <https://github.com/c2Devel/botocore>`_ repositories. For isolated use our dependencies, it is highly recommended to use a virtual environment.
39
51
 
40
- .. code-block:: bash
41
52
 
42
- $ pip install c2client
53
+ 1. Clone the repository
54
+
55
+ .. code-block:: bash
56
+
57
+ git clone https://github.com/C2Devel/c2-client.git && cd c2-client
58
+
59
+ 2. Setup the virtual environment(Unix based system)
60
+
61
+ .. code-block:: bash
62
+
63
+ python3 -m venv .venv && source .venv/bin/activate
64
+
65
+ 3. Install the package in editable mode along with dependencies from requirements.txt
66
+
67
+ .. code-block:: bash
68
+
69
+ pip install -e . -r requirements.txt
70
+
43
71
 
44
72
  Usage
45
73
  -----
@@ -75,5 +103,3 @@ Send simple request:
75
103
 
76
104
  $ c2-ec2 RunInstances ImageId cmi-078880A0 Description "Test instance" \
77
105
  InstanceType m1.small MaxCount 1 MinCount 1 SecurityGroup.1 test
78
-
79
-
@@ -9,11 +9,27 @@ Use https://github.com/c2devel/boto3.git and python scripts instead.**
9
9
  Installation
10
10
  ------------
11
11
 
12
- Using pip:
12
+ C2client package relies on forked versions of boto3 and botocore from the `C2Devel/boto3 <https://github.com/c2Devel/boto3>`_ and `C2Devel/botocore <https://github.com/c2Devel/botocore>`_ repositories. For isolated use our dependencies, it is highly recommended to use a virtual environment.
13
13
 
14
- .. code-block:: bash
15
14
 
16
- $ pip install c2client
15
+ 1. Clone the repository
16
+
17
+ .. code-block:: bash
18
+
19
+ git clone https://github.com/C2Devel/c2-client.git && cd c2-client
20
+
21
+ 2. Setup the virtual environment(Unix based system)
22
+
23
+ .. code-block:: bash
24
+
25
+ python3 -m venv .venv && source .venv/bin/activate
26
+
27
+ 3. Install the package in editable mode along with dependencies from requirements.txt
28
+
29
+ .. code-block:: bash
30
+
31
+ pip install -e . -r requirements.txt
32
+
17
33
 
18
34
  Usage
19
35
  -----
@@ -0,0 +1 @@
1
+ __version__ = "0.26"
@@ -1,16 +1,18 @@
1
1
  import argparse
2
+ import datetime
2
3
  import json
3
4
  import re
4
5
  import ssl
6
+ import sys
5
7
  from abc import abstractmethod
6
8
  from functools import wraps
7
- from typing import Any, Dict, Optional
9
+ from typing import Any, Callable, Dict, Optional
8
10
 
9
11
  import boto3
10
12
  import inflection
11
13
 
12
14
  from c2client.errors import InvalidMethodName
13
- from c2client.utils import from_dot_notation, get_env_var, convert_args
15
+ from c2client.utils import convert_args, flatten_key_value_dict, from_dot_notation, get_env_var
14
16
 
15
17
 
16
18
  ssl._create_default_https_context = ssl._create_unverified_context
@@ -84,6 +86,12 @@ class BaseClient:
84
86
 
85
87
  class C2Client(BaseClient):
86
88
 
89
+ DOT_NOTATION_EXIT_HOOKS: Dict[str, Dict[str, Callable]] = {}
90
+ """
91
+ Per-method per-parameter transformation hooks
92
+ to be run after parsing request from dot notation.
93
+ """
94
+
87
95
  @classmethod
88
96
  def get_client(cls, verify: bool):
89
97
  """Return boto3 client."""
@@ -104,7 +112,13 @@ class C2Client(BaseClient):
104
112
  )
105
113
 
106
114
  @classmethod
107
- def make_request(cls, method: str, arguments: Optional[Dict], verify: bool) -> str:
115
+ def make_request(
116
+ cls,
117
+ method: str,
118
+ arguments: Optional[Dict],
119
+ verify: bool,
120
+ convert_to_str: bool = True
121
+ ) -> str:
108
122
 
109
123
  client = cls.get_client(verify)
110
124
 
@@ -114,14 +128,22 @@ class C2Client(BaseClient):
114
128
  if arguments:
115
129
  arguments = cls.convert_fields_names(arguments)
116
130
  shape = client.meta.service_model.operation_model(method).input_shape
117
- arguments = convert_args(from_dot_notation(arguments), shape)
131
+ arguments = convert_args(
132
+ from_dot_notation(
133
+ arguments,
134
+ exit_hooks=cls.DOT_NOTATION_EXIT_HOOKS.get(method),
135
+ ),
136
+ shape,
137
+ )
118
138
 
119
139
  result = getattr(client, inflection.underscore(method))(**arguments)
120
140
 
121
- result.pop("ResponseMetadata", None)
141
+ if convert_to_str:
142
+ result.pop("ResponseMetadata", None)
122
143
 
123
- # default=str is required for serializing Datetime objects
124
- return json.dumps(result, indent=4, default=str)
144
+ # default=str is required for serializing Datetime objects
145
+ return json.dumps(result, indent=4, default=str)
146
+ return result
125
147
 
126
148
  @staticmethod
127
149
  def convert_fields_names(arguments: dict) -> Dict[str, Any]:
@@ -241,3 +263,76 @@ class DirectConnectClient(C2Client):
241
263
 
242
264
  url_key = "DIRECT_CONNECT_URL"
243
265
  client_name = "directconnect"
266
+
267
+
268
+ class KMSClient(C2Client):
269
+
270
+ url_key = "KMS_URL"
271
+ client_name = "kms"
272
+
273
+
274
+ class ResourceGroupsTaggingClient(C2Client):
275
+
276
+ url_key = "RGT_URL"
277
+ client_name = "resourcegroupstaggingapi"
278
+
279
+ DOT_NOTATION_EXIT_HOOKS = {
280
+ "TagResources": {
281
+ "Tags": flatten_key_value_dict,
282
+ }
283
+ }
284
+
285
+
286
+ class LogsClient(C2Client):
287
+
288
+ url_key = "CLOUDWATCH_LOGS_URL"
289
+ client_name = "logs"
290
+
291
+ @classmethod
292
+ @exitcode
293
+ def execute(cls) -> None:
294
+ action, arguments, verify = parse_arguments()
295
+ if action == "StartLiveTail":
296
+ symbols = ["|", "/", "-", "\\"]
297
+ counter = 0
298
+
299
+ try:
300
+ resp = super().make_request(
301
+ action, arguments, verify, convert_to_str=False
302
+ )
303
+ stream = resp["responseStream"]
304
+
305
+ skipped = False
306
+ got_logs = False
307
+
308
+ for item in stream:
309
+ if not skipped and "sessionStart" in item:
310
+ skipped = True
311
+ continue
312
+
313
+ if "sessionUpdate" in item:
314
+ events = item["sessionUpdate"]["sessionResults"]
315
+ if events:
316
+ if not got_logs:
317
+ got_logs = True
318
+ print("\rLogs received:", " " * 8)
319
+
320
+ for event in events:
321
+ ts = datetime.datetime.fromtimestamp(
322
+ event.get("timestamp", 0) / 1_000
323
+ )
324
+ msg = event.get("message", "").strip()
325
+ print(f"\r[{ts}] {msg}")
326
+
327
+ sys.stdout.write(
328
+ f"\rWaiting for logs... {symbols[counter % len(symbols)]}"
329
+ )
330
+ sys.stdout.flush()
331
+ counter += 1
332
+ sys.stdout.write("\r")
333
+
334
+ except KeyboardInterrupt:
335
+ print("\rReceiving events has been stopped.")
336
+ else:
337
+ response = cls.make_request(action, arguments, verify)
338
+ print(response)
@@ -1,6 +1,6 @@
1
1
  import dataclasses
2
2
  import os
3
- from typing import Any, Dict
3
+ from typing import Any, Callable, Dict, List, Optional
4
4
 
5
5
  from botocore.model import ListShape, StructureShape, Shape
6
6
 
@@ -20,8 +20,33 @@ class Parameter:
20
20
  shape: Shape
21
21
 
22
22
 
23
- def from_dot_notation(source):
24
- """Convert a incoming query to a request dictionary.
23
+ def flatten_key_value_dict(
24
+ target_list: List[Dict[str, Any]],
25
+ key_field: str = "Key",
26
+ value_field: str = "Value",
27
+ ) -> Dict[Any, Any]:
28
+ """
29
+ Generic flattening dot notation exit hook.
30
+
31
+ Transforms
32
+ [{<key_field>: <key>, <value_field>: <value>}]
33
+ into
34
+ {<key>: <value>}
35
+ """
36
+
37
+ return {
38
+ item[key_field]: item[value_field]
39
+ for item in target_list
40
+ }
41
+
42
+
43
+ def from_dot_notation(
44
+ source: Dict[Any, Any],
45
+ exit_hooks: Optional[Dict[str, Callable]] = None,
46
+ ):
47
+ """
48
+ Convert a incoming query to a request dictionary.
49
+
25
50
  For example::
26
51
  1. {"Action": ["Action"], "Param": ["Value"]}
27
52
  2. {"Action": ["Action"], "Param.2": ["Value2"], "Param.1": ["Value1"]}
@@ -30,13 +55,23 @@ def from_dot_notation(source):
30
55
  1. {"Action": "Action", "Param": "Value"}
31
56
  2. {"Action": "Action", "Param": ["Value1", "Value2"]}
32
57
  3. {"Action": "Action", "Param": { "SubParam": "Value"}}
58
+
33
59
  :type query: dict
34
60
  :param query: This is dictionary, returned by '_get_query()'.
61
+ :type exit_hooks: dict
62
+ :param exit_hooks: Per-parameter mapping of additional transformation
63
+ to be performed after parsing dot notation.
35
64
  """
36
65
 
37
66
  result = {"result": {}}
38
67
  for key, value in sorted(source.items()):
39
68
  _process_tokens(key.split("."), value, result, "result")
69
+
70
+ if exit_hooks is not None:
71
+ for parameter_name, exit_hook in exit_hooks.items():
72
+ if parameter_name in result["result"]:
73
+ result["result"][parameter_name] = exit_hook(result["result"][parameter_name])
74
+
40
75
  return result["result"]
41
76
 
42
77
 
@@ -1,14 +1,13 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: c2client
3
- Version: 0.25
4
- Summary: CROC Cloud Platform - API Client
3
+ Version: 0.26
4
+ Summary: RockitCloud Platform - API Client
5
5
  Home-page: https://github.com/c2devel/c2-client
6
- Author: CROC Cloud Team
7
- Author-email: devel@croc.ru
6
+ Author: RockitCLoud Team
7
+ Author-email: devel@k2.cloud
8
8
  Maintainer: Andrey Kulaev
9
9
  Maintainer-email: adkulaev@gmail.com
10
10
  License: GPL3
11
- Platform: UNKNOWN
12
11
  Classifier: Development Status :: 5 - Production/Stable
13
12
  Classifier: Environment :: Console
14
13
  Classifier: Intended Audience :: Developers
@@ -23,6 +22,19 @@ Classifier: Programming Language :: Python :: 3.10
23
22
  Classifier: Programming Language :: Python :: 3.11
24
23
  Classifier: Programming Language :: Python :: 3.12
25
24
  Classifier: Programming Language :: Python :: 3.13
25
+ Requires-Dist: boto3
26
+ Requires-Dist: botocore
27
+ Requires-Dist: inflection==0.3.1
28
+ Dynamic: author
29
+ Dynamic: author-email
30
+ Dynamic: classifier
31
+ Dynamic: description
32
+ Dynamic: home-page
33
+ Dynamic: license
34
+ Dynamic: maintainer
35
+ Dynamic: maintainer-email
36
+ Dynamic: requires-dist
37
+ Dynamic: summary
26
38
 
27
39
  K2 Cloud API Client
28
40
  =====================
@@ -35,11 +47,27 @@ Use https://github.com/c2devel/boto3.git and python scripts instead.**
35
47
  Installation
36
48
  ------------
37
49
 
38
- Using pip:
50
+ C2client package relies on forked versions of boto3 and botocore from the `C2Devel/boto3 <https://github.com/c2Devel/boto3>`_ and `C2Devel/botocore <https://github.com/c2Devel/botocore>`_ repositories. For isolated use our dependencies, it is highly recommended to use a virtual environment.
39
51
 
40
- .. code-block:: bash
41
52
 
42
- $ pip install c2client
53
+ 1. Clone the repository
54
+
55
+ .. code-block:: bash
56
+
57
+ git clone https://github.com/C2Devel/c2-client.git && cd c2-client
58
+
59
+ 2. Setup the virtual environment(Unix based system)
60
+
61
+ .. code-block:: bash
62
+
63
+ python3 -m venv .venv && source .venv/bin/activate
64
+
65
+ 3. Install the package in editable mode along with dependencies from requirements.txt
66
+
67
+ .. code-block:: bash
68
+
69
+ pip install -e . -r requirements.txt
70
+
43
71
 
44
72
  Usage
45
73
  -----
@@ -75,5 +103,3 @@ Send simple request:
75
103
 
76
104
  $ c2-ec2 RunInstances ImageId cmi-078880A0 Description "Test instance" \
77
105
  InstanceType m1.small MaxCount 1 MinCount 1 SecurityGroup.1 test
78
-
79
-
@@ -10,7 +10,9 @@ c2-eks = c2client.clients:EKSClient.execute
10
10
  c2-eks-legacy = c2client.clients:LegacyEKSClient.execute
11
11
  c2-elb = c2client.clients:ELBClient.execute
12
12
  c2-iam = c2client.clients:IAMClient.execute
13
+ c2-kms = c2client.clients:KMSClient.execute
14
+ c2-logs = c2client.clients:LogsClient.execute
13
15
  c2-paas = c2client.clients:PaasClient.execute
16
+ c2-rgt = c2client.clients:ResourceGroupsTaggingClient.execute
14
17
  c2-route53 = c2client.clients:Route53Client.execute
15
18
  c2rc-convert = c2client.c2rc_convert:main
16
-
@@ -24,6 +24,7 @@ entrypoints = [
24
24
  ("c2-bs", "BSClient"),
25
25
  ("c2-ct", "CTClient"),
26
26
  ("c2-cw", "CWClient"),
27
+ ("c2-dc", "DirectConnectClient"),
27
28
  ("c2-ec2", "EC2Client"),
28
29
  ("c2-efs", "EFSClient"),
29
30
  ("c2-eks", "EKSClient"),
@@ -31,19 +32,21 @@ entrypoints = [
31
32
  ("c2-elb", "ELBClient"),
32
33
  ("c2-iam", "IAMClient"),
33
34
  ("c2-paas", "PaasClient"),
35
+ ("c2-rgt", "ResourceGroupsTaggingClient"),
34
36
  ("c2-route53", "Route53Client"),
35
- ("c2-dc", "DirectConnectClient"),
37
+ ("c2-kms", "KMSClient"),
38
+ ("c2-logs", "LogsClient"),
36
39
  ]
37
40
 
38
41
  setup(
39
42
  name="c2client",
40
43
  version=__version__,
41
- description="CROC Cloud Platform - API Client",
44
+ description="RockitCloud Platform - API Client",
42
45
  long_description=get_description(),
43
46
  url="https://github.com/c2devel/c2-client",
44
47
  license="GPL3",
45
- author="CROC Cloud Team",
46
- author_email="devel@croc.ru",
48
+ author="RockitCLoud Team",
49
+ author_email="devel@k2.cloud",
47
50
  maintainer="Andrey Kulaev",
48
51
  maintainer_email="adkulaev@gmail.com",
49
52
  classifiers=[
@@ -1 +0,0 @@
1
- __version__ = "0.25"
File without changes
File without changes
File without changes
File without changes