comparison planemo/lib/python3.7/site-packages/boto/vendored/regions/regions.py @ 0:d30785e31577 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:18:57 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d30785e31577
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 # http://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 """Resolves regions and endpoints.
14
15 This module implements endpoint resolution, including resolving endpoints for a
16 given service and region and resolving the available endpoints for a service
17 in a specific AWS partition.
18 """
19 import logging
20 import re
21
22 from boto.vendored.regions.exceptions import NoRegionError
23
24 LOG = logging.getLogger(__name__)
25 DEFAULT_URI_TEMPLATE = '{service}.{region}.{dnsSuffix}'
26 DEFAULT_SERVICE_DATA = {'endpoints': {}}
27
28
29 class BaseEndpointResolver(object):
30 """Resolves regions and endpoints. Must be subclassed."""
31 def construct_endpoint(self, service_name, region_name=None):
32 """Resolves an endpoint for a service and region combination.
33
34 :type service_name: string
35 :param service_name: Name of the service to resolve an endpoint for
36 (e.g., s3)
37
38 :type region_name: string
39 :param region_name: Region/endpoint name to resolve (e.g., us-east-1)
40 if no region is provided, the first found partition-wide endpoint
41 will be used if available.
42
43 :rtype: dict
44 :return: Returns a dict containing the following keys:
45 - partition: (string, required) Resolved partition name
46 - endpointName: (string, required) Resolved endpoint name
47 - hostname: (string, required) Hostname to use for this endpoint
48 - sslCommonName: (string) sslCommonName to use for this endpoint.
49 - credentialScope: (dict) Signature version 4 credential scope
50 - region: (string) region name override when signing.
51 - service: (string) service name override when signing.
52 - signatureVersions: (list<string>) A list of possible signature
53 versions, including s3, v4, v2, and s3v4
54 - protocols: (list<string>) A list of supported protocols
55 (e.g., http, https)
56 - ...: Other keys may be included as well based on the metadata
57 """
58 raise NotImplementedError
59
60 def get_available_partitions(self):
61 """Lists the partitions available to the endpoint resolver.
62
63 :return: Returns a list of partition names (e.g., ["aws", "aws-cn"]).
64 """
65 raise NotImplementedError
66
67 def get_available_endpoints(self, service_name, partition_name='aws',
68 allow_non_regional=False):
69 """Lists the endpoint names of a particular partition.
70
71 :type service_name: string
72 :param service_name: Name of a service to list endpoint for (e.g., s3)
73
74 :type partition_name: string
75 :param partition_name: Name of the partition to limit endpoints to.
76 (e.g., aws for the public AWS endpoints, aws-cn for AWS China
77 endpoints, aws-us-gov for AWS GovCloud (US) Endpoints, etc.
78
79 :type allow_non_regional: bool
80 :param allow_non_regional: Set to True to include endpoints that are
81 not regional endpoints (e.g., s3-external-1,
82 fips-us-gov-west-1, etc).
83 :return: Returns a list of endpoint names (e.g., ["us-east-1"]).
84 """
85 raise NotImplementedError
86
87
88 class EndpointResolver(BaseEndpointResolver):
89 """Resolves endpoints based on partition endpoint metadata"""
90 def __init__(self, endpoint_data):
91 """
92 :param endpoint_data: A dict of partition data.
93 """
94 if 'partitions' not in endpoint_data:
95 raise ValueError('Missing "partitions" in endpoint data')
96 self._endpoint_data = endpoint_data
97
98 def get_available_partitions(self):
99 result = []
100 for partition in self._endpoint_data['partitions']:
101 result.append(partition['partition'])
102 return result
103
104 def get_available_endpoints(self, service_name, partition_name='aws',
105 allow_non_regional=False):
106 result = []
107 for partition in self._endpoint_data['partitions']:
108 if partition['partition'] != partition_name:
109 continue
110 services = partition['services']
111 if service_name not in services:
112 continue
113 for endpoint_name in services[service_name]['endpoints']:
114 if allow_non_regional or endpoint_name in partition['regions']:
115 result.append(endpoint_name)
116 return result
117
118 def construct_endpoint(self, service_name, region_name=None):
119 # Iterate over each partition until a match is found.
120 for partition in self._endpoint_data['partitions']:
121 result = self._endpoint_for_partition(
122 partition, service_name, region_name)
123 if result:
124 return result
125
126 def _endpoint_for_partition(self, partition, service_name, region_name):
127 # Get the service from the partition, or an empty template.
128 service_data = partition['services'].get(
129 service_name, DEFAULT_SERVICE_DATA)
130 # Use the partition endpoint if no region is supplied.
131 if region_name is None:
132 if 'partitionEndpoint' in service_data:
133 region_name = service_data['partitionEndpoint']
134 else:
135 raise NoRegionError()
136 # Attempt to resolve the exact region for this partition.
137 if region_name in service_data['endpoints']:
138 return self._resolve(
139 partition, service_name, service_data, region_name)
140 # Check to see if the endpoint provided is valid for the partition.
141 if self._region_match(partition, region_name):
142 # Use the partition endpoint if set and not regionalized.
143 partition_endpoint = service_data.get('partitionEndpoint')
144 is_regionalized = service_data.get('isRegionalized', True)
145 if partition_endpoint and not is_regionalized:
146 LOG.debug('Using partition endpoint for %s, %s: %s',
147 service_name, region_name, partition_endpoint)
148 return self._resolve(
149 partition, service_name, service_data, partition_endpoint)
150 LOG.debug('Creating a regex based endpoint for %s, %s',
151 service_name, region_name)
152 return self._resolve(
153 partition, service_name, service_data, region_name)
154
155 def _region_match(self, partition, region_name):
156 if region_name in partition['regions']:
157 return True
158 if 'regionRegex' in partition:
159 return re.compile(partition['regionRegex']).match(region_name)
160 return False
161
162 def _resolve(self, partition, service_name, service_data, endpoint_name):
163 result = service_data['endpoints'].get(endpoint_name, {})
164 result['partition'] = partition['partition']
165 result['endpointName'] = endpoint_name
166 # Merge in the service defaults then the partition defaults.
167 self._merge_keys(service_data.get('defaults', {}), result)
168 self._merge_keys(partition.get('defaults', {}), result)
169 hostname = result.get('hostname', DEFAULT_URI_TEMPLATE)
170 result['hostname'] = self._expand_template(
171 partition, result['hostname'], service_name, endpoint_name)
172 if 'sslCommonName' in result:
173 result['sslCommonName'] = self._expand_template(
174 partition, result['sslCommonName'], service_name,
175 endpoint_name)
176 result['dnsSuffix'] = partition['dnsSuffix']
177 return result
178
179 def _merge_keys(self, from_data, result):
180 for key in from_data:
181 if key not in result:
182 result[key] = from_data[key]
183
184 def _expand_template(self, partition, template, service_name,
185 endpoint_name):
186 return template.format(
187 service=service_name, region=endpoint_name,
188 dnsSuffix=partition['dnsSuffix'])