beaker 3.20.0 → 3.21.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.
Files changed (55) hide show
  1. checksums.yaml +8 -8
  2. data/beaker.gemspec +4 -5
  3. data/docs/how_to/hypervisors/README.md +7 -3
  4. data/docs/tutorials/quick_start_rake_tasks.md +1 -1
  5. data/lib/beaker/command.rb +1 -1
  6. data/lib/beaker/host.rb +6 -4
  7. data/lib/beaker/host/windows/exec.rb +10 -0
  8. data/lib/beaker/host/windows/pkg.rb +1 -29
  9. data/lib/beaker/host_prebuilt_steps.rb +1 -0
  10. data/lib/beaker/hypervisor.rb +26 -37
  11. data/lib/beaker/ssh_connection.rb +8 -15
  12. data/lib/beaker/version.rb +1 -1
  13. data/spec/beaker/dsl/install_utils/windows_utils_spec.rb +1 -1
  14. data/spec/beaker/host/windows/exec_spec.rb +18 -0
  15. data/spec/beaker/host/windows/pkg_spec.rb +0 -7
  16. data/spec/beaker/host_prebuilt_steps_spec.rb +1 -0
  17. data/spec/beaker/host_spec.rb +31 -40
  18. data/spec/beaker/hypervisor/hypervisor_spec.rb +20 -34
  19. data/spec/beaker/ssh_connection_spec.rb +18 -19
  20. data/spec/spec_helper.rb +0 -1
  21. metadata +23 -57
  22. data/docs/how_to/hypervisors/aws.md +0 -149
  23. data/docs/how_to/hypervisors/ec2.md +0 -81
  24. data/docs/how_to/hypervisors/google_compute_engine.md +0 -41
  25. data/docs/how_to/hypervisors/vagrant.md +0 -165
  26. data/docs/how_to/hypervisors/vagrant_hosts_file_examples.md +0 -60
  27. data/docs/how_to/hypervisors/vagrant_libvirt.md +0 -58
  28. data/docs/how_to/hypervisors/vmware_fusion.md +0 -36
  29. data/docs/how_to/hypervisors/vsphere.md +0 -54
  30. data/lib/beaker/hypervisor/aws_sdk.rb +0 -989
  31. data/lib/beaker/hypervisor/ec2_helper.rb +0 -41
  32. data/lib/beaker/hypervisor/fusion.rb +0 -65
  33. data/lib/beaker/hypervisor/google_compute.rb +0 -164
  34. data/lib/beaker/hypervisor/google_compute_helper.rb +0 -577
  35. data/lib/beaker/hypervisor/vagrant.rb +0 -286
  36. data/lib/beaker/hypervisor/vagrant_custom.rb +0 -11
  37. data/lib/beaker/hypervisor/vagrant_fusion.rb +0 -17
  38. data/lib/beaker/hypervisor/vagrant_libvirt.rb +0 -41
  39. data/lib/beaker/hypervisor/vagrant_parallels.rb +0 -18
  40. data/lib/beaker/hypervisor/vagrant_virtualbox.rb +0 -76
  41. data/lib/beaker/hypervisor/vagrant_workstation.rb +0 -13
  42. data/lib/beaker/hypervisor/vsphere.rb +0 -85
  43. data/lib/beaker/hypervisor/vsphere_helper.rb +0 -204
  44. data/spec/beaker/hypervisor/aws_sdk_spec.rb +0 -980
  45. data/spec/beaker/hypervisor/ec2_helper_spec.rb +0 -44
  46. data/spec/beaker/hypervisor/fusion_spec.rb +0 -41
  47. data/spec/beaker/hypervisor/vagrant_custom_spec.rb +0 -46
  48. data/spec/beaker/hypervisor/vagrant_fusion_spec.rb +0 -32
  49. data/spec/beaker/hypervisor/vagrant_libvirt_spec.rb +0 -61
  50. data/spec/beaker/hypervisor/vagrant_parallels_spec.rb +0 -44
  51. data/spec/beaker/hypervisor/vagrant_spec.rb +0 -479
  52. data/spec/beaker/hypervisor/vagrant_virtualbox_spec.rb +0 -44
  53. data/spec/beaker/hypervisor/vagrant_workstation_spec.rb +0 -32
  54. data/spec/beaker/hypervisor/vsphere_helper_spec.rb +0 -163
  55. data/spec/beaker/hypervisor/vsphere_spec.rb +0 -90
