Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/boto3/session.py: 61%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

102 statements  

1# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"). You 

4# may not use this file except in compliance with the License. A copy of 

5# the License is located at 

6# 

7# https://aws.amazon.com/apache2.0/ 

8# 

9# or in the "license" file accompanying this file. This file is 

10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 

11# ANY KIND, either express or implied. See the License for the specific 

12# language governing permissions and limitations under the License. 

13 

14import copy 

15import os 

16 

17import botocore.session 

18from botocore.client import Config 

19from botocore.exceptions import ( 

20 DataNotFoundError, 

21 NoCredentialsError, 

22 UnknownServiceError, 

23) 

24 

25import boto3 

26import boto3.utils 

27from boto3.exceptions import ResourceNotExistsError, UnknownAPIVersionError 

28 

29from .resources.factory import ResourceFactory 

30 

31 

32class Session: 

33 """ 

34 A session stores configuration state and allows you to create service 

35 clients and resources. 

36 

37 :type aws_access_key_id: string 

38 :param aws_access_key_id: AWS access key ID 

39 :type aws_secret_access_key: string 

40 :param aws_secret_access_key: AWS secret access key 

41 :type aws_session_token: string 

42 :param aws_session_token: AWS temporary session token 

43 :type region_name: string 

44 :param region_name: Default region when creating new connections 

45 :type botocore_session: botocore.session.Session 

46 :param botocore_session: Use this Botocore session instead of creating 

47 a new default one. 

48 :type profile_name: string 

49 :param profile_name: The name of a profile to use. If not given, then 

50 the default profile is used. 

51 :type aws_account_id: string 

52 :param aws_account_id: AWS account ID 

53 """ 

54 

55 def __init__( 

56 self, 

57 aws_access_key_id=None, 

58 aws_secret_access_key=None, 

59 aws_session_token=None, 

60 region_name=None, 

61 botocore_session=None, 

62 profile_name=None, 

63 aws_account_id=None, 

64 ): 

65 if botocore_session is not None: 

66 self._session = botocore_session 

67 else: 

68 # Create a new default session 

69 self._session = botocore.session.get_session() 

70 

71 # Setup custom user-agent string if it isn't already customized 

72 if self._session.user_agent_name == 'Botocore': 

73 botocore_info = f'Botocore/{self._session.user_agent_version}' 

74 if self._session.user_agent_extra: 

75 self._session.user_agent_extra += ' ' + botocore_info 

76 else: 

77 self._session.user_agent_extra = botocore_info 

78 self._session.user_agent_name = 'Boto3' 

79 self._session.user_agent_version = boto3.__version__ 

80 

81 if profile_name is not None: 

82 self._session.set_config_variable('profile', profile_name) 

83 

84 creds = ( 

85 aws_access_key_id, 

86 aws_secret_access_key, 

87 aws_session_token, 

88 aws_account_id, 

89 ) 

90 if any(creds): 

91 if self._account_id_set_without_credentials( 

92 aws_account_id, aws_access_key_id, aws_secret_access_key 

93 ): 

94 raise NoCredentialsError() 

95 self._session.set_credentials( 

96 aws_access_key_id, 

97 aws_secret_access_key, 

98 aws_session_token, 

99 aws_account_id, 

100 ) 

101 

102 if region_name is not None: 

103 self._session.set_config_variable('region', region_name) 

104 

105 self.resource_factory = ResourceFactory( 

106 self._session.get_component('event_emitter') 

107 ) 

108 self._setup_loader() 

109 self._register_default_handlers() 

110 

111 def __repr__(self): 

112 return '{}(region_name={})'.format( 

113 self.__class__.__name__, 

114 repr(self._session.get_config_variable('region')), 

115 ) 

116 

117 @property 

118 def profile_name(self): 

119 """ 

120 The **read-only** profile name. 

121 """ 

122 return self._session.profile or 'default' 

123 

124 @property 

