furnish-aws 0.0.1
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 +15 -0
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/Guardfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +59 -0
- data/Rakefile +32 -0
- data/furnish-aws.gemspec +30 -0
- data/lib/furnish/aws/version.rb +6 -0
- data/lib/furnish/provisioners/aws.rb +101 -0
- data/lib/furnish/provisioners/ec2.rb +372 -0
- data/lib/furnish/provisioners/security_group.rb +380 -0
- data/test/helper.rb +61 -0
- data/test/test_aws_base_class.rb +30 -0
- data/test/test_ec2.rb +225 -0
- data/test/test_security_group.rb +322 -0
- metadata +188 -0
data/test/test_ec2.rb
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'furnish/provisioners/ec2'
|
3
|
+
require 'furnish/provisioners/security_group'
|
4
|
+
|
5
|
+
class TestEC2 < Furnish::SchedulerTestCase
|
6
|
+
AMI = "ami-e2861d8b" # ubuntu 12.04 LTS from vendor, us-east-1 instance store
|
7
|
+
KEY_PAIR_NAME = "furnish-test-key"
|
8
|
+
DUMMY_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDZ2lpDmXAxAo8XKThAgkF+iPcXPs6S72RPTcb191Krq43Offay8VdnLecRYLZslvbaQKLfvsfjwZP95yJt2GHnMhSOY4gXkowmjLFjth6BQK42vsuMVVDpwQn9kIPvgCh2UA3b1ti1dV9VznSgBaxDoCsZpzIlF6LHGMIU6qkX938ZQ2IPahu144FTemEwWWvPX6Eyow8narSRGTPFWqbY+Q8jti/pLroNxMiq4nMpIYlCH5fW37C7bSyQOgdAtCq3YfxzM45j2cRVOQKjNLDH8Al6OH7wOsDJUxu0MbfnHSIMcDH3jDyDWqkrAle6B0d+52/7SeqTLMrH8aMPDLIwXW9MwLW7kdMt2XCLZWCo3bf+JOvC2BxZSjLnaOaruM/ckjnzhZYX/qLm49T0feh1+3JZhYD40+aYRT+r1Se+0+AP1YeY9pRSfo0KD0nd1VbKbgIYUY0d/n5fmbsejAmGB4IhVEXgKBhSLHEJiNrB5ahqxHziObr3Y64J6uQ088egs7uxtK/NOm5WqsW+QSPu4xvtFawzkQjALw3pGw9C3DJuCJ2hoO3OdVo8SGlIGvtEYZnEOU5sWSP3gfd4TWRVgc6pOwrlXWHG1/6151Ufpm2blRZFv0j10WaDPYw/W+JEUwczrAg6hacZa0SPpybPzwNBLFQXRz1BeB/dKUykCQ=="
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@klass = Furnish::Provisioner::EC2
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
sched.teardown
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def make_key(obj)
|
21
|
+
delete_key(obj)
|
22
|
+
obj.ec2.key_pairs.import("furnish-test-key", DUMMY_KEY)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_key(obj)
|
26
|
+
obj.ec2.key_pairs["furnish-test-key"].delete rescue nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def security_group_provisioner
|
30
|
+
Furnish::Provisioner::SecurityGroup.new(base_args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_provisioner(ec2_args=args)
|
34
|
+
[
|
35
|
+
security_group_provisioner,
|
36
|
+
@klass.new(ec2_args)
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
def base_args
|
41
|
+
{
|
42
|
+
:access_key => ENV["AWS_ACCESS_KEY_ID"],
|
43
|
+
:secret_key => ENV["AWS_SECRET_ACCESS_KEY"],
|
44
|
+
:region => "us-east-1"
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def args
|
49
|
+
base_args.merge({
|
50
|
+
:instance_type => ENV["FURNISH_EC2_TEST_INSTANCE_SIZE"] || "c1.medium",
|
51
|
+
:key_name => KEY_PAIR_NAME,
|
52
|
+
:image_id => AMI
|
53
|
+
})
|
54
|
+
end
|
55
|
+
|
56
|
+
def make_basic_obj
|
57
|
+
opts = {
|
58
|
+
:access_key => "qwe123",
|
59
|
+
:secret_key => "password1",
|
60
|
+
:key_name => "foo",
|
61
|
+
:image_id => "ami-1234",
|
62
|
+
:region => "us-east-1"
|
63
|
+
}
|
64
|
+
|
65
|
+
obj = @klass.new(opts)
|
66
|
+
|
67
|
+
# the object constructed, and the options used to build it, for later reflection.
|
68
|
+
return obj, opts
|
69
|
+
end
|
70
|
+
|
71
|
+
def make_launch_options_obj
|
72
|
+
obj, opts = make_basic_obj
|
73
|
+
|
74
|
+
# add defaults
|
75
|
+
opts.merge!(:count => 1, :instance_type => "c1.medium", :security_group_ids => [])
|
76
|
+
|
77
|
+
# deal with things launch_options doesn't need to care about
|
78
|
+
[:access_key, :secret_key, :region].each { |x| opts.delete(x) }
|
79
|
+
|
80
|
+
return obj, opts
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_constructor
|
84
|
+
base_args = { :access_key => "qwe123", :secret_key => "password1" }
|
85
|
+
assert_raises(ArgumentError, "AWS region must be provided to the provisioner.") { @klass.new(base_args) }
|
86
|
+
assert_raises(ArgumentError, "key_name is required for instance provision") { @klass.new(base_args.merge(:availability_zone => "us-east-1b")) }
|
87
|
+
|
88
|
+
base_args.merge!(:key_name => "foo")
|
89
|
+
|
90
|
+
assert_raises(ArgumentError, "an AMI image_id must be provided") { @klass.new(base_args) }
|
91
|
+
|
92
|
+
base_args.merge!(:image_id => "ami-1234")
|
93
|
+
|
94
|
+
obj = @klass.new(base_args.merge(:availability_zone => "us-east-1b"))
|
95
|
+
assert_equal("us-east-1", obj.region, "AZ was mapped to region name when region isn't supplied")
|
96
|
+
assert_equal(1, obj.count, "default instance count is 1")
|
97
|
+
assert_equal("c1.medium", obj.instance_type, "default instance type is c1.medium")
|
98
|
+
assert_kind_of(Array, obj.security_group_ids, "security group is array by default")
|
99
|
+
assert_empty(obj.security_group_ids, "default array of security groups is empty")
|
100
|
+
|
101
|
+
base_args.merge!(:region => "us-east-1")
|
102
|
+
|
103
|
+
{
|
104
|
+
:count => 2,
|
105
|
+
:instance_type => "m1.small",
|
106
|
+
:security_group_ids => %w[quux]
|
107
|
+
}.each do |key, value|
|
108
|
+
obj = @klass.new(base_args.merge(key => value))
|
109
|
+
assert_equal(value, obj.send(key), "#{key.to_s} accepts default overrides in the constructor")
|
110
|
+
end
|
111
|
+
|
112
|
+
assert_raises(ArgumentError) { @klass.new(base_args.merge(:region => "us-east-1", :availability_zone => "us-east-2a")) }
|
113
|
+
assert_kind_of(Furnish::Provisioner::AWS, @klass.new(base_args.merge(:region => "us-east-1")))
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_launch_options
|
117
|
+
obj, opts = make_launch_options_obj
|
118
|
+
assert_equal(opts, obj.launch_options, "launch_options generates sane defaults")
|
119
|
+
|
120
|
+
@klass::PASSTHROUGH_ATTRS.each do |test_key|
|
121
|
+
obj, opts = make_launch_options_obj
|
122
|
+
obj.send("#{test_key}=", "something")
|
123
|
+
assert_equal(opts.merge(test_key.to_sym => "something"), obj.launch_options, "changes to #{test_key} are reflected")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_startup_shutdown
|
128
|
+
secgroup = security_group_provisioner
|
129
|
+
assert(secgroup.startup, "security group was provisioned")
|
130
|
+
obj = @klass.new(args.merge(:security_group_ids => [secgroup.group_id]))
|
131
|
+
make_key(obj)
|
132
|
+
|
133
|
+
assert_empty(obj.instance_ids, "no instance_ids are stored")
|
134
|
+
result = obj.startup
|
135
|
+
assert(result, "machine was provisioned")
|
136
|
+
refute_empty(result[:ips], "result has ip addresses")
|
137
|
+
refute_empty(result[:ec2_instance_ids], "result has instance ids")
|
138
|
+
assert(result[:ips].all? { |str| str.kind_of?(String) && str.split(/\./).count == 4 && str !~ /^10\./ }, "all items are strings and look like IP addresses and are not private IPs")
|
139
|
+
assert(result[:ec2_instance_ids].all? { |str| str.kind_of?(String) && str =~ /^i-/ }, "all items are strings and look like EC2 instance ids")
|
140
|
+
refute_empty(obj.instance_ids, "we now have instance_ids")
|
141
|
+
assert(obj.instance_ids.all? { |id| obj.ec2.instances[id].status == :running }, "all machines are running")
|
142
|
+
assert(obj.instance_ids.all? { |id| obj.ec2.instances[id].security_groups.map(&:id) == [secgroup.group_id] }, "machines are in the appropriate security group")
|
143
|
+
assert_equal([secgroup.group_id], obj.security_group_ids, "group ids reflect all groups the machines are in")
|
144
|
+
instance_ids = obj.instance_ids
|
145
|
+
assert(obj.shutdown, "shutdown was successsful")
|
146
|
+
assert(instance_ids.all? { |id| obj.ec2.instances[id].status == :terminated }, "all machines are terminated")
|
147
|
+
|
148
|
+
obj = @klass.new(args)
|
149
|
+
assert_empty(obj.instance_ids, "no instance_ids are stored")
|
150
|
+
result = obj.startup(:security_group_ids => [secgroup.group_id])
|
151
|
+
assert(result, "machine was provisioned")
|
152
|
+
refute_empty(result[:ips], "result has ip addresses")
|
153
|
+
refute_empty(result[:ec2_instance_ids], "result has instance ids")
|
154
|
+
assert(result[:ips].all? { |str| str.kind_of?(String) && str.split(/\./).count == 4 && str !~ /^10\./ }, "all items are strings and look like IP addresses and are not private IPs")
|
155
|
+
assert(result[:ec2_instance_ids].all? { |str| str.kind_of?(String) && str =~ /^i-/ }, "all items are strings and look like EC2 instance ids")
|
156
|
+
refute_empty(obj.instance_ids, "we now have instance_ids")
|
157
|
+
assert(obj.instance_ids.all? { |id| obj.ec2.instances[id].status == :running }, "all machines are running")
|
158
|
+
assert(obj.instance_ids.all? { |id| obj.ec2.instances[id].security_groups.map(&:id) == [secgroup.group_id] }, "machines are in the appropriate security group")
|
159
|
+
assert_equal([secgroup.group_id], obj.security_group_ids, "group ids reflect all groups the machines are in")
|
160
|
+
instance_ids = obj.instance_ids
|
161
|
+
assert(obj.shutdown, "shutdown was successsful")
|
162
|
+
assert(instance_ids.all? { |id| obj.ec2.instances[id].status == :terminated }, "all machines are terminated")
|
163
|
+
|
164
|
+
secgroup2 = security_group_provisioner
|
165
|
+
assert(secgroup2.startup, "security group was provisioned")
|
166
|
+
obj = @klass.new(args.merge(:security_group_ids => [secgroup.group_id]))
|
167
|
+
|
168
|
+
assert_empty(obj.instance_ids, "no instance_ids are stored")
|
169
|
+
result = obj.startup(:security_group_ids => [secgroup2.group_id])
|
170
|
+
assert(result, "machine was provisioned")
|
171
|
+
refute_empty(result[:ips], "result has ip addresses")
|
172
|
+
refute_empty(result[:ec2_instance_ids], "result has instance ids")
|
173
|
+
assert(result[:ips].all? { |str| str.kind_of?(String) && str.split(/\./).count == 4 && str !~ /^10\./ }, "all items are strings and look like IP addresses and are not private IPs")
|
174
|
+
assert(result[:ec2_instance_ids].all? { |str| str.kind_of?(String) && str =~ /^i-/ }, "all items are strings and look like EC2 instance ids")
|
175
|
+
refute_empty(obj.instance_ids, "we now have instance_ids")
|
176
|
+
assert(obj.instance_ids.all? { |id| obj.ec2.instances[id].status == :running }, "all machines are running")
|
177
|
+
assert(obj.instance_ids.all? { |id| obj.ec2.instances[id].security_groups.map(&:id).sort == [secgroup.group_id, secgroup2.group_id].sort }, "machines are in the appropriate security groups")
|
178
|
+
assert_equal([secgroup.group_id, secgroup2.group_id].sort, obj.security_group_ids.sort, "group ids reflect all groups the machines are in")
|
179
|
+
instance_ids = obj.instance_ids
|
180
|
+
assert(obj.shutdown, "shutdown was successsful")
|
181
|
+
assert(instance_ids.all? { |id| obj.ec2.instances[id].status == :terminated }, "all machines are terminated")
|
182
|
+
ensure
|
183
|
+
delete_key(obj) rescue nil
|
184
|
+
obj.shutdown rescue nil
|
185
|
+
secgroup.shutdown rescue nil
|
186
|
+
secgroup2.shutdown rescue nil
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_provisioner
|
190
|
+
secgroup = security_group_provisioner
|
191
|
+
obj = @klass.new(args)
|
192
|
+
make_key(obj)
|
193
|
+
|
194
|
+
sched.serial = true
|
195
|
+
sched.schedule_provision('test1', [secgroup, obj])
|
196
|
+
sched.run
|
197
|
+
assert_solved('test1')
|
198
|
+
prov = sched.vm.groups['test1']
|
199
|
+
instance_ids = prov[1].instance_ids
|
200
|
+
assert_equal(1, instance_ids.count, "instance_ids are getting tracked inside the provisioner")
|
201
|
+
assert_equal([prov[0].group_id], prov[1].security_group_ids, "security groups were propogated correctly")
|
202
|
+
assert_equal(["ami #{prov[1].image_id}; #{prov[1].count} servers; instance_ids: #{instance_ids.inspect}"], prov[1].report, "reporting is accurate")
|
203
|
+
assert(instance_ids.all? { |id| obj.ec2.instances[id].status == :running }, "all instances are running")
|
204
|
+
sched.teardown_group('test1')
|
205
|
+
refute_solved('test1')
|
206
|
+
assert(instance_ids.all? { |id| obj.ec2.instances[id].status == :terminated }, "all machines are terminated after shutdown")
|
207
|
+
|
208
|
+
# try with a larger count
|
209
|
+
obj = @klass.new(args.merge(:count => 5))
|
210
|
+
sched.schedule_provision('test2', [secgroup, obj])
|
211
|
+
sched.run
|
212
|
+
assert_solved('test2')
|
213
|
+
prov = sched.vm.groups['test2']
|
214
|
+
instance_ids = prov[1].instance_ids
|
215
|
+
assert_equal(5, instance_ids.count, "instance_ids are getting tracked inside the provisioner")
|
216
|
+
assert_equal([prov[0].group_id], prov[1].security_group_ids, "security groups were propogated correctly")
|
217
|
+
assert_equal(["ami #{prov[1].image_id}; #{prov[1].count} servers; instance_ids: #{instance_ids.inspect}"], prov[1].report, "reporting is accurate")
|
218
|
+
assert(instance_ids.all? { |id| obj.ec2.instances[id].status == :running }, "all instances are running")
|
219
|
+
sched.teardown_group('test2')
|
220
|
+
refute_solved('test2')
|
221
|
+
assert(instance_ids.all? { |id| obj.ec2.instances[id].status == :terminated }, "all machines are terminated after shutdown")
|
222
|
+
ensure
|
223
|
+
delete_key(obj) rescue nil
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,322 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'furnish/provisioners/security_group'
|
3
|
+
|
4
|
+
#--
|
5
|
+
# FIXME logging tests
|
6
|
+
#++
|
7
|
+
class TestSecurityGroup < Furnish::SchedulerTestCase
|
8
|
+
AMI = "ami-e2861d8b" # ubuntu 12.04 LTS from vendor, us-east-1 instance store
|
9
|
+
KEY_PAIR_NAME = "furnish-test-key"
|
10
|
+
DUMMY_KEY = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDZ2lpDmXAxAo8XKThAgkF+iPcXPs6S72RPTcb191Krq43Offay8VdnLecRYLZslvbaQKLfvsfjwZP95yJt2GHnMhSOY4gXkowmjLFjth6BQK42vsuMVVDpwQn9kIPvgCh2UA3b1ti1dV9VznSgBaxDoCsZpzIlF6LHGMIU6qkX938ZQ2IPahu144FTemEwWWvPX6Eyow8narSRGTPFWqbY+Q8jti/pLroNxMiq4nMpIYlCH5fW37C7bSyQOgdAtCq3YfxzM45j2cRVOQKjNLDH8Al6OH7wOsDJUxu0MbfnHSIMcDH3jDyDWqkrAle6B0d+52/7SeqTLMrH8aMPDLIwXW9MwLW7kdMt2XCLZWCo3bf+JOvC2BxZSjLnaOaruM/ckjnzhZYX/qLm49T0feh1+3JZhYD40+aYRT+r1Se+0+AP1YeY9pRSfo0KD0nd1VbKbgIYUY0d/n5fmbsejAmGB4IhVEXgKBhSLHEJiNrB5ahqxHziObr3Y64J6uQ088egs7uxtK/NOm5WqsW+QSPu4xvtFawzkQjALw3pGw9C3DJuCJ2hoO3OdVo8SGlIGvtEYZnEOU5sWSP3gfd4TWRVgc6pOwrlXWHG1/6151Ufpm2blRZFv0j10WaDPYw/W+JEUwczrAg6hacZa0SPpybPzwNBLFQXRz1BeB/dKUykCQ=="
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@klass = Furnish::Provisioner::SecurityGroup
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
sched.teardown
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_key(obj)
|
23
|
+
delete_key(obj)
|
24
|
+
obj.ec2.key_pairs.import("furnish-test-key", DUMMY_KEY)
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_key(obj)
|
28
|
+
obj.ec2.key_pairs["furnish-test-key"].delete rescue nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def args
|
32
|
+
{
|
33
|
+
:access_key => ENV["AWS_ACCESS_KEY_ID"],
|
34
|
+
:secret_key => ENV["AWS_SECRET_ACCESS_KEY"],
|
35
|
+
:region => "us-east-1"
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_test_group
|
40
|
+
obj = @klass.new(args)
|
41
|
+
group = obj.ec2.security_groups.create(obj.generate_group_name)
|
42
|
+
|
43
|
+
return obj, group
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate_perms(obj, group_id, type=:ingress, &block)
|
47
|
+
obj.ec2.security_groups[group_id].send("#{type}_ip_permissions").any?(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def can_ping(obj, group_id, cidr)
|
51
|
+
validate_perms(obj, group_id) { |o| o.protocol == :icmp && o.ip_ranges.include?(cidr) }
|
52
|
+
end
|
53
|
+
|
54
|
+
def has_rule(obj, group_id, proto, port_range, addrs=["0.0.0.0/0"])
|
55
|
+
unless port_range.kind_of?(Range)
|
56
|
+
port_range = (port_range..port_range)
|
57
|
+
end
|
58
|
+
|
59
|
+
validate_perms(obj, group_id) do |o|
|
60
|
+
o.protocol == proto && o.port_range == port_range && addrs.all? { |a| o.ip_ranges.include?(a) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_constructor
|
65
|
+
assert_raises(
|
66
|
+
ArgumentError,
|
67
|
+
"AWS region must be provided to the provisioner."
|
68
|
+
) do
|
69
|
+
@klass.new(:access_key => "quux", :secret_key => "frobnik")
|
70
|
+
end # I hereby declare syntax bankruptcy
|
71
|
+
|
72
|
+
obj = @klass.new(args)
|
73
|
+
|
74
|
+
{
|
75
|
+
:ingress => { :authorize => [], :revoke => [] },
|
76
|
+
:egress => { :authorize => [], :revoke => [] },
|
77
|
+
:allow_ping => [],
|
78
|
+
:disallow_ping => [],
|
79
|
+
:group_name => :auto,
|
80
|
+
:group_prefix => "furnish-auto-",
|
81
|
+
:kill_instances => true,
|
82
|
+
:group_id => nil
|
83
|
+
}.each do |key, value|
|
84
|
+
assert_equal(value, obj.send(key), "default for #{key} is correct")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_generate_group_name
|
89
|
+
obj = @klass.new(args)
|
90
|
+
obj.group_prefix = nil
|
91
|
+
|
92
|
+
assert_raises(
|
93
|
+
ArgumentError,
|
94
|
+
"group_prefix must be set when auto-generating security group names"
|
95
|
+
) do
|
96
|
+
obj.generate_group_name
|
97
|
+
end
|
98
|
+
|
99
|
+
obj = @klass.new(args)
|
100
|
+
name = obj.generate_group_name
|
101
|
+
assert(name.start_with?(obj.group_prefix), 'generated name starts with the group prefix')
|
102
|
+
refute_includes(obj.ec2.security_groups.filter('group-name', [name]).map(&:name), name, 'generated name does NOT exist')
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_allow_disallow_ping
|
106
|
+
obj, test_group = create_test_group
|
107
|
+
|
108
|
+
obj.allow_ping = true
|
109
|
+
obj.disallow_ping = false
|
110
|
+
obj.apply_group_rules(test_group)
|
111
|
+
|
112
|
+
assert(
|
113
|
+
can_ping(obj, test_group.id, '0.0.0.0/0'),
|
114
|
+
'allow_ping is true when set so on the provisioner'
|
115
|
+
)
|
116
|
+
|
117
|
+
test_group.delete
|
118
|
+
|
119
|
+
obj, test_group = create_test_group
|
120
|
+
|
121
|
+
obj.allow_ping = false
|
122
|
+
obj.disallow_ping = true
|
123
|
+
obj.apply_group_rules(test_group)
|
124
|
+
|
125
|
+
refute(
|
126
|
+
can_ping(obj, test_group.id, '0.0.0.0/0'),
|
127
|
+
'disallow_ping is true when set so on the provisioner'
|
128
|
+
)
|
129
|
+
|
130
|
+
test_group.delete
|
131
|
+
|
132
|
+
cidrs = [ "1.1.1.1/32", "1.2.3.4/24" ]
|
133
|
+
|
134
|
+
obj, test_group = create_test_group
|
135
|
+
obj.allow_ping = cidrs
|
136
|
+
obj.disallow_ping = false
|
137
|
+
obj.apply_group_rules(test_group)
|
138
|
+
|
139
|
+
cidrs.each do |addr|
|
140
|
+
assert(
|
141
|
+
can_ping(obj, test_group.id, addr),
|
142
|
+
"#{addr} is whitelisted for pings when set with #allow_ping="
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
146
|
+
test_group.delete
|
147
|
+
|
148
|
+
obj, test_group = create_test_group
|
149
|
+
obj.allow_ping = false
|
150
|
+
obj.disallow_ping = cidrs
|
151
|
+
obj.apply_group_rules(test_group)
|
152
|
+
|
153
|
+
cidrs.each do |addr|
|
154
|
+
refute(
|
155
|
+
can_ping(obj, test_group.id, addr),
|
156
|
+
"#{addr} is blacklisted for pings when set with #disallow_ping="
|
157
|
+
)
|
158
|
+
end
|
159
|
+
|
160
|
+
test_group.delete
|
161
|
+
ensure
|
162
|
+
test_group.delete rescue nil
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_apply_group_rules
|
166
|
+
#--
|
167
|
+
# this does not cover allow/disallow ping, that's in test_allow_disallow_ping.
|
168
|
+
# FIXME still need to cover tests that only work with VPC
|
169
|
+
#++
|
170
|
+
|
171
|
+
obj, test_group = create_test_group
|
172
|
+
obj.ingress = { :authorize => [[:tcp, 22]] }
|
173
|
+
|
174
|
+
obj.apply_group_rules(test_group)
|
175
|
+
assert(has_rule(obj, test_group.id, :tcp, 22), "tcp/22 rule was configured for security group")
|
176
|
+
test_group.delete
|
177
|
+
|
178
|
+
obj, test_group = create_test_group
|
179
|
+
obj.ingress = { :authorize => [[:tcp, 22]], :revoke => [[:tcp, 22]] }
|
180
|
+
obj.apply_group_rules(test_group)
|
181
|
+
refute(has_rule(obj, test_group.id, :tcp, 22), "authorizing and revoking the same rule ends up in no rule")
|
182
|
+
test_group.delete
|
183
|
+
|
184
|
+
obj, test_group = create_test_group
|
185
|
+
obj.ingress = { :authorize => [[:tcp, 22, '1.2.3.4/32', '2.3.4.5/8']] }
|
186
|
+
obj.apply_group_rules(test_group)
|
187
|
+
assert(has_rule(obj, test_group.id, :tcp, 22, ['1.2.3.4/32', '2.3.4.5/8']), "inlined CIDR gets propogated correctly")
|
188
|
+
test_group.delete
|
189
|
+
|
190
|
+
obj, test_group = create_test_group
|
191
|
+
obj.ingress = { :authorize => [[:tcp, 22, ['1.2.3.4/32', '2.3.4.5/8']]] }
|
192
|
+
obj.apply_group_rules(test_group)
|
193
|
+
assert(has_rule(obj, test_group.id, :tcp, 22, ['1.2.3.4/32', '2.3.4.5/8']), "nested CIDR gets propogated correctly")
|
194
|
+
test_group.delete
|
195
|
+
|
196
|
+
obj, test_group = create_test_group
|
197
|
+
obj.ingress = { :authorize => [[:tcp, 22..23]] }
|
198
|
+
obj.apply_group_rules(test_group)
|
199
|
+
assert(has_rule(obj, test_group.id, :tcp, 22..23), "ranges work")
|
200
|
+
test_group.delete
|
201
|
+
|
202
|
+
obj, test_group = create_test_group
|
203
|
+
obj.ingress = { :authorize => [[:tcp, 22..23], [:udp, 22..23]] }
|
204
|
+
obj.apply_group_rules(test_group)
|
205
|
+
assert(has_rule(obj, test_group.id, :tcp, 22..23), "mixed tcp/udp works, multiple rules work")
|
206
|
+
assert(has_rule(obj, test_group.id, :udp, 22..23), "mixed tcp/udp works, multiple rules work")
|
207
|
+
test_group.delete
|
208
|
+
|
209
|
+
obj, test_group = create_test_group
|
210
|
+
obj.egress = { :authorize => [['10.10.10.10/32']] }
|
211
|
+
assert_raises(
|
212
|
+
ArgumentError,
|
213
|
+
"egress filtering was configured for #{test_group.id}/#{test_group.name} and it is not a VPC security group"
|
214
|
+
) { obj.apply_group_rules(test_group) }
|
215
|
+
|
216
|
+
test_group.delete
|
217
|
+
ensure
|
218
|
+
test_group.delete rescue nil
|
219
|
+
end
|
220
|
+
|
221
|
+
def test_startup
|
222
|
+
obj = @klass.new(args)
|
223
|
+
|
224
|
+
assert_equal(:auto, obj.group_name, "group name is :auto by default")
|
225
|
+
assert(obj.startup, "startup completes with defaults")
|
226
|
+
refute_nil(obj.group_id, "group id is set after startup")
|
227
|
+
refute_equal(:auto, obj.group_name, ":auto group_name was changed after startup to actual name")
|
228
|
+
obj.ec2.security_groups[obj.group_id].delete
|
229
|
+
|
230
|
+
group_name = "furnish-test-frobnik"
|
231
|
+
obj = @klass.new(args.merge(:group_name => group_name))
|
232
|
+
assert(obj.startup, "startup completed with fixed group name")
|
233
|
+
refute_nil(obj.group_id, "group id is set after startup")
|
234
|
+
assert_equal(group_name, obj.group_name, "group name does not change after startup when name not initially set to :auto")
|
235
|
+
|
236
|
+
obj = @klass.new(args.merge(:group_name => group_name))
|
237
|
+
assert(obj.startup, "startup completed on a second run of same fixed group name")
|
238
|
+
refute_nil(obj.group_id, "group id is set after startup on an existing group")
|
239
|
+
assert_equal(group_name, obj.group_name, "group name does not change after startup when name not initially set to :auto")
|
240
|
+
obj.ec2.security_groups[obj.group_id].delete
|
241
|
+
|
242
|
+
obj = @klass.new(args.merge(:allow_ping => ['1.1.1.1/8'], :ingress => { :authorize => [[:tcp, 22]] }))
|
243
|
+
assert(obj.startup, "startup completes with defaults")
|
244
|
+
refute_nil(obj.group_id, "group id is set after startup on an existing group")
|
245
|
+
assert(has_rule(obj, obj.group_id, :tcp, 22), "tcp/22 rule was configured for security group")
|
246
|
+
assert(can_ping(obj, obj.group_id, '1.1.1.1/8'), "ping allow was configured properly")
|
247
|
+
obj.ec2.security_groups[obj.group_id].delete
|
248
|
+
ensure
|
249
|
+
obj.ec2.security_groups[obj.group_id].delete rescue nil
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_shutdown
|
253
|
+
#
|
254
|
+
# FIXME instance reap tests -- need EC2 bits done first
|
255
|
+
#
|
256
|
+
|
257
|
+
group_name = "furnish-test-frobnik"
|
258
|
+
obj = @klass.new(args.merge(:group_name => group_name))
|
259
|
+
refute(obj.find_group_by_name(group_name), 'group name does not exist beforehand')
|
260
|
+
assert(obj.shutdown, 'shutdown still works if group does not exist beforehand')
|
261
|
+
assert(obj.startup, 'security group was created successfully')
|
262
|
+
assert(obj.find_group_by_name(group_name), 'group name does exist after startup')
|
263
|
+
assert(obj.shutdown, 'shutdown succeeded after group creation')
|
264
|
+
refute(obj.find_group_by_name(group_name), 'group name does not exist after shutdown')
|
265
|
+
|
266
|
+
obj = @klass.new(args)
|
267
|
+
assert(obj.startup, "group was created")
|
268
|
+
|
269
|
+
make_key(obj)
|
270
|
+
|
271
|
+
ec2_obj = Furnish::Provisioner::EC2.new(
|
272
|
+
:access_key => ENV["AWS_ACCESS_KEY_ID"],
|
273
|
+
:secret_key => ENV["AWS_SECRET_ACCESS_KEY"],
|
274
|
+
:region => "us-east-1",
|
275
|
+
:instance_type => ENV["FURNISH_EC2_TEST_INSTANCE_SIZE"] || "c1.medium",
|
276
|
+
:key_name => KEY_PAIR_NAME,
|
277
|
+
:image_id => AMI
|
278
|
+
)
|
279
|
+
|
280
|
+
assert(ec2_obj.startup(:security_group_ids => [obj.group_id]), "machine was started attached to the group")
|
281
|
+
assert(obj.shutdown, "shutdown of security group succeeded")
|
282
|
+
assert(ec2_obj.instance_ids.all? { |id| obj.ec2.instances[id].status == :terminated }, "all machines have been terminated as a result of the security group termination")
|
283
|
+
|
284
|
+
obj = @klass.new(args.merge(:kill_instances => false))
|
285
|
+
assert(obj.startup, "group was created")
|
286
|
+
|
287
|
+
ec2_obj = Furnish::Provisioner::EC2.new(
|
288
|
+
:access_key => ENV["AWS_ACCESS_KEY_ID"],
|
289
|
+
:secret_key => ENV["AWS_SECRET_ACCESS_KEY"],
|
290
|
+
:region => "us-east-1",
|
291
|
+
:instance_type => ENV["FURNISH_EC2_TEST_INSTANCE_SIZE"] || "c1.medium",
|
292
|
+
:key_name => KEY_PAIR_NAME,
|
293
|
+
:image_id => AMI
|
294
|
+
)
|
295
|
+
|
296
|
+
assert(ec2_obj.startup(:security_group_ids => [obj.group_id]), "machine was started attached to the group")
|
297
|
+
assert_raises(RuntimeError) { obj.shutdown }
|
298
|
+
assert(ec2_obj.shutdown, "machines shutdown directly")
|
299
|
+
assert(obj.shutdown, "security group destroyed successfully")
|
300
|
+
ensure
|
301
|
+
delete_key(obj) rescue nil
|
302
|
+
obj.ec2.security_groups[obj.group_id].delete rescue nil
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_with_scheduler
|
306
|
+
obj = @klass.new(args)
|
307
|
+
sched.serial = true
|
308
|
+
sched.schedule_provision('test1', [obj])
|
309
|
+
sched.run
|
310
|
+
assert_solved('test1')
|
311
|
+
solved_obj = sched.vm.groups['test1'].first
|
312
|
+
refute_equal(:auto, solved_obj.group_name, 'group_name is no longer :auto after provision')
|
313
|
+
assert(obj.find_group_by_name(solved_obj.group_name), 'group exists after provision')
|
314
|
+
refute_nil(solved_obj.group_id, 'group_id is set after provision')
|
315
|
+
assert_equal(["name: #{solved_obj.group_name}, id: #{solved_obj.group_id}"], solved_obj.report, "report is returning expected data")
|
316
|
+
sched.teardown
|
317
|
+
refute(obj.find_group_by_name(solved_obj.group_name), 'group does not exist after teardown')
|
318
|
+
ensure
|
319
|
+
obj.find_group_by_name(obj.group_name).delete rescue nil
|
320
|
+
obj.ec2.security_groups[obj.group_id].delete rescue nil
|
321
|
+
end
|
322
|
+
end
|