MovableInkAWS 1.3.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a474efe41182db10e521fd3df11b259261591f6113f2ab71cf66b0e603199578
4
- data.tar.gz: 527f38ea7a18d93366b1fe9cbf16f75c3d8f79c8d6f29d6b44e8a4b7eb92d82f
3
+ metadata.gz: ca127d84b2a782fac6a45b9f2ab7d39891ea9b58c1f72897198363fdec217b03
4
+ data.tar.gz: 1bead2930395e8a2f53b7dce303a5904790072e78f7abf965514f29af736d7ac
5
5
  SHA512:
6
- metadata.gz: 778adf6177659e449ee6a4c4fea6007120d7397bd5acd109111dfaf3f673af6289e1e9b82f8b8c2a34583c86d9b567283836cedbaa822a183bdd730b074fb9e7
7
- data.tar.gz: 6f94b899d09790472b843e2fd69f895ed349f97a4b21443d413b61713d464c8eb864cdfce1a495139a2eb67c31cd36ab3fe0f485d333ab2b5f58e178c87ee167
6
+ metadata.gz: 6225008398613de6fd9d239394029bf141252ed6adca815068bd1a88be2df8e7a6947a3a7055aaab41d4833c00edeb770e90b191395f139597fb7a5455de47c9
7
+ data.tar.gz: 5bf8debaf1f7afafb249b494d26c5142c5d5ce147721e112183c5c6f66a5d7a543c1af7d5f4d3cf4fbe701763a50042c5ed47d6a288db357b0b364c51fbb3713
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ gemspec
3
3
 
4
4
  group :test do
5
5
  gem 'rspec', '~> 3.6'
6
+ gem 'webmock'
6
7
  end
@@ -15,11 +15,14 @@ PATH
15
15
  aws-sdk-sns (~> 1)
16
16
  aws-sdk-ssm (~> 1)
17
17
  aws-sigv4 (~> 1.1)
18
+ diplomat (= 2.4.2)
18
19
  httparty (= 0.16.3)
19
20
 
20
21
  GEM
21
22
  remote: https://rubygems.org/
22
23
  specs:
24
+ addressable (2.7.0)
25
+ public_suffix (>= 2.0.2, < 5.0)
23
26
  aws-eventstream (1.1.0)
24
27
  aws-partitions (1.383.0)
25
28
  aws-sdk-athena (1.33.0)
@@ -66,7 +69,16 @@ GEM
66
69
  aws-sigv4 (~> 1.1)
67
70
  aws-sigv4 (1.2.2)
68
71
  aws-eventstream (~> 1, >= 1.0.2)
72
+ crack (0.4.3)
73
+ safe_yaml (~> 1.0.0)
74
+ deep_merge (1.2.1)
69
75
  diff-lcs (1.3)
76
+ diplomat (2.4.2)
77
+ deep_merge (~> 1.0, >= 1.0.1)
78
+ faraday (>= 0.9, < 1.1.0)
79
+ faraday (1.0.1)
80
+ multipart-post (>= 1.2, < 3)
81
+ hashdiff (1.0.0)
70
82
  httparty (0.16.3)
71
83
  mime-types (~> 3.0)
72
84
  multi_xml (>= 0.5.2)
@@ -75,6 +87,8 @@ GEM
75
87
  mime-types-data (~> 3.2015)
76
88
  mime-types-data (3.2020.0512)
77
89
  multi_xml (0.6.0)
90
+ multipart-post (2.1.1)
91
+ public_suffix (4.0.5)
78
92
  rspec (3.9.0)
79
93
  rspec-core (~> 3.9.0)
80
94
  rspec-expectations (~> 3.9.0)
@@ -88,6 +102,11 @@ GEM
88
102
  diff-lcs (>= 1.2.0, < 2.0)
89
103
  rspec-support (~> 3.9.0)
90
104
  rspec-support (3.9.3)
105
+ safe_yaml (1.0.5)
106
+ webmock (3.7.6)
107
+ addressable (>= 2.3.6)
108
+ crack (>= 0.3.2)
109
+ hashdiff (>= 0.4.0, < 2.0.0)
91
110
 
92
111
  PLATFORMS
93
112
  ruby
@@ -95,6 +114,7 @@ PLATFORMS
95
114
  DEPENDENCIES
96
115
  MovableInkAWS!
