ibm-cloud-sdk-core 3.16.0__py3-none-any.whl → 3.20.6__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.
- ibm_cloud_sdk_core/__init__.py +1 -0
- ibm_cloud_sdk_core/api_exception.py +18 -4
- ibm_cloud_sdk_core/authenticators/__init__.py +1 -0
- ibm_cloud_sdk_core/authenticators/authenticator.py +2 -1
- ibm_cloud_sdk_core/authenticators/basic_authenticator.py +5 -6
- ibm_cloud_sdk_core/authenticators/bearer_token_authenticator.py +1 -1
- ibm_cloud_sdk_core/authenticators/container_authenticator.py +25 -16
- ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py +33 -21
- ibm_cloud_sdk_core/authenticators/iam_authenticator.py +22 -13
- ibm_cloud_sdk_core/authenticators/iam_request_based_authenticator.py +5 -7
- ibm_cloud_sdk_core/authenticators/mcsp_authenticator.py +130 -0
- ibm_cloud_sdk_core/authenticators/vpc_instance_authenticator.py +7 -10
- ibm_cloud_sdk_core/base_service.py +107 -91
- ibm_cloud_sdk_core/detailed_response.py +21 -15
- ibm_cloud_sdk_core/get_authenticator.py +28 -16
- ibm_cloud_sdk_core/http_adapter.py +28 -0
- ibm_cloud_sdk_core/private_helpers.py +34 -0
- ibm_cloud_sdk_core/token_managers/container_token_manager.py +61 -30
- ibm_cloud_sdk_core/token_managers/cp4d_token_manager.py +30 -22
- ibm_cloud_sdk_core/token_managers/iam_request_based_token_manager.py +43 -20
- ibm_cloud_sdk_core/token_managers/iam_token_manager.py +24 -13
- ibm_cloud_sdk_core/token_managers/jwt_token_manager.py +3 -16
- ibm_cloud_sdk_core/token_managers/mcsp_token_manager.py +102 -0
- ibm_cloud_sdk_core/token_managers/token_manager.py +13 -23
- ibm_cloud_sdk_core/token_managers/vpc_instance_token_manager.py +33 -13
- ibm_cloud_sdk_core/utils.py +121 -46
- ibm_cloud_sdk_core/version.py +1 -1
- {ibm_cloud_sdk_core-3.16.0.dist-info → ibm_cloud_sdk_core-3.20.6.dist-info}/METADATA +40 -28
- ibm_cloud_sdk_core-3.20.6.dist-info/RECORD +34 -0
- {ibm_cloud_sdk_core-3.16.0.dist-info → ibm_cloud_sdk_core-3.20.6.dist-info}/WHEEL +1 -1
- ibm_cloud_sdk_core-3.20.6.dist-info/top_level.txt +1 -0
- ibm_cloud_sdk_core-3.16.0.dist-info/RECORD +0 -52
- ibm_cloud_sdk_core-3.16.0.dist-info/top_level.txt +0 -3
- ibm_cloud_sdk_core-3.16.0.dist-info/zip-safe +0 -1
- test/__init__.py +0 -0
- test/test_api_exception.py +0 -73
- test/test_authenticator.py +0 -21
- test/test_base_service.py +0 -933
- test/test_basic_authenticator.py +0 -36
- test/test_bearer_authenticator.py +0 -28
- test/test_container_authenticator.py +0 -105
- test/test_container_token_manager.py +0 -283
- test/test_cp4d_authenticator.py +0 -171
- test/test_cp4d_token_manager.py +0 -56
- test/test_detailed_response.py +0 -57
- test/test_iam_authenticator.py +0 -157
- test/test_iam_token_manager.py +0 -362
- test/test_jwt_token_manager.py +0 -109
- test/test_no_auth_authenticator.py +0 -15
- test/test_token_manager.py +0 -84
- test/test_utils.py +0 -634
- test/test_vpc_instance_authenticator.py +0 -66
- test/test_vpc_instance_token_manager.py +0 -266
- test_integration/__init__.py +0 -0
- test_integration/test_cp4d_authenticator_integration.py +0 -45
- {ibm_cloud_sdk_core-3.16.0.dist-info → ibm_cloud_sdk_core-3.20.6.dist-info}/LICENSE +0 -0
test/test_base_service.py
DELETED
|
@@ -1,933 +0,0 @@
|
|
|
1
|
-
# coding=utf-8
|
|
2
|
-
# pylint: disable=missing-docstring,protected-access,too-few-public-methods
|
|
3
|
-
import gzip
|
|
4
|
-
import json
|
|
5
|
-
import os
|
|
6
|
-
import ssl
|
|
7
|
-
import tempfile
|
|
8
|
-
import time
|
|
9
|
-
from shutil import copyfile
|
|
10
|
-
from typing import Optional
|
|
11
|
-
from urllib3.exceptions import ConnectTimeoutError, MaxRetryError
|
|
12
|
-
|
|
13
|
-
import jwt
|
|
14
|
-
import pytest
|
|
15
|
-
import responses
|
|
16
|
-
import requests
|
|
17
|
-
|
|
18
|
-
from ibm_cloud_sdk_core import ApiException
|
|
19
|
-
from ibm_cloud_sdk_core import BaseService, DetailedResponse
|
|
20
|
-
from ibm_cloud_sdk_core import CP4DTokenManager
|
|
21
|
-
from ibm_cloud_sdk_core import get_authenticator_from_environment
|
|
22
|
-
from ibm_cloud_sdk_core.authenticators import (IAMAuthenticator, NoAuthAuthenticator, Authenticator,
|
|
23
|
-
BasicAuthenticator, CloudPakForDataAuthenticator)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class IncludeExternalConfigService(BaseService):
|
|
27
|
-
default_service_url = 'https://servicesthatincludeexternalconfig.com/api'
|
|
28
|
-
|
|
29
|
-
def __init__(
|
|
30
|
-
self,
|
|
31
|
-
api_version: str,
|
|
32
|
-
authenticator: Optional[Authenticator] = None,
|
|
33
|
-
trace_id: Optional[str] = None
|
|
34
|
-
) -> None:
|
|
35
|
-
BaseService.__init__(
|
|
36
|
-
self,
|
|
37
|
-
service_url=self.default_service_url,
|
|
38
|
-
authenticator=authenticator,
|
|
39
|
-
disable_ssl_verification=False
|
|
40
|
-
)
|
|
41
|
-
self.api_version = api_version
|
|
42
|
-
self.trace_id = trace_id
|
|
43
|
-
self.configure_service('include-external-config')
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class AnyServiceV1(BaseService):
|
|
47
|
-
default_url = 'https://gateway.watsonplatform.net/test/api'
|
|
48
|
-
|
|
49
|
-
def __init__(
|
|
50
|
-
self,
|
|
51
|
-
version: str,
|
|
52
|
-
service_url: str = default_url,
|
|
53
|
-
authenticator: Optional[Authenticator] = None,
|
|
54
|
-
disable_ssl_verification: bool = False
|
|
55
|
-
) -> None:
|
|
56
|
-
BaseService.__init__(
|
|
57
|
-
self,
|
|
58
|
-
service_url=service_url,
|
|
59
|
-
authenticator=authenticator,
|
|
60
|
-
disable_ssl_verification=disable_ssl_verification)
|
|
61
|
-
self.version = version
|
|
62
|
-
|
|
63
|
-
def op_with_path_params(self, path0: str, path1: str) -> DetailedResponse:
|
|
64
|
-
if path0 is None:
|
|
65
|
-
raise ValueError('path0 must be provided')
|
|
66
|
-
if path1 is None:
|
|
67
|
-
raise ValueError('path1 must be provided')
|
|
68
|
-
params = {'version': self.version}
|
|
69
|
-
url = '/v1/foo/{0}/bar/{1}/baz'.format(
|
|
70
|
-
*self._encode_path_vars(path0, path1))
|
|
71
|
-
request = self.prepare_request(method='GET', url=url, params=params)
|
|
72
|
-
response = self.send(request)
|
|
73
|
-
return response
|
|
74
|
-
|
|
75
|
-
def with_http_config(self, http_config: dict) -> DetailedResponse:
|
|
76
|
-
self.set_http_config(http_config)
|
|
77
|
-
request = self.prepare_request(method='GET', url='')
|
|
78
|
-
response = self.send(request)
|
|
79
|
-
return response
|
|
80
|
-
|
|
81
|
-
def any_service_call(self) -> DetailedResponse:
|
|
82
|
-
request = self.prepare_request(method='GET', url='')
|
|
83
|
-
response = self.send(request)
|
|
84
|
-
return response
|
|
85
|
-
|
|
86
|
-
def head_request(self) -> DetailedResponse:
|
|
87
|
-
request = self.prepare_request(method='HEAD', url='')
|
|
88
|
-
response = self.send(request)
|
|
89
|
-
return response
|
|
90
|
-
|
|
91
|
-
def get_document_as_stream(self) -> DetailedResponse:
|
|
92
|
-
params = {'version': self.version}
|
|
93
|
-
url = '/v1/streamjson'
|
|
94
|
-
request = self.prepare_request(method='GET', url=url, params=params)
|
|
95
|
-
response = self.send(request, stream=True)
|
|
96
|
-
return response
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def get_access_token() -> str:
|
|
100
|
-
access_token_layout = {
|
|
101
|
-
"username": "dummy",
|
|
102
|
-
"role": "Admin",
|
|
103
|
-
"permissions": ["administrator", "manage_catalog"],
|
|
104
|
-
"sub": "admin",
|
|
105
|
-
"iss": "sss",
|
|
106
|
-
"aud": "sss",
|
|
107
|
-
"uid": "sss",
|
|
108
|
-
"iat": 3600,
|
|
109
|
-
"exp": int(time.time())
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
access_token = jwt.encode(
|
|
113
|
-
access_token_layout,
|
|
114
|
-
'secret',
|
|
115
|
-
algorithm='HS256',
|
|
116
|
-
headers={
|
|
117
|
-
'kid': '230498151c214b788dd97f22b85410a5'
|
|
118
|
-
})
|
|
119
|
-
return access_token
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def test_invalid_authenticator():
|
|
123
|
-
with pytest.raises(ValueError) as err:
|
|
124
|
-
AnyServiceV1('2021-08-18')
|
|
125
|
-
|
|
126
|
-
assert str(err.value) == 'authenticator must be provided'
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
@responses.activate
|
|
130
|
-
def test_url_encoding():
|
|
131
|
-
service = AnyServiceV1('2017-07-07', authenticator=NoAuthAuthenticator())
|
|
132
|
-
|
|
133
|
-
# All characters in path0 _must_ be encoded in path segments
|
|
134
|
-
path0 = ' \"<>^`{}|/\\?#%[]'
|
|
135
|
-
path0_encoded = '%20%22%3C%3E%5E%60%7B%7D%7C%2F%5C%3F%23%25%5B%5D'
|
|
136
|
-
# All non-ASCII chars _must_ be encoded in path segments
|
|
137
|
-
path1 = '比萨浇头'.encode('utf8') # "pizza toppings"
|
|
138
|
-
path1_encoded = '%E6%AF%94%E8%90%A8%E6%B5%87%E5%A4%B4'
|
|
139
|
-
|
|
140
|
-
path_encoded = '/v1/foo/' + path0_encoded + '/bar/' + path1_encoded + '/baz'
|
|
141
|
-
test_url = service.default_url + path_encoded
|
|
142
|
-
|
|
143
|
-
responses.add(
|
|
144
|
-
responses.GET,
|
|
145
|
-
test_url,
|
|
146
|
-
status=200,
|
|
147
|
-
body=json.dumps({
|
|
148
|
-
"foobar": "baz"
|
|
149
|
-
}),
|
|
150
|
-
content_type='application/json')
|
|
151
|
-
|
|
152
|
-
# Set Host as a default header on the service.
|
|
153
|
-
service.set_default_headers({'Host': 'alternatehost.ibm.com:443'})
|
|
154
|
-
|
|
155
|
-
response = service.op_with_path_params(path0, path1)
|
|
156
|
-
|
|
157
|
-
assert response is not None
|
|
158
|
-
assert len(responses.calls) == 1
|
|
159
|
-
assert path_encoded in responses.calls[0].request.url
|
|
160
|
-
assert 'version=2017-07-07' in responses.calls[0].request.url
|
|
161
|
-
|
|
162
|
-
# Verify that the Host header was set in the request.
|
|
163
|
-
assert responses.calls[0].request.headers.get(
|
|
164
|
-
'Host') == 'alternatehost.ibm.com:443'
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
@responses.activate
|
|
168
|
-
def test_stream_json_response():
|
|
169
|
-
service = AnyServiceV1('2017-07-07', authenticator=NoAuthAuthenticator())
|
|
170
|
-
|
|
171
|
-
path = '/v1/streamjson'
|
|
172
|
-
test_url = service.default_url + path
|
|
173
|
-
|
|
174
|
-
expected_response = json.dumps(
|
|
175
|
-
{"id": 1, "rev": "v1", "content": "this is a document"})
|
|
176
|
-
|
|
177
|
-
# print("Expected response: ", expected_response)
|
|
178
|
-
|
|
179
|
-
# Simulate a JSON response
|
|
180
|
-
responses.add(
|
|
181
|
-
responses.GET,
|
|
182
|
-
test_url,
|
|
183
|
-
status=200,
|
|
184
|
-
body=expected_response,
|
|
185
|
-
content_type='application/json')
|
|
186
|
-
|
|
187
|
-
# Invoke the operation and receive an "iterable" as the response
|
|
188
|
-
response = service.get_document_as_stream()
|
|
189
|
-
|
|
190
|
-
assert response is not None
|
|
191
|
-
assert len(responses.calls) == 1
|
|
192
|
-
|
|
193
|
-
# retrieve the requests.Response object from the DetailedResponse
|
|
194
|
-
resp = response.get_result()
|
|
195
|
-
assert isinstance(resp, requests.Response)
|
|
196
|
-
assert hasattr(resp, "iter_content")
|
|
197
|
-
|
|
198
|
-
# Retrieve the response body, one chunk at a time.
|
|
199
|
-
actual_response = ''
|
|
200
|
-
for chunk in resp.iter_content(chunk_size=3):
|
|
201
|
-
actual_response += chunk.decode("utf-8")
|
|
202
|
-
|
|
203
|
-
# print("Actual response: ", actual_response)
|
|
204
|
-
assert actual_response == expected_response
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
@responses.activate
|
|
208
|
-
def test_http_config():
|
|
209
|
-
service = AnyServiceV1('2017-07-07', authenticator=NoAuthAuthenticator())
|
|
210
|
-
responses.add(
|
|
211
|
-
responses.GET,
|
|
212
|
-
service.default_url,
|
|
213
|
-
status=200,
|
|
214
|
-
body=json.dumps({
|
|
215
|
-
"foobar": "baz"
|
|
216
|
-
}),
|
|
217
|
-
content_type='application/json')
|
|
218
|
-
|
|
219
|
-
response = service.with_http_config({'timeout': 100})
|
|
220
|
-
assert response is not None
|
|
221
|
-
assert len(responses.calls) == 1
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
def test_fail_http_config():
|
|
225
|
-
service = AnyServiceV1('2017-07-07', authenticator=NoAuthAuthenticator())
|
|
226
|
-
with pytest.raises(TypeError):
|
|
227
|
-
service.with_http_config(None)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
@responses.activate
|
|
231
|
-
def test_cwd():
|
|
232
|
-
file_path = os.path.join(
|
|
233
|
-
os.path.dirname(__file__), '../resources/ibm-credentials.env')
|
|
234
|
-
# Try changing working directories to test getting creds from cwd
|
|
235
|
-
cwd = os.getcwd()
|
|
236
|
-
os.chdir(os.path.dirname(file_path))
|
|
237
|
-
iam_authenticator = get_authenticator_from_environment('ibm_watson')
|
|
238
|
-
service = AnyServiceV1('2017-07-07', authenticator=iam_authenticator)
|
|
239
|
-
service.configure_service('ibm_watson')
|
|
240
|
-
os.chdir(cwd)
|
|
241
|
-
assert service.service_url == 'https://cwdserviceurl'
|
|
242
|
-
assert service.authenticator is not None
|
|
243
|
-
|
|
244
|
-
# Copy credentials file to cwd to test loading from current working directory
|
|
245
|
-
temp_env_path = os.getcwd() + '/ibm-credentials.env'
|
|
246
|
-
copyfile(file_path, temp_env_path)
|
|
247
|
-
iam_authenticator = get_authenticator_from_environment('ibm_watson')
|
|
248
|
-
service = AnyServiceV1('2017-07-07', authenticator=iam_authenticator)
|
|
249
|
-
service.configure_service('ibm_watson')
|
|
250
|
-
os.remove(temp_env_path)
|
|
251
|
-
assert service.service_url == 'https://cwdserviceurl'
|
|
252
|
-
assert service.authenticator is not None
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
@responses.activate
|
|
256
|
-
def test_iam():
|
|
257
|
-
file_path = os.path.join(
|
|
258
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-iam.env')
|
|
259
|
-
os.environ['IBM_CREDENTIALS_FILE'] = file_path
|
|
260
|
-
iam_authenticator = get_authenticator_from_environment('ibm-watson')
|
|
261
|
-
service = AnyServiceV1('2017-07-07', authenticator=iam_authenticator)
|
|
262
|
-
assert service.service_url == 'https://gateway.watsonplatform.net/test/api'
|
|
263
|
-
del os.environ['IBM_CREDENTIALS_FILE']
|
|
264
|
-
assert service.authenticator is not None
|
|
265
|
-
|
|
266
|
-
response = {
|
|
267
|
-
"access_token": get_access_token(),
|
|
268
|
-
"token_type": "Bearer",
|
|
269
|
-
"expires_in": 3600,
|
|
270
|
-
"expiration": int(time.time()),
|
|
271
|
-
"refresh_token": "jy4gl91BQ"
|
|
272
|
-
}
|
|
273
|
-
responses.add(
|
|
274
|
-
responses.POST,
|
|
275
|
-
url='https://iam.cloud.ibm.com/identity/token',
|
|
276
|
-
body=json.dumps(response),
|
|
277
|
-
status=200)
|
|
278
|
-
responses.add(
|
|
279
|
-
responses.GET,
|
|
280
|
-
url='https://gateway.watsonplatform.net/test/api',
|
|
281
|
-
body=json.dumps({
|
|
282
|
-
"foobar": "baz"
|
|
283
|
-
}),
|
|
284
|
-
content_type='application/json')
|
|
285
|
-
service.any_service_call()
|
|
286
|
-
assert "grant-type%3Aapikey" in responses.calls[0].request.body
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
def test_no_auth():
|
|
290
|
-
class MadeUp:
|
|
291
|
-
def __init__(self):
|
|
292
|
-
self.lazy = 'made up'
|
|
293
|
-
|
|
294
|
-
with pytest.raises(ValueError) as err:
|
|
295
|
-
service = AnyServiceV1('2017-07-07', authenticator=MadeUp())
|
|
296
|
-
service.prepare_request(
|
|
297
|
-
responses.GET,
|
|
298
|
-
url='https://gateway.watsonplatform.net/test/api',
|
|
299
|
-
)
|
|
300
|
-
assert str(err.value) == 'authenticator should be of type Authenticator'
|
|
301
|
-
|
|
302
|
-
service = AnyServiceV1('2017-07-07', authenticator=NoAuthAuthenticator())
|
|
303
|
-
service.prepare_request(
|
|
304
|
-
responses.GET,
|
|
305
|
-
url='https://gateway.watsonplatform.net/test/api',
|
|
306
|
-
)
|
|
307
|
-
assert service.authenticator is not None
|
|
308
|
-
assert isinstance(service.authenticator, Authenticator)
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
def test_for_cp4d():
|
|
312
|
-
cp4d_authenticator = CloudPakForDataAuthenticator('my_username', 'my_password',
|
|
313
|
-
'my_url')
|
|
314
|
-
service = AnyServiceV1('2017-07-07', authenticator=cp4d_authenticator)
|
|
315
|
-
assert service.authenticator.token_manager is not None
|
|
316
|
-
assert service.authenticator.token_manager.username == 'my_username'
|
|
317
|
-
assert service.authenticator.token_manager.password == 'my_password'
|
|
318
|
-
assert service.authenticator.token_manager.url == 'my_url/v1/authorize'
|
|
319
|
-
assert isinstance(service.authenticator.token_manager, CP4DTokenManager)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
def test_disable_ssl_verification():
|
|
323
|
-
service1 = AnyServiceV1(
|
|
324
|
-
'2017-07-07', authenticator=NoAuthAuthenticator(), disable_ssl_verification=True)
|
|
325
|
-
assert service1.disable_ssl_verification is True
|
|
326
|
-
|
|
327
|
-
service1.set_disable_ssl_verification(False)
|
|
328
|
-
assert service1.disable_ssl_verification is False
|
|
329
|
-
|
|
330
|
-
cp4d_authenticator = CloudPakForDataAuthenticator('my_username', 'my_password',
|
|
331
|
-
'my_url')
|
|
332
|
-
service2 = AnyServiceV1('2017-07-07', authenticator=cp4d_authenticator)
|
|
333
|
-
assert service2.disable_ssl_verification is False
|
|
334
|
-
cp4d_authenticator.set_disable_ssl_verification(True)
|
|
335
|
-
assert service2.authenticator.token_manager.disable_ssl_verification is True
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
@responses.activate
|
|
339
|
-
def test_http_head():
|
|
340
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
341
|
-
expected_headers = {'Test-Header1': 'value1', 'Test-Header2': 'value2'}
|
|
342
|
-
responses.add(
|
|
343
|
-
responses.HEAD,
|
|
344
|
-
service.default_url,
|
|
345
|
-
status=200,
|
|
346
|
-
headers=expected_headers,
|
|
347
|
-
content_type=None)
|
|
348
|
-
|
|
349
|
-
response = service.head_request()
|
|
350
|
-
assert response is not None
|
|
351
|
-
assert len(responses.calls) == 1
|
|
352
|
-
assert response.headers is not None
|
|
353
|
-
assert response.headers == expected_headers
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
@responses.activate
|
|
357
|
-
def test_response_with_no_body():
|
|
358
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
359
|
-
responses.add(responses.GET, service.default_url, status=200, body=None)
|
|
360
|
-
|
|
361
|
-
response = service.any_service_call()
|
|
362
|
-
assert response is not None
|
|
363
|
-
assert len(responses.calls) == 1
|
|
364
|
-
assert response.get_result() is None
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
def test_has_bad_first_or_last_char():
|
|
368
|
-
with pytest.raises(ValueError) as err:
|
|
369
|
-
basic_authenticator = BasicAuthenticator(
|
|
370
|
-
'{my_username}', 'my_password')
|
|
371
|
-
AnyServiceV1('2018-11-20', authenticator=basic_authenticator).prepare_request(
|
|
372
|
-
responses.GET,
|
|
373
|
-
'https://gateway.watsonplatform.net/test/api'
|
|
374
|
-
)
|
|
375
|
-
assert str(
|
|
376
|
-
err.value
|
|
377
|
-
) == 'The username and password shouldn\'t start or end with curly brackets or quotes. '\
|
|
378
|
-
'Please remove any surrounding {, }, or \" characters.'
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
@responses.activate
|
|
382
|
-
def test_request_server_error():
|
|
383
|
-
responses.add(
|
|
384
|
-
responses.GET,
|
|
385
|
-
'https://gateway.watsonplatform.net/test/api',
|
|
386
|
-
status=500,
|
|
387
|
-
body=json.dumps({
|
|
388
|
-
'error': 'internal server error'
|
|
389
|
-
}),
|
|
390
|
-
content_type='application/json')
|
|
391
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
392
|
-
try:
|
|
393
|
-
prepped = service.prepare_request('GET', url='')
|
|
394
|
-
service.send(prepped)
|
|
395
|
-
except ApiException as err:
|
|
396
|
-
assert err.message == 'internal server error'
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
@responses.activate
|
|
400
|
-
def test_request_success_json():
|
|
401
|
-
responses.add(
|
|
402
|
-
responses.GET,
|
|
403
|
-
'https://gateway.watsonplatform.net/test/api',
|
|
404
|
-
status=200,
|
|
405
|
-
body=json.dumps({
|
|
406
|
-
'foo': 'bar'
|
|
407
|
-
}),
|
|
408
|
-
content_type='application/json')
|
|
409
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
410
|
-
prepped = service.prepare_request('GET', url='')
|
|
411
|
-
detailed_response = service.send(prepped)
|
|
412
|
-
assert detailed_response.get_result() == {'foo': 'bar'}
|
|
413
|
-
|
|
414
|
-
service = AnyServiceV1(
|
|
415
|
-
'2018-11-20', authenticator=BasicAuthenticator('my_username', 'my_password'))
|
|
416
|
-
service.set_default_headers({'test': 'header'})
|
|
417
|
-
service.set_disable_ssl_verification(True)
|
|
418
|
-
prepped = service.prepare_request('GET', url='')
|
|
419
|
-
detailed_response = service.send(prepped)
|
|
420
|
-
assert detailed_response.get_result() == {'foo': 'bar'}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
@responses.activate
|
|
424
|
-
def test_request_success_response():
|
|
425
|
-
responses.add(
|
|
426
|
-
responses.GET,
|
|
427
|
-
'https://gateway.watsonplatform.net/test/api',
|
|
428
|
-
status=200,
|
|
429
|
-
body=json.dumps({
|
|
430
|
-
'foo': 'bar'
|
|
431
|
-
}),
|
|
432
|
-
content_type='application/json')
|
|
433
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
434
|
-
prepped = service.prepare_request('GET', url='')
|
|
435
|
-
detailed_response = service.send(prepped)
|
|
436
|
-
assert detailed_response.get_result() == {"foo": "bar"}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
@responses.activate
|
|
440
|
-
def test_request_fail_401():
|
|
441
|
-
responses.add(
|
|
442
|
-
responses.GET,
|
|
443
|
-
'https://gateway.watsonplatform.net/test/api',
|
|
444
|
-
status=401,
|
|
445
|
-
body=json.dumps({
|
|
446
|
-
'foo': 'bar'
|
|
447
|
-
}),
|
|
448
|
-
content_type='application/json')
|
|
449
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
450
|
-
try:
|
|
451
|
-
prepped = service.prepare_request('GET', url='')
|
|
452
|
-
service.send(prepped)
|
|
453
|
-
except ApiException as err:
|
|
454
|
-
assert err.message == 'Unauthorized: Access is denied due to invalid credentials'
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
def test_misc_methods():
|
|
458
|
-
|
|
459
|
-
class MockModel:
|
|
460
|
-
|
|
461
|
-
def __init__(self, xyz=None):
|
|
462
|
-
self.xyz = xyz
|
|
463
|
-
|
|
464
|
-
def _to_dict(self):
|
|
465
|
-
_dict = {}
|
|
466
|
-
if hasattr(self, 'xyz') and self.xyz is not None:
|
|
467
|
-
_dict['xyz'] = self.xyz
|
|
468
|
-
return _dict
|
|
469
|
-
|
|
470
|
-
@classmethod
|
|
471
|
-
def _from_dict(cls, _dict):
|
|
472
|
-
args = {}
|
|
473
|
-
if 'xyz' in _dict:
|
|
474
|
-
args['xyz'] = _dict.get('xyz')
|
|
475
|
-
return cls(**args)
|
|
476
|
-
|
|
477
|
-
mock = MockModel('foo')
|
|
478
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
479
|
-
model1 = service._convert_model(mock)
|
|
480
|
-
assert model1 == {'xyz': 'foo'}
|
|
481
|
-
|
|
482
|
-
model2 = service._convert_model("{\"xyz\": \"foo\"}")
|
|
483
|
-
assert model2 is not None
|
|
484
|
-
assert model2['xyz'] == 'foo'
|
|
485
|
-
|
|
486
|
-
temp = ['default', '123']
|
|
487
|
-
res_str = service._convert_list(temp)
|
|
488
|
-
assert res_str == 'default,123'
|
|
489
|
-
|
|
490
|
-
temp2 = 'default123'
|
|
491
|
-
res_str2 = service._convert_list(temp2)
|
|
492
|
-
assert res_str2 == temp2
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
def test_default_headers():
|
|
496
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
497
|
-
service.set_default_headers({'xxx': 'yyy'})
|
|
498
|
-
assert service.default_headers == {'xxx': 'yyy'}
|
|
499
|
-
with pytest.raises(TypeError):
|
|
500
|
-
service.set_default_headers('xxx')
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
def test_set_service_url():
|
|
504
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
505
|
-
with pytest.raises(ValueError) as err:
|
|
506
|
-
service.set_service_url('{url}')
|
|
507
|
-
assert str(err.value) == 'The service url shouldn\'t start or end with curly brackets or quotes. '\
|
|
508
|
-
'Be sure to remove any {} and \" characters surrounding your service url'
|
|
509
|
-
|
|
510
|
-
service.set_service_url('my_url')
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
def test_http_client():
|
|
514
|
-
auth = BasicAuthenticator('my_username', 'my_password')
|
|
515
|
-
service = AnyServiceV1('2018-11-20', authenticator=auth)
|
|
516
|
-
assert isinstance(service.get_http_client(), requests.sessions.Session)
|
|
517
|
-
assert service.get_http_client().headers.get(
|
|
518
|
-
'Accept-Encoding') == 'gzip, deflate'
|
|
519
|
-
|
|
520
|
-
new_http_client = requests.Session()
|
|
521
|
-
new_http_client.headers.update({'Accept-Encoding': 'gzip'})
|
|
522
|
-
service.set_http_client(http_client=new_http_client)
|
|
523
|
-
assert service.get_http_client().headers.get('Accept-Encoding') == 'gzip'
|
|
524
|
-
|
|
525
|
-
with pytest.raises(TypeError):
|
|
526
|
-
service.set_http_client("bad_argument_type")
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
def test_get_authenticator():
|
|
530
|
-
auth = BasicAuthenticator('my_username', 'my_password')
|
|
531
|
-
service = AnyServiceV1('2018-11-20', authenticator=auth)
|
|
532
|
-
assert service.get_authenticator() is not None
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
def test_gzip_compression():
|
|
536
|
-
# Should return uncompressed data when gzip is off
|
|
537
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
538
|
-
assert not service.get_enable_gzip_compression()
|
|
539
|
-
prepped = service.prepare_request(
|
|
540
|
-
'GET', url='', data=json.dumps({"foo": "bar"}))
|
|
541
|
-
assert prepped['data'] == b'{"foo": "bar"}'
|
|
542
|
-
assert prepped['headers'].get('content-encoding') != 'gzip'
|
|
543
|
-
|
|
544
|
-
# Should return compressed data when gzip is on
|
|
545
|
-
service.set_enable_gzip_compression(True)
|
|
546
|
-
assert service.get_enable_gzip_compression()
|
|
547
|
-
prepped = service.prepare_request(
|
|
548
|
-
'GET', url='', data=json.dumps({"foo": "bar"}))
|
|
549
|
-
assert prepped['data'] == gzip.compress(b'{"foo": "bar"}')
|
|
550
|
-
assert prepped['headers'].get('content-encoding') == 'gzip'
|
|
551
|
-
|
|
552
|
-
# Should return compressed data when gzip is on for non-json data
|
|
553
|
-
assert service.get_enable_gzip_compression()
|
|
554
|
-
prepped = service.prepare_request('GET', url='', data=b'rawdata')
|
|
555
|
-
assert prepped['data'] == gzip.compress(b'rawdata')
|
|
556
|
-
assert prepped['headers'].get('content-encoding') == 'gzip'
|
|
557
|
-
|
|
558
|
-
# Should return compressed data when gzip is on for gzip file data
|
|
559
|
-
assert service.get_enable_gzip_compression()
|
|
560
|
-
with tempfile.TemporaryFile(mode='w+b') as t_f:
|
|
561
|
-
with gzip.GzipFile(mode='wb', fileobj=t_f) as gz_f:
|
|
562
|
-
gz_f.write(json.dumps({"foo": "bar"}).encode())
|
|
563
|
-
with gzip.GzipFile(mode='rb', fileobj=t_f) as gz_f:
|
|
564
|
-
gzip_data = gz_f.read()
|
|
565
|
-
prepped = service.prepare_request('GET', url='', data=gzip_data)
|
|
566
|
-
assert prepped['data'] == gzip.compress(t_f.read())
|
|
567
|
-
assert prepped['headers'].get('content-encoding') == 'gzip'
|
|
568
|
-
|
|
569
|
-
# Should return compressed json data when gzip is on for gzip file json data
|
|
570
|
-
assert service.get_enable_gzip_compression()
|
|
571
|
-
with tempfile.TemporaryFile(mode='w+b') as t_f:
|
|
572
|
-
with gzip.GzipFile(mode='wb', fileobj=t_f) as gz_f:
|
|
573
|
-
gz_f.write("rawdata".encode())
|
|
574
|
-
with gzip.GzipFile(mode='rb', fileobj=t_f) as gz_f:
|
|
575
|
-
gzip_data = gz_f.read()
|
|
576
|
-
prepped = service.prepare_request('GET', url='', data=gzip_data)
|
|
577
|
-
assert prepped['data'] == gzip.compress(t_f.read())
|
|
578
|
-
assert prepped['headers'].get('content-encoding') == 'gzip'
|
|
579
|
-
|
|
580
|
-
# Should return uncompressed data when content-encoding is set
|
|
581
|
-
assert service.get_enable_gzip_compression()
|
|
582
|
-
prepped = service.prepare_request('GET', url='', headers={"content-encoding": "gzip"},
|
|
583
|
-
data=json.dumps({"foo": "bar"}))
|
|
584
|
-
assert prepped['data'] == b'{"foo": "bar"}'
|
|
585
|
-
assert prepped['headers'].get('content-encoding') == 'gzip'
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
def test_gzip_compression_external():
|
|
589
|
-
# Should set gzip compression from external config
|
|
590
|
-
file_path = os.path.join(
|
|
591
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-gzip.env')
|
|
592
|
-
os.environ['IBM_CREDENTIALS_FILE'] = file_path
|
|
593
|
-
service = IncludeExternalConfigService(
|
|
594
|
-
'v1', authenticator=NoAuthAuthenticator())
|
|
595
|
-
assert service.service_url == 'https://mockurl'
|
|
596
|
-
assert service.get_enable_gzip_compression() is True
|
|
597
|
-
prepped = service.prepare_request(
|
|
598
|
-
'GET', url='', data=json.dumps({"foo": "bar"}))
|
|
599
|
-
assert prepped['data'] == gzip.compress(b'{"foo": "bar"}')
|
|
600
|
-
assert prepped['headers'].get('content-encoding') == 'gzip'
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
def test_retry_config_default():
|
|
604
|
-
service = BaseService(service_url='https://mockurl/',
|
|
605
|
-
authenticator=NoAuthAuthenticator())
|
|
606
|
-
service.enable_retries()
|
|
607
|
-
assert service.retry_config.total == 4
|
|
608
|
-
assert service.retry_config.backoff_factor == 1.0
|
|
609
|
-
assert service.http_client.get_adapter('https://').max_retries.total == 4
|
|
610
|
-
|
|
611
|
-
# Ensure retries fail after 4 retries
|
|
612
|
-
error = ConnectTimeoutError()
|
|
613
|
-
retry = service.http_client.get_adapter('https://').max_retries
|
|
614
|
-
retry = retry.increment(error=error)
|
|
615
|
-
retry = retry.increment(error=error)
|
|
616
|
-
retry = retry.increment(error=error)
|
|
617
|
-
retry = retry.increment(error=error)
|
|
618
|
-
with pytest.raises(MaxRetryError) as retry_err:
|
|
619
|
-
retry.increment(error=error)
|
|
620
|
-
assert retry_err.value.reason == error
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
def test_retry_config_disable():
|
|
624
|
-
# Test disabling retries
|
|
625
|
-
service = BaseService(service_url='https://mockurl/',
|
|
626
|
-
authenticator=NoAuthAuthenticator())
|
|
627
|
-
service.enable_retries()
|
|
628
|
-
service.disable_retries()
|
|
629
|
-
assert service.retry_config is None
|
|
630
|
-
assert service.http_client.get_adapter('https://').max_retries.total == 0
|
|
631
|
-
|
|
632
|
-
# Ensure retries are not started after one connection attempt
|
|
633
|
-
error = ConnectTimeoutError()
|
|
634
|
-
retry = service.http_client.get_adapter('https://').max_retries
|
|
635
|
-
with pytest.raises(MaxRetryError) as retry_err:
|
|
636
|
-
retry.increment(error=error)
|
|
637
|
-
assert retry_err.value.reason == error
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
def test_retry_config_non_default():
|
|
641
|
-
service = BaseService(service_url='https://mockurl/',
|
|
642
|
-
authenticator=NoAuthAuthenticator())
|
|
643
|
-
service.enable_retries(2, 0.3)
|
|
644
|
-
assert service.retry_config.total == 2
|
|
645
|
-
assert service.retry_config.backoff_factor == 0.3
|
|
646
|
-
|
|
647
|
-
# Ensure retries fail after 2 retries
|
|
648
|
-
error = ConnectTimeoutError()
|
|
649
|
-
retry = service.http_client.get_adapter('https://').max_retries
|
|
650
|
-
retry = retry.increment(error=error)
|
|
651
|
-
retry = retry.increment(error=error)
|
|
652
|
-
with pytest.raises(MaxRetryError) as retry_err:
|
|
653
|
-
retry.increment(error=error)
|
|
654
|
-
assert retry_err.value.reason == error
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
def test_retry_config_external():
|
|
658
|
-
file_path = os.path.join(
|
|
659
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-retry.env')
|
|
660
|
-
os.environ['IBM_CREDENTIALS_FILE'] = file_path
|
|
661
|
-
service = IncludeExternalConfigService(
|
|
662
|
-
'v1', authenticator=NoAuthAuthenticator())
|
|
663
|
-
assert service.retry_config.total == 3
|
|
664
|
-
assert service.retry_config.backoff_factor == 0.2
|
|
665
|
-
|
|
666
|
-
# Ensure retries fail after 3 retries
|
|
667
|
-
error = ConnectTimeoutError()
|
|
668
|
-
retry = service.http_client.get_adapter('https://').max_retries
|
|
669
|
-
retry = retry.increment(error=error)
|
|
670
|
-
retry = retry.increment(error=error)
|
|
671
|
-
retry = retry.increment(error=error)
|
|
672
|
-
with pytest.raises(MaxRetryError) as retry_err:
|
|
673
|
-
retry.increment(error=error)
|
|
674
|
-
assert retry_err.value.reason == error
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
@responses.activate
|
|
678
|
-
def test_user_agent_header():
|
|
679
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
680
|
-
user_agent_header = service.user_agent_header
|
|
681
|
-
assert user_agent_header is not None
|
|
682
|
-
assert user_agent_header['User-Agent'] is not None
|
|
683
|
-
|
|
684
|
-
responses.add(
|
|
685
|
-
responses.GET,
|
|
686
|
-
'https://gateway.watsonplatform.net/test/api',
|
|
687
|
-
status=200,
|
|
688
|
-
body='some text')
|
|
689
|
-
prepped = service.prepare_request('GET', url='', headers={
|
|
690
|
-
'user-agent': 'my_user_agent'
|
|
691
|
-
})
|
|
692
|
-
response = service.send(prepped)
|
|
693
|
-
assert response.get_result().request.headers.get(
|
|
694
|
-
'user-agent') == 'my_user_agent'
|
|
695
|
-
|
|
696
|
-
prepped = service.prepare_request('GET', url='', headers=None)
|
|
697
|
-
response = service.send(prepped)
|
|
698
|
-
assert response.get_result().request.headers.get(
|
|
699
|
-
'user-agent') == user_agent_header['User-Agent']
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
@responses.activate
|
|
703
|
-
def test_reserved_keys(caplog):
|
|
704
|
-
service = AnyServiceV1('2021-07-02', authenticator=NoAuthAuthenticator())
|
|
705
|
-
responses.add(
|
|
706
|
-
responses.GET,
|
|
707
|
-
'https://gateway.watsonplatform.net/test/api',
|
|
708
|
-
status=200,
|
|
709
|
-
body='some text')
|
|
710
|
-
prepped = service.prepare_request('GET', url='', headers={'key': 'OK'})
|
|
711
|
-
response = service.send(
|
|
712
|
-
prepped,
|
|
713
|
-
headers={'key': 'bad'},
|
|
714
|
-
method='POST',
|
|
715
|
-
url='localhost',
|
|
716
|
-
cookies=None,
|
|
717
|
-
hooks={'response': []})
|
|
718
|
-
assert response.get_result().request.headers.get('key') == 'OK'
|
|
719
|
-
assert response.get_result().request.url == 'https://gateway.watsonplatform.net/test/api'
|
|
720
|
-
assert response.get_result().request.method == 'GET'
|
|
721
|
-
assert response.get_result().request.hooks == {'response': []}
|
|
722
|
-
assert caplog.record_tuples[0][2] == '"method" has been removed from the request'
|
|
723
|
-
assert caplog.record_tuples[1][2] == '"url" has been removed from the request'
|
|
724
|
-
assert caplog.record_tuples[2][2] == '"cookies" has been removed from the request'
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
@responses.activate
|
|
728
|
-
def test_ssl_error():
|
|
729
|
-
responses.add(
|
|
730
|
-
responses.GET,
|
|
731
|
-
'https://gateway.watsonplatform.net/test/api',
|
|
732
|
-
body=requests.exceptions.SSLError())
|
|
733
|
-
service = AnyServiceV1('2021-08-18', authenticator=NoAuthAuthenticator())
|
|
734
|
-
with pytest.raises(requests.exceptions.SSLError):
|
|
735
|
-
prepped = service.prepare_request('GET', url='')
|
|
736
|
-
service.send(prepped)
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
def test_files_dict():
|
|
740
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
741
|
-
|
|
742
|
-
form_data = {}
|
|
743
|
-
with open(
|
|
744
|
-
os.path.join(
|
|
745
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-iam.env'), 'r', encoding='utf-8') as file:
|
|
746
|
-
form_data['file1'] = (None, file, 'application/octet-stream')
|
|
747
|
-
form_data['string1'] = (None, 'hello', 'text/plain')
|
|
748
|
-
request = service.prepare_request(
|
|
749
|
-
'GET', url='', headers={'X-opt-out': True}, files=form_data)
|
|
750
|
-
files = request['files']
|
|
751
|
-
assert isinstance(files, list)
|
|
752
|
-
assert len(files) == 2
|
|
753
|
-
files_dict = dict(files)
|
|
754
|
-
file1 = files_dict['file1']
|
|
755
|
-
assert file1[0] == 'ibm-credentials-iam.env'
|
|
756
|
-
string1 = files_dict['string1']
|
|
757
|
-
assert string1[0] is None
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
def test_files_list():
|
|
761
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
762
|
-
|
|
763
|
-
form_data = []
|
|
764
|
-
with open(
|
|
765
|
-
os.path.join(
|
|
766
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-iam.env'), 'r', encoding='utf-8') as file:
|
|
767
|
-
form_data.append(('file1', (None, file, 'application/octet-stream')))
|
|
768
|
-
form_data.append(('string1', (None, 'hello', 'text/plain')))
|
|
769
|
-
request = service.prepare_request(
|
|
770
|
-
'GET', url='', headers={'X-opt-out': True}, files=form_data)
|
|
771
|
-
files = request['files']
|
|
772
|
-
assert isinstance(files, list)
|
|
773
|
-
assert len(files) == 2
|
|
774
|
-
files_dict = dict(files)
|
|
775
|
-
file1 = files_dict['file1']
|
|
776
|
-
assert file1[0] == 'ibm-credentials-iam.env'
|
|
777
|
-
string1 = files_dict['string1']
|
|
778
|
-
assert string1[0] is None
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
def test_files_duplicate_parts():
|
|
782
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
783
|
-
|
|
784
|
-
form_data = []
|
|
785
|
-
with open(
|
|
786
|
-
os.path.join(
|
|
787
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-iam.env'), 'r', encoding='utf-8') as file:
|
|
788
|
-
form_data.append(
|
|
789
|
-
('creds_file', (None, file, 'application/octet-stream')))
|
|
790
|
-
with open(
|
|
791
|
-
os.path.join(
|
|
792
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-basic.env'), 'r', encoding='utf-8') as file:
|
|
793
|
-
form_data.append(
|
|
794
|
-
('creds_file', (None, file, 'application/octet-stream')))
|
|
795
|
-
with open(
|
|
796
|
-
os.path.join(
|
|
797
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-bearer.env'), 'r', encoding='utf-8') as file:
|
|
798
|
-
form_data.append(
|
|
799
|
-
('creds_file', (None, file, 'application/octet-stream')))
|
|
800
|
-
request = service.prepare_request(
|
|
801
|
-
'GET', url='', headers={'X-opt-out': True}, files=form_data)
|
|
802
|
-
files = request['files']
|
|
803
|
-
assert isinstance(files, list)
|
|
804
|
-
assert len(files) == 3
|
|
805
|
-
for part_name, file_tuple in files:
|
|
806
|
-
assert part_name == 'creds_file'
|
|
807
|
-
assert file_tuple[0] is not None
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
def test_json():
|
|
811
|
-
service = AnyServiceV1('2018-11-20', authenticator=NoAuthAuthenticator())
|
|
812
|
-
req = service.prepare_request('POST', url='', headers={
|
|
813
|
-
'X-opt-out': True}, data={'hello': 'world', 'fóó': 'bår'})
|
|
814
|
-
assert req.get(
|
|
815
|
-
'data') == b'{"hello": "world", "f\\u00f3\\u00f3": "b\\u00e5r"}'
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
def test_service_url_handling():
|
|
819
|
-
service = AnyServiceV1(
|
|
820
|
-
'2018-11-20', service_url='https://host///////', authenticator=NoAuthAuthenticator())
|
|
821
|
-
assert service.service_url == 'https://host'
|
|
822
|
-
|
|
823
|
-
service.set_service_url('https://host/')
|
|
824
|
-
assert service.service_url == 'https://host'
|
|
825
|
-
|
|
826
|
-
req = service.prepare_request('POST',
|
|
827
|
-
url='/path/',
|
|
828
|
-
headers={'X-opt-out': True},
|
|
829
|
-
data={'hello': 'world'})
|
|
830
|
-
assert req.get('url') == 'https://host/path/'
|
|
831
|
-
|
|
832
|
-
service = AnyServiceV1(
|
|
833
|
-
'2018-11-20', service_url='https://host/', authenticator=NoAuthAuthenticator())
|
|
834
|
-
assert service.service_url == 'https://host'
|
|
835
|
-
|
|
836
|
-
service.set_service_url('https://host/')
|
|
837
|
-
assert service.service_url == 'https://host'
|
|
838
|
-
|
|
839
|
-
req = service.prepare_request('POST',
|
|
840
|
-
url='/',
|
|
841
|
-
headers={'X-opt-out': True},
|
|
842
|
-
data={'hello': 'world'})
|
|
843
|
-
assert req.get('url') == 'https://host/'
|
|
844
|
-
|
|
845
|
-
req = service.prepare_request('POST',
|
|
846
|
-
url='////',
|
|
847
|
-
headers={'X-opt-out': True},
|
|
848
|
-
data={'hello': 'world'})
|
|
849
|
-
assert req.get('url') == 'https://host/'
|
|
850
|
-
|
|
851
|
-
service.set_service_url(None)
|
|
852
|
-
assert service.service_url is None
|
|
853
|
-
|
|
854
|
-
service = AnyServiceV1('2018-11-20', service_url='/',
|
|
855
|
-
authenticator=NoAuthAuthenticator())
|
|
856
|
-
assert service.service_url == ''
|
|
857
|
-
|
|
858
|
-
service.set_service_url('/')
|
|
859
|
-
assert service.service_url == ''
|
|
860
|
-
|
|
861
|
-
with pytest.raises(ValueError) as err:
|
|
862
|
-
service.prepare_request('POST',
|
|
863
|
-
url='/',
|
|
864
|
-
headers={'X-opt-out': True},
|
|
865
|
-
data={'hello': 'world'})
|
|
866
|
-
assert str(err.value) == 'The service_url is required'
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
def test_service_url_slash():
|
|
870
|
-
service = AnyServiceV1('2018-11-20', service_url='/',
|
|
871
|
-
authenticator=NoAuthAuthenticator())
|
|
872
|
-
assert service.service_url == ''
|
|
873
|
-
with pytest.raises(ValueError) as err:
|
|
874
|
-
service.prepare_request('POST',
|
|
875
|
-
url='/',
|
|
876
|
-
headers={'X-opt-out': True},
|
|
877
|
-
data={'hello': 'world'})
|
|
878
|
-
assert str(err.value) == 'The service_url is required'
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
def test_service_url_not_set():
|
|
882
|
-
service = BaseService(service_url='', authenticator=NoAuthAuthenticator())
|
|
883
|
-
with pytest.raises(ValueError) as err:
|
|
884
|
-
service.prepare_request('POST', url='')
|
|
885
|
-
assert str(err.value) == 'The service_url is required'
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
def test_setting_proxy():
|
|
889
|
-
service = BaseService(service_url='test',
|
|
890
|
-
authenticator=IAMAuthenticator('wonder woman'))
|
|
891
|
-
assert service.authenticator is not None
|
|
892
|
-
assert service.authenticator.token_manager.http_config == {}
|
|
893
|
-
|
|
894
|
-
http_config = {
|
|
895
|
-
"proxies": {
|
|
896
|
-
"http": "user:password@host:port"
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
service.set_http_config(http_config)
|
|
900
|
-
assert service.authenticator.token_manager.http_config == http_config
|
|
901
|
-
|
|
902
|
-
service2 = BaseService(service_url='test', authenticator=BasicAuthenticator(
|
|
903
|
-
'marvellous', 'mrs maisel'))
|
|
904
|
-
service2.set_http_config(http_config)
|
|
905
|
-
assert service2.authenticator is not None
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
def test_configure_service():
|
|
909
|
-
file_path = os.path.join(
|
|
910
|
-
os.path.dirname(__file__), '../resources/ibm-credentials-external.env')
|
|
911
|
-
os.environ['IBM_CREDENTIALS_FILE'] = file_path
|
|
912
|
-
service = IncludeExternalConfigService(
|
|
913
|
-
'v1', authenticator=NoAuthAuthenticator())
|
|
914
|
-
assert service.service_url == 'https://externallyconfigured.com/api'
|
|
915
|
-
assert service.disable_ssl_verification is True
|
|
916
|
-
# The authenticator should not be changed as a result of configure_service()
|
|
917
|
-
assert isinstance(service.get_authenticator(), NoAuthAuthenticator)
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
def test_configure_service_error():
|
|
921
|
-
service = BaseService(
|
|
922
|
-
service_url='v1', authenticator=NoAuthAuthenticator())
|
|
923
|
-
with pytest.raises(ValueError) as err:
|
|
924
|
-
service.configure_service(None)
|
|
925
|
-
assert str(err.value) == 'Service_name must be of type string.'
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
def test_min_ssl_version():
|
|
929
|
-
service = AnyServiceV1('2022-03-08', authenticator=NoAuthAuthenticator())
|
|
930
|
-
adapter = service.http_client.get_adapter('https://')
|
|
931
|
-
ssl_context = adapter.poolmanager.connection_pool_kw.get('ssl_context', None)
|
|
932
|
-
assert ssl_context is not None
|
|
933
|
-
assert ssl_context.minimum_version == ssl.TLSVersion.TLSv1_2
|