beaker-vagrant 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ require 'beaker/hypervisor/vagrant'
2
+
3
+ class Beaker::VagrantCustom < Beaker::Vagrant
4
+ def provision(provider = nil)
5
+ super
6
+ end
7
+
8
+ def make_vfile hosts, options = {}
9
+ FileUtils.cp(@options[:vagrantfile_path], @vagrant_file)
10
+ end
11
+ end
@@ -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