1515import time
1616from alibabacloud .handlers import RequestContext
1717from alibabacloud .handlers .prepare_handler import PrepareHandler
18+ from alibabacloud .handlers .credentials_handler import CredentialsHandler
1819from alibabacloud .handlers .signer_handler import SignerHandler
19- from alibabacloud .handlers .url_handler import URLHandler
20- from alibabacloud .handlers .http_header_handler import HttpHeaderHandler
20+
2121from alibabacloud .handlers .timeout_config_reader import TimeoutConfigReader
2222from alibabacloud .handlers .endpoint_handler import EndpointHandler
2323from alibabacloud .handlers .log_handler import LogHandler
2424from alibabacloud .handlers .retry_handler import RetryHandler
2525from alibabacloud .handlers .server_error_handler import ServerErrorHandler
2626from alibabacloud .handlers .http_handler import HttpHandler
27- from alibabacloud .credentials .credentials_provider import DefaultCredentialsProvider
27+
28+ from alibabacloud .credentials .provider import DefaultChainedCredentialsProvider
29+
2830from alibabacloud .endpoint .default_endpoint_resolver import DefaultEndpointResolver
31+
2932DEFAULT_HANDLERS = [
3033 PrepareHandler ,
31- SignerHandler , # 获取Signature
32- URLHandler , # 获取url
33- HttpHeaderHandler , # 获取签名的header
34+ CredentialsHandler ,
35+ SignerHandler , # 获取Signature,header,params
36+ # HttpHeaderHandler, # 获取签名的header
3437 TimeoutConfigReader , # 获取timeout
3538 EndpointHandler , # 获取endpoint
3639 LogHandler ,
@@ -53,19 +56,26 @@ class ClientConfig:
5356 处理client级别的所有的参数
5457 """
5558
59+ ENV_NAME_FOR_CONFIG_FILE = 'ALIBABA_CLOUD_CONFIG_FILE'
60+ DEFAULT_NAME_FOR_CONFIG_FILE = '~/.alibabacloud/config'
61+
5662 def __init__ (self , access_key_id = None , access_key_secret = None , bearer_token = None ,
5763 secret_token = None , region_id = None ,
58- enable_retry_policy = None , max_retry_times = None , user_agent = None ,
64+ max_retry_times = None , user_agent = None ,
5965 extra_user_agent = None , enable_https = None , http_port = None , https_port = None ,
6066 connection_timeout = None , read_timeout = None , enable_http_debug = None ,
6167 http_proxy = None , https_proxy = None , enable_stream_logger = None ,
62- profile_name = None , config_file = None , auto_retry = True ):
68+ profile_name = None , config_file = None , enable_retry = True , endpoint = None ):
69+
6370 # credentials部分会用到
6471 self .access_key_id = access_key_id
6572 self .access_key_secret = access_key_secret
6673 self .secret_token = secret_token
6774 self .bearer_token = bearer_token
6875 self .region_id = region_id
76+ self .enable_retry = enable_retry
77+ self .max_retry_times = max_retry_times
78+ self .endpoint = endpoint
6979
7080 # user-agent
7181 self .user_agent = user_agent
@@ -81,62 +91,45 @@ def __init__(self, access_key_id=None, access_key_secret=None, bearer_token=None
8191 self .enable_stream_logger = enable_stream_logger
8292 # credentials 的profile
8393 self .profile_name = profile_name
94+ # 读取配置文件
8495 self .config_file = config_file
85- # self.enable_http_debug = enable_http_debug # http-debug 只从环境变量获取,不设置开关
86- self .http_debug = None
96+ self .enable_http_debug = enable_http_debug # http-debug 只从环境变量获取,不设置开关
8797 # proxy provider两个: client env
8898 self .http_proxy = http_proxy
8999 self .https_proxy = https_proxy
90100 self ._proxy = {
91101 'http' : self .http_proxy ,
92102 'https' : self .https_proxy ,
93103 }
94- # retry
95- self ._auto_retry = auto_retry
96- import aliyunsdkcore .retry .retry_policy as retry_policy
97- # retry
98- self .enable_retry_policy = enable_retry_policy
99- self .max_retry_times = max_retry_times
100- if self ._auto_retry :
101- self .retry_policy = retry_policy .get_default_retry_policy (
102- max_retry_times = self .max_retry_times )
103- else :
104- self .retry_policy = retry_policy .NO_RETRY_POLICY
105104
106105 def read_from_env (self ):
107106 # 从环境变量读取一定量的数据
108- env_vars = ['HTTP_DEBUG' , ' HTTPS_PROXY' , 'HTTP_PROXY' ]
107+ env_vars = ['HTTPS_PROXY' , 'HTTP_PROXY' ]
109108 for item in env_vars :
110109 if getattr (self , item .lower ()) is None :
111110 setattr (self , item .lower (), os .environ .get (item ) or os .environ .get (item .lower ()))
112111
112+ self .enable_http_debug = os .environ .get ('DEBUG' )
113+
113114 def read_from_profile (self ):
114- ENV_NAME_FOR_CONFIG_FILE = 'ALIBABA_CLOUD_CONFIG_FILE'
115- DEFAULT_NAME_FOR_CONFIG_FILE = ['/etc/.alibabacloud/config' ,
116- '~/alibabacloud/config' ]
115+ profile = {}
117116 # TODO read from profile
118117 from alibabacloud .utils .ini_helper import load_config
119- profile = {}
120- loaded_config = {}
121118 if self .config_file is None :
122- if ENV_NAME_FOR_CONFIG_FILE in os .environ :
123-
124- env_config_file_path = os .environ .get (ENV_NAME_FOR_CONFIG_FILE )
125- if env_config_file_path is None or len (env_config_file_path ) == 0 :
119+ # 没有指定file
120+ if self .ENV_NAME_FOR_CONFIG_FILE in os .environ :
121+
122+ env_config_file_path = os .environ .get (self .ENV_NAME_FOR_CONFIG_FILE )
123+ if env_config_file_path is not None :
124+ full_path = os .path .expanduser (env_config_file_path )
125+ loaded_config = load_config (full_path )
126+ profile = loaded_config .get (self .profile_name , {})
127+ else :
126128 # 默认配置不存在
127- return None
128- full_path = os .path .expanduser (env_config_file_path )
129- loaded_config = load_config (full_path )
130- profile = loaded_config .get (self .profile_name , {})
131- else :
132- potential_locations = DEFAULT_NAME_FOR_CONFIG_FILE
133- for filename in potential_locations :
134- try :
135- loaded_config = load_config (filename )
136- break
137- except Exception :
138- continue
139- profile = loaded_config .get (self .profile_name , {})
129+ filename = self .DEFAULT_NAME_FOR_CONFIG_FILE
130+ loaded_config = load_config (filename )
131+ profile = loaded_config .get (self .profile_name , {})
132+
140133 else :
141134 profile = load_config (self .config_file )
142135
@@ -151,80 +144,101 @@ def read_from_default(self):
151144 # 用户实例化的时候,就进行了覆盖
152145 pass
153146
147+ def _update_config (self , new_config ):
148+ # request 的config 更新client的config
149+ request_settings = ['enable_https' , 'connection_timeout' , 'read_timeout' ]
150+ for attr in request_settings :
151+ setattr (self , attr , getattr (new_config , attr ))
152+
154153
155154def get_merged_client_config (config ):
156- # config.read_from_env()
157- # config.read_from_profile()
155+ config .read_from_env ()
156+ config .read_from_profile ()
158157 # config.read_from_default()
158+
159159 return config
160160
161161
162162class AlibabaCloudClient :
163163
164- def __init__ (self , client_config , credentials_provider = DefaultCredentialsProvider ):
164+ def __init__ (self , client_config , credentials_provider ):
165165 self .config = get_merged_client_config (client_config )
166- self .credentials_provider = DefaultCredentialsProvider
166+
167+ if credentials_provider is not None :
168+ self .credentials_provider = credentials_provider
169+ else :
170+ self .credentials_provider = DefaultChainedCredentialsProvider ()
167171 self .handlers = DEFAULT_HANDLERS
168172 self .logger = None # TODO initialize
169173 # endpoint_resolver阶段需要
170174 self .endpoint_resolver = DefaultEndpointResolver (self ) # TODO initialize
171- # self.product_code = None
172- # self.location_service_code = None
173- # self.location_service_type = None
174- # self.location_endpoint_type = None
175-
176- def handle_request (self , api_request , request_handlers = None , context = None ):
177- # TODO handle different types of request
178- from aliyunsdkcore .request import CommonRequest
179- if isinstance (api_request , CommonRequest ):
180- api_request .trans_to_acs_request ()
181-
182- if not context :
183- context = RequestContext ()
184- context .api_request = api_request
185- from .request import HTTPRequest
186- context .http_request = HTTPRequest ()
175+ # TODO product_code 如何获取
176+ self .product_code = None
177+ self .location_service_code = None
178+ self .location_service_type = None
179+ self .location_endpoint_type = None
180+
181+ import aliyunsdkcore .retry .retry_policy as retry_policy
182+ # retry
183+ if self .config .enable_retry :
184+ self .retry_policy = retry_policy .get_default_retry_policy (
185+ max_retry_times = self .config .max_retry_times )
186+ else :
187+ self .retry_policy = retry_policy .NO_RETRY_POLICY
188+
189+ def _handle_request (self , api_request , _config = None , _raise_exception = True ):
190+ context = RequestContext ()
191+ context .api_request = api_request
192+ from .request import HTTPRequest
193+ context .http_request = HTTPRequest ()
194+ if _config :
195+ # For backward compatibility
196+ context .config = _config
197+ else :
187198 context .config = self .config
188- context .credentials_provider = self .credentials_provider
189- context .product_code = api_request .get_product ()
190- context .location_service_code = api_request .get_location_service_code ()
191- context .location_endpoint_type = api_request .get_location_endpoint_type ()
192- context .endpoint_resolver = self .endpoint_resolver
193- # credentials 是和请求解耦的,从请求的流程来看,不应该放在handle当中
194- context .credentials = self .get_credentials ()
195-
196- if not request_handlers :
197- request_handlers = self .handlers
198- for i in range (len (request_handlers )):
199- request_handlers [i ]().handle_request (context )
200-
201- for i in reversed (range (len (request_handlers ))):
202- request_handlers [i ]().handle_response (context )
203- if context .retry_flag :
204- time .sleep (context .retry_backoff / 1000.0 )
205- self .handle_request (api_request ,
206- request_handlers = request_handlers [i :],
207- context = context )
208- if context .exception :
209- return context .exception
210-
211- return context .http_response .content
212-
213- def get_credentials (self ):
214- credentials_provider = self .credentials_provider ({
215- 'access_key_id' : self .config .access_key_id ,
216- 'access_key_secret' : self .config .access_key_secret ,
217- 'secret_token' : self .config .secret_token ,
218- 'bearer_token' : self .config .bearer_token ,
219- 'profile_name' : 'client5'
220- })
221- credentials = credentials_provider .load_credentials ()
222- if credentials is None :
223- from aliyunsdkcore .acs_exception .exceptions import ClientException
224- raise ClientException (
225- 'Credentials' ,
226- 'Unable to locate credentials.'
227- )
228- return credentials
199+ context .client = self
200+
201+ handler_index = 0
202+
203+ while True :
204+
205+ for i in range (len (self .handlers [handler_index :])):
206+ self .handlers [i ]().handle_request (context )
207+
208+ for i in reversed (range (len (self .handlers [handler_index :]))):
209+ self .handlers [i ]().handle_response (context )
210+ if context .retry_flag :
211+ time .sleep (context .retry_backoff )
212+ handler_index = i
213+ context .retry_flag = False
214+ continue
215+
216+ break
217+
218+ if context .exception and _raise_exception :
219+ raise context .exception
220+
221+ return context
222+
223+
224+ class ECSClient (AlibabaCloudClient ):
225+
226+ def __init__ (self ):
227+ self .product = 'Ecs'
228+ self .location_service_code = 'ecs'
229+ self .location_endpoint_type = 'OpenAPI'
230+
231+ def create_instance (self , ** params ):
232+ api_request = APIRequest (** params )
233+ return self ._handle_request (api_request ).result
234+
235+ def delete_instance (self , ** params ):
236+ api_request = APIRequest (** params )
237+ return self ._handle_request (api_request ).result
238+
229239
240+ class OTSClient (AlibabaCloudClient ):
230241
242+ def create_table (self , ** params ):
243+ api_request = APIRequest (** params )
244+ return self ._handle_request (api_request ).result
0 commit comments