Skip to content

Commit 0e48856

Browse files
committed
♻️ chore: refactor profile logic
1 parent 0b939de commit 0e48856

File tree

19 files changed

+26538
-370
lines changed

19 files changed

+26538
-370
lines changed

.github/actions/setup-test/action.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ description: "Setup toolchain and run smoke test"
33
runs:
44
using: composite
55
steps:
6-
- name: ⬇️ Import Outscale API description
7-
run: make init
8-
shell: bash
96
- name: ⬇️ Install uv
107
uses: astral-sh/setup-uv@v6
118
- name: ⬇️ Setup Python

.github/scripts/release-build.sh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ branch_name="autobuild-$new_sdk_version"
2121
git branch -m $branch_name
2222

2323
# Update osc-api version
24-
cd "$root/osc_sdk_python/osc-api"
25-
git reset --hard $osc_api_version
26-
cd ..
27-
git add osc-api
28-
cd "$root"
24+
<<<<<<< Updated upstream
25+
curl -o $root/osc_sdk_python/resources/outscale.yaml "https://raw.githubusercontent.com/outscale/osc-api/refs/tags/$osc_api_version/outscale.yaml"
26+
git add $root/osc_sdk_python/resources/outscale.yaml
27+
=======
28+
curl --retry 10 -o "${root}/osc_sdk_python/resources/outscale.yaml" "https://raw.githubusercontent.com/outscale/osc-api/refs/tags/${osc_api_version}/outscale.yaml"
29+
git add "${root}/osc_sdk_python/resources/outscale.yaml"
30+
>>>>>>> Stashed changes
2931

3032
# Setup new SDK version
3133
for f in "$root/README.md" "$root/osc_sdk_python/VERSION"; do

.github/workflows/setup-test.yml

Whitespace-only changes.

.gitmodules

Lines changed: 0 additions & 3 deletions
This file was deleted.

Makefile

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,17 @@ test-lint:
1919
@uv tool run ruff check
2020

2121
.PHONY: test-int
22-
test-int: init
22+
test-int:
2323
@uv run pytest -s
2424

2525
.PHONY: package
26-
package: init
26+
package:
2727
@uv build
2828

2929
.PHONY: upload-package
3030
upload-package: package
3131
@uv publish --trusted-publishing=always
3232

33-
.PHONY: osc-api-update
34-
osc-api-update:
35-
cd osc_sdk_python/osc-api/; git fetch; git checkout origin/master; cd ..; git add osc-api
36-
37-
.PHONY: init
38-
init: osc_sdk_python/osc-api/outscale.yaml
39-
@echo Initialization: OK
40-
41-
osc_sdk_python/osc-api/outscale.yaml:
42-
git submodule update --init .
43-
4433
.PHONY: clean
4534
clean:
4635
@echo cleaning...

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ Example:
149149
```python
150150
from osc_sdk_python import Gateway
151151
152-
gw = Gateway(email="your@email.com", password="yourAccountPassword")
153-
keys = gw.ReadAccessKeys()
152+
with Gateway(email="your@email.com", password="yourAccountPassword") as gw:
153+
keys = gw.ReadAccessKeys()
154154
```
155155

156156
### Retry Options

docs/examples.md

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ Basic usage with the default profile:
55
```python
66
from osc_sdk_python import Gateway
77

8-
gw = Gateway()
9-
10-
# Example: list VMs
11-
vms = gw.ReadVms()
12-
print(vms)
8+
with Gateway() as gw:
9+
# Example: list VMs
10+
vms = gw.ReadVms()
11+
print(vms)
1312
```
1413

1514
Using a specific profile:
@@ -30,21 +29,20 @@ Example:
3029
```python
3130
from osc_sdk_python import Gateway
3231

33-
gw = Gateway(profile="profile_1")
32+
with Gateway(profile="profile_1") as gw:
33+
# Calls with API action as method
34+
result = gw.ReadSecurityGroups(Filters={"SecurityGroupNames": ["default"]})
35+
result = gw.CreateVms(ImageId="ami-3e158364", VmType="tinav4.c2r4")
3436

35-
# Calls with API action as method
36-
result = gw.ReadSecurityGroups(Filters={"SecurityGroupNames": ["default"]})
37-
result = gw.CreateVms(ImageId="ami-3e158364", VmType="tinav4.c2r4")
38-
39-
# Or raw calls:
40-
result = gw.raw("ReadVms")
41-
result = gw.raw(
42-
"CreateVms",
43-
ImageId="ami-xx",
44-
BlockDeviceMappings=[{"/dev/sda1": {"Size": 10}}],
45-
SecurityGroupIds=["sg-aaa", "sg-bbb"],
46-
Wrong="wrong",
47-
)
37+
# Or raw calls:
38+
result = gw.raw("ReadVms")
39+
result = gw.raw(
40+
"CreateVms",
41+
ImageId="ami-xx",
42+
BlockDeviceMappings=[{"/dev/sda1": {"Size": 10}}],
43+
SecurityGroupIds=["sg-aaa", "sg-bbb"],
44+
Wrong="wrong",
45+
)
4846
```
4947