@@ -1,13 +0,0 @@
1
- require 'beaker/hypervisor/vagrant'
2
-
3
- class Beaker::VagrantWorkstation < Beaker::Vagrant
4
- def provision(provider = 'vmware_workstation')
5
- super
6
- end
7
-
8
- def self.provider_vfile_section(host, options)
9
- " v.vm.provider :vmware_workstation do |v|\n" +
10
- " v.vmx['memsize'] = '#{memsize(host,options)}'\n" +
11
- " end\n"
12
- end
13
- end
@@ -1,85 +0,0 @@
1
- require 'yaml' unless defined?(YAML)
2
-
3
- module Beaker
4
- class Vsphere < Beaker::Hypervisor
5
-
6
- def initialize(vsphere_hosts, options)
7
- @options = options
8
- @logger = options[:logger]
9
- @hosts = vsphere_hosts
10
- end
11
-
12
- def provision
13
- vsphere_credentials = VsphereHelper.load_config(@options[:dot_fog])
14
-
15
- @logger.notify "Connecting to vSphere at #{vsphere_credentials[:server]}" +
16
- " with credentials for #{vsphere_credentials[:user]}"
17
-
18
- vsphere_helper = VsphereHelper.new( vsphere_credentials )
19
-
20
- vsphere_vms = {}
21
- @hosts.each do |h|
22
- name = h["vmname"] || h.name
23
- vsphere_vms[name] = h["snapshot"]
24
- end
25
- vms = vsphere_helper.find_vms(vsphere_vms.keys)
26
- vsphere_vms.each_pair do |name, snap|
27
- unless vm = vms[name]
28
- raise "Couldn't find VM #{name} in vSphere!"
29
- end
30
-
31
- if snap
32
- snapshot = vsphere_helper.find_snapshot(vm, snap) or
33
- raise "Could not find snapshot '#{snap}' for VM #{vm.name}!"
34
-
35
- @logger.notify "Reverting #{vm.name} to snapshot '#{snap}'"
36
- start = Time.now
37
- # This will block for each snapshot...
38
- # The code to issue them all and then wait until they are all done sucks
39
- snapshot.RevertToSnapshot_Task.wait_for_completion
40
-
41
- time = Time.now - start
42
- @logger.notify "Spent %.2f seconds reverting" % time
43
- end
44
-
45
- unless vm.runtime.powerState == "poweredOn"
46
- @logger.notify "Booting #{vm.name}"
47
- start = Time.now
48
- vm.PowerOnVM_Task.wait_for_completion
49
- @logger.notify "Spent %.2f seconds booting #{vm.name}" % (Time.now - start)
50
- end
51
- end
52
-
53
- vsphere_helper.close
54
- end
55
-
56
- def cleanup
57
- @logger.notify "Destroying vsphere boxes"
58
- vsphere_credentials = VsphereHelper.load_config(@options[:dot_fog])
59
-
60
- @logger.notify "Connecting to vSphere at #{vsphere_credentials[:server]}" +
61
- " with credentials for #{vsphere_credentials[:user]}"
62
-
63
- vsphere_helper = VsphereHelper.new( vsphere_credentials )
64
-
65
- vm_names = @hosts.map {|h| h['vmname'] || h.name }
66
- vms = vsphere_helper.find_vms vm_names
67
- vm_names.each do |name|
68
- unless vm = vms[name]
69
- raise "Couldn't find VM #{name} in vSphere!"
70
- end
71
-
72
- if vm.runtime.powerState == "poweredOn"
73
- @logger.notify "Shutting down #{vm.name}"
74
- start = Time.now
75
- vm.PowerOffVM_Task.wait_for_completion
76
- @logger.notify(
77
- "Spent %.2f seconds halting #{vm.name}" % (Time.now - start) )
78
- end
79
- end
80
-
81
- vsphere_helper.close
82
- end
83
-
84
- end
85
- end
@@ -1,204 +0,0 @@
1
- require 'yaml' unless defined?(YAML)
2
- require 'rbvmomi'
3
- require 'beaker/logger'
4
-
5
- class VsphereHelper
6
- def initialize vInfo
7
- @logger = vInfo[:logger] || Beaker::Logger.new
8
- @connection = RbVmomi::VIM.connect :host => vInfo[:server],
9
- :user => vInfo[:user],
10
- :password => vInfo[:pass],
11
- :insecure => true
12
- end
13
-
14
- def self.load_config(dot_fog = '.fog')
15
- # support Fog/Cloud Provisioner layout
16
- # (ie, someplace besides my made up conf)
17
- vsphere_credentials = nil
18
- if File.exists?( dot_fog )
19
- vsphere_credentials = load_fog_credentials(dot_fog)
20
- else
21
- raise ArgumentError, ".fog file '#{dot_fog}' does not exist"
22
- end
23
-
24
- return vsphere_credentials
25
- end
26
-
27
- def self.load_fog_credentials(dot_fog = '.fog')
28
- vInfo = YAML.load_file( dot_fog )
29
-
30
- vsphere_credentials = {}
31
- vsphere_credentials[:server] = vInfo[:default][:vsphere_server]
32
- vsphere_credentials[:user] = vInfo[:default][:vsphere_username]
33
- vsphere_credentials[:pass] = vInfo[:default][:vsphere_password]
34
-
35
- return vsphere_credentials
36
- end
37
-
38
- def find_snapshot vm, snapname
39
- if vm.snapshot
40
- search_child_snaps vm.snapshot.rootSnapshotList, snapname
41
- else
42
- raise "vm #{vm.name} has no snapshots to revert to"
43
- end
44
- end
45
-
46
- def search_child_snaps tree, snapname
47
- snapshot = nil
48
- tree.each do |child|
49
- if child.name == snapname
50
- snapshot ||= child.snapshot
51
- else
52
- snapshot ||= search_child_snaps child.childSnapshotList, snapname
53
- end
54
- end
55
- snapshot
56
- end
57
-
58
- def find_customization name
59
- csm = @connection.serviceContent.customizationSpecManager
60
-
61
- begin
62
- customizationSpec = csm.GetCustomizationSpec({:name => name}).spec
63
- rescue
64
- customizationSpec = nil
65
- end
66
-
67
- return customizationSpec
68
- end
69
-
70
- # an easier wrapper around the horrid PropertyCollector interface,
71
- # necessary for searching VMs in all Datacenters that may be nested
72
- # within folders of arbitrary depth
73
- # returns a hash array of <name> => <VirtualMachine ManagedObjects>
74
- def find_vms names, connection = @connection
75
- names = names.is_a?(Array) ? names : [ names ]
76
- containerView = get_base_vm_container_from connection
77
- propertyCollector = connection.propertyCollector
78
-
79
- objectSet = [{
80
- :obj => containerView,
81
- :skip => true,
82
- :selectSet => [ RbVmomi::VIM::TraversalSpec.new({
83
- :name => 'gettingTheVMs',
84
- :path => 'view',
85
- :skip => false,
86
- :type => 'ContainerView'
87
- }) ]
88
- }]
89
-
90
- propSet = [{
91
- :pathSet => [ 'name' ],
92
- :type => 'VirtualMachine'
93
- }]
94
-
95
- results = propertyCollector.RetrievePropertiesEx({
96
- :specSet => [{
97
- :objectSet => objectSet,
98
- :propSet => propSet
99
- }],
100
- :options => { :maxObjects => nil }
101
- })
102
-
103
- vms = {}
104
- results.objects.each do |result|
105
- name = result.propSet.first.val
106
- next unless names.include? name
107
- vms[name] = result.obj
108
- end
109
-
110
- while results.token do
111
- results = propertyCollector.ContinueRetrievePropertiesEx({:token => results.token})
112
- results.objects.each do |result|
113
- name = result.propSet.first.val
114
- next unless names.include? name
115
- vms[name] = result.obj
116
- end
117
- end
118
- vms
119
- end
120
-
121
- def find_datastore(dc,datastorename)
122
- datacenter = @connection.serviceInstance.find_datacenter(dc)
123
- datacenter.find_datastore(datastorename)
124
- end
125
-
126
- def find_folder(dc,foldername)
127
- datacenter = @connection.serviceInstance.find_datacenter(dc)
128
- base = datacenter.vmFolder.traverse(foldername)
129
- if base != nil
130
- base
131
- else
132
- abort "Failed to find folder #{foldername}"
133
- end
134
- end
135
-
136
- def find_pool(dc,poolname)
137
- datacenter = @connection.serviceInstance.find_datacenter(dc)
138
- base = datacenter.hostFolder
139
- pools = poolname.split('/')
140
- pools.each do |pool|
141
- case base
142
- when RbVmomi::VIM::Folder
143
- base = base.childEntity.find { |f| f.name == pool }
144
- when RbVmomi::VIM::ClusterComputeResource
145
- base = base.resourcePool.resourcePool.find { |f| f.name == pool }
146
- when RbVmomi::VIM::ResourcePool
147
- base = base.resourcePool.find { |f| f.name == pool }
148
- else
149
- abort "Unexpected object type encountered (#{base.class}) while finding resource pool"
150
- end
151
- end
152
-
153
- base = base.resourcePool unless base.is_a?(RbVmomi::VIM::ResourcePool) and base.respond_to?(:resourcePool)
154
- base
155
- end
156
-
157
- def get_base_vm_container_from connection
158
- viewManager = connection.serviceContent.viewManager
159
- viewManager.CreateContainerView({
160
- :container => connection.serviceContent.rootFolder,
161
- :recursive => true,
162
- :type => [ 'VirtualMachine' ]
163
- })
164
- end
165
-
166
- def wait_for_tasks tasks, try, attempts
167
- obj_set = tasks.map { |task| { :obj => task } }
168
- filter = @connection.propertyCollector.CreateFilter(
169
- :spec => {
170
- :propSet => [{ :type => 'Task',
171
- :all => false,
172
- :pathSet => ['info.state']}],
173
- :objectSet => obj_set
174
- },
175
- :partialUpdates => false
176
- )
177
- ver = ''
178
- while true
179
- result = @connection.propertyCollector.WaitForUpdates(:version => ver)
180
- ver = result.version
181
- complete = 0
182
- tasks.each do |task|
183
- if ['success', 'error'].member? task.info.state
184
- complete += 1
185
- end
186
- end
187
- break if (complete == tasks.length)
188
- if try <= attempts
189
- sleep 5
190
- try += 1
191
- else
192
- raise "unable to complete Vsphere tasks before timeout"
193
- end
194
- end
195
-
196
- filter.DestroyPropertyFilter
197
- tasks
198
- end
199
-
200
- def close
201
- @connection.close
202
- end
203
- end
204
-
@@ -1,980 +0,0 @@
1
- require 'spec_helper'
2
-
3
- module Beaker
4
- describe AwsSdk do
5
- let( :options ) { make_opts.merge({ 'logger' => double().as_null_object, 'timestamp' => Time.now }) }
6
- let(:aws) {
7
- # Mock out the call to load_fog_credentials
8
- allow_any_instance_of( Beaker::AwsSdk ).
9
- to receive(:load_fog_credentials).
10
- and_return({
11
- :access_key => fog_file_contents[:default][:aws_access_key_id],
12
- :secret_key => fog_file_contents[:default][:aws_secret_access_key],
13
- })
14
-
15
-
16
- # This is needed because the EC2 api looks up a local endpoints.json file
17
- FakeFS.deactivate!
18
- aws = Beaker::AwsSdk.new(@hosts, options)
19
- FakeFS.activate!
20
-
21
- aws
22
- }
23
- let(:amispec) {{
24
- "centos-5-x86-64-west" => {
25
- :image => {:pe => "ami-sekrit1"},
26
- :region => "us-west-2",
27
- },
28
- "centos-6-x86-64-west" => {
29
- :image => {:pe => "ami-sekrit2"},
30
- :region => "us-west-2",
31
- },
32
- "centos-7-x86-64-west" => {
33
- :image => {:pe => "ami-sekrit3"},
34
- :region => "us-west-2",
35
- },
36
- "ubuntu-12.04-amd64-west" => {
37
- :image => {:pe => "ami-sekrit4"},
38
- :region => "us-west-2"
39
- },
40
- }}
41
-
42
- before :each do
43
- @hosts = make_hosts({:snapshot => :pe}, 6)
44
- @hosts[0][:platform] = "centos-5-x86-64-west"
45
- @hosts[1][:platform] = "centos-6-x86-64-west"
46
- @hosts[2][:platform] = "centos-7-x86-64-west"
47
- @hosts[3][:platform] = "ubuntu-12.04-amd64-west"
48
- @hosts[3][:user] = "ubuntu"
49
- @hosts[4][:platform] = 'f5-host'
50
- @hosts[4][:user] = 'notroot'
51
- @hosts[5][:platform] = 'netscaler-host'
52
-
53
- ENV['AWS_ACCESS_KEY'] = nil
54
- ENV['AWS_SECRET_ACCESS_KEY'] = nil
55
- end
56
-
57
- context 'loading credentials' do
58
-
59
- it 'from .fog file' do
60
- creds = aws.load_fog_credentials
61
- expect( creds[:access_key] ).to eq("IMANACCESSKEY")
62
- expect( creds[:secret_key] ).to eq("supersekritkey")
63
- end
64
-
65
-
66
- it 'from environment variables' do
67
- ENV['AWS_ACCESS_KEY_ID'] = "IMANACCESSKEY"
68
- ENV['AWS_SECRET_ACCESS_KEY'] = "supersekritkey"
69
-
70
- creds = aws.load_env_credentials
71
- expect( creds[:access_key] ).to eq("IMANACCESSKEY")
72
- expect( creds[:secret_key] ).to eq("supersekritkey")
73
- end
74
- end
75
-
76
- describe '#provision' do
77
- before :each do
78
- expect(aws).to receive(:launch_all_nodes)
79
- expect(aws).to receive(:add_tags)
80
- expect(aws).to receive(:populate_dns)
81
- expect(aws).to receive(:enable_root_on_hosts)
82
- expect(aws).to receive(:set_hostnames)
83
- expect(aws).to receive(:configure_hosts)
84
- end
85
-
86
- it 'should step through provisioning' do
87
- allow( aws ).to receive( :wait_for_status_netdev )
88
- aws.provision
89
- end
90
-
91
- it 'should return nil' do
92
- allow( aws ).to receive( :wait_for_status_netdev )
93
- expect(aws.provision).to be_nil
94
- end
95
- end
96
-
97
- describe '#kill_instances' do
98
- let( :ec2_instance ) { double('ec2_instance', :nil? => false, :exists? => true, :id => "ec2", :terminate => nil) }
99
- let( :vpc_instance ) { double('vpc_instance', :nil? => false, :exists? => true, :id => "vpc", :terminate => nil) }
100
- let( :nil_instance ) { double('vpc_instance', :nil? => true, :exists? => true, :id => "nil", :terminate => nil) }
101
- let( :unreal_instance ) { double('vpc_instance', :nil? => false, :exists? => false, :id => "unreal", :terminate => nil) }
102
- subject(:kill_instances) { aws.kill_instances(instance_set) }
103
-
104
- it 'should return nil' do
105
- instance_set = [ec2_instance, vpc_instance, nil_instance, unreal_instance]
106
- expect(aws.kill_instances(instance_set)).to be_nil
107
- end
108
-
109
- it 'cleanly handles an empty instance list' do
110
- instance_set = []
111
- expect(aws.kill_instances(instance_set)).to be_nil
112
- end
113
-
114
- context 'in general use' do
115
- let( :instance_set ) { [ec2_instance, vpc_instance] }
116
-
117
- it 'terminates each running instance' do
118
- instance_set.each do |instance|
119
- expect(instance).to receive(:terminate).once
120
- end
121
- expect(kill_instances).to be_nil
122
- end
123
-
124
- it 'verifies instances are not nil' do
125
- instance_set.each do |instance|
126
- expect(instance).to receive(:nil?)
127
- allow(instance).to receive(:terminate).once
128
- end
129
- expect(kill_instances).to be_nil
130
- end
131
-
132
- it 'verifies instances exist in AWS' do
133
- instance_set.each do |instance|
134
- expect(instance).to receive(:exists?)
135
- allow(instance).to receive(:terminate).once
136
- end
137
- expect(kill_instances).to be_nil
138
- end
139
- end
140
-
141
- context 'for a single running instance' do
142
- let( :instance_set ) { [ec2_instance] }
143
-
144
- it 'terminates the running instance' do
145
- instance_set.each do |instance|
146
- expect(instance).to receive(:terminate).once
147
- end
148
- expect(kill_instances).to be_nil
149
- end
150
-
151
- it 'verifies instance is not nil' do
152
- instance_set.each do |instance|
153
- expect(instance).to receive(:nil?)
154
- allow(instance).to receive(:terminate).once
155
- end
156
- expect(kill_instances).to be_nil
157
- end
158
-
159
- it 'verifies instance exists in AWS' do
160
- instance_set.each do |instance|
161
- expect(instance).to receive(:exists?)
162
- allow(instance).to receive(:terminate).once
163
- end
164
- expect(kill_instances).to be_nil
165
- end
166
- end
167
-
168
- context 'when an instance does not exist' do
169
- let( :instance_set ) { [unreal_instance] }
170
-
171
- it 'does not call terminate' do
172
- instance_set.each do |instance|
173
- expect(instance).to receive(:terminate).exactly(0).times
174
- end
175
- expect(kill_instances).to be_nil
176
- end
177
-
178
- it 'verifies instance does not exist' do
179
- instance_set.each do |instance|
180
- expect(instance).to receive(:exists?).once
181
- allow(instance).to receive(:terminate).exactly(0).times
182
- end
183
- expect(kill_instances).to be_nil
184
- end
185
- end
186
-
187
- context 'when an instance is nil' do
188
- let( :instance_set ) { [nil_instance] }
189
-
190
- it 'does not call terminate' do
191
- instance_set.each do |instance|
192
- expect(instance).to receive(:terminate).exactly(0).times
193
- end
194
- expect(kill_instances).to be_nil
195
- end
196
-
197
- it 'verifies instance is nil' do
198
- instance_set.each do |instance|
199
- expect(instance).to receive(:nil?).once
200
- allow(instance).to receive(:terminate).exactly(0).times
201
- end
202
- expect(kill_instances).to be_nil
203
- end
204
- end
205
-
206
- end
207
-
208
- describe '#cleanup' do
209
- subject(:cleanup) { aws.cleanup }
210
- let( :ec2_instance ) { double('ec2_instance', :nil? => false, :exists? => true, :terminate => nil, :id => 'id') }
211
-
212
- context 'with a list of hosts' do
213
- before :each do
214
- @hosts.each {|host| host['instance'] = ec2_instance}
215
- expect(aws).to receive( :delete_key_pair_all_regions )
216
- end
217
-
218
- it { is_expected.to be_nil }
219
-
220
- it 'kills instances' do
221
- expect(aws).to receive(:kill_instances).once
222
- expect(cleanup).to be_nil
223
- end
224
- end
225
-
226
- context 'with an empty host list' do
227
- before :each do
228
- @hosts = []
229
- expect(aws).to receive( :delete_key_pair_all_regions )
230
- end
231
-
232
- it { is_expected.to be_nil }
233
-
234
- it 'kills instances' do
235
- expect(aws).to receive(:kill_instances).once
236
- expect(cleanup).to be_nil
237
- end
238
- end
239
- end
240
-
241
- describe '#log_instances', :wip do
242
- end
243
-
244
- describe '#instance_by_id' do
245
- subject { aws.instance_by_id('my_id') }
246
- it { is_expected.to be_instance_of(AWS::EC2::Instance) }
247
- end
248
-
249
- describe '#instances' do
250
- subject { aws.instances }
251
- it { is_expected.to be_instance_of(AWS::EC2::InstanceCollection) }
252
- end
253
-
254
- describe '#vpc_by_id' do
255
- subject { aws.vpc_by_id('my_id') }
256
- it { is_expected.to be_instance_of(AWS::EC2::VPC) }
257
- end
258
-
259
- describe '#vpcs' do
260
- subject { aws.vpcs }
261
- it { is_expected.to be_instance_of(AWS::EC2::VPCCollection) }
262
- end
263
-
264
- describe '#security_group_by_id' do
265
- subject { aws.security_group_by_id('my_id') }
266
- it { is_expected.to be_instance_of(AWS::EC2::SecurityGroup) }
267
- end
268
-
269
- describe '#security_groups' do
270
- subject { aws.security_groups }
271
- it { is_expected.to be_instance_of(AWS::EC2::SecurityGroupCollection) }
272
- end
273
-
274
- describe '#kill_zombies' do
275
- it 'calls delete_key_pair_all_regions' do
276
- ec2_mock = Object.new
277
- allow(ec2_mock).to receive( :regions ).and_return( {} )
278
- aws.instance_variable_set( :@ec2, ec2_mock )
279
-
280
- expect( aws ).to receive( :delete_key_pair_all_regions ).once
281
-
282
- aws.kill_zombies()
283
- end
284
- end
285
-
286
- describe '#kill_zombie_volumes', :wip do
287
- end
288
-
289
- describe '#create_instance', :wip do
290
- end
291
-
292
- describe '#launch_nodes_on_some_subnet', :wip do
293
- end
294
-
295
- describe '#launch_all_nodes', :wip do
296
- end
297
-
298
- describe '#wait_for_status' do
299
- let( :aws_instance ) { double('aws_instance', :id => "ec2", :terminate => nil) }
300
- let( :instance_set ) { [{:instance => aws_instance}] }
301
- subject(:wait_for_status) { aws.wait_for_status(:running, instance_set) }
302
-
303
- context 'single instance' do
304
- it 'behaves correctly in typical case' do
305
- allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running)
306
- expect(aws).to receive(:backoff_sleep).exactly(3).times
307
- expect(wait_for_status).to eq(instance_set)
308
- end
309
-
310
- it 'executes block correctly instead of status if given one' do
311
- barn_value = 'did you grow up in a barn?'
312
- allow(aws_instance).to receive( :[] ).with( :barn ) { barn_value }
313
- expect(aws_instance).to receive(:status).exactly(0).times
314
- expect(aws).to receive(:backoff_sleep).exactly(1).times
315
- aws.wait_for_status(:running, instance_set) do |instance|
316
- expect( instance[:barn] ).to be === barn_value
317
- true
318
- end
319
- end
320
- end
321
-
322
- context 'with multiple instances' do
323
- let( :instance_set ) { [{:instance => aws_instance}, {:instance => aws_instance}] }
324
-
325
- it 'returns the instance set passed to it' do
326
- allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running, :waiting, :waiting, :running)
327
- allow(aws).to receive(:backoff_sleep).exactly(6).times
328
- expect(wait_for_status).to eq(instance_set)
329
- end
330
-
331
- it 'calls backoff_sleep once per instance.status call' do
332
- allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running, :waiting, :waiting, :running)
333
- expect(aws).to receive(:backoff_sleep).exactly(6).times
334
- expect(wait_for_status).to eq(instance_set)
335
- end
336
-
337
- it 'executes block correctly instead of status if given one' do
338
- barn_value = 'did you grow up in a barn?'
339
- not_barn_value = 'notabarn'
340
- allow(aws_instance).to receive( :[] ).with( :barn ).and_return(not_barn_value, barn_value, not_barn_value, barn_value)
341
- allow(aws_instance).to receive(:status).and_return(:waiting)
342
- expect(aws).to receive(:backoff_sleep).exactly(4).times
343
- aws.wait_for_status(:running, instance_set) do |instance|
344
- instance[:barn] == barn_value
345
- end
346
- end
347
- end
348
-
349
- context 'after 10 tries' do
350
- it 'raises RuntimeError' do
351
- expect(aws_instance).to receive(:status).and_return(:waiting).exactly(10).times
352
- expect(aws).to receive(:backoff_sleep).exactly(9).times
353
- expect { wait_for_status }.to raise_error('Instance never reached state running')
354
- end
355
-
356
- it 'still raises RuntimeError if given a block' do
357
- expect(aws_instance).to receive(:status).and_return(:waiting).exactly(10).times
358
- expect(aws).to receive(:backoff_sleep).exactly(9).times
359
- expect { wait_for_status { false } }.to raise_error('Instance never reached state running')
360
- end
361
- end
362
-
363
- context 'with an invalid instance' do
364
- it 'raises AWS::EC2::Errors::InvalidInstanceID::NotFound' do
365
- expect(aws_instance).to receive(:status).and_raise(AWS::EC2::Errors::InvalidInstanceID::NotFound).exactly(10).times
366
- allow(aws).to receive(:backoff_sleep).at_most(10).times
367
- expect(wait_for_status).to eq(instance_set)
368
- end
369
- end
370
- end
371
-
372
- describe '#add_tags' do
373
- let( :aws_instance ) { double('aws_instance', :add_tag => nil) }
374
- subject(:add_tags) { aws.add_tags }
375
-
376
- it 'returns nil' do
377
- @hosts.each {|host| host['instance'] = aws_instance}
378
- expect(add_tags).to be_nil
379
- end
380
-
381
- it 'handles a single host' do
382
- @hosts[0]['instance'] = aws_instance
383
- @hosts = [@hosts[0]]
384
- expect(add_tags).to be_nil
385
- end
386
-
387
- context 'with multiple hosts' do
388
- before :each do
389
- @hosts.each {|host| host['instance'] = aws_instance}
390
- end
391
-
392
- it 'handles host_tags hash on host object' do
393
- # set :host_tags on first host
394
- aws.instance_eval {
395
- @hosts[0][:host_tags] = {'test_tag' => 'test_value'}
396
- }
397
- expect(aws_instance).to receive(:add_tag).with('test_tag', hash_including(:value => 'test_value')).at_least(:once)
398
- expect(add_tags).to be_nil
399
- end
400
-
401
- it 'adds tag for jenkins_build_url' do
402
- aws.instance_eval('@options[:jenkins_build_url] = "my_build_url"')
403
- expect(aws_instance).to receive(:add_tag).with('jenkins_build_url', hash_including(:value => 'my_build_url')).at_least(:once)
404
- expect(add_tags).to be_nil
405
- end
406
-
407
- it 'adds tag for Name' do
408
- expect(aws_instance).to receive(:add_tag).with('Name', hash_including(:value => /vm/)).at_least(@hosts.size).times
409
- expect(add_tags).to be_nil
410
- end
411
-
412
- it 'adds tag for department' do
413
- aws.instance_eval('@options[:department] = "my_department"')
414
- expect(aws_instance).to receive(:add_tag).with('department', hash_including(:value => 'my_department')).at_least(:once)
415
- expect(add_tags).to be_nil
416
- end
417
-
418
- it 'adds tag for project' do
419
- aws.instance_eval('@options[:project] = "my_project"')
420
- expect(aws_instance).to receive(:add_tag).with('project', hash_including(:value => 'my_project')).at_least(:once)
421
- expect(add_tags).to be_nil
422
- end
423
-
424
- it 'adds tag for created_by' do
425
- aws.instance_eval('@options[:created_by] = "my_created_by"')
426
- expect(aws_instance).to receive(:add_tag).with('created_by', hash_including(:value => 'my_created_by')).at_least(:once)
427
- expect(add_tags).to be_nil
428
- end
429
- end
430
- end
431
-
432
- describe '#populate_dns' do
433
- let( :vpc_instance ) { {ip_address: nil, private_ip_address: "vpc_private_ip", dns_name: "vpc_dns_name"} }
434
- let( :ec2_instance ) { {ip_address: "ec2_public_ip", private_ip_address: "ec2_private_ip", dns_name: "ec2_dns_name"} }
435
- subject(:populate_dns) { aws.populate_dns }
436
-
437
- context 'on a public EC2 instance' do
438
- before :each do
439
- @hosts.each {|host| host['instance'] = make_instance ec2_instance}
440
- end
441
-
442
- it 'sets host ip to instance.ip_address' do
443
- populate_dns
444
- hosts = aws.instance_variable_get( :@hosts )
445
- hosts.each do |host|
446
- expect(host['ip']).to eql(ec2_instance[:ip_address])
447
- end
448
- end
449
-
450
- it 'sets host private_ip to instance.private_ip_address' do
451
- populate_dns
452
- hosts = aws.instance_variable_get( :@hosts )
453
- hosts.each do |host|
454
- expect(host['private_ip']).to eql(ec2_instance[:private_ip_address])
455
- end
456
- end
457
-
458
- it 'sets host dns_name to instance.dns_name' do
459
- populate_dns
460
- hosts = aws.instance_variable_get( :@hosts )
461
- hosts.each do |host|
462
- expect(host['dns_name']).to eql(ec2_instance[:dns_name])
463
- end
464
- end
465
- end
466
-
467
- context 'on a VPC based instance' do
468
- before :each do
469
- @hosts.each {|host| host['instance'] = make_instance vpc_instance}
470
- end
471
-
472
- it 'sets host ip to instance.private_ip_address' do
473
- populate_dns
474
- hosts = aws.instance_variable_get( :@hosts )
475
- hosts.each do |host|
476
- expect(host['ip']).to eql(vpc_instance[:private_ip_address])
477
- end
478
- end
479
-
480
- it 'sets host private_ip to instance.private_ip_address' do
481
- populate_dns
482
- hosts = aws.instance_variable_get( :@hosts )
483
- hosts.each do |host|
484
- expect(host['private_ip']).to eql(vpc_instance[:private_ip_address])
485
- end
486
- end
487
-
488
- it 'sets host dns_name to instance.dns_name' do
489
- populate_dns
490
- hosts = aws.instance_variable_get( :@hosts )
491
- hosts.each do |host|
492
- expect(host['dns_name']).to eql(vpc_instance[:dns_name])
493
- end
494
- end
495
- end
496
- end
497
-
498
- describe '#etc_hosts_entry' do
499
- let( :host ) { @hosts[0] }
500
- let( :interface ) { :ip }
501
- subject(:etc_hosts_entry) { aws.etc_hosts_entry(host, interface) }
502
-
503
- it 'returns a predictable host entry' do
504
- expect(aws).to receive(:get_domain_name).and_return('lan')
505
- expect(etc_hosts_entry).to eq("ip.address.for.vm1\tvm1 vm1.lan vm1.box.tld\n")
506
- end
507
-
508
- context 'when :private_ip is requested' do
509
- let( :interface ) { :private_ip }
510
- it 'returns host entry for the private_ip' do
511
- host = @hosts[0]
512
- expect(aws).to receive(:get_domain_name).and_return('lan')
513
- expect(etc_hosts_entry).to eq("private.ip.for.vm1\tvm1 vm1.lan vm1.box.tld\n")
514
- end
515
- end
516
- end
517
-
518
- describe '#configure_hosts' do
519
- subject(:configure_hosts) { aws.configure_hosts }
520
-
521
- it { is_expected.to be_nil }
522
-
523
- context 'calls #set_etc_hosts' do
524
- it 'for each host (except the f5 ones)' do
525
- non_netdev_hosts = @hosts.select{ |h| !(h['platform'] =~ /f5|netscaler/) }
526
- expect(aws).to receive(:set_etc_hosts).exactly(non_netdev_hosts.size).times
527
- expect(configure_hosts).to be_nil
528
- end
529
-
530
- it 'with predictable host entries' do
531
- @hosts = [@hosts[0], @hosts[1]]
532
- entries = "127.0.0.1\tlocalhost localhost.localdomain\n"\
533
- "private.ip.for.vm1\tvm1 vm1.lan vm1.box.tld\n"\
534
- "ip.address.for.vm2\tvm2 vm2.lan vm2.box.tld\n"
535
- allow(aws).to receive(:get_domain_name).and_return('lan')
536
- expect(aws).to receive(:set_etc_hosts).with(@hosts[0], entries)
537
- expect(aws).to receive(:set_etc_hosts).with(@hosts[1], anything)
538
- expect(configure_hosts).to be_nil
539
- end
540
- end
541
- end
542
-
543
- describe '#enable_root_on_hosts' do
544
- context 'enabling root shall be called once for the ubuntu machine' do
545
- it "should enable root once" do
546
- allow(aws).to receive(:enable_root_netscaler)
547
- expect( aws ).to receive(:copy_ssh_to_root).with( @hosts[3], options ).once()
548
- expect( aws ).to receive(:enable_root_login).with( @hosts[3], options).once()
549
- aws.enable_root_on_hosts();
550
- end
551
- end
552
-
553
- it 'enables root once on the f5 host through its code path' do
554
- allow(aws).to receive(:enable_root_netscaler)
555
- expect( aws ).to receive(:enable_root_f5).with( @hosts[4] ).once()
556
- aws.enable_root_on_hosts()
557
- end
558
- end
559
-
560
- describe '#enable_root_f5' do
561
- let( :f5_host ) { @hosts[4] }
562
- subject(:enable_root_f5) { aws.enable_root_f5(f5_host) }
563
-
564
- it 'creates a password on the host' do
565
- result_mock = Beaker::Result.new(f5_host, '')
566
- result_mock.exit_code = 0
567
- allow( f5_host ).to receive( :exec ).and_return(result_mock)
568
- allow( aws ).to receive( :backoff_sleep )
569
- sha_mock = Object.new
570
- allow( Digest::SHA256 ).to receive( :new ).and_return(sha_mock)
571
- expect( sha_mock ).to receive( :hexdigest ).once()
572
- enable_root_f5
573
- end
574
-
575
- it 'tries 10x before failing correctly' do
576
- result_mock = Beaker::Result.new(f5_host, '')
577
- result_mock.exit_code = 2
578
- allow( f5_host ).to receive( :exec ).and_return(result_mock)
579
- expect( aws ).to receive( :backoff_sleep ).exactly(9).times
580
- expect{ enable_root_f5 }.to raise_error( RuntimeError, /unable/ )
581
- end
582
- end
583
-
584
- describe '#enable_root_netscaler' do
585
- let( :ns_host ) { @hosts[5] }
586
- subject(:enable_root_netscaler) { aws.enable_root_netscaler(ns_host) }
587
-
588
- it 'set password to instance id of the host' do
589
- instance_mock = Object.new
590
- allow( instance_mock ).to receive(:id).and_return("i-842018")
591
- ns_host["instance"]=instance_mock
592
- enable_root_netscaler
593
- expect(ns_host['ssh'][:password]).to eql("i-842018")
594
- end
595
- end
596
-
597
- describe '#set_hostnames' do
598
- subject(:set_hostnames) { aws.set_hostnames }
599
- it 'returns @hosts' do
600
- expect(set_hostnames).to eq(@hosts)
601
- end
602
-
603
- context 'for each host' do
604
- it 'calls exec' do
605
- @hosts.each do |host|
606
- expect(host).to receive(:exec).once unless host['platform'] =~ /netscaler/
607
- end
608
- expect(set_hostnames).to eq(@hosts)
609
- end
610
-
611
- it 'passes a Command instance to exec' do
612
- @hosts.each do |host|
613
- expect(host).to receive(:exec).with( instance_of(Beaker::Command) ).once unless host['platform'] =~ /netscaler/
614
- end
615
- expect(set_hostnames).to eq(@hosts)
616
- end
617
-
618
- it 'sets the the vmhostname to the dns_name for each host' do
619
- expect(set_hostnames).to eq(@hosts)
620
- @hosts.each do |host|
621
- expect(host[:vmhostname]).to eq(host[:dns_name])
622
- expect(host[:vmhostname]).to eq(host.hostname)
623
- end
624
- end
625
-
626
- it 'sets the the vmhostname to the beaker config name for each host' do
627
- options[:use_beaker_hostnames] = true
628
- @hosts.each do |host|
629
- host[:name] = "prettyponyprincess"
630
- end
631
- expect(set_hostnames).to eq(@hosts)
632
- @hosts.each do |host|
633
- puts host[:name]
634
- expect(host[:vmhostname]).to eq(host[:name])
635
- expect(host[:vmhostname]).to eq(host.hostname)
636
- end
637
- end
638
-
639
- end
640
- end
641
-
642
- describe '#backoff_sleep' do
643
- it "should call sleep 1024 times at attempt 10" do
644
- expect_any_instance_of( Object ).to receive(:sleep).with(1024)
645
- aws.backoff_sleep(10)
646
- end
647
- end
648
-
649
- describe '#public_key' do
650
- subject(:public_key) { aws.public_key }
651
-
652
- it "retrieves contents from local ~/.ssh/id_rsa.pub file" do
653
- # Stub calls to file read/exists
654
- key_value = 'foobar_Rsa'
655
- allow(File).to receive(:exists?).with(/id_dsa.pub/) { false }
656
- allow(File).to receive(:exists?).with(/id_rsa.pub/) { true }
657
- allow(File).to receive(:read).with(/id_rsa.pub/) { key_value }
658
-
659
- # Should return contents of allow( previously ).to receivebed id_rsa.pub
660
- expect(public_key).to be === key_value
661
- end
662
-
663
- it "retrieves contents from local ~/.ssh/id_dsa.pub file" do
664
- # Stub calls to file read/exists
665
- key_value = 'foobar_Dsa'
666
- allow(File).to receive(:exists?).with(/id_rsa.pub/) { false }
667
- allow(File).to receive(:exists?).with(/id_dsa.pub/) { true }
668
- allow(File).to receive(:read).with(/id_dsa.pub/) { key_value }
669
-
670
- expect(public_key).to be === key_value
671
- end
672
-
673
- it "should return an error if the files do not exist" do
674
- expect { public_key }.to raise_error(RuntimeError, /Expected to find a public key/)
675
- end
676
-
677
- it "uses options-provided keys" do
678
- opts = aws.instance_variable_get( :@options )
679
- opts[:ssh][:keys] = ['fake_key1', 'fake_key2']
680
- aws.instance_variable_set( :@options, opts )
681
-
682
- key_value = 'foobar_Custom2'
683
- allow(File).to receive(:exists?).with(anything) { false }
684
- allow(File).to receive(:exists?).with(/fake_key2/) { true }
685
- allow(File).to receive(:read).with(/fake_key2/) { key_value }
686
-
687
- expect(public_key).to be === key_value
688
- end
689
- end
690
-
691
- describe '#key_name' do
692
- it 'returns a key name from the local hostname' do
693
- # Mock out the hostname and local user calls
694
- expect( Socket ).to receive(:gethostname) { "foobar" }
695
- expect( aws ).to receive(:local_user) { "bob" }
696
-
697
- # Should match the expected composite key name
698
- expect(aws.key_name).to match(/^Beaker-bob-foobar-/)
699
- end
700
-
701
- it 'uses the generated random string from :aws_keyname_modifier' do
702
- expect(aws.key_name).to match(/#{options[:aws_keyname_modifier]}/)
703
- end
704
-
705
- it 'uses nanosecond time value to make key name collision harder' do
706
- options[:timestamp] = Time.now
707
- nanosecond_value = options[:timestamp].strftime("%N")
708
- expect(aws.key_name).to match(/#{nanosecond_value}/)
709
- end
710
- end
711
-
712
- describe '#local_user' do
713
- it 'returns ENV["USER"]' do
714
- stub_const('ENV', ENV.to_hash.merge('USER' => 'SuperUser'))
715
- expect(aws.local_user).to eq("SuperUser")
716
- end
717
- end
718
-
719
- describe '#ensure_key_pair' do
720
- let( :region ) { double('region', :name => 'test_region_name') }
721
- subject(:ensure_key_pair) { aws.ensure_key_pair(region) }
722
- let( :key_name ) { "Beaker-rspec-SUT" }
723
-
724
- it 'deletes the given keypair, then recreates it' do
725
- allow( aws ).to receive( :key_name ).and_return(key_name)
726
-
727
- expect( aws ).to receive( :delete_key_pair ).with( region, key_name).once.ordered
728
- expect( aws ).to receive( :create_new_key_pair ).with( region, key_name).once.ordered
729
- ensure_key_pair
730
- end
731
- end
732
-
733
- describe '#delete_key_pair_all_regions' do
734
- it 'calls delete_key_pair over all regions' do
735
- key_name = 'kname_test1538'
736
- allow(aws).to receive( :key_name ).and_return(key_name)
737
- regions = []
738
- regions << double('region', :key_pairs => 'pair1', :name => 'name1')
739
- regions << double('region', :key_pairs => 'pair2', :name => 'name2')
740
- ec2_mock = Object.new
741
- allow(ec2_mock).to receive( :regions ).and_return(regions)
742
- aws.instance_variable_set( :@ec2, ec2_mock )
743
- region_keypairs_hash_mock = {}
744
- region_keypairs_hash_mock[double('region')] = ['key1', 'key2', 'key3']
745
- region_keypairs_hash_mock[double('region')] = ['key4', 'key5', 'key6']
746
- allow( aws ).to receive( :my_key_pairs ).and_return( region_keypairs_hash_mock )
747
-
748
- region_keypairs_hash_mock.each_pair do |region, keyname_array|
749
- keyname_array.each do |keyname|
750
- expect( aws ).to receive( :delete_key_pair ).with( region, keyname )
751
- end
752
- end
753
- aws.delete_key_pair_all_regions
754
- end
755
- end
756
-
757
- describe '#my_key_pairs' do
758
- let( :region ) { double('region', :name => 'test_region_name') }
759
-
760
- it 'uses the default keyname if no filter is given' do
761
- default_keyname_answer = 'test_pair_6193'
762
- allow( aws ).to receive( :key_name ).and_return( default_keyname_answer )
763
-
764
- kp_mock_1 = double('keypair')
765
- kp_mock_2 = double('keypair')
766
- regions = []
767
- regions << double('region', :key_pairs => kp_mock_1, :name => 'name1')
768
- regions << double('region', :key_pairs => kp_mock_2, :name => 'name2')
769
- ec2_mock = Object.new
770
- allow( ec2_mock ).to receive( :regions ).and_return( regions )
771
- aws.instance_variable_set( :@ec2, ec2_mock )
772
-
773
- kp_mock = double('keypair')
774
- allow( region ).to receive( :key_pairs ).and_return( kp_mock )
775
- expect( kp_mock_1 ).to receive( :filter ).with( 'key-name', default_keyname_answer ).and_return( [] )
776
- expect( kp_mock_2 ).to receive( :filter ).with( 'key-name', default_keyname_answer ).and_return( [] )
777
-
778
- aws.my_key_pairs()
779
- end
780
-
781
- it 'uses the filter passed if given' do
782
- default_keyname_answer = 'test_pair_6194'
783
- allow( aws ).to receive( :key_name ).and_return( default_keyname_answer )
784
- name_filter = 'filter_pair_1597'
785
- filter_star = "#{name_filter}-*"
786
-
787
- kp_mock_1 = double('keypair')
788
- kp_mock_2 = double('keypair')
789
- regions = []
790
- regions << double('region', :key_pairs => kp_mock_1, :name => 'name1')
791
- regions << double('region', :key_pairs => kp_mock_2, :name => 'name2')
792
- ec2_mock = Object.new
793
- allow( ec2_mock ).to receive( :regions ).and_return( regions )
794
- aws.instance_variable_set( :@ec2, ec2_mock )
795
-
796
- kp_mock = double('keypair')
797
- allow( region ).to receive( :key_pairs ).and_return( kp_mock )
798
- expect( kp_mock_1 ).to receive( :filter ).with( 'key-name', filter_star ).and_return( [] )
799
- expect( kp_mock_2 ).to receive( :filter ).with( 'key-name', filter_star ).and_return( [] )
800
-
801
- aws.my_key_pairs(name_filter)
802
- end
803
- end
804
-
805
- describe '#delete_key_pair' do
806
- let( :region ) { double('region', :name => 'test_region_name') }
807
-
808
- it 'calls delete on a keypair if it exists' do
809
- pair_name = 'pair1'
810
- kp_mock = double('keypair', :exists? => true)
811
- expect( kp_mock ).to receive( :delete ).once
812
- pairs = { pair_name => kp_mock }
813
- allow( region ).to receive( :key_pairs ).and_return( pairs )
814
- aws.delete_key_pair(region, pair_name)
815
- end
816
-
817
- it 'skips delete on a keypair if it does not exist' do
818
- pair_name = 'pair1'
819
- kp_mock = double('keypair', :exists? => false)
820
- expect( kp_mock ).to receive( :delete ).never
821
- pairs = { pair_name => kp_mock }
822
- allow( region ).to receive( :key_pairs ).and_return( pairs )
823
- aws.delete_key_pair(region, pair_name)
824
- end
825
- end
826
-
827
- describe '#create_new_key_pair' do
828
- let(:region) { double('region', :name => 'test_region_name') }
829
- let(:ssh_string) { 'ssh_string_test_0867' }
830
- let(:pairs) { double('keypairs') }
831
- let(:pair) { double('keypair') }
832
- let(:pair_name) { 'pair_name_1555432' }
833
-
834
- before :each do
835
- allow(aws).to receive(:public_key).and_return(ssh_string)
836
- expect(pairs).to receive(:import).with(pair_name, ssh_string)
837
- expect(pairs).to receive(:[]).with(pair_name).and_return(pair)
838
- expect(region).to receive(:key_pairs).and_return(pairs).twice
839
- end
840
-
841
- it 'imports the key given from public_key' do
842
- expect(pair).to receive(:exists?).and_return(true)
843
- aws.create_new_key_pair(region, pair_name)
844
- end
845
-
846
- it 'raises an exception if subsequent keypair check is false' do
847
- expect(pair).to receive(:exists?).and_return(false).exactly(5).times
848
- expect(aws).to receive(:backoff_sleep).exactly(5).times
849
- expect { aws.create_new_key_pair(region, pair_name) }.
850
- to raise_error(RuntimeError,
851
- "AWS key pair #{pair_name} can not be queried, even after import")
852
- end
853
- end
854
-
855
- describe '#group_id' do
856
- it 'should return a predicatable group_id from a port list' do
857
- expect(aws.group_id([22, 1024])).to eq("Beaker-2799478787")
858
- end
859
-
860
- it 'should return a predicatable group_id from an empty list' do
861
- expect { aws.group_id([]) }.to raise_error(ArgumentError, "Ports list cannot be nil or empty")
862
- end
863
- end
864
-
865
- describe '#ensure_group' do
866
- let( :vpc ) { double('vpc') }
867
- let( :ports ) { [22, 80, 8080] }
868
- subject(:ensure_group) { aws.ensure_group(vpc, ports) }
869
-
870
- context 'for an existing group' do
871
- before :each do
872
- @group = double(:nil? => false)
873
- end
874
-
875
- it 'returns group from vpc lookup' do
876
- expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(@group)
877
- expect(ensure_group).to eq(@group)
878
- end
879
-
880
- context 'during group lookup' do
881
- it 'performs group_id lookup for ports' do
882
- expect(aws).to receive(:group_id).with(ports)
883
- expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(@group)
884
- expect(ensure_group).to eq(@group)
885
- end
886
-
887
- it 'filters on group_id' do
888
- expect(vpc).to receive(:security_groups).and_return(vpc)
889
- expect(vpc).to receive(:filter).with('group-name', 'Beaker-1521896090').and_return(vpc)
890
- expect(vpc).to receive(:first).and_return(@group)
891
- expect(ensure_group).to eq(@group)
892
- end
893
- end
894
- end
895
-
896
- context 'when group does not exist' do
897
- it 'creates group if group.nil?' do
898
- group = double(:nil? => true)
899
- expect(aws).to receive(:create_group).with(vpc, ports).and_return(group)
900
- expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(group)
901
- expect(ensure_group).to eq(group)
902
- end
903
- end
904
- end
905
-
906
- describe '#create_group' do
907
- let( :rv ) { double('rv') }
908
- let( :ports ) { [22, 80, 8080] }
909
- subject(:create_group) { aws.create_group(rv, ports) }
910
-
911
- before :each do
912
- @group = double(:nil? => false)
913
- end
914
-
915
- it 'returns a newly created group' do
916
- allow(rv).to receive_message_chain('security_groups.create').and_return(@group)
917
- allow(@group).to receive(:authorize_ingress).at_least(:once)
918
- expect(create_group).to eq(@group)
919
- end
920
-
921
- it 'requests group_id for ports given' do
922
- expect(aws).to receive(:group_id).with(ports)
923
- allow(rv).to receive_message_chain('security_groups.create').and_return(@group)
924
- allow(@group).to receive(:authorize_ingress).at_least(:once)
925
- expect(create_group).to eq(@group)
926
- end
927
-
928
- it 'creates group with expected arguments' do
929
- group_name = "Beaker-1521896090"
930
- group_desc = "Custom Beaker security group for #{ports.to_a}"
931
- expect(rv).to receive_message_chain('security_groups.create')
932
- .with(group_name, :description => group_desc)
933
- .and_return(@group)
934
- allow(@group).to receive(:authorize_ingress).at_least(:once)
935
- expect(create_group).to eq(@group)
936
- end
937
-
938
- it 'authorizes requested ports for group' do
939
- expect(rv).to receive_message_chain('security_groups.create').and_return(@group)
940
- ports.each do |port|
941
- expect(@group).to receive(:authorize_ingress).with(:tcp, port).once
942
- end
943
- expect(create_group).to eq(@group)
944
- end
945
- end
946
-
947
- describe '#load_fog_credentials' do
948
- # Receive#and_call_original below allows us to test the core load_fog_credentials method
949
- let(:creds) { {:access_key => 'awskey', :secret_key => 'awspass'} }
950
- let(:dot_fog) { '.fog' }
951
- subject(:load_fog_credentials) { aws.load_fog_credentials(dot_fog) }
952
-
953
- it 'returns loaded fog credentials' do
954
- fog_hash = {:default => {:aws_access_key_id => 'awskey', :aws_secret_access_key => 'awspass'}}
955
- expect(aws).to receive(:load_fog_credentials).and_call_original
956
- expect(YAML).to receive(:load_file).and_return(fog_hash)
957
- expect(load_fog_credentials).to eq(creds)
958
- end
959
-
960
- context 'raises errors' do
961
- it 'if missing access_key credential' do
962
- fog_hash = {:default => {:aws_secret_access_key => 'awspass'}}
963
- err_text = "You must specify an aws_access_key_id in your .fog file (#{dot_fog}) for ec2 instances!"
964
- expect(aws).to receive(:load_fog_credentials).and_call_original
965
- expect(YAML).to receive(:load_file).and_return(fog_hash)
966
- expect { load_fog_credentials }.to raise_error(err_text)
967
- end
968
-
969
- it 'if missing secret_key credential' do
970
- dot_fog = '.fog'
971
- fog_hash = {:default => {:aws_access_key_id => 'awskey'}}
972
- err_text = "You must specify an aws_secret_access_key in your .fog file (#{dot_fog}) for ec2 instances!"
973
- expect(aws).to receive(:load_fog_credentials).and_call_original
974
- expect(YAML).to receive(:load_file).and_return(fog_hash)
975
- expect { load_fog_credentials }.to raise_error(err_text)
976
- end
977
- end
978
- end
979
- end
980
- end