byteplus-python-sdk-v2 3.0.61__py2.py3-none-any.whl → 3.0.63__py2.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.
- {byteplus_python_sdk_v2-3.0.61.dist-info → byteplus_python_sdk_v2-3.0.63.dist-info}/METADATA +1 -1
- {byteplus_python_sdk_v2-3.0.61.dist-info → byteplus_python_sdk_v2-3.0.63.dist-info}/RECORD +111 -64
- {byteplus_python_sdk_v2-3.0.61.dist-info → byteplus_python_sdk_v2-3.0.63.dist-info}/WHEEL +1 -1
- byteplussdkcore/api_client.py +36 -8
- byteplussdkcore/auth/provider_binding.py +42 -0
- byteplussdkcore/auth/providers/sts_oidc_provider.py +23 -3
- byteplussdkcore/auth/providers/sts_provider.py +32 -3
- byteplussdkcore/auth/providers/sts_saml_provider.py +23 -3
- byteplussdkcore/auth/sts_http_config.py +133 -0
- byteplussdkcore/configuration.py +1 -1
- byteplussdkcore/feature/rds/connect_utils.py +6 -8
- byteplussdkcore/interceptor/interceptors/request.py +5 -0
- byteplussdkcore/rest.py +27 -0
- byteplussdkcore/retryer/retry_condition.py +29 -1
- byteplussdkecopartner/__init__.py +10 -0
- byteplussdkecopartner/api/eco_partner_api.py +291 -0
- byteplussdkecopartner/models/__init__.py +10 -0
- byteplussdkecopartner/models/download_bill_request.py +129 -0
- byteplussdkredis/models/configure_node_for_create_enterprise_db_instance_input.py → byteplussdkecopartner/models/download_bill_response.py +23 -23
- byteplussdkecopartner/models/file_for_download_bill_output.py +175 -0
- byteplussdkecopartner/models/initiate_bill_generation_request.py +190 -0
- byteplussdkecopartner/models/initiate_bill_generation_response.py +253 -0
- byteplussdkecopartner/models/item_for_list_billing_items_output.py +461 -0
- byteplussdkecopartner/models/list_billing_items_request.py +240 -0
- byteplussdkecopartner/models/list_billing_items_response.py +253 -0
- byteplussdkecopartner/models/task_for_download_bill_output.py +409 -0
- byteplussdkecopartner/models/total_for_list_billing_items_output.py +305 -0
- byteplussdkredis/__init__.py +6 -4
- byteplussdkredis/api/redis_api.py +97 -97
- byteplussdkredis/models/__init__.py +6 -4
- byteplussdkredis/models/describe_planned_event_impact_detail_request.py +124 -0
- byteplussdkredis/models/describe_planned_event_impact_detail_response.py +123 -0
- byteplussdkredis/models/impact_for_describe_planned_event_impact_detail_output.py +149 -0
- byteplussdkredis/models/impact_item_for_describe_planned_event_impact_detail_output.py +201 -0
- byteplussdkredis/models/impact_summary_for_describe_planned_events_output.py +201 -0
- byteplussdkredis/models/involved_node_for_describe_planned_event_impact_detail_output.py +201 -0
- byteplussdkredis/models/planned_event_for_describe_planned_events_output.py +79 -1
- byteplussdkresourcecenter/__init__.py +16 -0
- byteplussdkresourcecenter/api/resourcecenter_api.py +485 -0
- byteplussdkresourcecenter/models/__init__.py +16 -0
- byteplussdkresourcecenter/models/create_query_request.py +11 -3
- byteplussdkresourcecenter/models/execute_multi_account_sql_query_request.py +211 -0
- byteplussdkresourcecenter/models/execute_multi_account_sql_query_response.py +149 -0
- byteplussdkresourcecenter/models/execute_sql_query_request.py +9 -0
- byteplussdkresourcecenter/models/execute_sql_query_response.py +29 -3
- byteplussdkresourcecenter/models/get_multi_account_resource_center_status_response.py +15 -15
- byteplussdkresourcecenter/models/get_multi_account_resource_description_request.py +204 -0
- byteplussdkresourcecenter/models/get_multi_account_resource_description_response.py +461 -0
- byteplussdkresourcecenter/models/get_resource_description_request.py +177 -0
- byteplussdkresourcecenter/models/get_resource_description_response.py +461 -0
- byteplussdkresourcecenter/models/list_multi_account_resource_relationships_request.py +262 -0
- byteplussdkresourcecenter/models/list_multi_account_resource_relationships_response.py +149 -0
- byteplussdkresourcecenter/models/list_resource_relationships_request.py +235 -0
- byteplussdkresourcecenter/models/list_resource_relationships_response.py +149 -0
- byteplussdkresourcecenter/models/related_type_name_for_list_resource_types_output.py +149 -0
- byteplussdkresourcecenter/models/resource_relationship_for_list_multi_account_resource_relationships_output.py +227 -0
- byteplussdkresourcecenter/models/resource_relationship_for_list_resource_relationships_output.py +227 -0
- byteplussdkresourcecenter/models/resource_type_for_list_resource_types_output.py +55 -3
- byteplussdkresourcecenter/models/scope_for_execute_multi_account_sql_query_input.py +175 -0
- byteplussdkresourcecenter/models/search_multi_account_resources_request.py +20 -0
- byteplussdkresourcecenter/models/search_resources_request.py +6 -0
- byteplussdkredis/models/create_enterprise_db_instance_response.py → byteplussdkresourcecenter/models/tag_for_get_multi_account_resource_description_output.py +35 -35
- byteplussdkredis/models/tag_for_create_enterprise_db_instance_input.py → byteplussdkresourcecenter/models/tag_for_get_resource_description_output.py +14 -14
- byteplussdkresourcecenter/models/update_query_request.py +9 -0
- byteplussdkvpc/__init__.py +17 -0
- byteplussdkvpc/api/vpc_api.py +582 -0
- byteplussdkvpc/models/__init__.py +17 -0
- byteplussdkvpc/models/authorize_security_group_egress_batch_request.py +150 -0
- byteplussdkvpc/models/authorize_security_group_egress_batch_response.py +149 -0
- byteplussdkvpc/models/authorize_security_group_ingress_batch_request.py +150 -0
- byteplussdkvpc/models/authorize_security_group_ingress_batch_response.py +149 -0
- byteplussdkvpc/models/create_flow_log_request.py +27 -1
- byteplussdkvpc/models/create_flow_log_response.py +29 -3
- byteplussdkvpc/models/create_ipam_pool_request.py +2 -5
- byteplussdkvpc/models/create_ipam_request.py +0 -3
- byteplussdkvpc/models/create_ipam_resource_discovery_request.py +9 -0
- byteplussdkvpc/models/create_ipam_scope_request.py +2 -5
- byteplussdkvpc/models/create_network_interface_request.py +81 -3
- byteplussdkvpc/models/describe_ipam_pools_request.py +6 -0
- byteplussdkvpc/models/describe_ipam_resource_cidrs_request.py +27 -1
- byteplussdkvpc/models/describe_ipam_resource_discoveries_request.py +6 -0
- byteplussdkvpc/models/describe_ipam_scopes_request.py +6 -0
- byteplussdkvpc/models/describe_ipams_request.py +2 -2
- byteplussdkvpc/models/describe_network_interface_attributes_response.py +79 -1
- byteplussdkvpc/models/ipam_resource_cidr_for_describe_ipam_resource_cidrs_output.py +53 -1
- byteplussdkvpc/models/modify_flow_log_attribute_request.py +27 -1
- byteplussdkvpc/models/modify_flow_log_attribute_response.py +29 -3
- byteplussdkvpc/models/modify_ipam_pool_request.py +2 -5
- byteplussdkvpc/models/modify_ipam_request.py +2 -5
- byteplussdkvpc/models/modify_ipam_resource_discovery_request.py +61 -6
- byteplussdkvpc/models/modify_ipam_resource_discovery_response.py +27 -1
- byteplussdkvpc/models/modify_ipam_scope_request.py +2 -5
- byteplussdkvpc/models/modify_network_interface_attributes_request.py +81 -3
- byteplussdkvpc/models/modify_security_group_egress_batch_request.py +150 -0
- byteplussdkvpc/models/modify_security_group_egress_batch_response.py +149 -0
- byteplussdkvpc/models/modify_security_group_ingress_batch_request.py +150 -0
- byteplussdkvpc/models/modify_security_group_ingress_batch_response.py +149 -0
- byteplussdkvpc/models/network_interface_set_for_describe_network_interfaces_output.py +79 -1
- byteplussdkvpc/models/overlap_detail_for_describe_ipam_resource_cidrs_output.py +175 -0
- byteplussdkvpc/models/permission_for_authorize_security_group_egress_batch_input.py +412 -0
- byteplussdkvpc/models/permission_for_authorize_security_group_ingress_batch_input.py +412 -0
- byteplussdkvpc/models/permission_for_describe_security_group_attributes_output.py +27 -1
- byteplussdkvpc/models/permission_for_modify_security_group_egress_batch_input.py +439 -0
- byteplussdkvpc/models/permission_for_modify_security_group_ingress_batch_input.py +439 -0
- byteplussdkvpc/models/revoke_security_group_egress_batch_request.py +150 -0
- byteplussdkvpc/models/revoke_security_group_egress_batch_response.py +149 -0
- byteplussdkvpc/models/revoke_security_group_ingress_batch_request.py +150 -0
- byteplussdkvpc/models/revoke_security_group_ingress_batch_response.py +149 -0
- byteplussdkredis/models/create_enterprise_db_instance_request.py +0 -625
- {byteplus_python_sdk_v2-3.0.61.dist-info → byteplus_python_sdk_v2-3.0.63.dist-info}/licenses/LICENSE.txt +0 -0
- {byteplus_python_sdk_v2-3.0.61.dist-info → byteplus_python_sdk_v2-3.0.63.dist-info}/licenses/NOTICE.md +0 -0
- {byteplus_python_sdk_v2-3.0.61.dist-info → byteplus_python_sdk_v2-3.0.63.dist-info}/top_level.txt +0 -0
byteplussdkcore/api_client.py
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import absolute_import
|
|
4
4
|
|
|
5
|
+
import copy
|
|
5
6
|
import datetime
|
|
6
7
|
import logging
|
|
8
|
+
import threading
|
|
7
9
|
import time
|
|
8
10
|
from multiprocessing.pool import ThreadPool
|
|
9
11
|
from time import sleep
|
|
@@ -59,6 +61,8 @@ class ApiClient(object):
|
|
|
59
61
|
if configuration is None:
|
|
60
62
|
configuration = Configuration()
|
|
61
63
|
self.configuration = configuration
|
|
64
|
+
self._credential_binding_lock = threading.Lock()
|
|
65
|
+
self.rebind_credential_provider()
|
|
62
66
|
# Use the pool property to lazily initialize the ThreadPool.
|
|
63
67
|
self._pool = None
|
|
64
68
|
self._base_auto_retry = configuration.auto_retry
|
|
@@ -69,7 +73,7 @@ class ApiClient(object):
|
|
|
69
73
|
self.default_headers[header_name] = header_value
|
|
70
74
|
self.cookie = cookie
|
|
71
75
|
# Set default User-Agent.
|
|
72
|
-
self.user_agent = 'byteplus-python-sdk-v2/3.0.
|
|
76
|
+
self.user_agent = 'byteplus-python-sdk-v2/3.0.63'
|
|
73
77
|
self.client_side_validation = configuration.client_side_validation
|
|
74
78
|
|
|
75
79
|
self.interceptor_chain = InterceptorChain()
|
|
@@ -106,6 +110,24 @@ class ApiClient(object):
|
|
|
106
110
|
def set_default_header(self, header_name, header_value):
|
|
107
111
|
self.default_headers[header_name] = header_value
|
|
108
112
|
|
|
113
|
+
def rebind_credential_provider(self):
|
|
114
|
+
"""Snapshot the current provider/proxy configuration with a fresh STS cache.
|
|
115
|
+
|
|
116
|
+
Call after changing configuration or provider settings. Existing requests
|
|
117
|
+
retain their binding; concurrent mutation of the source is unsupported.
|
|
118
|
+
Custom providers retain their identity and no-argument retrieval API.
|
|
119
|
+
"""
|
|
120
|
+
from byteplussdkcore.auth.provider_binding import bind_credential_provider
|
|
121
|
+
with self._credential_binding_lock:
|
|
122
|
+
self._credential_provider = bind_credential_provider(
|
|
123
|
+
self.configuration.credential_provider, self.configuration)
|
|
124
|
+
|
|
125
|
+
def _create_request(self, *args, **kwargs):
|
|
126
|
+
provider = self._credential_provider
|
|
127
|
+
request = Request(self.configuration, *args, **kwargs)
|
|
128
|
+
request.credential_provider = provider
|
|
129
|
+
return request
|
|
130
|
+
|
|
109
131
|
def __call_api(
|
|
110
132
|
self, resource_path, method, path_params=None,
|
|
111
133
|
query_params=None, header_params=None, body=None, post_params=None,
|
|
@@ -119,8 +141,7 @@ class ApiClient(object):
|
|
|
119
141
|
if self.cookie:
|
|
120
142
|
header_params['Cookie'] = self.cookie
|
|
121
143
|
|
|
122
|
-
request =
|
|
123
|
-
self.configuration,
|
|
144
|
+
request = self._create_request(
|
|
124
145
|
resource_path, method, path_params,
|
|
125
146
|
query_params, header_params, body, post_params,
|
|
126
147
|
files, response_type, auth_settings,
|
|
@@ -414,7 +435,8 @@ class ApiClient(object):
|
|
|
414
435
|
host=None, scheme='https', region='cn-beijing',
|
|
415
436
|
timeout=30, service='sts',
|
|
416
437
|
max_retries=3, retry_interval=1,
|
|
417
|
-
provider_name="ApiClient"
|
|
438
|
+
provider_name="ApiClient",
|
|
439
|
+
proxy_url=None, ca_file=None, insecure_skip_verify=False):
|
|
418
440
|
"""Invoke an STS federation endpoint (AssumeRoleWithOIDC / AssumeRoleWithSAML / etc.)
|
|
419
441
|
through the SDK's main REST stack while explicitly disabling signing.
|
|
420
442
|
|
|
@@ -444,10 +466,8 @@ class ApiClient(object):
|
|
|
444
466
|
Returns the unwrapped `Result` dict from the STS response. Business
|
|
445
467
|
errors bubble up as `rest.ApiException` (matching master behavior).
|
|
446
468
|
"""
|
|
447
|
-
#
|
|
448
|
-
|
|
449
|
-
# settings propagate to the STS call.
|
|
450
|
-
fresh = Configuration()
|
|
469
|
+
# Preserve the initiating provider's bind-time transport snapshot.
|
|
470
|
+
fresh = copy.copy(self.configuration)
|
|
451
471
|
# Break recursion on three fronts:
|
|
452
472
|
# 1. credential_provider=None so SignRequestInterceptor won't call
|
|
453
473
|
# back into the provider via get_credentials().
|
|
@@ -472,6 +492,7 @@ class ApiClient(object):
|
|
|
472
492
|
# Caller semantics: max_retries = TOTAL attempts (legacy from
|
|
473
493
|
# _do_http_request's for-loop). Configuration semantics:
|
|
474
494
|
# num_max_retries = retries AFTER the initial attempt. Convert.
|
|
495
|
+
fresh.auto_retry = True
|
|
475
496
|
fresh.num_max_retries = max(max_retries - 1, 0)
|
|
476
497
|
# retry_interval is seconds; Configuration uses ms.
|
|
477
498
|
# Collapse the exponential-backoff range to a fixed delay.
|
|
@@ -480,6 +501,13 @@ class ApiClient(object):
|
|
|
480
501
|
fresh.min_retry_delay_ms = delay_ms
|
|
481
502
|
fresh.max_retry_delay_ms = delay_ms
|
|
482
503
|
|
|
504
|
+
# Proxy / TLS customization for reaching the STS endpoint. Only applied
|
|
505
|
+
# when the caller opted in (any of the three set); otherwise the fresh
|
|
506
|
+
# Configuration keeps its inherited proxy/TLS settings (including
|
|
507
|
+
# HTTP_PROXY / HTTPS_PROXY env-var fallback in RESTClientObject).
|
|
508
|
+
from byteplussdkcore.auth.sts_http_config import StsHttpConfig
|
|
509
|
+
StsHttpConfig(proxy_url, ca_file, insecure_skip_verify).apply_to_configuration(fresh)
|
|
510
|
+
|
|
483
511
|
# NOTE: NEW ApiClient(fresh), not self -- avoids re-entering caller's provider chain.
|
|
484
512
|
client = ApiClient(fresh)
|
|
485
513
|
# BuildRequestInterceptor parses resource_path by index:
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Client-local bindings for the concrete built-in STS providers."""
|
|
2
|
+
import copy
|
|
3
|
+
import threading
|
|
4
|
+
|
|
5
|
+
from six.moves.urllib.parse import urlparse
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def new_sts_configuration(provider):
|
|
9
|
+
from byteplussdkcore.configuration import Configuration
|
|
10
|
+
|
|
11
|
+
snapshot = getattr(provider, '_sts_base_configuration', None)
|
|
12
|
+
configuration = copy.copy(snapshot) if snapshot is not None else Configuration()
|
|
13
|
+
configuration.credential_provider = None
|
|
14
|
+
return configuration
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def bind_credential_provider(provider, configuration):
|
|
18
|
+
from .providers.sts_provider import StsCredentialProvider
|
|
19
|
+
from .providers.sts_oidc_provider import StsOidcCredentialProvider
|
|
20
|
+
from .providers.sts_saml_provider import StsSamlCredentialProvider
|
|
21
|
+
|
|
22
|
+
# Unknown subclasses can own resources or custom copy behavior.
|
|
23
|
+
if type(provider) not in (
|
|
24
|
+
StsCredentialProvider, StsOidcCredentialProvider, StsSamlCredentialProvider):
|
|
25
|
+
return provider
|
|
26
|
+
|
|
27
|
+
with provider._lock:
|
|
28
|
+
bound = copy.copy(provider)
|
|
29
|
+
bound.policy = copy.deepcopy(provider.policy)
|
|
30
|
+
bound.credentials = None
|
|
31
|
+
bound.expired_time = None
|
|
32
|
+
bound._lock = threading.Lock()
|
|
33
|
+
bound._sts_base_configuration = new_sts_configuration(provider)
|
|
34
|
+
# Endpoint resolution accepts a scheme embedded in host.
|
|
35
|
+
scheme = urlparse(bound.host).scheme if bound.host and '://' in bound.host else bound.scheme
|
|
36
|
+
bound.scheme = scheme
|
|
37
|
+
fallback = configuration.proxy
|
|
38
|
+
if not fallback and scheme in ('http', 'https'):
|
|
39
|
+
fallback = getattr(configuration, scheme + '_proxy')
|
|
40
|
+
# Do not turn environment proxy settings into explicit overrides.
|
|
41
|
+
bound._proxy_fallback = fallback or None
|
|
42
|
+
return bound
|
|
@@ -27,7 +27,8 @@ class StsOidcCredentialProvider(Provider):
|
|
|
27
27
|
host='sts.ap-southeast-1.byteplusapi.com', region='ap-southeast-1', timeout=30,
|
|
28
28
|
expired_buffer_seconds=60, policy=None,
|
|
29
29
|
role_trn=None, oidc_token_file=None, session_name=None,
|
|
30
|
-
max_retries=3, retry_interval=1
|
|
30
|
+
max_retries=3, retry_interval=1,
|
|
31
|
+
proxy_url=None, ca_file=None, insecure_skip_verify=False):
|
|
31
32
|
|
|
32
33
|
self._legacy_mode = oidc_token is not None
|
|
33
34
|
|
|
@@ -78,6 +79,13 @@ class StsOidcCredentialProvider(Provider):
|
|
|
78
79
|
self.region = region
|
|
79
80
|
self.scheme = scheme
|
|
80
81
|
|
|
82
|
+
# Proxy / TLS customization for reaching the STS endpoint. All optional;
|
|
83
|
+
# empty by default so RESTClientObject keeps its normal behavior
|
|
84
|
+
# (including HTTP_PROXY / HTTPS_PROXY env-var fallback).
|
|
85
|
+
self.proxy_url = proxy_url or None
|
|
86
|
+
self.ca_file = ca_file or None
|
|
87
|
+
self.insecure_skip_verify = bool(insecure_skip_verify)
|
|
88
|
+
|
|
81
89
|
if expired_buffer_seconds > 600:
|
|
82
90
|
raise ValueError('expired_buffer_seconds must be less than or equal to 600')
|
|
83
91
|
self.expired_buffer_seconds = expired_buffer_seconds
|
|
@@ -157,8 +165,17 @@ class StsOidcCredentialProvider(Provider):
|
|
|
157
165
|
|
|
158
166
|
# Late imports to avoid circular deps (auth.providers is imported
|
|
159
167
|
# indirectly by byteplussdkcore/__init__.py).
|
|
160
|
-
from byteplussdkcore import ApiClient
|
|
161
|
-
|
|
168
|
+
from byteplussdkcore import ApiClient
|
|
169
|
+
from byteplussdkcore.auth.provider_binding import new_sts_configuration
|
|
170
|
+
from byteplussdkcore.auth.sts_http_config import StsHttpConfig
|
|
171
|
+
configuration = new_sts_configuration(self)
|
|
172
|
+
configuration.scheme = self.scheme
|
|
173
|
+
# Apply overrides before ApiClient constructs its REST transport.
|
|
174
|
+
StsHttpConfig(
|
|
175
|
+
self.proxy_url or getattr(self, '_proxy_fallback', None),
|
|
176
|
+
self.ca_file, self.insecure_skip_verify
|
|
177
|
+
).apply_to_configuration(configuration)
|
|
178
|
+
resp_result = ApiClient(configuration)._sts_call(
|
|
162
179
|
action='AssumeRoleWithOIDC',
|
|
163
180
|
version='2018-01-01',
|
|
164
181
|
params=params,
|
|
@@ -169,6 +186,9 @@ class StsOidcCredentialProvider(Provider):
|
|
|
169
186
|
max_retries=self.max_retries,
|
|
170
187
|
retry_interval=self.retry_interval,
|
|
171
188
|
provider_name=self.PROVIDER_NAME,
|
|
189
|
+
proxy_url=self.proxy_url or getattr(self, '_proxy_fallback', None),
|
|
190
|
+
ca_file=self.ca_file,
|
|
191
|
+
insecure_skip_verify=self.insecure_skip_verify,
|
|
172
192
|
)
|
|
173
193
|
if 'Credentials' not in resp_result:
|
|
174
194
|
raise RuntimeError(
|
|
@@ -5,7 +5,7 @@ from datetime import datetime
|
|
|
5
5
|
|
|
6
6
|
import dateutil.parser
|
|
7
7
|
|
|
8
|
-
from byteplussdkcore import UniversalApi, UniversalInfo, ApiClient
|
|
8
|
+
from byteplussdkcore import UniversalApi, UniversalInfo, ApiClient
|
|
9
9
|
from .provider import Provider, CredentialValue
|
|
10
10
|
|
|
11
11
|
|
|
@@ -20,7 +20,8 @@ class AssumeRoleCredentials:
|
|
|
20
20
|
|
|
21
21
|
class StsCredentialProvider(Provider):
|
|
22
22
|
def __init__(self, ak, sk, role_name, account_id, duration_seconds=3600, scheme='https',
|
|
23
|
-
host='sts.ap-southeast-1.byteplusapi.com', region='ap-southeast-1', timeout=30, expired_buffer_seconds=60, policy=None, max_retries=3, retry_interval=1
|
|
23
|
+
host='sts.ap-southeast-1.byteplusapi.com', region='ap-southeast-1', timeout=30, expired_buffer_seconds=60, policy=None, max_retries=3, retry_interval=1,
|
|
24
|
+
proxy_url=None, ca_file=None, insecure_skip_verify=False):
|
|
24
25
|
self.ak = ak
|
|
25
26
|
self.sk = sk
|
|
26
27
|
self.role_name = role_name
|
|
@@ -36,6 +37,13 @@ class StsCredentialProvider(Provider):
|
|
|
36
37
|
self.scheme = scheme
|
|
37
38
|
self.policy = policy
|
|
38
39
|
|
|
40
|
+
# Proxy / TLS customization for reaching the STS endpoint. All optional;
|
|
41
|
+
# empty by default so RESTClientObject keeps its normal behavior
|
|
42
|
+
# (including HTTP_PROXY / HTTPS_PROXY env-var fallback).
|
|
43
|
+
self.proxy_url = proxy_url or None
|
|
44
|
+
self.ca_file = ca_file or None
|
|
45
|
+
self.insecure_skip_verify = bool(insecure_skip_verify)
|
|
46
|
+
|
|
39
47
|
self.expired_time = None
|
|
40
48
|
if expired_buffer_seconds > 600:
|
|
41
49
|
raise ValueError('expired_buffer_seconds must be less than or equal to 600')
|
|
@@ -69,18 +77,39 @@ class StsCredentialProvider(Provider):
|
|
|
69
77
|
}
|
|
70
78
|
if self.policy is not None:
|
|
71
79
|
params['Policy'] = self.policy
|
|
72
|
-
|
|
80
|
+
# Bound clients retain the default STS transport settings from binding.
|
|
81
|
+
# Direct provider use still inherits the current default configuration.
|
|
82
|
+
from byteplussdkcore.auth.provider_binding import new_sts_configuration
|
|
83
|
+
configuration = new_sts_configuration(self)
|
|
84
|
+
# Break recursion: this AssumeRole call signs with the explicit ak/sk
|
|
85
|
+
# below, so it must NOT re-enter a credential provider (which could be
|
|
86
|
+
# this very provider via the inherited default configuration).
|
|
87
|
+
configuration.credential_provider = None
|
|
73
88
|
configuration.ak = self.ak
|
|
74
89
|
configuration.sk = self.sk
|
|
90
|
+
configuration.session_token = ""
|
|
75
91
|
configuration.host = self.host
|
|
76
92
|
configuration.region = self.region
|
|
77
93
|
configuration.scheme = self.scheme
|
|
78
94
|
configuration.read_timeout = self.timeout
|
|
79
95
|
|
|
96
|
+
# Provider max_retries controls total attempts independently of business retry.
|
|
97
|
+
configuration.auto_retry = True
|
|
80
98
|
configuration.num_max_retries = max(self.max_retries - 1, 0)
|
|
81
99
|
delay_ms = int(self.retry_interval * 1000)
|
|
82
100
|
configuration.min_retry_delay_ms = delay_ms
|
|
83
101
|
configuration.max_retry_delay_ms = delay_ms
|
|
102
|
+
|
|
103
|
+
# Proxy / TLS customization for reaching the STS endpoint. Only applied
|
|
104
|
+
# when the caller opted in; otherwise the configuration keeps its
|
|
105
|
+
# default proxy/TLS settings (including HTTP_PROXY / HTTPS_PROXY
|
|
106
|
+
# env-var fallback in RESTClientObject).
|
|
107
|
+
from byteplussdkcore.auth.sts_http_config import StsHttpConfig
|
|
108
|
+
StsHttpConfig(
|
|
109
|
+
self.proxy_url or getattr(self, '_proxy_fallback', None),
|
|
110
|
+
self.ca_file, self.insecure_skip_verify
|
|
111
|
+
).apply_to_configuration(configuration)
|
|
112
|
+
|
|
84
113
|
c = UniversalApi(ApiClient(configuration))
|
|
85
114
|
info = UniversalInfo(method='GET', service='sts', version='2018-01-01', action='AssumeRole',
|
|
86
115
|
content_type='text/plain')
|
|
@@ -24,7 +24,8 @@ class StsSamlCredentialProvider(Provider):
|
|
|
24
24
|
def __init__(self, role_name=None, account_id=None, provider_name=None, saml_resp=None,
|
|
25
25
|
duration_seconds=3600, scheme='https',
|
|
26
26
|
host='sts.ap-southeast-1.byteplusapi.com', region='ap-southeast-1', timeout=30, expired_buffer_seconds=60,
|
|
27
|
-
policy=None, role_trn=None, saml_provider_trn=None, max_retries=3, retry_interval=1
|
|
27
|
+
policy=None, role_trn=None, saml_provider_trn=None, max_retries=3, retry_interval=1,
|
|
28
|
+
proxy_url=None, ca_file=None, insecure_skip_verify=False):
|
|
28
29
|
self.role_name = role_name
|
|
29
30
|
self.account_id = account_id
|
|
30
31
|
self.provider_name = provider_name
|
|
@@ -58,6 +59,13 @@ class StsSamlCredentialProvider(Provider):
|
|
|
58
59
|
self.scheme = scheme
|
|
59
60
|
self.policy = policy
|
|
60
61
|
|
|
62
|
+
# Proxy / TLS customization for reaching the STS endpoint. All optional;
|
|
63
|
+
# empty by default so RESTClientObject keeps its normal behavior
|
|
64
|
+
# (including HTTP_PROXY / HTTPS_PROXY env-var fallback).
|
|
65
|
+
self.proxy_url = proxy_url or None
|
|
66
|
+
self.ca_file = ca_file or None
|
|
67
|
+
self.insecure_skip_verify = bool(insecure_skip_verify)
|
|
68
|
+
|
|
61
69
|
self.expired_time = None
|
|
62
70
|
if expired_buffer_seconds > 600:
|
|
63
71
|
raise ValueError('expired_buffer_seconds must be less than or equal to 600')
|
|
@@ -117,8 +125,17 @@ class StsSamlCredentialProvider(Provider):
|
|
|
117
125
|
}
|
|
118
126
|
if self.policy is not None:
|
|
119
127
|
params['Policy'] = self.policy
|
|
120
|
-
from byteplussdkcore import ApiClient
|
|
121
|
-
|
|
128
|
+
from byteplussdkcore import ApiClient
|
|
129
|
+
from byteplussdkcore.auth.provider_binding import new_sts_configuration
|
|
130
|
+
from byteplussdkcore.auth.sts_http_config import StsHttpConfig
|
|
131
|
+
configuration = new_sts_configuration(self)
|
|
132
|
+
configuration.scheme = self.scheme
|
|
133
|
+
# Apply overrides before ApiClient constructs its REST transport.
|
|
134
|
+
StsHttpConfig(
|
|
135
|
+
self.proxy_url or getattr(self, '_proxy_fallback', None),
|
|
136
|
+
self.ca_file, self.insecure_skip_verify
|
|
137
|
+
).apply_to_configuration(configuration)
|
|
138
|
+
resp_result = ApiClient(configuration)._sts_call(
|
|
122
139
|
action='AssumeRoleWithSAML',
|
|
123
140
|
version='2018-01-01',
|
|
124
141
|
params=params,
|
|
@@ -129,6 +146,9 @@ class StsSamlCredentialProvider(Provider):
|
|
|
129
146
|
max_retries=self.max_retries,
|
|
130
147
|
retry_interval=self.retry_interval,
|
|
131
148
|
provider_name=self.PROVIDER_NAME,
|
|
149
|
+
proxy_url=self.proxy_url or getattr(self, '_proxy_fallback', None),
|
|
150
|
+
ca_file=self.ca_file,
|
|
151
|
+
insecure_skip_verify=self.insecure_skip_verify,
|
|
132
152
|
)
|
|
133
153
|
if 'Credentials' not in resp_result:
|
|
134
154
|
raise RuntimeError(
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
"""Proxy / TLS customization shared by the STS credential providers.
|
|
3
|
+
|
|
4
|
+
This mirrors the Go SDK's ``ProxyConfig`` (see ``byteplus/credentials/
|
|
5
|
+
http_client.go``). It bundles the three public knobs used when reaching the
|
|
6
|
+
STS endpoint and knows how to project them onto an SDK ``Configuration``:
|
|
7
|
+
|
|
8
|
+
proxy_url -> configuration.proxy
|
|
9
|
+
ca_file -> configuration.ssl_ca_cert
|
|
10
|
+
insecure_skip_verify -> configuration.verify_ssl (inverted)
|
|
11
|
+
|
|
12
|
+
Unlike the Go SDK -- which builds a dedicated ``*http.Transport`` -- the
|
|
13
|
+
Python SDK already routes every request (including STS federation calls)
|
|
14
|
+
through ``RESTClientObject``, which reads these ``Configuration`` fields
|
|
15
|
+
directly. So the only thing this helper needs to do is set the fields.
|
|
16
|
+
|
|
17
|
+
An explicit provider ``proxy_url`` wins over its client-local fallback.
|
|
18
|
+
When both are empty, the transport retains default configuration and
|
|
19
|
+
``HTTP_PROXY`` / ``HTTPS_PROXY`` lookup; it does not implement ``NO_PROXY``.
|
|
20
|
+
|
|
21
|
+
TLS priority also matches Go's ``tls.Config``: ``insecure_skip_verify``
|
|
22
|
+
takes precedence over ``ca_file`` (when verification is skipped the custom
|
|
23
|
+
CA is irrelevant).
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import absolute_import
|
|
27
|
+
|
|
28
|
+
import base64
|
|
29
|
+
|
|
30
|
+
import six
|
|
31
|
+
from six.moves.urllib.parse import unquote, urlparse
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class StsHttpConfig(object):
|
|
35
|
+
"""Carries proxy / TLS options for a single STS request path.
|
|
36
|
+
|
|
37
|
+
:param proxy_url: Forward proxy address, ``scheme://[user:password@]host:port``.
|
|
38
|
+
Empty preserves default configuration and environment lookup.
|
|
39
|
+
:param ca_file: Path to a custom CA bundle (PEM) used to verify the STS
|
|
40
|
+
server certificate. Restores verification unless skipped.
|
|
41
|
+
Empty inherits ssl_ca_cert, otherwise REST uses certifi.
|
|
42
|
+
:param insecure_skip_verify: When True, skip TLS certificate/hostname
|
|
43
|
+
verification. For debugging only; never use in production.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, proxy_url=None, ca_file=None, insecure_skip_verify=False):
|
|
47
|
+
self.proxy_url = proxy_url or None
|
|
48
|
+
self.ca_file = ca_file or None
|
|
49
|
+
self.insecure_skip_verify = bool(insecure_skip_verify)
|
|
50
|
+
|
|
51
|
+
def is_empty(self):
|
|
52
|
+
"""True when no proxy/TLS option is configured.
|
|
53
|
+
|
|
54
|
+
Callers use this to leave the underlying ``Configuration`` untouched,
|
|
55
|
+
so existing behavior (including BYTEPLUS env-var proxies) is
|
|
56
|
+
preserved when the user did not opt in. Mirrors Go's ``IsZero``.
|
|
57
|
+
"""
|
|
58
|
+
return (not self.proxy_url) and (not self.ca_file) and (not self.insecure_skip_verify)
|
|
59
|
+
|
|
60
|
+
def apply_to_configuration(self, configuration):
|
|
61
|
+
"""Project the configured options onto ``configuration`` in place.
|
|
62
|
+
|
|
63
|
+
No-op when :meth:`is_empty` is True.
|
|
64
|
+
"""
|
|
65
|
+
if self.is_empty():
|
|
66
|
+
return configuration
|
|
67
|
+
|
|
68
|
+
if self.proxy_url:
|
|
69
|
+
# Highest-priority proxy source; RESTClientObject honors this over
|
|
70
|
+
# http_proxy / https_proxy / env vars.
|
|
71
|
+
configuration.proxy = self.proxy_url
|
|
72
|
+
|
|
73
|
+
# TLS: insecure_skip_verify wins over ca_file (same as Go's tls.Config,
|
|
74
|
+
# where RootCAs is ignored once InsecureSkipVerify is set).
|
|
75
|
+
if self.insecure_skip_verify:
|
|
76
|
+
configuration.verify_ssl = False
|
|
77
|
+
configuration.ssl_ca_cert = None
|
|
78
|
+
elif self.ca_file:
|
|
79
|
+
configuration.verify_ssl = True
|
|
80
|
+
configuration.ssl_ca_cert = self.ca_file
|
|
81
|
+
|
|
82
|
+
return configuration
|
|
83
|
+
|
|
84
|
+
def proxy_authorization_header(self):
|
|
85
|
+
"""Return the ``Proxy-Authorization`` header value, or None.
|
|
86
|
+
|
|
87
|
+
Delegates to :func:`build_proxy_authorization_header` using this
|
|
88
|
+
config's ``proxy_url``.
|
|
89
|
+
"""
|
|
90
|
+
return build_proxy_authorization_header(self.proxy_url)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def build_proxy_authorization_header(proxy_url):
|
|
94
|
+
"""Build a ``Basic`` ``Proxy-Authorization`` value from an embedded userinfo.
|
|
95
|
+
|
|
96
|
+
urllib3 (v2) does NOT automatically forward the ``user:password@`` embedded
|
|
97
|
+
in a proxy URL as a ``Proxy-Authorization`` header, whereas Go's
|
|
98
|
+
``http.ProxyURL`` / ``http.ProxyFromEnvironment`` do. To keep behavior
|
|
99
|
+
aligned with the Go SDK, callers extract this header explicitly and pass it
|
|
100
|
+
to ``ProxyManager(proxy_headers=...)``.
|
|
101
|
+
|
|
102
|
+
Returns None when ``proxy_url`` is empty or carries no userinfo. Raises
|
|
103
|
+
``ValueError`` when ``proxy_url`` cannot be parsed.
|
|
104
|
+
"""
|
|
105
|
+
if not proxy_url:
|
|
106
|
+
return None
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
parsed = urlparse(proxy_url)
|
|
110
|
+
except (ValueError, AttributeError) as e:
|
|
111
|
+
raise ValueError("invalid proxy url {0!r}: {1}".format(proxy_url, e))
|
|
112
|
+
|
|
113
|
+
username = parsed.username
|
|
114
|
+
if username is None:
|
|
115
|
+
return None
|
|
116
|
+
password = parsed.password or ""
|
|
117
|
+
|
|
118
|
+
# Go's http.Transport derives proxy Basic auth from url.Userinfo, whose
|
|
119
|
+
# Username()/Password() return the PERCENT-DECODED values. urlparse keeps
|
|
120
|
+
# userinfo raw, so decode here to stay byte-for-byte identical with the Go
|
|
121
|
+
# SDK (e.g. a "p%40ss" password must be sent as "p@ss").
|
|
122
|
+
# Python 2 unquote accepts UTF-8 bytes; Python 3 accepts text.
|
|
123
|
+
if six.PY2:
|
|
124
|
+
username = username.encode("utf-8") if isinstance(username, six.text_type) else username
|
|
125
|
+
password = password.encode("utf-8") if isinstance(password, six.text_type) else password
|
|
126
|
+
username = unquote(username)
|
|
127
|
+
password = unquote(password)
|
|
128
|
+
if isinstance(username, six.text_type):
|
|
129
|
+
username = username.encode("utf-8")
|
|
130
|
+
if isinstance(password, six.text_type):
|
|
131
|
+
password = password.encode("utf-8")
|
|
132
|
+
# urllib3.make_headers uses Latin-1, which cannot encode UTF-8 userinfo.
|
|
133
|
+
return "Basic " + base64.b64encode(username + b":" + password).decode("ascii")
|
byteplussdkcore/configuration.py
CHANGED
|
@@ -302,7 +302,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
|
|
|
302
302
|
"OS: {env}\n" \
|
|
303
303
|
"Python Version: {pyversion}\n" \
|
|
304
304
|
"Version of the API: 0.1.0\n" \
|
|
305
|
-
"SDK Package Version: 3.0.
|
|
305
|
+
"SDK Package Version: 3.0.63".\
|
|
306
306
|
format(env=sys.platform, pyversion=sys.version)
|
|
307
307
|
|
|
308
308
|
@property
|
|
@@ -6,9 +6,8 @@ This module provides utilities for generating authentication tokens for RDS MySQ
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
from byteplussdkcore.endpoint.providers.standard_provider import StandardEndpointResolver
|
|
9
|
-
from byteplussdkcore.interceptor import InterceptorChain, InterceptorContext,
|
|
9
|
+
from byteplussdkcore.interceptor import InterceptorChain, InterceptorContext, \
|
|
10
10
|
ResolveEndpointInterceptor
|
|
11
|
-
from byteplussdkcore.interceptor import Request
|
|
12
11
|
|
|
13
12
|
DEFAULT_SERVICE = 'rds_mysql'
|
|
14
13
|
DEFAULT_API_VERSION = '2022-01-01'
|
|
@@ -58,11 +57,10 @@ def build_auth_token(api_client, db_user, instance_id, expires=None):
|
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
# Create Request with presign mode
|
|
61
|
-
request =
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
query_params=query)
|
|
60
|
+
request = api_client._create_request(
|
|
61
|
+
resource_path='/{}/{}/{}/get/text_plain/'.format(
|
|
62
|
+
DEFAULT_API, DEFAULT_API_VERSION, DEFAULT_SERVICE),
|
|
63
|
+
method='GET', query_params=query)
|
|
66
64
|
request.endpoint_provider = StandardEndpointResolver()
|
|
67
65
|
request.service = DEFAULT_SERVICE
|
|
68
66
|
request.is_presign = True
|
|
@@ -82,7 +80,7 @@ def build_auth_token(api_client, db_user, instance_id, expires=None):
|
|
|
82
80
|
|
|
83
81
|
# Step 3: Sign request (host is None, won't be included in signature)
|
|
84
82
|
sign_chain = InterceptorChain()
|
|
85
|
-
sign_chain.append_request_interceptor(
|
|
83
|
+
sign_chain.append_request_interceptor(api_client.sign_request_interceptor)
|
|
86
84
|
context = sign_chain.execute_request(context)
|
|
87
85
|
|
|
88
86
|
return context.request.signed_query
|
|
@@ -57,6 +57,10 @@ class Request(object):
|
|
|
57
57
|
self.session_token = configuration.session_token
|
|
58
58
|
self.region = configuration.region
|
|
59
59
|
self.scheme = configuration.scheme
|
|
60
|
+
# Business proxy snapshot; credential routing belongs to ApiClient's binding.
|
|
61
|
+
self.proxy = configuration.proxy
|
|
62
|
+
self.http_proxy = configuration.http_proxy
|
|
63
|
+
self.https_proxy = configuration.https_proxy
|
|
60
64
|
self.endpoint_provider = configuration.endpoint_provider
|
|
61
65
|
self.custom_bootstrap_region = configuration.custom_bootstrap_region
|
|
62
66
|
self.use_dual_stack = configuration.use_dual_stack
|
|
@@ -64,6 +68,7 @@ class Request(object):
|
|
|
64
68
|
# ApiClient injects its private base retryer before interception.
|
|
65
69
|
self.auto_retry = configuration.auto_retry
|
|
66
70
|
self.retryer = None
|
|
71
|
+
# ApiClient replaces this with its persistent binding before signing.
|
|
67
72
|
self.credential_provider = configuration.credential_provider
|
|
68
73
|
self.invocation_id = str(uuid.uuid4())
|
|
69
74
|
self.retry_count = 0
|
byteplussdkcore/rest.py
CHANGED
|
@@ -147,6 +147,11 @@ class RESTClientObject(object):
|
|
|
147
147
|
)
|
|
148
148
|
|
|
149
149
|
if proxy_url:
|
|
150
|
+
# urllib3 (v2) does not forward the ``user:password@`` embedded in
|
|
151
|
+
# the proxy URL as a Proxy-Authorization header, unlike Go's
|
|
152
|
+
# http.ProxyURL. Extract it explicitly so proxies requiring Basic
|
|
153
|
+
# auth work the same way across SDKs.
|
|
154
|
+
proxy_headers = self.__proxy_authorization_headers(proxy_url)
|
|
150
155
|
self.pool_manager = urllib3.ProxyManager(
|
|
151
156
|
num_pools=pools_size,
|
|
152
157
|
maxsize=maxsize,
|
|
@@ -155,6 +160,7 @@ class RESTClientObject(object):
|
|
|
155
160
|
cert_file=configuration.cert_file,
|
|
156
161
|
key_file=configuration.key_file,
|
|
157
162
|
proxy_url=proxy_url,
|
|
163
|
+
proxy_headers=proxy_headers,
|
|
158
164
|
timeout=timeout,
|
|
159
165
|
retries=Retry(total=False),
|
|
160
166
|
**addition_pool_args
|
|
@@ -191,6 +197,27 @@ class RESTClientObject(object):
|
|
|
191
197
|
proxy_url = os.getenv('https_proxy')
|
|
192
198
|
return proxy_url
|
|
193
199
|
|
|
200
|
+
@staticmethod
|
|
201
|
+
def __proxy_authorization_headers(proxy_url):
|
|
202
|
+
"""Build proxy_headers carrying Proxy-Authorization, or None.
|
|
203
|
+
|
|
204
|
+
Returns a dict ``{'Proxy-Authorization': 'Basic ...'}`` when the proxy
|
|
205
|
+
URL embeds a ``user:password@`` userinfo, otherwise None (so urllib3
|
|
206
|
+
keeps its default empty proxy headers). Never raises: a malformed proxy
|
|
207
|
+
URL simply yields no auth header and lets the connection attempt (and
|
|
208
|
+
its clearer downstream error) proceed.
|
|
209
|
+
"""
|
|
210
|
+
try:
|
|
211
|
+
from byteplussdkcore.auth.sts_http_config import (
|
|
212
|
+
build_proxy_authorization_header,
|
|
213
|
+
)
|
|
214
|
+
value = build_proxy_authorization_header(proxy_url)
|
|
215
|
+
except Exception:
|
|
216
|
+
return None
|
|
217
|
+
if not value:
|
|
218
|
+
return None
|
|
219
|
+
return {"Proxy-Authorization": value}
|
|
220
|
+
|
|
194
221
|
def request(self, method, url, query_params=None, headers=None,
|
|
195
222
|
body=None, post_params=None, _preload_content=True,
|
|
196
223
|
_request_timeout=None):
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import errno
|
|
1
2
|
import json
|
|
2
3
|
import logging
|
|
3
4
|
import socket
|
|
5
|
+
import ssl
|
|
4
6
|
import traceback
|
|
5
7
|
from abc import abstractmethod
|
|
6
8
|
|
|
7
9
|
import urllib3
|
|
10
|
+
from six.moves.http_client import BadStatusLine
|
|
8
11
|
|
|
9
12
|
from byteplussdkcore.observability.debugger import sdk_core_logger
|
|
10
13
|
from byteplussdkcore.rest import ApiException, RESTResponse
|
|
@@ -73,7 +76,7 @@ class DefaultRetryCondition(RetryCondition):
|
|
|
73
76
|
Returns:
|
|
74
77
|
bool: True if the request should be retried, False otherwise.
|
|
75
78
|
"""
|
|
76
|
-
if err is not None and
|
|
79
|
+
if err is not None and self._is_retryable_exception(err):
|
|
77
80
|
sdk_core_logger.debug_retry("retry for retryable exception, err: %s", err)
|
|
78
81
|
return True
|
|
79
82
|
|
|
@@ -105,6 +108,31 @@ class DefaultRetryCondition(RetryCondition):
|
|
|
105
108
|
sdk_core_logger.debug_retry("no need to retry")
|
|
106
109
|
return False
|
|
107
110
|
|
|
111
|
+
@classmethod
|
|
112
|
+
def _is_retryable_exception(cls, err):
|
|
113
|
+
# Retry the underlying connection failure, not every proxy failure.
|
|
114
|
+
# In particular, a CONNECT 407 or a TLS/configuration error must stop.
|
|
115
|
+
seen = set()
|
|
116
|
+
while isinstance(err, (urllib3.exceptions.ProxyError, urllib3.exceptions.MaxRetryError)):
|
|
117
|
+
if id(err) in seen:
|
|
118
|
+
return False
|
|
119
|
+
seen.add(id(err))
|
|
120
|
+
if isinstance(err, urllib3.exceptions.ProxyError):
|
|
121
|
+
err = err.original_error
|
|
122
|
+
else:
|
|
123
|
+
err = err.reason
|
|
124
|
+
if isinstance(err, (ssl.SSLError, urllib3.exceptions.SSLError)):
|
|
125
|
+
return False
|
|
126
|
+
if isinstance(err, cls.__retry_exceptions):
|
|
127
|
+
return True
|
|
128
|
+
# RemoteDisconnected on Python 3, empty BadStatusLine on Python 2.
|
|
129
|
+
if isinstance(err, BadStatusLine) and err.line in ("", "''"):
|
|
130
|
+
return True
|
|
131
|
+
return isinstance(err, socket.error) and err.errno in (
|
|
132
|
+
errno.ECONNRESET, errno.ECONNREFUSED, errno.ECONNABORTED,
|
|
133
|
+
errno.EPIPE, errno.ETIMEDOUT, errno.ENETUNREACH, errno.EHOSTUNREACH,
|
|
134
|
+
)
|
|
135
|
+
|
|
108
136
|
@staticmethod
|
|
109
137
|
def __json_loads(data):
|
|
110
138
|
"""
|
|
@@ -26,13 +26,23 @@ from byteplussdkecopartner.models.create_invitation_link_response import CreateI
|
|
|
26
26
|
from byteplussdkecopartner.models.create_unique_invitation_link_request import CreateUniqueInvitationLinkRequest
|
|
27
27
|
from byteplussdkecopartner.models.create_unique_invitation_link_response import CreateUniqueInvitationLinkResponse
|
|
28
28
|
from byteplussdkecopartner.models.customer_for_get_customer_details_by_type_output import CustomerForGetCustomerDetailsByTypeOutput
|
|
29
|
+
from byteplussdkecopartner.models.download_bill_request import DownloadBillRequest
|
|
30
|
+
from byteplussdkecopartner.models.download_bill_response import DownloadBillResponse
|
|
31
|
+
from byteplussdkecopartner.models.file_for_download_bill_output import FileForDownloadBillOutput
|
|
29
32
|
from byteplussdkecopartner.models.get_customer_details_by_type_request import GetCustomerDetailsByTypeRequest
|
|
30
33
|
from byteplussdkecopartner.models.get_customer_details_by_type_response import GetCustomerDetailsByTypeResponse
|
|
31
34
|
from byteplussdkecopartner.models.get_customer_details_by_uid_request import GetCustomerDetailsByUIDRequest
|
|
32
35
|
from byteplussdkecopartner.models.get_customer_details_by_uid_response import GetCustomerDetailsByUIDResponse
|
|
33
36
|
from byteplussdkecopartner.models.get_quota_information_request import GetQuotaInformationRequest
|
|
34
37
|
from byteplussdkecopartner.models.get_quota_information_response import GetQuotaInformationResponse
|
|
38
|
+
from byteplussdkecopartner.models.initiate_bill_generation_request import InitiateBillGenerationRequest
|
|
39
|
+
from byteplussdkecopartner.models.initiate_bill_generation_response import InitiateBillGenerationResponse
|
|
40
|
+
from byteplussdkecopartner.models.item_for_list_billing_items_output import ItemForListBillingItemsOutput
|
|
41
|
+
from byteplussdkecopartner.models.list_billing_items_request import ListBillingItemsRequest
|
|
42
|
+
from byteplussdkecopartner.models.list_billing_items_response import ListBillingItemsResponse
|
|
35
43
|
from byteplussdkecopartner.models.modify_quota_request import ModifyQuotaRequest
|
|
36
44
|
from byteplussdkecopartner.models.modify_quota_response import ModifyQuotaResponse
|
|
37
45
|
from byteplussdkecopartner.models.settle_quota_payment_request import SettleQuotaPaymentRequest
|
|
38
46
|
from byteplussdkecopartner.models.settle_quota_payment_response import SettleQuotaPaymentResponse
|
|
47
|
+
from byteplussdkecopartner.models.task_for_download_bill_output import TaskForDownloadBillOutput
|
|
48
|
+
from byteplussdkecopartner.models.total_for_list_billing_items_output import TotalForListBillingItemsOutput
|