MovableInkAWS 1.3.3 → 2.0.0

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: 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: []