125 def region_name(self): 

126 """ 

127 The **read-only** region name. 

128 """ 

129 return self._session.get_config_variable('region') 

130 

131 @property 

132 def events(self): 

133 """ 

134 The event emitter for a session 

135 """ 

136 return self._session.get_component('event_emitter') 

137 

138 @property 

139 def available_profiles(self): 

140 """ 

141 The profiles available to the session credentials 

142 """ 

143 return self._session.available_profiles 

144 

145 def _setup_loader(self): 

146 """ 

147 Setup loader paths so that we can load resources. 

148 """ 

149 self._loader = self._session.get_component('data_loader') 

150 self._loader.search_paths.append( 

151 os.path.join(os.path.dirname(__file__), 'data') 

152 ) 

153 

154 def get_available_services(self): 

155 """ 

156 Get a list of available services that can be loaded as low-level 

157 clients via :py:meth:`Session.client`. 

158 

159 :rtype: list 

160 :return: List of service names 

161 """ 

162 return self._session.get_available_services() 

163 

164 def get_available_resources(self): 

165 """ 

166 Get a list of available services that can be loaded as resource 

167 clients via :py:meth:`Session.resource`. 

168 

169 :rtype: list 

170 :return: List of service names 

171 """ 

172 return self._loader.list_available_services(type_name='resources-1') 

173 

174 def get_available_partitions(self): 

175 """Lists the available partitions 

176 

177 :rtype: list 

178 :return: Returns a list of partition names (e.g., ["aws", "aws-cn"]) 

179 """ 

180 return self._session.get_available_partitions() 

181 

182 def get_available_regions( 

183 self, service_name, partition_name='aws', allow_non_regional=False 

184 ): 

185 """Lists the region and endpoint names of a particular partition. 

186 

187 The list of regions returned by this method are regions that are 

188 explicitly known by the client to exist and is not comprehensive. A 

189 region not returned in this list may still be available for the 

190 provided service. 

191 

192 :type service_name: string 

193 :param service_name: Name of a service to list endpoint for (e.g., s3). 

194 

195 :type partition_name: string 

196 :param partition_name: Name of the partition to limit endpoints to. 

197 (e.g., aws for the public AWS endpoints, aws-cn for AWS China 

198 endpoints, aws-us-gov for AWS GovCloud (US) Endpoints, etc.) 

199 

200 :type allow_non_regional: bool 

201 :param allow_non_regional: Set to True to include endpoints that are 

202 not regional endpoints (e.g., s3-external-1, 

203 fips-us-gov-west-1, etc). 

204 

205 :return: Returns a list of endpoint names (e.g., ["us-east-1"]). 

206 """ 

207 return self._session.get_available_regions( 

208 service_name=service_name, 

209 partition_name=partition_name, 

210 allow_non_regional=allow_non_regional, 

211 ) 

212 

213 def get_credentials(self): 

214 """ 

215 Return the :class:`botocore.credentials.Credentials` object 

216 associated with this session. If the credentials have not 

217 yet been loaded, this will attempt to load them. If they 

218 have already been loaded, this will return the cached 

219 credentials. 

220 """ 

221 return self._session.get_credentials() 

222 

223 def get_partition_for_region(self, region_name): 

224 """Lists the partition name of a particular region. 

225 

226 :type region_name: string 

227 :param region_name: Name of the region to list partition for (e.g., 

228 us-east-1). 

229 

230 :rtype: string 

231 :return: Returns the respective partition name (e.g., aws). 

232 """ 

233 return self._session.get_partition_for_region(region_name) 

234 

235 def client( 

236 self, 

237 service_name, 

238 region_name=None, 

239 api_version=None, 

240 use_ssl=True, 

241 verify=None, 

242 endpoint_url=None, 

243 aws_access_key_id=None, 

244 aws_secret_access_key=None, 

245 aws_session_token=None, 

246 config=None, 

247 aws_account_id=None, 

248 ): 

