Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/boto3/session.py: 60%
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
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
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.
14import copy
15import os
17import botocore.session
18from botocore.client import Config
19from botocore.exceptions import (
20 DataNotFoundError,
21 NoCredentialsError,
22 UnknownServiceError,
23)
25import boto3
26import boto3.utils
27from boto3.exceptions import ResourceNotExistsError, UnknownAPIVersionError
29from .resources.factory import ResourceFactory
32class Session:
33 """
34 A session stores configuration state and allows you to create service
35 clients and resources.
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 """
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()
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__
81 if profile_name is not None:
82 self._session.set_config_variable('profile', profile_name)
84 credentials_kwargs = {
85 "aws_access_key_id": aws_access_key_id,
86 "aws_secret_access_key": aws_secret_access_key,
87 "aws_session_token": aws_session_token,
88 "aws_account_id": aws_account_id,
89 }
91 if any(credentials_kwargs.values()):
92 if self._account_id_set_without_credentials(**credentials_kwargs):
93 raise NoCredentialsError()
95 if aws_account_id is None:
96 del credentials_kwargs["aws_account_id"]
98 self._session.set_credentials(*credentials_kwargs.values())
100 if region_name is not None:
101 self._session.set_config_variable('region', region_name)
103 self.resource_factory = ResourceFactory(
104 self._session.get_component('event_emitter')
105 )
106 self._setup_loader()
107 self._register_default_handlers()
109 def __repr__(self):
110 return '{}(region_name={})'.format(
111 self.__class__.__name__,
112 repr(self._session.get_config_variable('region')),
113 )
115 @property
116 def profile_name(self):
117 """
118 The **read-only** profile name.
119 """
120 return self._session.profile or 'default'
122 @property
123 def region_name(self):
124 """
125 The **read-only** region name.
126 """
127 return self._session.get_config_variable('region')
129 @property
130 def events(self):
131 """
132 The event emitter for a session
133 """
134 return self._session.get_component('event_emitter')
136 @property
137 def available_profiles(self):
138 """
139 The profiles available to the session credentials
140 """
141 return self._session.available_profiles
143 def _setup_loader(self):
144 """
145 Setup loader paths so that we can load resources.
146 """
147 self._loader = self._session.get_component('data_loader')
148 self._loader.search_paths.append(
149 os.path.join(os.path.dirname(__file__), 'data')
150 )
152 def get_available_services(self):
153 """
154 Get a list of available services that can be loaded as low-level
155 clients via :py:meth:`Session.client`.
157 :rtype: list
158 :return: List of service names
159 """
160 return self._session.get_available_services()
162 def get_available_resources(self):
163 """
164 Get a list of available services that can be loaded as resource
165 clients via :py:meth:`Session.resource`.
167 :rtype: list
168 :return: List of service names
169 """
170 return self._loader.list_available_services(type_name='resources-1')
172 def get_available_partitions(self):
173 """Lists the available partitions
175 :rtype: list
176 :return: Returns a list of partition names (e.g., ["aws", "aws-cn"])
177 """
178 return self._session.get_available_partitions()
180 def get_available_regions(
181 self, service_name, partition_name='aws', allow_non_regional=False
182 ):
183 """Lists the region and endpoint names of a particular partition.
185 The list of regions returned by this method are regions that are
186 explicitly known by the client to exist and is not comprehensive. A
187 region not returned in this list may still be available for the
188 provided service.
190 :type service_name: string
191 :param service_name: Name of a service to list endpoint for (e.g., s3).
193 :type partition_name: string
194 :param partition_name: Name of the partition to limit endpoints to.
195 (e.g., aws for the public AWS endpoints, aws-cn for AWS China
196 endpoints, aws-us-gov for AWS GovCloud (US) Endpoints, etc.)
198 :type allow_non_regional: bool
199 :param allow_non_regional: Set to True to include endpoints that are
200 not regional endpoints (e.g., s3-external-1,
201 fips-us-gov-west-1, etc).
203 :return: Returns a list of endpoint names (e.g., ["us-east-1"]).
204 """
205 return self._session.get_available_regions(
206 service_name=service_name,
207 partition_name=partition_name,
208 allow_non_regional=allow_non_regional,
209 )
211 def get_credentials(self):
212 """
213 Return the :class:`botocore.credentials.Credentials` object
214 associated with this session. If the credentials have not
215 yet been loaded, this will attempt to load them. If they
216 have already been loaded, this will return the cached
217 credentials.
218 """
219 return self._session.get_credentials()
221 def get_partition_for_region(self, region_name):
222 """Lists the partition name of a particular region.
224 :type region_name: string
225 :param region_name: Name of the region to list partition for (e.g.,
226 us-east-1).
228 :rtype: string
229 :return: Returns the respective partition name (e.g., aws).
230 """
231 return self._session.get_partition_for_region(region_name)
233 def client(
234 self,
235 service_name,
236 region_name=None,
237 api_version=None,
238 use_ssl=True,
239 verify=None,
240 endpoint_url=None,
241 aws_access_key_id=None,
242 aws_secret_access_key=None,
243 aws_session_token=None,
244 config=None,
245 aws_account_id=None,
246 ):
247 """
248 Create a low-level service client by name.
250 :type service_name: string
251 :param service_name: The name of a service, e.g. 's3' or 'ec2'. You
252 can get a list of available services via
253 :py:meth:`get_available_services`.
255 :type region_name: string
256 :param region_name: The name of the region associated with the client.
257 A client is associated with a single region.
259 :type api_version: string
260 :param api_version: The API version to use. By default, botocore will
261 use the latest API version when creating a client. You only need
262 to specify this parameter if you want to use a previous API version
263 of the client.
265 :type use_ssl: boolean
266 :param use_ssl: Whether or not to use SSL. By default, SSL is used.
267 Note that not all services support non-ssl connections.
269 :type verify: boolean/string
270 :param verify: Whether or not to verify SSL certificates. By default
271 SSL certificates are verified. You can provide the following
272 values:
274 * False - do not validate SSL certificates. SSL will still be
275 used (unless use_ssl is False), but SSL certificates
276 will not be verified.
277 * path/to/cert/bundle.pem - A filename of the CA cert bundle to
278 uses. You can specify this argument if you want to use a
279 different CA cert bundle than the one used by botocore.
281 :type endpoint_url: string
282 :param endpoint_url: The complete URL to use for the constructed
283 client. Normally, botocore will automatically construct the
284 appropriate URL to use when communicating with a service. You
285 can specify a complete URL (including the "http/https" scheme)
286 to override this behavior. If this value is provided,
287 then ``use_ssl`` is ignored.
289 :type aws_access_key_id: string
290 :param aws_access_key_id: The access key to use when creating
291 the client. This is entirely optional, and if not provided,
292 the credentials configured for the session will automatically
293 be used. You only need to provide this argument if you want
294 to override the credentials used for this specific client.
296 :type aws_secret_access_key: string
297 :param aws_secret_access_key: The secret key to use when creating
298 the client. Same semantics as aws_access_key_id above.
300 :type aws_session_token: string
301 :param aws_session_token: The session token to use when creating
302 the client. Same semantics as aws_access_key_id above.
304 :type config: botocore.client.Config
305 :param config: Advanced client configuration options. If region_name
306 is specified in the client config, its value will take precedence
307 over environment variables and configuration values, but not over
308 a region_name value passed explicitly to the method. See
309 `botocore config documentation
310 <https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html>`_
311 for more details.
313 :type aws_account_id: string
314 :param aws_account_id: The account id to use when creating
315 the client. Same semantics as aws_access_key_id above.
317 :return: Service client instance
319 """
320 create_client_kwargs = {
321 'region_name': region_name,
322 'api_version': api_version,
323 'use_ssl': use_ssl,
324 'verify': verify,
325 'endpoint_url': endpoint_url,
326 'aws_access_key_id': aws_access_key_id,
327 'aws_secret_access_key': aws_secret_access_key,
328 'aws_session_token': aws_session_token,
329 'config': config,
330 'aws_account_id': aws_account_id,
331 }
332 if aws_account_id is None:
333 # Remove aws_account_id for arbitrary
334 # botocore version mismatches in AWS Lambda.
335 del create_client_kwargs['aws_account_id']
337 return self._session.create_client(
338 service_name, **create_client_kwargs
339 )
341 def resource(
342 self,
343 service_name,
344 region_name=None,
345 api_version=None,
346 use_ssl=True,
347 verify=None,
348 endpoint_url=None,
349 aws_access_key_id=None,
350 aws_secret_access_key=None,
351 aws_session_token=None,
352 config=None,
353 ):
354 """
355 Create a resource service client by name.
357 :type service_name: string
358 :param service_name: The name of a service, e.g. 's3' or 'ec2'. You
359 can get a list of available services via
360 :py:meth:`get_available_resources`.
362 :type region_name: string
363 :param region_name: The name of the region associated with the client.
364 A client is associated with a single region.
366 :type api_version: string
367 :param api_version: The API version to use. By default, botocore will
368 use the latest API version when creating a client. You only need
369 to specify this parameter if you want to use a previous API version
370 of the client.
372 :type use_ssl: boolean
373 :param use_ssl: Whether or not to use SSL. By default, SSL is used.
374 Note that not all services support non-ssl connections.
376 :type verify: boolean/string
377 :param verify: Whether or not to verify SSL certificates. By default
378 SSL certificates are verified. You can provide the following
379 values:
381 * False - do not validate SSL certificates. SSL will still be
382 used (unless use_ssl is False), but SSL certificates
383 will not be verified.
384 * path/to/cert/bundle.pem - A filename of the CA cert bundle to
385 uses. You can specify this argument if you want to use a
386 different CA cert bundle than the one used by botocore.
388 :type endpoint_url: string
389 :param endpoint_url: The complete URL to use for the constructed
390 client. Normally, botocore will automatically construct the
391 appropriate URL to use when communicating with a service. You
392 can specify a complete URL (including the "http/https" scheme)
393 to override this behavior. If this value is provided,
394 then ``use_ssl`` is ignored.
396 :type aws_access_key_id: string
397 :param aws_access_key_id: The access key to use when creating
398 the client. This is entirely optional, and if not provided,
399 the credentials configured for the session will automatically
400 be used. You only need to provide this argument if you want
401 to override the credentials used for this specific client.
403 :type aws_secret_access_key: string
404 :param aws_secret_access_key: The secret key to use when creating
405 the client. Same semantics as aws_access_key_id above.
407 :type aws_session_token: string
408 :param aws_session_token: The session token to use when creating
409 the client. Same semantics as aws_access_key_id above.
411 :type config: botocore.client.Config
412 :param config: Advanced client configuration options. If region_name
413 is specified in the client config, its value will take precedence
414 over environment variables and configuration values, but not over
415 a region_name value passed explicitly to the method. If
416 user_agent_extra is specified in the client config, it overrides
417 the default user_agent_extra provided by the resource API. See
418 `botocore config documentation
419 <https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html>`_
420 for more details.
422 :return: Subclass of :py:class:`~boto3.resources.base.ServiceResource`
423 """
424 try:
425 resource_model = self._loader.load_service_model(
426 service_name, 'resources-1', api_version
427 )
428 except UnknownServiceError:
429 available = self.get_available_resources()
430 has_low_level_client = (
431 service_name in self.get_available_services()
432 )
433 raise ResourceNotExistsError(
434 service_name, available, has_low_level_client
435 )
436 except DataNotFoundError:
437 # This is because we've provided an invalid API version.
438 available_api_versions = self._loader.list_api_versions(
439 service_name, 'resources-1'
440 )
441 raise UnknownAPIVersionError(
442 service_name, api_version, ', '.join(available_api_versions)
443 )
445 if api_version is None:
446 # Even though botocore's load_service_model() can handle
447 # using the latest api_version if not provided, we need
448 # to track this api_version in boto3 in order to ensure
449 # we're pairing a resource model with a client model
450 # of the same API version. It's possible for the latest
451 # API version of a resource model in boto3 to not be
452 # the same API version as a service model in botocore.
453 # So we need to look up the api_version if one is not
454 # provided to ensure we load the same API version of the
455 # client.
456 #
457 # Note: This is relying on the fact that
458 # loader.load_service_model(..., api_version=None)
459 # and loader.determine_latest_version(..., 'resources-1')
460 # both load the same api version of the file.
461 api_version = self._loader.determine_latest_version(
462 service_name, 'resources-1'
463 )
465 # Creating a new resource instance requires the low-level client
466 # and service model, the resource version and resource JSON data.
467 # We pass these to the factory and get back a class, which is
468 # instantiated on top of the low-level client.
469 if config is not None:
470 if config.user_agent_extra is None:
471 config = copy.deepcopy(config)
472 config.user_agent_extra = 'Resource'
473 else:
474 config = Config(user_agent_extra='Resource')
475 client = self.client(
476 service_name,
477 region_name=region_name,
478 api_version=api_version,
479 use_ssl=use_ssl,
480 verify=verify,
481 endpoint_url=endpoint_url,
482 aws_access_key_id=aws_access_key_id,
483 aws_secret_access_key=aws_secret_access_key,
484 aws_session_token=aws_session_token,
485 config=config,
486 )
487 service_model = client.meta.service_model
489 # Create a ServiceContext object to serve as a reference to
490 # important read-only information about the general service.
491 service_context = boto3.utils.ServiceContext(
492 service_name=service_name,
493 service_model=service_model,
494 resource_json_definitions=resource_model['resources'],
495 service_waiter_model=boto3.utils.LazyLoadedWaiterModel(
496 self._session, service_name, api_version
497 ),
498 )
500 # Create the service resource class.
501 cls = self.resource_factory.load_from_definition(
502 resource_name=service_name,
503 single_resource_json_definition=resource_model['service'],
504 service_context=service_context,
505 )
507 return cls(client=client)
509 def _register_default_handlers(self):
510 # S3 customizations
511 self._session.register(
512 'creating-client-class.s3',
513 boto3.utils.lazy_call(
514 'boto3.s3.inject.inject_s3_transfer_methods'
515 ),
516 )
517 self._session.register(
518 'creating-resource-class.s3.Bucket',
519 boto3.utils.lazy_call('boto3.s3.inject.inject_bucket_methods'),
520 )
521 self._session.register(
522 'creating-resource-class.s3.Object',
523 boto3.utils.lazy_call('boto3.s3.inject.inject_object_methods'),
524 )
525 self._session.register(
526 'creating-resource-class.s3.ObjectSummary',
527 boto3.utils.lazy_call(
528 'boto3.s3.inject.inject_object_summary_methods'
529 ),
530 )
532 # DynamoDb customizations
533 self._session.register(
534 'creating-resource-class.dynamodb',
535 boto3.utils.lazy_call(
536 'boto3.dynamodb.transform.register_high_level_interface'
537 ),
538 unique_id='high-level-dynamodb',
539 )
540 self._session.register(
541 'creating-resource-class.dynamodb.Table',
542 boto3.utils.lazy_call(
543 'boto3.dynamodb.table.register_table_methods'
544 ),
545 unique_id='high-level-dynamodb-table',
546 )
548 # EC2 Customizations
549 self._session.register(
550 'creating-resource-class.ec2.ServiceResource',
551 boto3.utils.lazy_call('boto3.ec2.createtags.inject_create_tags'),
552 )
554 self._session.register(
555 'creating-resource-class.ec2.Instance',
556 boto3.utils.lazy_call(
557 'boto3.ec2.deletetags.inject_delete_tags',
558 event_emitter=self.events,
559 ),
560 )
562 def _account_id_set_without_credentials(
563 self,
564 *,
565 aws_account_id,
566 aws_access_key_id,
567 aws_secret_access_key,
568 **kwargs,
569 ):
570 if aws_account_id is None:
571 return False
572 elif aws_access_key_id is None or aws_secret_access_key is None:
573 return True
574 return False