boxes 2.0.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 +7 -0
- data/.gitignore +13 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +3 -0
- data/LICENSE +22 -0
- data/README.md +51 -0
- data/Rakefile +34 -0
- data/bin/boxes +6 -0
- data/boxes.gemspec +39 -0
- data/features/boxes.feature +8 -0
- data/features/build.feature +16 -0
- data/features/env.feature +18 -0
- data/features/support/env.rb +1 -0
- data/lib/boxes.rb +28 -0
- data/lib/boxes/builder.rb +77 -0
- data/lib/boxes/command.rb +12 -0
- data/lib/boxes/command/build.rb +45 -0
- data/lib/boxes/command/env.rb +50 -0
- data/lib/boxes/config.rb +73 -0
- data/lib/boxes/environment.rb +74 -0
- data/lib/boxes/errors.rb +19 -0
- data/lib/boxes/subprocess.rb +39 -0
- data/lib/boxes/template.rb +50 -0
- data/lib/boxes/version.rb +4 -0
- data/scripts/ansible.sh +13 -0
- data/scripts/chef.sh +28 -0
- data/scripts/postinstall.sh +42 -0
- data/scripts/puppet.sh +14 -0
- data/scripts/purge.sh +60 -0
- data/scripts/ruby.sh +41 -0
- data/scripts/vmtools.sh +32 -0
- data/spec/boxes/builder_spec.rb +52 -0
- data/spec/boxes/config_spec.rb +142 -0
- data/spec/boxes/environment_spec.rb +73 -0
- data/spec/boxes/subprocess_spec.rb +35 -0
- data/spec/boxes/template_spec.rb +53 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/subprocess_command.rb +7 -0
- data/templates/debian/preseed.cfg +69 -0
- data/templates/debian/wheezy64.erb +59 -0
- data/templates/ubuntu/precise64.erb +59 -0
- data/templates/ubuntu/preseed.cfg +61 -0
- data/templates/ubuntu/trusty64.erb +59 -0
- metadata +230 -0
data/scripts/vmtools.sh
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
##
|
4
|
+
# Configure the relevant VM tools for this builder.
|
5
|
+
##
|
6
|
+
|
7
|
+
case $PACKER_BUILDER_TYPE in
|
8
|
+
'virtualbox-iso')
|
9
|
+
echo "Installing VirtualBox Guest Additions..."
|
10
|
+
apt-get -qy install dkms
|
11
|
+
mount -o loop /home/vagrant/VBoxGuestAdditions.iso /mnt
|
12
|
+
sh /mnt/VBoxLinuxAdditions.run
|
13
|
+
umount /mnt
|
14
|
+
|
15
|
+
rm -f /home/vagrant/VBoxGuestAdditions.iso
|
16
|
+
;;
|
17
|
+
'vmware-iso')
|
18
|
+
echo "Installing VMware Tools..."
|
19
|
+
mkdir -p /mnt/cdrom
|
20
|
+
mount -o loop /home/vagrant/linux.iso /mnt/cdrom
|
21
|
+
|
22
|
+
cd /tmp
|
23
|
+
tar -zxpf /mnt/cdrom/VMwareTools-*.tar.gz -C /tmp/
|
24
|
+
/tmp/vmware-tools-distrib/vmware-install.pl -d
|
25
|
+
|
26
|
+
umount /mnt/cdrom
|
27
|
+
rm -f /home/vagrant/linux.iso
|
28
|
+
;;
|
29
|
+
*)
|
30
|
+
printf "Nothing to do for the %s builder type.\n" $PACKER_BUILDER_TYPE
|
31
|
+
;;
|
32
|
+
esac
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxes::Builder do
|
4
|
+
let(:env) { Boxes::Environment.new }
|
5
|
+
|
6
|
+
describe '#initialize' do
|
7
|
+
it 'unpacks the arguments for the build' do
|
8
|
+
build = Boxes::Builder.new(env, name: 'build-name',
|
9
|
+
provider: 'vmware',
|
10
|
+
template: 'ubuntu/trusty64',
|
11
|
+
scripts: ['ruby.sh'])
|
12
|
+
|
13
|
+
expect(build.template.name).to eq 'ubuntu/trusty64'
|
14
|
+
expect(build.scripts).to include('ruby.sh')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'requires a name' do
|
18
|
+
expect do
|
19
|
+
Boxes::Builder.new(env, provider: 'vmware', template: 'ubuntu/trusty64')
|
20
|
+
end.to raise_error(Boxes::Errors::MissingArgumentError)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'requires a provider' do
|
24
|
+
expect do
|
25
|
+
Boxes::Builder.new(env, name: 'build-name', template: 'ubuntu/trusty64')
|
26
|
+
end.to raise_error(Boxes::Errors::MissingArgumentError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'requires a template' do
|
30
|
+
expect do
|
31
|
+
Boxes::Builder.new(env, name: 'build-name', provider: 'vmware')
|
32
|
+
end.to raise_error(Boxes::Errors::MissingArgumentError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'throws an exception on unknown templates' do
|
36
|
+
expect do
|
37
|
+
Boxes::Builder.new(env, name: 'build-name',
|
38
|
+
provider: 'vmware',
|
39
|
+
template: 'nope/nope')
|
40
|
+
end.to raise_error(Boxes::Errors::TemplateNotFoundError)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'throws an exception on unknown scripts' do
|
44
|
+
expect do
|
45
|
+
Boxes::Builder.new(env, name: 'build-name',
|
46
|
+
provider: 'vmware',
|
47
|
+
template: 'ubuntu/trusty64',
|
48
|
+
scripts: ['nope.sh'])
|
49
|
+
end.to raise_error(Boxes::Errors::ScriptNotFoundError)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxes::Config do
|
4
|
+
let(:config) { Boxes::Config.new }
|
5
|
+
|
6
|
+
context 'with no ENV modification' do
|
7
|
+
it 'tries to load a user config file if one exists' do
|
8
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
9
|
+
allow(YAML).to receive(:load_file).and_return({})
|
10
|
+
|
11
|
+
config
|
12
|
+
|
13
|
+
config_path = Pathname.new('~/.boxes/config.yml').expand_path
|
14
|
+
expect(YAML).to have_received(:load_file).with(config_path)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'has a set of default config values' do
|
18
|
+
expect(described_class::DEFAULTS).to be_a(Hash)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has a home directory' do
|
22
|
+
expect(config.home_dir).to eq Pathname.new('~/.boxes').expand_path
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'has a working directory' do
|
26
|
+
expect(config.working_dir).to eq Pathname.new('~/.boxes/tmp').expand_path
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'has an array of template paths' do
|
30
|
+
expect(config.template_paths).to be_a Array
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'supports adding additional template paths' do
|
34
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
35
|
+
allow(YAML).to receive(:load_file).and_return(
|
36
|
+
template_paths: ['~/user_templates'])
|
37
|
+
|
38
|
+
default_templates = Boxes::Config::DEFAULTS[:template_paths]
|
39
|
+
|
40
|
+
expect(config.template_paths).to include('~/user_templates')
|
41
|
+
expect(config.template_paths).to include(default_templates.first)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'does not duplicate template path values' do
|
45
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
46
|
+
|
47
|
+
default_templates = Boxes::Config::DEFAULTS[:template_paths]
|
48
|
+
|
49
|
+
allow(YAML).to receive(:load_file).and_return(
|
50
|
+
template_paths: default_templates)
|
51
|
+
|
52
|
+
expect(config.template_paths).to include(default_templates.first)
|
53
|
+
expect(config.template_paths.count).to eq default_templates.count
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'has an array of script paths' do
|
57
|
+
expect(config.script_paths).to be_a Array
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'supports adding additional script paths' do
|
61
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
62
|
+
allow(YAML).to receive(:load_file).and_return(
|
63
|
+
script_paths: ['~/user_scripts'])
|
64
|
+
|
65
|
+
default_scripts = Boxes::Config::DEFAULTS[:script_paths]
|
66
|
+
|
67
|
+
expect(config.script_paths).to include('~/user_scripts')
|
68
|
+
expect(config.script_paths).to include(default_scripts.first)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'does not duplicate script path values' do
|
72
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
73
|
+
|
74
|
+
default_scripts = Boxes::Config::DEFAULTS[:script_paths]
|
75
|
+
|
76
|
+
allow(YAML).to receive(:load_file).and_return(
|
77
|
+
script_paths: default_scripts)
|
78
|
+
|
79
|
+
expect(config.script_paths).to include(default_scripts.first)
|
80
|
+
expect(config.script_paths.count).to eq default_scripts.count
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'has an array of environment variables' do
|
84
|
+
expect(config.environment_vars).to be_a Array
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'supports adding additional environment variables' do
|
88
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
89
|
+
allow(YAML).to receive(:load_file).and_return(
|
90
|
+
environment_vars: [{ 'CUSTOM_VAR' => 'TRUE' }])
|
91
|
+
|
92
|
+
default_env_vars = Boxes::Config::DEFAULTS[:environment_vars]
|
93
|
+
|
94
|
+
expect(config.environment_vars).to include('CUSTOM_VAR' => 'TRUE')
|
95
|
+
expect(config.environment_vars).to include(default_env_vars.first)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'does not duplicate environment variable values' do
|
99
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
100
|
+
|
101
|
+
default_env_vars = Boxes::Config::DEFAULTS[:environment_vars]
|
102
|
+
|
103
|
+
allow(YAML).to receive(:load_file).and_return(
|
104
|
+
environment_vars: default_env_vars)
|
105
|
+
|
106
|
+
expect(config.environment_vars).to include(default_env_vars.first)
|
107
|
+
expect(config.environment_vars.count).to eq default_env_vars.count
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with ENV modification' do
|
112
|
+
it 'tries to load a different user config file' do
|
113
|
+
allow_any_instance_of(Pathname).to receive(:exist?).and_return(true)
|
114
|
+
allow(YAML).to receive(:load_file).and_return({})
|
115
|
+
|
116
|
+
ENV['BOXES_HOME_DIR'] = '/something'
|
117
|
+
|
118
|
+
config
|
119
|
+
|
120
|
+
config_path = Pathname.new('/something/config.yml').expand_path
|
121
|
+
expect(YAML).to have_received(:load_file).with(config_path)
|
122
|
+
|
123
|
+
ENV.delete 'BOXES_HOME_DIR'
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'can change the home directory' do
|
127
|
+
ENV['BOXES_HOME_DIR'] = '/something'
|
128
|
+
|
129
|
+
expect(config.home_dir).to eq Pathname.new('/something')
|
130
|
+
|
131
|
+
ENV.delete 'BOXES_HOME_DIR'
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'can change the working directory' do
|
135
|
+
ENV['BOXES_WORKING_DIR'] = '/something'
|
136
|
+
|
137
|
+
expect(config.working_dir).to eq Pathname.new('/something')
|
138
|
+
|
139
|
+
ENV.delete 'BOXES_WORKING_DIR'
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxes::Environment do
|
4
|
+
include FakeFS::SpecHelpers
|
5
|
+
|
6
|
+
let(:env) { Boxes::Environment.new }
|
7
|
+
|
8
|
+
before do
|
9
|
+
current_directory = File.expand_path('../../..', __FILE__)
|
10
|
+
|
11
|
+
FileUtils.mkdir_p(current_directory + '/templates')
|
12
|
+
FileUtils.mkdir_p(current_directory + '/templates/ubuntu')
|
13
|
+
FileUtils.touch(current_directory + '/templates/ubuntu/trusty64.erb')
|
14
|
+
FileUtils.touch(current_directory + '/templates/ubuntu/preseed.cfg')
|
15
|
+
|
16
|
+
FileUtils.mkdir_p(current_directory + '/scripts')
|
17
|
+
FileUtils.touch(current_directory + '/scripts/postinstall.sh')
|
18
|
+
FileUtils.touch(current_directory + '/scripts/purge.sh')
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#initialize' do
|
22
|
+
it 'successfully builds up a working tree' do
|
23
|
+
working_dir = Boxes.config.working_dir
|
24
|
+
test_template = working_dir + 'templates/ubuntu/trusty64.erb'
|
25
|
+
test_script = working_dir + 'scripts/postinstall.sh'
|
26
|
+
|
27
|
+
env
|
28
|
+
|
29
|
+
[working_dir,
|
30
|
+
working_dir + 'templates',
|
31
|
+
working_dir + 'scripts'].each do |e|
|
32
|
+
expect(File.directory?(e)).to be_truthy
|
33
|
+
end
|
34
|
+
|
35
|
+
expect(File.exist?(test_template)).to be_truthy
|
36
|
+
expect(File.exist?(test_script)).to be_truthy
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#available_templates' do
|
41
|
+
it 'lists available templates' do
|
42
|
+
expect(env.available_templates).to be_a(Array)
|
43
|
+
expect(env.available_templates).to include('ubuntu/trusty64')
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'doesn\'t include hidden templates' do
|
47
|
+
expect(env.available_templates).not_to include('ubuntu/preseed.cfg')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '#hidden_templates' do
|
52
|
+
it 'lists hidden templates' do
|
53
|
+
expect(env.hidden_templates).to include('ubuntu/preseed.cfg')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#available_scripts' do
|
58
|
+
it 'lists available scripts' do
|
59
|
+
expect(env.available_scripts).to be_a(Array)
|
60
|
+
expect(env.available_scripts).to include('postinstall.sh')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'doesn\'t include hidden scripts' do
|
64
|
+
expect(env.available_scripts).not_to include('purge.sh')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#hidden_scripts' do
|
69
|
+
it 'lists hidden scripts' do
|
70
|
+
expect(env.hidden_scripts).to include('purge.sh')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxes::Subprocess do
|
4
|
+
let(:command) do
|
5
|
+
File.expand_path 'spec/support/subprocess_command.rb'
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'runs a command and yields a block' do
|
9
|
+
expect { |b| Boxes::Subprocess.run(command, &b) }.to yield_control
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'runs a command and returns stdout' do
|
13
|
+
total_stdout = ''
|
14
|
+
Boxes::Subprocess.run(command) do |stdout, _stderr, _thread|
|
15
|
+
total_stdout << stdout
|
16
|
+
end
|
17
|
+
|
18
|
+
expect(total_stdout).to eq "A happy output.\n"
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'runs a command and returns stderr' do
|
22
|
+
total_stderr = ''
|
23
|
+
Boxes::Subprocess.run(command) do |_stdout, stderr, _thread|
|
24
|
+
total_stderr << stderr
|
25
|
+
end
|
26
|
+
|
27
|
+
expect(total_stderr).to eq "An unhappy output.\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns a status code' do
|
31
|
+
status = Boxes::Subprocess.run(command) { |_stdout, _stderr, _thread| }
|
32
|
+
|
33
|
+
expect(status.exitstatus).to eq 5
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Boxes::Template do
|
4
|
+
include FakeFS::SpecHelpers
|
5
|
+
|
6
|
+
let(:env) { Boxes::Environment.new }
|
7
|
+
|
8
|
+
before do
|
9
|
+
current_directory = File.expand_path('../../..', __FILE__)
|
10
|
+
|
11
|
+
FileUtils.mkdir_p(current_directory + '/templates')
|
12
|
+
FileUtils.mkdir_p(current_directory + '/templates/ubuntu')
|
13
|
+
|
14
|
+
mock_template = <<-EOF
|
15
|
+
<% @scripts.each do |s| %>
|
16
|
+
<%= s %>
|
17
|
+
<% end %>
|
18
|
+
EOF
|
19
|
+
|
20
|
+
File.open(current_directory + '/templates/ubuntu/trusty64.erb', 'w') do |f|
|
21
|
+
f.puts mock_template
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#initialize' do
|
26
|
+
it 'can read in a known template' do
|
27
|
+
template = described_class.new(env, 'ubuntu/trusty64')
|
28
|
+
|
29
|
+
expect(template.template).to be_a(String)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'throws an exception if the template is missing' do
|
33
|
+
expect do
|
34
|
+
described_class.new(env, 'nope/nope')
|
35
|
+
end.to raise_error(Boxes::Errors::TemplateNotFoundError)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'stores the template name' do
|
39
|
+
template = described_class.new(env, 'ubuntu/trusty64')
|
40
|
+
|
41
|
+
expect(template.name).to eq 'ubuntu/trusty64'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#render' do
|
46
|
+
it 'renders a template with a set of variables' do
|
47
|
+
template = described_class.new(env, 'ubuntu/trusty64')
|
48
|
+
rendered = template.render(scripts: ['ruby.sh'])
|
49
|
+
|
50
|
+
expect(rendered).to include('ruby.sh')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
#
|
2
|
+
# Based upon: https://help.ubuntu.com/12.04/installation-guide/example-preseed.txt
|
3
|
+
#
|
4
|
+
|
5
|
+
# localisation
|
6
|
+
d-i debian-installer/locale string en_US.utf8
|
7
|
+
d-i console-keymaps-at/keymap select us
|
8
|
+
|
9
|
+
# networking
|
10
|
+
d-i netcfg/choose_interface select auto
|
11
|
+
d-i netcfg/get_hostname string unassigned-hostname
|
12
|
+
d-i netcfg/get_domain string unassigned-domain
|
13
|
+
d-i netcfg/wireless_wep string
|
14
|
+
|
15
|
+
# apt mirrors
|
16
|
+
d-i mirror/country string manual
|
17
|
+
d-i mirror/http/hostname string http.us.debian.org
|
18
|
+
d-i mirror/http/directory string /debian
|
19
|
+
d-i mirror/http/proxy string
|
20
|
+
|
21
|
+
# clock and time zone
|
22
|
+
d-i clock-setup/utc boolean true
|
23
|
+
d-i time/zone string GMT
|
24
|
+
d-i clock-setup/ntp boolean true
|
25
|
+
|
26
|
+
# partitioning
|
27
|
+
d-i partman-auto/method string lvm
|
28
|
+
d-i partman-lvm/device_remove_lvm boolean true
|
29
|
+
d-i partman-md/device_remove_md boolean true
|
30
|
+
d-i partman-lvm/confirm boolean true
|
31
|
+
d-i partman-lvm/confirm_nooverwrite boolean true
|
32
|
+
|
33
|
+
#d-i partman-auto-lvm/guided_size string max
|
34
|
+
d-i partman-auto/choose_recipe select atomic
|
35
|
+
d-i partman-partitioning/confirm_write_new_label boolean true
|
36
|
+
d-i partman/choose_partition select finish
|
37
|
+
d-i partman/confirm boolean true
|
38
|
+
d-i partman/confirm_nooverwrite boolean true
|
39
|
+
|
40
|
+
# users
|
41
|
+
d-i passwd/root-login boolean false
|
42
|
+
d-i passwd/user-fullname string Vagrant User
|
43
|
+
d-i passwd/username string vagrant
|
44
|
+
d-i passwd/user-password password vagrant
|
45
|
+
d-i passwd/user-password-again password vagrant
|
46
|
+
d-i user-setup/allow-password-weak boolean true
|
47
|
+
d-i user-setup/encrypt-home boolean false
|
48
|
+
|
49
|
+
# packages
|
50
|
+
tasksel tasksel/first multiselect standard
|
51
|
+
#d-i pkgsel/install-language-support boolean false
|
52
|
+
d-i pkgsel/include string openssh-server nfs-common curl ntp acpid sudo bzip2 rsync git
|
53
|
+
d-i pkgsel/upgrade select full-upgrade
|
54
|
+
d-i pkgsel/update-policy select none
|
55
|
+
d-i popularity-contest/participate boolean false
|
56
|
+
postfix postfix/main_mailer_type select No configuration
|
57
|
+
|
58
|
+
# boot loader
|
59
|
+
d-i grub-installer/only_debian boolean true
|
60
|
+
|
61
|
+
# hide the shutdown notice
|
62
|
+
d-i finish-install/reboot_in_progress note
|
63
|
+
|
64
|
+
# advanced options
|
65
|
+
|
66
|
+
# ensure the default VirtualBox additions doesn't install
|
67
|
+
d-i preseed/early_command string sed -i \
|
68
|
+
'/in-target/idiscover(){/sbin/discover|grep -v VirtualBox;}' \
|
69
|
+
/usr/lib/pre-pkgsel.d/20install-hwpackages
|