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.
@@ -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