beaker-vagrant 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +25 -0
- data/.rspec +3 -0
- data/.simplecov +9 -0
- data/Gemfile +27 -0
- data/LICENSE +202 -0
- data/README.md +36 -0
- data/Rakefile +161 -0
- data/acceptance/config/nodes/redhat-nodes.yml +25 -0
- data/beaker-vagrant.gemspec +37 -0
- data/bin/beaker-vagrant +32 -0
- data/docs/vagrant.md +165 -0
- data/docs/vagrant_hosts_file_examples.md +60 -0
- data/docs/vagrant_libvirt.md +58 -0
- data/lib/beaker-vagrant/version.rb +3 -0
- data/lib/beaker/hypervisor/vagrant.rb +287 -0
- data/lib/beaker/hypervisor/vagrant_custom.rb +11 -0
- data/lib/beaker/hypervisor/vagrant_fusion.rb +17 -0
- data/lib/beaker/hypervisor/vagrant_libvirt.rb +41 -0
- data/lib/beaker/hypervisor/vagrant_parallels.rb +18 -0
- data/lib/beaker/hypervisor/vagrant_virtualbox.rb +76 -0
- data/lib/beaker/hypervisor/vagrant_workstation.rb +13 -0
- data/spec/beaker/hypervisor/vagrant_custom_spec.rb +46 -0
- data/spec/beaker/hypervisor/vagrant_fusion_spec.rb +32 -0
- data/spec/beaker/hypervisor/vagrant_libvirt_spec.rb +61 -0
- data/spec/beaker/hypervisor/vagrant_parallels_spec.rb +44 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +479 -0
- data/spec/beaker/hypervisor/vagrant_virtualbox_spec.rb +44 -0
- data/spec/beaker/hypervisor/vagrant_workstation_spec.rb +32 -0
- data/spec/spec_helper.rb +17 -0
- metadata +214 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'beaker/hypervisor/vagrant'
|
2
|
+
|
3
|
+
class Beaker::VagrantFusion < Beaker::Vagrant
|
4
|
+
def provision(provider = 'vmware_fusion')
|
5
|
+
# By default vmware_fusion creates a .vagrant directory relative to the
|
6
|
+
# Vagrantfile path. That means beaker tries to scp the VM to itself unless
|
7
|
+
# we move the VM files elsewhere.
|
8
|
+
ENV['VAGRANT_VMWARE_CLONE_DIRECTORY'] = '~/.vagrant/vmware_fusion'
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.provider_vfile_section(host, options)
|
13
|
+
" v.vm.provider :vmware_fusion do |v|\n" +
|
14
|
+
" v.vmx['memsize'] = '#{memsize(host, options)}'\n" +
|
15
|
+
" end\n"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'beaker/hypervisor/vagrant'
|
2
|
+
|
3
|
+
class Beaker::VagrantLibvirt < Beaker::Vagrant
|
4
|
+
@memory = nil
|
5
|
+
@cpu = nil
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_reader :memory
|
9
|
+
end
|
10
|
+
|
11
|
+
# Return a random mac address with colons
|
12
|
+
#
|
13
|
+
# @return [String] a random mac address
|
14
|
+
def randmac
|
15
|
+
"08:00:27:" + (1..3).map{"%0.2X"%rand(256)}.join(':')
|
16
|
+
end
|
17
|
+
|
18
|
+
def provision(provider = 'libvirt')
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.provider_vfile_section(host, options)
|
23
|
+
" v.vm.provider :libvirt do |node|\n" +
|
24
|
+
" node.cpus = #{cpus(host, options)}\n" +
|
25
|
+
" node.memory = #{memsize(host, options)}\n" +
|
26
|
+
build_options_str(options) +
|
27
|
+
" end\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.build_options_str(options)
|
31
|
+
other_options_str = ''
|
32
|
+
if options['libvirt']
|
33
|
+
other_options = []
|
34
|
+
options['libvirt'].each do |k, v|
|
35
|
+
other_options << " node.#{k} = '#{v}'"
|
36
|
+
end
|
37
|
+
other_options_str = other_options.join("\n")
|
38
|
+
end
|
39
|
+
"#{other_options_str}\n"
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'beaker/hypervisor/vagrant'
|
2
|
+
|
3
|
+
class Beaker::VagrantParallels < Beaker::Vagrant
|
4
|
+
def provision(provider = 'parallels')
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.provider_vfile_section(host, options)
|
9
|
+
provider_section = ""
|
10
|
+
provider_section << " v.vm.provider :parallels do |prl|\n"
|
11
|
+
provider_section << " prl.optimize_power_consumption = false\n"
|
12
|
+
provider_section << " prl.memory = '#{memsize(host,options)}'\n"
|
13
|
+
provider_section << " prl.update_guest_tools = false\n" if options[:prl_update_guest_tools] == 'disable'
|
14
|
+
provider_section << " end\n"
|
15
|
+
|
16
|
+
provider_section
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'beaker/hypervisor/vagrant'
|
2
|
+
|
3
|
+
class Beaker::VagrantVirtualbox < Beaker::Vagrant
|
4
|
+
def provision(provider = 'virtualbox')
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
# Generate a VM customization string
|
9
|
+
def self.vb_customize(command, args)
|
10
|
+
" vb.customize ['#{command}', #{args.map{|a| "'#{a.to_s}'"}.join(", ")}]\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
# Generate a VM customization string for the current VM
|
14
|
+
def self.vb_customize_vm(command, args)
|
15
|
+
" vb.customize ['#{command}', :id, #{args.map{|a| "'#{a.to_s}'"}.join(", ")}]\n"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.provider_vfile_section(host, options)
|
19
|
+
# Allow memory and CPUs to be set at a per node level or overall, and take the most specific setting
|
20
|
+
provider_section = ""
|
21
|
+
provider_section << " v.vm.provider :virtualbox do |vb|\n"
|
22
|
+
provider_section << " vb.customize ['modifyvm', :id, '--memory', '#{memsize(host,options)}', '--cpus', '#{cpus(host,options)}']\n"
|
23
|
+
provider_section << " vb.vbguest.auto_update = false" if options[:vbguest_plugin] == 'disable'
|
24
|
+
|
25
|
+
# Guest volume support
|
26
|
+
# - Creates a new AHCI controller with the requisite number of ports,
|
27
|
+
# the default controller is limited in its number of supported ports (2).
|
28
|
+
# The AHCI emulation is generic enough for acceptance testing, and
|
29
|
+
# presents the devices as SCSI devices in /sys/class/scsi_disk.
|
30
|
+
# - Creates the defined volumes in beaker's temporary folder and attaches
|
31
|
+
# them to the controller in order starting at port 0. This presents disks
|
32
|
+
# as 2:0:0:0, 3:0:0:0 ... much like you'd see on commercial storage boxes
|
33
|
+
if host['volumes']
|
34
|
+
provider_section << self.vb_customize_vm('storagectl', [
|
35
|
+
'--name', 'SATA Controller',
|
36
|
+
'--add', 'sata',
|
37
|
+
'--controller', 'IntelAHCI',
|
38
|
+
'--portcount', host['volumes'].length
|
39
|
+
])
|
40
|
+
host['volumes'].keys.each_with_index do |volume, index|
|
41
|
+
volume_path = "#{host.name}-#{volume}.vdi"
|
42
|
+
provider_section << self.vb_customize('createhd', [
|
43
|
+
'--filename', volume_path,
|
44
|
+
'--size', host['volumes'][volume]['size'],
|
45
|
+
])
|
46
|
+
provider_section << self.vb_customize_vm('storageattach', [
|
47
|
+
'--storagectl', 'SATA Controller',
|
48
|
+
'--port', index,
|
49
|
+
'--device', 0,
|
50
|
+
'--type', 'hdd',
|
51
|
+
'--medium', volume_path,
|
52
|
+
])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
provider_section << " vb.customize [\"modifyvm\", :id, \"--natdnshostresolver1\", \"#{host['natdns']}\"]\n" unless host['natdns'].nil?
|
57
|
+
|
58
|
+
provider_section << " vb.customize [\"modifyvm\", :id, \"--natdnsproxy1\", \"#{host['natdns']}\"]\n" unless host['natdns'].nil?
|
59
|
+
|
60
|
+
provider_section << " vb.gui = true\n" unless host['vb_gui'].nil?
|
61
|
+
|
62
|
+
provider_section << " [\"modifyvm\", :id, \"--cpuidset\", \"1\",\"000206a7\",\"02100800\",\"1fbae3bf\",\"bfebfbff\"\]" if /osx/i.match(host['platform'])
|
63
|
+
|
64
|
+
if host['disk_path']
|
65
|
+
unless File.exist?(host['disk_path'])
|
66
|
+
host['disk_path'] = File.join(host['disk_path'], "#{host.name}.vmdk")
|
67
|
+
provider_section << " vb.customize ['createhd', '--filename', '#{host['disk_path']}', '--size', #{host['disk_size'] ||= 5 * 1024}, '--format', 'vmdk']\n"
|
68
|
+
end
|
69
|
+
provider_section << " vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium','#{host['disk_path']}']\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
provider_section << " end\n"
|
73
|
+
|
74
|
+
provider_section
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,13 @@
|
|
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
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Beaker::VagrantCustom do
|
4
|
+
let( :options ) { make_opts.merge({ :hosts_file => 'sample.cfg', 'logger' => double().as_null_object }) }
|
5
|
+
let( :vagrant ) { Beaker::VagrantCustom.new( @hosts, options ) }
|
6
|
+
|
7
|
+
let(:test_dir) { 'tmp/tests' }
|
8
|
+
let(:custom_vagrant_file_path) { File.expand_path(test_dir + '/CustomVagrantfile') }
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
@hosts = make_hosts()
|
12
|
+
end
|
13
|
+
|
14
|
+
it "uses the vagrant_custom provider for provisioning" do
|
15
|
+
@hosts.each do |host|
|
16
|
+
host_prev_name = host['user']
|
17
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, 'vagrant' ).once
|
18
|
+
expect( vagrant ).to receive( :copy_ssh_to_root ).with( host, options ).once
|
19
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, host_prev_name ).once
|
20
|
+
end
|
21
|
+
expect( vagrant ).to receive( :hack_etc_hosts ).with( @hosts, options ).once
|
22
|
+
FakeFS.activate!
|
23
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "up" ).once
|
24
|
+
vagrant.provision
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'takes vagrant configuration from existing file' do
|
28
|
+
it 'writes the vagrant file to the correct location' do
|
29
|
+
options.merge!({ :vagrantfile_path => custom_vagrant_file_path })
|
30
|
+
|
31
|
+
create_files([custom_vagrant_file_path])
|
32
|
+
|
33
|
+
vagrant_file_contents = <<-EOF
|
34
|
+
FOO
|
35
|
+
EOF
|
36
|
+
File.open(custom_vagrant_file_path, 'w') { |file| file.write(vagrant_file_contents) }
|
37
|
+
|
38
|
+
vagrant_copy_location = "#{test_dir}/NewVagrantLocation"
|
39
|
+
vagrant.instance_variable_set(:@vagrant_file, vagrant_copy_location)
|
40
|
+
vagrant.make_vfile(@hosts, options)
|
41
|
+
vagrant_copy_file = File.open(vagrant_copy_location, 'r')
|
42
|
+
expect(vagrant_copy_file.read).to be === vagrant_file_contents
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Beaker::VagrantFusion do
|
4
|
+
let( :options ) { make_opts.merge({ :hosts_file => 'sample.cfg', 'logger' => double().as_null_object }) }
|
5
|
+
let( :vagrant ) { Beaker::VagrantFusion.new( @hosts, options ) }
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@hosts = make_hosts()
|
9
|
+
end
|
10
|
+
|
11
|
+
it "uses the vmware_fusion provider for provisioning" do
|
12
|
+
@hosts.each do |host|
|
13
|
+
host_prev_name = host['user']
|
14
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, 'vagrant' ).once
|
15
|
+
expect( vagrant ).to receive( :copy_ssh_to_root ).with( host, options ).once
|
16
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, host_prev_name ).once
|
17
|
+
end
|
18
|
+
expect( vagrant ).to receive( :hack_etc_hosts ).with( @hosts, options ).once
|
19
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "up --provider vmware_fusion" ).once
|
20
|
+
vagrant.provision
|
21
|
+
end
|
22
|
+
|
23
|
+
it "can make a Vagranfile for a set of hosts" do
|
24
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
25
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
26
|
+
|
27
|
+
vagrant.make_vfile( @hosts )
|
28
|
+
|
29
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
30
|
+
expect( vagrantfile ).to include( %Q{ v.vm.provider :vmware_fusion do |v|\n v.vmx['memsize'] = '1024'\n end})
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Beaker::VagrantLibvirt do
|
4
|
+
let( :options ) { make_opts.merge({ :hosts_file => 'sample.cfg',
|
5
|
+
'logger' => double().as_null_object,
|
6
|
+
'libvirt' => { 'uri' => 'qemu+ssh://root@host/system'},
|
7
|
+
'vagrant_cpus' => 2,
|
8
|
+
}) }
|
9
|
+
let( :vagrant ) { Beaker::VagrantLibvirt.new( @hosts, options ) }
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
@hosts = make_hosts()
|
13
|
+
end
|
14
|
+
|
15
|
+
it "uses the vagrant_libvirt provider for provisioning" do
|
16
|
+
@hosts.each do |host|
|
17
|
+
host_prev_name = host['user']
|
18
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, 'vagrant' ).once
|
19
|
+
expect( vagrant ).to receive( :copy_ssh_to_root ).with( host, options ).once
|
20
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, host_prev_name ).once
|
21
|
+
end
|
22
|
+
expect( vagrant ).to receive( :hack_etc_hosts ).with( @hosts, options ).once
|
23
|
+
FakeFS.activate!
|
24
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "up --provider libvirt" ).once
|
25
|
+
vagrant.provision
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'Correct vagrant configuration' do
|
29
|
+
before(:each) do
|
30
|
+
FakeFS.activate!
|
31
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
32
|
+
|
33
|
+
vagrant.make_vfile( @hosts, options )
|
34
|
+
@vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can make a Vagranfile for a set of hosts" do
|
38
|
+
expect( @vagrantfile ).to include( %Q{ v.vm.provider :libvirt do |node|})
|
39
|
+
end
|
40
|
+
|
41
|
+
it "can specify the memory as an integer" do
|
42
|
+
expect( @vagrantfile.split("\n").map(&:strip) )
|
43
|
+
.to include('node.memory = 1024')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "can specify the number of cpus" do
|
47
|
+
expect( @vagrantfile.split("\n").map(&:strip) )
|
48
|
+
.to include("node.cpus = 2")
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can specify any libvirt option" do
|
52
|
+
expect( @vagrantfile.split("\n").map(&:strip) )
|
53
|
+
.to include("node.uri = 'qemu+ssh://root@host/system'")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "has a mac address in the proper format" do
|
57
|
+
expect( @vagrantfile.split("\n").map(&:strip) )
|
58
|
+
.to include(/:mac => "08:00:27:\h{2}:\h{2}:\h{2}"/)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Beaker::VagrantParallels do
|
4
|
+
let( :options ) { make_opts.merge({ :hosts_file => 'sample.cfg', 'logger' => double().as_null_object }) }
|
5
|
+
let( :vagrant ) { Beaker::VagrantParallels.new( @hosts, options ) }
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@hosts = make_hosts()
|
9
|
+
end
|
10
|
+
|
11
|
+
it "uses the parallels provider for provisioning" do
|
12
|
+
@hosts.each do |host|
|
13
|
+
host_prev_name = host['user']
|
14
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, 'vagrant' ).once
|
15
|
+
expect( vagrant ).to receive( :copy_ssh_to_root ).with( host, options ).once
|
16
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, host_prev_name ).once
|
17
|
+
end
|
18
|
+
expect( vagrant ).to receive( :hack_etc_hosts ).with( @hosts, options ).once
|
19
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "up --provider parallels" ).once
|
20
|
+
vagrant.provision
|
21
|
+
end
|
22
|
+
|
23
|
+
it "can make a Vagranfile for a set of hosts" do
|
24
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
25
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
26
|
+
|
27
|
+
vagrant.make_vfile( @hosts )
|
28
|
+
|
29
|
+
vagrantfile = File.read( File.expand_path( File.join( path, 'Vagrantfile' )))
|
30
|
+
expect( vagrantfile ).to include( %Q{ v.vm.provider :parallels do |prl|\n prl.optimize_power_consumption = false\n prl.memory = '1024'\n end})
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can disable the auto-update functionality of the Parallels Guest Tools" do
|
34
|
+
options.merge!({ :prl_update_guest_tools => 'disable' })
|
35
|
+
|
36
|
+
vfile_section = vagrant.class.provider_vfile_section( @hosts.first, options )
|
37
|
+
|
38
|
+
match = vfile_section.match(/prl.update_guest_tools = false/)
|
39
|
+
|
40
|
+
expect( match ).to_not be nil
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,479 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Beaker
|
4
|
+
describe Vagrant do
|
5
|
+
|
6
|
+
let( :options ) {
|
7
|
+
make_opts.merge({
|
8
|
+
'logger' => double().as_null_object,
|
9
|
+
:hosts_file => 'sample.cfg',
|
10
|
+
:forward_ssh_agent => true,
|
11
|
+
})
|
12
|
+
}
|
13
|
+
|
14
|
+
let( :vagrant ) { Beaker::Vagrant.new( @hosts, options ) }
|
15
|
+
|
16
|
+
before :each do
|
17
|
+
@hosts = make_hosts({
|
18
|
+
:mount_folders => {
|
19
|
+
:test_temp => {:from => './', :to => '/temp'},
|
20
|
+
:test_tmp => {:from => '../', :to => '/tmp'}
|
21
|
+
},
|
22
|
+
:forwarded_ports => {
|
23
|
+
:http => {:from => 10080, :to => 80},
|
24
|
+
:ssl => {:from => 4443, :to => 443},
|
25
|
+
:tomcat => {:from => 8080, :to => 8080}
|
26
|
+
}
|
27
|
+
})
|
28
|
+
end
|
29
|
+
|
30
|
+
it "stores the vagrant file in $WORKINGDIR/.vagrant/beaker_vagrant_files/sample.cfg" do
|
31
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
32
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
33
|
+
|
34
|
+
expect( path ).to be === File.join(Dir.pwd, '.vagrant', 'beaker_vagrant_files', 'sample.cfg')
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can make a Vagrantfile for a set of hosts" do
|
39
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
40
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
41
|
+
|
42
|
+
vagrant.make_vfile( @hosts )
|
43
|
+
|
44
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
45
|
+
puts "file is #{path}\n"
|
46
|
+
expect( vagrantfile ).to be === <<-EOF
|
47
|
+
Vagrant.configure("2") do |c|
|
48
|
+
c.ssh.insert_key = false
|
49
|
+
c.vm.define 'vm1' do |v|
|
50
|
+
v.vm.hostname = 'vm1'
|
51
|
+
v.vm.box = 'vm2vm1_of_my_box'
|
52
|
+
v.vm.box_url = 'http://address.for.my.box.vm1'
|
53
|
+
v.vm.box_check_update = 'true'
|
54
|
+
v.vm.network :private_network, ip: "ip.address.for.vm1", :netmask => "255.255.0.0", :mac => "0123456789"
|
55
|
+
v.vm.synced_folder './', '/temp', create: true
|
56
|
+
v.vm.synced_folder '../', '/tmp', create: true
|
57
|
+
v.vm.network :forwarded_port, guest: 80, host: 10080
|
58
|
+
v.vm.network :forwarded_port, guest: 443, host: 4443
|
59
|
+
v.vm.network :forwarded_port, guest: 8080, host: 8080
|
60
|
+
v.vm.provider :virtualbox do |vb|
|
61
|
+
vb.customize ['modifyvm', :id, '--memory', '1024', '--cpus', '1']
|
62
|
+
end
|
63
|
+
end
|
64
|
+
c.vm.define 'vm2' do |v|
|
65
|
+
v.vm.hostname = 'vm2'
|
66
|
+
v.vm.box = 'vm2vm2_of_my_box'
|
67
|
+
v.vm.box_url = 'http://address.for.my.box.vm2'
|
68
|
+
v.vm.box_check_update = 'true'
|
69
|
+
v.vm.network :private_network, ip: "ip.address.for.vm2", :netmask => "255.255.0.0", :mac => "0123456789"
|
70
|
+
v.vm.synced_folder './', '/temp', create: true
|
71
|
+
v.vm.synced_folder '../', '/tmp', create: true
|
72
|
+
v.vm.network :forwarded_port, guest: 80, host: 10080
|
73
|
+
v.vm.network :forwarded_port, guest: 443, host: 4443
|
74
|
+
v.vm.network :forwarded_port, guest: 8080, host: 8080
|
75
|
+
v.vm.provider :virtualbox do |vb|
|
76
|
+
vb.customize ['modifyvm', :id, '--memory', '1024', '--cpus', '1']
|
77
|
+
end
|
78
|
+
end
|
79
|
+
c.vm.define 'vm3' do |v|
|
80
|
+
v.vm.hostname = 'vm3'
|
81
|
+
v.vm.box = 'vm2vm3_of_my_box'
|
82
|
+
v.vm.box_url = 'http://address.for.my.box.vm3'
|
83
|
+
v.vm.box_check_update = 'true'
|
84
|
+
v.vm.network :private_network, ip: "ip.address.for.vm3", :netmask => "255.255.0.0", :mac => "0123456789"
|
85
|
+
v.vm.synced_folder './', '/temp', create: true
|
86
|
+
v.vm.synced_folder '../', '/tmp', create: true
|
87
|
+
v.vm.network :forwarded_port, guest: 80, host: 10080
|
88
|
+
v.vm.network :forwarded_port, guest: 443, host: 4443
|
89
|
+
v.vm.network :forwarded_port, guest: 8080, host: 8080
|
90
|
+
v.vm.provider :virtualbox do |vb|
|
91
|
+
vb.customize ['modifyvm', :id, '--memory', '1024', '--cpus', '1']
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
EOF
|
96
|
+
end
|
97
|
+
|
98
|
+
it "can make a Vagrantfile with ssh agent forwarding enabled" do
|
99
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
100
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
101
|
+
|
102
|
+
hosts = make_hosts({},1)
|
103
|
+
vagrant.make_vfile( hosts, options )
|
104
|
+
|
105
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
106
|
+
expect( vagrantfile ).to match(/(ssh.forward_agent = true)/)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "can make a Vagrantfile with synced_folder disabled" do
|
110
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
111
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
112
|
+
|
113
|
+
hosts = make_hosts({:synced_folder => 'disabled'},1)
|
114
|
+
vagrant.make_vfile( hosts, options )
|
115
|
+
|
116
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
117
|
+
expect( vagrantfile ).to match(/v.vm.synced_folder .* disabled: true/)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "can make a Vagrantfile with network mac autogenerated" do
|
121
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
122
|
+
|
123
|
+
hosts = make_hosts({},1)
|
124
|
+
vagrant.make_vfile( hosts, options )
|
125
|
+
|
126
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
127
|
+
expect( vagrantfile ).to match(/v.vm.network :private_network, ip: "ip.address.for.vm1", :netmask => "255.255.0.0", :mac => ".+/)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "can make a Vagrantfile with network mac specified" do
|
131
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
132
|
+
|
133
|
+
hosts = make_hosts({:network_mac => 'b6:33:ae:19:48:f9'},1)
|
134
|
+
vagrant.make_vfile( hosts, options )
|
135
|
+
|
136
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
137
|
+
expect( vagrantfile ).to match(/v.vm.network :private_network, ip: "ip.address.for.vm1", :netmask => "255.255.0.0", :mac => "b6:33:ae:19:48:f9/)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "can make a Vagrantfile with network mac disabled" do
|
141
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
142
|
+
|
143
|
+
hosts = make_hosts({:network_mac => 'false'},1)
|
144
|
+
vagrant.make_vfile( hosts, options )
|
145
|
+
|
146
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
147
|
+
expect( vagrantfile ).to match(/v.vm.network :private_network, ip: "ip.address.for.vm1", :netmask => "255.255.0.0"/)
|
148
|
+
end
|
149
|
+
|
150
|
+
context "when generating a windows config" do
|
151
|
+
before do
|
152
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
153
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
154
|
+
@hosts[0][:platform] = 'windows'
|
155
|
+
|
156
|
+
vagrant.make_vfile( @hosts )
|
157
|
+
|
158
|
+
@generated_file = File.read( File.expand_path( File.join( path, "Vagrantfile") ) )
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'has the proper port forwarding for RDP' do
|
162
|
+
expect( @generated_file ).to match /v.vm.network :forwarded_port, guest: 3389, host: 3389, id: 'rdp', auto_correct: true/
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'has the proper port forwarding for WinRM' do
|
166
|
+
expect( @generated_file ).to match /v.vm.network :forwarded_port, guest: 5985, host: 5985, id: 'winrm', auto_correct: true/
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'configures the guest type to windows' do
|
170
|
+
expect( @generated_file ).to match /v.vm.guest = :windows/
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'sets a non-default memsize' do
|
174
|
+
expect( @generated_file ).to match /'--memory', '2048',/
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
it "uses the memsize defined per vagrant host" do
|
179
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
180
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
181
|
+
|
182
|
+
vagrant.make_vfile( @hosts, {'vagrant_memsize' => 'hello!'} )
|
183
|
+
|
184
|
+
generated_file = File.read( File.expand_path( File.join( path, "Vagrantfile") ) )
|
185
|
+
|
186
|
+
match = generated_file.match(/vb.customize \['modifyvm', :id, '--memory', 'hello!', '--cpus', '1'\]/)
|
187
|
+
|
188
|
+
expect( match ).to_not be nil
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
it "uses the cpus defined per vagrant host" do
|
193
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
194
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
195
|
+
|
196
|
+
vagrant.make_vfile( @hosts, {'vagrant_cpus' => 'goodbye!'} )
|
197
|
+
|
198
|
+
generated_file = File.read( File.expand_path( File.join( path, "Vagrantfile") ) )
|
199
|
+
|
200
|
+
match = generated_file.match(/vb.customize \['modifyvm', :id, '--memory', '1024', '--cpus', 'goodbye!'\]/)
|
201
|
+
|
202
|
+
expect( match ).to_not be nil
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
context "port forwarding rules" do
|
207
|
+
it "supports all Vagrant parameters" do
|
208
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
209
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
210
|
+
|
211
|
+
hosts = make_hosts(
|
212
|
+
{
|
213
|
+
:forwarded_ports => {
|
214
|
+
:http => {
|
215
|
+
:from => 10080,
|
216
|
+
:from_ip => '127.0.0.1',
|
217
|
+
:to => 80,
|
218
|
+
:to_ip => '0.0.0.0',
|
219
|
+
:protocol => 'udp'
|
220
|
+
}
|
221
|
+
}
|
222
|
+
},1)
|
223
|
+
vagrant.make_vfile( hosts, options )
|
224
|
+
|
225
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
226
|
+
expect( vagrantfile ).to match(/v.vm.network :forwarded_port, protocol: 'udp', guest_ip: '0.0.0.0', guest: 80, host_ip: '127.0.0.1', host: 10080/)
|
227
|
+
end
|
228
|
+
|
229
|
+
it "supports supports from_ip" do
|
230
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
231
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
232
|
+
|
233
|
+
hosts = make_hosts(
|
234
|
+
{
|
235
|
+
:forwarded_ports => {
|
236
|
+
:http => {
|
237
|
+
:from => 10080,
|
238
|
+
:from_ip => '127.0.0.1',
|
239
|
+
:to => 80,
|
240
|
+
}
|
241
|
+
}
|
242
|
+
},1)
|
243
|
+
vagrant.make_vfile( hosts, options )
|
244
|
+
|
245
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
246
|
+
expect( vagrantfile ).to match(/v.vm.network :forwarded_port, guest: 80, host_ip: '127.0.0.1', host: 10080/)
|
247
|
+
end
|
248
|
+
|
249
|
+
it "supports all to_ip" do
|
250
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
251
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
252
|
+
|
253
|
+
hosts = make_hosts(
|
254
|
+
{
|
255
|
+
:forwarded_ports => {
|
256
|
+
:http => {
|
257
|
+
:from => 10080,
|
258
|
+
:to => 80,
|
259
|
+
:to_ip => '0.0.0.0',
|
260
|
+
}
|
261
|
+
}
|
262
|
+
},1)
|
263
|
+
vagrant.make_vfile( hosts, options )
|
264
|
+
|
265
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
266
|
+
expect( vagrantfile ).to match(/v.vm.network :forwarded_port, guest_ip: '0.0.0.0', guest: 80, host: 10080/)
|
267
|
+
end
|
268
|
+
|
269
|
+
it "supports all protocol" do
|
270
|
+
path = vagrant.instance_variable_get( :@vagrant_path )
|
271
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
272
|
+
|
273
|
+
hosts = make_hosts(
|
274
|
+
{
|
275
|
+
:forwarded_ports => {
|
276
|
+
:http => {
|
277
|
+
:from => 10080,
|
278
|
+
:to => 80,
|
279
|
+
:protocol => 'udp'
|
280
|
+
}
|
281
|
+
}
|
282
|
+
},1)
|
283
|
+
vagrant.make_vfile( hosts, options )
|
284
|
+
|
285
|
+
vagrantfile = File.read( File.expand_path( File.join( path, "Vagrantfile")))
|
286
|
+
expect( vagrantfile ).to match(/v.vm.network :forwarded_port, protocol: 'udp', guest: 80, host: 10080/)
|
287
|
+
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
it "can generate a new /etc/hosts file referencing each host" do
|
292
|
+
|
293
|
+
@hosts.each do |host|
|
294
|
+
expect( vagrant ).to receive( :get_domain_name ).with( host ).and_return( 'labs.lan' )
|
295
|
+
expect( vagrant ).to receive( :set_etc_hosts ).with( host, "127.0.0.1\tlocalhost localhost.localdomain\nip.address.for.vm1\tvm1.labs.lan vm1\nip.address.for.vm2\tvm2.labs.lan vm2\nip.address.for.vm3\tvm3.labs.lan vm3\n" ).once
|
296
|
+
end
|
297
|
+
|
298
|
+
vagrant.hack_etc_hosts( @hosts, options )
|
299
|
+
|
300
|
+
end
|
301
|
+
|
302
|
+
context "can copy vagrant's key to root .ssh on each host" do
|
303
|
+
|
304
|
+
it "can copy to root on unix" do
|
305
|
+
host = @hosts[0]
|
306
|
+
host[:platform] = 'unix'
|
307
|
+
|
308
|
+
expect( Command ).to receive( :new ).with("sudo su -c \"cp -r .ssh /root/.\"").once
|
309
|
+
expect( Command ).to receive( :new ).with("sudo fixfiles restore /root").once
|
310
|
+
expect( Command ).to receive( :new ).with("sudo selinuxenabled").once
|
311
|
+
|
312
|
+
vagrant.copy_ssh_to_root( host, options )
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
it "can copy to Administrator on windows" do
|
317
|
+
host = @hosts[0]
|
318
|
+
host[:platform] = 'windows'
|
319
|
+
expect( host ).to receive( :is_cygwin? ).and_return(true)
|
320
|
+
|
321
|
+
expect( Command ).to_not receive( :new ).with("sudo fixfiles restore /root")
|
322
|
+
expect( Command ).to receive( :new ).with("cp -r .ssh /cygdrive/c/Users/Administrator/.").once
|
323
|
+
expect( Command ).to receive( :new ).with("chown -R Administrator /cygdrive/c/Users/Administrator/.ssh").once
|
324
|
+
|
325
|
+
# This is checked on all platforms since Linux isn't called out specifically in the code
|
326
|
+
# If this fails, nothing further is activated
|
327
|
+
result = Beaker::Result.new(host, '')
|
328
|
+
result.exit_code = 1
|
329
|
+
expect( Command ).to receive( :new ).with("sudo selinuxenabled")
|
330
|
+
allow( host ).to receive(:exec).and_return(result)
|
331
|
+
|
332
|
+
vagrant.copy_ssh_to_root( host, options )
|
333
|
+
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
it "can generate a ssh-config file" do
|
338
|
+
host = @hosts[0]
|
339
|
+
name = host.name
|
340
|
+
allow( Dir ).to receive( :chdir ).and_yield()
|
341
|
+
out = double( 'stdout' )
|
342
|
+
allow( out ).to receive( :read ).and_return("Host #{name}
|
343
|
+
HostName 127.0.0.1
|
344
|
+
User vagrant
|
345
|
+
Port 2222
|
346
|
+
UserKnownHostsFile /dev/null
|
347
|
+
StrictHostKeyChecking no
|
348
|
+
PasswordAuthentication no
|
349
|
+
IdentityFile /home/root/.vagrant.d/insecure_private_key
|
350
|
+
IdentitiesOnly yes")
|
351
|
+
|
352
|
+
wait_thr = OpenStruct.new
|
353
|
+
state = double( 'state' )
|
354
|
+
allow( state ).to receive( :success? ).and_return( true )
|
355
|
+
wait_thr.value = state
|
356
|
+
|
357
|
+
allow( Open3 ).to receive( :popen3 ).with( {"RUBYLIB"=>""}, 'vagrant', 'ssh-config', name ).and_return( [ "", out, "", wait_thr ])
|
358
|
+
|
359
|
+
file = double( 'file' )
|
360
|
+
allow( file ).to receive( :path ).and_return( '/path/sshconfig' )
|
361
|
+
allow( file ).to receive( :rewind ).and_return( true )
|
362
|
+
|
363
|
+
expect( Tempfile ).to receive( :new ).with( "#{host.name}").and_return( file )
|
364
|
+
expect( file ).to receive( :write ).with("Host ip.address.for.#{name}\n HostName 127.0.0.1\n User root\n Port 2222\n UserKnownHostsFile /dev/null\n StrictHostKeyChecking no\n PasswordAuthentication no\n IdentityFile /home/root/.vagrant.d/insecure_private_key\n IdentitiesOnly yes")
|
365
|
+
|
366
|
+
vagrant.set_ssh_config( host, 'root' )
|
367
|
+
expect( host['ssh'] ).to be === { :config => file.path }
|
368
|
+
expect( host['user']).to be === 'root'
|
369
|
+
|
370
|
+
end
|
371
|
+
|
372
|
+
describe "get_ip_from_vagrant_file" do
|
373
|
+
before :each do
|
374
|
+
allow( vagrant ).to receive( :randmac ).and_return( "0123456789" )
|
375
|
+
vagrant.make_vfile( @hosts )
|
376
|
+
end
|
377
|
+
|
378
|
+
it "can find the correct ip for the provided hostname" do
|
379
|
+
@hosts.each do |host|
|
380
|
+
expect( vagrant.get_ip_from_vagrant_file(host.name) ).to be === host[:ip]
|
381
|
+
end
|
382
|
+
|
383
|
+
end
|
384
|
+
|
385
|
+
it "returns nil if it is unable to find an ip" do
|
386
|
+
expect( vagrant.get_ip_from_vagrant_file("unknown") ).to be_nil
|
387
|
+
end
|
388
|
+
|
389
|
+
it "raises an error if no Vagrantfile is present" do
|
390
|
+
File.delete( vagrant.instance_variable_get( :@vagrant_file ) )
|
391
|
+
@hosts.each do |host|
|
392
|
+
expect{ vagrant.get_ip_from_vagrant_file(host.name) }.to raise_error RuntimeError, /No vagrant file found/
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
describe "provisioning and cleanup" do
|
398
|
+
|
399
|
+
before :each do
|
400
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "up" ).once
|
401
|
+
@hosts.each do |host|
|
402
|
+
host_prev_name = host['user']
|
403
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, 'vagrant' ).once
|
404
|
+
expect( vagrant ).to receive( :copy_ssh_to_root ).with( host, options ).once
|
405
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, host_prev_name ).once
|
406
|
+
end
|
407
|
+
expect( vagrant ).to receive( :hack_etc_hosts ).with( @hosts, options ).once
|
408
|
+
end
|
409
|
+
|
410
|
+
it "can provision a set of hosts" do
|
411
|
+
options = vagrant.instance_variable_get( :@options )
|
412
|
+
expect( vagrant ).to receive( :make_vfile ).with( @hosts, options ).once
|
413
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "destroy --force" ).never
|
414
|
+
vagrant.provision
|
415
|
+
end
|
416
|
+
|
417
|
+
it "destroys an existing set of hosts before provisioning" do
|
418
|
+
vagrant.make_vfile( @hosts )
|
419
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "destroy --force" ).once
|
420
|
+
vagrant.provision
|
421
|
+
end
|
422
|
+
|
423
|
+
it "notifies user of failed provision" do
|
424
|
+
vagrant.provision
|
425
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "destroy --force" ).and_raise( RuntimeError )
|
426
|
+
expect( options['logger'] ).to receive( :debug ).with( /Vagrantfile/ )
|
427
|
+
expect{ vagrant.provision }.to raise_error( RuntimeError )
|
428
|
+
end
|
429
|
+
|
430
|
+
it "can cleanup" do
|
431
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "destroy --force" ).once
|
432
|
+
expect( FileUtils ).to receive( :rm_rf ).once
|
433
|
+
|
434
|
+
vagrant.provision
|
435
|
+
vagrant.cleanup
|
436
|
+
|
437
|
+
end
|
438
|
+
|
439
|
+
end
|
440
|
+
|
441
|
+
describe "provisioning and cleanup on windows" do
|
442
|
+
before :each do
|
443
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "up" ).once
|
444
|
+
@hosts.each do |host|
|
445
|
+
host_prev_name = host['user']
|
446
|
+
expect( vagrant ).to receive( :set_ssh_config ).with( host, 'vagrant' ).once
|
447
|
+
expect( vagrant ).not_to receive( :copy_ssh_to_root ).with( host, options ).once
|
448
|
+
expect( vagrant ).not_to receive( :set_ssh_config ).with( host, host_prev_name ).once
|
449
|
+
end
|
450
|
+
expect( vagrant ).to receive( :hack_etc_hosts ).with( @hosts, options ).once
|
451
|
+
end
|
452
|
+
|
453
|
+
it "can provision a set of hosts" do
|
454
|
+
options = vagrant.instance_variable_get( :@options )
|
455
|
+
expect( vagrant ).to receive( :make_vfile ).with( @hosts, options ).once
|
456
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "destroy --force" ).never
|
457
|
+
vagrant.provision
|
458
|
+
end
|
459
|
+
|
460
|
+
it "destroys an existing set of hosts before provisioning" do
|
461
|
+
vagrant.make_vfile( @hosts )
|
462
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "destroy --force" ).once
|
463
|
+
vagrant.provision
|
464
|
+
end
|
465
|
+
|
466
|
+
it "can cleanup" do
|
467
|
+
expect( vagrant ).to receive( :vagrant_cmd ).with( "destroy --force" ).once
|
468
|
+
expect( FileUtils ).to receive( :rm_rf ).once
|
469
|
+
|
470
|
+
vagrant.provision
|
471
|
+
vagrant.cleanup
|
472
|
+
|
473
|
+
end
|
474
|
+
|
475
|
+
end
|
476
|
+
|
477
|
+
end
|
478
|
+
|
479
|
+
end
|