249 """ 

250 Create a low-level service client by name. 

251 

252 :type service_name: string 

253 :param service_name: The name of a service, e.g. 's3' or 'ec2'. You 

254 can get a list of available services via 

255 :py:meth:`get_available_services`. 

256 

257 :type region_name: string 

258 :param region_name: The name of the region associated with the client. 

259 A client is associated with a single region. 

260 

261 :type api_version: string 

262 :param api_version: The API version to use. By default, botocore will 

263 use the latest API version when creating a client. You only need 

264 to specify this parameter if you want to use a previous API version 

265 of the client. 

266 

267 :type use_ssl: boolean 

268 :param use_ssl: Whether or not to use SSL. By default, SSL is used. 

269 Note that not all services support non-ssl connections. 

270 

271 :type verify: boolean/string 

272 :param verify: Whether or not to verify SSL certificates. By default 

273 SSL certificates are verified. You can provide the following 

274 values: 

275 

276 * False - do not validate SSL certificates. SSL will still be 

277 used (unless use_ssl is False), but SSL certificates 

278 will not be verified. 

279 * path/to/cert/bundle.pem - A filename of the CA cert bundle to 

280 uses. You can specify this argument if you want to use a 

281 different CA cert bundle than the one used by botocore. 

282 

283 :type endpoint_url: string 

284 :param endpoint_url: The complete URL to use for the constructed 

285 client. Normally, botocore will automatically construct the 

286 appropriate URL to use when communicating with a service. You 

287 can specify a complete URL (including the "http/https" scheme) 

288 to override this behavior. If this value is provided, 

289 then ``use_ssl`` is ignored. 

290 

291 :type aws_access_key_id: string 

292 :param aws_access_key_id: The access key to use when creating 

293 the client. This is entirely optional, and if not provided, 

294 the credentials configured for the session will automatically 

295 be used. You only need to provide this argument if you want 

296 to override the credentials used for this specific client. 

297 

298 :type aws_secret_access_key: string 

299 :param aws_secret_access_key: The secret key to use when creating 

300 the client. Same semantics as aws_access_key_id above. 

301 

302 :type aws_session_token: string 

303 :param aws_session_token: The session token to use when creating 

304 the client. Same semantics as aws_access_key_id above. 

305 

306 :type config: botocore.client.Config 

307 :param config: Advanced client configuration options. If region_name 

308 is specified in the client config, its value will take precedence 

309 over environment variables and configuration values, but not over 

310 a region_name value passed explicitly to the method. See 

311 `botocore config documentation 

312 <https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html>`_ 

313 for more details. 

314 

315 :type aws_account_id: string 

316 :param aws_account_id: The account id to use when creating 

317 the client. Same semantics as aws_access_key_id above. 

318 

319 :return: Service client instance 

320 

321 """ 

322 return self._session.create_client( 

323 service_name, 

324 region_name=region_name, 

325 api_version=api_version, 

326 use_ssl=use_ssl, 

327 verify=verify, 

328 endpoint_url=endpoint_url, 

329 aws_access_key_id=aws_access_key_id, 

330 aws_secret_access_key=aws_secret_access_key, 

331 aws_session_token=aws_session_token, 

332 config=config, 

333 aws_account_id=aws_account_id, 

334 ) 

335 

336 def resource( 

337 self, 

338 service_name, 

339 region_name=None, 

340 api_version=None, 

341 use_ssl=True, 

342 verify=None, 

343 endpoint_url=None, 

344 aws_access_key_id=None, 

345 aws_secret_access_key=None, 

346 aws_session_token=None, 

347 config=None, 

348 ): 

