bin/nuri in nuri-0.5.2 vs bin/nuri in nuri-0.5.3

- old
+ new

@@ -6,15 +6,10 @@ Version = File.read(File.dirname(__FILE__) + "/../VERSION").strip About = "Nuri #{Version} (c) 2013" Nuri.init -def console(*args) - print Time.now.strftime('%Y-%m-%d %H:%M:%S '.yellow) - $stdout.puts(args) -end - class Nuri::Console include Nuri::Helper ParentEliminator = Sfp::Visitor::ParentEliminator.new @@ -35,11 +30,11 @@ Usage: #{cmd}state [options] where [options] are: EOS opt :model_file, 'file contains a model of desired state', :default => Nuri.main, :short => '-m' opt :json, 'print output in JSON' - opt :plain, 'print output in plain text' + opt :color, 'enable colorized output' opt :no_push_module, 'disable automatic push module' end help, args = check_help(args) opts = process_args args, parser @@ -52,13 +47,14 @@ master.set_model opts state = master.get_state opts state.accept(Sfp::Helper::Sfp2Ruby) if opts[:json] - puts (opts[:plain] ? JSON.generate(state) : CodeRay.encode(JSON.pretty_generate(state), :json, :terminal)) + puts (!opts[:color] ? JSON.generate(state) : CodeRay.encode(JSON.pretty_generate(state), :json, :terminal)) else - puts (opts[:plain] ? YAML.dump(state) : CodeRay.encode(YAML.dump(state), :yaml, :terminal)) + puts (!opts[:color] ? YAML.dump(state) : CodeRay.encode(YAML.dump(state), :yaml, :terminal)) + end else $stderr.puts "Model file '#{opts[:model_file]}' is not exist! Use \"-h\" option for more details.".red end @@ -71,20 +67,22 @@ where [options] are: EOS opt :model_file, 'file contains a model of desired state', :default => Nuri.main, :short => '-m' opt :parallel, 'generate a parallel plan', :short => '-l' opt :apply, 'generate and execute a plan', :short => '-a' - opt :plain, 'print output in plain JSON' + opt :json, 'print the plan in JSON' + opt :color, 'enable colorized output' opt :no_interactive, 'disable interactive input' opt :no_push_module, 'disable automatic push module' opt :image, 'image graph of the generated plan', :default => Dir.home + '/.nuri/plan.png' end help, args = check_help(args) opts = process_args args, parser if help parser.educate(STDOUT) + elsif File.exist?(opts[:model_file]) opts[:plan] = true opts[:push_modules] = true if !opts[:no_push_module] master = Nuri::Master.new master.set_model(opts) @@ -93,51 +91,54 @@ if plan['workflow'].length > 0 plan_file = Dir.home + '/.nuri/plan.json' File.open(plan_file, 'w') { |f| f.write(JSON.generate(plan)) } if opts[:image] - system "#{File.dirname(__FILE__)}/sfw2graph #{plan_file} #{opts[:image]}" + system "#{File.dirname(__FILE__)}/nuri-sfwgraph #{plan_file} #{opts[:image]}" end - if opts[:plain] - puts JSON.generate(plan) + if opts[:json] + json = JSON.pretty_generate(plan) + puts (opts[:color] ? CodeRay.encode(json, :json, :terminal) : json) + else actions = plan['workflow'] if plan['type'] == 'sequential' - p = 'Sequential Plan:'.yellow + p = 'Sequential Plan:' actions.each_index { |i| p += "\n#{i+1}. #{actions[i]['name']} #{JSON.generate(actions[i]['parameters'])}" } puts p else - p = 'Partial-Order Plan:'.yellow + p = 'Partial-Order Plan:' actions.each { |op| p += "\n#{op['id']+1}. #{op['name']} #{JSON.generate(op['parameters'])} (#{op['predecessors'].map{|i|i+1}}, #{op['successors'].map{|i|i+1}})" } puts p end + end if not opts[:apply] and not opts[:no_interactive] print "Execute the plan [y/N]? " opts[:apply] = true if STDIN.gets.chomp.upcase == 'Y' end if opts[:apply] - puts 'Executing the plan: '.yellow + puts 'Executing the plan:' opts[:plan] = plan if master.execute_plan(opts) - puts "Execution success!".green + puts (opts[:color] ? "Execution success.".green : "Execution success.") else - puts "Execution failed!".red + puts (opts[:color] ? "Execution failed.".red : "Execution failed.") end end elsif plan['workflow'].length == 0 - puts (opts[:plain] ? 'Goal state has been achieved.' : 'Goal state has been achieved.').green + puts (opts[:color] ? "Goal state has been achieved.".green : "Goal state has been achieved.") end else - $stderr.puts (opts[:plain] ? "No solution!".yellow : "No solution!".red) + $stderr.puts (opts[:color] ? "No solution.".red : "No solution.") end else - $stderr.puts "Model file '#{opts[:model_file]}' is not exist! Use \"-h\" option for more details.".red + $stderr.puts "Model file '#{opts[:model_file]}' is not exist! Use \"-h\" option for more details." end end def do_bsig(args=ARGV, cmd="nuri ") parser = Trollop::Parser.new do @@ -146,11 +147,11 @@ where [options] are: EOS opt :model_file, 'file contains a model of desired state', :default => Nuri.main, :short => '-m' opt :purge, 'purge existing BSig model', :short => '-g' opt :deploy, 'generate and then deploy a BSig model' - opt :plain, 'print output in plain JSON' + opt :color, 'enable colorized output' opt :no_interactive, 'disable interactive input' end help, args = check_help(args) opts = process_args args, parser @@ -161,49 +162,48 @@ opts[:parallel] = true master = Nuri::Master.new master.set_model(opts) if opts[:purge] + print "Purging Behavioural Signature model " if master.purge_bsig(opts) - puts "Purging Behavioural Signature model [OK]".green + puts (opts[:color] ? "[OK]".green : "[OK]") else - puts "Purging Behavioural Signature model [Failed]".red + puts (opts[:color] ? "[Failed]".red : "[Failed]") end + else bsig = master.get_bsig(opts) if bsig.is_a?(Hash) and bsig.length > 0 empty_local_bsig = bsig.select { |name,local_bsig| local_bsig['operators'].length <= 0 } if empty_local_bsig.length != bsig.length - if opts[:plain] - puts JSON.generate(bsig) - else - puts CodeRay.encode(JSON.pretty_generate(bsig), :json, :terminal) - end + json = JSON.pretty_generate(bsig) + puts (opts[:color] ? CodeRay.encode(json, :json, :terminal) : json) if not opts[:no_interactive] and not opts[:deploy] print "Deploy the BSig model [y/N]? " opts[:deploy] = true if STDIN.gets.chomp.upcase == 'Y' end if opts[:deploy] - puts 'Deploying the BSig model: '.yellow + print 'Deploying the BSig model ' opts[:bsig] = bsig if master.deploy_bsig(opts) - puts "Deployment success!".green + puts (opts[:color] ? "[OK]".green : "[OK]") else - puts "Deployment failed!".red + puts (opts[:color] ? "[Failed]".red : "[Failed]") end end else - puts (opts[:plain] ? 'Goal state has been achieved.' : 'Goal state has been achieved.').green + puts (opts[:color] ? "Goal state has been achieved.".green : "Goal state has been achieved.") end else - $stderr.puts (opts[:plain] ? "No solution!".yellow : "No solution!".red) + $stderr.puts (opts[:color] ? "No solution.".red : "No solution.") end end else - $stderr.puts "Model file '#{opts[:model_file]}' is not exist! Use \"-h\" option for more details.".red + $stderr.puts "Model file '#{opts[:model_file]}' is not exist! Use \"-h\" option for more details." end end def do_agent(args=ARGV, cmd="nuri ") parser = Trollop::Parser.new do @@ -214,27 +214,30 @@ upgrade upgrade agent (use SSH for remote node) start start the agent (use SSH for remote node) restart restart the agent (use SSH for remode node) stop stop the agent (use SSH for remote node) status get status (use SSH for remote node) + reset delete all modules, model (desired state), bsig-model, + and agents list state get current state model get current model bsig get current Behavioural Signature model exec <action> execute given action description <action> := <path> [param1=value1 param2=value2 ...] module get modules list - log get last 100 lines of logs + log get last 100 lines of agent's logs file list list of available agents from model file where [options] are: EOS opt :model_file, 'file contains a model of desired state', :default => Nuri.main, :short => '-m' opt :address, "address", :default => 'localhost' opt :port, "port", :default => 1314 opt :ssh_user, "SSH username", :short => '-u', :default => 'root' opt :ssh_port, "SSH port", :short => '-p', :default => '22' opt :raw, "print a RAW output" + opt :color, "enable colorized output" end help, args = check_help(args) subcommand = (args.length > 0 ? args.shift : '') opts = process_args args, parser ssh_opt = '' @@ -246,78 +249,82 @@ if help parser.educate(STDOUT) elsif `which sfpagent`.strip.length > 0 or ssh_opt.length > 0 case subcommand - when 'install' + when 'i', 'install' system("#{ssh_opt} sudo gem install sfpagent --no-ri --no-rdoc") - when 'start' + when 's', 'start' system "#{ssh_opt} sfpagent -s && sleep 5" system "#{ssh_opt} sfpagent -a" - when 'restart' + when 'r', 'restart' system "#{ssh_opt} sfpagent -r" - when 'stop' + when 't', 'stop' system("#{ssh_opt} sfpagent -t") - when 'status' + when 'a', 'status' system("#{ssh_opt} sfpagent -a") when 'upgrade' system("#{ssh_opt} sudo gem update sfpagent --no-ri --no-rdoc") - when 'state' + when 'e', 'state' code, state = get_data(opts[:address], 1314, "/state") if code == '200' and state =~ /{.*}/ state = JSON[state]['state'] if not opts[:raw] state.keys.each { |key| state.delete(key) if state[key]['_context'] != 'object' } state.accept(Sfp::Helper::Sfp2Ruby) end - puts CodeRay.encode(YAML.dump(state), :yaml, :terminal) + puts (opts[:color] ? CodeRay.encode(YAML.dump(state), :yaml, :terminal) : YAML.dump(state)) + else puts state + end - when 'model' + when 'm', 'model' code, model = get_data(opts[:address], 1314, "/model") - if code == '200' and model =~ /{.*}/ + if code == '200' and model =~ /{.+}/ model = JSON[model] if not opts[:raw] model.select! { |k,v| k[0,1] != '_' and (not v.is_a?(Hash) or v['_context'] == 'object') } model.accept(Sfp::Helper::Sfp2Ruby) end - puts CodeRay.encode(YAML.dump(model), :yaml, :terminal) - elsif code == '404' - puts "The model of desired state is not exist!" + puts (opts[:color] ? CodeRay.encode(YAML.dump(model), :yaml, :terminal) : YAML.dump(model)) + elsif code == '404' or model == '{}' + puts "Model of desired state is not exist." else $stderr.puts "Error: #{code}" end - when 'bsig' - code, json = get_data(opts[:address], 1314, "/bsig") - if code == '200' and json.length > 0 - puts CodeRay.encode(JSON.pretty_generate(JSON[json]), :json, :terminal) - elsif code == '404' - puts 'Behavioural Signature model is not exist!' + when 'b', 'bsig' + code, bsig = get_data(opts[:address], 1314, "/bsig") + if code == '200' and bsig =~ /{.+}/ + json = JSON.pretty_generate(JSON[json]) + puts (opts[:color] ? CodeRay.encode(json, :json, :terminal) : json) + elsif code == '404' or bsig == '{}' + puts 'Behavioural Signature model is not exist.' else $stderr.puts "Error: #{code}" end - when 'module' - code, json = get_data(opts[:address], 1314, "/modules") - if code == '200' and json.length >= 2 - puts CodeRay.encode(YAML.dump(JSON[json]), :yaml, :terminal) - elsif code == '404' - puts 'No module is available!' + when 'mod', 'module', 'modules' + code, modules = get_data(opts[:address], 1314, "/modules") + if code == '200' and modules =~ /{.+}/ + output = YAML.dump(JSON[modules]) + puts (opts[:color] ? CodeRay.encode(output, :yaml, :terminal) : output) + elsif code == '404' or modules == '{}' + puts 'No module is available.' else $stderr.puts "Error: #{code}" end - when 'exec', 'execute' + when 'x', 'exec', 'execute' if args.length > 0 name = args.shift name = '$.' + name if !name.isref parameters = {} args.each do |arg| @@ -326,29 +333,48 @@ parameters[arg[0]] = arg[1] end end data = { 'action' => JSON.generate({ 'name' => name, 'parameters' => parameters }) } code, _ = post_data(opts[:address], 1314, "/execute", data) - puts (code == '200' ? "Executing #{name} [OK]".green : "Executing #{name} [Failed]".red) + if opts[:color] + puts (code == '200' ? "Executing #{name} [OK]".green : "Executing #{name} [Failed]".red) + else + puts (code == '200' ? "Executing #{name} [OK]" : "Executing #{name} [Failed]") + end else $stderr.puts 'Invalid parameters (usage: agent exec <action-path> [action-arguments]).' end - when 'log' + when 'g', 'log', 'logs' puts Net::HTTP.get "#{opts[:address]}", "/log", 1314 - when 'list' + when 'l', 'list' get_agents(opts).each { |name,model| puts "#{name} address=#{model['sfpAddress']} port=#{model['sfpPort']}" } - when 'help' + when 'reset' + codes = [] + codes[0], _ = delete_data(opts[:address], 1314, "/bsig") + codes[1], _ = delete_data(opts[:address], 1314, "/model/cache") + codes[2], _ = delete_data(opts[:address], 1314, "/model") + codes[3], _ = delete_data(opts[:address], 1314, "/modules") + codes[4], _ = delete_data(opts[:address], 1314, "/agents") + + failed = codes.index { |x| x != '200' } + if opts[:color] + puts (failed ? "Reset agent [Failed]".red : "Reset agent [OK]".green) + else + puts (failed ? "Reset agent [Failed]" : "Reset agent [OK]") + end + + when 'h', 'help' parser.educate(STDOUT) else - $stderr.puts 'Unrecognized command! Use \"-h\" to print available commands.'.red + $stderr.puts 'Unrecognized command! Use -h to print available commands.' end else - $stderr.puts 'sfpagent gem is not installed!'.red + $stderr.puts 'sfpagent gem is not installed!' end end def do_edit(args=ARGV) file = (args[0].nil? ? Nuri.main : args[0].to_s) @@ -380,11 +406,12 @@ end agents end def do_console - banner = <<-EOS + parser = Trollop::Parser.new do + banner <<-EOS Usage: <command> [options] when <command> is: state get current state plan generate a plan bsig deployment with distributed mechanism @@ -392,16 +419,17 @@ edit edit file help print this help exit exit this console EOS + end username = `whoami`.strip puts About loop do begin - print "nuri@#{username}> ".green + print "nuri@#{username}> ".cyan begin input = STDIN.gets raise Exception if input.nil? rescue Exception puts '' @@ -432,17 +460,17 @@ when 'cd' Dir.chdir(args[0].to_s) when 'pwd' puts Dir.pwd when 'ls' - system "ls --color #{args.join(" ")}" + system "ls #{args.join(" ")}" when 'help' - puts banner + parser.educate(STDOUT) when 'version', '-v' puts About else - $stderr.puts 'Unrecognized command! Use \"-h\" option to print available commands.'.red + $stderr.puts 'Unrecognized command! Use -h option to print available commands.' end end rescue Exception => e $stderr.puts "#{e}\n#{e.backtrace.join("\n")}" end @@ -456,11 +484,11 @@ Usage: #{cmd}state [options] where [options] are: EOS opt :model_file, 'file contains a model of desired state', :default => Nuri.main, :short => '-m' opt :json, 'print output in JSON' - opt :plain, 'print output in plain format' + opt :color, 'enable colorized output' end help, args = check_help(args) opts = process_args args, parser if help @@ -473,17 +501,17 @@ model.accept(ParentEliminator) model.select! { |k,v| k[0,1] != '_' and (not v.is_a?(Hash) or v['_context'] == 'object') } model.accept(Sfp::Helper::Sfp2Ruby) if opts[:json] - puts (opts[:plain] ? JSON.generate(model) : CodeRay.encode(JSON.pretty_generate(model), :json, :terminal)) + puts (!opts[:color] ? JSON.generate(model) : CodeRay.encode(JSON.pretty_generate(model), :json, :terminal)) else - puts (opts[:plain] ? YAML.dump(model) : CodeRay.encode(YAML.dump(model), :yaml, :terminal)) + puts (!opts[:color] ? YAML.dump(model) : CodeRay.encode(YAML.dump(model), :yaml, :terminal)) end else - $stderr.puts "Model file '#{opts[:model_file]}' is not exist! Use \"-h\" option for more details.".red + $stderr.puts "Model file '#{opts[:model_file]}' is not exist! Use \"-h\" option for more details." end end @@ -501,22 +529,22 @@ EOS if ARGV.length > 0 success = false case ARGV.shift - when 'state' + when 's', 'state' do_state - when 'plan' + when 'p', 'plan' do_plan - when 'bsig' + when 'b', 'bsig' do_bsig - when 'agent' + when 'a', 'agent' do_agent - when 'console' + when 'c', 'console' do_console - when 'edit' + when 'e', 'edit' do_edit - when 'model' + when 'm', 'model' do_model else puts banner end else