python3-core-api-client 0.1__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 (59) hide show
  1. cyberfusion/CoreApiClient/__init__.py +0 -0
  2. cyberfusion/CoreApiClient/_encoders.py +7 -0
  3. cyberfusion/CoreApiClient/connector.py +382 -0
  4. cyberfusion/CoreApiClient/exceptions.py +13 -0
  5. cyberfusion/CoreApiClient/http.py +21 -0
  6. cyberfusion/CoreApiClient/interfaces.py +9 -0
  7. cyberfusion/CoreApiClient/models.py +5350 -0
  8. cyberfusion/CoreApiClient/resources/__init__.py +99 -0
  9. cyberfusion/CoreApiClient/resources/basic_authentication_realms.py +85 -0
  10. cyberfusion/CoreApiClient/resources/borg_archives.py +144 -0
  11. cyberfusion/CoreApiClient/resources/borg_repositories.py +134 -0
  12. cyberfusion/CoreApiClient/resources/certificate_managers.py +99 -0
  13. cyberfusion/CoreApiClient/resources/certificates.py +63 -0
  14. cyberfusion/CoreApiClient/resources/clusters.py +233 -0
  15. cyberfusion/CoreApiClient/resources/cmses.py +289 -0
  16. cyberfusion/CoreApiClient/resources/crons.py +76 -0
  17. cyberfusion/CoreApiClient/resources/custom_config_snippets.py +88 -0
  18. cyberfusion/CoreApiClient/resources/custom_configs.py +82 -0
  19. cyberfusion/CoreApiClient/resources/customers.py +97 -0
  20. cyberfusion/CoreApiClient/resources/daemons.py +76 -0
  21. cyberfusion/CoreApiClient/resources/database_user_grants.py +66 -0
  22. cyberfusion/CoreApiClient/resources/database_users.py +82 -0
  23. cyberfusion/CoreApiClient/resources/databases.py +140 -0
  24. cyberfusion/CoreApiClient/resources/domain_routers.py +43 -0
  25. cyberfusion/CoreApiClient/resources/firewall_groups.py +82 -0
  26. cyberfusion/CoreApiClient/resources/firewall_rules.py +67 -0
  27. cyberfusion/CoreApiClient/resources/fpm_pools.py +110 -0
  28. cyberfusion/CoreApiClient/resources/ftp_users.py +89 -0
  29. cyberfusion/CoreApiClient/resources/haproxy_listens.py +67 -0
  30. cyberfusion/CoreApiClient/resources/haproxy_listens_to_nodes.py +70 -0
  31. cyberfusion/CoreApiClient/resources/health.py +14 -0
  32. cyberfusion/CoreApiClient/resources/hosts_entries.py +63 -0
  33. cyberfusion/CoreApiClient/resources/htpasswd_files.py +67 -0
  34. cyberfusion/CoreApiClient/resources/htpasswd_users.py +82 -0
  35. cyberfusion/CoreApiClient/resources/login.py +28 -0
  36. cyberfusion/CoreApiClient/resources/logs.py +50 -0
  37. cyberfusion/CoreApiClient/resources/mail_accounts.py +105 -0
  38. cyberfusion/CoreApiClient/resources/mail_aliases.py +79 -0
  39. cyberfusion/CoreApiClient/resources/mail_domains.py +79 -0
  40. cyberfusion/CoreApiClient/resources/mail_hostnames.py +82 -0
  41. cyberfusion/CoreApiClient/resources/malwares.py +53 -0
  42. cyberfusion/CoreApiClient/resources/mariadb_encryption_keys.py +56 -0
  43. cyberfusion/CoreApiClient/resources/node_add_ons.py +74 -0
  44. cyberfusion/CoreApiClient/resources/nodes.py +112 -0
  45. cyberfusion/CoreApiClient/resources/passenger_apps.py +99 -0
  46. cyberfusion/CoreApiClient/resources/redis_instances.py +85 -0
  47. cyberfusion/CoreApiClient/resources/root_ssh_keys.py +77 -0
  48. cyberfusion/CoreApiClient/resources/security_txt_policies.py +85 -0
  49. cyberfusion/CoreApiClient/resources/sites.py +29 -0
  50. cyberfusion/CoreApiClient/resources/ssh_keys.py +77 -0
  51. cyberfusion/CoreApiClient/resources/task_collections.py +38 -0
  52. cyberfusion/CoreApiClient/resources/tombstones.py +29 -0
  53. cyberfusion/CoreApiClient/resources/unix_users.py +122 -0
  54. cyberfusion/CoreApiClient/resources/url_redirects.py +79 -0
  55. cyberfusion/CoreApiClient/resources/virtual_hosts.py +120 -0
  56. python3_core_api_client-0.1.dist-info/METADATA +236 -0
  57. python3_core_api_client-0.1.dist-info/RECORD +59 -0
  58. python3_core_api_client-0.1.dist-info/WHEEL +5 -0
  59. python3_core_api_client-0.1.dist-info/top_level.txt +1 -0
