MovableInkAWS 1.0.13 → 1.0.18

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: 4b350dcc6432c0f218c528e9779bde52cfc535e605529a0513c05b02e605e396
4
- data.tar.gz: 7197977f915549ff7c19623a446fd05c24768bf2773a72851e8cd98bcc619ec8
3
+ metadata.gz: c67a1debb22324f3f567c390c5a5baf61c714b56567712dd6269dd044b2ed9dd
4
+ data.tar.gz: 9b02840d52d5ee4a4f99060ec274f9938617247e1df9468efbb352fb2ff2285f
5
5
  SHA512:
6
- metadata.gz: 9f6130a4a62193455450492c46fa1efde90b8b96c912637550bbc6797ed5fc45b28517295ed624f5668d3ea9efd19a3bc7e90c4afea8a6ab7699507ce38961c1
7
- data.tar.gz: 363122ff9d3f11c9d04def581a25251139efdf7b2cb3d1c29ca2cc22d43622b2fda5731ff235016e5f0855ffb78becfb41294bd57f424982f349d051a8ae868e
6
+ metadata.gz: f547de79011e7fc83bb33db7d905da20c55d8a5308ef6e539193bfabacbcf1a5f0cde3a417ec454b6c24f0361ec1bef5b0d05ebbba5730f1cc5427643be28550
7
+ data.tar.gz: 87ad9c72f123ef2e70d3ff35d89eeef5dac3948144668e88554de402eff5b71e733144d2d7dc9fd51473662a3e36fc479525c1ff01a63ac0d34c1046d1d2d2c7
@@ -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.13)
4
+ MovableInkAWS (1.0.18)
5
5
  aws-sdk-athena (~> 1)
6
6
  aws-sdk-autoscaling (~> 1)
7
7
  aws-sdk-cloudwatch (~> 1)
@@ -19,48 +19,48 @@ PATH
19
19
  GEM
20
20
  remote: https://rubygems.org/
21
21
  specs:
22
- aws-eventstream (1.0.3)
23
- aws-partitions (1.280.0)
24
- aws-sdk-athena (1.22.0)
22
+ aws-eventstream (1.1.0)
23
+ aws-partitions (1.322.0)
24
+ aws-sdk-athena (1.26.0)
25
25
  aws-sdk-core (~> 3, >= 3.71.0)
26
26
  aws-sigv4 (~> 1.1)
27
- aws-sdk-autoscaling (1.32.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.33.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.90.1)
34
- aws-eventstream (~> 1.0, >= 1.0.2)
33
+ aws-sdk-core (3.97.0)
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.147.0)
38
+ aws-sdk-ec2 (1.164.0)
39
39
  aws-sdk-core (~> 3, >= 3.71.0)
40
40
  aws-sigv4 (~> 1.1)
41
- aws-sdk-elasticache (1.29.0)
41
+ aws-sdk-elasticache (1.35.0)
42
42
  aws-sdk-core (~> 3, >= 3.71.0)
43
43
  aws-sigv4 (~> 1.1)
44
- aws-sdk-kms (1.29.0)
44
+ aws-sdk-kms (1.32.0)
45
45
  aws-sdk-core (~> 3, >= 3.71.0)
46
46
  aws-sigv4 (~> 1.1)
47
- aws-sdk-rds (1.78.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.30.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.60.2)
54
- aws-sdk-core (~> 3, >= 3.83.0)
53
+ aws-sdk-s3 (1.67.0)
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.21.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.71.0)
60
+ aws-sdk-ssm (1.79.0)
61
61
  aws-sdk-core (~> 3, >= 3.71.0)
62
62
  aws-sigv4 (~> 1.1)
63
- aws-sigv4 (1.1.1)
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)
@@ -69,7 +69,7 @@ GEM
69
69
  jmespath (1.4.0)
70
70
  mime-types (3.3.1)
71
71
  mime-types-data (~> 3.2015)
72
- mime-types-data (3.2019.1009)
72
+ mime-types-data (3.2020.0512)
73
73
  multi_xml (0.6.0)
