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
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 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 )
102 if region_name is not None:
103 self._session.set_config_variable('region', region_name)
105 self.resource_factory = ResourceFactory(
106 self._session.get_component('event_emitter')
107 )
108 self._setup_loader()
109 self._register_default_handlers()
111 def __repr__(self):
112 return '{}(region_name={})'.format(
113 self.__class__.__name__,
114 repr(self._session.get_config_variable('region')),
115 )
117 @property
118 def profile_name(self):
119 """
120 The **read-only** profile name.
121 """
122 return self._session.profile or 'default'
124 @property
125 def region_name(self):
126 """
127 The **read-only** region name.
128 """
129 return self._session.get_config_variable('region')
131 @property
132 def events(self):
133 """
134 The event emitter for a session
135 """
136 return self._session.get_component('event_emitter')
138 @property
139 def available_profiles(self):
140 """
141 The profiles available to the session credentials
142 """
143 return self._session.available_profiles
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 )
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`.
159 :rtype: list
160 :return: List of service names
161 """
162 return self._session.get_available_services()
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`.
169 :rtype: list
170 :return: List of service names
171 """
172 return self._loader.list_available_services(type_name='resources-1')
174 def get_available_partitions(self):
175 """Lists the available partitions
177 :rtype: list
178 :return: Returns a list of partition names (e.g., ["aws", "aws-cn"])
179 """
180 return self._session.get_available_partitions()
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.
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.
192 :type service_name: string
193 :param service_name: Name of a service to list endpoint for (e.g., s3).
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.)
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).
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 )
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()
223 def get_partition_for_region(self, region_name):
224 """Lists the partition name of a particular region.
226 :type region_name: string
227 :param region_name: Name of the region to list partition for (e.g.,
228 us-east-1).
230 :rtype: string
231 :return: Returns the respective partition name (e.g., aws).
232 """
233 return self._session.get_partition_for_region(region_name)
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.
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`.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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.
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.
319 :return: Service client instance
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 )
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.
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`.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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.
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 )
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 )
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
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 )
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 )
502 return cls(client=client)
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 )
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 )
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 )
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 )
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