Created
July 11, 2012 22:01
-
-
Save ChrisLundquist/3093930 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
root@collectd03:/opt/razor# git remote update | |
Fetching origin | |
Fetching bluebox | |
Fetching lynxbat | |
root@collectd03:/opt/razor# git diff lynxbat/master | |
diff --git a/bin/razor b/bin/razor | |
index 910ac06..8d0f080 100755 | |
--- a/bin/razor | |
+++ b/bin/razor | |
@@ -1,193 +1,7 @@ | |
#!/usr/bin/env ruby | |
-# | |
-# CLI Control for ProjectRazor | |
-# Format will be 'project_razor [module namespace] [module args{}]' | |
-# | |
-# We first add our Lib path to the load path. This is for non-gem ease of use | |
lib_path = File.dirname(File.expand_path(__FILE__)).sub(/\/bin$/,"/lib") | |
$LOAD_PATH.unshift(lib_path) | |
- | |
-require 'rubygems' if RUBY_VERSION < '1.9' | |
-# We require the root lib | |
-require "project_razor" | |
- | |
-# We need these for misc operations later | |
-require "json" | |
-require "colored" | |
-require "optparse" | |
- | |
-# We set a constant for our Slice root Namespace. We use this to pull the slice names back out | |
-# from objectspace | |
-SLICE_PREFIX = "ProjectRazor::Slice::" | |
- | |
-# | |
-def init | |
- @obj = ProjectRazor::Object.new | |
- @version = @obj.get_razor_version | |
- @logger = @obj.get_logger | |
- get_slices_loaded | |
-end | |
- | |
-# Call the slice | |
-def call_razor_slice | |
- begin | |
- if is_slice? | |
- razor_module = Object.full_const_get(SLICE_PREFIX + @namespace.capitalize).new(@args) | |
- razor_module.web_command = @web_command | |
- razor_module.verbose = @verbose | |
- razor_module.debug = @debug | |
- razor_module.slice_call | |
- else | |
- if @web_command | |
- puts JSON.dump({"slice" => "ProjectRazor::Slice", "result" => "InvalidSlice", "http_err_code" => 404}) | |
- else | |
- if @namespace | |
- print "\n [#{@namespace.capitalize}] ".red | |
- print "<-Invalid Slice \n".yellow | |
- end | |
- end | |
- end | |
- rescue => e | |
- @logger.error "Razor slice error: #{e.message}" | |
- if @namespace | |
- print "\n [#{@namespace.capitalize}] ".red | |
- print "<-#{e.message} \n".yellow | |
- else | |
- print "\nMust Enter Slice Name \n".yellow | |
- end | |
- raise e if @debug | |
- end | |
-end | |
- | |
-# Load slices | |
-def get_slices_loaded | |
- temp_hash = {} | |
- | |
- slice_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib/project_razor/slice/*.rb")) | |
- | |
- Dir.glob(slice_path) do |f| | |
- name = File.basename(f,File.extname(f)).capitalize | |
- temp_hash[SLICE_PREFIX+name] = name unless name == 'Slice' | |
- end | |
- | |
- @slice_array = {} | |
- temp_hash.each_value {|x| @slice_array[x] = x} | |
- @slice_array = @slice_array.each_value.collect {|x| x} | |
-end | |
- | |
-# Validate slice | |
-def is_slice? | |
- @slice_array.each { |slice| return true if @namespace.downcase == slice.downcase } if @namespace | |
- false | |
-end | |
- | |
-def print_loaded_slices | |
- print "\nLoaded slices:\n\t" | |
- x = 1 | |
- @slice_array.sort.each do |slice| | |
- slice_obj = ::Object.full_const_get(SLICE_PREFIX + slice.capitalize).new([]) | |
- unless slice_obj.hidden | |
- print "[#{slice.downcase}] ".white | |
- if x > 5 | |
- print "\n\t" | |
- x = 0 | |
- end | |
- x += 1 | |
- end | |
- end | |
- print "\n" | |
-end | |
- | |
-def get_optparse | |
- | |
- OptionParser.new do |opts| | |
- opts.banner = "\n" + "Razor - #{@version}".bold.green | |
- opts.separator "Usage: " | |
- opts.separator "razor [slice name] [command argument] [command argument]...".red | |
- opts.separator "" | |
- opts.separator "Switches".yellow | |
- | |
- @options[:verbose] = false | |
- opts.on( '-v', '--verbose', 'Enables verbose object printing'.yellow ) do | |
- @options[:verbose] = true | |
- end | |
- | |
- @options[:debug] = false | |
- opts.on( '-d', '--debug', 'Enables printing proper Ruby stacktrace'.yellow ) do | |
- @options[:debug] = true | |
- end | |
- | |
- @options[:webcommand] = false | |
- opts.on( '-w', '--webcommand', 'Accepts web commands.'.yellow ) do | |
- @options[:webcommand] = true | |
- end | |
- | |
- @options[:nocolor] = false | |
- opts.on( '-n', '--no-color', 'Disables console color. Useful for script wrapping.'.yellow ) do | |
- @options[:nocolor] = true | |
- end | |
- | |
- opts.on_tail( '-h', '--help', 'Display this screen'.yellow ) do | |
- puts opts | |
- print_loaded_slices | |
- exit | |
- end | |
- end | |
-end | |
- | |
-def get_first_args | |
- f = [] | |
- ARGV.each do |a| | |
- if a.start_with?("-") | |
- f << a | |
- else | |
- return f | |
- end | |
- end | |
- f | |
-end | |
-# Initialise some values | |
-init | |
-first_args = get_first_args | |
-(0..first_args.count-1).each {ARGV.shift} if first_args.count > 0 | |
-@options = {} | |
-optparse = get_optparse | |
-begin | |
- optparse.parse(first_args) | |
-rescue OptionParser::InvalidOption => e | |
- # We may use this option later so we will continue | |
- #puts e.message | |
- #puts optparse | |
- #exit | |
-end | |
- | |
-@web_command = @options[:webcommand] | |
-@debug = @options[:debug] | |
-@verbose = @options[:verbose] | |
- | |
-if @options[:nocolor] or !STDOUT.tty? | |
- # if this flag is set, override the default behavior of the underlying "colorize" method | |
- # from the "Colored" module so that it just returns the string that was passed into it | |
- # (this will have the effect of turning off any color that might be included in any of | |
- # the output statements involving Strings in Razor) | |
- module Colored | |
- extend self | |
- def colorize(string, options = {}) | |
- string | |
- end | |
- end | |
- String.send(:include, Colored) | |
- optparse = get_optparse # reload optparse with color disabled | |
-end | |
- | |
-if ARGV.empty? && !@web_command | |
- puts optparse | |
- print_loaded_slices | |
-end | |
- | |
-@namespace = ARGV.shift | |
-@args = ARGV | |
- | |
-call_razor_slice | |
+require 'project_razor/cli' | |
+ProjectRazor::Cli.run(ARGV.dup) | |
diff --git a/lib/project_razor/cli.rb b/lib/project_razor/cli.rb | |
new file mode 100644 | |
index 0000000..ca3f2ab | |
--- /dev/null | |
+++ b/lib/project_razor/cli.rb | |
@@ -0,0 +1,133 @@ | |
+require 'rubygems' if RUBY_VERSION < '1.9' | |
+ | |
+require 'colored' | |
+require 'json' | |
+require 'optparse' | |
+require 'project_razor' | |
+ | |
+module ProjectRazor | |
+ class Cli | |
+ attr_reader :namespace | |
+ attr_reader :action | |
+ attr_reader :args | |
+ attr_reader :options | |
+ | |
+ SLICE_PREFIX = "ProjectRazor::Slice::" | |
+ | |
+ def self.run(args) | |
+ exit(new(args, $stdout).run) | |
+ end | |
+ | |
+ def initialize(args=[], output=$stdout) | |
+ @obj = ProjectRazor::Object.new | |
+ @version = @obj.get_razor_version | |
+ @logger = @obj.get_logger | |
+ | |
+ @args = args | |
+ @output = output | |
+ @options = { | |
+ :colorize => STDOUT.tty?, | |
+ :verbose => false, | |
+ :debug => false, | |
+ :webcommand => false, | |
+ } | |
+ @exit_code = 0 | |
+ end | |
+ | |
+ def opts | |
+ opts_parser = OptionParser.new do |opts| | |
+ opts.banner = "Usage: "+"razor [global options] [slice] [command] [command options] ...".red | |
+ opts.separator "" | |
+ opts.separator "Global Options:".yellow | |
+ | |
+ opts.on('-v', '--verbose', 'Enable object verbose output.') { @options[:verbose] = true } | |
+ opts.on('-d', '--debug', 'Enable Ruby stack trace output.') { @options[:debug] = true } | |
+ opts.on('-w', '--webcommand', 'Accept web commands.') { @options[:webcommand] = true } | |
+ opts.on('-n', '--no-color', 'Disable console color.') { @options[:colorize] = false; require 'project_razor/cli/colored' } | |
+ | |
+ opts.on_tail('-h', '--help', 'This help message.') { display_help; @exit_code=129; exit(@exit_code) } | |
+ end | |
+ end | |
+ | |
+ def parse_options! | |
+ @args = opts.order!(@args) | |
+ self | |
+ end | |
+ | |
+ def parse_slice! | |
+ slice = @args.shift | |
+ @namespace = slice | |
+ end | |
+ | |
+ def display_usage | |
+ puts opts | |
+ end | |
+ | |
+ def display_help | |
+ puts "\nRazor - #{@version}".bold.green | |
+ display_usage | |
+ puts "\n" | |
+ puts "Available Slices:" | |
+ puts "\t" + cli_slices.keys.collect { |x| "[#{x}]".white }.join(' ') | |
+ end | |
+ | |
+ def puts(*val) | |
+ @output.puts val | |
+ end | |
+ | |
+ def available_slices | |
+ slices = Hash[ ProjectRazor::Slice.class_children.map{|s| [s.to_s.gsub(SLICE_PREFIX,'').downcase, s] } ] | |
+ end | |
+ | |
+ def cli_slices | |
+ slices = available_slices | |
+ slices.delete_if { |k, v| v.new([]).hidden } | |
+ end | |
+ | |
+ def run | |
+ trap('TERM') { print "\nTerminated\n"; exit(1) } | |
+ | |
+ parse_options! | |
+ # Disable color output. | |
+ require 'project_razor/cli/colored' unless @options[:colorize] | |
+ parse_slice! | |
+ | |
+ if @namespace && available_slices.has_key?(@namespace) | |
+ slice = available_slices[@namespace].new(@args) | |
+ slice.web_command = @options[:webcommand] | |
+ slice.verbose = @options[:verbose] | |
+ slice.debug= @options[:debug] | |
+ slice.slice_call | |
+ else | |
+ if @options[:webcommand] | |
+ puts JSON.dump({"slice" => "ProjectRazor::Slice", "result" => "InvalidSlice", "http_err_code" => 404}) | |
+ @exit_code = 1 | |
+ else | |
+ puts "[#{@namespace}]".red + " <- Invalid Slice".yellow if @namespace | |
+ display_help | |
+ @exit_code = 1 | |
+ end | |
+ end | |
+ rescue OptionParser::InvalidOption => e | |
+ unless @options[:webcommand] | |
+ puts(e.backtrace) if @options[:debug] | |
+ puts(e.message.red) | |
+ # if we successfully loaded the slice, print the slice options | |
+ if slice && slice.respond_to?(:command_opts) | |
+ puts(slice.command_opts) | |
+ else | |
+ puts(opts) | |
+ end | |
+ end | |
+ @exit_code = 129 | |
+ rescue Exception => e | |
+ unless @options[:webcommand] | |
+ puts(e.backtrace) if @options[:debug] | |
+ puts(e.message.red) | |
+ end | |
+ @exit_code = 1 | |
+ ensure | |
+ return @exit_code | |
+ end | |
+ end | |
+end | |
diff --git a/lib/project_razor/cli/colored.rb b/lib/project_razor/cli/colored.rb | |
new file mode 100644 | |
index 0000000..45d8101 | |
--- /dev/null | |
+++ b/lib/project_razor/cli/colored.rb | |
@@ -0,0 +1,7 @@ | |
+module Colored | |
+ extend self | |
+ def colorize(string, options = {}) | |
+ string | |
+ end | |
+end | |
+String.send(:include, Colored) | |
diff --git a/lib/project_razor/cli/version.rb b/lib/project_razor/cli/version.rb | |
new file mode 100644 | |
index 0000000..93adfa4 | |
--- /dev/null | |
+++ b/lib/project_razor/cli/version.rb | |
@@ -0,0 +1,6 @@ | |
+module Project_Razor | |
+ module Cli | |
+ VERSION = '0.1.6.0' | |
+ end | |
+end | |
+ | |
diff --git a/lib/project_razor/model/ubuntu/oneiric/preseed.erb b/lib/project_razor/model/ubuntu/oneiric/preseed.erb | |
index b744916..4c87654 100644 | |
--- a/lib/project_razor/model/ubuntu/oneiric/preseed.erb | |
+++ b/lib/project_razor/model/ubuntu/oneiric/preseed.erb | |
@@ -18,6 +18,7 @@ d-i partman-lvm/device_remove_lvm boolean true | |
d-i partman-md/device_remove_md boolean true | |
d-i partman-auto-lvm/guided_size string max | |
d-i partman-auto/choose_recipe select atomic | |
+d-i partman-auto/purge_lvm_from_device boolean true | |
d-i partman/default_filesystem string ext4 | |
d-i partman-lvm/confirm boolean true | |
d-i partman-lvm/confirm_nooverwrite boolean true | |
diff --git a/lib/project_razor/model/ubuntu/precise/preseed.erb b/lib/project_razor/model/ubuntu/precise/preseed.erb | |
index 305200f..ee0e428 100644 | |
--- a/lib/project_razor/model/ubuntu/precise/preseed.erb | |
+++ b/lib/project_razor/model/ubuntu/precise/preseed.erb | |
@@ -18,6 +18,7 @@ d-i partman-lvm/device_remove_lvm boolean true | |
d-i partman-md/device_remove_md boolean true | |
d-i partman-auto-lvm/guided_size string max | |
d-i partman-auto/choose_recipe select atomic | |
+d-i partman-auto/purge_lvm_from_device boolean true | |
d-i partman/default_filesystem string ext4 | |
d-i partman-lvm/confirm boolean true | |
d-i partman-lvm/confirm_nooverwrite boolean true | |
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb | |
index 2e5c829..550f812 100644 | |
--- a/spec/spec_helper.rb | |
+++ b/spec/spec_helper.rb | |
@@ -3,5 +3,6 @@ $LOAD_PATH.unshift File.expand_path(File.join(dir, '..', 'lib')) | |
require 'project_razor' | |
require 'rspec' | |
+require 'mocha' | |
require 'json' | |
require 'net/http' | |
diff --git a/spec/unit/cli_spec.rb b/spec/unit/cli_spec.rb | |
new file mode 100644 | |
index 0000000..7c7c1c6 | |
--- /dev/null | |
+++ b/spec/unit/cli_spec.rb | |
@@ -0,0 +1,145 @@ | |
+#!/usr/bin/env rspec | |
+require 'spec_helper' | |
+ | |
+require 'project_razor/cli' | |
+ | |
+describe ProjectRazor::Cli do | |
+ | |
+ output = $stdout | |
+ | |
+ describe 'when parsing global options' do | |
+ it 'should disable color for non-tty STDOUT' do | |
+ args = '' | |
+ STDOUT.stub(:tty?).and_return(false) | |
+ cli = ProjectRazor::Cli.new(args.split, output).parse_options! | |
+ cli.options[:colorize].should == false | |
+ end | |
+ | |
+ it 'should disable color when specified' do | |
+ args = '--no-color' | |
+ cli = ProjectRazor::Cli.new(args.split, output).parse_options! | |
+ cli.options[:colorize].should == false | |
+ end | |
+ | |
+ [ '--debug', | |
+ '-d' | |
+ ].each do |args| | |
+ it 'should enable debug when specified' do | |
+ cli = ProjectRazor::Cli.new(args.split, output).parse_options! | |
+ cli.options[:debug].should == true | |
+ end | |
+ end | |
+ | |
+ [ '--verbose', | |
+ '-v' | |
+ ].each do |args| | |
+ it 'should enable verbose when specified' do | |
+ cli = ProjectRazor::Cli.new(args.split, output).parse_options! | |
+ cli.options[:verbose].should == true | |
+ end | |
+ end | |
+ | |
+ [ '--webcommand', | |
+ '-w' | |
+ ].each do |args| | |
+ it 'should enable webcommand when specified' do | |
+ cli = ProjectRazor::Cli.new(args.split, output).parse_options! | |
+ cli.options[:webcommand].should == true | |
+ end | |
+ end | |
+ | |
+ it 'should parse global options and parse slices' do | |
+ args = '-d image' | |
+ | |
+ cli = ProjectRazor::Cli.new(args.split, $stdout) | |
+ cli.parse_options! | |
+ cli.parse_slice! | |
+ cli.namespace.should == 'image' | |
+ end | |
+ | |
+ it 'should throw exception on unknown options' do | |
+ args = '-z' | |
+ expect { ProjectRazor::Cli.new(args.split, output).parse_options! }.should raise_error(OptionParser::InvalidOption) | |
+ end | |
+ | |
+ it 'should suppress exceptions for webcommand' do | |
+ args = '-w -z' | |
+ output = mock | |
+ output.expects(:puts).never | |
+ cli = ProjectRazor::Cli.new(args.split, output).run | |
+ cli.should == 129 | |
+ end | |
+ end | |
+ | |
+ describe 'when loading slices' do | |
+ it 'should ignore hidden slices for cli' do | |
+ args = '' | |
+ cli = ProjectRazor::Cli.new(args.split, output).cli_slices | |
+ cli.keys.sort.should == %w( bmc broker image log model node policy tag ) | |
+ end | |
+ | |
+ it 'should find all availble slices' do | |
+ args = '' | |
+ cli = ProjectRazor::Cli.new(args.split, output).available_slices | |
+ cli.keys.sort.should == %w(base bmc boot broker config image log model node policy tag) | |
+ end | |
+ | |
+ it 'should display help when no options provided' do | |
+ args = '' | |
+ cli = ProjectRazor::Cli.new(args.split, $stdout) | |
+ cli.should_receive(:display_help) | |
+ cli.run.should == 1 | |
+ end | |
+ | |
+ it 'should display help for invalid slices for cli' do | |
+ args = '-d zzz' | |
+ cli = ProjectRazor::Cli.new(args.split, $stdout) | |
+ cli.should_receive(:puts).with(/Invalid Slice/).once | |
+ cli.should_receive(:display_help) | |
+ cli.run.should == 1 | |
+ end | |
+ | |
+ it 'should return json for invalid slices for webcommand' do | |
+ args = '-w zzz' | |
+ cli = ProjectRazor::Cli.new(args.split, $stdout) | |
+ cli.should_receive(:puts).with(JSON.dump({ "slice" => "ProjectRazor::Slice", "result" => "InvalidSlice", "http_err_code" => 404 })) | |
+ cli.should_receive(:display_help).never | |
+ cli.run.should == 1 | |
+ end | |
+ | |
+ before :each do | |
+ @image = mock(ProjectRazor::Slice::Image) | |
+ @image.stub(:web_command=) | |
+ @image.stub(:verbose=) | |
+ @image.stub(:debug=) | |
+ @image.stub(:slice_call) | |
+ end | |
+ | |
+ it 'should invoke available slices' do | |
+ args = 'image' | |
+ | |
+ ProjectRazor::Slice::Image.should_receive(:new).with([]).and_return(@image) | |
+ cli = ProjectRazor::Cli.new(args.split, $stdout) | |
+ cli.stubs(:available_slices).returns({'image'=>ProjectRazor::Slice::Image}) | |
+ cli.run.should == 0 | |
+ end | |
+ | |
+ it 'should invoke available slices with command options' do | |
+ args = 'image --help -f baz' | |
+ | |
+ ProjectRazor::Slice::Image.should_receive(:new).with(['--help', '-f', 'baz']).and_return(@image) | |
+ cli = ProjectRazor::Cli.new(args.split, $stdout) | |
+ cli.stubs(:available_slices).returns({'image'=>ProjectRazor::Slice::Image}) | |
+ cli.run.should == 0 | |
+ end | |
+ | |
+ it 'should invoke available slices after stripping global options' do | |
+ args = '-d image -d -f baz' | |
+ | |
+ ProjectRazor::Slice::Image.should_receive(:new).with(['-d', '-f', 'baz']).and_return(@image) | |
+ cli = ProjectRazor::Cli.new(args.split, $stdout) | |
+ cli.stubs(:available_slices).returns({'image'=>ProjectRazor::Slice::Image}) | |
+ cli.run.should == 0 | |
+ end | |
+ end | |
+end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment