MovableInkAWS 1.0.15 → 1.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68e65c324f0ef9ce4d4c2607ecc050ff7ee04070b819200e3ad34805e56f3d0f
4
- data.tar.gz: 2868c07278470a371c0ac88eb13985566d4a881eb2d944b63a118d45d033844e
3
+ metadata.gz: a81a0a05ca7f2dbd8f8b6d3e966e1e89f09ad5f38c0fcc27c19ed4e19177bc3c
4
+ data.tar.gz: fb1e2c6618c0790bbaa9dcc5a5c4dba8d62bd9d0a7de5159079443f98ce71fb1
5
5
  SHA512:
6
- metadata.gz: e1da5c8861b8cec7a0b60056177b6e1b5121e9c87108bb4385edc4c32786a33f4ad306a0735eb1327c28b32302e26bb9303e61422488cb3010bf2d9b0524203b
7
- data.tar.gz: bb5bfc766d27391c49e8f981efd0abac83cedb7bac6446dc6b399706b91dc77dc8586c72ae482eb04b4b7734ed398ee620ba9fa8095a3f1ef5e83543f84b463a
6
+ metadata.gz: be347e295cd8c88b75d19d114e3a2f8ea8ca03377b2d5a6d521c2179453d994c3d620f5dc87e5b76bdc1603e1acc560d38d1d5354f9b6b5499b0da94f6acb98f
7
+ data.tar.gz: a2b8833b9e95b7e980c112caf2516a85922df954744beda219b6b9150539bf7caa786ef1c79563a83e74eb1c13ebb349838245e186f6545f3c92262fdc0c1fe1
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.2
4
+ - 2.5
5
+ - 2.6
5
6
 
6
7
  bundler_args: "--retry=3"
7
8
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- MovableInkAWS (1.0.15)
4
+ MovableInkAWS (1.1.4)
5
5
  aws-sdk-athena (~> 1)
6
6
  aws-sdk-autoscaling (~> 1)
7
7
  aws-sdk-cloudwatch (~> 1)
@@ -20,47 +20,47 @@ GEM
20
20
  remote: https://rubygems.org/
21
21
  specs:
22
22
  aws-eventstream (1.1.0)
23
- aws-partitions (1.321.0)
24
- aws-sdk-athena (1.25.0)
23
+ aws-partitions (1.325.0)
24
+ aws-sdk-athena (1.27.0)
25
25
  aws-sdk-core (~> 3, >= 3.71.0)
26
26
  aws-sigv4 (~> 1.1)
27
- aws-sdk-autoscaling (1.36.0)
27
+ aws-sdk-autoscaling (1.37.0)
28
28
  aws-sdk-core (~> 3, >= 3.71.0)
29
29
  aws-sigv4 (~> 1.1)
30
- aws-sdk-cloudwatch (1.37.0)
30
+ aws-sdk-cloudwatch (1.38.0)
31
31
  aws-sdk-core (~> 3, >= 3.71.0)
32
32
  aws-sigv4 (~> 1.1)
33
- aws-sdk-core (3.96.1)
33
+ aws-sdk-core (3.97.1)
34
34
  aws-eventstream (~> 1, >= 1.0.2)
35
35
  aws-partitions (~> 1, >= 1.239.0)
36
36
  aws-sigv4 (~> 1.1)
37
37
  jmespath (~> 1.0)
38
- aws-sdk-ec2 (1.163.0)
38
+ aws-sdk-ec2 (1.165.0)
39
39
  aws-sdk-core (~> 3, >= 3.71.0)
40
40
  aws-sigv4 (~> 1.1)
41
- aws-sdk-elasticache (1.34.0)
41
+ aws-sdk-elasticache (1.36.0)
42
42
  aws-sdk-core (~> 3, >= 3.71.0)
43
43
  aws-sigv4 (~> 1.1)
44
- aws-sdk-kms (1.31.0)
44
+ aws-sdk-kms (1.33.0)
45
45
  aws-sdk-core (~> 3, >= 3.71.0)
46
46
  aws-sigv4 (~> 1.1)
47
- aws-sdk-rds (1.84.0)
47
+ aws-sdk-rds (1.85.0)
48
48
  aws-sdk-core (~> 3, >= 3.71.0)
49
49
  aws-sigv4 (~> 1.1)
50
- aws-sdk-route53 (1.34.0)
50
+ aws-sdk-route53 (1.35.0)
51
51
  aws-sdk-core (~> 3, >= 3.71.0)
52
52
  aws-sigv4 (~> 1.1)
53
- aws-sdk-s3 (1.66.0)
53
+ aws-sdk-s3 (1.67.1)
54
54
  aws-sdk-core (~> 3, >= 3.96.1)
55
55
  aws-sdk-kms (~> 1)
56
56
  aws-sigv4 (~> 1.1)
57
- aws-sdk-sns (1.23.0)
57
+ aws-sdk-sns (1.24.0)
58
58
  aws-sdk-core (~> 3, >= 3.71.0)
59
59
  aws-sigv4 (~> 1.1)
60
- aws-sdk-ssm (1.78.0)
60
+ aws-sdk-ssm (1.80.0)
61
61
  aws-sdk-core (~> 3, >= 3.71.0)
62
62
  aws-sigv4 (~> 1.1)
63
- aws-sigv4 (1.1.3)
63
+ aws-sigv4 (1.1.4)
64
64
  aws-eventstream (~> 1.0, >= 1.0.2)
65
65
  diff-lcs (1.3)
66
66
  httparty (0.16.3)
@@ -75,15 +75,15 @@ GEM
75
75
  rspec-core (~> 3.9.0)
76
76
  rspec-expectations (~> 3.9.0)
77
77
  rspec-mocks (~> 3.9.0)
78
- rspec-core (3.9.0)
79
- rspec-support (~> 3.9.0)
80
- rspec-expectations (3.9.0)
78
+ rspec-core (3.9.2)
79
+ rspec-support (~> 3.9.3)
80
+ rspec-expectations (3.9.2)
81
81
  diff-lcs (>= 1.2.0, < 2.0)
82
82
  rspec-support (~> 3.9.0)
83
- rspec-mocks (3.9.0)
83
+ rspec-mocks (3.9.1)
84
84
  diff-lcs (>= 1.2.0, < 2.0)
85
85
  rspec-support (~> 3.9.0)
86
- rspec-support (3.9.0)
86
+ rspec-support (3.9.3)
87
87
 
88
88
  PLATFORMS
89
89
  ruby
@@ -93,4 +93,4 @@ DEPENDENCIES
93
93
  rspec (~> 3.6)
94
94
 
95
95
  BUNDLED WITH
96
- 1.17.3
96
+ 2.1.3
@@ -1,4 +1,5 @@
1
1
  require_relative 'aws/errors'
2
+ require_relative 'aws/metadata'
2
3
  require_relative 'aws/ec2'
3
4
  require_relative 'aws/sns'
4
5
  require_relative 'aws/autoscaling'
@@ -13,6 +14,7 @@ require 'aws-sdk-cloudwatch'
13
14
 
14
15
  module MovableInk
15
16
  class AWS
17
+ include Metadata
16
18
  include EC2
17
19
  include SNS
18
20
  include Autoscaling
@@ -77,12 +79,15 @@ module MovableInk
77
79
  notify_and_sleep(sleep_time, $!.class)
78
80
  end
79
81
  rescue Aws::Errors::ServiceError => e
80
- message = "#{e.class}: #{e.message}\nFrom `#{e.backtrace.last.gsub("`","'")}`"
82
+ message = "#{e.class}: #{e.message}\nFrom #{$0}\n```\n#{e.backtrace.first(3).join("\n").gsub("`","'")}\n```"
81
83
  notify_slack(subject: 'Unhandled AWS API Error', message: message)
82
84
  puts message
83
85
  raise MovableInk::AWS::Errors::ServiceError
84
86
  end
85
87
  end
88
+ message = "From: #{$0}\n```\n#{Thread.current.backtrace.first(3).join("\n").gsub("`","'")}\n```"
89
+ notify_slack(subject: "AWS API failed after #{tries} attempts", message: message)
90
+ puts message
86
91
  raise MovableInk::AWS::Errors::FailedWithBackoff
