diff env/lib/python3.7/site-packages/boto/regioninfo.py @ 0:26e78fe6e8c4 draft

"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author shellac
date Sat, 02 May 2020 07:14:21 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/env/lib/python3.7/site-packages/boto/regioninfo.py	Sat May 02 07:14:21 2020 -0400
@@ -0,0 +1,290 @@
+# Copyright (c) 2006-2010 Mitch Garnaat http://garnaat.org/
+# Copyright (c) 2010, Eucalyptus Systems, Inc.
+# All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+import os
+
+import boto
+from boto.compat import json
+from boto.exception import BotoClientError
+from boto.endpoints import BotoEndpointResolver
+from boto.endpoints import StaticEndpointBuilder
+
+
+_endpoints_cache = {}
+
+
+def load_endpoint_json(path):
+    """
+    Loads a given JSON file & returns it.
+
+    :param path: The path to the JSON file
+    :type path: string
+
+    :returns: The loaded data
+    """
+    return _load_json_file(path)
+
+
+def _load_json_file(path):
+    """
+    Loads a given JSON file & returns it.
+
+    :param path: The path to the JSON file
+    :type path: string
+
+    :returns: The loaded data
+    """
+    with open(path, 'r') as endpoints_file:
+        return json.load(endpoints_file)
+
+
+def merge_endpoints(defaults, additions):
+    """
+    Given an existing set of endpoint data, this will deep-update it with
+    any similarly structured data in the additions.
+
+    :param defaults: The existing endpoints data
+    :type defaults: dict
+
+    :param defaults: The additional endpoints data
+    :type defaults: dict
+
+    :returns: The modified endpoints data
+    :rtype: dict
+    """
+    # We can't just do an ``defaults.update(...)`` here, as that could
+    # *overwrite* regions if present in both.
+    # We'll iterate instead, essentially doing a deeper merge.
+    for service, region_info in additions.items():
+        # Set the default, if not present, to an empty dict.
+        defaults.setdefault(service, {})
+        defaults[service].update(region_info)
+
+    return defaults
+
+
+def load_regions():
+    """
+    Actually load the region/endpoint information from the JSON files.
+
+    By default, this loads from the default included ``boto/endpoints.json``
+    file.
+
+    Users can override/extend this by supplying either a ``BOTO_ENDPOINTS``
+    environment variable or a ``endpoints_path`` config variable, either of
+    which should be an absolute path to the user's JSON file.
+
+    :returns: The endpoints data
+    :rtype: dict
+    """
+    # Load the defaults first.
+    endpoints = _load_builtin_endpoints()
+    additional_path = None
+
+    # Try the ENV var. If not, check the config file.
+    if os.environ.get('BOTO_ENDPOINTS'):
+        additional_path = os.environ['BOTO_ENDPOINTS']
+    elif boto.config.get('Boto', 'endpoints_path'):
+        additional_path = boto.config.get('Boto', 'endpoints_path')
+
+    # If there's a file provided, we'll load it & additively merge it into
+    # the endpoints.
+    if additional_path:
+        additional = load_endpoint_json(additional_path)
+        endpoints = merge_endpoints(endpoints, additional)
+
+    return endpoints
+
+
+def _load_builtin_endpoints(_cache=_endpoints_cache):
+    """Loads the builtin endpoints in the legacy format."""
+    # If there's a cached response, return it
+    if _cache:
+        return _cache
+
+    # Load the endpoints file
+    endpoints = _load_json_file(boto.ENDPOINTS_PATH)
+
+    # Build the endpoints into the legacy format
+    resolver = BotoEndpointResolver(endpoints)
+    builder = StaticEndpointBuilder(resolver)
+    endpoints = builder.build_static_endpoints()
+
+    # Cache the endpoints and then return them
+    _cache.update(endpoints)
+    return _cache
+
+
+def get_regions(service_name, region_cls=None, connection_cls=None):
+    """
+    Given a service name (like ``ec2``), returns a list of ``RegionInfo``
+    objects for that service.
+
+    This leverages the ``endpoints.json`` file (+ optional user overrides) to
+    configure/construct all the objects.
+
+    :param service_name: The name of the service to construct the ``RegionInfo``
+        objects for. Ex: ``ec2``, ``s3``, ``sns``, etc.
+    :type service_name: string
+
+    :param region_cls: (Optional) The class to use when constructing. By
+        default, this is ``RegionInfo``.
+    :type region_cls: class
+
+    :param connection_cls: (Optional) The connection class for the
+        ``RegionInfo`` object. Providing this allows the ``connect`` method on
+        the ``RegionInfo`` to work. Default is ``None`` (no connection).
+    :type connection_cls: class
+
+    :returns: A list of configured ``RegionInfo`` objects
+    :rtype: list
+    """
+    endpoints = load_regions()
+
+    if service_name not in endpoints:
+        raise BotoClientError(
+            "Service '%s' not found in endpoints." % service_name
+        )
+
+    if region_cls is None:
+        region_cls = RegionInfo
+
+    region_objs = []
+
+    for region_name, endpoint in endpoints.get(service_name, {}).items():
+        region_objs.append(
+            region_cls(
+                name=region_name,
+                endpoint=endpoint,
+                connection_cls=connection_cls
+            )
+        )
+
+    return region_objs
+
+
+def connect(service_name, region_name, region_cls=None,
+            connection_cls=None, **kw_params):
+    """Create a connection class for a given service in a given region.
+
+    :param service_name: The name of the service to construct the
+        ``RegionInfo`` object for, e.g. ``ec2``, ``s3``, etc.
+    :type service_name: str
+
+    :param region_name: The name of the region to connect to, e.g.
+        ``us-west-2``, ``eu-central-1``, etc.
+    :type region_name: str
+
+    :param region_cls: (Optional) The class to use when constructing. By
+        default, this is ``RegionInfo``.
+    :type region_cls: class
+
+    :param connection_cls: (Optional) The connection class for the
+        ``RegionInfo`` object. Providing this allows the ``connect`` method on
+        the ``RegionInfo`` to work. Default is ``None`` (no connection).
+    :type connection_cls: class
+
+    :returns: A configured connection class.
+    """
+    if region_cls is None:
+        region_cls = RegionInfo
+    region = _get_region(service_name, region_name, region_cls, connection_cls)
+
+    if region is None and _use_endpoint_heuristics():
+        region = _get_region_with_heuristics(
+            service_name, region_name, region_cls, connection_cls
+        )
+
+    if region is None:
+        return None
+
+    return region.connect(**kw_params)
+
+
+def _get_region(service_name, region_name, region_cls=None,
+                connection_cls=None):
+    """Finds the region by searching through the known regions."""
+    for region in get_regions(service_name, region_cls, connection_cls):
+        if region.name == region_name:
+            return region
+    return None
+
+
+def _get_region_with_heuristics(service_name, region_name, region_cls=None,
+                                connection_cls=None):
+    """Finds the region using known regions and heuristics."""
+    endpoints = load_endpoint_json(boto.ENDPOINTS_PATH)
+    resolver = BotoEndpointResolver(endpoints)
+    hostname = resolver.resolve_hostname(service_name, region_name)
+
+    return region_cls(
+        name=region_name,
+        endpoint=hostname,
+        connection_cls=connection_cls
+    )
+
+
+def _use_endpoint_heuristics():
+    env_var = os.environ.get('BOTO_USE_ENDPOINT_HEURISTICS', 'false').lower()
+    config_var = boto.config.getbool('Boto', 'use_endpoint_heuristics', False)
+    return env_var == 'true' or config_var
+
+
+class RegionInfo(object):
+    """
+    Represents an AWS Region
+    """
+
+    def __init__(self, connection=None, name=None, endpoint=None,
+                 connection_cls=None):
+        self.connection = connection
+        self.name = name
+        self.endpoint = endpoint
+        self.connection_cls = connection_cls
+
+    def __repr__(self):
+        return 'RegionInfo:%s' % self.name
+
+    def startElement(self, name, attrs, connection):
+        return None
+
+    def endElement(self, name, value, connection):
+        if name == 'regionName':
+            self.name = value
+        elif name == 'regionEndpoint':
+            self.endpoint = value
+        else:
+            setattr(self, name, value)
+
+    def connect(self, **kw_params):
+        """
+        Connect to this Region's endpoint. Returns an connection
+        object pointing to the endpoint associated with this region.
+        You may pass any of the arguments accepted by the connection
+        class's constructor as keyword arguments and they will be
+        passed along to the connection object.
+
+        :rtype: Connection object
+        :return: The connection to this regions endpoint
+        """
+        if self.connection_cls:
+            return self.connection_cls(region=self, **kw_params)