97
116
  rspec (~> 3.6)
117
+ webmock
98
118
 
99
119
  BUNDLED WITH
100
120
  2.1.3
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_runtime_dependency 'aws-sdk-ssm', '~> 1'
24
24
  s.add_runtime_dependency 'aws-sigv4', '~> 1.1'
25
25
  s.add_runtime_dependency 'httparty', '0.16.3'
26
+ s.add_runtime_dependency 'diplomat', '2.4.2'
26
27
 
27
28
  all_files = `git ls-files`.split("\n")
28
29
  test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,4 +1,5 @@
1
1
  require 'aws-sdk-ec2'
2
+ require 'diplomat'
2
3
 
3
4
  module MovableInk
4
5
  class AWS
@@ -75,7 +76,7 @@ module MovableInk
75
76
  @me ||= all_instances.select{|instance| instance.instance_id == instance_id}.first rescue nil
76
77
  end
77
78
 
78
- def instances(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false, use_cache: true)
79
+ def instances_with_ec2_discovery(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false, use_cache: true)
79
80
  roles = role.split(/\s*,\s*/)
80
81
  if use_cache == false
81
82
  filter = default_filter.push({
@@ -106,6 +107,64 @@ module MovableInk
106
107
  end
107
108
  end
108
109
 
110
+ def instances_with_consul_discovery(role:, region: my_region, availability_zone: nil)
111
+ if role == nil || role == ''
112
+ raise MovableInk::AWS::Errors::RoleNameRequiredError
113
+ end
114
+
115
+ if role.include?('_')
116
+ raise MovableInk::AWS::Errors::RoleNameInvalidError
117
+ end
118
+
119
+ Diplomat.configure do |config|
120
+ config.url = "https://localhost:8501"
121
+ config.options = { ssl: { verify: false } }
122
+ end
123
+
124
+ consul_instances = Diplomat::Service.get(role, :all, { :dc => datacenter(region: region), :stale => true, :cached => true }).map { |node|
125
+ OpenStruct.new (
126
+ {
127
+ private_ip_address: node.Address,
128
+ instance_id: node.NodeMeta['instance_id'],
129
+ tags: [
130
+ {
131
+ key: 'Name',
132
+ value: node.Node
133
+ },
134
+ {
135
+ key: 'mi:roles',
136
+ value: node.NodeMeta['mi_roles']
137
+ },
138
+ {
139
+ key: 'mi:monitoring_roles',
140
+ value: node.NodeMeta['mi_monitoring_roles']
141
+ }
142
+ ],
143
+ placement: {
144
+ availability_zone: node.NodeMeta['availability_zone']
145
+ }
146
+ })
147
+ }
148
+
149
+ if availability_zone
150
+ consul_instances.select { |consul_instance|
151
+ consul_instance.placement[:availability_zone] == availability_zone
152
+ }
153
+ else
154
+ consul_instances
155
+ end
156
+ end
157
+
158
+ def instances(role:, exclude_roles: [], region: my_region, availability_zone: nil, exact_match: false, use_cache: true, discovery_type: 'ec2')
159
+ if discovery_type == 'ec2'
160
+ instances_with_ec2_discovery(role: role, exclude_roles: exclude_roles, region: region, availability_zone: availability_zone, exact_match: exact_match, use_cache: use_cache)
161
+ elsif discovery_type == 'consul'
162
+ instances_with_consul_discovery(role: role, region: region, availability_zone: availability_zone)
163
+ else
164
+ raise MovableInk::AWS::Errors::InvalidDiscoveryTypeError
165
+ end
166
+ end
167
+
109
168
  def thopter
110
169
  private_ip_addresses(thopter_instance).first
111
170
  end
@@ -5,6 +5,9 @@ module MovableInk
5
5
  class FailedWithBackoff < StandardError; end
6
6
  class EC2Required < StandardError; end
7
7
  class NoEnvironmentTagError < StandardError; end
8
+ class InvalidDiscoveryTypeError < StandardError; end
9
+ class RoleNameRequiredError < StandardError; end
10
+ class RoleNameInvalidError < StandardError; end
8
11
  end
9
12
  end
10
13
  end
@@ -1,5 +1,5 @@
1
1
  module MovableInk
2
2
  class AWS
3
- VERSION = '1.3.3'
3
+ VERSION = '2.0.0'
4
4
  end
5
5
  end
@@ -1,4 +1,5 @@
1
1
  require_relative '../lib/movable_ink/aws'
2
+ require 'webmock/rspec'
2
3
 
3
4
  describe MovableInk::AWS::EC2 do
4
5
  context "outside EC2" do
@@ -21,6 +22,7 @@ describe MovableInk::AWS::EC2 do
21
22
  end
22
23
 
23
24
  context "inside EC2" do
25
+ WebMock.allow_net_connect!
24
26
  let(:aws) { MovableInk::AWS.new }
25
27
  let(:ec2) { Aws::EC2::Client.new(stub_responses: true) }
26
28
  let(:tag_data) { ec2.stub_data(:describe_tags, tags: [
@@ -305,6 +307,165 @@ describe MovableInk::AWS::EC2 do
305
307
  end
306
308
  end
307
309
 
310
+ context "instances with consul discovery" do
311
+ let(:my_availability_zone) { 'us-east-1a' }
312
+ let(:my_datacenter) { 'iad' }
313
+ let(:other_availability_zone) { 'us-east-1b' }
314
+ let(:consul_app_service_instances) {
315
+ [
316
+ {
317
+ Node: 'app_instance1',
318
+ Address: '10.0.0.1',
319
+ Datacenter: my_datacenter,
320
+ NodeMeta:
321
+ {
322
+ availability_zone: my_availability_zone,
323
+ instance_id: 'i-12345',
324
+ mi_monitoring_roles: 'app',
325
+ mi_roles: 'app'
326
+ },
327
+ ServiceID: 'app',
328
+ ServiceName: 'app',
329
+ ServiceTags: ['foo', 'bar'],
330
+ ServicePort: 80,
331
+ },
332
+ {
333
+ Node: 'app_instance2',
334
+ Address: '10.0.0.2',
335
+ Datacenter: my_datacenter,
336
+ NodeMeta:
337
+ {
338
+ availability_zone: my_availability_zone,
339
+ instance_id: 'i-54321',
340
+ mi_monitoring_roles: 'app',
341
+ mi_roles: 'app'
342
+ },
343
+ ServiceID: 'app',
344
+ ServiceName: 'app',
345
+ ServiceTags: ['foo', 'bar'],
346
+ ServicePort: 80,
347
+ }
348
+ ]
349
+ }
350
+
351
+ let(:consul_ojos_service_instances) {
352
+ [
353
+ {
354
+ Node: 'ojos_instance1',
355
+ Address: '10.0.0.3',
356
+ Datacenter: my_datacenter,
357
+ NodeMeta:
358
+ {
359
+ availability_zone: my_availability_zone,
360
+ instance_id: 'i-123abc',
361
+ mi_monitoring_roles: 'ojos',
362
+ mi_roles: 'ojos'
363
+ },
364
+ ServiceID: 'ojos',
365
+ ServiceName: 'ojos',
366
+ ServiceTags: ['foo', 'bar'],
367
+ ServicePort: 2702,
368
+ },
369
+ {
370
+ Node: 'ojos_instance2',
371
+ Address: '10.0.0.4',
372
+ Datacenter: my_datacenter,
373
+ NodeMeta:
374
+ {
375
+ availability_zone: other_availability_zone,
376
+ instance_id: 'i-zyx987',
377
+ mi_monitoring_roles: 'ojos',
378
+ mi_roles: 'ojos'
379
+ },
380
+ ServiceID: 'ojos',
381
+ ServiceName: 'ojos',
382
+ ServiceTags: ['foo', 'bar'],
383
+ ServicePort: 2702,
384
+ },
385
+ {
386
+ Node: 'ojos_instance3',
387
+ Address: '10.0.0.5',
388
+ Datacenter: my_datacenter,
389
+ NodeMeta:
390
+ {
391
+ availability_zone: other_availability_zone,
392
+ instance_id: 'i-987654',
393
+ mi_monitoring_roles: 'ojos',
394
+ mi_roles: 'ojos'
395
+ },
396
+ ServiceID: 'ojos',
397
+ ServiceName: 'ojos',
398
+ ServiceTags: ['foo', 'bar'],
399
+ ServicePort: 2702,
400
+ }
401
+ ]
402
+ }
403
+
404
+ before(:each) do
405
+ allow(aws).to receive(:mi_env).and_return('test')
406
+ allow(aws).to receive(:availability_zone).and_return(my_availability_zone)
407
+ allow(aws).to receive(:my_region).and_return('us-east-1')
408
+ allow(aws).to receive(:ec2).and_return(ec2)
409
+ end
410
+
411
+ it "returns an error if no role is defined" do
412
+ expect{ aws.instances(role: nil, discovery_type: 'consul') }.to raise_error(MovableInk::AWS::Errors::RoleNameRequiredError)
413
+ end
414
+
415
+ it "returns an error if an invalid role is passed" do
416
+ expect{ aws.instances(role: 'asset_proxy', discovery_type: 'consul') }.to raise_error(MovableInk::AWS::Errors::RoleNameInvalidError)
417
+ end
418
+
419
+ it "returns all instances matching a consul service" do
420
+ miaws = double(MovableInk::AWS)
421
+ allow(miaws).to receive(:my_region).and_return('us-east-1')
422
+
423
+ json = JSON.generate(consul_app_service_instances)
424
+ stub_request(:get, "https://localhost:8501/v1/catalog/service/app?dc=#{my_datacenter}&stale=true&cached=true").
425
+ with(
426
+ headers: {
427
+ 'Accept'=>'*/*',
428
+ 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
429
+ 'User-Agent'=>'Faraday v1.0.1'
430
+ }).
431
+ to_return(status: 200, body: json, headers: {})
432
+
433
+ app_instances = aws.instances(role: 'app', discovery_type: 'consul')
434
+ expect(app_instances.map{|i| i.tags.first[:value]}).to eq(['app_instance1', 'app_instance2'])
435
+
436
+ json = JSON.generate(consul_ojos_service_instances)
437
+ stub_request(:get, "https://localhost:8501/v1/catalog/service/ojos?dc=#{my_datacenter}&stale=true&cached=true").
438
+ with(
439
+ headers: {
440
+ 'Accept'=>'*/*',
441
+ 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
442
+ 'User-Agent'=>'Faraday v1.0.1'
443
+ }).
444
+ to_return(status: 200, body: json, headers: {})
445
+
446
+ ojos_instances = aws.instances(role: 'ojos', discovery_type: 'consul')
447
+ expect(ojos_instances.map{|i| i.tags.first[:value ]}).to eq(['ojos_instance1', 'ojos_instance2', 'ojos_instance3'])
448
+ end
449
+
450
+ it "returns all instances matching a consul service filtered by availability_zone" do
451
+ miaws = double(MovableInk::AWS)
452
+ allow(miaws).to receive(:my_region).and_return('us-east-1')
453
+
454
+ json = JSON.generate(consul_ojos_service_instances)
455
+ stub_request(:get, "https://localhost:8501/v1/catalog/service/ojos?dc=iad&stale=true&cached=true").
456
+ with(
457
+ headers: {
458
+ 'Accept'=>'*/*',
459
+ 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
460
+ 'User-Agent'=>'Faraday v1.0.1'
461
+ }).
462
+ to_return(status: 200, body: json, headers: {})
463
+
464
+ ojos_instances = aws.instances(role: 'ojos', availability_zone: other_availability_zone, discovery_type: 'consul')
465
+ expect(ojos_instances.map{|i| i.tags.first[:value]}).to eq(['ojos_instance2', 'ojos_instance3'])
466
+ end
467
+ end
468
+
308
469
  context "ordered roles" do
309
470
  let(:my_availability_zone) { 'us-east-1a' }
310
471
  let(:other_availability_zone) { 'us-east-1b' }
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.3.3
4
+ version: 2.0.0
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-10-20 00:00:00.000000000 Z
11
+ date: 2020-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-core
@@ -206,6 +206,20 @@ dependencies:
206
206
  - - '='
207
207
  - !ruby/object:Gem::Version
208
208
  version: 0.16.3
209
+ - !ruby/object:Gem::Dependency
210
+ name: diplomat
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - '='
214
+ - !ruby/object:Gem::Version
215
+ version: 2.4.2
216
+ type: :runtime
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - '='
221
+ - !ruby/object:Gem::Version
222
+ version: 2.4.2
209
223
  description: AWS Utility methods for MovableInk
210
224
  email: mchesler@movableink.com
211
225
  executables: []