87
92
  end
88
93
 
@@ -90,14 +95,6 @@ module MovableInk
90
95
  self.class.regions
91
96
  end
92
97
 
93
- def availability_zone
94
- @availability_zone ||= begin
95
- az = `ec2metadata --availability-zone 2>/dev/null`.chomp
96
- raise(MovableInk::AWS::Errors::EC2Required) if az.empty?
97
- az
98
- end
99
- end
100
-
101
98
  def my_region
102
99
  @my_region ||= availability_zone.chop
103
100
  end
@@ -63,14 +63,6 @@ module MovableInk
63
63
  end
64
64
  end
65
65
 
66
- def instance_id
67
- @instance_id ||= begin
68
- id = `ec2metadata --instance-id 2>/dev/null`.chomp
69
- raise(MovableInk::AWS::Errors::EC2Required) if id.empty?
70
- id
71
- end
72
- end
73
-
74
66
  def instance_tags
75
67
  @instance_tags ||= run_with_backoff(quiet: true) do
76
68
  ec2.describe_tags({
@@ -79,30 +71,31 @@ module MovableInk
79
71
  end
80
72
  end
81
73
 
82
- def private_ipv4
83
- @ipv4 ||= begin
84
- ipv4 = `ec2metadata --local-ipv4 2>/dev/null`.chomp
85
- raise(MovableInk::AWS::Errors::EC2Required) if ipv4.empty?
86
- ipv4
87
- end
88
- end
89
-
90
74
  def me
91
75
  @me ||= all_instances.select{|instance| instance.instance_id == instance_id}.first rescue nil
92
76
  end
93
77
 
94
- def instances(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false)
95
- instances = all_instances(region: region).select { |instance|
96
- instance.tags.select{ |tag| tag.key == 'mi:roles' }.detect { |tag|
97
- roles = tag.value.split(/\s*,\s*/)
98
- if exact_match
99
- roles == [role]
100
- else
101
- exclude_roles.push('decommissioned')
102
- roles.include?(role) && !roles.any? { |role| exclude_roles.include?(role) }
103
- end
78
+ def instances(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false, use_cache: true)
79
+ roles = role.split(/\s*,\s*/)
80
+ if use_cache == false
81
+ filter = default_filter.push({
82
+ name: 'tag:mi:roles',
83
+ values: roles
84
+ })
85
+ instances = load_all_instances(region, filter: filter)
86
+ else
87
+ instances = all_instances(region: region).select { |instance|
88
+ instance.tags.select{ |tag| tag.key == 'mi:roles' }.detect { |tag|
89
+ tag_roles = tag.value.split(/\s*,\s*/)
90
+ if exact_match
91
+ tag_roles == roles
92
+ else
93
+ exclude_roles.push('decommissioned')
94
+ tag_roles.any? { |tag_role| roles.include?(tag_role) } && !tag_roles.any? { |role| exclude_roles.include?(role) }
95
+ end
96
+ }
104
97
  }
105
- }
98
+ end
106
99
 
107
100
  if availability_zone
108
101
  instances.select { |instance|
@@ -118,15 +111,15 @@ module MovableInk
118
111
  end
119
112
 
120
113
  def statsd_host
121
- instance_ip_addresses_by_role(role: 'statsd', availability_zone: availability_zone).sample
114
+ instance_ip_addresses_by_role(role: 'statsd', availability_zone: availability_zone, use_cache: false).sample
122
115
  end
123
116
 
124
117
  def private_ip_addresses(instances)
125
118
  instances.map(&:private_ip_address)
126
119
  end
127
120
 
128
- def instance_ip_addresses_by_role(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false)
129
- private_ip_addresses(instances(role: role, exclude_roles: exclude_roles, region: region, availability_zone: availability_zone, exact_match: exact_match))
121
+ def instance_ip_addresses_by_role(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false, use_cache: true)
122
+ private_ip_addresses(instances(role: role, exclude_roles: exclude_roles, region: region, availability_zone: availability_zone, exact_match: exact_match, use_cache: use_cache))
130
123
  end
131
124
 
132
125
  def instance_ip_addresses_by_role_ordered(role:, exclude_roles: [], region: my_region, exact_match: false)
@@ -0,0 +1,62 @@
1
+ require 'net/http'
2
+
3
+ module MovableInk
4
+ class AWS
5
+ module Metadata
6
+ def http
7
+ @http ||= begin
8
+ http = Net::HTTP.new("169.254.169.254", 80)
9
+ http.open_timeout = 1
10
+ http.read_timeout = 1
11
+ http
12
+ end
13
+ end
14
+
15
+ def retrieve_metadata(key)
16
+ request = Net::HTTP::Get.new("/latest/meta-data/#{key}")
17
+ request['X-aws-ec2-metadata-token'] = imds_token
18
+ response = http.request(request)
19
+ response.body
20
+ rescue
21
+ ""
22
+ end
23
+
24
+ def availability_zone
25
+ @availability_zone ||= begin
26
+ az = retrieve_metadata('placement/availability-zone')
27
+ raise(MovableInk::AWS::Errors::EC2Required) if az.empty?
28
+ az
29
+ end
30
+ end
31
+
32
+ def instance_id
33
+ @instance_id ||= begin
34
+ id = retrieve_metadata('instance-id')
35
+ raise(MovableInk::AWS::Errors::EC2Required) if id.empty?
36
+ id
37
+ end
38
+ end
39
+
40
+ def private_ipv4
41
+ @ipv4 ||= begin
42
+ ipv4 = retrieve_metadata('local-ipv4')
43
+ raise(MovableInk::AWS::Errors::EC2Required) if ipv4.empty?
44
+ ipv4
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def imds_token
51
+ begin
52
+ request = Net::HTTP::Put.new('/latest/api/token')
53
+ request['X-aws-ec2-metadata-token-ttl-seconds'] = 120
54
+ response = http.request(request)
55
+ response.body
56
+ rescue
57
+ nil
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,5 +1,5 @@
1
1
  module MovableInk
2
2
  class AWS
3
- VERSION = '1.0.15'
3
+ VERSION = '1.1.4'
4
4
  end
5
5
  end
@@ -2,15 +2,6 @@ require_relative '../lib/movable_ink/aws'
2
2
 
3
3
  describe MovableInk::AWS do
4
4
  context "outside EC2" do
5
- it "should raise an error if EC2 is required" do
6
- aws = MovableInk::AWS.new
7
- allow(aws).to receive(:`).with('ec2metadata --instance-id 2>/dev/null').and_return("")
8
- allow(aws).to receive(:`).with('ec2metadata --availability-zone 2>/dev/null').and_return("")
9
-
10
- expect{ aws.instance_id }.to raise_error(MovableInk::AWS::Errors::EC2Required)
11
- expect{ aws.availability_zone }.to raise_error(MovableInk::AWS::Errors::EC2Required)
12
- end
13
-
14
5
  it 'doesnt raise an error if instance_id is set' do
15
6
  aws = MovableInk::AWS.new(instance_id: 'i-987654321')
16
7
  expect(aws.instance_id).to eq('i-987654321')
@@ -18,21 +9,9 @@ describe MovableInk::AWS do
18
9
  end
19
10
 
20
11
  context "inside EC2" do
21
- it "should call ec2metadata to get the instance ID" do
22
- aws = MovableInk::AWS.new
23
- expect(aws).to receive(:`).with('ec2metadata --instance-id 2>/dev/null').and_return("i-12345\n")
24
- expect(aws.instance_id).to eq('i-12345')
25
- end
26
-
27
- it "should call ec2metadata to get the availability zone" do
28
- aws = MovableInk::AWS.new
29
- expect(aws).to receive(:`).with('ec2metadata --availability-zone 2>/dev/null').and_return("us-east-1a\n")
30
- expect(aws.availability_zone).to eq('us-east-1a')
31
- end
32
-
33
12
  it "should find the datacenter by region" do
34
13
  aws = MovableInk::AWS.new
35
- expect(aws).to receive(:`).with('ec2metadata --availability-zone 2>/dev/null').and_return("us-east-1a\n")
14
+ expect(aws).to receive(:retrieve_metadata).with('placement/availability-zone').and_return("us-east-1a")
36
15
  expect(aws.datacenter).to eq('iad')
37
16
  end
38
17
 
@@ -42,9 +21,9 @@ describe MovableInk::AWS do
42
21
  ec2 = Aws::EC2::Client.new(stub_responses: true)
43
22
  ec2.stub_responses(:describe_instances, 'RequestLimitExceeded')
44
23
 
45
- expect(aws).to receive(:notify_slack).exactly(9).times
24
+ expect(aws).to receive(:notify_slack).exactly(10).times
46
25
  expect(aws).to receive(:sleep).exactly(9).times.and_return(true)
47
- expect(STDOUT).to receive(:puts).exactly(9).times
26
+ expect(STDOUT).to receive(:puts).exactly(10).times
48
27
 
49
28
  aws.run_with_backoff { ec2.describe_instances } rescue nil
50
29
  end
@@ -64,9 +43,9 @@ describe MovableInk::AWS do
64
43
  ec2 = Aws::EC2::Client.new(stub_responses: true)
65
44
  ec2.stub_responses(:describe_instances, 'RequestLimitExceeded')
66
45
 
67
- expect(aws).to receive(:notify_slack).exactly(1).times
46
+ expect(aws).to receive(:notify_slack).exactly(2).times
68
47
  expect(aws).to receive(:sleep).exactly(9).times.and_return(true)
69
- expect(STDOUT).to receive(:puts).exactly(1).times
48
+ expect(STDOUT).to receive(:puts).exactly(2).times
70
49
 
71
50
  aws.run_with_backoff(quiet: true) { ec2.describe_instances } rescue nil
72
51
  end
@@ -77,6 +56,8 @@ describe MovableInk::AWS do
77
56
  ec2.stub_responses(:describe_instances, 'RequestLimitExceeded')
78
57
 
79
58
  expect(aws).to receive(:notify_and_sleep).exactly(9).times
59
+ expect(aws).to receive(:notify_slack).exactly(1).times
60
+ expect(STDOUT).to receive(:puts).exactly(1).times
80
61
  expect{ aws.run_with_backoff { ec2.describe_instances } }.to raise_error(MovableInk::AWS::Errors::FailedWithBackoff)
81
62
  end
82
63
  end
@@ -4,17 +4,11 @@ describe MovableInk::AWS::EC2 do
4
4
  context "outside EC2" do
5
5
  it "should raise an error if trying to load mi_env outside of EC2" do
6
6
  aws = MovableInk::AWS.new
7
- allow(aws).to receive(:`).with('ec2metadata --instance-id 2>/dev/null').and_return("")
8
- allow(aws).to receive(:`).with('ec2metadata --availability-zone 2>/dev/null').and_return("")
7
+ allow(aws).to receive(:retrieve_metadata).with('instance-id').and_return("")
8
+ allow(aws).to receive(:retrieve_metadata).with('placement/availability-zone').and_return("")
9
9
  expect{ aws.mi_env }.to raise_error(MovableInk::AWS::Errors::EC2Required)
10
10
  end
11
11
 
12
- it 'should raise an error if trying to load private_ipv4 outside of EC2' do
13
- aws = MovableInk::AWS.new
14
- allow(aws).to receive(:`).with('ec2metadata --local-ipv4 2>/dev/null').and_return('')
15
- expect{ aws.private_ipv4 }.to raise_error(MovableInk::AWS::Errors::EC2Required)
16
- end
17
-
18
12
  it "should use the provided environment" do
19
13
  aws = MovableInk::AWS.new(environment: 'test')
20
14
  expect(aws.mi_env).to eq('test')
@@ -67,12 +61,6 @@ describe MovableInk::AWS::EC2 do
67
61
  expect(aws.mi_env).to eq('test')
68
62
  end
69
63
 
70
- it 'calls ec2metadata to get the private ipv4 address of the instance' do
71
- aws = MovableInk::AWS.new
72
- allow(aws).to receive(:`).with('ec2metadata --local-ipv4 2>/dev/null').and_return('10.0.0.1')
73
- expect(aws.private_ipv4).to eq('10.0.0.1')
74
- end
75
-
76
64
  context 'instance_tags' do
77
65
  it 'returns the tags of the current instance' do
78
66
  ec2.stub_responses(:describe_tags, tag_data)
@@ -153,18 +141,6 @@ describe MovableInk::AWS::EC2 do
153
141
  availability_zone: availability_zone
154
142
  }
155
143
  },
156
- {
157
- tags: [
158
- {
159
- key: 'mi:roles',
160
- value: 'something_else'
161
- }
162
- ],
163
- private_ip_address: '10.0.0.3',
164
- placement: {
165
- availability_zone: availability_zone
166
- }
167
- }
168
144
  ]])
169
145
  }
170
146
 
@@ -183,8 +159,8 @@ describe MovableInk::AWS::EC2 do
183
159
  context "instances" do
184
160
  let(:my_availability_zone) { 'us-east-1a' }
185
161
  let(:other_availability_zone) { 'us-east-1b' }
186
- let(:instance_data) { ec2.stub_data(:describe_instances, reservations: [
187
- instances: [
162
+ let(:instances) {
163
+ [
188
164
  {
189
165
  tags: [
190
166
  {
@@ -252,12 +228,54 @@ describe MovableInk::AWS::EC2 do
252
228
  placement: {
253
229
  availability_zone: other_availability_zone
254
230
  }
231
+ },
232
+ {
233
+ tags: [
234
+ {
235
+ key: 'mi:name',
236
+ value: 'instance5'
237
+ },
238
+ {
239
+ key: 'mi:roles',
240
+ value: 'app_db'
241
+ }
242
+ ],
243
+ instance_id: 'i-321cba',
244
+ private_ip_address: '10.0.0.5',
245
+ placement: {
246
+ availability_zone: other_availability_zone
247
+ }
255
248
  }
256
- ]])
249
+ ]
250
+ }
251
+ let(:single_role_instance_data) { ec2.stub_data(:describe_instances, reservations: [
252
+ instances: instances.select { |instance|
253
+ instance[:tags].detect { |tag| tag[:key] == 'mi:roles' && tag[:value] == 'app_db_replica' }
254
+ }
255
+ ])}
256
+ let(:multi_role_instance_data) { ec2.stub_data(:describe_instances, reservations: [
257
+ instances: instances.select { |instance|
258
+ instance[:tags].detect { |tag|
259
+ tag[:key] == 'mi:roles' && ['app_db', 'app_db_replica'].any?(tag[:value])
260
+ }
261
+ }
262
+ ])}
263
+ let(:all_roles_instance_data) { ec2.stub_data(:describe_instances, reservations: [ instances: instances ])
257
264
  }
258
265
 
259
266
  before(:each) do
260
- ec2.stub_responses(:describe_instances, instance_data)
267
+ ec2.stub_responses(:describe_instances, -> (context) {
268
+ if (context.params[:filters].length == 2)
269
+ all_roles_instance_data
270
+ else
271
+ role_filter = context.params[:filters].detect { |filter| filter[:name] == 'tag:mi:roles' }
272
+ if role_filter[:values].length == 1
273
+ single_role_instance_data
274
+ else
275
+ multi_role_instance_data
276
+ end
277
+ end
278
+ })
261
279
  allow(aws).to receive(:mi_env).and_return('test')
262
280
  allow(aws).to receive(:availability_zone).and_return(my_availability_zone)
263
281
  allow(aws).to receive(:my_region).and_return('us-east-1')
@@ -283,6 +301,16 @@ describe MovableInk::AWS::EC2 do
283
301
  expect(instances.map{|i| i.tags.first.value }).to eq(['instance4'])
284
302
  end
285
303
 
304
+ it "returns roles with exactly the specified role, letting the API to the filtering" do
305
+ instances = aws.instances(role: 'app_db_replica', use_cache: false)
306
+ expect(instances.map{|i| i.tags.first.value }).to eq(['instance4'])
307
+ end
308
+
309
+ it "returns roles with any of the specified roles, letting the API to the filtering" do
310
+ instances = aws.instances(role: 'app_db,app_db_replica', use_cache: false)
311
+ expect(instances.map{|i| i.tags.first.value }).to eq(['instance4', 'instance5'])
312
+ end
313
+
286
314
  it "excludes requested roles" do
287
315
  instances = aws.instances(role: 'app_db_replica', exclude_roles: ['db'])
288
316
  expect(instances.map{|i| i.tags.first.value }).to eq(['instance1', 'instance4'])
@@ -0,0 +1,40 @@
1
+ require_relative '../lib/movable_ink/aws'
2
+
3
+ describe MovableInk::AWS::Metadata do
4
+ context 'outside ec2' do
5
+ it 'should raise an error if EC2 is required' do
6
+ aws = MovableInk::AWS.new
7
+ allow(aws).to receive(:retrieve_metadata).with('instance-id').and_return("")
8
+ allow(aws).to receive(:retrieve_metadata).with('placement/availability-zone').and_return("")
9
+
10
+ expect{ aws.instance_id }.to raise_error(MovableInk::AWS::Errors::EC2Required)
11
+ expect{ aws.availability_zone }.to raise_error(MovableInk::AWS::Errors::EC2Required)
12
+ end
13
+
14
+ it 'should raise an error if trying to load private_ipv4 outside of EC2' do
15
+ aws = MovableInk::AWS.new
16
+ allow(aws).to receive(:retrieve_metadata).with('local-ipv4').and_return('')
17
+ expect{ aws.private_ipv4 }.to raise_error(MovableInk::AWS::Errors::EC2Required)
18
+ end
19
+ end
20
+
21
+ context 'inside ec2' do
22
+ it 'calls the EC2 metadata service to get the private ipv4 address of the instance' do
23
+ aws = MovableInk::AWS.new
24
+ allow(aws).to receive(:retrieve_metadata).with('local-ipv4').and_return('10.0.0.1')
25
+ expect(aws.private_ipv4).to eq('10.0.0.1')
26
+ end
27
+
28
+ it 'calls the EC2 metadata service to get the instance ID' do
29
+ aws = MovableInk::AWS.new
30
+ expect(aws).to receive(:retrieve_metadata).with('instance-id').and_return("i-12345")
31
+ expect(aws.instance_id).to eq('i-12345')
32
+ end
33
+
34
+ it 'calls the EC2 metadata service to get the availability zone' do
35
+ aws = MovableInk::AWS.new
36
+ expect(aws).to receive(:retrieve_metadata).with('placement/availability-zone').and_return("us-east-1a")
37
+ expect(aws.availability_zone).to eq('us-east-1a')
38
+ end
39
+ end
40
+ end
@@ -82,6 +82,8 @@ describe MovableInk::AWS::SSM do
82
82
  allow(aws).to receive(:ssm_client).and_return(1)
83
83
  allow(aws).to receive(:ssm_client_failover).and_return(2)
84
84
  allow(aws).to receive(:notify_and_sleep).and_return(nil)
85
+ allow(aws).to receive(:notify_slack).and_return(nil)
86
+ allow(STDOUT).to receive(:puts).and_return(nil)
85
87
 
86
88
  results = []
87
89
  calls = 0
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: MovableInkAWS
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.15
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Chesler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-27 00:00:00.000000000 Z
11
+ date: 2020-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-core
@@ -212,6 +212,7 @@ files:
212
212
  - lib/movable_ink/aws/ec2.rb
213
213
  - lib/movable_ink/aws/elasticache.rb
214
214
  - lib/movable_ink/aws/errors.rb
215
+ - lib/movable_ink/aws/metadata.rb
215
216
  - lib/movable_ink/aws/route53.rb
216
217
  - lib/movable_ink/aws/s3.rb
217
218
  - lib/movable_ink/aws/sns.rb
@@ -221,6 +222,7 @@ files:
221
222
  - spec/aws_spec.rb
222
223
  - spec/ec2_spec.rb
223
224
  - spec/elasticache_spec.rb
225
+ - spec/metadata_spec.rb
224
226
  - spec/route53_spec.rb
225
227
  - spec/s3_spec.rb
226
228
  - spec/sns_spec.rb