349 """ 

350 Create a resource service client by name. 

351 

352 :type service_name: string 

353 :param service_name: The name of a service, e.g. 's3' or 'ec2'. You 

354 can get a list of available services via 

355 :py:meth:`get_available_resources`. 

356 

357 :type region_name: string 

358 :param region_name: The name of the region associated with the client. 

359 A client is associated with a single region. 

360 

361 :type api_version: string 

362 :param api_version: The API version to use. By default, botocore will 

363 use the latest API version when creating a client. You only need 

364 to specify this parameter if you want to use a previous API version 

365 of the client. 

366 

367 :type use_ssl: boolean 

368 :param use_ssl: Whether or not to use SSL. By default, SSL is used. 

369 Note that not all services support non-ssl connections. 

370 

371 :type verify: boolean/string 

372 :param verify: Whether or not to verify SSL certificates. By default 

373 SSL certificates are verified. You can provide the following 

374 values: 

375 

376 * False - do not validate SSL certificates. SSL will still be 

377 used (unless use_ssl is False), but SSL certificates 

378 will not be verified. 

379 * path/to/cert/bundle.pem - A filename of the CA cert bundle to 

380 uses. You can specify this argument if you want to use a 

381 different CA cert bundle than the one used by botocore. 

382 

383 :type endpoint_url: string 

384 :param endpoint_url: The complete URL to use for the constructed 

385 client. Normally, botocore will automatically construct the 

386 appropriate URL to use when communicating with a service. You 

387 can specify a complete URL (including the "http/https" scheme) 

388 to override this behavior. If this value is provided, 

389 then ``use_ssl`` is ignored. 

390 

391 :type aws_access_key_id: string 

392 :param aws_access_key_id: The access key to use when creating 

393 the client. This is entirely optional, and if not provided, 

394 the credentials configured for the session will automatically 

395 be used. You only need to provide this argument if you want 

396 to override the credentials used for this specific client. 

397 

398 :type aws_secret_access_key: string 

399 :param aws_secret_access_key: The secret key to use when creating 

400 the client. Same semantics as aws_access_key_id above. 

401 

402 :type aws_session_token: string 

403 :param aws_session_token: The session token to use when creating 

404 the client. Same semantics as aws_access_key_id above. 

405 

406 :type config: botocore.client.Config 

407 :param config: Advanced client configuration options. If region_name 

408 is specified in the client config, its value will take precedence 

409 over environment variables and configuration values, but not over 

410 a region_name value passed explicitly to the method. If 

411 user_agent_extra is specified in the client config, it overrides 

412 the default user_agent_extra provided by the resource API. See 

413 `botocore config documentation 

414 <https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html>`_ 

415 for more details. 

416 

417 :return: Subclass of :py:class:`~boto3.resources.base.ServiceResource` 

418 """ 

419 try: 

420 resource_model = self._loader.load_service_model( 

421 service_name, 'resources-1', api_version 

422 ) 

423 except UnknownServiceError: 

424 available = self.get_available_resources() 

425 has_low_level_client = ( 

426 service_name in self.get_available_services() 

427 ) 

428 raise ResourceNotExistsError( 

429 service_name, available, has_low_level_client 

430 ) 

431 except DataNotFoundError: 

432 # This is because we've provided an invalid API version. 

433 available_api_versions = self._loader.list_api_versions( 

434 service_name, 'resources-1' 

435 ) 

436 raise UnknownAPIVersionError( 

437 service_name, api_version, ', '.join(available_api_versions) 

438 ) 

439 

440 if api_version is None: 

441 # Even though botocore's load_service_model() can handle 

442 # using the latest api_version if not provided, we need 

443 # to track this api_version in boto3 in order to ensure 

444 # we're pairing a resource model with a client model 

445 # of the same API version. It's possible for the latest 

446 # API version of a resource model in boto3 to not be 

447 # the same API version as a service model in botocore. 

448 # So we need to look up the api_version if one is not 

449 # provided to ensure we load the same API version of the 

450 # client. 

451 # 

452 # Note: This is relying on the fact that 

453 # loader.load_service_model(..., api_version=None) 

454 # and loader.determine_latest_version(..., 'resources-1') 