File without changes
@@ -0,0 +1,7 @@
1
+ import datetime
2
+ from json import JSONEncoder
3
+
4
+
5
+ class DatetimeEncoder(JSONEncoder):
6
+ def default(self, o: datetime.datetime) -> str:
7
+ return o.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
@@ -0,0 +1,382 @@
1
+ import json
2
+ from typing import Optional, Tuple
3
+ from urllib.parse import urlparse
4
+
5
+ from cyberfusion.CoreApiClient._encoders import DatetimeEncoder
6
+ from cyberfusion.CoreApiClient.exceptions import CallException, AuthenticationException
7
+
8
+ from requests.sessions import Session
9
+ from typing import Dict, Any, Union
10
+ from requests.adapters import HTTPAdapter, Retry
11
+ import requests
12
+ import certifi
13
+ from functools import cached_property
14
+ from cyberfusion.CoreApiClient import resources
15
+ import datetime
16
+ import importlib.metadata
17
+ from cyberfusion.CoreApiClient.http import Response
18
+
19
+
20
+ class CoreApiConnector:
21
+ def __init__(
22
+ self,
23
+ base_url: str = "https://core-api.cyberfusion.io",
24
+ *,
25
+ username: Optional[str] = None,
26
+ password: Optional[str] = None,
27
+ api_key: Optional[str] = None,
28
+ requests_session: Optional[Session] = None,
29
+ ) -> None:
30
+ self.base_url = base_url
31
+ self.username = username
32
+ self.password = password
33
+ self.api_key = api_key
34
+
35
+ self._jwt_metadata: Optional[Tuple[str, Any]] = None
36
+
37
+ if (self.username and self.password) and self.api_key:
38
+ raise ValueError(
39
+ "Specify either username and password, or API key, not both"
40
+ )
41
+
42
+ if self.username and not self.password:
43
+ raise ValueError("If username is specified, password must be specified")
44
+
45
+ if self.password and not self.username:
46
+ raise ValueError("If password is specified, username must be specified")
47
+
48
+ if not self.api_key and not (self.username and self.password):
49
+ raise ValueError("Specify either username and password, or API key")
50
+
51
+ self.requests_session = requests_session or self.get_default_requests_session()
52
+
53
+ @property
54
+ def root_url(self) -> str:
55
+ return urlparse(self.base_url)._replace(path="").geturl()
56
+
57
+ @property
58
+ def authentication_headers(self) -> Dict[str, str]:
59
+ headers = {}
60
+
61
+ if self.api_key:
62
+ headers["X-API-Key"] = self.api_key
63
+ else:
64
+ login = False
65
+
66
+ if not self._jwt_metadata:
67
+ login = True
68
+ else:
69
+ access_token, expires_at = self._jwt_metadata
70
+
71
+ if datetime.datetime.utcnow() >= expires_at:
72
+ login = True
73
+
74
+ if login:
75
+ response = self.requests_session.post(
76
+ "".join([self.root_url, "/api/v1/login/access-token"]),
77
+ data={"username": self.username, "password": self.password},
78
+ verify=certifi.where(),
79
+ timeout=60,
80
+ headers={"Content-Type": "application/x-www-form-urlencoded"},
81
+ )
82
+
83
+ try:
84
+ response.raise_for_status()
85
+ except requests.exceptions.HTTPError as e:
86
+ raise AuthenticationException(
87
+ response.text, response.status_code
88
+ ) from e
89
+
90
+ json = response.json()
91
+
92
+ access_token = json["access_token"]
93
+ expires_in = json["expires_in"]
94
+ expires_at = datetime.datetime.utcnow() + datetime.timedelta(
95
+ seconds=expires_in
96
+ )
97
+
98
+ self._jwt_metadata = (access_token, expires_at)
99
+
100
+ headers["Authorization"] = "Bearer " + access_token
101
+
102
+ return headers
103
+
104
+ def send(
105
+ self,
106
+ method: str,
107
+ path: str,
108
+ data: Optional[Union[str, dict]] = None,
109
+ query_parameters: Optional[dict] = None,
110
+ *,
111
+ content_type: str = "application/json",
112
+ ) -> Response:
113
+ url = "".join([self.base_url, path])
114
+
115
+ if data and content_type == "application/json":
116
+ data = json.dumps(data, cls=DatetimeEncoder)
117
+
118
+ if query_parameters:
119
+ for key, value in query_parameters.items():
120
+ if isinstance(value, datetime.datetime):
121
+ query_parameters[key] = json.loads(
122
+ json.dumps(value, cls=DatetimeEncoder)
123
+ )
124
+
125
+ requests_response = self.requests_session.request(
126
+ method,
127
+ url,
128
+ headers=self.authentication_headers | {"Content-Type": content_type},
129
+ data=data,
130
+ params=query_parameters,
131
+ verify=certifi.where(),
132
+ timeout=60,
133
+ )
134
+
135
+ local_response = Response(
136
+ status_code=requests_response.status_code,
137
+ body=requests_response.text,
138
+ headers=requests_response.headers,
139
+ )
140
+
141
+ return local_response
142
+
143
+ def send_or_fail(
144
+ self,
145
+ method: str,
146
+ path: str,
147
+ data: Optional[dict] = None,
148
+ query_parameters: Optional[dict] = None,
149
+ *,
150
+ content_type: str = "application/json",
151
+ ) -> Response:
152
+ local_response = self.send(
153
+ method, path, data, query_parameters, content_type=content_type
154
+ )
155
+
156
+ if local_response.failed:
157
+ raise CallException(local_response.body, local_response.status_code)
158
+
159
+ return local_response
160
+
161
+ def get_default_requests_session(self) -> requests.sessions.Session:
162
+ session = requests.Session()
163
+
164
+ adapter = HTTPAdapter(
165
+ max_retries=Retry(
166
+ total=10,
167
+ backoff_factor=2.5,
168
+ allowed_methods=None,
169
+ status_forcelist=[502, 503],
170
+ )
171
+ )
172
+
173
+ session.mount(self.base_url + "/", adapter)
174
+
175
+ session.headers.update(
176
+ {
177
+ "User-Agent": "python3-core-api-client/"
178
+ + importlib.metadata.version("python3-core-api-client")
179
+ }
180
+ )
181
+
182
+ return session
183
+
184
+ @cached_property
185
+ def login(self) -> resources.login.Login:
186
+ return resources.login.Login(self)
187
+
188
+ @cached_property
189
+ def sites(self) -> resources.sites.Sites:
190
+ return resources.sites.Sites(self)
191
+
192
+ @cached_property
193
+ def customers(self) -> resources.customers.Customers:
194
+ return resources.customers.Customers(self)
195
+
196
+ @cached_property
197
+ def haproxy_listens(self) -> resources.haproxy_listens.HAProxyListens:
198
+ return resources.haproxy_listens.HAProxyListens(self)
199
+
200
+ @cached_property
201
+ def haproxy_listens_to_nodes(
202
+ self,
203
+ ) -> resources.haproxy_listens_to_nodes.HAProxyListensToNodes:
204
+ return resources.haproxy_listens_to_nodes.HAProxyListensToNodes(self)
205
+
206
+ @cached_property
207
+ def borg_repositories(self) -> resources.borg_repositories.BorgRepositories:
208
+ return resources.borg_repositories.BorgRepositories(self)
209
+
210
+ @cached_property
211
+ def borg_archives(self) -> resources.borg_archives.BorgArchives:
212
+ return resources.borg_archives.BorgArchives(self)
213
+
214
+ @cached_property
215
+ def certificates(self) -> resources.certificates.Certificates:
216
+ return resources.certificates.Certificates(self)
217
+
218
+ @cached_property
219
+ def certificate_managers(
220
+ self,
221
+ ) -> resources.certificate_managers.CertificateManagers:
222
+ return resources.certificate_managers.CertificateManagers(self)
223
+
224
+ @cached_property
225
+ def tombstones(self) -> resources.tombstones.Tombstones:
226
+ return resources.tombstones.Tombstones(self)
227
+
228
+ @cached_property
229
+ def clusters(self) -> resources.clusters.Clusters:
230
+ return resources.clusters.Clusters(self)
231
+
232
+ @cached_property
233
+ def virtual_hosts(self) -> resources.virtual_hosts.VirtualHosts:
234
+ return resources.virtual_hosts.VirtualHosts(self)
235
+
236
+ @cached_property
237
+ def mail_hostnames(self) -> resources.mail_hostnames.MailHostnames:
238
+ return resources.mail_hostnames.MailHostnames(self)
239
+
240
+ @cached_property
241
+ def domain_routers(self) -> resources.domain_routers.DomainRouters:
242
+ return resources.domain_routers.DomainRouters(self)
243
+
244
+ @cached_property
245
+ def url_redirects(self) -> resources.url_redirects.URLRedirects:
246
+ return resources.url_redirects.URLRedirects(self)
247
+
248
+ @cached_property
249
+ def htpasswd_files(self) -> resources.htpasswd_files.HtpasswdFiles:
250
+ return resources.htpasswd_files.HtpasswdFiles(self)
251
+
252
+ @cached_property
253
+ def htpasswd_users(self) -> resources.htpasswd_users.HtpasswdUsers:
254
+ return resources.htpasswd_users.HtpasswdUsers(self)
255
+
256
+ @cached_property
257
+ def basic_authentication_realms(
258
+ self,
259
+ ) -> resources.basic_authentication_realms.BasicAuthenticationRealms:
260
+ return resources.basic_authentication_realms.BasicAuthenticationRealms(self)
261
+
262
+ @cached_property
263
+ def node_add_ons(self) -> resources.node_add_ons.NodeAddOns:
264
+ return resources.node_add_ons.NodeAddOns(self)
265
+
266
+ @cached_property
267
+ def crons(self) -> resources.crons.Crons:
268
+ return resources.crons.Crons(self)
269
+
270
+ @cached_property
271
+ def daemons(self) -> resources.daemons.Daemons:
272
+ return resources.daemons.Daemons(self)
273
+
274
+ @cached_property
275
+ def mariadb_encryption_keys(
276
+ self,
277
+ ) -> resources.mariadb_encryption_keys.MariaDBEncryptionKeys:
278
+ return resources.mariadb_encryption_keys.MariaDBEncryptionKeys(self)
279
+
280
+ @cached_property
281
+ def firewall_rules(self) -> resources.firewall_rules.FirewallRules:
282
+ return resources.firewall_rules.FirewallRules(self)
283
+
284
+ @cached_property
285
+ def hosts_entries(self) -> resources.hosts_entries.HostsEntries:
286
+ return resources.hosts_entries.HostsEntries(self)
287
+
288
+ @cached_property
289
+ def security_txt_policies(
290
+ self,
291
+ ) -> resources.security_txt_policies.SecurityTXTPolicies:
292
+ return resources.security_txt_policies.SecurityTXTPolicies(self)
293
+
294
+ @cached_property
295
+ def firewall_groups(self) -> resources.firewall_groups.FirewallGroups:
296
+ return resources.firewall_groups.FirewallGroups(self)
297
+
298
+ @cached_property
299
+ def custom_config_snippets(
300
+ self,
301
+ ) -> resources.custom_config_snippets.CustomConfigSnippets:
302
+ return resources.custom_config_snippets.CustomConfigSnippets(self)
303
+
304
+ @cached_property
305
+ def custom_configs(self) -> resources.custom_configs.CustomConfigs:
306
+ return resources.custom_configs.CustomConfigs(self)
307
+
308
+ @cached_property
309
+ def ftp_users(self) -> resources.ftp_users.FTPUsers:
310
+ return resources.ftp_users.FTPUsers(self)
311
+
312
+ @cached_property
313
+ def cmses(self) -> resources.cmses.CMSes:
314
+ return resources.cmses.CMSes(self)
315
+
316
+ @cached_property
317
+ def fpm_pools(self) -> resources.fpm_pools.FPMPools:
318
+ return resources.fpm_pools.FPMPools(self)
319
+
320
+ @cached_property
321
+ def passenger_apps(self) -> resources.passenger_apps.PassengerApps:
322
+ return resources.passenger_apps.PassengerApps(self)
323
+
324
+ @cached_property
325
+ def redis_instances(self) -> resources.redis_instances.RedisInstances:
326
+ return resources.redis_instances.RedisInstances(self)
327
+
328
+ @cached_property
329
+ def task_collections(self) -> resources.task_collections.TaskCollections:
330
+ return resources.task_collections.TaskCollections(self)
331
+
332
+ @cached_property
333
+ def nodes(self) -> resources.nodes.Nodes:
334
+ return resources.nodes.Nodes(self)
335
+
336
+ @cached_property
337
+ def unix_users(self) -> resources.unix_users.UNIXUsers:
338
+ return resources.unix_users.UNIXUsers(self)
339
+
340
+ @cached_property
341
+ def logs(self) -> resources.logs.Logs:
342
+ return resources.logs.Logs(self)
343
+
344
+ @cached_property
345
+ def ssh_keys(self) -> resources.ssh_keys.SSHKeys:
346
+ return resources.ssh_keys.SSHKeys(self)
347
+
348
+ @cached_property
349
+ def root_ssh_keys(self) -> resources.root_ssh_keys.RootSSHKeys:
350
+ return resources.root_ssh_keys.RootSSHKeys(self)
351
+
352
+ @cached_property
353
+ def malwares(self) -> resources.malwares.Malwares:
354
+ return resources.malwares.Malwares(self)
355
+
356
+ @cached_property
357
+ def databases(self) -> resources.databases.Databases:
358
+ return resources.databases.Databases(self)
359
+
360
+ @cached_property
361
+ def database_users(self) -> resources.database_users.DatabaseUsers:
362
+ return resources.database_users.DatabaseUsers(self)
363
+
364
+ @cached_property
365
+ def database_user_grants(self) -> resources.database_user_grants.DatabaseUserGrants:
366
+ return resources.database_user_grants.DatabaseUserGrants(self)
367
+
368
+ @cached_property
369
+ def mail_domains(self) -> resources.mail_domains.MailDomains:
370
+ return resources.mail_domains.MailDomains(self)
371
+
372
+ @cached_property
373
+ def mail_accounts(self) -> resources.mail_accounts.MailAccounts:
374
+ return resources.mail_accounts.MailAccounts(self)
375
+
376
+ @cached_property
377
+ def mail_aliases(self) -> resources.mail_aliases.MailAliases:
378
+ return resources.mail_aliases.MailAliases(self)
379
+
380
+ @cached_property
381
+ def health(self) -> resources.health.Health:
382
+ return resources.health.Health(self)
@@ -0,0 +1,13 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class CallException(Exception):
6
+ body: str
7
+ status_code: int
8
+
9
+
10
+ @dataclass
11
+ class AuthenticationException(Exception):
12
+ body: str
13
+ status_code: int
@@ -0,0 +1,21 @@
1
+ import json
2
+ from dataclasses import dataclass
3
+ from http import HTTPStatus
4
+ from typing import Any
5
+
6
+ from requests.structures import CaseInsensitiveDict
7
+
8
+
9
+ @dataclass
10
+ class Response:
11
+ status_code: int
12
+ body: str
13
+ headers: CaseInsensitiveDict
14
+
15
+ @property
16
+ def failed(self) -> bool:
17
+ return self.status_code >= HTTPStatus.BAD_REQUEST
18
+
19
+ @property
20
+ def json(self) -> Any:
21
+ return json.loads(self.body)
@@ -0,0 +1,9 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ if TYPE_CHECKING: # pragma: no cover
4
+ from cyberfusion.CoreApiClient.connector import CoreApiConnector
5
+
6
+
7
+ class Resource:
8
+ def __init__(self, api_connector: "CoreApiConnector") -> None:
9
+ self.api_connector = api_connector