byteplus-python-sdk-v2 3.0.60__py2.py3-none-any.whl → 3.0.62__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.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/METADATA +1 -1
- {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/RECORD +75 -52
- 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
- byteplussdkcr/__init__.py +4 -0
- byteplussdkcr/api/cr_api.py +194 -0
- byteplussdkcr/models/__init__.py +4 -0
- byteplussdkcr/models/create_namespace_request.py +55 -3
- byteplussdkcr/models/create_registry_response.py +29 -1
- byteplussdkcr/models/filter_for_list_registries_input.py +27 -1
- byteplussdkcr/models/get_authorization_token_request.py +27 -1
- byteplussdkcr/models/proxy_cache_for_list_registries_output.py +81 -3
- byteplussdkcr/models/update_public_endpoint_request.py +27 -1
- byteplussdkcr/models/update_registry_request.py +176 -0
- byteplussdkcr/models/update_registry_response.py +95 -0
- byteplussdkcr/models/update_tag_description_request.py +244 -0
- byteplussdkcr/models/update_tag_description_response.py +95 -0
- byteplussdkcr/models/vpc_for_update_vpc_endpoint_input.py +27 -1
- 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
- {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/WHEEL +0 -0
- {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/licenses/LICENSE.txt +0 -0
- {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/licenses/NOTICE.md +0 -0
- {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/top_level.txt +0 -0
|
@@ -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.62".\
|
|
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
|
"""
|
byteplussdkcr/__init__.py
CHANGED
|
@@ -93,12 +93,16 @@ from byteplussdkcr.models.status_for_list_registries_output import StatusForList
|
|
|
93
93
|
from byteplussdkcr.models.success_for_delete_tags_output import SuccessForDeleteTagsOutput
|
|
94
94
|
from byteplussdkcr.models.update_public_endpoint_request import UpdatePublicEndpointRequest
|
|
95
95
|
from byteplussdkcr.models.update_public_endpoint_response import UpdatePublicEndpointResponse
|
|
96
|
+
from byteplussdkcr.models.update_registry_request import UpdateRegistryRequest
|
|
97
|
+
from byteplussdkcr.models.update_registry_response import UpdateRegistryResponse
|
|
96
98
|
from byteplussdkcr.models.update_repository_request import UpdateRepositoryRequest
|
|
97
99
|
from byteplussdkcr.models.update_repository_response import UpdateRepositoryResponse
|
|
98
100
|
from byteplussdkcr.models.update_robot_account_password_request import UpdateRobotAccountPasswordRequest
|
|
99
101
|
from byteplussdkcr.models.update_robot_account_password_response import UpdateRobotAccountPasswordResponse
|
|
100
102
|
from byteplussdkcr.models.update_robot_account_request import UpdateRobotAccountRequest
|
|
101
103
|
from byteplussdkcr.models.update_robot_account_response import UpdateRobotAccountResponse
|
|
104
|
+
from byteplussdkcr.models.update_tag_description_request import UpdateTagDescriptionRequest
|
|
105
|
+
from byteplussdkcr.models.update_tag_description_response import UpdateTagDescriptionResponse
|
|
102
106
|
from byteplussdkcr.models.update_vpc_endpoint_request import UpdateVpcEndpointRequest
|
|
103
107
|
from byteplussdkcr.models.update_vpc_endpoint_response import UpdateVpcEndpointResponse
|
|
104
108
|
from byteplussdkcr.models.vpc_for_get_vpc_endpoint_output import VpcForGetVpcEndpointOutput
|
byteplussdkcr/api/cr_api.py
CHANGED
|
@@ -2361,6 +2361,103 @@ class CRApi(object):
|
|
|
2361
2361
|
_request_timeout=params.get('_request_timeout'),
|
|
2362
2362
|
collection_formats=collection_formats)
|
|
2363
2363
|
|
|
2364
|
+
def update_registry(self, body, **kwargs): # noqa: E501
|
|
2365
|
+
"""update_registry # noqa: E501
|
|
2366
|
+
|
|
2367
|
+
This method makes a synchronous HTTP request by default. To make an
|
|
2368
|
+
asynchronous HTTP request, please pass async_req=True
|
|
2369
|
+
>>> thread = api.update_registry(body, async_req=True)
|
|
2370
|
+
>>> result = thread.get()
|
|
2371
|
+
|
|
2372
|
+
:param async_req bool
|
|
2373
|
+
:param UpdateRegistryRequest body: (required)
|
|
2374
|
+
:return: UpdateRegistryResponse
|
|
2375
|
+
If the method is called asynchronously,
|
|
2376
|
+
returns the request thread.
|
|
2377
|
+
"""
|
|
2378
|
+
kwargs['_return_http_data_only'] = True
|
|
2379
|
+
if kwargs.get('async_req'):
|
|
2380
|
+
return self.update_registry_with_http_info(body, **kwargs) # noqa: E501
|
|
2381
|
+
else:
|
|
2382
|
+
(data) = self.update_registry_with_http_info(body, **kwargs) # noqa: E501
|
|
2383
|
+
return data
|
|
2384
|
+
|
|
2385
|
+
def update_registry_with_http_info(self, body, **kwargs): # noqa: E501
|
|
2386
|
+
"""update_registry # noqa: E501
|
|
2387
|
+
|
|
2388
|
+
This method makes a synchronous HTTP request by default. To make an
|
|
2389
|
+
asynchronous HTTP request, please pass async_req=True
|
|
2390
|
+
>>> thread = api.update_registry_with_http_info(body, async_req=True)
|
|
2391
|
+
>>> result = thread.get()
|
|
2392
|
+
|
|
2393
|
+
:param async_req bool
|
|
2394
|
+
:param UpdateRegistryRequest body: (required)
|
|
2395
|
+
:return: UpdateRegistryResponse
|
|
2396
|
+
If the method is called asynchronously,
|
|
2397
|
+
returns the request thread.
|
|
2398
|
+
"""
|
|
2399
|
+
|
|
2400
|
+
all_params = ['body'] # noqa: E501
|
|
2401
|
+
all_params.append('async_req')
|
|
2402
|
+
all_params.append('_return_http_data_only')
|
|
2403
|
+
all_params.append('_preload_content')
|
|
2404
|
+
all_params.append('_request_timeout')
|
|
2405
|
+
|
|
2406
|
+
params = locals()
|
|
2407
|
+
for key, val in six.iteritems(params['kwargs']):
|
|
2408
|
+
if key not in all_params:
|
|
2409
|
+
raise TypeError(
|
|
2410
|
+
"Got an unexpected keyword argument '%s'"
|
|
2411
|
+
" to method update_registry" % key
|
|
2412
|
+
)
|
|
2413
|
+
params[key] = val
|
|
2414
|
+
del params['kwargs']
|
|
2415
|
+
# verify the required parameter 'body' is set
|
|
2416
|
+
if self.api_client.client_side_validation and ('body' not in params or
|
|
2417
|
+
params['body'] is None): # noqa: E501
|
|
2418
|
+
raise ValueError("Missing the required parameter `body` when calling `update_registry`") # noqa: E501
|
|
2419
|
+
|
|
2420
|
+
collection_formats = {}
|
|
2421
|
+
|
|
2422
|
+
path_params = {}
|
|
2423
|
+
|
|
2424
|
+
query_params = []
|
|
2425
|
+
|
|
2426
|
+
header_params = {}
|
|
2427
|
+
|
|
2428
|
+
form_params = []
|
|
2429
|
+
local_var_files = {}
|
|
2430
|
+
|
|
2431
|
+
body_params = None
|
|
2432
|
+
if 'body' in params:
|
|
2433
|
+
body_params = params['body']
|
|
2434
|
+
# HTTP header `Accept`
|
|
2435
|
+
header_params['Accept'] = self.api_client.select_header_accept(
|
|
2436
|
+
['application/json']) # noqa: E501
|
|
2437
|
+
|
|
2438
|
+
# HTTP header `Content-Type`
|
|
2439
|
+
header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501
|
|
2440
|
+
['application/json']) # noqa: E501
|
|
2441
|
+
|
|
2442
|
+
# Authentication setting
|
|
2443
|
+
auth_settings = ['byteplusSign'] # noqa: E501
|
|
2444
|
+
|
|
2445
|
+
return self.api_client.call_api(
|
|
2446
|
+
'/UpdateRegistry/2022-05-12/cr/post/application_json/', 'POST',
|
|
2447
|
+
path_params,
|
|
2448
|
+
query_params,
|
|
2449
|
+
header_params,
|
|
2450
|
+
body=body_params,
|
|
2451
|
+
post_params=form_params,
|
|
2452
|
+
files=local_var_files,
|
|
2453
|
+
response_type='UpdateRegistryResponse', # noqa: E501
|
|
2454
|
+
auth_settings=auth_settings,
|
|
2455
|
+
async_req=params.get('async_req'),
|
|
2456
|
+
_return_http_data_only=params.get('_return_http_data_only'),
|
|
2457
|
+
_preload_content=params.get('_preload_content', True),
|
|
2458
|
+
_request_timeout=params.get('_request_timeout'),
|
|
2459
|
+
collection_formats=collection_formats)
|
|
2460
|
+
|
|
2364
2461
|
def update_repository(self, body, **kwargs): # noqa: E501
|
|
2365
2462
|
"""update_repository # noqa: E501
|
|
2366
2463
|
|
|
@@ -2652,6 +2749,103 @@ class CRApi(object):
|
|
|
2652
2749
|
_request_timeout=params.get('_request_timeout'),
|
|
2653
2750
|
collection_formats=collection_formats)
|
|
2654
2751
|
|
|
2752
|
+
def update_tag_description(self, body, **kwargs): # noqa: E501
|
|
2753
|
+
"""update_tag_description # noqa: E501
|
|
2754
|
+
|
|
2755
|
+
This method makes a synchronous HTTP request by default. To make an
|
|
2756
|
+
asynchronous HTTP request, please pass async_req=True
|
|
2757
|
+
>>> thread = api.update_tag_description(body, async_req=True)
|
|
2758
|
+
>>> result = thread.get()
|
|
2759
|
+
|
|
2760
|
+
:param async_req bool
|
|
2761
|
+
:param UpdateTagDescriptionRequest body: (required)
|
|
2762
|
+
:return: UpdateTagDescriptionResponse
|
|
2763
|
+
If the method is called asynchronously,
|
|
2764
|
+
returns the request thread.
|
|
2765
|
+
"""
|
|
2766
|
+
kwargs['_return_http_data_only'] = True
|
|
2767
|
+
if kwargs.get('async_req'):
|
|
2768
|
+
return self.update_tag_description_with_http_info(body, **kwargs) # noqa: E501
|
|
2769
|
+
else:
|
|
2770
|
+
(data) = self.update_tag_description_with_http_info(body, **kwargs) # noqa: E501
|
|
2771
|
+
return data
|
|
2772
|
+
|
|
2773
|
+
def update_tag_description_with_http_info(self, body, **kwargs): # noqa: E501
|
|
2774
|
+
"""update_tag_description # noqa: E501
|
|
2775
|
+
|
|
2776
|
+
This method makes a synchronous HTTP request by default. To make an
|
|
2777
|
+
asynchronous HTTP request, please pass async_req=True
|
|
2778
|
+
>>> thread = api.update_tag_description_with_http_info(body, async_req=True)
|
|
2779
|
+
>>> result = thread.get()
|
|
2780
|
+
|
|
2781
|
+
:param async_req bool
|
|
2782
|
+
:param UpdateTagDescriptionRequest body: (required)
|
|
2783
|
+
:return: UpdateTagDescriptionResponse
|
|
2784
|
+
If the method is called asynchronously,
|
|
2785
|
+
returns the request thread.
|
|
2786
|
+
"""
|
|
2787
|
+
|
|
2788
|
+
all_params = ['body'] # noqa: E501
|
|
2789
|
+
all_params.append('async_req')
|
|
2790
|
+
all_params.append('_return_http_data_only')
|
|
2791
|
+
all_params.append('_preload_content')
|
|
2792
|
+
all_params.append('_request_timeout')
|
|
2793
|
+
|
|
2794
|
+
params = locals()
|
|
2795
|
+
for key, val in six.iteritems(params['kwargs']):
|
|
2796
|
+
if key not in all_params:
|
|
2797
|
+
raise TypeError(
|
|
2798
|
+
"Got an unexpected keyword argument '%s'"
|
|
2799
|
+
" to method update_tag_description" % key
|
|
2800
|
+
)
|
|
2801
|
+
params[key] = val
|
|
2802
|
+
del params['kwargs']
|
|
2803
|
+
# verify the required parameter 'body' is set
|
|
2804
|
+
if self.api_client.client_side_validation and ('body' not in params or
|
|
2805
|
+
params['body'] is None): # noqa: E501
|
|
2806
|
+
raise ValueError("Missing the required parameter `body` when calling `update_tag_description`") # noqa: E501
|
|
2807
|
+
|
|
2808
|
+
collection_formats = {}
|
|
2809
|
+
|
|
2810
|
+
path_params = {}
|
|
2811
|
+
|
|
2812
|
+
query_params = []
|
|
2813
|
+
|
|
2814
|
+
header_params = {}
|
|
2815
|
+
|
|
2816
|
+
form_params = []
|
|
2817
|
+
local_var_files = {}
|
|
2818
|
+
|
|
2819
|
+
body_params = None
|
|
2820
|
+
if 'body' in params:
|
|
2821
|
+
body_params = params['body']
|
|
2822
|
+
# HTTP header `Accept`
|
|
2823
|
+
header_params['Accept'] = self.api_client.select_header_accept(
|
|
2824
|
+
['application/json']) # noqa: E501
|
|
2825
|
+
|
|
2826
|
+
# HTTP header `Content-Type`
|
|
2827
|
+
header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501
|
|
2828
|
+
['application/json']) # noqa: E501
|
|
2829
|
+
|
|
2830
|
+
# Authentication setting
|
|
2831
|
+
auth_settings = ['byteplusSign'] # noqa: E501
|
|
2832
|
+
|
|
2833
|
+
return self.api_client.call_api(
|
|
2834
|
+
'/UpdateTagDescription/2022-05-12/cr/post/application_json/', 'POST',
|
|
2835
|
+
path_params,
|
|
2836
|
+
query_params,
|
|
2837
|
+
header_params,
|
|
2838
|
+
body=body_params,
|
|
2839
|
+
post_params=form_params,
|
|
2840
|
+
files=local_var_files,
|
|
2841
|
+
response_type='UpdateTagDescriptionResponse', # noqa: E501
|
|
2842
|
+
auth_settings=auth_settings,
|
|
2843
|
+
async_req=params.get('async_req'),
|
|
2844
|
+
_return_http_data_only=params.get('_return_http_data_only'),
|
|
2845
|
+
_preload_content=params.get('_preload_content', True),
|
|
2846
|
+
_request_timeout=params.get('_request_timeout'),
|
|
2847
|
+
collection_formats=collection_formats)
|
|
2848
|
+
|
|
2655
2849
|
def update_vpc_endpoint(self, body, **kwargs): # noqa: E501
|
|
2656
2850
|
"""update_vpc_endpoint # noqa: E501
|
|
2657
2851
|
|
byteplussdkcr/models/__init__.py
CHANGED
|
@@ -89,12 +89,16 @@ from byteplussdkcr.models.status_for_list_registries_output import StatusForList
|
|
|
89
89
|
from byteplussdkcr.models.success_for_delete_tags_output import SuccessForDeleteTagsOutput
|
|
90
90
|
from byteplussdkcr.models.update_public_endpoint_request import UpdatePublicEndpointRequest
|
|
91
91
|
from byteplussdkcr.models.update_public_endpoint_response import UpdatePublicEndpointResponse
|
|
92
|
+
from byteplussdkcr.models.update_registry_request import UpdateRegistryRequest
|
|
93
|
+
from byteplussdkcr.models.update_registry_response import UpdateRegistryResponse
|
|
92
94
|
from byteplussdkcr.models.update_repository_request import UpdateRepositoryRequest
|
|
93
95
|
from byteplussdkcr.models.update_repository_response import UpdateRepositoryResponse
|
|
94
96
|
from byteplussdkcr.models.update_robot_account_password_request import UpdateRobotAccountPasswordRequest
|
|
95
97
|
from byteplussdkcr.models.update_robot_account_password_response import UpdateRobotAccountPasswordResponse
|
|
96
98
|
from byteplussdkcr.models.update_robot_account_request import UpdateRobotAccountRequest
|
|
97
99
|
from byteplussdkcr.models.update_robot_account_response import UpdateRobotAccountResponse
|
|
100
|
+
from byteplussdkcr.models.update_tag_description_request import UpdateTagDescriptionRequest
|
|
101
|
+
from byteplussdkcr.models.update_tag_description_response import UpdateTagDescriptionResponse
|
|
98
102
|
from byteplussdkcr.models.update_vpc_endpoint_request import UpdateVpcEndpointRequest
|
|
99
103
|
from byteplussdkcr.models.update_vpc_endpoint_response import UpdateVpcEndpointResponse
|
|
100
104
|
from byteplussdkcr.models.vpc_for_get_vpc_endpoint_output import VpcForGetVpcEndpointOutput
|