ucloud-sdk-python3 0.11.81__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.
Files changed (280) hide show
  1. ucloud/__init__.py +0 -0
  2. ucloud/client.py +469 -0
  3. ucloud/core/__init__.py +0 -0
  4. ucloud/core/auth/__init__.py +3 -0
  5. ucloud/core/auth/_cfg.py +72 -0
  6. ucloud/core/client/__init__.py +8 -0
  7. ucloud/core/client/_cfg.py +96 -0
  8. ucloud/core/client/_client.py +176 -0
  9. ucloud/core/exc/__init__.py +9 -0
  10. ucloud/core/exc/_exc.py +94 -0
  11. ucloud/core/transport/__init__.py +4 -0
  12. ucloud/core/transport/_requests.py +135 -0
  13. ucloud/core/transport/http.py +120 -0
  14. ucloud/core/transport/utils.py +40 -0
  15. ucloud/core/typesystem/__init__.py +0 -0
  16. ucloud/core/typesystem/abstract.py +60 -0
  17. ucloud/core/typesystem/encoder.py +33 -0
  18. ucloud/core/typesystem/fields.py +149 -0
  19. ucloud/core/typesystem/schema.py +97 -0
  20. ucloud/core/utils/__init__.py +0 -0
  21. ucloud/core/utils/compat.py +15 -0
  22. ucloud/core/utils/deco.py +31 -0
  23. ucloud/core/utils/log.py +29 -0
  24. ucloud/core/utils/middleware.py +63 -0
  25. ucloud/helpers/__init__.py +0 -0
  26. ucloud/helpers/utils.py +90 -0
  27. ucloud/helpers/wait.py +108 -0
  28. ucloud/services/__init__.py +0 -0
  29. ucloud/services/cube/__init__.py +0 -0
  30. ucloud/services/cube/client.py +618 -0
  31. ucloud/services/cube/schemas/__init__.py +0 -0
  32. ucloud/services/cube/schemas/apis.py +548 -0
  33. ucloud/services/cube/schemas/models.py +58 -0
  34. ucloud/services/iam/__init__.py +0 -0
  35. ucloud/services/iam/client.py +1078 -0
  36. ucloud/services/iam/schemas/__init__.py +0 -0
  37. ucloud/services/iam/schemas/apis.py +973 -0
  38. ucloud/services/iam/schemas/models.py +127 -0
  39. ucloud/services/ipsecvpn/__init__.py +0 -0
  40. ucloud/services/ipsecvpn/client.py +522 -0
  41. ucloud/services/ipsecvpn/schemas/__init__.py +0 -0
  42. ucloud/services/ipsecvpn/schemas/apis.py +455 -0
  43. ucloud/services/ipsecvpn/schemas/models.py +134 -0
  44. ucloud/services/ipv6gw/__init__.py +0 -0
  45. ucloud/services/ipv6gw/client.py +44 -0
  46. ucloud/services/ipv6gw/schemas/__init__.py +0 -0
  47. ucloud/services/ipv6gw/schemas/apis.py +34 -0
  48. ucloud/services/ipv6gw/schemas/models.py +3 -0
  49. ucloud/services/isms/__init__.py +0 -0
  50. ucloud/services/isms/client.py +330 -0
  51. ucloud/services/isms/schemas/__init__.py +0 -0
  52. ucloud/services/isms/schemas/apis.py +272 -0
  53. ucloud/services/isms/schemas/models.py +50 -0
  54. ucloud/services/pathx/__init__.py +0 -0
  55. ucloud/services/pathx/client.py +1656 -0
  56. ucloud/services/pathx/schemas/__init__.py +0 -0
  57. ucloud/services/pathx/schemas/apis.py +1289 -0
  58. ucloud/services/pathx/schemas/models.py +420 -0
  59. ucloud/services/stepflow/__init__.py +0 -0
  60. ucloud/services/stepflow/client.py +98 -0
  61. ucloud/services/stepflow/schemas/__init__.py +0 -0
  62. ucloud/services/stepflow/schemas/apis.py +67 -0
  63. ucloud/services/stepflow/schemas/models.py +37 -0
  64. ucloud/services/sts/__init__.py +0 -0
  65. ucloud/services/sts/client.py +46 -0
  66. ucloud/services/sts/schemas/__init__.py +0 -0
  67. ucloud/services/sts/schemas/apis.py +35 -0
  68. ucloud/services/sts/schemas/models.py +16 -0
  69. ucloud/services/tidb/__init__.py +0 -0
  70. ucloud/services/tidb/client.py +120 -0
  71. ucloud/services/tidb/schemas/__init__.py +0 -0
  72. ucloud/services/tidb/schemas/apis.py +103 -0
  73. ucloud/services/tidb/schemas/models.py +11 -0
  74. ucloud/services/uaaa/__init__.py +0 -0
  75. ucloud/services/uaaa/client.py +311 -0
  76. ucloud/services/uaaa/schemas/__init__.py +0 -0
  77. ucloud/services/uaaa/schemas/apis.py +252 -0
  78. ucloud/services/uaaa/schemas/models.py +47 -0
  79. ucloud/services/uaccount/__init__.py +0 -0
  80. ucloud/services/uaccount/client.py +547 -0
  81. ucloud/services/uaccount/schemas/__init__.py +0 -0
  82. ucloud/services/uaccount/schemas/apis.py +442 -0
  83. ucloud/services/uaccount/schemas/models.py +128 -0
  84. ucloud/services/uads/__init__.py +0 -0
  85. ucloud/services/uads/client.py +1148 -0
  86. ucloud/services/uads/schemas/__init__.py +0 -0
  87. ucloud/services/uads/schemas/apis.py +983 -0
  88. ucloud/services/uads/schemas/models.py +199 -0
  89. ucloud/services/ubill/__init__.py +0 -0
  90. ucloud/services/ubill/client.py +248 -0
  91. ucloud/services/ubill/schemas/__init__.py +0 -0
  92. ucloud/services/ubill/schemas/apis.py +183 -0
  93. ucloud/services/ubill/schemas/models.py +107 -0
  94. ucloud/services/ucdn/__init__.py +0 -0
  95. ucloud/services/ucdn/client.py +1964 -0
  96. ucloud/services/ucdn/schemas/__init__.py +0 -0
  97. ucloud/services/ucdn/schemas/apis.py +1395 -0
  98. ucloud/services/ucdn/schemas/models.py +576 -0
  99. ucloud/services/ucloudstack/__init__.py +0 -0
  100. ucloud/services/ucloudstack/client.py +3352 -0
  101. ucloud/services/ucloudstack/schemas/__init__.py +0 -0
  102. ucloud/services/ucloudstack/schemas/apis.py +2887 -0
  103. ucloud/services/ucloudstack/schemas/models.py +560 -0
  104. ucloud/services/ucompshare/__init__.py +0 -0
  105. ucloud/services/ucompshare/client.py +820 -0
  106. ucloud/services/ucompshare/schemas/__init__.py +0 -0
  107. ucloud/services/ucompshare/schemas/apis.py +623 -0
  108. ucloud/services/ucompshare/schemas/models.py +241 -0
  109. ucloud/services/udb/__init__.py +0 -0
  110. ucloud/services/udb/client.py +2463 -0
  111. ucloud/services/udb/schemas/__init__.py +0 -0
  112. ucloud/services/udb/schemas/apis.py +2053 -0
  113. ucloud/services/udb/schemas/models.py +319 -0
  114. ucloud/services/udbproxy/__init__.py +0 -0
  115. ucloud/services/udbproxy/client.py +67 -0
  116. ucloud/services/udbproxy/schemas/__init__.py +0 -0
  117. ucloud/services/udbproxy/schemas/apis.py +38 -0
  118. ucloud/services/udbproxy/schemas/models.py +31 -0
  119. ucloud/services/uddb/__init__.py +0 -0
  120. ucloud/services/uddb/client.py +456 -0
  121. ucloud/services/uddb/schemas/__init__.py +0 -0
  122. ucloud/services/uddb/schemas/apis.py +520 -0
  123. ucloud/services/uddb/schemas/models.py +96 -0
  124. ucloud/services/udi/__init__.py +0 -0
  125. ucloud/services/udi/client.py +250 -0
  126. ucloud/services/udi/schemas/__init__.py +0 -0
  127. ucloud/services/udi/schemas/apis.py +205 -0
  128. ucloud/services/udi/schemas/models.py +58 -0
  129. ucloud/services/udisk/__init__.py +0 -0
  130. ucloud/services/udisk/client.py +832 -0
  131. ucloud/services/udisk/schemas/__init__.py +0 -0
  132. ucloud/services/udisk/schemas/apis.py +741 -0
  133. ucloud/services/udisk/schemas/models.py +100 -0
  134. ucloud/services/udns/__init__.py +0 -0
  135. ucloud/services/udns/client.py +380 -0
  136. ucloud/services/udns/schemas/__init__.py +0 -0
  137. ucloud/services/udns/schemas/apis.py +293 -0
  138. ucloud/services/udns/schemas/models.py +58 -0
  139. ucloud/services/udpn/__init__.py +0 -0
  140. ucloud/services/udpn/client.py +240 -0
  141. ucloud/services/udpn/schemas/__init__.py +0 -0
  142. ucloud/services/udpn/schemas/apis.py +203 -0
  143. ucloud/services/udpn/schemas/models.py +29 -0
  144. ucloud/services/udts/__init__.py +0 -0
  145. ucloud/services/udts/client.py +410 -0
  146. ucloud/services/udts/schemas/__init__.py +0 -0
  147. ucloud/services/udts/schemas/apis.py +403 -0
  148. ucloud/services/udts/schemas/models.py +93 -0
  149. ucloud/services/uec/__init__.py +0 -0
  150. ucloud/services/uec/client.py +1510 -0
  151. ucloud/services/uec/schemas/__init__.py +0 -0
  152. ucloud/services/uec/schemas/apis.py +1195 -0
  153. ucloud/services/uec/schemas/models.py +316 -0
  154. ucloud/services/ufile/__init__.py +0 -0
  155. ucloud/services/ufile/client.py +698 -0
  156. ucloud/services/ufile/schemas/__init__.py +0 -0
  157. ucloud/services/ufile/schemas/apis.py +542 -0
  158. ucloud/services/ufile/schemas/models.py +139 -0
  159. ucloud/services/ufs/__init__.py +0 -0
  160. ucloud/services/ufs/client.py +328 -0
  161. ucloud/services/ufs/schemas/__init__.py +0 -0
  162. ucloud/services/ufs/schemas/apis.py +265 -0
  163. ucloud/services/ufs/schemas/models.py +52 -0
  164. ucloud/services/ugn/__init__.py +0 -0
  165. ucloud/services/ugn/client.py +857 -0
  166. ucloud/services/ugn/schemas/__init__.py +0 -0
  167. ucloud/services/ugn/schemas/apis.py +678 -0
  168. ucloud/services/ugn/schemas/models.py +191 -0
  169. ucloud/services/uhost/__init__.py +0 -0
  170. ucloud/services/uhost/client.py +1647 -0
  171. ucloud/services/uhost/schemas/__init__.py +0 -0
  172. ucloud/services/uhost/schemas/apis.py +1483 -0
  173. ucloud/services/uhost/schemas/models.py +427 -0
  174. ucloud/services/uhub/__init__.py +0 -0
  175. ucloud/services/uhub/client.py +229 -0
  176. ucloud/services/uhub/schemas/__init__.py +0 -0
  177. ucloud/services/uhub/schemas/apis.py +194 -0
  178. ucloud/services/uhub/schemas/models.py +39 -0
  179. ucloud/services/uk8s/__init__.py +0 -0
  180. ucloud/services/uk8s/client.py +729 -0
  181. ucloud/services/uk8s/schemas/__init__.py +0 -0
  182. ucloud/services/uk8s/schemas/apis.py +639 -0
  183. ucloud/services/uk8s/schemas/models.py +179 -0
  184. ucloud/services/ulb/__init__.py +0 -0
  185. ucloud/services/ulb/client.py +2285 -0
  186. ucloud/services/ulb/schemas/__init__.py +0 -0
  187. ucloud/services/ulb/schemas/apis.py +1678 -0
  188. ucloud/services/ulb/schemas/models.py +591 -0
  189. ucloud/services/ulighthost/__init__.py +0 -0
  190. ucloud/services/ulighthost/client.py +576 -0
  191. ucloud/services/ulighthost/schemas/__init__.py +0 -0
  192. ucloud/services/ulighthost/schemas/apis.py +445 -0
  193. ucloud/services/ulighthost/schemas/models.py +133 -0
  194. ucloud/services/umem/__init__.py +0 -0
  195. ucloud/services/umem/client.py +1829 -0
  196. ucloud/services/umem/schemas/__init__.py +0 -0
  197. ucloud/services/umem/schemas/apis.py +1477 -0
  198. ucloud/services/umem/schemas/models.py +327 -0
  199. ucloud/services/umongodb/__init__.py +0 -0
  200. ucloud/services/umongodb/client.py +752 -0
  201. ucloud/services/umongodb/schemas/__init__.py +0 -0
  202. ucloud/services/umongodb/schemas/apis.py +567 -0
  203. ucloud/services/umongodb/schemas/models.py +220 -0
  204. ucloud/services/unet/__init__.py +0 -0
  205. ucloud/services/unet/client.py +1278 -0
  206. ucloud/services/unet/schemas/__init__.py +0 -0
  207. ucloud/services/unet/schemas/apis.py +1006 -0
  208. ucloud/services/unet/schemas/models.py +275 -0
  209. ucloud/services/unvs/__init__.py +0 -0
  210. ucloud/services/unvs/client.py +87 -0
  211. ucloud/services/unvs/schemas/__init__.py +0 -0
  212. ucloud/services/unvs/schemas/apis.py +66 -0
  213. ucloud/services/unvs/schemas/models.py +19 -0
  214. ucloud/services/upfs/__init__.py +0 -0
  215. ucloud/services/upfs/client.py +252 -0
  216. ucloud/services/upfs/schemas/__init__.py +0 -0
  217. ucloud/services/upfs/schemas/apis.py +204 -0
  218. ucloud/services/upfs/schemas/models.py +36 -0
  219. ucloud/services/upgsql/__init__.py +0 -0
  220. ucloud/services/upgsql/client.py +1007 -0
  221. ucloud/services/upgsql/schemas/__init__.py +0 -0
  222. ucloud/services/upgsql/schemas/apis.py +827 -0
  223. ucloud/services/upgsql/schemas/models.py +158 -0
  224. ucloud/services/uphone/__init__.py +0 -0
  225. ucloud/services/uphone/client.py +2122 -0
  226. ucloud/services/uphone/schemas/__init__.py +0 -0
  227. ucloud/services/uphone/schemas/apis.py +1799 -0
  228. ucloud/services/uphone/schemas/models.py +357 -0
  229. ucloud/services/uphost/__init__.py +0 -0
  230. ucloud/services/uphost/client.py +847 -0
  231. ucloud/services/uphost/schemas/__init__.py +0 -0
  232. ucloud/services/uphost/schemas/apis.py +689 -0
  233. ucloud/services/uphost/schemas/models.py +175 -0
  234. ucloud/services/urocketmq/__init__.py +0 -0
  235. ucloud/services/urocketmq/client.py +117 -0
  236. ucloud/services/urocketmq/schemas/__init__.py +0 -0
  237. ucloud/services/urocketmq/schemas/apis.py +92 -0
  238. ucloud/services/urocketmq/schemas/models.py +14 -0
  239. ucloud/services/uslk/__init__.py +0 -0
  240. ucloud/services/uslk/client.py +249 -0
  241. ucloud/services/uslk/schemas/__init__.py +0 -0
  242. ucloud/services/uslk/schemas/apis.py +191 -0
  243. ucloud/services/uslk/schemas/models.py +74 -0
  244. ucloud/services/usms/__init__.py +0 -0
  245. ucloud/services/usms/client.py +759 -0
  246. ucloud/services/usms/schemas/__init__.py +0 -0
  247. ucloud/services/usms/schemas/apis.py +653 -0
  248. ucloud/services/usms/schemas/models.py +215 -0
  249. ucloud/services/utsdb/__init__.py +0 -0
  250. ucloud/services/utsdb/client.py +604 -0
  251. ucloud/services/utsdb/schemas/__init__.py +0 -0
  252. ucloud/services/utsdb/schemas/apis.py +515 -0
  253. ucloud/services/utsdb/schemas/models.py +61 -0
  254. ucloud/services/uvms/__init__.py +0 -0
  255. ucloud/services/uvms/client.py +119 -0
  256. ucloud/services/uvms/schemas/__init__.py +0 -0
  257. ucloud/services/uvms/schemas/apis.py +88 -0
  258. ucloud/services/uvms/schemas/models.py +40 -0
  259. ucloud/services/vpc/__init__.py +0 -0
  260. ucloud/services/vpc/client.py +3233 -0
  261. ucloud/services/vpc/schemas/__init__.py +0 -0
  262. ucloud/services/vpc/schemas/apis.py +2529 -0
  263. ucloud/services/vpc/schemas/models.py +651 -0
  264. ucloud/testing/__init__.py +0 -0
  265. ucloud/testing/driver/__init__.py +5 -0
  266. ucloud/testing/driver/_scenario.py +93 -0
  267. ucloud/testing/driver/_specification.py +57 -0
  268. ucloud/testing/driver/_step.py +166 -0
  269. ucloud/testing/env.py +28 -0
  270. ucloud/testing/exc.py +18 -0
  271. ucloud/testing/funcs.py +68 -0
  272. ucloud/testing/mock.py +28 -0
  273. ucloud/testing/op.py +177 -0
  274. ucloud/testing/utest.py +195 -0
  275. ucloud/version.py +1 -0
  276. ucloud_sdk_python3-0.11.81.dist-info/LICENSE +202 -0
  277. ucloud_sdk_python3-0.11.81.dist-info/METADATA +71 -0
  278. ucloud_sdk_python3-0.11.81.dist-info/RECORD +280 -0
  279. ucloud_sdk_python3-0.11.81.dist-info/WHEEL +5 -0
  280. ucloud_sdk_python3-0.11.81.dist-info/top_level.txt +1 -0
