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 +4 -4
- data/.travis.yml +2 -1
- data/Gemfile.lock +21 -21
- data/lib/movable_ink/aws.rb +6 -9
- data/lib/movable_ink/aws/ec2.rb +23 -30
- data/lib/movable_ink/aws/metadata.rb +62 -0
- data/lib/movable_ink/version.rb +1 -1
- data/spec/aws_spec.rb +7 -26
- data/spec/ec2_spec.rb +58 -30
- data/spec/metadata_spec.rb +40 -0
- data/spec/ssm_spec.rb +2 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a81a0a05ca7f2dbd8f8b6d3e966e1e89f09ad5f38c0fcc27c19ed4e19177bc3c
|
4
|
+
data.tar.gz: fb1e2c6618c0790bbaa9dcc5a5c4dba8d62bd9d0a7de5159079443f98ce71fb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be347e295cd8c88b75d19d114e3a2f8ea8ca03377b2d5a6d521c2179453d994c3d620f5dc87e5b76bdc1603e1acc560d38d1d5354f9b6b5499b0da94f6acb98f
|
7
|
+
data.tar.gz: a2b8833b9e95b7e980c112caf2516a85922df954744beda219b6b9150539bf7caa786ef1c79563a83e74eb1c13ebb349838245e186f6545f3c92262fdc0c1fe1
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
MovableInkAWS (1.
|
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.
|
24
|
-
aws-sdk-athena (1.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
79
|
-
rspec-support (~> 3.9.
|
80
|
-
rspec-expectations (3.9.
|
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.
|
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.
|
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.
|
96
|
+
2.1.3
|
data/lib/movable_ink/aws.rb
CHANGED
@@ -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
|
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
|
data/lib/movable_ink/aws/ec2.rb
CHANGED
@@ -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
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
data/lib/movable_ink/version.rb
CHANGED
data/spec/aws_spec.rb
CHANGED
@@ -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(
|
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(
|
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(
|
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(
|
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(
|
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
|
data/spec/ec2_spec.rb
CHANGED
@@ -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(
|
8
|
-
allow(aws).to receive(
|
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(:
|
187
|
-
|
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,
|
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
|
data/spec/ssm_spec.rb
CHANGED
@@ -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.
|
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-
|
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
|