aws-partitions 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bcd64cee1eb0c323f8692ff5a4c7dca11389772b
4
+ data.tar.gz: 0adcedec22ecafcc3d905eef56a8e44db74ab6d3
5
+ SHA512:
6
+ metadata.gz: e5bf87351f61caedae8f502e12e6697fd30983961307e629ba2829990a95e6e58abd16ab4602a6f602ed9f308ece8779f4ea5313fc92c2bce084e98da8ef77cb
7
+ data.tar.gz: ecdb63091ac2d9a8023ab1637d95299a4d418d7d2a2c0131c13166129d1eb89b02ed7d5d7a0773a8f0e04696e35477b592c514d964f651f987e358b8dc6a1764
@@ -0,0 +1,306 @@
1
+ require_relative 'aws-partitions/endpoint_provider'
2
+ require_relative 'aws-partitions/partition'
3
+ require_relative 'aws-partitions/partition_list'
4
+ require_relative 'aws-partitions/region'
5
+ require_relative 'aws-partitions/service'
6
+
7
+ require 'json'
8
+
9
+ module Aws
10
+
11
+ # A {Partition} is a group of AWS {Region} and {Service} objects. You
12
+ # can use a partition to determine what services are available in a region,
13
+ # or what regions a service is available in.
14
+ #
15
+ # ## Partitions
16
+ #
17
+ # **AWS accounts are scoped to a single partition**. You can get a partition
18
+ # by name. Valid partition names include:
19
+ #
20
+ # * `"aws"` - Public AWS partition
21
+ # * `"aws-cn"` - AWS China
22
+ # * `"aws-us-gov"` - AWS GovCloud
23
+ #
24
+ # To get a partition by name:
25
+ #
26
+ # aws = Aws::Partitions.partition('aws')
27
+ #
28
+ # You can also enumerate all partitions:
29
+ #
30
+ # Aws::Partitions.each do |partition|
31
+ # puts partition.name
32
+ # end
33
+ #
34
+ # ## Regions
35
+ #
36
+ # A {Partition} is divided up into one or more regions. For example, the
37
+ # "aws" partition contains, "us-east-1", "us-west-1", etc. You can get
38
+ # a region by name. Calling {Partition#region} will return an instance
39
+ # of {Region}.
40
+ #
41
+ # region = Aws::Partitions.partition('aws').region('us-west-2')
42
+ # region.name
43
+ # #=> "us-west-2"
44
+ #
45
+ # You can also enumerate all regions within a partition:
46
+ #
47
+ # Aws::Partitions.partition('aws').regions.each do |region|
48
+ # puts region.name
49
+ # end
50
+ #
51
+ # Each {Region} object has a name, description and a list of services
52
+ # available to that region:
53
+ #
54
+ # us_west_2 = Aws::Partitions.partition('aws').region('us-west-2')
55
+ #
56
+ # us_west_2.name #=> "us-west-2"
57
+ # us_west_2.description #=> "US West (Oregon)"
58
+ # us_west_2.partition_name "aws"
59
+ # us_west_2.services #=> #<Set: {"APIGateway", "AutoScaling", ... }
60
+ #
61
+ # To know if a service is available within a region, you can call `#include?`
62
+ # on the set of service names:
63
+ #
64
+ # region.services.include?('DynamoDB') #=> true/false
65
+ #
66
+ # The service name should be the service's module name as used by
67
+ # the AWS SDK for Ruby. To find the complete list of supported
68
+ # service names, see {Partition#services}.
69
+ #
70
+ # Its also possible to enumerate every service for every region in
71
+ # every partition.
72
+ #
73
+ # Aws::Partitions.partitions.each do |partition|
74
+ # partition.regions.each do |region|
75
+ # region.services.each do |service_name|
76
+ # puts "#{partition.name} -> #{region.name} -> #{service_name}"
77
+ # end
78
+ # end
79
+ # end
80
+ #
81
+ # ## Services
82
+ #
83
+ # A {Partition} has a list of services available. You can get a
84
+ # single {Service} by name:
85
+ #
86
+ # Aws::Partitions.partition('aws').service('DynamoDB')
87
+ #
88
+ # You can also enumerate all services in a partition:
89
+ #
90
+ # Aws::Partitions.partition('aws').services.each do |service|
91
+ # puts service.name
92
+ # end
93
+ #
94
+ # Each {Service} object has a name, and information about regions
95
+ # that service is available in.
96
+ #
97
+ # service.name #=> "DynamoDB"
98
+ # service.partition_name #=> "aws"
99
+ # service.regions #=> #<Set: {"us-east-1", "us-west-1", ... }
100
+ #
101
+ # Some services have multiple regions, and others have a single partition
102
+ # wide region. For example, {Aws::IAM} has a single region in the "aws"
103
+ # partition. The {Service#regionalized?} method indicates when this is
104
+ # the case.
105
+ #
106
+ # iam = Aws::Partitions.partition('aws').service('IAM')
107
+ #
108
+ # iam.regionalized? #=> false
109
+ # service.partition_region #=> "aws-global"
110
+ #
111
+ # Its also possible to enumerate every region for every service in
112
+ # every partition.
113
+ #
114
+ # Aws::Partitions.partitions.each do |partition|
115
+ # partition.services.each do |service|
116
+ # service.regions.each do |region_name|
117
+ # puts "#{partition.name} -> #{region_name} -> #{service.name}"
118
+ # end
119
+ # end
120
+ # end
121
+ #
122
+ # ## Service Names
123
+ #
124
+ # {Service} names are those used by the the AWS SDK for Ruby. They
125
+ # correspond to the service's module.
126
+ #
127
+ module Partitions
128
+
129
+ class << self
130
+
131
+ include Enumerable
132
+
133
+ # @return [Enumerable<Partition>]
134
+ def each(&block)
135
+ default_partition_list.each(&block)
136
+ end
137
+
138
+ # Return the partition with the given name. A partition describes
139
+ # the services and regions available in that partition.
140
+ #
141
+ # aws = Aws::Partitions.partition('aws')
142
+ #
143
+ # puts "Regions available in the aws partition:\n"
144
+ # aws.regions.each do |region|
145
+ # puts region.name
146
+ # end
147
+ #
148
+ # puts "Services available in the aws partition:\n"
149
+ # aws.services.each do |services|
150
+ # puts services.name
151
+ # end
152
+ #
153
+ # @param [String] name The name of the partition to return.
154
+ # Valid names include "aws", "aws-cn", and "aws-us-gov".
155
+ #
156
+ # @return [Partition]
157
+ #
158
+ # @raise [ArgumentError] Raises an `ArgumentError` if a partition is
159
+ # not found with the given name. The error message contains a list
160
+ # of valid partition names.
161
+ def partition(name)
162
+ default_partition_list.partition(name)
163
+ end
164
+
165
+ # Returns an array with every partitions. A partition describes
166
+ # the services and regions available in that partition.
167
+ #
168
+ # Aws::Partitions.partitions.each do |partition|
169
+ #
170
+ # puts "Regions available in #{partition.name}:\n"
171
+ # partition.regions.each do |region|
172
+ # puts region.name
173
+ # end
174
+ #
175
+ # puts "Services available in #{partition.name}:\n"
176
+ # partition.services.each do |service|
177
+ # puts service.name
178
+ # end
179
+ # end
180
+ #
181
+ # @return [Enumerable<Partition>] Returns an enumerable of all
182
+ # known partitions.
183
+ def partitions
184
+ default_partition_list
185
+ end
186
+
187
+ # @param [Hash] new_partitions
188
+ # @api private For internal use only.
189
+ def add(new_partitions)
190
+ new_partitions['partitions'].each do |partition|
191
+ default_partition_list.add_partition(Partition.build(partition))
192
+ defaults['partitions'] << partition
193
+ end
194
+ end
195
+
196
+ # @api private For internal use only.
197
+ def clear
198
+ default_partition_list.clear
199
+ defaults['partitions'].clear
200
+ end
201
+
202
+ # @return [PartitionList]
203
+ # @api private
204
+ def default_partition_list
205
+ @default_partition_list ||= PartitionList.build(defaults)
206
+ end
207
+
208
+ # @return [Hash]
209
+ # @api private
210
+ def defaults
211
+ @defaults ||= begin
212
+ path = File.expand_path('../../partitions.json', __FILE__)
213
+ JSON.load(File.read(path))
214
+ end
215
+ end
216
+
217
+ # @return [Hash<String,String>] Returns a map of service module names
218
+ # to their id as used in the endpoints.json document.
219
+ # @api private For internal use only.
220
+ def service_ids
221
+ @service_ids ||= begin
222
+ # service ids
223
+ {
224
+ 'ACM' => 'acm',
225
+ 'APIGateway' => 'apigateway',
226
+ 'ApplicationAutoScaling' => 'application-autoscaling',
227
+ 'ApplicationDiscoveryService' => 'discovery',
228
+ 'AutoScaling' => 'autoscaling',
229
+ 'Budgets' => 'budgets',
230
+ 'CloudFormation' => 'cloudformation',
231
+ 'CloudFront' => 'cloudfront',
232
+ 'CloudHSM' => 'cloudhsm',
233
+ 'CloudSearch' => 'cloudsearch',
234
+ 'CloudTrail' => 'cloudtrail',
235
+ 'CloudWatch' => 'monitoring',
236
+ 'CloudWatchEvents' => 'events',
237
+ 'CloudWatchLogs' => 'logs',
238
+ 'CodeCommit' => 'codecommit',
239
+ 'CodeDeploy' => 'codedeploy',
240
+ 'CodePipeline' => 'codepipeline',
241
+ 'CognitoIdentity' => 'cognito-identity',
242
+ 'CognitoIdentityProvider' => 'cognito-idp',
243
+ 'CognitoSync' => 'cognito-sync',
244
+ 'ConfigService' => 'config',
245
+ 'DataPipeline' => 'datapipeline',
246
+ 'DatabaseMigrationService' => 'dms',
247
+ 'DeviceFarm' => 'devicefarm',
248
+ 'DirectConnect' => 'directconnect',
249
+ 'DirectoryService' => 'ds',
250
+ 'DynamoDB' => 'dynamodb',
251
+ 'DynamoDBStreams' => 'streams.dynamodb',
252
+ 'EC2' => 'ec2',
253
+ 'ECR' => 'ecr',
254
+ 'ECS' => 'ecs',
255
+ 'EFS' => 'elasticfilesystem',
256
+ 'EMR' => 'elasticmapreduce',
257
+ 'ElastiCache' => 'elasticache',
258
+ 'ElasticBeanstalk' => 'elasticbeanstalk',
259
+ 'ElasticLoadBalancing' => 'elasticloadbalancing',
260
+ 'ElasticLoadBalancingV2' => 'elasticloadbalancing',
261
+ 'ElasticTranscoder' => 'elastictranscoder',
262
+ 'ElasticsearchService' => 'es',
263
+ 'Firehose' => 'firehose',
264
+ 'GameLift' => 'gamelift',
265
+ 'Glacier' => 'glacier',
266
+ 'IAM' => 'iam',
267
+ 'ImportExport' => 'importexport',
268
+ 'Inspector' => 'inspector',
269
+ 'IoT' => 'iot',
270
+ 'IoTDataPlane' => 'data.iot',
271
+ 'KMS' => 'kms',
272
+ 'Kinesis' => 'kinesis',
273
+ 'KinesisAnalytics' => 'kinesisanalytics',
274
+ 'Lambda' => 'lambda',
275
+ 'LambdaPreview' => 'lambda',
276
+ 'MachineLearning' => 'machinelearning',
277
+ 'MarketplaceCommerceAnalytics' => 'marketplacecommerceanalytics',
278
+ 'MarketplaceMetering' => 'metering.marketplace',
279
+ 'OpsWorks' => 'opsworks',
280
+ 'RDS' => 'rds',
281
+ 'Redshift' => 'redshift',
282
+ 'Route53' => 'route53',
283
+ 'Route53Domains' => 'route53domains',
284
+ 'S3' => 's3',
285
+ 'SES' => 'email',
286
+ 'SMS' => 'sms',
287
+ 'SNS' => 'sns',
288
+ 'SQS' => 'sqs',
289
+ 'SSM' => 'ssm',
290
+ 'STS' => 'sts',
291
+ 'SWF' => 'swf',
292
+ 'ServiceCatalog' => 'servicecatalog',
293
+ 'SimpleDB' => 'sdb',
294
+ 'Snowball' => 'snowball',
295
+ 'StorageGateway' => 'storagegateway',
296
+ 'Support' => 'support',
297
+ 'WAF' => 'waf',
298
+ 'WorkSpaces' => 'workspaces',
299
+ }
300
+ # end service ids
301
+ end
302
+ end
303
+
304
+ end
305
+ end
306
+ end
@@ -0,0 +1,115 @@
1
+ module Aws
2
+ module Partitions
3
+ # @api private
4
+ class EndpointProvider
5
+
6
+ # Intentionally marked private. The format of the endpoint rules
7
+ # is an implementation detail.
8
+ # @api private
9
+ def initialize(rules)
10
+ @rules = rules
11
+ end
12
+
13
+ # @param [String] region
14
+ # @param [String] service The endpoint prefix for the service, e.g. "monitoring" for
15
+ # cloudwatch.
16
+ # @api private Use the static class methods instead.
17
+ def resolve(region, service)
18
+ "https://" + endpoint_for(region, service)
19
+ end
20
+
21
+ # @api private Use the static class methods instead.
22
+ def signing_region(region, service)
23
+ get_partition(region).
24
+ fetch("services", {}).
25
+ fetch(service, {}).
26
+ fetch("endpoints", {}).
27
+ fetch(region, {}).
28
+ fetch("credentialScope", {}).
29
+ fetch("region", region)
30
+ end
31
+
32
+ # @api private Use the static class methods instead.
33
+ def dns_suffix_for(region)
34
+ partition = get_partition(region)
35
+ partition['dnsSuffix']
36
+ end
37
+
38
+ private
39
+
40
+ def endpoint_for(region, service)
41
+ partition = get_partition(region)
42
+ endpoint = default_endpoint(partition, service, region)
43
+ service_cfg = partition.fetch("services", {}).fetch(service, {})
44
+
45
+ # Check for service-level default endpoint.
46
+ endpoint = service_cfg.fetch("defaults", {}).fetch("hostname", endpoint)
47
+
48
+ # Check for global endpoint.
49
+ if service_cfg["isRegionalized"] == false
50
+ region = service_cfg.fetch("partitionEndpoint", region)
51
+ end
52
+
53
+ # Check for service/region level endpoint.
54
+ endpoint = service_cfg.fetch("endpoints", {}).
55
+ fetch(region, {}).fetch("hostname", endpoint)
56
+
57
+ endpoint
58
+ end
59
+
60
+ def default_endpoint(partition, service, region)
61
+ hostname_template = partition["defaults"]["hostname"]
62
+ hostname_template.
63
+ sub('{region}', region).
64
+ sub('{service}', service).
65
+ sub('{dnsSuffix}', partition["dnsSuffix"])
66
+ end
67
+
68
+ def get_partition(region)
69
+ partition_containing_region(region) ||
70
+ partition_matching_region(region) ||
71
+ default_partition
72
+ end
73
+
74
+ def partition_containing_region(region)
75
+ @rules['partitions'].find do |p|
76
+ p['regions'].key?(region)
77
+ end
78
+ end
79
+
80
+ def partition_matching_region(region)
81
+ @rules['partitions'].find do |p|
82
+ region.match(p["regionRegex"]) ||
83
+ p['services'].values.find { |svc| svc['endpoints'].key?(region) }
84
+ end
85
+ end
86
+
87
+ def default_partition
88
+ @rules['partitions'].find { |p| p["partition"] == "aws" } ||
89
+ @rules['partitions'].first
90
+ end
91
+
92
+ class << self
93
+
94
+ def resolve(region, service)
95
+ default_provider.resolve(region, service)
96
+ end
97
+
98
+ def signing_region(region, service)
99
+ default_provider.signing_region(region, service)
100
+ end
101
+
102
+ def dns_suffix_for(region)
103
+ default_provider.dns_suffix_for(region)
104
+ end
105
+
106
+ private
107
+
108
+ def default_provider
109
+ @default_provider ||= EndpointProvider.new(Partitions.defaults)
110
+ end
111
+
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,95 @@
1
+ module Aws
2
+ module Partitions
3
+ class Partition
4
+
5
+ # @option options [required, String] :name
6
+ # @option options [required, Hash<String,Region>] :regions
7
+ # @option options [required, Hash<String,Service>] :services
8
+ # @api private
9
+ def initialize(options = {})
10
+ @name = options[:name]
11
+ @regions = options[:regions]
12
+ @services = options[:services]
13
+ end
14
+
15
+ # @return [String] The partition name, e.g. "aws", "aws-cn", "aws-us-gov".
16
+ attr_reader :name
17
+
18
+ # @param [String] region_name The name of the region, e.g. "us-east-1".
19
+ # @return [Region]
20
+ # @raise [ArgumentError] Raises `ArgumentError` for unknown region name.
21
+ def region(region_name)
22
+ if @regions.key?(region_name)
23
+ @regions[region_name]
24
+ else
25
+ msg = "invalid region name #{region_name.inspect}; valid region "
26
+ msg << "names include %s" % [@regions.keys.join(', ')]
27
+ raise ArgumentError, msg
28
+ end
29
+ end
30
+
31
+ # @return [Array<Region>]
32
+ def regions
33
+ @regions.values
34
+ end
35
+
36
+ # @param [String] service_name The service module name.
37
+ # @return [Service]
38
+ # @raise [ArgumentError] Raises `ArgumentError` for unknown service name.
39
+ def service(service_name)
40
+ if @services.key?(service_name)
41
+ @services[service_name]
42
+ else
43
+ msg = "invalid service name #{service_name.inspect}; valid service "
44
+ msg << "names include %s" % [@services.keys.join(', ')]
45
+ raise ArgumentError, msg
46
+ end
47
+ end
48
+
49
+ # @return [Array<Service>]
50
+ def services
51
+ @services.values
52
+ end
53
+
54
+ class << self
55
+
56
+ # @api private
57
+ def build(partition)
58
+ Partition.new(
59
+ name: partition['partition'],
60
+ regions: build_regions(partition),
61
+ services: build_services(partition),
62
+ )
63
+ end
64
+
65
+ private
66
+
67
+ # @param [Hash] partition
68
+ # @return [Hash<String,Region>]
69
+ def build_regions(partition)
70
+ partition['regions'].inject({}) do |regions, (region_name, region)|
71
+ unless region_name == "#{partition['partition']}-global"
72
+ regions[region_name] = Region.build(region_name, region, partition)
73
+ end
74
+ regions
75
+ end
76
+ end
77
+
78
+ # @param [Hash] partition
79
+ # @return [Hash<String,Service>]
80
+ def build_services(partition)
81
+ Partitions.service_ids.inject({}) do |services, (svc_name, svc_id)|
82
+ if partition['services'].key?(svc_id)
83
+ svc_data = partition['services'][svc_id]
84
+ services[svc_name] = Service.build(svc_name, svc_data, partition)
85
+ else
86
+ services[svc_name] = Service.build(svc_name, {'endpoints' => {}}, partition)
87
+ end
88
+ services
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+ end
95
+ end