Skip to content

Commit 04f9d69

Browse files
committed
🚨 fix: fix integration tests
1 parent 523c881 commit 04f9d69

File tree

10 files changed

+164
-179
lines changed

10 files changed

+164
-179
lines changed

.github/workflows/Pyinstaller-windows.yml

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,20 @@ jobs:
1111
runs-on: windows-latest
1212
steps:
1313
- uses: actions/checkout@v5
14+
with:
15+
submodules: true
1416

15-
- uses: msys2/setup-msys2@v2
17+
- uses: actions/setup-python@v6
1618
with:
17-
msystem: MINGW64
18-
install: >-
19-
git
20-
base-devel
21-
zip
22-
pacboy:
23-
openssl
24-
python-pip
19+
python-version: '3.13'
2520

26-
- shell: msys2 {0}
21+
- name: build and package
2722
run: |
28-
git submodule update --init
2923
python --version
3024
python -m pip install pyinstaller
3125
python -m pip install .
32-
pyinstaller --distpath ./pkg --clean --name osc-cli osc_sdk/sdk.py --add-data /mingw64/bin/libcrypto-3-x64.dll:. --add-data /mingw64/bin/libssl-3-x64.dll:.
33-
zip -r osc-cli-x86_64.zip pkg/osc-cli
26+
pyinstaller --distpath ./pkg --clean --name osc-cli osc_sdk/sdk.py
27+
28+
- name: smoke test
29+
run: |
3430
./pkg/osc-cli/osc-cli.exe api ReadRegions | grep api.eu-west-2.outscale.com
35-
- name: Upload artifacts
36-
uses: actions/upload-artifact@v5
37-
if: ${{ github.event_name != 'push' }}
38-
with:
39-
name: osc-cli-win
40-
path: |
41-
osc-cli-x86_64.zip
42-
- name: upload nightly
43-
uses: "marvinpinto/action-automatic-releases@latest"
44-
if: ${{ github.event_name == 'push' }}
45-
with:
46-
repo_token: "${{ secrets.GITHUB_TOKEN }}"
47-
prerelease: true
48-
automatic_release_tag: "nightly-windows"
49-
title: "Windows Development Build"
50-
files: |
51-
osc-cli-x86_64.zip

osc_sdk/__init__.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
1-
from .sdk import DirectLinkCall, EimCall, FcuCall, IcuCall, LbuCall, OKMSCall, OSCCall
1+
from .sdk import (
2+
DirectLinkCall,
3+
EimCall,
4+
FcuCall,
5+
IcuCall,
6+
LbuCall,
7+
LegacyProblem,
8+
OKMSCall,
9+
OSCCall,
10+
Problem,
11+
)

osc_sdk/problem.py

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

osc_sdk/sdk.py

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,144 @@
1919
from requests.models import Response
2020
from typing_extensions import TypedDict
2121