@@ -0,0 +1,93 @@
1
+ import functools
2
+
3
+ from ucloud.testing.driver import _step
4
+
5
+
6
+ class Scenario:
7
+ def __init__(self, spec, id_, title=None, owners=None):
8
+ self.id = id_
9
+ self.title = title
10
+ self.store = {}
11
+ self.errors = []
12
+ self.steps = []
13
+ self.spec = spec
14
+ self.owners = owners
15
+
16
+ def step(self, invoker, *args, **kwargs):
17
+ step = _step.Step(self, invoker, *args, **kwargs)
18
+ self.steps.append(step)
19
+ return step
20
+
21
+ def api(self, **step_kwargs):
22
+ def deco(fn):
23
+ step = self.step(fn, **step_kwargs)
24
+
25
+ @functools.wraps(fn)
26
+ def wrapped(*args, **kwargs):
27
+ return step.run_api(*args, **kwargs)
28
+
29
+ return wrapped
30
+
31
+ return deco
32
+
33
+ def func(self, **step_kwargs):
34
+ def deco(fn):
35
+ step = self.step(fn, **step_kwargs)
36
+
37
+ @functools.wraps(fn)
38
+ def wrapped(*args, **kwargs):
39
+ return step.run_func(*args, **kwargs)
40
+
41
+ return wrapped
42
+
43
+ return deco
44
+
45
+ @property
46
+ def status(self):
47
+ if all([item.status == "skipped" for item in self.steps]):
48
+ status = "skipped"
49
+ elif any([item.status == "failed" for item in self.steps]):
50
+ status = "failed"
51
+ else:
52
+ status = "passed"
53
+ return status
54
+
55
+ @property
56
+ def start_time(self):
57
+ times = [
58
+ item.start_time for item in self.steps if item.status != "skipped"
59
+ ]
60
+ return min(times) if times else 0
61
+
62
+ @property
63
+ def end_time(self):
64
+ times = [
65
+ item.end_time for item in self.steps if item.status != "skipped"
66
+ ]
67
+ return max(times) if times else 0
68
+
69
+ def json(self):
70
+ return {
71
+ "title": self.title,
72
+ "status": self.status,
73
+ "steps": [item.json() for item in self.steps],
74
+ "owners": self.owners,
75
+ "execution": {
76
+ "duration": self.end_time - self.start_time,
77
+ "start_time": self.start_time,
78
+ "end_time": self.end_time,
79
+ },
80
+ "passed_count": len(
81
+ [1 for item in self.steps if item.status == "passed"]
82
+ ),
83
+ "failed_count": len(
84
+ [1 for item in self.steps if item.status == "failed"]
85
+ ),
86
+ "skipped_count": len(
87
+ [1 for item in self.steps if item.status == "skipped"]
88
+ ),
89
+ }
90
+
91
+ def __call__(self, *args, **kwargs):
92
+ for step in self.steps:
93
+ step(step, *args, **kwargs)
@@ -0,0 +1,57 @@
1
+ from ucloud.testing.driver import _scenario
2
+
3
+
4
+ class Specification:
5
+ def __init__(self):
6
+ self.scenarios = []
7
+
8
+ def scenario(self, id_, title="", owners=None):
9
+ scenario = _scenario.Scenario(self, id_, title, owners)
10
+ self.scenarios.append(scenario)
11
+ return scenario
12
+
13
+ @property
14
+ def status(self):
15
+ if all([item.status == "skipped" for item in self.scenarios]):
16
+ status = "skipped"
17
+ elif any([item.status == "failed" for item in self.scenarios]):
18
+ status = "failed"
19
+ else:
20
+ status = "passed"
21
+ return status
22
+
23
+ @property
24
+ def start_time(self):
25
+ times = [
26
+ item.start_time
27
+ for item in self.scenarios
28
+ if item.status != "skipped"
29
+ ]
30
+ return min(times) if times else 0
31
+
32
+ @property
33
+ def end_time(self):
34
+ times = [
35
+ item.end_time for item in self.scenarios if item.status != "skipped"
36
+ ]
37
+ return max(times) if times else 0
38
+
39
+ def json(self):
40
+ return {
41
+ "status": self.status,
42
+ "execution": {
43
+ "duration": self.end_time - self.start_time,
44
+ "start_time": self.start_time,
45
+ "end_time": self.end_time,
46
+ },
47
+ "scenarios": [item.json() for item in self.scenarios],
48
+ "passed_count": len(
49
+ [1 for item in self.scenarios if item.status == "passed"]
50
+ ),
51
+ "failed_count": len(
52
+ [1 for item in self.scenarios if item.status == "failed"]
53
+ ),
54
+ "skipped_count": len(
55
+ [1 for item in self.scenarios if item.status == "skipped"]
56
+ ),
57
+ }
@@ -0,0 +1,166 @@
1
+ import logging
2
+ import time
3
+ import typing
4
+
5
+ from ucloud.core.transport import http
6
+ from ucloud.testing import exc, utest, op
7
+ from ucloud.testing.exc import ValueNotFoundError, CompareError
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ class Step:
13
+ def __init__(
14
+ self,
15
+ scenario,
16
+ invoker,
17
+ max_retries: int = 0,
18
+ retry_interval: int = 0,
19
+ startup_delay: int = 0,
20
+ retry_for: typing.Tuple = (CompareError, ValueNotFoundError),
21
+ fast_fail: bool = False,
22
+ validators: typing.Callable[[dict], typing.List[typing.Tuple]] = None,
23
+ title: str = "",
24
+ **kwargs
25
+ ):
26
+ """Step is the test step in a test scenario
27
+ :param invoker: invoker is a callable function
28
+ :param max_retries: the maximum retry number by the `retry_for` exception,
29
+ it will resolve the flaky testing case
30
+ :param retry_interval: the interval between twice retrying
31
+ :param retry_for: the exceptions to retrying
32
+ :param startup_delay: the delay seconds before any action execution
33
+ :param fast_fail: if fast fail is true, the test will fail when got
34
+ unexpected exception
35
+ :return:
36
+ """
37
+ self.invoker = invoker
38
+ self.validators = validators or (lambda _: [])
39
+
40
+ self.max_retries = max_retries
41
+ self.retry_interval = retry_interval
42
+ self.retry_for = retry_for
43
+ self.startup_delay = startup_delay
44
+ self.fast_fail = fast_fail
45
+
46
+ self.start_time = 0
47
+ self.end_time = 0
48
+ self.status = "skipped"
49
+
50
+ self.title = title
51
+ self.type = "api"
52
+ self.errors = []
53
+
54
+ self.extras = kwargs
55
+ self.scenario = scenario
56
+ self.store = scenario.store
57
+ self.api_retries = []
58
+
59
+ def run_api(self, client, *args, **kwargs):
60
+ client.transport.middleware.response(self._handle_response, 0)
61
+ try:
62
+ result = self._run(
63
+ self._set_default_response, client, *args, **kwargs
64
+ )
65
+ except Exception as e:
66
+ raise e
67
+ finally:
68
+ client.transport.middleware.response_handlers.pop(0)
69
+ return result
70
+
71
+ def run_func(self, *args, **kwargs):
72
+ return self._run(None, *args, **kwargs)
73
+
74
+ def json(self):
75
+ return {
76
+ "title": self.title,
77
+ "type": self.type,
78
+ "status": self.status,
79
+ "execution": {
80
+ "max_retries": self.max_retries,
81
+ "retry_interval": self.retry_interval,
82
+ "startup_delay": self.startup_delay,
83
+ "fast_fail": self.fast_fail,
84
+ "duration": self.end_time - self.start_time,
85
+ "start_time": self.start_time,
86
+ "end_time": self.end_time,
87
+ },
88
+ "api_retries": self.api_retries,
89
+ "errors": list(set([str(e) for e in self.errors])),
90
+ }
91
+
92
+ def _handle_response(self, resp: http.Response):
93
+ req = resp.request.payload()
94
+ req.pop("Signature", None)
95
+
96
+ self.api_retries.append(
97
+ {
98
+ "request": req,
99
+ "response": resp.json(),
100
+ "request_uuid": resp.headers.get("X-UCLOUD-REQUEST-UUID"),
101
+ "request_time": resp.request.request_time,
102
+ }
103
+ )
104
+ return resp
105
+
106
+ def _set_default_response(self, result):
107
+ if result is None:
108
+ return result
109
+ result.setdefault("RetCode", 0)
110
+ if "action" in self.extras:
111
+ result["Action"] = "{}Response".format(self.extras["action"])
112
+ return result
113
+
114
+ def _run(self, invoke_callback=None, *args, **kwargs):
115
+ self.start_time = time.time()
116
+
117
+ try:
118
+ result = self._run_with_callback(invoke_callback, *args, **kwargs)
119
+ except Exception as e:
120
+ raise e
121
+ finally:
122
+ self.end_time = time.time()
123
+
124
+ return result
125
+
126
+ def _run_with_callback(self, invoke_callback=None, *args, **kwargs):
127
+ # wait for delay before startup
128
+ if self.startup_delay:
129
+ time.sleep(self.startup_delay)
130
+
131
+ for i in range(self.max_retries + 1):
132
+ self.errors.clear()
133
+
134
+ # invoke function to load result
135
+ try:
136
+ result = self.invoker(self, *args, **kwargs)
137
+ except Exception as e:
138
+ result = None
139
+ self.errors.append(e)
140
+ else:
141
+ invoke_callback and invoke_callback(result)
142
+
143
+ for validator in self.validators(self.store):
144
+ try:
145
+ op.check(
146
+ validator[0],
147
+ utest.value_at_path(result, validator[1]),
148
+ validator[2],
149
+ )
150
+ except self.retry_for as e:
151
+ self.errors.append(e)
152
+ except Exception as e:
153
+ self.errors.append(e)
154
+
155
+ # if got error, retrying or raise it
156
+ if self.errors:
157
+ if i == self.max_retries:
158
+ self.status = "failed"
159
+ raise exc.ValidateError(self.errors)
160
+
161
+ if self.retry_interval:
162
+ time.sleep(self.retry_interval)
163
+ continue
164
+
165
+ self.status = "passed"
166
+ return result or None
ucloud/testing/env.py ADDED
@@ -0,0 +1,28 @@
1
+ import os
2
+
3
+ ACC_ENV_KEY = "USDKACC"
4
+ ACC_SKIP_REASON = "skip test for non-acc environment"
5
+
6
+
7
+ def get_skip_reason():
8
+ return ACC_SKIP_REASON
9
+
10
+
11
+ def is_acc() -> bool:
12
+ """check test env is acceptance testing or not"""
13
+ return os.getenv(ACC_ENV_KEY)
14
+
15
+
16
+ def is_ut() -> bool:
17
+ """check test env is unit testing or not"""
18
+ return not is_acc()
19
+
20
+
21
+ def pre_check_env():
22
+ """pre check environment for testing
23
+
24
+ NOTE: system environment variables credential is required for test environment
25
+ """
26
+ assert os.getenv("UCLOUD_PUBLIC_KEY"), "invalid public key"
27
+ assert os.getenv("UCLOUD_PRIVATE_KEY"), "invalid private key"
28
+ assert os.getenv("UCLOUD_PROJECT_ID"), "invalid region"
ucloud/testing/exc.py ADDED
@@ -0,0 +1,18 @@
1
+ class UTestError(Exception):
2
+ pass
3
+
4
+
5
+ class ValidateError(UTestError):
6
+ def __init__(self, errors):
7
+ self.errors = errors
8
+
9
+ def __str__(self):
10
+ return str(self.errors)
11
+
12
+
13
+ class ValueNotFoundError(UTestError):
14
+ pass
15
+
16
+
17
+ class CompareError(UTestError):
18
+ pass
@@ -0,0 +1,68 @@
1
+ import datetime
2
+ import time
3
+
4
+
5
+ def concat(*args):
6
+ """cancat strings
7
+
8
+ >>> concat(42, 'foo', 'bar')
9
+ '42foobar'
10
+ """
11
+ return "".join([str(s) for s in args])
12
+
13
+
14
+ def concat_without_dot(args):
15
+ """replace blank
16
+
17
+ >>> concat_without_dot('42foo bar')
18
+ '42foobar'
19
+ """
20
+ return "".join([str(s) for s in args.split()])
21
+
22
+
23
+ def search_value(array, origin_key, origin_value, dest_key):
24
+ """given origin key and value,search dest_value form array by dest_key
25
+
26
+ >>> d = [{"UHostId": "foo", "Name": "testing"}]
27
+ >>> search_value(d, "Name", "testing", "UHostId")
28
+ 'foo'
29
+ """
30
+ arr = [i.get(dest_key, "") for i in array if i[origin_key] == origin_value]
31
+ if arr:
32
+ return arr[0]
33
+ return ""
34
+
35
+
36
+ def timedelta(timestamp, value, typ="days"):
37
+ """given timestamp(10bit) and calculate relative delta time
38
+
39
+ >>> timedelta(0, 1, "days")
40
+ 86400.0
41
+
42
+ :param timestamp: timestamp (round to second)
43
+ :param value: float, can as positive or negative
44
+ :param typ: days/hours
45
+ :return: timestamp
46
+ """
47
+ value = int(value)
48
+ dt = datetime.datetime.fromtimestamp(float(timestamp))
49
+ if typ == "days":
50
+ dt += datetime.timedelta(days=value)
51
+ elif typ == "hours":
52
+ dt += datetime.timedelta(hours=value)
53
+ return time.mktime(dt.timetuple())
54
+
55
+
56
+ def get_timestamp(length=13):
57
+ """get current timestamp string
58
+
59
+ >>> len(str(int(get_timestamp(10))))
60
+ 10
61
+
62
+ :param length: length of timestamp, can only between 0 and 16
63
+ :return:
64
+ """
65
+ if isinstance(length, int) and 0 < length < 17:
66
+ return int("{:.6f}".format(time.time()).replace(".", "")[:length])
67
+
68
+ raise ValueError("timestamp length can only between 0 and 16.")
ucloud/testing/mock.py ADDED
@@ -0,0 +1,28 @@
1
+ import json
2
+ import typing
3
+
4
+ from ucloud.core.transport import Transport, Request, Response
5
+
6
+
7
+ class MockedTransport(Transport):
8
+ def __init__(self):
9
+ super(MockedTransport, self).__init__()
10
+ self.transport_handlers = []
11
+ self.client_handler = []
12
+
13
+ def send(self, req: Request, **options: typing.Any) -> Response:
14
+ resp = Response(req.url, req.method)
15
+ for handler in self.transport_handlers:
16
+ resp = handler(req)
17
+
18
+ for handler in self.client_handler:
19
+ payload = handler(req.payload())
20
+ resp.content = json.dumps(payload).encode("utf-8")
21
+
22
+ return resp
23
+
24
+ def mock(self, handler: typing.Callable[[Request], Response]):
25
+ self.transport_handlers.append(handler)
26
+
27
+ def mock_data(self, handler: typing.Callable[[dict], dict]):
28
+ self.client_handler.append(handler)
ucloud/testing/op.py ADDED
@@ -0,0 +1,177 @@
1
+ import re
2
+
3
+ from ucloud.testing.exc import CompareError
4
+
5
+
6
+ def eq(value, expected):
7
+ """value is equal to expected"""
8
+ assert value == expected
9
+
10
+
11
+ def ne(value, expected):
12
+ """value is equal to expected"""
13
+ assert value != expected
14
+
15
+
16
+ def gt(value, expected):
17
+ """value is greater than expected"""
18
+ assert float(value) > float(expected)
19
+
20
+
21
+ def ge(value, expected):
22
+ """value is greater than or equal to expected"""
23
+ assert float(value) >= float(expected)
24
+
25
+
26
+ def abs_eq(value, expected):
27
+ """value is approx equal to expected"""
28
+ assert round(float(value), 2) == round(float(expected), 2)
29
+
30
+
31
+ def lt(value, expected):
32
+ """value is less than excepted"""
33
+ assert float(value) < float(expected)
34
+
35
+
36
+ def le(value, expected):
37
+ """value is less than or equal to excepted"""
38
+ assert float(value) <= float(expected)
39
+
40
+
41
+ def str_eq(value, expected):
42
+ """value is equal to excepted as string"""
43
+ assert str(value) == str(expected)
44
+
45
+
46
+ def float_eq(value, expected):
47
+ """value is equal to excepted as float"""
48
+ assert round(float(value), 2) == round(float(expected), 2)
49
+
50
+
51
+ def len_eq(value, expected):
52
+ """length of value is equal to excepted"""
53
+ assert isinstance(expected, int)
54
+ assert len(value) == expected
55
+
56
+
57
+ def len_gt(value, expected):
58
+ """length of value is greater than excepted"""
59
+ assert isinstance(expected, int)
60
+ assert len(value) > expected
61
+
62
+
63
+ def len_ge(value, expected):
64
+ """length of value is greater than or equal to excepted"""
65
+ assert isinstance(expected, int)
66
+ assert len(value) >= expected
67
+
68
+
69
+ def len_lt(value, expected):
70
+ """length of value is less than excepted"""
71
+ assert isinstance(expected, int)
72
+ assert len(value) < expected
73
+
74
+
75
+ def len_le(value, expected):
76
+ """length of value is less than or equal to excepted"""
77
+ assert isinstance(expected, int)
78
+ assert len(value) <= expected
79
+
80
+
81
+ def contains(value, expected):
82
+ """value is contains expected"""
83
+ assert expected in value
84
+
85
+
86
+ def contained_by(value, expected):
87
+ """value is contained by expected"""
88
+ assert value in expected
89
+
90
+
91
+ def type_eq(value, expected):
92
+ assert isinstance(value, expected)
93
+
94
+
95
+ def regex(value, expected):
96
+ assert isinstance(expected, str)
97
+ assert isinstance(value, str)
98
+ assert re.match(expected, value)
99
+
100
+
101
+ def startswith(value, expected):
102
+ assert str(value).startswith(expected)
103
+
104
+
105
+ def endswith(value, expected):
106
+ assert str(value).endswith(expected)
107
+
108
+
109
+ def object_contains(value, expected):
110
+ assert str(expected) in str(value)
111
+
112
+
113
+ def object_not_contains(value, expected):
114
+ assert str(expected) not in str(value)
115
+
116
+
117
+ mapper = {
118
+ "eq": eq,
119
+ "equals": eq,
120
+ "==": eq,
121
+ "abs_eq": abs_eq,
122
+ "abs_equals": abs_eq,
123
+ "lt": lt,
124
+ "less_than": lt,
125
+ "le": le,
126
+ "less_than_or_equals": le,
127
+ "gt": gt,
128
+ "greater_than": gt,
129
+ "ge": ge,
130
+ "greater_than_or_equals": ge,
131
+ "ne": ne,
132
+ "not_equals": ne,
133
+ "str_eq": str_eq,
134
+ "string_equals": str_eq,
135
+ "float_eq": float_eq,
136
+ "float_equals": float_eq,
137
+ "len_eq": len_eq,
138
+ "length_equals": len_eq,
139
+ "count_eq": len_eq,
140
+ "len_gt": len_gt,
141
+ "count_gt": len_gt,
142
+ "length_greater_than": len_gt,
143
+ "count_greater_than": len_gt,
144
+ "len_ge": len_ge,
145
+ "count_ge": len_ge,
146
+ "length_greater_than_or_equals": len_ge,
147
+ "count_greater_than_or_equals": len_ge,
148
+ "len_lt": len_lt,
149
+ "count_lt": len_lt,
150
+ "length_less_than": len_lt,
151
+ "count_less_than": len_lt,
152
+ "len_le": len_le,
153
+ "count_le": len_le,
154
+ "length_less_than_or_equals": len_le,
155
+ "count_less_than_or_equals": len_le,
156
+ "contains": contains,
157
+ "contained_by": contained_by,
158
+ "type": type_eq,
159
+ "regex": regex,
160
+ "startswith": startswith,
161
+ "endswith": endswith,
162
+ "object_contains": object_contains,
163
+ "object_not_contains": object_not_contains,
164
+ }
165
+
166
+
167
+ def check(name, value, expected):
168
+ if name not in mapper:
169
+ raise CompareError("comparator {} is not found".format(name))
170
+
171
+ try:
172
+ return mapper.get(name)(value, expected)
173
+ except AssertionError as e:
174
+ msg = "assert error, expect {} {} {}, got error {}".format(
175
+ value, name, expected, e
176
+ )
177
+ raise CompareError(msg)