You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
5.8 KiB

4 years ago
require "optparse" unless defined?(OptionParser)
require "ostruct" unless defined?(OpenStruct)
require "bento/common"
require "bento/runner"
require "bento/normalize"
require "bento/test"
require "bento/upload"
class Options
NAME = File.basename($PROGRAM_NAME).freeze
def self.parse(args)
options = OpenStruct.new
options.template_files = calculate_templates("packer_templates/**/*.json")
global = OptionParser.new do |opts|
opts.banner = "Usage: #{NAME} [SUBCOMMAND [options]]"
opts.separator ""
opts.separator <<-COMMANDS.gsub(/^ {8}/, "")
build : build one or more templates
help : prints this help message
list : list all templates in project
normalize : normalize one or more templates
test : test one or more builds with kitchen
upload : upload and release one or more builds to Vagrant Cloud
COMMANDS
end
# @tas50: commenting this out since it's unused 11/30/2018
# platforms_argv_proc = proc { |opts|
# opts.platforms = builds["public"] unless args.empty?
# }
templates_argv_proc = proc { |opts|
opts.template_files = calculate_templates(args) unless args.empty?
opts.template_files.each do |t|
unless File.exist?("#{t}.json")
warn "File #{t}.json does not exist for template '#{t}'"
exit(1)
end
end
}
box_version_argv_proc = proc { |opts|
opts.box = ARGV[0]
opts.version = ARGV[1]
}
md_json_argv_proc = proc { |opts|
opts.md_json = ARGV[0]
}
subcommand = {
help: {
parser: OptionParser.new {},
argv: proc { |_opts|
puts global
exit(0)
},
},
build: {
class: BuildRunner,
parser: OptionParser.new do |opts|
opts.banner = "Usage: #{NAME} build [options] TEMPLATE[ TEMPLATE ...]"
opts.on("-n", "--dry-run", "Dry run (what would happen)") do |opt|
options.dry_run = opt
end
opts.on("-c BUILD_YML", "--config BUILD_YML", "Use a configuration file") do |opt|
options.config = opt
end
opts.on("-d", "--[no-]debug", "Run packer with debug output") do |opt|
options.debug = opt
end
opts.on("-o BUILDS", "--only BUILDS", "Only build some Packer builds (ex: parallels-iso,virtualbox-iso,vmware-iso)") do |opt|
options.only = opt
end
opts.on("-e BUILDS", "--except BUILDS", "Build all Packer builds except these (ex: parallels-iso,virtualbox-iso,vmware-iso)") do |opt|
options.except = opt
end
opts.on("-m MIRROR", "--mirror MIRROR", "Look for isos at MIRROR") do |opt|
options.mirror = opt
end
opts.on("-C cpus", "--cpus CPUS", "# of CPUs per provider") do |opt|
options.cpus = opt
end
opts.on("-M MEMORY", "--memory MEMORY", "Memory (MB) per provider") do |opt|
options.mem = opt
end
opts.on("-H", "--headed", "Display provider UI windows") do |opt|
options.headed = opt
end
opts.on("-S", "--single", "Disable parallelization of Packer builds") do |opt|
options.single = opt
end
# the default template override version unless a user passes one
options.override_version = Time.now.gmtime.strftime("%Y%m.%d.0")
opts.on("-v VERSION", "--version VERSION", "Override the date computed version of #{options.override_version}") do |opt|
options.override_version = opt
end
end,
argv: templates_argv_proc,
},
list: {
class: ListRunner,
parser: OptionParser.new do |opts|
opts.banner = "Usage: #{NAME} list [TEMPLATE ...]"
end,
argv: templates_argv_proc,
},
normalize: {
class: NormalizeRunner,
parser: OptionParser.new do |opts|
opts.banner = "Usage: #{NAME} normalize TEMPLATE[ TEMPLATE ...]"
opts.on("-d", "--[no-]debug", "Run packer with debug output") do |opt|
options.debug = opt
end
end,
argv: templates_argv_proc,
},
test: {
class: TestRunner,
parser: OptionParser.new do |opts|
opts.banner = "Usage: #{NAME} test [options]"
opts.on("--no-shared-folder", "Disable shared folder testing") do |opt|
options.no_shared = opt
end
opts.on("-p", "--provisioner PROVISIONER", "Use a specfic provisioner") do |opt|
options.provisioner = opt
end
end,
argv: proc {},
},
upload: {
class: UploadRunner,
parser: OptionParser.new do |opts|
opts.banner = "Usage: #{NAME} upload"
end,
argv: md_json_argv_proc,
},
}
global.order!
command = args.empty? ? :help : ARGV.shift.to_sym
subcommand.fetch(command).fetch(:parser).order!
subcommand.fetch(command).fetch(:argv).call(options)
options.command = command
options.klass = subcommand.fetch(command).fetch(:class)
options
end
def self.calculate_templates(globs)
Array(globs)
.map { |glob| result = Dir.glob(glob); result.empty? ? glob : result }
.flatten
.sort
.delete_if { |file| file =~ /\.(variables||metadata)\.json/ }
.map { |template| template.sub(/\.json$/, "") }
end
end
class ListRunner
include Common
attr_reader :templates
def initialize(opts)
@templates = opts.template_files
end
def start
templates.each { |template| puts template }
end
end
class Runner
attr_reader :options
def initialize(options)
@options = options
end
def start
options.klass.new(options).start
end
end