74
74
  rspec (3.9.0)
75
75
  rspec-core (~> 3.9.0)
@@ -93,4 +93,4 @@ DEPENDENCIES
93
93
  rspec (~> 3.6)
94
94
 
95
95
  BUNDLED WITH
96
- 1.17.1
96
+ 1.17.3
@@ -59,6 +59,7 @@ module MovableInk
59
59
  return yield
60
60
  rescue Aws::EC2::Errors::RequestLimitExceeded,
61
61
  Aws::EC2::Errors::ResourceAlreadyAssociated,
62
+ Aws::EC2::Errors::Unavailable,
62
63
  Aws::SNS::Errors::ThrottledException,
63
64
  Aws::AutoScaling::Errors::ThrottledException,
64
65
  Aws::S3::Errors::SlowDown,
@@ -76,12 +77,15 @@ module MovableInk
76
77
  notify_and_sleep(sleep_time, $!.class)
77
78
  end
78
79
  rescue Aws::Errors::ServiceError => e
79
- message = "#{e.class}: #{e.message}\nFrom `#{e.backtrace.last.gsub("`","'")}`"
80
+ message = "#{e.class}: #{e.message}\nFrom #{$0}\n```\n#{e.backtrace.first(3).join("\n").gsub("`","'")}\n```"
80
81
  notify_slack(subject: 'Unhandled AWS API Error', message: message)
81
82
  puts message
82
83
  raise MovableInk::AWS::Errors::ServiceError
83
84
  end
84
85
  end
86
+ message = "From: #{$0}\n```\n#{Thread.current.backtrace.first(3).join("\n").gsub("`","'")}\n```"
87
+ notify_slack(subject: "AWS API failed after #{tries} attempts", message: message)
88
+ puts message
85
89
  raise MovableInk::AWS::Errors::FailedWithBackoff
86
90
  end
87
91
 
@@ -29,23 +29,12 @@ module MovableInk
29
29
  raise MovableInk::AWS::Errors::NoEnvironmentTagError
30
30
  end
31
31
 
32
- def thopter_filter
33
- [{
34
- name: 'tag:mi:roles',
35
- values: ['*thopter*']
36
- },
37
- {
38
- name: 'tag:mi:env',
39
- values: [mi_env]
40
- },
41
- {
42
- name: 'instance-state-name',
43
- values: ['running']
44
- }]
45
- end
46
-
47
32
  def thopter_instance
48
- @thopter_instance ||= load_all_instances('us-east-1', filter: thopter_filter)
33
+ @thopter_instance ||= all_instances(region: 'us-east-1').select do |instance|
34
+ instance.tags.select{ |tag| tag.key == 'mi:roles' }.detect do |tag|
35
+ tag.value.include?('thopter')
36
+ end
37
+ end
49
38
  end
50
39
 
51
40
  def all_instances(region: my_region, no_filter: false)
@@ -102,18 +91,27 @@ module MovableInk
102
91
  @me ||= all_instances.select{|instance| instance.instance_id == instance_id}.first rescue nil
103
92
  end
104
93
 
