Skip to content

Commit 350224b

Browse files
committed
Merge bento-ya back into bento
Move all the templates into their own directory. This starts the process of shipping a binary that can be run to build and ship the boxes. This will replace Rake and will be used in Travis to validate the configs as well. Signed-off-by: Tim Smith <[email protected]>
1 parent 032bb6c commit 350224b

File tree

193 files changed

+1524
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

193 files changed

+1524
-2
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ cache: bundler
44

55
env:
66
global:
7-
- PACKER_VERSION="1.3.4"
7+
- PACKER_VERSION="1.3.5"
88
- PATH=$HOME/bin:$PATH
99

1010
rvm:

Gemfile

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
source "https://rubygems.org"
22

3-
gem "bento-ya"
3+
group :development do
4+
gem "chefstyle"
5+
gem "rake", ">= 12"
6+
gem "mixlib-shellout", ">= 2.3.2"
7+
gem "vagrant_cloud", "~> 2.0"
8+
end

bin/bento

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env ruby
2+
Signal.trap("INT") { exit 1 }
3+
4+
$stdout.sync = true
5+
$stderr.sync = true
6+
7+
$LOAD_PATH.unshift File.join(__dir__, %w{.. lib})
8+
require "bento/cli"
9+
10+
begin
11+
Runner.new(Options.parse(ARGV)).start
12+
rescue => ex
13+
warn ">>> #{ex.message}"
14+
exit(($CHILD_STATUS && $CHILD_STATUS.exitstatus) || 99)
15+
end

lib/bento.rb

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require "bento/common"
2+
require "bento/version"

