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.
Files changed (75) hide show
  1. {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/METADATA +1 -1
  2. {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/RECORD +75 -52
  3. byteplussdkcore/api_client.py +36 -8
  4. byteplussdkcore/auth/provider_binding.py +42 -0
  5. byteplussdkcore/auth/providers/sts_oidc_provider.py +23 -3
  6. byteplussdkcore/auth/providers/sts_provider.py +32 -3
  7. byteplussdkcore/auth/providers/sts_saml_provider.py +23 -3
  8. byteplussdkcore/auth/sts_http_config.py +133 -0
  9. byteplussdkcore/configuration.py +1 -1
  10. byteplussdkcore/feature/rds/connect_utils.py +6 -8
  11. byteplussdkcore/interceptor/interceptors/request.py +5 -0
  12. byteplussdkcore/rest.py +27 -0
  13. byteplussdkcore/retryer/retry_condition.py +29 -1
  14. byteplussdkcr/__init__.py +4 -0
  15. byteplussdkcr/api/cr_api.py +194 -0
  16. byteplussdkcr/models/__init__.py +4 -0
  17. byteplussdkcr/models/create_namespace_request.py +55 -3
  18. byteplussdkcr/models/create_registry_response.py +29 -1
  19. byteplussdkcr/models/filter_for_list_registries_input.py +27 -1
  20. byteplussdkcr/models/get_authorization_token_request.py +27 -1
  21. byteplussdkcr/models/proxy_cache_for_list_registries_output.py +81 -3
  22. byteplussdkcr/models/update_public_endpoint_request.py +27 -1
  23. byteplussdkcr/models/update_registry_request.py +176 -0
  24. byteplussdkcr/models/update_registry_response.py +95 -0
  25. byteplussdkcr/models/update_tag_description_request.py +244 -0
  26. byteplussdkcr/models/update_tag_description_response.py +95 -0
  27. byteplussdkcr/models/vpc_for_update_vpc_endpoint_input.py +27 -1
  28. byteplussdkvpc/__init__.py +17 -0
  29. byteplussdkvpc/api/vpc_api.py +582 -0
  30. byteplussdkvpc/models/__init__.py +17 -0
  31. byteplussdkvpc/models/authorize_security_group_egress_batch_request.py +150 -0
  32. byteplussdkvpc/models/authorize_security_group_egress_batch_response.py +149 -0
  33. byteplussdkvpc/models/authorize_security_group_ingress_batch_request.py +150 -0
  34. byteplussdkvpc/models/authorize_security_group_ingress_batch_response.py +149 -0
  35. byteplussdkvpc/models/create_flow_log_request.py +27 -1
  36. byteplussdkvpc/models/create_flow_log_response.py +29 -3
  37. byteplussdkvpc/models/create_ipam_pool_request.py +2 -5
  38. byteplussdkvpc/models/create_ipam_request.py +0 -3
  39. byteplussdkvpc/models/create_ipam_resource_discovery_request.py +9 -0
  40. byteplussdkvpc/models/create_ipam_scope_request.py +2 -5
  41. byteplussdkvpc/models/create_network_interface_request.py +81 -3
  42. byteplussdkvpc/models/describe_ipam_pools_request.py +6 -0
  43. byteplussdkvpc/models/describe_ipam_resource_cidrs_request.py +27 -1
  44. byteplussdkvpc/models/describe_ipam_resource_discoveries_request.py +6 -0
  45. byteplussdkvpc/models/describe_ipam_scopes_request.py +6 -0
  46. byteplussdkvpc/models/describe_ipams_request.py +2 -2
  47. byteplussdkvpc/models/describe_network_interface_attributes_response.py +79 -1
  48. byteplussdkvpc/models/ipam_resource_cidr_for_describe_ipam_resource_cidrs_output.py +53 -1
  49. byteplussdkvpc/models/modify_flow_log_attribute_request.py +27 -1
  50. byteplussdkvpc/models/modify_flow_log_attribute_response.py +29 -3
  51. byteplussdkvpc/models/modify_ipam_pool_request.py +2 -5
  52. byteplussdkvpc/models/modify_ipam_request.py +2 -5
  53. byteplussdkvpc/models/modify_ipam_resource_discovery_request.py +61 -6
  54. byteplussdkvpc/models/modify_ipam_resource_discovery_response.py +27 -1
  55. byteplussdkvpc/models/modify_ipam_scope_request.py +2 -5
  56. byteplussdkvpc/models/modify_network_interface_attributes_request.py +81 -3
  57. byteplussdkvpc/models/modify_security_group_egress_batch_request.py +150 -0
  58. byteplussdkvpc/models/modify_security_group_egress_batch_response.py +149 -0
  59. byteplussdkvpc/models/modify_security_group_ingress_batch_request.py +150 -0
  60. byteplussdkvpc/models/modify_security_group_ingress_batch_response.py +149 -0
  61. byteplussdkvpc/models/network_interface_set_for_describe_network_interfaces_output.py +79 -1
  62. byteplussdkvpc/models/overlap_detail_for_describe_ipam_resource_cidrs_output.py +175 -0
  63. byteplussdkvpc/models/permission_for_authorize_security_group_egress_batch_input.py +412 -0
  64. byteplussdkvpc/models/permission_for_authorize_security_group_ingress_batch_input.py +412 -0
  65. byteplussdkvpc/models/permission_for_describe_security_group_attributes_output.py +27 -1
  66. byteplussdkvpc/models/permission_for_modify_security_group_egress_batch_input.py +439 -0
  67. byteplussdkvpc/models/permission_for_modify_security_group_ingress_batch_input.py +439 -0
  68. byteplussdkvpc/models/revoke_security_group_egress_batch_request.py +150 -0
  69. byteplussdkvpc/models/revoke_security_group_egress_batch_response.py +149 -0
  70. byteplussdkvpc/models/revoke_security_group_ingress_batch_request.py +150 -0
  71. byteplussdkvpc/models/revoke_security_group_ingress_batch_response.py +149 -0
  72. {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/WHEEL +0 -0
  73. {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/licenses/LICENSE.txt +0 -0
  74. {byteplus_python_sdk_v2-3.0.60.dist-info → byteplus_python_sdk_v2-3.0.62.dist-info}/licenses/NOTICE.md +0 -0
  75. {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, Configuration
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
- configuration = type.__call__(Configuration)
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, Configuration
121
- resp_result = ApiClient(Configuration())._sts_call(
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")
@@ -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.60".\
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, SignRequestInterceptor, \
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 = Request(configuration,
62
- resource_path='/{}/{}/{}/get/text_plain/'.format(DEFAULT_API, DEFAULT_API_VERSION,
63
- DEFAULT_SERVICE),
64
- method='GET',
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(SignRequestInterceptor())
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 isinstance(err, self.__retry_exceptions):
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
@@ -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
 
@@ -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