105
- def instances(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false)
106
- instances = all_instances(region: region).select { |instance|
107
- instance.tags.select{ |tag| tag.key == 'mi:roles' }.detect { |tag|
108
- roles = tag.value.split(/\s*,\s*/)
109
- if exact_match
110
- roles == [role]
111
- else
112
- exclude_roles.push('decommissioned')
113
- roles.include?(role) && !roles.any? { |role| exclude_roles.include?(role) }
114
- end
94
+ def instances(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false, use_cache: true)
95
+ roles = role.split(/\s*,\s*/)
96
+ if use_cache == false
97
+ filter = default_filter.push({
98
+ name: 'tag:mi:roles',
99
+ values: roles
100
+ })
101
+ instances = load_all_instances(my_region, filter: filter)
102
+ else
103
+ instances = all_instances(region: region).select { |instance|
104
+ instance.tags.select{ |tag| tag.key == 'mi:roles' }.detect { |tag|
105
+ tag_roles = tag.value.split(/\s*,\s*/)
106
+ if exact_match
107
+ tag_roles == roles
108
+ else
109
+ exclude_roles.push('decommissioned')
110
+ tag_roles.any? { |tag_role| roles.include?(tag_role) } && !tag_roles.any? { |role| exclude_roles.include?(role) }
111
+ end
112
+ }
115
113
  }
116
- }
114
+ end
117
115
 
118
116
  if availability_zone
119
117
  instances.select { |instance|
@@ -129,15 +127,15 @@ module MovableInk
129
127
  end
130
128
 
131
129
  def statsd_host
132
- instance_ip_addresses_by_role(role: 'statsd', availability_zone: availability_zone).sample
130
+ instance_ip_addresses_by_role(role: 'statsd', availability_zone: availability_zone, use_cache: false).sample
133
131
  end
134
132
 
135
133
  def private_ip_addresses(instances)
136
134
  instances.map(&:private_ip_address)
137
135
  end
138
136
 
139
- def instance_ip_addresses_by_role(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false)
140
- private_ip_addresses(instances(role: role, exclude_roles: exclude_roles, region: region, availability_zone: availability_zone, exact_match: exact_match))
137
+ def instance_ip_addresses_by_role(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false, use_cache: true)
138
+ private_ip_addresses(instances(role: role, exclude_roles: exclude_roles, region: region, availability_zone: availability_zone, exact_match: exact_match, use_cache: use_cache))
141
139
  end
142
140
 
143
141
  def instance_ip_addresses_by_role_ordered(role:, exclude_roles: [], region: my_region, exact_match: false)
@@ -1,5 +1,5 @@
1
1
  module MovableInk
2
2
  class AWS
3
- VERSION = '1.0.13'
3
+ VERSION = '1.0.18'
4
4
  end
5
5
  end
@@ -42,9 +42,9 @@ describe MovableInk::AWS do
42
42
  ec2 = Aws::EC2::Client.new(stub_responses: true)
43
43
  ec2.stub_responses(:describe_instances, 'RequestLimitExceeded')
44
44
 
45
- expect(aws).to receive(:notify_slack).exactly(9).times
45
+ expect(aws).to receive(:notify_slack).exactly(10).times
46
46
  expect(aws).to receive(:sleep).exactly(9).times.and_return(true)
47
- expect(STDOUT).to receive(:puts).exactly(9).times
47
+ expect(STDOUT).to receive(:puts).exactly(10).times
48
48
 
49
49
  aws.run_with_backoff { ec2.describe_instances } rescue nil
50
50
  end
@@ -64,9 +64,9 @@ describe MovableInk::AWS do
64
64
  ec2 = Aws::EC2::Client.new(stub_responses: true)
65
65
  ec2.stub_responses(:describe_instances, 'RequestLimitExceeded')
66
66
 
67
- expect(aws).to receive(:notify_slack).exactly(1).times
67
+ expect(aws).to receive(:notify_slack).exactly(2).times
68
68
  expect(aws).to receive(:sleep).exactly(9).times.and_return(true)
69
- expect(STDOUT).to receive(:puts).exactly(1).times
69
+ expect(STDOUT).to receive(:puts).exactly(2).times
70
70
 
71
71
  aws.run_with_backoff(quiet: true) { ec2.describe_instances } rescue nil
72
72
  end
@@ -77,6 +77,8 @@ describe MovableInk::AWS do
77
77
  ec2.stub_responses(:describe_instances, 'RequestLimitExceeded')
78
78
 
79
79
  expect(aws).to receive(:notify_and_sleep).exactly(9).times
80
+ expect(aws).to receive(:notify_slack).exactly(1).times
81
+ expect(STDOUT).to receive(:puts).exactly(1).times
80
82
  expect{ aws.run_with_backoff { ec2.describe_instances } }.to raise_error(MovableInk::AWS::Errors::FailedWithBackoff)
81
83
  end
82
84
  end
@@ -153,18 +153,6 @@ describe MovableInk::AWS::EC2 do
153
153
  availability_zone: availability_zone
154
154
  }
155
155
  },
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
156
  ]])