lib/bento/build.rb

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
require "bento/common"
2+
require "bento/buildmetadata"
3+
require "bento/providermetadata"
4+
require "bento/packerexec"
5+
6+
class BuildRunner
7+
include Common
8+
include PackerExec
9+
10+
attr_reader :template_files, :config, :dry_run, :debug, :only, :except, :mirror, :headed, :single,
11+
:override_version, :build_timestamp, :cpus, :mem
12+
13+
def initialize(opts)
14+
@template_files = opts.template_files
15+
@config = opts.config ||= false
16+
@dry_run = opts.dry_run
17+
@debug = opts.debug
18+
@only = opts.only ||= "parallels-iso,virtualbox-iso,vmware-iso"
19+
@except = opts.except
20+
@mirror = opts.mirror
21+
@headed = opts.headed ||= false
22+
@single = opts.single ||= false
23+
@override_version = opts.override_version
24+
@build_timestamp = Time.now.gmtime.strftime("%Y%m%d%H%M%S")
25+
@cpus = opts.cpus
26+
@mem = opts.mem
27+
end
28+
29+
def start
30+
templates = config ? build_list : template_files
31+
banner("Starting build for templates:")
32+
templates.each { |t| puts "- #{t}" }
33+
time = Benchmark.measure do
34+
templates.each { |template| build(template) }
35+
end
36+
banner("Build finished in #{duration(time.real)}.")
37+
end
38+
39+
private
40+
41+
def build(file)
42+
bento_dir = Dir.pwd
43+
dir = File.dirname(file)
44+
template = File.basename(file)
45+
Dir.chdir dir
46+
for_packer_run_with(template) do |md_file, _var_file|
47+
cmd = packer_build_cmd(template, md_file.path)
48+
banner("[#{template}] Building: '#{cmd.join(' ')}'")
49+
time = Benchmark.measure do
50+
system(*cmd) || raise("[#{template}] Error building, exited #{$CHILD_STATUS}")
51+
end
52+
write_final_metadata(template, time.real.ceil)
53+
banner("[#{template}] Finished building in #{duration(time.real)}.")
54+
end
55+
Dir.chdir(bento_dir)
56+
end
57+
58+
def packer_build_cmd(template, var_file)
59+
vars = "#{template}.variables.json"
60+
cmd = %W{packer build -var-file=#{var_file} #{template}.json}
61+
cmd.insert(2, "-var-file=#{vars}") if File.exist?(vars)
62+
cmd.insert(2, "-only=#{only}")
63+
cmd.insert(2, "-except=#{except}") if except
64+
# Build the command line in the correct order and without spaces as future input for the splat operator.
65+
cmd.insert(2, "cpus=#{cpus}") if cpus
66+
cmd.insert(2, "-var") if cpus
67+
cmd.insert(2, "memory=#{mem}") if mem
68+
cmd.insert(2, "-var") if mem
69+
cmd.insert(2, "mirror=#{mirror}") if mirror
70+
cmd.insert(2, "-var") if mirror
71+
cmd.insert(2, "headless=true") unless headed
72+
cmd.insert(2, "-var") unless headed
73+
cmd.insert(2, "-parallel=false") if single
74+
cmd.insert(2, "-debug") if debug
75+
cmd.insert(0, "echo") if dry_run
76+
cmd
77+
end
78+
79+
def write_final_metadata(template, buildtime)
80+
md = BuildMetadata.new(template, build_timestamp, override_version).read
81+
path = File.join("../builds")
82+
filename = File.join(path, "#{md[:box_basename]}.metadata.json")
83+
md[:providers] = ProviderMetadata.new(path, md[:box_basename]).read
84+
md[:providers].each do |p|
85+
p[:build_time] = buildtime
86+
p[:build_cpus] = cpus unless cpus.nil?
87+
p[:build_mem] = mem unless mem.nil?
88+
end
89+
90+
if dry_run
91+
banner("(Dry run) Metadata file contents would be something similar to:")
92+
puts JSON.pretty_generate(md)
93+
else
94+
File.open(filename, "wb") { |file| file.write(JSON.pretty_generate(md)) }
95+
end
96+
end
97+
end

lib/bento/buildmetadata.rb

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
require "bento/common"
2+
require "mixlib/shellout"
3+
4+
class BuildMetadata
5+
include Common
6+
7+
def initialize(template, build_timestamp, override_version)
8+
@template = template
9+
@build_timestamp = build_timestamp
10+
@override_version = override_version
11+
end
12+
13+
def read
14+
{
15+
name: name,
16+
version: version,
17+
build_timestamp: build_timestamp,
18+
git_revision: git_revision,
19+
git_status: git_clean? ? "clean" : "dirty",
20+
box_basename: box_basename,
21+
template: template_vars.fetch("template", UNKNOWN),
22+
packer: packer_ver,
23+
vagrant: vagrant_ver,
24+
}
25+
end
26+
27+
private
28+
29+
UNKNOWN = "__unknown__".freeze
30+
31+
attr_reader :template, :build_timestamp, :override_version
32+
33+
def box_basename
34+
"#{name.gsub("/", "__")}-#{version}"
35+
end
36+
37+
def git_revision
38+
`git rev-parse HEAD`.strip
39+
end
40+
41+
def git_clean?
42+
`git status --porcelain`.strip.empty?
43+
end
44+
45+
def merged_vars
46+
@merged_vars ||= begin
47+
if File.exist?("#{template}.variables.json")
48+
template_vars.merge(JSON.load(IO.read("#{template}.variables.json")))
49+
else
50+
template_vars
51+
end
52+
end
53+
end
54+
55+
def name
56+
merged_vars.fetch("name", template)
57+
end
58+
59+
def template_vars
60+
@template_vars ||= JSON.load(IO.read("#{template}.json")).fetch("variables")
61+
end
62+
63+
def version
64+
override_version || merged_vars.fetch("version", "#{UNKNOWN}.TIMESTAMP")
65+
.rpartition(".").first.concat(build_timestamp.to_s)
66+
end
67+
68+
def packer_ver
69+
cmd = Mixlib::ShellOut.new("packer --version")
70+
cmd.run_command
71+
cmd.stdout.split("\n")[0]
72+
end
73+
74+
def vagrant_ver
75+
if ENV["TRAVIS"]
76+
"travis"
77+
else
78+
cmd = Mixlib::ShellOut.new("vagrant --version")
79+
cmd.run_command
80+
cmd.stdout.split(" ")[1]
81+
end
82+
end
83+
end

0 commit comments

Comments
 (0)