455 # both load the same api version of the file. 

456 api_version = self._loader.determine_latest_version( 

457 service_name, 'resources-1' 

458 ) 

459 

460 # Creating a new resource instance requires the low-level client 

461 # and service model, the resource version and resource JSON data. 

462 # We pass these to the factory and get back a class, which is 

463 # instantiated on top of the low-level client. 

464 if config is not None: 

465 if config.user_agent_extra is None: 

466 config = copy.deepcopy(config) 

467 config.user_agent_extra = 'Resource' 

468 else: 

469 config = Config(user_agent_extra='Resource') 

470 client = self.client( 

471 service_name, 

472 region_name=region_name, 

473 api_version=api_version, 

474 use_ssl=use_ssl, 

475 verify=verify, 

476 endpoint_url=endpoint_url, 

477 aws_access_key_id=aws_access_key_id, 

478 aws_secret_access_key=aws_secret_access_key, 

479 aws_session_token=aws_session_token, 

480 config=config, 

481 ) 

482 service_model = client.meta.service_model 

483 

484 # Create a ServiceContext object to serve as a reference to 

485 # important read-only information about the general service. 

486 service_context = boto3.utils.ServiceContext( 

487 service_name=service_name, 

488 service_model=service_model, 

489 resource_json_definitions=resource_model['resources'], 

490 service_waiter_model=boto3.utils.LazyLoadedWaiterModel( 

491 self._session, service_name, api_version 

492 ), 

493 ) 

494 

495 # Create the service resource class. 

496 cls = self.resource_factory.load_from_definition( 

497 resource_name=service_name, 

498 single_resource_json_definition=resource_model['service'], 

499 service_context=service_context, 

500 ) 

501 

502 return cls(client=client) 

503 

504 def _register_default_handlers(self): 

505 # S3 customizations 

506 self._session.register( 

507 'creating-client-class.s3', 

508 boto3.utils.lazy_call( 

509 'boto3.s3.inject.inject_s3_transfer_methods' 

510 ), 

511 ) 

512 self._session.register( 

513 'creating-resource-class.s3.Bucket', 

514 boto3.utils.lazy_call('boto3.s3.inject.inject_bucket_methods'), 

515 ) 

516 self._session.register( 

517 'creating-resource-class.s3.Object', 

518 boto3.utils.lazy_call('boto3.s3.inject.inject_object_methods'), 

519 ) 

520 self._session.register( 

521 'creating-resource-class.s3.ObjectSummary', 

522 boto3.utils.lazy_call( 

523 'boto3.s3.inject.inject_object_summary_methods' 

524 ), 

525 ) 

526 

527 # DynamoDb customizations 

528 self._session.register( 

529 'creating-resource-class.dynamodb', 

530 boto3.utils.lazy_call( 

531 'boto3.dynamodb.transform.register_high_level_interface' 

532 ), 

533 unique_id='high-level-dynamodb', 

534 ) 

535 self._session.register( 

536 'creating-resource-class.dynamodb.Table', 

537 boto3.utils.lazy_call( 

538 'boto3.dynamodb.table.register_table_methods' 

539 ), 

540 unique_id='high-level-dynamodb-table', 

541 ) 

542 

543 # EC2 Customizations 

544 self._session.register( 

545 'creating-resource-class.ec2.ServiceResource', 

546 boto3.utils.lazy_call('boto3.ec2.createtags.inject_create_tags'), 

547 ) 

548 

549 self._session.register( 

550 'creating-resource-class.ec2.Instance', 

551 boto3.utils.lazy_call( 

552 'boto3.ec2.deletetags.inject_delete_tags', 

553 event_emitter=self.events, 

554 ), 

555 ) 

556 

557 def _account_id_set_without_credentials( 

558 self, account_id, access_key, secret_key 

559 ): 

560 if account_id is None: 

561 return False 

562 elif access_key is None or secret_key is None: 

563 return True 

564 return False