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.
@@ -0,0 +1,73 @@
1
+ module Boxes
2
+ # Stores the configuration for Boxes.
3
+ class Config
4
+ # The default settings for the configuration.
5
+ DEFAULTS = {
6
+ environment_vars: [
7
+ { 'PACKER_CACHE_DIR' => (
8
+ Pathname.new(ENV['BOXES_HOME_DIR'] || '~/.boxes'
9
+ ).expand_path + 'packer_cache') }
10
+ ],
11
+ template_paths: [
12
+ # the gem install directory
13
+ File.expand_path('../../../templates', __FILE__)
14
+ ],
15
+ script_paths: [
16
+ # the gem install directory
17
+ File.expand_path('../../../scripts', __FILE__)
18
+ ]
19
+ }
20
+
21
+ # The directory which boxes works out of.
22
+ def home_dir
23
+ @home_dir ||= Pathname.new(
24
+ ENV['BOXES_HOME_DIR'] || '~/.boxes').expand_path
25
+ end
26
+
27
+ # The directory inside the `home_dir` which boxes runs builds inside of.
28
+ def working_dir
29
+ @working_dir ||= Pathname.new(
30
+ ENV['BOXES_WORKING_DIR'] || home_dir + 'tmp').expand_path
31
+ end
32
+
33
+ # Paths known to boxes for discovering templates.
34
+ attr_accessor :template_paths
35
+
36
+ # Paths known to boxes for discovering scripts.
37
+ attr_accessor :script_paths
38
+
39
+ # A Hash of environment variables Boxes sets in the run environment.
40
+ attr_accessor :environment_vars
41
+
42
+ def initialize
43
+ configure_with(DEFAULTS)
44
+
45
+ return unless user_settings_file.exist?
46
+
47
+ user_settings = YAML.load_file(user_settings_file)
48
+ configure_with(user_settings)
49
+ end
50
+
51
+ private
52
+
53
+ def user_settings_file
54
+ home_dir + 'config.yml'
55
+ end
56
+
57
+ def configure_with(opts = {}) # rubocop:disable Metrics/MethodLength
58
+ opts.each do |k, v|
59
+ next unless respond_to?("#{k}=")
60
+
61
+ if v.class == Array
62
+ v.each do |e|
63
+ set = Set.new(send("#{k}".to_sym))
64
+ set << e
65
+ send("#{k}=".to_sym, set.to_a)
66
+ end
67
+ else
68
+ send("#{k}=".to_sym, v)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,74 @@
1
+ module Boxes
2
+ # For creating and managing the environment which boxes uses.
3
+ class Environment
4
+ def initialize
5
+ FileUtils.mkdir_p(Boxes.config.working_dir)
6
+
7
+ copy_templates
8
+ copy_scripts
9
+ end
10
+
11
+ def available_templates
12
+ t = Dir.glob("#{Boxes.config.working_dir}/templates/*/**")
13
+ a = t.collect { |c| c.include?('preseed.cfg') ? next : c }.compact
14
+
15
+ a.collect do |c|
16
+ c = c.gsub(Boxes.config.working_dir.to_s + '/templates/', '')
17
+ c.gsub('.erb', '')
18
+ end
19
+ end
20
+
21
+ def hidden_templates
22
+ t = Dir.glob("#{Boxes.config.working_dir}/templates/*/**")
23
+ a = t.collect { |c| c.include?('preseed.cfg') ? c : next }.compact
24
+
25
+ a.collect do |c|
26
+ c.gsub(Boxes.config.working_dir.to_s + '/templates/', '')
27
+ end
28
+ end
29
+
30
+ def available_scripts
31
+ t = Dir.glob("#{Boxes.config.working_dir}/scripts/*")
32
+ a = t.collect { |c| c.include?('purge.sh') ? next : c }.compact
33
+
34
+ a.collect do |c|
35
+ c.gsub(Boxes.config.working_dir.to_s + '/scripts/', '')
36
+ end
37
+ end
38
+
39
+ def hidden_scripts
40
+ t = Dir.glob("#{Boxes.config.working_dir}/scripts/*")
41
+ a = t.collect { |c| c.include?('purge.sh') ? c : next }.compact
42
+
43
+ a.collect do |c|
44
+ c.gsub(Boxes.config.working_dir.to_s + '/scripts/', '')
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def copy_templates
51
+ templates_dir = Boxes.config.working_dir + 'templates'
52
+
53
+ FileUtils.mkdir_p(templates_dir)
54
+
55
+ Boxes.config.template_paths.each do |template_path|
56
+ Dir.glob("#{template_path}/*").each do |src_template|
57
+ FileUtils.cp_r(src_template, templates_dir)
58
+ end
59
+ end
60
+ end
61
+
62
+ def copy_scripts
63
+ scripts_dir = Boxes.config.working_dir + 'scripts'
64
+
65
+ FileUtils.mkdir_p(Boxes.config.working_dir + 'scripts')
66
+
67
+ Boxes.config.script_paths.each do |script_path|
68
+ Dir.glob("#{script_path}/*").each do |src_script|
69
+ FileUtils.cp_r(src_script, scripts_dir)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,19 @@
1
+ module Boxes
2
+ # A collection of errors which can be raised by boxes.
3
+ module Errors
4
+ # Base error class for all other errors.
5
+ class BoxesError < StandardError; end
6
+
7
+ # Raised when a template is missing.
8
+ class TemplateNotFoundError < BoxesError; end
9
+
10
+ # Raised when a script is missing.
11
+ class ScriptNotFoundError < BoxesError; end
12
+
13
+ # Raised when an expected argument is missing.
14
+ class MissingArgumentError < BoxesError; end
15
+
16
+ # Raised when a build fails.
17
+ class BuildRunError < BoxesError; end
18
+ end
19
+ end
@@ -0,0 +1,39 @@
1
+ module Boxes
2
+ # Standardise handling the stdout and stderr from Open3.
3
+ #
4
+ # @example Print the values returned to stdout and stderr
5
+ # Boxes::Utils::Subprocess.run 'ls' do |stdout, stderr, thread|
6
+ # puts stdout unless stdout == nil
7
+ # puts stderr unless stderr == nil
8
+ # end
9
+ #
10
+ class Subprocess
11
+ # Create a new subprocess with a command, with a block for the response.
12
+ #
13
+ # @param cmd [String] the command to run
14
+ # @yield [stdout, stderr, thread] Gives the stdout, stderr and process
15
+ # thread to the block.
16
+ def self.run(command) # rubocop:disable Metrics/MethodLength
17
+ # see: http://stackoverflow.com/a/1162850/83386
18
+ Open3.popen3(command) do |_stdin, stdout, stderr, thread|
19
+ # read each stream from a new thread
20
+ { out: stdout, err: stderr }.each do |key, stream|
21
+ Thread.new do
22
+ stream.each_line do |line|
23
+ # yield the block depending on the stream
24
+ if key == :out
25
+ yield line, nil, thread if block_given?
26
+ else
27
+ yield nil, line, thread if block_given?
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ thread.join # don't exit until the external process is done
34
+
35
+ thread.value
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,50 @@
1
+ module Boxes
2
+ # Representations of Packer templates.
3
+ class Template
4
+ include Boxes::Errors
5
+
6
+ attr_reader :name, :template
7
+
8
+ # Load a template with a given name.
9
+ #
10
+ # @param env [Boxes::Environment] the environment to source templates.
11
+ # @param name [String] the name of the template.
12
+ #
13
+ # @return [Boxes::Template] a template instance.
14
+ def initialize(env, name)
15
+ fail(TemplateNotFoundError) unless env.available_templates.include?(name)
16
+
17
+ @name = name
18
+ @template = ''
19
+ File.open(Boxes.config.working_dir + "templates/#{name}.erb") do |f|
20
+ @template << f.read
21
+ end
22
+ end
23
+
24
+ # Render the template.
25
+ #
26
+ # @param args [Hash] the values to set.
27
+ #
28
+ # @return [String] the rendered template.
29
+ def render(args)
30
+ ERB.new(template, nil, '-').result(ERBContext.new(args).get_binding)
31
+ end
32
+
33
+ # A context to render inside, to avoid polluting other classes.
34
+ class ERBContext
35
+ # Create a new context with a given hash of values.
36
+ #
37
+ # @params args [Hash] the values to substitute.
38
+ def initialize(args = {})
39
+ args.each_pair do |k, v|
40
+ instance_variable_set('@' + k.to_s, v)
41
+ end
42
+ end
43
+
44
+ # The binding which is passed to ERB.
45
+ def get_binding # rubocop:disable Style/AccessorMethodName
46
+ binding
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,4 @@
1
+ # Versions and other declarations.
2
+ module Boxes
3
+ VERSION = '2.0.0'
4
+ end
@@ -0,0 +1,13 @@
1
+ #!/bin/bash
2
+
3
+ case $(lsb_release -is) in
4
+ 'ubuntu')
5
+ apt-add-repository ppa:ansible/ansible
6
+ apt-get -qy update
7
+ apt-get -qy install ansible
8
+ ;;
9
+ *)
10
+ easy_install pip
11
+ pip install ansible
12
+ ;;
13
+ esac
data/scripts/chef.sh ADDED
@@ -0,0 +1,28 @@
1
+ #!/bin/bash
2
+
3
+ # Get the Chef package version through their metadata service.
4
+ platform=$(lsb_release -si | tr '[:upper:]' '[:lower:]')
5
+ release=$(lsb_release -sr)
6
+ version_url="https://www.opscode.com/chef/metadata?v=&prerelease=false&nightlies=false&p=$platform&pv=$release&m=x86_64"
7
+ current_version=$(curl -s "$version_url")
8
+
9
+ version_url=$(echo "$current_version" | awk '/url/{print $2}')
10
+ version_sha=$(echo "$current_version" | awk '/sha256/{print $2}')
11
+
12
+ # fetch chef
13
+ curl $version_url -o chef.deb
14
+
15
+ # check the file
16
+ echo "$version_sha chef.deb" > '/tmp/chef-checksum'
17
+ shasum -a 256 -c '/tmp/chef-checksum'
18
+ if [ $? -ne 0 ]; then
19
+ echo "Downloaded Chef package failed to checksum."
20
+ exit 1
21
+ fi
22
+
23
+ # install
24
+ dpkg -i chef.deb
25
+
26
+ # cleanup
27
+ rm chef.deb
28
+ rm /tmp/chef-checksum
@@ -0,0 +1,42 @@
1
+ # postinstall.sh based upon Mitchell's old basebox example
2
+
3
+ # mark the build time
4
+ date > /etc/vagrant_box_build_time
5
+
6
+ # update the apt cache and packages
7
+ case $(lsb_release -cs) in
8
+ 'precise')
9
+ apt-get clean
10
+ rm -rf /var/lib/apt/lists/*
11
+ apt-get clean
12
+ ;;
13
+ *)
14
+ ;;
15
+ esac
16
+
17
+ apt-get -qy update
18
+ apt-get -qy upgrade
19
+
20
+ # install some oft used packages
21
+ apt-get -qy install linux-headers-$(uname -r) build-essential
22
+ apt-get -qy install zlib1g-dev libssl-dev
23
+ apt-get -qy install python-software-properties python-setuptools python-dev
24
+ apt-get -qy install ruby1.9.3
25
+
26
+ # configure password-less sudo
27
+ usermod -a -G sudo vagrant
28
+ echo "%vagrant ALL=NOPASSWD:ALL" > /tmp/vagrant
29
+ mv /tmp/vagrant /etc/sudoers.d/vagrant
30
+ chmod 0440 /etc/sudoers.d/vagrant
31
+
32
+ # install the vagrant-provided ssh keys
33
+ mkdir -pm 700 /home/vagrant/.ssh
34
+ curl -Lo /home/vagrant/.ssh/authorized_keys \
35
+ 'https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub'
36
+ chmod 0600 /home/vagrant/.ssh/authorized_keys
37
+ chown -R vagrant:vagrant /home/vagrant/.ssh
38
+
39
+ # clean up any artifacts
40
+ rm -f /home/vagrant/shutdown.sh
41
+
42
+ exit
data/scripts/puppet.sh ADDED
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+
3
+ # see: http://docs.puppetlabs.com/guides/puppetlabs_package_repositories.html
4
+
5
+ # determine the os release
6
+ os_release=$(lsb_release -cs)
7
+
8
+ # configure the puppet package sources
9
+ wget http://apt.puppetlabs.com/puppetlabs-release-$os_release.deb
10
+ dpkg -i puppetlabs-release-$os_release.deb
11
+ apt-get -q update
12
+
13
+ # install puppet
14
+ apt-get install -qy puppet
data/scripts/purge.sh ADDED
@@ -0,0 +1,60 @@
1
+ #!/bin/bash
2
+
3
+ ##
4
+ # Purge unnecessary data from the image to keep it small.
5
+ #
6
+ # Based on: https://gist.github.com/adrienbrault/3775253
7
+ ##
8
+
9
+ # tidy up DCHP leases
10
+ echo "Cleaning up dhcp..."
11
+ rm /var/lib/dhcp/*
12
+
13
+ # make sure Udev doesn't block our network
14
+ # http://6.ptmc.org/?p=164
15
+ echo "Cleaning up udev..."
16
+ rm /etc/udev/rules.d/70-persistent-net.rules
17
+ mkdir /etc/udev/rules.d/70-persistent-net.rules
18
+ rm -rf /dev/.udev/
19
+ rm /lib/udev/rules.d/75-persistent-net-generator.rules
20
+
21
+ # clean up apt
22
+ echo "Cleaning up apt..."
23
+ apt-get -qy autoremove
24
+ apt-get clean -qy
25
+ apt-get autoclean -qy
26
+
27
+ # nuke the bash history
28
+ echo "Removing bash history..."
29
+ unset HISTFILE
30
+ rm -f /root/.bash_history
31
+ rm -f /home/vagrant/.bash_history
32
+
33
+ # clean up the logs
34
+ echo "Cleaning up logs..."
35
+ find /var/log -type f | while read f; do echo -ne '' > $f; done;
36
+
37
+ # zero any and all free space
38
+ echo "Cleaning free space..."
39
+ dd if=/dev/zero of=/EMPTY bs=1M
40
+ rm -f /EMPTY
41
+
42
+ # whiteout root
43
+ echo "Cleaning up /..."
44
+ #count=`df --sync -kP / | tail -n1 | awk -F ' ' '{print $4}'`;
45
+ dd if=/dev/zero of=/tmp/whitespace bs=1024;
46
+ rm /tmp/whitespace;
47
+
48
+ # whiteout /boot
49
+ echo "Cleaning up /boot..."
50
+ #count=`df --sync -kP /boot | tail -n1 | awk -F ' ' '{print $4}'`;
51
+ dd if=/dev/zero of=/boot/whitespace bs=1024;
52
+ rm /boot/whitespace;
53
+
54
+ # whiteout the swap
55
+ echo "Cleaning up swap partitions..."
56
+ swappart=`cat /proc/swaps | tail -n1 | awk -F ' ' '{print $1}'`
57
+ swapoff $swappart;
58
+ dd if=/dev/zero of=$swappart;
59
+ mkswap $swappart;
60
+ swapon $swappart;
data/scripts/ruby.sh ADDED
@@ -0,0 +1,41 @@
1
+ #!/bin/bash
2
+
3
+ # this installs chruby, ruby-install and a selection of rubies and is used in
4
+ # the 'ruby' special box type.
5
+
6
+ chruby_version=0.3.9
7
+ rubyinstall_version=0.5.0
8
+
9
+ # install chruby
10
+ wget -O chruby-$chruby_version.tar.gz https://github.com/postmodern/chruby/archive/v$chruby_version.tar.gz
11
+ tar -xzvf chruby-$chruby_version.tar.gz
12
+ cd chruby-$chruby_version/
13
+ make install
14
+
15
+ # configure system-wide
16
+ cat << 'EOF' > /etc/profile.d/chruby.sh
17
+ if [ -n "$BASH_VERSION" ] || [ -n "$ZSH_VERSION" ]; then
18
+ source /usr/local/share/chruby/chruby.sh
19
+ source /usr/local/share/chruby/auto.sh
20
+ fi
21
+ EOF
22
+
23
+ # install ruby-install
24
+ wget -O ruby-install-$rubyinstall_version.tar.gz https://github.com/postmodern/ruby-install/archive/v$rubyinstall_version.tar.gz
25
+ tar -xzvf ruby-install-$rubyinstall_version.tar.gz
26
+ cd ruby-install-$rubyinstall_version/
27
+ make install
28
+
29
+ # install a set of recent MRI Rubies.
30
+ ruby-install ruby 2.1.5
31
+ ruby-install ruby 2.2.0
32
+ ruby-install ruby 2.2.1
33
+ ruby-install ruby 2.2.2
34
+
35
+ # update gems and install bundler
36
+ source /usr/local/share/chruby/chruby.sh
37
+ for ruby in `chruby`; do
38
+ chruby-exec $ruby -- gem install bundler
39
+ done
40
+
41
+ exit