lib/kameleon/cli.rb in kameleon-builder-2.1.3 vs lib/kameleon/cli.rb in kameleon-builder-2.2.0
- old
+ new
@@ -2,93 +2,106 @@
require 'kameleon/recipe'
require 'kameleon/utils'
module Kameleon
class CLI < Thor
+ include Thor::Actions
-
class_option :color, :type => :boolean, :default => true,
:desc => "Enable colorization in output"
class_option :debug, :type => :boolean, :default => false,
:desc => "Enable debug output"
+ class_option :script, :type => :boolean, :default => false,
+ :desc => "never prompts for user intervention",
+ :aliases => "-s"
map %w(-h --help) => :help
- no_commands do
- def logger
- @logger ||= Log4r::Logger.new("kameleon::[kameleon]")
- end
- end
-
- method_option :force,:type => :boolean,
- :default => false, :aliases => "-f",
- :desc => "Overwrite all existing files"
desc "import [TEMPLATE_NAME]", "Imports the given template"
def import(template_name)
templates_path = Kameleon.env.templates_path
template_path = File.join(templates_path, template_name) + '.yaml'
begin
- template_recipe = RecipeTemplate.new(template_path, :strict => false)
+ tpl = RecipeTemplate.new(template_path)
rescue
raise TemplateNotFound, "Template '#{template_name}' not found. " \
"To see all templates, run the command "\
"`kameleon templates`"
else
- logger.notice("Importing template '#{template_name}'...")
- template_recipe.copy_template(options[:force])
- logger.notice("done")
+ files2copy = tpl.base_recipes_files + tpl.files
+ files2copy.each do |path|
+ relative_path = path.relative_path_from(Kameleon.env.templates_path)
+ dst = File.join(Kameleon.env.workspace, relative_path)
+ copy_file(path, dst)
+ end
end
end
- method_option :force,:type => :boolean,
- :default => false, :aliases => "-f",
- :desc => "Overwrite all existing files"
desc "new [RECIPE_NAME] [TEMPLATE_NAME]", "Creates a new recipe"
def new(recipe_name, template_name)
if recipe_name == template_name
fail RecipeError, "Recipe name should be different from template name"
end
templates_path = Kameleon.env.templates_path
template_path = File.join(templates_path, template_name) + '.yaml'
begin
- template_recipe = RecipeTemplate.new(template_path, :strict => false)
+ tpl = RecipeTemplate.new(template_path)
rescue
raise TemplateNotFound, "Template '#{template_name}' not found. " \
"To see all templates, run the command "\
"`kameleon templates`"
else
- logger.notice("Cloning template '#{template_name}'...")
- template_recipe.copy_template(options[:force])
- logger.notice("Creating extended recipe from template '#{template_name}'...")
- template_recipe.copy_extended_recipe(recipe_name, options[:force])
- logger.notice("done")
+ files2copy = tpl.base_recipes_files + tpl.files
+ files2copy.each do |path|
+ relative_path = path.relative_path_from(Kameleon.env.templates_path)
+ dst = File.join(Kameleon.env.workspace, relative_path)
+ copy_file(path, dst)
+ end
+ Dir::mktmpdir do |tmp_dir|
+ recipe_path = File.join(tmp_dir, recipe_name + '.yaml')
+ ## copying recipe
+ File.open(recipe_path, 'w+') do |file|
+ extend_erb_tpl = File.join(Kameleon.env.templates_path, "extend.erb")
+ erb = ERB.new(File.open(extend_erb_tpl, 'rb') { |f| f.read })
+ result = erb.result(binding)
+ file.write(result)
+ end
+ recipe_dst = File.join(Kameleon.env.workspace, recipe_name + '.yaml')
+ copy_file(recipe_path, Pathname.new(recipe_dst))
+ end
end
end
desc "templates", "Lists all defined templates"
def templates
- Log4r::Outputter['console'].level = Log4r::ERROR unless Kameleon.env.debug
puts "The following templates are available in " \
"#{ Kameleon.templates_path }:"
templates_hash = []
- Kameleon.templates_files.each do |f|
+ templates_path = File.join(Kameleon.env.templates_path, "/")
+ all_yaml_files = Dir["#{templates_path}**/*.yaml"]
+ steps_files = Dir["#{templates_path}steps/**/*.yaml"]
+ templates_files = all_yaml_files - steps_files
+ templates_files.each do |f|
begin
- recipe = RecipeTemplate.new(f, :strict => false)
+ recipe = RecipeTemplate.new(f)
templates_hash.push({
- "name" => recipe.name,
+ "name" => f.gsub(templates_path, "").chomp(".yaml"),
"description" => recipe.metainfo['description'],
})
rescue => e
raise e if Kameleon.env.debug
end
end
templates_hash = templates_hash.sort_by{ |k| k["name"] }
- tp templates_hash, {"name" => {:width => 30}}, { "description" => {:width => 60}}
+ name_width = templates_hash.map { |k| k['name'].size }.max
+ desc_width = Kameleon.ui.shell.terminal_width - name_width - 3
+ tp(templates_hash,
+ {"name" => {:width => name_width}},
+ { "description" => {:width => desc_width}})
end
desc "version", "Prints the Kameleon's version information"
def version
- Log4r::Outputter['console'].level = Log4r::OFF unless Kameleon.env.debug
puts "Kameleon version #{Kameleon::VERSION}"
end
map %w(-v --version) => :version
desc "build [RECIPE_PATH]", "Builds the appliance from the given recipe"
@@ -101,130 +114,104 @@
method_option :from_checkpoint, :type => :string ,
:default => nil,
:desc => "Using specific checkpoint to build the image. " \
"Default value is the last checkpoint."
method_option :checkpoint, :type => :boolean ,
- :default => true,
- :desc => "Do not use checkpoints"
+ :default => false,
+ :desc => "Enable checkpoint"
method_option :cache, :type => :boolean,
:default => false,
:desc => "Generate a persistent cache for the appliance."
+ method_option :cache_path, :type => :string ,
+ :default => nil,
+ :desc => "Set the cache directory path"
method_option :from_cache, :type => :string ,
:default => nil,
:desc => "Using a persistent cache tar file to build the image."
method_option :proxy_path, :type => :string ,
:default => nil,
:desc => "Full path of the proxy binary to use for the persistent cache."
- def build(recipe_path)
+ def build(recipe_path=nil)
+ if recipe_path.nil? && !options[:from_cache].nil?
+ Kameleon.ui.info("Using the cached recipe")
+ @cache = Kameleon::Persistent_cache.instance
+ @cache.cache_path = options[:from_cache]
+ recipe_path = @cache.get_recipe
+ end
+ raise BuildError, "A recipe file or a persistent cache archive " \
+ "is required to run this command." if recipe_path.nil?
clean(recipe_path) if options[:clean]
engine = Kameleon::Engine.new(Recipe.new(recipe_path), options)
- logger.notice("Starting build recipe '#{recipe_path}'")
+ Kameleon.ui.info("Starting build recipe '#{recipe_path}'")
start_time = Time.now.to_i
engine.build
total_time = Time.now.to_i - start_time
- logger.notice("")
- logger.notice("Build recipe '#{recipe_path}' is completed !")
- logger.notice("Build total duration : #{total_time} secs")
- logger.notice("Build directory : #{engine.cwd}")
- logger.notice("Build recipe file : #{engine.build_recipe_path}")
- logger.notice("Log file : #{Kameleon.env.log_file}")
+ Kameleon.ui.info("")
+ Kameleon.ui.info("Successfully built '#{recipe_path}'")
+ Kameleon.ui.info("Total duration : #{total_time} secs")
end
desc "checkpoints [RECIPE_PATH]", "Lists all availables checkpoints"
method_option :build_path, :type => :string ,
:default => nil, :aliases => "-b",
:desc => "Set the build directory path"
def checkpoints(recipe_path)
- Log4r::Outputter['console'].level = Log4r::ERROR unless Kameleon.env.debug
+ Kameleon.ui.level = "error"
engine = Kameleon::Engine.new(Recipe.new(recipe_path), options)
engine.pretty_checkpoints_list
end
- desc "clean [RECIPE_PATH]", "Cleaning 'out' and 'local' contexts and removing all checkpoints"
+ desc "clean [RECIPE_PATH]", "Cleaning all contexts and removing the checkpoints"
method_option :build_path, :type => :string ,
:default => nil, :aliases => "-b",
:desc => "Set the build directory path"
def clean(recipe_path)
- Log4r::Outputter['console'].level = Log4r::INFO
- engine = Kameleon::Engine.new(Recipe.new(recipe_path), options)
- engine.clear
+ opts = Hash.new.merge options
+ opts[:lazyload] = false
+ opts[:fail_silently] = true
+ engine = Kameleon::Engine.new(Recipe.new(recipe_path), opts)
+ engine.clean(:with_checkpoint => true)
end
map %w(clear) => :clean
desc "commands", "Lists all available commands", :hide => true
def commands
- puts CLI.all_commands.keys - ["commands", "completions"]
+ Kameleon.ui.info CLI.all_commands.keys - ["commands", "completions"]
end
desc "source_root", "Prints the kameleon directory path", :hide => true
def source_root
puts Kameleon.source_root
end
- # Hack Thor to init Kameleon env soon
- def self.init(base_config)
- env_options = Hash.new
- env_options.merge! base_config[:shell].base.options.clone
- # configure logger
- env_options["debug"] = true if ENV["KAMELEON_LOG"] == "debug"
- ENV["KAMELEON_LOG"] = "debug" if env_options["debug"]
- if ENV["KAMELEON_LOG"] && ENV["KAMELEON_LOG"] != ""
- level_name = ENV["KAMELEON_LOG"]
- else
- level_name = "info"
+ def initialize(*args)
+ super
+ self.options ||= {}
+ Kameleon.env = Kameleon::Environment.new(self.options)
+ if !$stdout.tty? or !options["color"]
+ Thor::Base.shell = Thor::Shell::Basic
end
- # Require Log4r and define the levels we'll be using
- require 'log4r-color/config'
- Log4r.define_levels(*Log4r::Log4rConfig::LogLevels)
-
- begin
- level = Log4r.const_get(level_name.upcase)
- rescue NameError
- level = Log4r.const_get("INFO")
- $stderr << "Invalid KAMELEON_LOG level is set: #{level_name}.\n" \
- "Please use one of the standard log levels: debug," \
- " info, warn, or error\n"
- raise KameleonError
+ Kameleon.ui = Kameleon::UI::Shell.new(self.options)
+ Kameleon.ui.level = "debug" if self.options["debug"]
+ opts = args[1]
+ cmd_name = args[2][:current_command].name
+ if opts.include? "--help"
+ CLI.command_help(Kameleon.ui.shell, cmd_name)
+ raise Kameleon::Exit
end
- format = ConsoleFormatter.new
- # format = Log4r::PatternFormatter.new(:pattern => '%11c: %M')
- if !$stdout.tty? or !env_options["color"]
- console_output = Log4r::StdoutOutputter.new('console',
- :formatter => format)
- Diffy::Diff.default_format = :text
- else
- console_output = Log4r::ColorOutputter.new 'console', {
- :colors => { :debug => :light_black,
- :info => :green,
- :progress_info => :green,
- :notice => :light_blue,
- :progress_notice => :light_blue,
- :warn => :yellow,
- :error => :red,
- :progress_error => :red,
- :fatal => :red,
- },
- :formatter => format,
- }
- Diffy::Diff.default_format = :color
- end
- logger = Log4r::Logger.new('kameleon')
- logger.level = level
- logger.outputters << console_output
- format_file = FileFormatter.new
- Kameleon.logger.debug("`kameleon` invoked: #{ARGV.inspect}")
- Kameleon.env = Kameleon::Environment.new(env_options)
- filelog = Log4r::FileOutputter.new('logfile',
- :trunc=>false,
- :filename => Kameleon.env.log_file.to_s,
- :formatter => format_file)
- logger.outputters << filelog
- logger = nil
end
- def self.start(given_args=ARGV, config={})
- config[:shell] ||= Thor::Base.shell.new
- dispatch(nil, given_args.dup, nil, config) { init(config) }
+ def self.start(*)
+ super
+ rescue Exception => e
+ Kameleon.ui = Kameleon::UI::Shell.new
+ raise e
end
+
+ def self.source_root
+ Kameleon.source_root
+ end
+
end
+
end