5048
---
@@ -57,15 +55,14 @@ result = gw.raw(
5755
from osc_sdk_python import Gateway
5856

5957
if __name__ == "__main__":
60-
gw = Gateway()
61-
62-
print("Your virtual machines:")
63-
for vm in gw.ReadVms()["Vms"]:
64-
print(vm["VmId"])
65-
66-
print("\nYour volumes:")
67-
for volume in gw.ReadVolumes()["Volumes"]:
68-
print(volume["VolumeId"])
58+
with Gateway() as gw:
59+
print("Your virtual machines:")
60+
for vm in gw.ReadVms()["Vms"]:
61+
print(vm["VmId"])
62+
63+
print("\nYour volumes:")
64+
for volume in gw.ReadVolumes()["Volumes"]:
65+
print(volume["VolumeId"])
6966
```
7067

7168
### Enabling logs
@@ -74,16 +71,15 @@ if __name__ == "__main__":
7471
from osc_sdk_python import *
7572

7673
if __name__ == "__main__":
77-
gw = Gateway(profile="profile_1")
78-
79-
# 'what' can be LOG_KEEP_ONLY_LAST_REQ or LOG_ALL
80-
# Here we print logs in memory, standard output and standard error
81-
gw.log.config(type=LOG_MEMORY | LOG_STDIO | LOG_STDERR, what=LOG_KEEP_ONLY_LAST_REQ)
74+
with Gateway(profile="profile_1") as gw:
75+
# 'what' can be LOG_KEEP_ONLY_LAST_REQ or LOG_ALL
76+
# Here we print logs in memory, standard output and standard error
77+
gw.log.config(type=LOG_MEMORY | LOG_STDIO | LOG_STDERR, what=LOG_KEEP_ONLY_LAST_REQ)
8278

83-
result = gw.raw("ReadVms")
79+
result = gw.raw("ReadVms")
8480

85-
last_request = gw.log.str()
86-
print(last_request)
81+
last_request = gw.log.str()
82+
print(last_request)
8783
```
8884

89-
Usage examples can be combined with the official [Outscale API documentation](https://docs.outscale.com/en/userguide/Home.html).
85+
Usage examples can be combined with the official [Outscale API documentation](https://docs.outscale.com/en/userguide/Home.html).

osc_sdk_python/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from .outscale_gateway import LOG_STDIO
55
from .outscale_gateway import LOG_MEMORY
66
from .version import get_version
7+
from .problem import Problem, ProblemDecoder
78

89
# what to Log
910
from .outscale_gateway import LOG_ALL
@@ -21,4 +22,6 @@
2122
"LOG_MEMORY",
2223
"LOG_ALL",
2324
"LOG_KEEP_ONLY_LAST_REQ",
25+
"Problem",
26+
"ProblemDecoder"
2427
]

osc_sdk_python/authentication.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ def __init__(self, credentials, host,
2626
self.algorithm = algorithm
2727
self.signed_headers = signed_headers
2828
self.user_agent = user_agent
29-
self.proxy = credentials.proxy
3029
self.x509_client_cert = credentials.x509_client_cert
3130

3231
def forge_headers_signed(self, uri, request_data):

osc_sdk_python/call.py

Lines changed: 54 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
# -*- coding: utf-8 -*-
21
from .authentication import Authentication
32
from .authentication import DEFAULT_USER_AGENT
4-
from .credentials import Credentials
3+
from .credentials import Profile
54
from .requester import Requester
5+
from requests import Session
6+
from requests.adapters import HTTPAdapter
7+
from urllib3.util.retry import Retry
8+
from urllib3.util import parse_url
69

710
import json
8-
import os
9-
11+
import warnings
1012

1113
class Call(object):
1214
def __init__(self, logger=None, limiter=None, **kwargs):
@@ -16,53 +18,47 @@ def __init__(self, logger=None, limiter=None, **kwargs):
1618
self.user_agent = kwargs.pop("user_agent", DEFAULT_USER_AGENT)
1719
self.logger = logger
1820
self.limiter = limiter
19-
self.update_credentials(
21+
self.update_profile(
2022
access_key=kwargs.pop("access_key", None),
2123
secret_key=kwargs.pop("secret_key", None),
2224
region=kwargs.pop("region", None),
2325
profile=kwargs.pop("profile", None),
24-
email=kwargs.pop("email", None),
26+
login=kwargs.pop("login", None),
2527
password=kwargs.pop("password", None),
26-
proxy=kwargs.pop("proxy", None),
2728
x509_client_cert=kwargs.pop("x509_client_cert", None),
28-
max_retries=kwargs.pop("max_retries", None),
29-
retry_backoff_factor=kwargs.pop("retry_backoff_factor", None),
30-
retry_backoff_jitter=kwargs.pop("retry_backoff_jitter", None),
31-
retry_backoff_max=kwargs.pop("retry_backoff_max", None)
3229
)
3330
self.update_limiter(
3431
limiter_max_requests=kwargs.pop("limiter_max_requests", None),
35-
limiter_window=kwargs.pop("limiter_window", None)
32+
limiter_window=kwargs.pop("limiter_window", None),
3633
)
34+
self.session = Session()
35+
self.session.mount("https://", self.adapter)
36+
self.session.mount("http://", self.adapter)
3737

38-
def update_credentials(
39-
self,
40-
region=None,
41-
profile=None,
42-
access_key=None,
43-
secret_key=None,
44-
email=None,
45-
password=None,
46-
proxy=None,
47-
x509_client_cert=None,
48-
max_retries=None,
49-
retry_backoff_factor=None,
50-
retry_backoff_jitter=None,
51-
retry_backoff_max=None,
52-
):
53-
self.credentials = {
54-
"access_key": access_key,
55-
"secret_key": secret_key,
56-
"region": region,
57-
"profile": profile,
58-
"email": email,
59-
"password": password,
60-
"x509_client_cert": x509_client_cert,
61-
"max_retries": max_retries,
62-
"retry_backoff_factor": retry_backoff_factor,
63-
"retry_backoff_jitter": retry_backoff_jitter,
64-
"retry_backoff_max": retry_backoff_max,
65-
}
38+
def update_credentials(self, **kwargs):
39+
warnings.warn(
40+
"update_credentials is deprecated, use update_profile instead",
41+
DeprecationWarning,
42+
stacklevel=2,
43+
)
44+
self.update_profile(**kwargs)
45+
46+
def update_profile(self, **kwargs):
47+
self.profile = Profile.from_standard_configuration(
48+
kwargs.pop("path", None), kwargs.pop("profile", None)
49+
)
50+
self.profile.merge(Profile(**kwargs))
51+
52+
self.adapter = HTTPAdapter(
53+
max_retries=Retry(
54+
total=3,
55+
backoff_factor=1,
56+
backoff_jitter=3,
57+
backoff_max=30,
58+
status_forcelist=(400, 429, 500, 503),
59+
allowed_methods=("POST", "GET"),
60+
)
61+
)
6662

6763
def update_limiter(
6864
self,
@@ -75,36 +71,27 @@ def update_limiter(
7571
if limiter_max_requests is not None:
7672
self.limiter.max_requests = limiter_max_requests
7773

78-
79-
def api(self, action, **data):
74+
def api(self, action, service="api", **data):
8075
try:
81-
credentials = Credentials(**self.credentials)
82-
host = (
83-
self.host
84-
if self.host
85-
else "api.{}.outscale.{}".format(
86-
credentials.region, credentials.get_url_extension()
87-
)
88-
)
89-
uri = "/api/{}/{}".format(self.version, action)
90-
protocol = "https" if self.ssl else "http"
91-
92-
endpoint = os.environ.get("OSC_ENDPOINT_API")
93-
if endpoint is None:
94-
endpoint = "{}://{}{}".format(protocol, host, uri)
95-
else:
96-
endpoint = "{}{}".format(endpoint, uri)
76+
endpoint = self.profile.get_endpoint(service) + "/" + action
77+
parsed_url = parse_url(endpoint)
78+
uri = parsed_url.path
79+
host = parsed_url.host
80+
print("endpoint :", endpoint)
81+
print("uri: ", uri)
82+
print("host: ", host)
9783

9884
if self.limiter is not None:
9985
self.limiter.acquire()
10086

10187
requester = Requester(
102-
Authentication(credentials, host, user_agent=self.user_agent),
88+
self.session,
89+
Authentication(
90+
self.profile,
91+
host,
92+
user_agent=self.user_agent,
93+
),
10394
endpoint,
104-
credentials.max_retries,
105-
credentials.retry_backoff_factor,
106-
credentials.retry_backoff_jitter,
107-
credentials.retry_backoff_max,
10895
)
10996
if self.logger is not None:
11097
self.logger.do_log(
@@ -113,3 +100,7 @@ def api(self, action, **data):
113100
return requester.send(uri, json.dumps(data))
114101
except Exception as err:
115102
raise err
103+
104+
def close(self):
105+
if self.session:
106+
self.session.close()

0 commit comments

Comments
 (0)