Skip to content

Commit 432c0c8

Browse files
TomaAlexandruAlexandru TomaLiviusP
authored
add compat layer over core library (#85)
* Compat Layer * rm unused data * Update README.md * backupunit * private cross connect functionality * s3keeys * disregard warning * add pcc to lan * nodepools update - add parameter lan ids and documentation * nodepools update * set useragent as compat sdk * Create config.yml for issue templates * Created template for bug * Created feature request template * rm print * set version on user agent * fix test shares * add public ips * change package * fix loadbalancer * fix tests * fix tests * change package name of the core to ionoscloud * fix cdrom tests * fix um * pylint code cosmetization * pylint sugestions fix * fix import * update code fot flake8 * pylint code cozmetization * pylint fixes * fix flake standard * refactor k8s tests * k8s nodepools tests refactor * review pull request: ensure transitive dependencies * change package version Co-authored-by: Alexandru Toma <alexandru.toma@ionos.com> Co-authored-by: Livius <plivius@yahoo.com>
1 parent df66b11 commit 432c0c8

71 files changed

Lines changed: 1447 additions & 1093 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: bug
6+
assignees: LiviusP
7+
8+
---
9+
10+
## Descripton
11+
<!-- A clear and concise description of what the bug is. -->
12+
13+
## Expected behavior
14+
<!-- A clear and concise description of what you expected to happen. -->
15+
16+
## Environment
17+
<!-- coud be ansible, python etc. version, depends on concrete sdk/tool -->
18+
hello version: <!-- run `hello --version` and paste the output between the ```marks. -->
19+
```
20+
```
21+
world version: <!-- run `grep version /etc/world.cfg` and paste the output between the ```marks. -->
22+
```
23+
```
24+
OS: <!-- use whatever fits and put it between the ```marks. -->
25+
```
26+
```
27+
28+
## Configuration Files
29+
<!-- could also be environment settings, e.g. LANG=de_DE -->
30+
31+
## How to Reproduce
32+
<!--
33+
Steps to reproduce the behavior:
34+
1. Go to '...'
35+
2. Execute `acme --emca template.xml`
36+
3. ...
37+
Might be omitted if there are no choices, eg. the single command is already in the description
38+
-->
39+
40+
## Error and Debug Output
41+
<!--
42+
Add anything, that could help here.
43+
You can increase the debug level by .. ' hello --whatsover=example`
44+
-->
45+
46+
## Additional Notes
47+
<!--
48+
Add any other content about the problem here.
49+
-->
50+
51+
## References
52+
<!--
53+
Add any other related issues or other links that you think are important for fixing the bug.
54+
-->

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: IONOS Cloud API
4+
url: https://devops.ionos.com/api/
5+
about: View API documentation
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: ''
5+
labels: enhancement
6+
assignees: LiviusP
7+
8+
---
9+
10+
### Current SDK Version
11+
<!---
12+
If you're not using the latest version, please check to see if something related to your request has already been implemented in a later version.
13+
-->
14+
15+
```
16+
...
17+
```
18+
19+
### Use-cases
20+
<!---
21+
In order to properly evaluate a feature request, it is necessary to understand the use-cases for it.
22+
23+
Please describe below the end goal you are trying to achieve that has led you to request this feature.
24+
25+
Please keep this section focused on the problem and not on the suggested solution. We'll get to that in a moment, below!
26+
-->
27+
28+
### Attempted Solutions
29+
<!---
30+
If you've already tried to solve the problem within SDKs existing features and found a limitation that prevented you from succeeding, please describe it below in as much detail as possible.
31+
32+
Ideally, this would include real code snippets that you tried and what results you got in each case.
33+
34+
Please remove any sensitive information such as passwords before sharing configuration snippets and command lines.
35+
--->
36+
37+
### Proposal
38+
<!---
39+
If you have an idea for a way to address the problem, please describe it below.
40+
41+
In this section, it's helpful to include specific examples of how what you are suggesting might look in configuration files, or on the command line, since that allows us to understand the full picture of what you are proposing.
42+
43+
-->
44+
45+
### References
46+
<!--
47+
Are there any other GitHub issues, whether open or closed, that are related to the problem you've described above or to the suggested solution? If so, please create a list below that mentions each of them. For example:
48+
49+
- #6017
50+
51+
-->

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
# Python SDK
33

4-
Version: ionosenterprise-sdk-python **5.4.0**
4+
Version: ionosenterprise-sdk-python **5.5.0**
55

66
## Table of Contents
77

@@ -2379,6 +2379,7 @@ The following table describes the request arguments:
23792379
| annotations | no | dict | Map of annotations attached to node pool |
23802380
| public_ips | no | list | List of IP addresses to be used by nodes |
23812381

2382+
23822383
Method signature:
23832384

23842385
```python
@@ -2492,7 +2493,7 @@ Method signature:
24922493
```python
24932494
def update_k8s_cluster_nodepool(self,
24942495
k8s_cluster_id, nodepool_id, node_count,
2495-
maintenance_window=None, auto_scaling=None):
2496+
maintenance_window=None, auto_scaling=None, lan_ids=None):
24962497
```
24972498

24982499
Update a nodepool:

coreadaptor/AuthAdaptor.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import ionoscloud
2+
3+
class AuthAdaptor:
4+
def __init__(self, username, password):
5+
self.username = username
6+
self.password = password
7+
8+
def get_api_client(self):
9+
return ionoscloud.ApiClient(ionoscloud.Configuration(
10+
username = self.username,
11+
password = self.password
12+
))

coreadaptor/IonosCoreProxy.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
from ionoscloud.exceptions import ApiException, ApiTimeout, ApiFailedRequest
2+
from ionosenterprise.errors import (
3+
ICNotAuthorizedError,
4+
ICNotFoundError,
5+
ICValidationError,
6+
ICRateLimitExceededError,
7+
ICError,
8+
ICFailedRequest,
9+
ICTimeoutError
10+
)
11+
import json
12+
import functools
13+
import re
14+
import inspect
15+
16+
class IonosCoreProxy:
17+
18+
custom_methods = {
19+
'start_server': 'POST-ACTION',
20+
'stop_server': 'POST-ACTION',
21+
'reboot_server': 'POST-ACTION',
22+
'restore_snapshot': 'POST-ACTION',
23+
'create_snapshot': 'POST-ACTION-JSON'
24+
}
25+
26+
@staticmethod
27+
def get_default_args(func):
28+
signature = inspect.signature(func)
29+
return {
30+
k: v.default
31+
for k, v in signature.parameters.items()
32+
if v.default is not inspect.Parameter.empty
33+
}
34+
35+
@staticmethod
36+
def _request_id(headers):
37+
# The request URL has currently the format:
38+
# {host_base}/requests/{request ID}/status
39+
# Thus search for a UUID.
40+
match = re.search('/requests/([-A-Fa-f0-9]+)/', headers['location'])
41+
if match:
42+
return match.group(1)
43+
else:
44+
raise Exception("Failed to extract request ID from response "
45+
"header 'location': '{location}'".format(location=headers['location']))
46+
47+
@staticmethod
48+
def process_response(f):
49+
@functools.wraps(f)
50+
def func(*args, **kwargs):
51+
try:
52+
response = f(*args, **kwargs)
53+
return IonosCoreProxy.handle_response_operations(f, response)
54+
except Exception as e:
55+
raise IonosCoreProxy.cast_exception(e)
56+
return func
57+
58+
@staticmethod
59+
def cast_exceptions(f):
60+
@functools.wraps(f)
61+
def func(*args, **kwargs):
62+
try:
63+
return f(*args, **kwargs)
64+
except Exception as e:
65+
if type(e) == ApiException:
66+
code = e.status
67+
msg = json.loads(e.body)
68+
url = e.url
69+
if code == 401:
70+
raise ICNotAuthorizedError(code, msg, url)
71+
elif code == 404:
72+
raise ICNotFoundError(code, msg, url)
73+
elif code == 422:
74+
raise ICValidationError(code, msg, url)
75+
elif code == 429:
76+
raise ICRateLimitExceededError(code, msg, url)
77+
else:
78+
raise ICError(code, msg, url)
79+
elif type(e) == ApiTimeout:
80+
raise ICTimeoutError(e.message, e.request_id)
81+
elif type(e) == ApiFailedRequest:
82+
raise ICFailedRequest(e.message, e.request_id)
83+
raise e
84+
return func
85+
86+
@staticmethod
87+
def _underscore_to_camelcase(f):
88+
def underscore_to_camelcase(value):
89+
def camelcase():
90+
yield str.lower
91+
while True:
92+
yield str.capitalize
93+
c = camelcase()
94+
return "".join(next(c)(x) if x else '_' for x in value.split("_"))
95+
def myprint(d):
96+
for k in list(d):
97+
v = d[k]
98+
del d[k]
99+
d[underscore_to_camelcase(k)] = v
100+
if isinstance(v, dict):
101+
myprint(v)
102+
103+
104+
@functools.wraps(f)
105+
def func(*args, **kwargs):
106+
x = f(*args, **kwargs)
107+
myprint(x)
108+
return x
109+
return func
110+
111+
@staticmethod
112+
def handle_response_operations(func, response):
113+
return_data = response[0]
114+
status_code = response[1]
115+
response_headers = response[2]
116+
117+
if func.__name__ in IonosCoreProxy.custom_methods and IonosCoreProxy.custom_methods[func.__name__] in ['POST-ACTION-JSON', 'POST-ACTION']:
118+
if status_code == 202 and func.__name__ in IonosCoreProxy.custom_methods and IonosCoreProxy.custom_methods[func.__name__] == 'POST-ACTION':
119+
return True
120+
121+
if 'location' in response_headers:
122+
if return_data == '':
123+
return_data = {}
124+
elif type(return_data) != dict:
125+
return_data = return_data.to_dict()
126+
return_data['requestId'] = IonosCoreProxy._request_id(response_headers)
127+
128+
return return_data
129+
130+
131+
132+
@staticmethod
133+
def cast_exception(e):
134+
if type(e).__name__ == ApiException.__name__:
135+
136+
code = e.status
137+
msg = json.loads(e.body)
138+
url = e.url
139+
140+
if 'messages' in msg:
141+
msg = msg['messages']
142+
143+
if code == 401:
144+
raise ICNotAuthorizedError(code, msg, url)
145+
if code == 404:
146+
raise ICNotFoundError(code, msg, url)
147+
if code == 422:
148+
raise ICValidationError(code, msg, url)
149+
if code == 429:
150+
raise ICRateLimitExceededError(code, msg, url)
151+
else:
152+
raise ICError(code, msg, url)
153+
raise e

coreadaptor/__init__.py

Whitespace-only changes.

examples/k8s.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777

7878
print('Waiting for the datacenter to be active!')
7979
datacenters = client.wait_for(
80-
fn_request=lambda: client.list_datacenters(),
80+
fn_request=client.list_datacenters(),
8181
fn_check=lambda r: list(filter(
8282
lambda e: e['properties']['name'] == datacenter_name,
8383
r['items']
@@ -97,7 +97,7 @@
9797

9898
print('Waiting for the cluster to be active!')
9999
clusters = client.wait_for(
100-
fn_request=lambda: client.list_k8s_clusters(),
100+
fn_request=client.list_k8s_clusters(),
101101
fn_check=lambda r: list(filter(
102102
lambda e: e['properties']['name'] == cluster_name,
103103
r['items']
@@ -162,7 +162,7 @@
162162

163163
print('Waiting for the cluster to be deleted!')
164164
clusters = client.wait_for(
165-
fn_request=lambda: client.list_k8s_clusters(),
165+
fn_request=client.list_k8s_clusters(),
166166
fn_check=lambda r: len(list(filter(
167167
lambda e: e['properties']['name'] == cluster_name,
168168
r['items']
@@ -178,7 +178,7 @@
178178

179179
print('Waiting for the datacenter to be deleted!')
180180
clusters = client.wait_for(
181-
fn_request=lambda: client.list_datacenters(),
181+
fn_request=client.list_datacenters(),
182182
fn_check=lambda r: len(list(filter(
183183
lambda e: e['properties']['name'] == datacenter_name,
184184
r['items']

ionosenterprise/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
"""Ionos Enterprise API Client Library for Python"""
16-
__version__ = '5.4.0'
16+
__version__ = '5.5.0'
1717

1818
API_HOST = 'https://api.ionos.com/cloudapi/v5'
1919
API_VERSION = '5.0'

0 commit comments

Comments
 (0)