169
157
  }
170
158
 
@@ -183,8 +171,8 @@ describe MovableInk::AWS::EC2 do
183
171
  context "instances" do
184
172
  let(:my_availability_zone) { 'us-east-1a' }
185
173
  let(:other_availability_zone) { 'us-east-1b' }
186
- let(:instance_data) { ec2.stub_data(:describe_instances, reservations: [
187
- instances: [
174
+ let(:instances) {
175
+ [
188
176
  {
189
177
  tags: [
190
178
  {
@@ -252,12 +240,54 @@ describe MovableInk::AWS::EC2 do
252
240
  placement: {
253
241
  availability_zone: other_availability_zone
254
242
  }
243
+ },
244
+ {
245
+ tags: [
246
+ {
247
+ key: 'mi:name',
248
+ value: 'instance5'
249
+ },
250
+ {
251
+ key: 'mi:roles',
252
+ value: 'app_db'
253
+ }
254
+ ],
255
+ instance_id: 'i-321cba',
256
+ private_ip_address: '10.0.0.5',
257
+ placement: {
258
+ availability_zone: other_availability_zone
259
+ }
255
260
  }
256
- ]])
261
+ ]
262
+ }
263
+ let(:single_role_instance_data) { ec2.stub_data(:describe_instances, reservations: [
264
+ instances: instances.select { |instance|
265
+ instance[:tags].detect { |tag| tag[:key] == 'mi:roles' && tag[:value] == 'app_db_replica' }
266
+ }
267
+ ])}
268
+ let(:multi_role_instance_data) { ec2.stub_data(:describe_instances, reservations: [
269
+ instances: instances.select { |instance|
270
+ instance[:tags].detect { |tag|
271
+ tag[:key] == 'mi:roles' && ['app_db', 'app_db_replica'].any?(tag[:value])
272
+ }
273
+ }
274
+ ])}
275
+ let(:all_roles_instance_data) { ec2.stub_data(:describe_instances, reservations: [ instances: instances ])
257
276
  }
258
277
 
259
278
  before(:each) do
260
- ec2.stub_responses(:describe_instances, instance_data)
279
+ ec2.stub_responses(:describe_instances, -> (context) {
280
+ if (context.params[:filters].length == 2)
281
+ all_roles_instance_data
282
+ else
283
+ role_filter = context.params[:filters].detect { |filter| filter[:name] == 'tag:mi:roles' }
284
+ if role_filter[:values].length == 1
285
+ single_role_instance_data
286
+ else
287
+ multi_role_instance_data
288
+ end
289
+ end
290
+ })
261
291
  allow(aws).to receive(:mi_env).and_return('test')
262
292
  allow(aws).to receive(:availability_zone).and_return(my_availability_zone)
263
293
  allow(aws).to receive(:my_region).and_return('us-east-1')
@@ -283,6 +313,16 @@ describe MovableInk::AWS::EC2 do
283
313
  expect(instances.map{|i| i.tags.first.value }).to eq(['instance4'])
284
314
  end
285
315
 
316
+ it "returns roles with exactly the specified role, letting the API to the filtering" do
317
+ instances = aws.instances(role: 'app_db_replica', use_cache: false)
318
+ expect(instances.map{|i| i.tags.first.value }).to eq(['instance4'])
319
+ end
320
+
321
+ it "returns roles with any of the specified roles, letting the API to the filtering" do
322
+ instances = aws.instances(role: 'app_db,app_db_replica', use_cache: false)
323
+ expect(instances.map{|i| i.tags.first.value }).to eq(['instance4', 'instance5'])
324
+ end
325
+
286
326
  it "excludes requested roles" do
287
327
  instances = aws.instances(role: 'app_db_replica', exclude_roles: ['db'])
288
328
  expect(instances.map{|i| i.tags.first.value }).to eq(['instance1', 'instance4'])
@@ -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.13
4
+ version: 1.0.18
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-08 00:00:00.000000000 Z
11
+ date: 2020-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-core