controlrepo 2.0.1 → 2.0.2
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 +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +40 -0
- data/controlrepo.gemspec +2 -1
- data/factsets/CentOS-6.6-64.json +342 -0
- data/factsets/CentOS-7.0-64.json +352 -0
- data/factsets/Debian-7.8-64.json +338 -0
- data/factsets/Ubuntu-12.04-32.json +328 -0
- data/factsets/Ubuntu-14.04-64.json +373 -0
- data/factsets/Windows_Server-2008r2-64.json +183 -0
- data/factsets/Windows_Server-2012r2-64.json +164 -0
- data/lib/controlrepo.rb +17 -2
- data/lib/controlrepo/beaker.rb +5 -5
- data/lib/controlrepo/rake_tasks.rb +28 -27
- data/lib/controlrepo/testconfig.rb +23 -15
- data/templates/acceptance_test_spec.rb.erb +1 -1
- data/templates/controlrepo.yaml.erb +38 -0
- data/templates/nodeset.yaml.erb +9 -9
- metadata +24 -2
@@ -0,0 +1,164 @@
|
|
1
|
+
{
|
2
|
+
"name": "win-e5k8tm30719",
|
3
|
+
"values": {
|
4
|
+
"agent_specified_environment": "production",
|
5
|
+
"architecture": "x64",
|
6
|
+
"dhcp_servers": {
|
7
|
+
"Ethernet": "10.0.2.2",
|
8
|
+
"system": "10.0.2.2"
|
9
|
+
},
|
10
|
+
"dmi": {
|
11
|
+
"manufacturer": "innotek GmbH",
|
12
|
+
"product": {
|
13
|
+
"name": "VirtualBox",
|
14
|
+
"serial_number": "0"
|
15
|
+
}
|
16
|
+
},
|
17
|
+
"env_windows_installdir": "C:\\Program Files\\Puppet Labs\\Puppet",
|
18
|
+
"facterversion": "3.1.1",
|
19
|
+
"fqdn": "WIN-E5K8TM30719",
|
20
|
+
"hardwareisa": "x64",
|
21
|
+
"hardwaremodel": "x86_64",
|
22
|
+
"hostname": "WIN-E5K8TM30719",
|
23
|
+
"id": "WIN-E5K8TM30719\\vagrant",
|
24
|
+
"identity": {
|
25
|
+
"user": "WIN-E5K8TM30719\\vagrant"
|
26
|
+
},
|
27
|
+
"interfaces": "Ethernet",
|
28
|
+
"ipaddress": "10.0.2.15",
|
29
|
+
"ipaddress6": "fe80::a180:36e0:3a6e:1005%12",
|
30
|
+
"ipaddress6_Ethernet": "fe80::a180:36e0:3a6e:1005%12",
|
31
|
+
"ipaddress_Ethernet": "10.0.2.15",
|
32
|
+
"is_virtual": true,
|
33
|
+
"kernel": "windows",
|
34
|
+
"kernelmajversion": "6.3",
|
35
|
+
"kernelrelease": "6.3.9600",
|
36
|
+
"kernelversion": "6.3.9600",
|
37
|
+
"macaddress": "08:00:27:81:38:FA",
|
38
|
+
"macaddress_Ethernet": "08:00:27:81:38:FA",
|
39
|
+
"manufacturer": "innotek GmbH",
|
40
|
+
"memory": {
|
41
|
+
"system": {
|
42
|
+
"available": "1.42 GiB",
|
43
|
+
"available_bytes": 1521610752,
|
44
|
+
"capacity": "29.13%",
|
45
|
+
"total": "2.00 GiB",
|
46
|
+
"total_bytes": 2147012608,
|
47
|
+
"used": "596.43 MiB",
|
48
|
+
"used_bytes": 625401856
|
49
|
+
}
|
50
|
+
},
|
51
|
+
"memoryfree": "1.42 GiB",
|
52
|
+
"memoryfree_mb": 1451.12109375,
|
53
|
+
"memorysize": "2.00 GiB",
|
54
|
+
"memorysize_mb": 2047.55078125,
|
55
|
+
"mtu_Ethernet": 1500,
|
56
|
+
"netmask": "255.255.255.0",
|
57
|
+
"netmask6": "ffff:ffff:ffff:ffff::",
|
58
|
+
"netmask6_Ethernet": "ffff:ffff:ffff:ffff::",
|
59
|
+
"netmask_Ethernet": "255.255.255.0",
|
60
|
+
"network": "10.0.2.0",
|
61
|
+
"network6": "fe80::%12",
|
62
|
+
"network6_Ethernet": "fe80::%12",
|
63
|
+
"network_Ethernet": "10.0.2.0",
|
64
|
+
"networking": {
|
65
|
+
"dhcp": "10.0.2.2",
|
66
|
+
"fqdn": "WIN-E5K8TM30719",
|
67
|
+
"hostname": "WIN-E5K8TM30719",
|
68
|
+
"interfaces": {
|
69
|
+
"Ethernet": {
|
70
|
+
"bindings": [
|
71
|
+
{
|
72
|
+
"address": "10.0.2.15",
|
73
|
+
"netmask": "255.255.255.0",
|
74
|
+
"network": "10.0.2.0"
|
75
|
+
}
|
76
|
+
],
|
77
|
+
"bindings6": [
|
78
|
+
{
|
79
|
+
"address": "fe80::a180:36e0:3a6e:1005%12",
|
80
|
+
"netmask": "ffff:ffff:ffff:ffff::",
|
81
|
+
"network": "fe80::%12"
|
82
|
+
}
|
83
|
+
],
|
84
|
+
"dhcp": "10.0.2.2",
|
85
|
+
"ip": "10.0.2.15",
|
86
|
+
"ip6": "fe80::a180:36e0:3a6e:1005%12",
|
87
|
+
"mac": "08:00:27:81:38:FA",
|
88
|
+
"mtu": 1500,
|
89
|
+
"netmask": "255.255.255.0",
|
90
|
+
"netmask6": "ffff:ffff:ffff:ffff::",
|
91
|
+
"network": "10.0.2.0",
|
92
|
+
"network6": "fe80::%12"
|
93
|
+
}
|
94
|
+
},
|
95
|
+
"ip": "10.0.2.15",
|
96
|
+
"ip6": "fe80::a180:36e0:3a6e:1005%12",
|
97
|
+
"mac": "08:00:27:81:38:FA",
|
98
|
+
"mtu": 1500,
|
99
|
+
"netmask": "255.255.255.0",
|
100
|
+
"netmask6": "ffff:ffff:ffff:ffff::",
|
101
|
+
"network": "10.0.2.0",
|
102
|
+
"network6": "fe80::%12",
|
103
|
+
"primary": "Ethernet"
|
104
|
+
},
|
105
|
+
"operatingsystem": "windows",
|
106
|
+
"operatingsystemmajrelease": "2012 R2",
|
107
|
+
"operatingsystemrelease": "2012 R2",
|
108
|
+
"os": {
|
109
|
+
"architecture": "x64",
|
110
|
+
"family": "windows",
|
111
|
+
"hardware": "x86_64",
|
112
|
+
"name": "windows",
|
113
|
+
"release": {
|
114
|
+
"full": "2012 R2",
|
115
|
+
"major": "2012 R2"
|
116
|
+
},
|
117
|
+
"windows": {
|
118
|
+
"system32": "C:\\Windows\\system32"
|
119
|
+
}
|
120
|
+
},
|
121
|
+
"osfamily": "windows",
|
122
|
+
"path": "C:/Program Files/Puppet Labs/Puppet/facter/bin;C:\\Program Files\\Puppet Labs\\Puppet\\puppet\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\facter\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\hiera\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\mcollective\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\sys\\ruby\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\sys\\tools\\bin;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Git\\cmd;C:\\Program Files (x86)\\Git\\bin;C:\\Program Files\\Puppet Labs\\Puppet\\bin",
|
123
|
+
"physicalprocessorcount": 1,
|
124
|
+
"processor0": "Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz",
|
125
|
+
"processorcount": 1,
|
126
|
+
"processors": {
|
127
|
+
"count": 1,
|
128
|
+
"isa": "x64",
|
129
|
+
"models": [
|
130
|
+
"Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz"
|
131
|
+
],
|
132
|
+
"physicalcount": 1
|
133
|
+
},
|
134
|
+
"productname": "VirtualBox",
|
135
|
+
"puppetversion": "4.2.3",
|
136
|
+
"ruby": {
|
137
|
+
"platform": "x64-mingw32",
|
138
|
+
"sitedir": "C:/Program Files/Puppet Labs/Puppet/sys/ruby/lib/ruby/site_ruby/2.1.0",
|
139
|
+
"version": "2.1.7"
|
140
|
+
},
|
141
|
+
"rubyplatform": "x64-mingw32",
|
142
|
+
"rubysitedir": "C:/Program Files/Puppet Labs/Puppet/sys/ruby/lib/ruby/site_ruby/2.1.0",
|
143
|
+
"rubyversion": "2.1.7",
|
144
|
+
"serialnumber": "0",
|
145
|
+
"system32": "C:\\Windows\\system32",
|
146
|
+
"system_uptime": {
|
147
|
+
"days": 0,
|
148
|
+
"hours": 0,
|
149
|
+
"seconds": 287,
|
150
|
+
"uptime": "0:04 hours"
|
151
|
+
},
|
152
|
+
"timezone": "Coordinated Universal Time",
|
153
|
+
"uptime": "0:04 hours",
|
154
|
+
"uptime_days": 0,
|
155
|
+
"uptime_hours": 0,
|
156
|
+
"uptime_seconds": 287,
|
157
|
+
"virtual": "virtualbox",
|
158
|
+
"clientcert": "win-e5k8tm30719",
|
159
|
+
"clientversion": "4.2.3",
|
160
|
+
"clientnoop": false
|
161
|
+
},
|
162
|
+
"timestamp": "2015-11-19T01:47:05.215450000+00:00",
|
163
|
+
"expiration": "2015-11-19T02:17:05.215450000+00:00"
|
164
|
+
}
|
data/lib/controlrepo.rb
CHANGED
@@ -90,7 +90,7 @@ class Controlrepo
|
|
90
90
|
@environment_conf = File.expand_path('./environment.conf',@root)
|
91
91
|
@facts_dir = File.expand_path('./spec/factsets',@root)
|
92
92
|
@spec_dir = File.expand_path('./spec',@root)
|
93
|
-
@facts_files = Dir["#{@facts_dir}/*.json"]
|
93
|
+
@facts_files = [Dir["#{@facts_dir}/*.json"],Dir["#{File.expand_path('../../factsets',__FILE__)}/*.json"]].flatten
|
94
94
|
@nodeset_file = File.expand_path('./spec/acceptance/nodesets/controlrepo-nodes.yml',@root)
|
95
95
|
@role_regex = /role[s]?:{2}/
|
96
96
|
@profile_regex = /profile[s]?:{2}/
|
@@ -99,6 +99,17 @@ class Controlrepo
|
|
99
99
|
$temp_modulepath = nil
|
100
100
|
end
|
101
101
|
|
102
|
+
def to_s
|
103
|
+
<<-END.gsub(/^\s{4}/,'')
|
104
|
+
puppetfile: #{@puppetfile}
|
105
|
+
environment_conf: #{@environment_conf}
|
106
|
+
facts_dir: #{@facts_dir}
|
107
|
+
spec_dir: #{@spec_dir}
|
108
|
+
facts_files: #{@facts_files}
|
109
|
+
nodeset_file: #{@nodeset_file}
|
110
|
+
END
|
111
|
+
end
|
112
|
+
|
102
113
|
def roles
|
103
114
|
classes.keep_if { |c| c =~ @role_regex }
|
104
115
|
end
|
@@ -214,7 +225,11 @@ class Controlrepo
|
|
214
225
|
end
|
215
226
|
|
216
227
|
def hiera_config
|
217
|
-
|
228
|
+
begin
|
229
|
+
YAML.load_file(hiera_config_file)
|
230
|
+
rescue TypeError
|
231
|
+
raise "Could not load hiera config file: #{hiera_config_file}"
|
232
|
+
end
|
218
233
|
end
|
219
234
|
|
220
235
|
def hiera_config=(data)
|
data/lib/controlrepo/beaker.rb
CHANGED
@@ -24,7 +24,7 @@ class Controlrepo
|
|
24
24
|
begin
|
25
25
|
if facts['os']['distro']['id'] == 'Debian'
|
26
26
|
os = 'Debian'
|
27
|
-
version = facts['os']['distro']['release']['major']
|
27
|
+
version = "#{facts['os']['distro']['release']['major']}.#{facts['os']['distro']['release']['minor']}"
|
28
28
|
end
|
29
29
|
rescue
|
30
30
|
# Do nothing
|
@@ -69,7 +69,7 @@ class Controlrepo
|
|
69
69
|
version = facts['os']['release']['major']
|
70
70
|
end
|
71
71
|
rescue
|
72
|
-
# Do nothing, this is the easiest way to handle the hash
|
72
|
+
# Do nothing, this is the easiest way to handle the hash being in different formats
|
73
73
|
end
|
74
74
|
|
75
75
|
begin
|
@@ -78,13 +78,13 @@ class Controlrepo
|
|
78
78
|
version = facts['os']['distro']['release']['major']
|
79
79
|
end
|
80
80
|
rescue
|
81
|
-
# Do nothing, this is the easiest way to handle the hash
|
81
|
+
# Do nothing, this is the easiest way to handle the hash being in different formats
|
82
82
|
end
|
83
83
|
|
84
84
|
begin
|
85
85
|
if facts['os']['distro']['id'] == 'Debian'
|
86
|
-
platform = '
|
87
|
-
version = facts['os']['distro']['release']['
|
86
|
+
platform = 'debian'
|
87
|
+
version = facts['os']['distro']['release']['full']
|
88
88
|
end
|
89
89
|
rescue
|
90
90
|
# Do nothing
|
@@ -24,6 +24,20 @@ task :hiera_setup do
|
|
24
24
|
repo.hiera_config = current_config
|
25
25
|
end
|
26
26
|
|
27
|
+
task :controlrepo_details do
|
28
|
+
require 'controlrepo'
|
29
|
+
puts Controlrepo.new.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
task :generate_controlrepo_yaml do
|
33
|
+
require 'controlrepo'
|
34
|
+
repo = Controlrepo.new
|
35
|
+
template_dir = File.expand_path('../../templates',File.dirname(__FILE__))
|
36
|
+
controlrepo_yaml_template = File.read(File.expand_path('./controlrepo.yaml.erb',template_dir))
|
37
|
+
puts ERB.new(controlrepo_yaml_template, nil, '-').result(binding)
|
38
|
+
end
|
39
|
+
|
40
|
+
|
27
41
|
task :generate_nodesets do
|
28
42
|
require 'controlrepo/beaker'
|
29
43
|
require 'net/http'
|
@@ -31,47 +45,33 @@ task :generate_nodesets do
|
|
31
45
|
|
32
46
|
repo = Controlrepo.new
|
33
47
|
|
34
|
-
|
35
|
-
Dir.mkdir("#{repo.root}/spec/acceptance")
|
36
|
-
puts "Created #{repo.root}/spec/acceptance"
|
37
|
-
rescue Errno::EEXIST
|
38
|
-
# Do nothing, this is okay
|
39
|
-
end
|
48
|
+
puts "HOSTS:"
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
# Do nothing, this is okay
|
46
|
-
end
|
47
|
-
|
48
|
-
facts = repo.facts
|
49
|
-
facts.each do |fact_set|
|
50
|
-
boxname = Controlrepo_beaker.facts_to_vagrant_box(fact_set)
|
51
|
-
platform = Controlrepo_beaker.facts_to_platform(fact_set)
|
50
|
+
repo.facts.each do |fact_set|
|
51
|
+
node_name = File.basename(repo.facts_files[repo.facts.index(fact_set)],'.json')
|
52
|
+
boxname = Controlrepo::Beaker.facts_to_vagrant_box(fact_set)
|
53
|
+
platform = Controlrepo::Beaker.facts_to_platform(fact_set)
|
52
54
|
response = Net::HTTP.get(URI.parse("https://atlas.hashicorp.com/api/v1/box/#{boxname}"))
|
53
55
|
url = 'URL goes here'
|
54
56
|
|
55
|
-
|
57
|
+
if response =~ /Not Found/i
|
58
|
+
comment_out = true
|
59
|
+
else
|
60
|
+
comment_out = false
|
56
61
|
box_info = JSON.parse(response)
|
57
62
|
box_info['current_version']['providers'].each do |provider|
|
58
|
-
if
|
63
|
+
if provider['name'] == 'virtualbox'
|
59
64
|
url = provider['original_url']
|
60
65
|
end
|
61
66
|
end
|
62
67
|
end
|
63
68
|
|
64
|
-
# Use an ERB template
|
69
|
+
# Use an ERB template
|
65
70
|
template_dir = File.expand_path('../../templates',File.dirname(__FILE__))
|
66
71
|
fixtures_template = File.read(File.expand_path('./nodeset.yaml.erb',template_dir))
|
67
|
-
|
68
|
-
if File.exists?(output_file) == false
|
69
|
-
File.write(output_file,ERB.new(fixtures_template, nil, '-').result(binding))
|
70
|
-
puts "Created #{output_file}"
|
71
|
-
else
|
72
|
-
puts "#{output_file} already exists, not going to overwrite because scared"
|
73
|
-
end
|
72
|
+
puts ERB.new(fixtures_template, nil, '-').result(binding)
|
74
73
|
end
|
74
|
+
|
75
75
|
end
|
76
76
|
|
77
77
|
task :controlrepo_autotest_prep do
|
@@ -121,6 +121,7 @@ task :controlrepo_autotest_prep do
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
end
|
124
|
+
binding.pry
|
124
125
|
File.write("#{@repo.temp_environmentpath}/#{@config.environment}/hiera.yaml",hiera_config.to_yaml)
|
125
126
|
|
126
127
|
@config.create_fixtures_symlinks(@repo)
|
@@ -2,6 +2,7 @@ require 'controlrepo/class'
|
|
2
2
|
require 'controlrepo/node'
|
3
3
|
require 'controlrepo/group'
|
4
4
|
require 'controlrepo/test'
|
5
|
+
require 'git'
|
5
6
|
|
6
7
|
class Controlrepo
|
7
8
|
class TestConfig
|
@@ -99,26 +100,33 @@ class Controlrepo
|
|
99
100
|
puppetcode.join("\n")
|
100
101
|
end
|
101
102
|
|
103
|
+
def checkout_branch(working_dir, branch)
|
104
|
+
Dir.chdir(working_dir)
|
105
|
+
g = Git.open(working_dir)
|
106
|
+
|
107
|
+
# if we are already on the right branch do nothing
|
108
|
+
if ! g.branch.current == @environment then
|
109
|
+
if g.branches.include? branch
|
110
|
+
g.branch(@environment).checkout
|
111
|
+
else
|
112
|
+
puts "Unable to checkout requested environment #{@environment}: branch not found"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
102
117
|
def r10k_deploy_local(repo = Controlrepo.new)
|
103
118
|
require 'controlrepo'
|
104
119
|
tempdir = Dir.mktmpdir('r10k')
|
105
120
|
repo.tempdir = tempdir
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
r10k_config[:sources].map do |name,source_settings|
|
112
|
-
source_settings["basedir"] = "#{tempdir}#{source_settings["basedir"]}"
|
113
|
-
FileUtils::mkdir_p(source_settings["basedir"])
|
114
|
-
# Yes, I realise this is going to set it many times
|
115
|
-
repo.temp_environmentpath = source_settings["basedir"]
|
116
|
-
end
|
117
|
-
File.write("#{tempdir}/r10k.yaml",r10k_config.to_yaml)
|
121
|
+
temp_code_dir = "#{tempdir}/etc/puppetlabs/code/environments/#{@environment}"
|
122
|
+
repo.temp_environmentpath = temp_code_dir.chomp("/#{@environment}")
|
123
|
+
FileUtils.mkdir_p(temp_code_dir)
|
124
|
+
FileUtils.cp_r("#{Dir.pwd}/.", temp_code_dir)
|
125
|
+
checkout_branch(temp_code_dir, @environment)
|
118
126
|
|
119
127
|
# Pull the trigger!
|
120
|
-
Dir.chdir(
|
121
|
-
|
128
|
+
Dir.chdir(temp_code_dir) do
|
129
|
+
system("r10k puppetfile install --verbose")
|
122
130
|
end
|
123
131
|
|
124
132
|
# Return tempdir for use
|
@@ -190,4 +198,4 @@ class Controlrepo
|
|
190
198
|
# with the output from the templated tests, us ethe better one
|
191
199
|
# bearing in minf that beaker has logger options that could help
|
192
200
|
end
|
193
|
-
end
|
201
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Classes to be tested
|
2
|
+
classes:
|
3
|
+
<% repo.roles.each do |role| -%>
|
4
|
+
- <%= role %>
|
5
|
+
<% end -%>
|
6
|
+
|
7
|
+
# Nodes to tests classes on, this refers to a 'factset' or 'nodeset'
|
8
|
+
# depending on weather you are running 'spec' or 'acceptance' tests
|
9
|
+
nodes:
|
10
|
+
<% repo.facts_files.each do |file| -%>
|
11
|
+
- <%= File.basename(file,'.json') %>
|
12
|
+
<% end -%>
|
13
|
+
|
14
|
+
# You can group classes here to save typing
|
15
|
+
class_groups:
|
16
|
+
|
17
|
+
# You can group nodes here to save typing
|
18
|
+
# We have created a 'non_windows_nodes' group because we can't
|
19
|
+
# give you Windows vagrant boxes to test with because licensing,
|
20
|
+
# we can give you fact sets though so go crazy with spec testing!
|
21
|
+
node_groups:
|
22
|
+
windows_nodes:
|
23
|
+
<% repo.facts_files.each do |file| -%>
|
24
|
+
<% if File.basename(file,'.json') =~ /Windows/i -%>
|
25
|
+
- <%= File.basename(file,'.json') %>
|
26
|
+
<% end -%>
|
27
|
+
<% end -%>
|
28
|
+
non_windows_nodes:
|
29
|
+
include: 'all_nodes'
|
30
|
+
exclude: 'windows_nodes'
|
31
|
+
|
32
|
+
test_matrix:
|
33
|
+
- all_nodes:
|
34
|
+
classes: 'all_classes'
|
35
|
+
tests: 'spec'
|
36
|
+
- non_windows_nodes:
|
37
|
+
classes: 'all_classes'
|
38
|
+
tests: 'acceptance'
|
data/templates/nodeset.yaml.erb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
|
2
|
-
<%=
|
3
|
-
roles:
|
4
|
-
- agent
|
5
|
-
type: aio
|
6
|
-
platform: <%= platform %>
|
7
|
-
box: <%= boxname %>
|
8
|
-
box_url: <%= url %>
|
9
|
-
hypervisor: vagrant_virtualbox
|
1
|
+
<% if comment_out then prefix = '#' end-%>
|
2
|
+
<%= prefix %> <%= node_name %>:
|
3
|
+
<%= prefix %> roles:
|
4
|
+
<%= prefix %> - agent
|
5
|
+
<%= prefix %> type: aio
|
6
|
+
<%= prefix %> platform: <%= platform %>
|
7
|
+
<%= prefix %> box: <%= boxname %>
|
8
|
+
<%= prefix %> box_url: <%= url %>
|
9
|
+
<%= prefix %> hypervisor: vagrant_virtualbox
|