esp_sdk 2.5.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile.lock +5 -3
- data/Guardfile +3 -1
- data/esp_sdk.gemspec +2 -1
- data/lib/esp/aws_clients.rb +2 -1
- data/lib/esp/commands/commands_tasks.rb +2 -1
- data/lib/esp/commands/console.rb +4 -0
- data/lib/esp/exceptions.rb +1 -0
- data/lib/esp/extensions/active_resource/dirty.rb +51 -0
- data/lib/esp/extensions/active_resource/formats/json_api_format.rb +5 -3
- data/lib/esp/extensions/active_resource/paginated_collection.rb +71 -38
- data/lib/esp/extensions/active_resource/validations.rb +4 -2
- data/lib/esp/external_account_creator.rb +4 -1
- data/lib/esp/resources/alert.rb +53 -42
- data/lib/esp/resources/cloud_trail_event.rb +18 -12
- data/lib/esp/resources/concerns/stat_totals.rb +70 -67
- data/lib/esp/resources/contact_request.rb +17 -14
- data/lib/esp/resources/custom_signature/definition.rb +46 -51
- data/lib/esp/resources/custom_signature/result/alert.rb +13 -5
- data/lib/esp/resources/custom_signature/result.rb +49 -53
- data/lib/esp/resources/custom_signature.rb +52 -61
- data/lib/esp/resources/dashboard.rb +11 -5
- data/lib/esp/resources/external_account.rb +59 -58
- data/lib/esp/resources/metadata.rb +21 -11
- data/lib/esp/resources/organization.rb +49 -39
- data/lib/esp/resources/region.rb +25 -28
- data/lib/esp/resources/report.rb +46 -44
- data/lib/esp/resources/reports/export/integration.rb +22 -13
- data/lib/esp/resources/resource.rb +4 -3
- data/lib/esp/resources/scan_interval.rb +19 -13
- data/lib/esp/resources/service.rb +17 -11
- data/lib/esp/resources/signature.rb +43 -53
- data/lib/esp/resources/stat.rb +72 -55
- data/lib/esp/resources/stat_custom_signature.rb +73 -65
- data/lib/esp/resources/stat_region.rb +76 -65
- data/lib/esp/resources/stat_service.rb +76 -65
- data/lib/esp/resources/stat_signature.rb +76 -65
- data/lib/esp/resources/sub_organization.rb +51 -60
- data/lib/esp/resources/suppression/region.rb +35 -30
- data/lib/esp/resources/suppression/signature.rb +35 -29
- data/lib/esp/resources/suppression/unique_identifier.rb +27 -22
- data/lib/esp/resources/suppression.rb +45 -34
- data/lib/esp/resources/tag.rb +20 -11
- data/lib/esp/resources/team.rb +56 -58
- data/lib/esp/resources/user.rb +35 -32
- data/lib/esp/version.rb +1 -1
- data/lib/esp.rb +39 -16
- data/lib/esp_sdk.rb +1 -0
- data/test/esp/extensions/active_resource/dirty_test.rb +81 -0
- data/test/esp/extensions/active_resource/formats/json_api_format_test.rb +8 -0
- data/test/esp/extensions/active_resource/paginated_collection_test.rb +7 -0
- data/test/esp/integration/json_api_format_integration_test.rb +5 -2
- data/test/esp/integration/organization_integration_test.rb +1 -1
- data/test/esp/resources/custom_signature_test.rb +15 -0
- data/test/factories/custom_signatures.rb +0 -10
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee71a8ce107cfd0be1c552e60e32ea3637c21eaa
|
4
|
+
data.tar.gz: f4087d8db9e1affb4f96a1eceae43ba3211673bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3f490d1f67a732b9b85daf1036d69af6b8295238ce9eb255b41f4fd10172106663e7e3bd7c7f45c7d0c12219b1a34bf68690bd0c12285c1cd25198fcf26aacd
|
7
|
+
data.tar.gz: 9ece944bf4867f36e4df3457e12c739b15d79dd0ebc729d9b5d2d47955e941b6b3e2042ef88a0fd9eec9fc35d77f052c113342bbbd06c346d1549dfcffb89f93
|
data/.gitignore
CHANGED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
|
+
## 2.6.0 - 2016-10-17
|
4
|
+
### Changed
|
5
|
+
- Only send changed attributes to API #39
|
6
|
+
- API now returns nested included relation data elements correctly. Change test to reflect corrected response. #40
|
7
|
+
- Calling `next_page` on queries without parameters (e.g. `ESP::ExternalAccount.all`) no longer errors. #35
|
8
|
+
- Silently ignore `null` entires if encountered in API responses. #69
|
9
|
+
- Switch from RDoc to Yard. #37
|
10
|
+
|
3
11
|
## 2.5.0 - 2016-07-20
|
4
12
|
### Added
|
5
13
|
- Add custom signature definitions and results. Code for a custom signature is now created/updated under a definition. Running a definition for an on demand test creates a result record which will have errors and alerts when completed.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
esp_sdk (2.
|
4
|
+
esp_sdk (2.6.0)
|
5
5
|
activeresource (~> 4.0.0)
|
6
6
|
api-auth (~> 2.0.0)
|
7
7
|
rack
|
@@ -107,7 +107,7 @@ GEM
|
|
107
107
|
rb-fsevent (0.9.6)
|
108
108
|
rb-inotify (0.9.5)
|
109
109
|
ffi (>= 0.5.0)
|
110
|
-
|
110
|
+
rdiscount (2.2.0.1)
|
111
111
|
rest-client (1.7.3)
|
112
112
|
mime-types (>= 1.16, < 3.0)
|
113
113
|
netrc (~> 0.7)
|
@@ -142,6 +142,7 @@ GEM
|
|
142
142
|
webmock (1.21.0)
|
143
143
|
addressable (>= 2.3.6)
|
144
144
|
crack (>= 0.3.2)
|
145
|
+
yard (0.9.5)
|
145
146
|
|
146
147
|
PLATFORMS
|
147
148
|
ruby
|
@@ -161,10 +162,11 @@ DEPENDENCIES
|
|
161
162
|
minitest-reporters
|
162
163
|
mocha
|
163
164
|
rake
|
164
|
-
|
165
|
+
rdiscount
|
165
166
|
rubocop
|
166
167
|
shoulda
|
167
168
|
webmock
|
169
|
+
yard
|
168
170
|
|
169
171
|
BUNDLED WITH
|
170
172
|
1.12.5
|
data/Guardfile
CHANGED
@@ -15,10 +15,12 @@
|
|
15
15
|
#
|
16
16
|
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
17
17
|
|
18
|
-
guard :minitest do
|
18
|
+
guard :minitest, all_on_start: false do
|
19
19
|
# with Minitest::Unit
|
20
20
|
watch(%r{^test/(.*)\/?test_(.*)\.rb$})
|
21
|
+
watch(%r{^test/.+_test\.rb$})
|
21
22
|
watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
|
23
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
22
24
|
watch(%r{^test/test_helper\.rb$}) { 'test' }
|
23
25
|
|
24
26
|
# with Minitest::Spec
|
data/esp_sdk.gemspec
CHANGED
@@ -33,9 +33,10 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency 'webmock'
|
34
34
|
spec.add_development_dependency 'coveralls'
|
35
35
|
spec.add_development_dependency 'factory_girl'
|
36
|
-
spec.add_development_dependency '
|
36
|
+
spec.add_development_dependency 'yard'
|
37
37
|
spec.add_development_dependency 'awesome_print'
|
38
38
|
spec.add_development_dependency 'aws-sdk'
|
39
|
+
spec.add_development_dependency 'rdiscount'
|
39
40
|
|
40
41
|
spec.add_dependency 'activeresource', '~> 4.0.0'
|
41
42
|
spec.add_dependency 'api-auth', '~> 2.0.0'
|
data/lib/esp/aws_clients.rb
CHANGED
data/lib/esp/commands/console.rb
CHANGED
data/lib/esp/exceptions.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Dirty
|
2
|
+
def original_attributes
|
3
|
+
@original_attributes ||= {}.with_indifferent_access
|
4
|
+
end
|
5
|
+
|
6
|
+
def original_attributes=(attributes = {})
|
7
|
+
@original_attributes = attributes.dup
|
8
|
+
end
|
9
|
+
|
10
|
+
def changed_attributes
|
11
|
+
attributes.select do |key, value|
|
12
|
+
next if value == original_attributes[key]
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Set the original attributes every time we instantiate an object from the api
|
19
|
+
# This happens on GET requests
|
20
|
+
module InstantiateWithOriginalAttributes
|
21
|
+
private
|
22
|
+
|
23
|
+
def instantiate_record(record, _prefix_options = {})
|
24
|
+
super(record, _prefix_options = {}).tap do |object|
|
25
|
+
object.original_attributes = object.attributes
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module LoadWithOriginalAttributes
|
31
|
+
# After sending to the API the object is reloaded with its attributes
|
32
|
+
# The persisted flag tells us it has been saved
|
33
|
+
def load(attributes, _remove_root = false, persisted = false)
|
34
|
+
if persisted
|
35
|
+
super.tap do |object|
|
36
|
+
object.original_attributes = object.attributes
|
37
|
+
end
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class ActiveResource::Base
|
45
|
+
include Dirty
|
46
|
+
prepend LoadWithOriginalAttributes
|
47
|
+
|
48
|
+
class << self
|
49
|
+
prepend InstantiateWithOriginalAttributes
|
50
|
+
end
|
51
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_support/json'
|
2
2
|
|
3
|
-
module ActiveResource
|
3
|
+
module ActiveResource
|
4
|
+
# @private
|
4
5
|
class ConnectionError
|
5
6
|
def initialize(response)
|
6
7
|
@response = if response.respond_to?(:response)
|
@@ -20,7 +21,8 @@ module ActiveResource # :nodoc: all
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
|
24
|
+
# @private
|
25
|
+
module Formats
|
24
26
|
module JsonAPIFormat
|
25
27
|
module_function
|
26
28
|
|
@@ -121,7 +123,7 @@ module ActiveResource # :nodoc: all
|
|
121
123
|
end
|
122
124
|
|
123
125
|
def self.merge_nested_included_objects(object, data, included)
|
124
|
-
assocs = included.select { |i| data.include?(
|
126
|
+
assocs = included.compact.select { |i| data.include?(i.slice('type', 'id')) }
|
125
127
|
# Remove the object from the included array to prevent an infinite loop if one of it's associations relates back to itself.
|
126
128
|
assoc_included = included.dup
|
127
129
|
assoc_included.delete(object)
|
@@ -1,12 +1,18 @@
|
|
1
1
|
require 'rack'
|
2
2
|
|
3
3
|
module ActiveResource
|
4
|
-
# Provides a mean to call the Evident.io API to easily retrieve paginated data
|
5
4
|
class PaginatedCollection < ActiveResource::Collection
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
# Internal variable used to construct queries.
|
6
|
+
# @return [Hash]
|
7
|
+
# @private
|
8
|
+
attr_reader :next_page_params, :previous_page_params, :last_page_params
|
9
|
+
# Internal variable used to construct queries.
|
10
|
+
# @return [Integer]
|
11
|
+
# @private
|
12
|
+
attr_accessor :from
|
13
|
+
|
14
|
+
# @private
|
15
|
+
def initialize(elements = [])
|
10
16
|
# If a collection is sent without the pagination links, then elements will just be an array.
|
11
17
|
if elements.is_a? Hash
|
12
18
|
super(elements['data'])
|
@@ -16,22 +22,24 @@ module ActiveResource
|
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
19
|
-
# Returns
|
25
|
+
# Returns the first page of results.
|
20
26
|
#
|
21
|
-
# Returns self
|
27
|
+
# Returns +self+ (and no API call is made) when already on the first page.
|
22
28
|
#
|
23
|
-
#
|
29
|
+
# @return [PaginatedCollection, self]
|
30
|
+
# @example
|
24
31
|
# alerts.current_page_number # => 5
|
25
32
|
# first_page = alerts.first_page
|
26
33
|
# alerts.current_page_number # => 5
|
27
34
|
# first_page.current_page_number # => 1
|
28
35
|
def first_page
|
29
|
-
previous_page? ?
|
36
|
+
previous_page? ? updated_collection(from: from, page: { number: 1 }) : self
|
30
37
|
end
|
31
38
|
|
32
39
|
# Updates the existing PaginatedCollection object with the first page of data when not on the first page.
|
33
40
|
#
|
34
|
-
#
|
41
|
+
# @return (see #first_page)
|
42
|
+
# @example
|
35
43
|
# alerts.current_page_number # => 5
|
36
44
|
# alerts.first_page!
|
37
45
|
# alerts.current_page_number # => 1
|
@@ -39,22 +47,24 @@ module ActiveResource
|
|
39
47
|
first_page.tap { |page| update_self(page) }
|
40
48
|
end
|
41
49
|
|
42
|
-
# Returns
|
50
|
+
# Returns the previous page of results.
|
43
51
|
#
|
44
|
-
# Returns self
|
52
|
+
# Returns +self+ (and no API call is made) when already on the first page.
|
45
53
|
#
|
46
|
-
#
|
54
|
+
# @return [PaginatedCollection, self]
|
55
|
+
# @example
|
47
56
|
# alerts.current_page_number # => 5
|
48
57
|
# previous_page = alerts.previous_page
|
49
58
|
# alerts.current_page_number # => 5
|
50
59
|
# previous_page.current_page_number # => 4
|
51
60
|
def previous_page
|
52
|
-
previous_page? ?
|
61
|
+
previous_page? ? updated_collection(previous_page_params.merge(from: from)) : self
|
53
62
|
end
|
54
63
|
|
55
64
|
# Updates the existing PaginatedCollection object with the previous page of data when not on the first page.
|
56
65
|
#
|
57
|
-
#
|
66
|
+
# @return (see #previous_page)
|
67
|
+
# @example
|
58
68
|
# alerts.current_page_number # => 5
|
59
69
|
# alerts.previous_page!
|
60
70
|
# alerts.current_page_number # => 4
|
@@ -62,22 +72,24 @@ module ActiveResource
|
|
62
72
|
previous_page.tap { |page| update_self(page) }
|
63
73
|
end
|
64
74
|
|
65
|
-
# Returns
|
75
|
+
# Returns the next page of results.
|
66
76
|
#
|
67
|
-
# Returns self
|
77
|
+
# Returns +self+ (and no API call is made) when already on the last page.
|
68
78
|
#
|
69
|
-
#
|
79
|
+
# @return [PaginatedCollection, self]
|
80
|
+
# @example
|
70
81
|
# alerts.current_page_number # => 5
|
71
82
|
# next_page = alerts.next_page
|
72
83
|
# alerts.current_page_number # => 5
|
73
84
|
# next_page.current_page_number # => 6
|
74
85
|
def next_page
|
75
|
-
next_page? ?
|
86
|
+
next_page? ? updated_collection(next_page_params.merge(from: from)) : self
|
76
87
|
end
|
77
88
|
|
78
89
|
# Updates the existing PaginatedCollection object with the last page of data when not on the last page.
|
79
90
|
#
|
80
|
-
#
|
91
|
+
# @return (see #next_page)
|
92
|
+
# @example
|
81
93
|
# alerts.current_page_number # => 5
|
82
94
|
# alerts.next_page!
|
83
95
|
# alerts.current_page_number # => 6
|
@@ -85,22 +97,24 @@ module ActiveResource
|
|
85
97
|
next_page.tap { |page| update_self(page) }
|
86
98
|
end
|
87
99
|
|
88
|
-
# Returns
|
100
|
+
# Returns the last page of results.
|
89
101
|
#
|
90
|
-
# Returns self
|
102
|
+
# Returns +self+ (and no API call is made) when already on the last page.
|
91
103
|
#
|
92
|
-
#
|
104
|
+
# @return [PaginatedCollection, self]
|
105
|
+
# @example
|
93
106
|
# alerts.current_page_number # => 5
|
94
107
|
# last_page = alerts.last_page
|
95
108
|
# alerts.current_page_number # => 5
|
96
109
|
# last_page.current_page_number # => 25
|
97
110
|
def last_page
|
98
|
-
!last_page? ?
|
111
|
+
!last_page? ? updated_collection(last_page_params.merge(from: from)) : self
|
99
112
|
end
|
100
113
|
|
101
114
|
# Updates the existing PaginatedCollection object with the last page of data when not on the last page.
|
102
115
|
#
|
103
|
-
#
|
116
|
+
# @return (see #last_page)
|
117
|
+
# @example
|
104
118
|
# alerts.current_page_number # => 5
|
105
119
|
# alerts.last_page!
|
106
120
|
# alerts.current_page_number # => 25
|
@@ -108,15 +122,14 @@ module ActiveResource
|
|
108
122
|
last_page.tap { |page| update_self(page) }
|
109
123
|
end
|
110
124
|
|
111
|
-
# Returns
|
112
|
-
#
|
113
|
-
# Returns self when +page_number+ == #current_page_number
|
125
|
+
# Returns the +page_number+ page of data.
|
114
126
|
#
|
115
|
-
#
|
127
|
+
# Returns +self+ when +page_number+ == +#current_page_number+
|
116
128
|
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
129
|
+
# @param page_number [Integer] The page number of the data wanted. Must be between 1 and +#last_page_number+.
|
130
|
+
# @return [PaginatedCollection, self]
|
131
|
+
# @raise [ArgumentError] if no page number or an out-of-bounds page number is supplied.
|
132
|
+
# @example
|
120
133
|
# alerts.current_page_number # => 5
|
121
134
|
# page = alerts.page(2)
|
122
135
|
# alerts.current_page_number # => 5
|
@@ -125,16 +138,14 @@ module ActiveResource
|
|
125
138
|
fail ArgumentError, "You must supply a page number." unless page_number.present?
|
126
139
|
fail ArgumentError, "Page number cannot be less than 1." if page_number.to_i < 1
|
127
140
|
fail ArgumentError, "Page number cannot be greater than the last page number." if page_number.to_i > last_page_number.to_i
|
128
|
-
page_number.to_i != current_page_number.to_i ?
|
141
|
+
page_number.to_i != current_page_number.to_i ? updated_collection(from: from, page: { number: page_number, size: (next_page_params || previous_page_params)['page']['size'] }) : self
|
129
142
|
end
|
130
143
|
|
131
144
|
# Returns a new PaginatedCollection with the +page_number+ page of data when not already on page +page_number+.
|
132
145
|
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
# ==== Example
|
146
|
+
# @param (see #page)
|
147
|
+
# @return (see #page)
|
148
|
+
# @example
|
138
149
|
# alerts.current_page_number # => 5
|
139
150
|
# alerts.page!(2)
|
140
151
|
# alerts.current_page_number # => 2
|
@@ -143,42 +154,64 @@ module ActiveResource
|
|
143
154
|
end
|
144
155
|
|
145
156
|
# The current page number of data.
|
157
|
+
#
|
158
|
+
# @return [String]
|
146
159
|
def current_page_number
|
147
160
|
(previous_page_number.to_i + 1).to_s
|
148
161
|
end
|
149
162
|
|
150
163
|
# The previous page number of data.
|
164
|
+
#
|
165
|
+
# @return [String, nil]
|
151
166
|
def previous_page_number
|
152
167
|
Hash(previous_page_params).fetch('page', {}).fetch('number', nil)
|
153
168
|
end
|
154
169
|
|
155
170
|
# The next page number of data.
|
171
|
+
#
|
172
|
+
# @return [String, nil]
|
156
173
|
def next_page_number
|
157
174
|
Hash(next_page_params).fetch('page', {}).fetch('number', nil)
|
158
175
|
end
|
159
176
|
|
160
177
|
# The last page number of data.
|
178
|
+
#
|
179
|
+
# @return [String, nil]
|
161
180
|
def last_page_number
|
162
181
|
Hash(last_page_params).fetch('page', {}).fetch('number', nil)
|
163
182
|
end
|
164
183
|
|
165
184
|
# Returns whether or not there is a previous page of data in the collection.
|
185
|
+
#
|
186
|
+
# @return [Boolean]
|
166
187
|
def previous_page?
|
167
188
|
!previous_page_number.nil?
|
168
189
|
end
|
169
190
|
|
170
191
|
# Returns whether or not there is a next page of data in the collection.
|
192
|
+
#
|
193
|
+
# @return [Boolean]
|
171
194
|
def next_page?
|
172
195
|
!next_page_number.nil?
|
173
196
|
end
|
174
197
|
|
175
198
|
# Returns whether or not the collection is on the last page.
|
199
|
+
#
|
200
|
+
# @return [Boolean]
|
176
201
|
def last_page?
|
177
202
|
last_page_number.nil?
|
178
203
|
end
|
179
204
|
|
180
205
|
private
|
181
206
|
|
207
|
+
# Start a new collection.
|
208
|
+
#
|
209
|
+
# @param params [Hash]
|
210
|
+
# @return [PaginatedCollection]
|
211
|
+
def updated_collection(params)
|
212
|
+
resource_class.where(original_params.merge(params))
|
213
|
+
end
|
214
|
+
|
182
215
|
def update_self(page)
|
183
216
|
@elements = page.elements
|
184
217
|
@next_page_params = page.next_page_params
|
@@ -1,8 +1,9 @@
|
|
1
|
-
module ActiveResource
|
1
|
+
module ActiveResource
|
2
|
+
# @private
|
2
3
|
module Validations
|
3
4
|
# Loads the set of remote errors into the object's Errors based on the
|
4
5
|
# content-type of the error-block received.
|
5
|
-
def load_remote_errors(remote_errors, save_cache = false)
|
6
|
+
def load_remote_errors(remote_errors, save_cache = false)
|
6
7
|
if self.class.format == ActiveResource::Formats::JsonAPIFormat
|
7
8
|
errors.from_json_api(remote_errors.response.body, save_cache)
|
8
9
|
elsif self.class.format == ActiveResource::Formats[:json]
|
@@ -11,6 +12,7 @@ module ActiveResource # :nodoc: all
|
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
15
|
+
# @private
|
14
16
|
class Errors
|
15
17
|
def from_json_api(json, save_cache = false)
|
16
18
|
raw_errors = decoded_errors(json)
|
@@ -1,4 +1,5 @@
|
|
1
|
-
module ESP
|
1
|
+
module ESP
|
2
|
+
# @private
|
2
3
|
class AddExternalAccountError < StandardError
|
3
4
|
EXIT_CODES = {
|
4
5
|
'12 characters' => 98,
|
@@ -20,6 +21,7 @@ module ESP # :nodoc: all
|
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
24
|
+
# @private
|
23
25
|
class ExternalAccountCreator
|
24
26
|
attr_reader :aws
|
25
27
|
|
@@ -27,6 +29,7 @@ module ESP # :nodoc: all
|
|
27
29
|
@aws = AWSClients.new
|
28
30
|
end
|
29
31
|
|
32
|
+
# @return [ESP::ExternalAccount]
|
30
33
|
def create
|
31
34
|
fail ESP::AddExternalAccountError, aws.errors.full_messages.join(', ') unless aws.valid?
|
32
35
|
|