aws-sdk-core 3.164.0 → 3.165.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/VERSION +1 -1
- data/lib/aws-sdk-core/arn.rb +13 -0
- data/lib/aws-sdk-core/binary/encode_handler.rb +12 -1
- data/lib/aws-sdk-core/endpoints/condition.rb +36 -0
- data/lib/aws-sdk-core/endpoints/endpoint.rb +17 -0
- data/lib/aws-sdk-core/endpoints/endpoint_rule.rb +71 -0
- data/lib/aws-sdk-core/endpoints/error_rule.rb +37 -0
- data/lib/aws-sdk-core/endpoints/function.rb +75 -0
- data/lib/aws-sdk-core/endpoints/matchers.rb +127 -0
- data/lib/aws-sdk-core/endpoints/reference.rb +26 -0
- data/lib/aws-sdk-core/endpoints/rule.rb +20 -0
- data/lib/aws-sdk-core/endpoints/rule_set.rb +47 -0
- data/lib/aws-sdk-core/endpoints/rules_provider.rb +32 -0
- data/lib/aws-sdk-core/endpoints/templater.rb +52 -0
- data/lib/aws-sdk-core/endpoints/tree_rule.rb +40 -0
- data/lib/aws-sdk-core/endpoints/url.rb +59 -0
- data/lib/aws-sdk-core/endpoints.rb +74 -0
- data/lib/aws-sdk-core/plugins/credentials_configuration.rb +24 -0
- data/lib/aws-sdk-core/plugins/endpoint_discovery.rb +6 -2
- data/lib/aws-sdk-core/plugins/regional_endpoint.rb +5 -0
- data/lib/aws-sdk-core/plugins/sign.rb +190 -0
- data/lib/aws-sdk-core/plugins/signature_v2.rb +1 -0
- data/lib/aws-sdk-core/plugins/signature_v4.rb +1 -0
- data/lib/aws-sdk-core/rest/request/headers.rb +2 -6
- data/lib/aws-sdk-core.rb +3 -0
- data/lib/aws-sdk-sso/client.rb +20 -3
- data/lib/aws-sdk-sso/endpoint_parameters.rb +66 -0
- data/lib/aws-sdk-sso/endpoint_provider.rb +112 -0
- data/lib/aws-sdk-sso/endpoints.rb +71 -0
- data/lib/aws-sdk-sso/plugins/endpoints.rb +76 -0
- data/lib/aws-sdk-sso.rb +5 -1
- data/lib/aws-sdk-ssooidc/client.rb +20 -3
- data/lib/aws-sdk-ssooidc/endpoint_parameters.rb +66 -0
- data/lib/aws-sdk-ssooidc/endpoint_provider.rb +111 -0
- data/lib/aws-sdk-ssooidc/endpoints.rb +57 -0
- data/lib/aws-sdk-ssooidc/plugins/endpoints.rb +74 -0
- data/lib/aws-sdk-ssooidc.rb +5 -1
- data/lib/aws-sdk-sts/client.rb +20 -3
- data/lib/aws-sdk-sts/endpoint_parameters.rb +78 -0
- data/lib/aws-sdk-sts/endpoint_provider.rb +229 -0
- data/lib/aws-sdk-sts/endpoints.rb +135 -0
- data/lib/aws-sdk-sts/plugins/endpoints.rb +84 -0
- data/lib/aws-sdk-sts/presigner.rb +13 -15
- data/lib/aws-sdk-sts.rb +5 -1
- data/lib/seahorse/client/async_base.rb +0 -1
- data/lib/seahorse/client/configuration.rb +2 -2
- data/lib/seahorse/util.rb +4 -0
- metadata +31 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df67380b30b1758bb4301b6c2c267866a5e62b068111975c5331ac20fe6290a4
|
4
|
+
data.tar.gz: b91374a34d93f7d328f8820a2ba89c6384fbf4dfe6254be974fe4d0b492dbbdf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0927312f09c93e40c158b18ac109c8bdee223aef6972868203d63cbd2120522367bc9448dc61f27cf445757ba9f5c00760122be8c469997b5b48fff19e2d9eeb'
|
7
|
+
data.tar.gz: 1a65436045eb469c4b1a18b3d7caa36be6659affb6e1dfd24dacf15587025585336bf0f8297f258f999471b2d1ed2f933e599230404fbd12ee6bc69bdc475ad7
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
Unreleased Changes
|
2
2
|
------------------
|
3
3
|
|
4
|
+
3.165.0 (2022-10-25)
|
5
|
+
------------------
|
6
|
+
|
7
|
+
* Feature - Updated Aws::SSOOIDC::Client with the latest API changes.
|
8
|
+
|
9
|
+
* Feature - Updated Aws::SSO::Client with the latest API changes.
|
10
|
+
|
11
|
+
* Feature - Add support for service gems to dynamically determine their own endpoints via modeling. Service gems now generate a plugin called "Endpoints" that defines configuration for EndpointProvider, a new public type, and any client config related to endpoints. Endpoint providers will resolve values using another new public type, Endpoint Parameters, generated for each service. The plugin will use the endpoint provider to resolve an endpoint and then apply it to the request prior to serialization. Endpoint providers can be composed to change endpoint resolution logic, i.e. for testing. In addition to endpoints, the endpoint provider may also override the authentication scheme (auth scheme) which details how the request should be signed for the endpoint. A new "Sign" plugin in core replaces the SignatureV4 plugin that will generically sign any type of auth scheme that a service might have.
|
12
|
+
|
4
13
|
3.164.0 (2022-10-21)
|
5
14
|
------------------
|
6
15
|
|
@@ -153,6 +162,8 @@ Unreleased Changes
|
|
153
162
|
|
154
163
|
* Feature - Updated Aws::SSO::Client with the latest API changes.
|
155
164
|
|
165
|
+
* Feature - Updated Aws::SSOOIDC::Client with the latest API changes.
|
166
|
+
|
156
167
|
3.135.0 (2022-08-24)
|
157
168
|
------------------
|
158
169
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.165.0
|
data/lib/aws-sdk-core/arn.rb
CHANGED
@@ -88,5 +88,18 @@ module Aws
|
|
88
88
|
resource: @resource
|
89
89
|
}
|
90
90
|
end
|
91
|
+
|
92
|
+
# Return the ARN as JSON
|
93
|
+
#
|
94
|
+
# @return [Hash]
|
95
|
+
def as_json(_options = nil)
|
96
|
+
{
|
97
|
+
'partition' => @partition,
|
98
|
+
'service' => @service,
|
99
|
+
'region' => @region,
|
100
|
+
'accountId' => @account_id,
|
101
|
+
'resource' => @resource
|
102
|
+
}
|
103
|
+
end
|
91
104
|
end
|
92
105
|
end
|
@@ -13,7 +13,7 @@ module Aws
|
|
13
13
|
context.config.api.metadata['protocol'],
|
14
14
|
eventstream_member,
|
15
15
|
context.operation.input,
|
16
|
-
context
|
16
|
+
signer_for(context)
|
17
17
|
)
|
18
18
|
context[:input_event_emitter] = input_es_handler.event_emitter
|
19
19
|
end
|
@@ -22,6 +22,17 @@ module Aws
|
|
22
22
|
|
23
23
|
private
|
24
24
|
|
25
|
+
def signer_for(context)
|
26
|
+
# New endpoint/signing logic, use the auth scheme to make a signer
|
27
|
+
if context[:auth_scheme]
|
28
|
+
Aws::Plugins::Sign.signer_for(context[:auth_scheme], context.config)
|
29
|
+
else
|
30
|
+
# Previous implementation always assumed sigv4_signer from config.
|
31
|
+
# Relies only on sigv4 signing (and plugin) for event stream services
|
32
|
+
context.config.sigv4_signer
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
25
36
|
def eventstream_input?(ctx)
|
26
37
|
ctx.operation.input.shape.members.each do |_, ref|
|
27
38
|
return ref if ref.eventstream
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# @api private
|
6
|
+
class Condition
|
7
|
+
def initialize(fn:, argv:, assign: nil)
|
8
|
+
@fn = Function.new(fn: fn, argv: argv)
|
9
|
+
@assign = assign
|
10
|
+
@assigned = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :fn
|
14
|
+
attr_reader :argv
|
15
|
+
attr_reader :assign
|
16
|
+
|
17
|
+
attr_reader :assigned
|
18
|
+
|
19
|
+
def match?(parameters, assigns)
|
20
|
+
output = @fn.call(parameters, assigns)
|
21
|
+
@assigned = @assigned.merge({ @assign => output }) if @assign
|
22
|
+
output
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.from_json(conditions_json)
|
26
|
+
conditions_json.each.with_object([]) do |condition, conditions|
|
27
|
+
conditions << new(
|
28
|
+
fn: condition['fn'],
|
29
|
+
argv: condition['argv'],
|
30
|
+
assign: condition['assign']
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
class Endpoint
|
6
|
+
def initialize(url:, properties: {}, headers: {})
|
7
|
+
@url = url
|
8
|
+
@properties = properties
|
9
|
+
@headers = headers
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :url
|
13
|
+
attr_reader :properties
|
14
|
+
attr_reader :headers
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# @api private
|
6
|
+
class EndpointRule < Rule
|
7
|
+
def initialize(type: 'endpoint', conditions:, endpoint:,
|
8
|
+
documentation: nil)
|
9
|
+
@type = type
|
10
|
+
@conditions = Condition.from_json(conditions)
|
11
|
+
@endpoint = endpoint
|
12
|
+
@documentation = documentation
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :type
|
16
|
+
attr_reader :conditions
|
17
|
+
attr_reader :endpoint
|
18
|
+
attr_reader :documentation
|
19
|
+
|
20
|
+
def match(parameters, assigned = {})
|
21
|
+
assigns = assigned.dup
|
22
|
+
matched = conditions.all? do |condition|
|
23
|
+
output = condition.match?(parameters, assigns)
|
24
|
+
assigns = assigns.merge(condition.assigned) if condition.assign
|
25
|
+
output
|
26
|
+
end
|
27
|
+
resolved_endpoint(parameters, assigns) if matched
|
28
|
+
end
|
29
|
+
|
30
|
+
def resolved_endpoint(parameters, assigns)
|
31
|
+
Endpoint.new(
|
32
|
+
url: resolve_value(@endpoint['url'], parameters, assigns),
|
33
|
+
properties: resolve_properties(
|
34
|
+
@endpoint['properties'] || {},
|
35
|
+
parameters,
|
36
|
+
assigns
|
37
|
+
),
|
38
|
+
headers: resolve_headers(parameters, assigns)
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def resolve_headers(parameters, assigns)
|
45
|
+
(@endpoint['headers'] || {}).each.with_object({}) do |(key, arr), headers|
|
46
|
+
headers[key] = []
|
47
|
+
arr.each do |value|
|
48
|
+
headers[key] << resolve_value(value, parameters, assigns)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def resolve_properties(obj, parameters, assigns)
|
54
|
+
case obj
|
55
|
+
when Hash
|
56
|
+
obj.each.with_object({}) do |(key, value), hash|
|
57
|
+
hash[key] = resolve_properties(value, parameters, assigns)
|
58
|
+
end
|
59
|
+
when Array
|
60
|
+
obj.collect { |value| resolve_properties(value, parameters, assigns) }
|
61
|
+
else
|
62
|
+
if obj.is_a?(String)
|
63
|
+
Templater.resolve(obj, parameters, assigns)
|
64
|
+
else
|
65
|
+
obj
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# @api private
|
6
|
+
class ErrorRule < Rule
|
7
|
+
def initialize(type: 'error', conditions:, error: nil, documentation: nil)
|
8
|
+
@type = type
|
9
|
+
@conditions = Condition.from_json(conditions)
|
10
|
+
@error = error
|
11
|
+
@documentation = documentation
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :type
|
15
|
+
attr_reader :conditions
|
16
|
+
attr_reader :error
|
17
|
+
attr_reader :documentation
|
18
|
+
|
19
|
+
def match(parameters, assigned = {})
|
20
|
+
assigns = assigned.dup
|
21
|
+
matched = conditions.all? do |condition|
|
22
|
+
output = condition.match?(parameters, assigns)
|
23
|
+
assigns = assigns.merge(condition.assigned) if condition.assign
|
24
|
+
output
|
25
|
+
end
|
26
|
+
resolved_error(parameters, assigns) if matched
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def resolved_error(parameters, assigns)
|
32
|
+
error = resolve_value(@error, parameters, assigns)
|
33
|
+
ArgumentError.new(error)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# @api private
|
6
|
+
class Function
|
7
|
+
def initialize(fn:, argv:)
|
8
|
+
@fn = fn
|
9
|
+
@argv = build_argv(argv)
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :fn
|
13
|
+
attr_reader :argv
|
14
|
+
|
15
|
+
def call(parameters, assigns)
|
16
|
+
args = []
|
17
|
+
@argv.each do |arg|
|
18
|
+
if arg.is_a?(Reference)
|
19
|
+
args << arg.resolve(parameters, assigns)
|
20
|
+
elsif arg.is_a?(Function)
|
21
|
+
args << arg.call(parameters, assigns)
|
22
|
+
else
|
23
|
+
if arg.is_a?(String)
|
24
|
+
arg = Templater.resolve(arg, parameters, assigns)
|
25
|
+
end
|
26
|
+
args << arg
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
case @fn
|
31
|
+
when 'isSet'
|
32
|
+
Matchers.set?(*args)
|
33
|
+
when 'not'
|
34
|
+
Matchers.not(*args)
|
35
|
+
when 'getAttr'
|
36
|
+
Matchers.attr(*args)
|
37
|
+
when 'substring'
|
38
|
+
Matchers.substring(*args)
|
39
|
+
when 'stringEquals'
|
40
|
+
Matchers.string_equals?(*args)
|
41
|
+
when 'booleanEquals'
|
42
|
+
Matchers.boolean_equals?(*args)
|
43
|
+
when 'uriEncode'
|
44
|
+
Matchers.uri_encode(*args)
|
45
|
+
when 'parseURL'
|
46
|
+
Matchers.parse_url(*args)
|
47
|
+
when 'isValidHostLabel'
|
48
|
+
Matchers.valid_host_label?(*args)
|
49
|
+
when 'aws.partition'
|
50
|
+
Matchers.aws_partition(*args)
|
51
|
+
when 'aws.parseArn'
|
52
|
+
Matchers.aws_parse_arn(*args)
|
53
|
+
when 'aws.isVirtualHostableS3Bucket'
|
54
|
+
Matchers.aws_virtual_hostable_s3_bucket?(*args)
|
55
|
+
else
|
56
|
+
raise "Function not found: #{@fn}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def build_argv(argv_json)
|
63
|
+
argv_json.each.with_object([]) do |arg, argv|
|
64
|
+
argv << if arg.is_a?(Hash) && arg['ref']
|
65
|
+
Reference.new(ref: arg['ref'])
|
66
|
+
elsif arg.is_a?(Hash) && arg['fn']
|
67
|
+
Function.new(fn: arg['fn'], argv: arg['argv'])
|
68
|
+
else
|
69
|
+
arg
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module Aws
|
6
|
+
module Endpoints
|
7
|
+
# generic matcher functions for service endpoints
|
8
|
+
# @api private
|
9
|
+
module Matchers
|
10
|
+
# Regex that extracts anything in square brackets
|
11
|
+
BRACKET_REGEX = /\[(.*?)\]/.freeze
|
12
|
+
|
13
|
+
# CORE
|
14
|
+
|
15
|
+
# isSet(value: Option<T>) bool
|
16
|
+
def self.set?(value)
|
17
|
+
!value.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
# not(value: bool) bool
|
21
|
+
def self.not(bool)
|
22
|
+
!bool
|
23
|
+
end
|
24
|
+
|
25
|
+
# getAttr(value: Object | Array, path: string) Document
|
26
|
+
def self.attr(value, path)
|
27
|
+
parts = path.split('.')
|
28
|
+
|
29
|
+
val = if (index = parts.first[BRACKET_REGEX, 1])
|
30
|
+
# remove brackets and index from part before indexing
|
31
|
+
value[parts.first.gsub(BRACKET_REGEX, '')][index.to_i]
|
32
|
+
else
|
33
|
+
value[parts.first]
|
34
|
+
end
|
35
|
+
|
36
|
+
if parts.size == 1
|
37
|
+
val
|
38
|
+
else
|
39
|
+
attr(val, parts.slice(1..-1).join('.'))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.substring(input, start, stop, reverse)
|
44
|
+
return nil if start >= stop || input.size < stop
|
45
|
+
|
46
|
+
return nil if input.chars.any? { |c| c.ord > 127 }
|
47
|
+
|
48
|
+
return input[start...stop] unless reverse
|
49
|
+
|
50
|
+
r_start = input.size - stop
|
51
|
+
r_stop = input.size - start
|
52
|
+
input[r_start...r_stop]
|
53
|
+
end
|
54
|
+
|
55
|
+
# stringEquals(value1: string, value2: string) bool
|
56
|
+
def self.string_equals?(value1, value2)
|
57
|
+
value1 == value2
|
58
|
+
end
|
59
|
+
|
60
|
+
# booleanEquals(value1: bool, value2: bool) bool
|
61
|
+
def self.boolean_equals?(value1, value2)
|
62
|
+
value1 == value2
|
63
|
+
end
|
64
|
+
|
65
|
+
# uriEncode(value: string) string
|
66
|
+
def self.uri_encode(value)
|
67
|
+
CGI.escape(value.encode('UTF-8')).gsub('+', '%20').gsub('%7E', '~')
|
68
|
+
end
|
69
|
+
|
70
|
+
# parseUrl(value: string) Option<URL>
|
71
|
+
def self.parse_url(value)
|
72
|
+
URL.new(value).as_json
|
73
|
+
rescue ArgumentError, URI::InvalidURIError
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
|
77
|
+
# isValidHostLabel(value: string, allowSubDomains: bool) bool
|
78
|
+
def self.valid_host_label?(value, allow_sub_domains = false)
|
79
|
+
return false if value.empty?
|
80
|
+
|
81
|
+
if allow_sub_domains
|
82
|
+
labels = value.split('.')
|
83
|
+
return labels.all? { |l| valid_host_label?(l) }
|
84
|
+
end
|
85
|
+
|
86
|
+
value =~ /\A(?!-)[a-zA-Z0-9-]{1,63}(?<!-)\z/
|
87
|
+
end
|
88
|
+
|
89
|
+
# AWS
|
90
|
+
|
91
|
+
# aws.partition(value: string) Option<Partition>
|
92
|
+
def self.aws_partition(value)
|
93
|
+
partition =
|
94
|
+
Aws::Partitions.find { |p| p.region?(value) } ||
|
95
|
+
Aws::Partitions.find { |p| value.match(p.region_regex) } ||
|
96
|
+
Aws::Partitions.find { |p| p.name == 'aws' }
|
97
|
+
|
98
|
+
return nil unless partition
|
99
|
+
|
100
|
+
partition.metadata
|
101
|
+
end
|
102
|
+
|
103
|
+
# aws.parseArn(value: string) Option<ARN>
|
104
|
+
def self.aws_parse_arn(value)
|
105
|
+
arn = Aws::ARNParser.parse(value)
|
106
|
+
json = arn.as_json
|
107
|
+
# HACK: because of poor naming and also requirement of splitting
|
108
|
+
resource = json.delete('resource')
|
109
|
+
json['resourceId'] = resource.split(%r{[:\/]}, -1)
|
110
|
+
json
|
111
|
+
rescue Aws::Errors::InvalidARNError
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
|
115
|
+
# aws.isVirtualHostableS3Bucket(value: string, allowSubDomains: bool) bool
|
116
|
+
def self.aws_virtual_hostable_s3_bucket?(value, allow_sub_domains = false)
|
117
|
+
!!(value.size < 64 &&
|
118
|
+
# regular naming rules
|
119
|
+
value =~ /^[a-z0-9][a-z0-9\-#{'.' if allow_sub_domains}]+[a-z0-9]$/ &&
|
120
|
+
# not IP address
|
121
|
+
value !~ /(\d+\.){3}\d+/ &&
|
122
|
+
# no dash and hyphen together
|
123
|
+
value !~ /[.-]{2}/)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# @api private
|
6
|
+
class Reference
|
7
|
+
def initialize(ref:)
|
8
|
+
@ref = ref
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :ref
|
12
|
+
|
13
|
+
def resolve(parameters, assigns)
|
14
|
+
if parameters.class.singleton_class::PARAM_MAP.key?(@ref)
|
15
|
+
member_name = parameters.class.singleton_class::PARAM_MAP[@ref]
|
16
|
+
parameters[member_name]
|
17
|
+
elsif assigns.key?(@ref)
|
18
|
+
assigns[@ref]
|
19
|
+
else
|
20
|
+
raise ArgumentError,
|
21
|
+
"Reference #{@ref} is not a param or an assigned value."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# @api private
|
6
|
+
class Rule
|
7
|
+
# Resolves a value that is a function, reference, or template string.
|
8
|
+
def resolve_value(value, parameters, assigns)
|
9
|
+
if value.is_a?(Hash) && value['fn']
|
10
|
+
Function.new(fn: value['fn'], argv: value['argv'])
|
11
|
+
.call(parameters, assigns)
|
12
|
+
elsif value.is_a?(Hash) && value['ref']
|
13
|
+
Reference.new(ref: value['ref']).resolve(parameters, assigns)
|
14
|
+
else
|
15
|
+
Templater.resolve(value, parameters, assigns)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# @api private
|
6
|
+
class RuleSet
|
7
|
+
def initialize(version:, service_id:, parameters:, rules:)
|
8
|
+
@version = version
|
9
|
+
@service_id = service_id
|
10
|
+
@parameters = parameters
|
11
|
+
@rules = RuleSet.rules_from_json(rules || [])
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :version
|
15
|
+
attr_reader :service_id
|
16
|
+
attr_reader :parameters
|
17
|
+
attr_reader :rules
|
18
|
+
|
19
|
+
def self.rules_from_json(rules_json)
|
20
|
+
rules_json.each.with_object([]) do |rule, rules|
|
21
|
+
if rule['type'] == 'endpoint'
|
22
|
+
rules << EndpointRule.new(
|
23
|
+
conditions: rule['conditions'],
|
24
|
+
endpoint: rule['endpoint'],
|
25
|
+
documentation: rule['documentation']
|
26
|
+
)
|
27
|
+
elsif rule['type'] == 'error'
|
28
|
+
rules << ErrorRule.new(
|
29
|
+
conditions: rule['conditions'],
|
30
|
+
error: rule['error'],
|
31
|
+
documentation: rule['documentation']
|
32
|
+
)
|
33
|
+
elsif rule['type'] == 'tree'
|
34
|
+
rules << TreeRule.new(
|
35
|
+
conditions: rule['conditions'],
|
36
|
+
rules: rule['rules'],
|
37
|
+
documentation: rule['documentation']
|
38
|
+
)
|
39
|
+
else
|
40
|
+
# should not happen
|
41
|
+
raise "Unknown endpoint rule type: #{rule}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Aws
|
2
|
+
module Endpoints
|
3
|
+
# @api private
|
4
|
+
class RulesProvider
|
5
|
+
def initialize(rule_set)
|
6
|
+
@rule_set = rule_set
|
7
|
+
end
|
8
|
+
|
9
|
+
def resolve_endpoint(parameters)
|
10
|
+
obj = resolve_rules(parameters)
|
11
|
+
case obj
|
12
|
+
when Endpoint
|
13
|
+
obj
|
14
|
+
when ArgumentError
|
15
|
+
raise obj
|
16
|
+
else
|
17
|
+
raise ArgumentError, 'No endpoint could be resolved'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def resolve_rules(parameters)
|
24
|
+
@rule_set.rules.each do |rule|
|
25
|
+
output = rule.match(parameters)
|
26
|
+
return output if output
|
27
|
+
end
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# Does substitutions for templated endpoint strings
|
6
|
+
# @api private
|
7
|
+
module Templater
|
8
|
+
class << self
|
9
|
+
def resolve(string, parameters, assigns)
|
10
|
+
# scans for strings in curly brackets {}
|
11
|
+
string.scan(/\{.+?\}/).each do |capture|
|
12
|
+
value = capture[1..-2] # strips curly brackets
|
13
|
+
string = string.gsub(capture, replace(value, parameters, assigns))
|
14
|
+
end
|
15
|
+
string
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Replaces the captured value with values from parameters or assign
|
21
|
+
def replace(capture, parameters, assigns)
|
22
|
+
# Pound sigil is used for getAttr calls
|
23
|
+
indexes = capture.split('#')
|
24
|
+
|
25
|
+
# no sigil found, just do substitution
|
26
|
+
if indexes.size == 1
|
27
|
+
extract_value(capture, parameters, assigns)
|
28
|
+
# sigil was found, need to call getAttr
|
29
|
+
elsif indexes.size == 2
|
30
|
+
ref, property = indexes
|
31
|
+
param = extract_value(ref, parameters, assigns)
|
32
|
+
Matchers.attr(param, property)
|
33
|
+
else
|
34
|
+
raise "Invalid templatable value: #{capture}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Checks both parameters and assigns hash for the referenced value
|
39
|
+
def extract_value(key, parameters, assigns)
|
40
|
+
if assigns.key?(key)
|
41
|
+
assigns[key]
|
42
|
+
elsif parameters.class.singleton_class::PARAM_MAP.key?(key)
|
43
|
+
member_name = parameters.class.singleton_class::PARAM_MAP[key]
|
44
|
+
parameters[member_name]
|
45
|
+
else
|
46
|
+
raise "Templatable value not found: #{key}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Aws
|
4
|
+
module Endpoints
|
5
|
+
# @api private
|
6
|
+
class TreeRule
|
7
|
+
def initialize(type: 'tree', conditions:, rules:, documentation: nil)
|
8
|
+
@type = type
|
9
|
+
@conditions = Condition.from_json(conditions)
|
10
|
+
@rules = RuleSet.rules_from_json(rules)
|
11
|
+
@documentation = documentation
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :type
|
15
|
+
attr_reader :conditions
|
16
|
+
attr_reader :error
|
17
|
+
attr_reader :documentation
|
18
|
+
|
19
|
+
def match(parameters, assigned = {})
|
20
|
+
assigns = assigned.dup
|
21
|
+
matched = conditions.all? do |condition|
|
22
|
+
output = condition.match?(parameters, assigns)
|
23
|
+
assigns = assigns.merge(condition.assigned) if condition.assign
|
24
|
+
output
|
25
|
+
end
|
26
|
+
resolve_rules(parameters, assigns) if matched
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def resolve_rules(parameters, assigns)
|
32
|
+
@rules.each do |rule|
|
33
|
+
output = rule.match(parameters, assigns)
|
34
|
+
return output if output
|
35
|
+
end
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|