22-
from .problem import api_error
22+
23+
class ProblemDecoder(json.JSONDecoder):
24+
def decode(self, s):
25+
data = super().decode(s)
26+
if isinstance(data, dict):
27+
return self._make_problem(data)
28+
return data
29+
30+
def _make_problem(self, data):
31+
type_ = data.pop("type", None)
32+
status = data.pop("status", None)
33+
title = data.pop("title", None)
34+
detail = data.pop("detail", None)
35+
instance = data.pop("instance", None)
36+
return Problem(type_, status, title, detail, instance, **data)
37+
38+
39+
class Problem(Exception):
40+
def __init__(self, type_, status, title, detail, instance, **kwargs):
41+
self._type = type_ or "about:blank"
42+
self.status = status
43+
self.title = title
44+
self.detail = detail
45+
self.instance = instance
46+
self.extras = kwargs
47+
48+
for k in self.extras:
49+
if k in ["type", "status", "title", "detail", "instance"]:
50+
raise ValueError(f"Reserved key '{k}' used in Problem extra arguments.")
51+
52+
def __str__(self):
53+
return self.title
54+
55+
def __repr__(self):
56+
return f"{self.__class__.__name__}<type={self._type}; status={self.status}; title={self.title}>"
57+
58+
def msg(self):
59+
msg = (
60+
f"type = {self._type}, "
61+
f"status = {self.status}, "
62+
f"title = {self.title}, "
63+
f"detail = {self.detail}, "
64+
f"instance = {self.instance}, "
65+
f"extras = {self.extras}"
66+
)
67+
return msg
68+
69+
@property
70+
def type(self):
71+
return self._type
72+
73+
74+
class LegacyProblemDecoder(json.JSONDecoder):
75+
def decode(self, s):
76+
data = super().decode(s)
77+
if isinstance(data, dict):
78+
return self._make_legacy_problem(data)
79+
return data
80+
81+
def _make_legacy_problem(self, data):
82+
request_id = None
83+
error_code = None
84+
code_type = None
85+
86+
if "__type" in data:
87+
error_code = data.get("__type")
88+
else:
89+
request_id = (data.get("ResponseContext") or {}).get("RequestId")
90+
errors = data.get("Errors")
91+
if errors:
92+
error = errors[0]
93+
error_code = error.get("Code")
94+
reason = error.get("Type")
95+
if error.get("Details"):
96+
code_type = reason
97+
else:
98+
code_type = None
99+
return LegacyProblem(None, error_code, code_type, request_id, None)
100+
101+
102+
class LegacyProblem(Exception):
103+
def __init__(self, status, error_code, code_type, request_id, url):
104+
self.status = status
105+
self.error_code = error_code
106+
self.code_type = code_type
107+
self.request_id = request_id
108+
self.url = url
109+
110+
def msg(self):
111+
msg = (
112+
f"status = {self.status}, "
113+
f"code = {self.error_code}, "
114+
f"{'code_type = ' if self.code_type is not None else ''}"
115+
f"{self.code_type + ', ' if self.code_type is not None else ''}"
116+
f"request_id = {self.request_id}, "
117+
f"url = {self.url}"
118+
)
119+
return msg
120+
121+
122+
def api_error(response):
123+
try:
124+
problem = None
125+
ct = response.headers.get("content-type") or ""
126+
if "application/json" in ct:
127+
problem: LegacyProblem = response.json(cls=LegacyProblemDecoder)
128+
problem.status = problem.status or str(response.status_code)
129+
problem.url = response.url
130+
elif "application/problem+json" in ct:
131+
problem: Problem = response.json(cls=ProblemDecoder)
132+
problem.status = problem.status or str(response.status_code)
133+
134+
if problem:
135+
return problem
136+
except json.JSONDecodeError:
137+
# If it is not JSON, pass
138+
pass
139+
140+
try:
141+
error = ET.fromstring(response.text)
142+
143+
err = dict()
144+
for key, attr in [
145+
("Code", "error_code"),
146+
("Message", "status"),
147+
("RequestId", "request_id"),
148+
("RequestID", "request_id"),
149+
]:
150+
value = next((x.text for x in error.iter() if x.tag.endswith(key)), None)
151+
if value:
152+
err[attr] = value
153+
154+
return LegacyProblem(**err)
155+
except:
156+
raise Exception(
157+
f"Could not decode error response from {response.url} with status code {response.status_code}"
158+
)
159+
23160

24161
CANONICAL_URI = "/"
25162
CONFIGURATION_FILE = "config.json"

osc_sdk/test_errors.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
import pytest
55

6-
from . import sdk
7-
from .problem import LegacyProblem
6+
from . import LegacyProblem, sdk
87

98

109
@dataclass

tests/generic_tests/00_one_call_per_service.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ source common_functions.sh
55
# Assuming you are running this from a prepared virtual environment
66
PROJECT_ROOT=$(cd "$(dirname $0)/../.." && pwd)
77
cd $PROJECT_ROOT
8-
c="python osc_sdk/sdk.py"
8+
c="python -m osc_sdk.sdk"
99

1010
echo -n "$(basename $0): "
1111

tests/generic_tests/01_auth_access_key.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ source common_functions.sh
55
# Assuming you are running this from a prepared virtual environment
66
PROJECT_ROOT=$(cd "$(dirname $0)/../.." && pwd)
77
cd $PROJECT_ROOT
8-
c="python osc_sdk/sdk.py"
8+
c="python -m osc_sdk.sdk"
99

1010
echo -n "$(basename $0): "
1111

tests/generic_tests/02_auth_bad.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ source common_functions.sh
55
# Assuming you are running this from a prepared virtual environment
66
PROJECT_ROOT=$(cd "$(dirname $0)/../.." && pwd)
77
cd $PROJECT_ROOT
8-
c="python osc_sdk/sdk.py"
8+
c="python -m osc_sdk.sdk"
99

1010
echo -n "$(basename $0): "
1111

tests/generic_tests/03_auth_password.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ source common_functions.sh
55
# Assuming you are running this from a prepared virtual environment
66
PROJECT_ROOT=$(cd "$(dirname $0)/../.." && pwd)
77
cd $PROJECT_ROOT
8-
c="python osc_sdk/sdk.py"
8+
c="python -m osc_sdk.sdk"
99

1010
echo -n "$(basename $0): "
1111

0 commit comments

Comments
 (0)