aws-partitions 1.507.0 → 1.774.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1374 -0
- data/VERSION +1 -1
- data/lib/aws-partitions/endpoint_provider.rb +147 -30
- data/lib/aws-partitions/partition.rb +10 -2
- data/lib/aws-partitions/partition_list.rb +50 -0
- data/lib/aws-partitions/service.rb +27 -0
- data/lib/aws-partitions.rb +85 -1
- data/partitions-metadata.json +192 -0
- data/partitions.json +16740 -3759
- metadata +3 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.774.0
|
@@ -37,31 +37,108 @@ module Aws
|
|
37
37
|
# "monitoring" for cloudwatch.
|
38
38
|
# @param [String] sts_regional_endpoints [STS only] Whether to use
|
39
39
|
# `legacy` (global endpoint for legacy regions) or `regional` mode for
|
40
|
-
#
|
40
|
+
# using regional endpoint for supported regions except 'aws-global'
|
41
|
+
# @param [Hash] variants Endpoint variants such as 'fips' or 'dualstack'
|
42
|
+
# @option variants [Boolean] :dualstack When true, resolve a dualstack
|
43
|
+
# endpoint.
|
44
|
+
# @option variants [Boolean] :fips When true, resolve a FIPS endpoint.
|
41
45
|
# @api private Use the static class methods instead.
|
42
|
-
def resolve(region, service, sts_regional_endpoints)
|
43
|
-
'https://' + endpoint_for(region, service, sts_regional_endpoints)
|
46
|
+
def resolve(region, service, sts_regional_endpoints, variants)
|
47
|
+
'https://' + endpoint_for(region, service, build_is_global_fn(sts_regional_endpoints), variants)
|
44
48
|
end
|
45
49
|
|
46
50
|
# @api private Use the static class methods instead.
|
47
|
-
def signing_region(region, service)
|
48
|
-
|
49
|
-
.fetch('services', {})
|
50
|
-
.fetch(service, {})
|
51
|
-
.fetch('endpoints', {})
|
52
|
-
.fetch(region, {})
|
53
|
-
.fetch('credentialScope', {})
|
51
|
+
def signing_region(region, service, sts_regional_endpoints)
|
52
|
+
credential_scope(region, service, build_is_global_fn(sts_regional_endpoints))
|
54
53
|
.fetch('region', region)
|
55
54
|
end
|
56
55
|
|
57
56
|
# @api private Use the static class methods instead.
|
58
|
-
def
|
59
|
-
|
57
|
+
def signing_service(region, service)
|
58
|
+
# don't default to the service name
|
59
|
+
# signers should prefer the api metadata's signingName
|
60
|
+
# if no service is set in the credentialScope
|
61
|
+
credential_scope(region, service, build_is_global_fn('regional'))
|
62
|
+
.fetch('service', nil)
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param [String] region The region used to fetch the partition.
|
66
|
+
# @param [String] service Used only if dualstack is true. Used to find a
|
67
|
+
# DNS suffix for a specific service.
|
68
|
+
# @param [Hash] variants Endpoint variants such as 'fips' or 'dualstack'
|
69
|
+
# @option variants [Boolean] :dualstack When true, resolve a dualstack
|
70
|
+
# endpoint.
|
71
|
+
# @option variants [Boolean] :fips When true, resolve a FIPS endpoint.
|
72
|
+
# @api private Use the static class methods instead.
|
73
|
+
def dns_suffix_for(region, service, variants)
|
74
|
+
if configured_variants?(variants)
|
75
|
+
resolve_variant(region, service, variants)['dnsSuffix']
|
76
|
+
else
|
77
|
+
get_partition(region)['dnsSuffix']
|
78
|
+
end
|
60
79
|
end
|
61
80
|
|
62
81
|
private
|
63
82
|
|
64
|
-
def
|
83
|
+
def configured_variants?(variants)
|
84
|
+
variants.values.any?
|
85
|
+
end
|
86
|
+
|
87
|
+
def fetch_variant(cfg, tags)
|
88
|
+
variants = cfg.fetch('variants', [])
|
89
|
+
variants.find { |v| tags == Set.new(v['tags']) } || {}
|
90
|
+
end
|
91
|
+
|
92
|
+
def resolve_variant(region, service, config_variants)
|
93
|
+
tags = Set.new(config_variants.select { |_k,v| v == true }.map { |k,_v| k.to_s })
|
94
|
+
is_global_fn = build_is_global_fn # ignore legacy STS config for variants
|
95
|
+
|
96
|
+
partition_cfg = get_partition(region)
|
97
|
+
service_cfg = partition_cfg.fetch('services', {})
|
98
|
+
.fetch(service, {})
|
99
|
+
|
100
|
+
endpoints_cfg = service_cfg.fetch('endpoints', {})
|
101
|
+
|
102
|
+
if is_global_fn.call(service, region, endpoints_cfg, service_cfg)
|
103
|
+
region = service_cfg.fetch('partitionEndpoint', region)
|
104
|
+
end
|
105
|
+
|
106
|
+
region_cfg = endpoints_cfg.fetch(region, {})
|
107
|
+
warn_deprecation(service, region) if region_cfg['deprecated']
|
108
|
+
|
109
|
+
partition_defaults = fetch_variant(partition_cfg.fetch('defaults', {}), tags)
|
110
|
+
service_defaults = fetch_variant(service_cfg.fetch('defaults', {}), tags)
|
111
|
+
endpoint_cfg = fetch_variant(region_cfg, tags)
|
112
|
+
|
113
|
+
# merge upwards, preferring values from endpoint > service > partition
|
114
|
+
partition_defaults.merge(service_defaults.merge(endpoint_cfg))
|
115
|
+
end
|
116
|
+
|
117
|
+
def validate_variant!(config_variants, resolved_variant)
|
118
|
+
unless resolved_variant['hostname'] && resolved_variant['dnsSuffix']
|
119
|
+
enabled_variants = config_variants.select { |_k, v| v}.map { |k, _v| k.to_s }.join(', ')
|
120
|
+
raise ArgumentError,
|
121
|
+
"#{enabled_variants} not supported for this region and partition."
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def endpoint_for(region, service, is_global_fn, variants)
|
126
|
+
if configured_variants?(variants)
|
127
|
+
endpoint_with_variants_for(region, service, variants)
|
128
|
+
else
|
129
|
+
endpoint_no_variants_for(region, service, is_global_fn)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def endpoint_with_variants_for(region, service, variants)
|
134
|
+
variant = resolve_variant(region, service, variants)
|
135
|
+
validate_variant!(variants, variant)
|
136
|
+
variant['hostname'].sub('{region}', region)
|
137
|
+
.sub('{service}', service)
|
138
|
+
.sub('{dnsSuffix}', variant['dnsSuffix'])
|
139
|
+
end
|
140
|
+
|
141
|
+
def endpoint_no_variants_for(region, service, is_global_fn)
|
65
142
|
partition = get_partition(region)
|
66
143
|
service_cfg = partition.fetch('services', {}).fetch(service, {})
|
67
144
|
|
@@ -72,30 +149,66 @@ module Aws
|
|
72
149
|
|
73
150
|
endpoints = service_cfg.fetch('endpoints', {})
|
74
151
|
|
75
|
-
# Check for sts legacy behavior
|
76
|
-
sts_legacy = service == 'sts' &&
|
77
|
-
sts_regional_endpoints == 'legacy' &&
|
78
|
-
STS_LEGACY_REGIONS.include?(region)
|
79
|
-
|
80
|
-
is_global = !endpoints.key?(region) &&
|
81
|
-
service_cfg['isRegionalized'] == false
|
82
|
-
|
83
152
|
# Check for global endpoint.
|
84
|
-
if
|
153
|
+
if is_global_fn.call(service, region, endpoints, service_cfg)
|
85
154
|
region = service_cfg.fetch('partitionEndpoint', region)
|
86
155
|
end
|
87
156
|
|
88
157
|
# Check for service/region level endpoint.
|
89
|
-
|
158
|
+
region_cfg = endpoints
|
90
159
|
.fetch(region, {})
|
160
|
+
endpoint = region_cfg
|
91
161
|
.fetch('hostname', default_endpoint)
|
92
162
|
|
163
|
+
warn_deprecation(service, region) if region_cfg['deprecated']
|
164
|
+
|
93
165
|
# Replace placeholders from the endpoints
|
94
166
|
endpoint.sub('{region}', region)
|
95
167
|
.sub('{service}', service)
|
96
168
|
.sub('{dnsSuffix}', partition['dnsSuffix'])
|
97
169
|
end
|
98
170
|
|
171
|
+
def warn_deprecation(service, region)
|
172
|
+
warn("The endpoint for service: #{service}, region: #{region}"\
|
173
|
+
' is deprecated.')
|
174
|
+
end
|
175
|
+
|
176
|
+
# returns a callable that takes a region
|
177
|
+
# and returns true if the service is global
|
178
|
+
def build_is_global_fn(sts_regional_endpoints='regional')
|
179
|
+
lambda do |service, region, endpoints, service_cfg|
|
180
|
+
# Check for sts legacy behavior
|
181
|
+
sts_legacy = service == 'sts' &&
|
182
|
+
sts_regional_endpoints == 'legacy' &&
|
183
|
+
STS_LEGACY_REGIONS.include?(region)
|
184
|
+
|
185
|
+
is_global = !endpoints.key?(region) &&
|
186
|
+
service_cfg['isRegionalized'] == false
|
187
|
+
|
188
|
+
sts_legacy || is_global
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def credential_scope(region, service, is_global_fn)
|
193
|
+
partition = get_partition(region)
|
194
|
+
service_cfg = partition.fetch('services', {})
|
195
|
+
.fetch(service, {})
|
196
|
+
endpoints = service_cfg.fetch('endpoints', {})
|
197
|
+
|
198
|
+
# Check for global endpoint.
|
199
|
+
if is_global_fn.call(service, region, endpoints, service_cfg)
|
200
|
+
region = service_cfg.fetch('partitionEndpoint', region)
|
201
|
+
end
|
202
|
+
|
203
|
+
default_credential_scope = service_cfg
|
204
|
+
.fetch('defaults', {})
|
205
|
+
.fetch('credentialScope', {})
|
206
|
+
|
207
|
+
endpoints
|
208
|
+
.fetch(region, {})
|
209
|
+
.fetch('credentialScope', default_credential_scope)
|
210
|
+
end
|
211
|
+
|
99
212
|
def get_partition(region_or_partition)
|
100
213
|
partition_containing_region(region_or_partition) ||
|
101
214
|
partition_matching_region(region_or_partition) ||
|
@@ -111,7 +224,7 @@ module Aws
|
|
111
224
|
|
112
225
|
def partition_matching_region(region)
|
113
226
|
@rules['partitions'].find do |p|
|
114
|
-
region.match(p['regionRegex']) ||
|
227
|
+
p['regionRegex'] && region.match(p['regionRegex']) ||
|
115
228
|
p['services'].values.find do |svc|
|
116
229
|
svc['endpoints'].key?(region) if svc.key?('endpoints')
|
117
230
|
end
|
@@ -128,16 +241,20 @@ module Aws
|
|
128
241
|
end
|
129
242
|
|
130
243
|
class << self
|
131
|
-
def resolve(region, service,
|
132
|
-
default_provider.resolve(region, service,
|
244
|
+
def resolve(region, service, sts_endpoint = 'regional', variants = {})
|
245
|
+
default_provider.resolve(region, service, sts_endpoint, variants)
|
246
|
+
end
|
247
|
+
|
248
|
+
def signing_region(region, service, sts_regional_endpoints = 'regional')
|
249
|
+
default_provider.signing_region(region, service, sts_regional_endpoints)
|
133
250
|
end
|
134
251
|
|
135
|
-
def
|
136
|
-
default_provider.
|
252
|
+
def signing_service(region, service)
|
253
|
+
default_provider.signing_service(region, service)
|
137
254
|
end
|
138
255
|
|
139
|
-
def dns_suffix_for(region)
|
140
|
-
default_provider.dns_suffix_for(region)
|
256
|
+
def dns_suffix_for(region, service = nil, variants = {})
|
257
|
+
default_provider.dns_suffix_for(region, service, variants)
|
141
258
|
end
|
142
259
|
|
143
260
|
private
|
@@ -10,12 +10,20 @@ module Aws
|
|
10
10
|
def initialize(options = {})
|
11
11
|
@name = options[:name]
|
12
12
|
@regions = options[:regions]
|
13
|
+
@region_regex = options[:region_regex]
|
13
14
|
@services = options[:services]
|
15
|
+
@metadata = options[:metadata]
|
14
16
|
end
|
15
17
|
|
16
18
|
# @return [String] The partition name, e.g. "aws", "aws-cn", "aws-us-gov".
|
17
19
|
attr_reader :name
|
18
20
|
|
21
|
+
# @return [String] The regex representing the region format.
|
22
|
+
attr_reader :region_regex
|
23
|
+
|
24
|
+
# @return [Metadata] The metadata for the partition.
|
25
|
+
attr_reader :metadata
|
26
|
+
|
19
27
|
# @param [String] region_name The name of the region, e.g. "us-east-1".
|
20
28
|
# @return [Region]
|
21
29
|
# @raise [ArgumentError] Raises `ArgumentError` for unknown region name.
|
@@ -70,6 +78,7 @@ module Aws
|
|
70
78
|
Partition.new(
|
71
79
|
name: partition['partition'],
|
72
80
|
regions: build_regions(partition),
|
81
|
+
region_regex: partition['regionRegex'],
|
73
82
|
services: build_services(partition)
|
74
83
|
)
|
75
84
|
end
|
@@ -79,8 +88,7 @@ module Aws
|
|
79
88
|
# @param [Hash] partition
|
80
89
|
# @return [Hash<String,Region>]
|
81
90
|
def build_regions(partition)
|
82
|
-
partition['regions'].each_with_object({}) do
|
83
|
-
|(region_name, region), regions|
|
91
|
+
partition['regions'].each_with_object({}) do |(region_name, region), regions|
|
84
92
|
next if region_name == "#{partition['partition']}-global"
|
85
93
|
|
86
94
|
regions[region_name] = Region.build(
|
@@ -42,12 +42,62 @@ module Aws
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
# @param [Partition] partition
|
46
|
+
# @api private
|
47
|
+
def merge_metadata(partitions_metadata)
|
48
|
+
partitions_metadata['partitions'].each do |partition_metadata|
|
49
|
+
outputs = partition_metadata['outputs']
|
50
|
+
|
51
|
+
if existing = @partitions[partition_metadata['id']]
|
52
|
+
@partitions[partition_metadata['id']] = Partition.new(
|
53
|
+
name: existing.name,
|
54
|
+
regions: build_metadata_regions(
|
55
|
+
partition_metadata['id'],
|
56
|
+
partition_metadata['regions'],
|
57
|
+
existing),
|
58
|
+
region_regex: partition_metadata['regionRegex'],
|
59
|
+
services: existing.services.each_with_object({}) do |s, services|
|
60
|
+
services[s.name] = s
|
61
|
+
end,
|
62
|
+
metadata: outputs
|
63
|
+
)
|
64
|
+
else
|
65
|
+
@partitions[partition_metadata['id']] = Partition.new(
|
66
|
+
name: partition_metadata['id'],
|
67
|
+
regions: build_metadata_regions(
|
68
|
+
partition_metadata['id'], partition_metadata['regions']
|
69
|
+
),
|
70
|
+
region_regex: partition_metadata['regionRegex'],
|
71
|
+
services: {},
|
72
|
+
metadata: outputs
|
73
|
+
)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
45
78
|
# Removed all partitions.
|
46
79
|
# @api private
|
47
80
|
def clear
|
48
81
|
@partitions = {}
|
49
82
|
end
|
50
83
|
|
84
|
+
private
|
85
|
+
|
86
|
+
def build_metadata_regions(partition_name, metadata_regions, existing = nil)
|
87
|
+
metadata_regions.each_with_object({}) do |(region_name, region), regions|
|
88
|
+
if existing && existing.region?(region_name)
|
89
|
+
regions[region_name] = existing.region(region_name)
|
90
|
+
else
|
91
|
+
regions[region_name] = Region.new(
|
92
|
+
name: region_name,
|
93
|
+
description: region['description'],
|
94
|
+
partition_name: partition_name,
|
95
|
+
services: Set.new
|
96
|
+
)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
51
101
|
class << self
|
52
102
|
|
53
103
|
# @api private
|
@@ -16,6 +16,8 @@ module Aws
|
|
16
16
|
@name = options[:name]
|
17
17
|
@partition_name = options[:partition_name]
|
18
18
|
@regions = options[:regions]
|
19
|
+
@fips_regions = options[:fips_regions]
|
20
|
+
@dualstack_regions = options[:dualstack_regions]
|
19
21
|
@regionalized = options[:regionalized]
|
20
22
|
@partition_region = options[:partition_region]
|
21
23
|
end
|
@@ -31,6 +33,14 @@ module Aws
|
|
31
33
|
# Regions are scoped to the partition.
|
32
34
|
attr_reader :regions
|
33
35
|
|
36
|
+
# @return [Set<String>] The FIPS compatible regions this service is
|
37
|
+
# available in. Regions are scoped to the partition.
|
38
|
+
attr_reader :fips_regions
|
39
|
+
|
40
|
+
# @return [Set<String>] The Dualstack compatible regions this service is
|
41
|
+
# available in. Regions are scoped to the partition.
|
42
|
+
attr_reader :dualstack_regions
|
43
|
+
|
34
44
|
# @return [String,nil] The global patition endpoint for this service.
|
35
45
|
# May be `nil`.
|
36
46
|
attr_reader :partition_region
|
@@ -54,6 +64,8 @@ module Aws
|
|
54
64
|
name: service_name,
|
55
65
|
partition_name: partition['partition'],
|
56
66
|
regions: regions(service, partition),
|
67
|
+
fips_regions: variant_regions('fips', service, partition),
|
68
|
+
dualstack_regions: variant_regions('dualstack', service, partition),
|
57
69
|
regionalized: service['isRegionalized'] != false,
|
58
70
|
partition_region: partition_region(service)
|
59
71
|
)
|
@@ -67,6 +79,21 @@ module Aws
|
|
67
79
|
names - ["#{partition['partition']}-global"]
|
68
80
|
end
|
69
81
|
|
82
|
+
def variant_regions(variant_name, service, partition)
|
83
|
+
svc_endpoints = service.fetch('endpoints', {})
|
84
|
+
names = Set.new
|
85
|
+
svc_endpoints.each do |key, value|
|
86
|
+
variants = value.fetch('variants', [])
|
87
|
+
variants.each do |variant|
|
88
|
+
tags = variant.fetch('tags', [])
|
89
|
+
if tags.include?(variant_name) && partition['regions'].key?(key)
|
90
|
+
names << key
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
names - ["#{partition['partition']}-global"]
|
95
|
+
end
|
96
|
+
|
70
97
|
def partition_region(service)
|
71
98
|
service['partitionEndpoint']
|
72
99
|
end
|