vop 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +66 -0
- data/README.md +2 -0
- data/Rakefile +6 -0
- data/bin/vop.rb +28 -0
- data/bin/vop.sh +4 -0
- data/exe/vop +28 -0
- data/lib/vop.rb +242 -0
- data/lib/vop/command.rb +168 -0
- data/lib/vop/command_loader.rb +47 -0
- data/lib/vop/entity.rb +61 -0
- data/lib/vop/loader.rb +35 -0
- data/lib/vop/plugin.rb +141 -0
- data/lib/vop/plugin_loader.rb +88 -0
- data/lib/vop/plugins/core/commands/clear_context.rb +3 -0
- data/lib/vop/plugins/core/commands/collect_contributions.rb +31 -0
- data/lib/vop/plugins/core/commands/edit.rb +12 -0
- data/lib/vop/plugins/core/commands/help.rb +38 -0
- data/lib/vop/plugins/core/commands/identity.rb +4 -0
- data/lib/vop/plugins/core/commands/list_contributors.rb +8 -0
- data/lib/vop/plugins/core/commands/list_entities.rb +3 -0
- data/lib/vop/plugins/core/commands/pry.rb +9 -0
- data/lib/vop/plugins/core/commands/reset.rb +5 -0
- data/lib/vop/plugins/core/commands/show_context.rb +3 -0
- data/lib/vop/plugins/core/commands/source.rb +5 -0
- data/lib/vop/plugins/core/commands/system_call.rb +5 -0
- data/lib/vop/plugins/core/core.plugin +4 -0
- data/lib/vop/plugins/core/helpers/command_loader/command_syntax.rb +45 -0
- data/lib/vop/plugins/core/helpers/command_loader/contributions.rb +28 -0
- data/lib/vop/plugins/core/helpers/command_loader/entities.rb +57 -0
- data/lib/vop/plugins/core/helpers/helper.rb +3 -0
- data/lib/vop/plugins/core/helpers/plugin_loader/plugin_syntax.rb +0 -0
- data/lib/vop/plugins/meta/commands/add_search_path.rb +6 -0
- data/lib/vop/plugins/meta/commands/delete_plugin.rb +13 -0
- data/lib/vop/plugins/meta/commands/list_commands.rb +17 -0
- data/lib/vop/plugins/meta/commands/list_plugins.rb +8 -0
- data/lib/vop/plugins/meta/commands/new_command.rb +14 -0
- data/lib/vop/plugins/meta/commands/new_plugin.rb +25 -0
- data/lib/vop/plugins/meta/commands/show_search_path.rb +3 -0
- data/lib/vop/plugins/meta/commands/who_provides.rb +5 -0
- data/lib/vop/plugins/meta/meta.plugin +1 -0
- data/lib/vop/plugins/ssh/commands/scp.rb +11 -0
- data/lib/vop/plugins/ssh/commands/ssh.rb +19 -0
- data/lib/vop/plugins/ssh/ssh.plugin +1 -0
- data/lib/vop/shell.rb +52 -0
- data/lib/vop/shell/backend.rb +28 -0
- data/lib/vop/shell/base_shell.rb +112 -0
- data/lib/vop/shell/formatter.rb +46 -0
- data/lib/vop/shell/vop_shell_backend.rb +257 -0
- data/lib/vop/version.rb +3 -0
- data/vop.gemspec +31 -0
- metadata +223 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
description "initializes a new plugin (folder)"
|
2
|
+
|
3
|
+
param! 'name'
|
4
|
+
param! 'path', :description => 'the path in which to create the new plugin.'
|
5
|
+
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
run do |params|
|
9
|
+
raise "no such path: #{params['path']}" unless File.exists? params['path']
|
10
|
+
|
11
|
+
# a plugin is a directory
|
12
|
+
plugin_path = File.join(params['path'], params['name'])
|
13
|
+
Dir.mkdir(plugin_path)
|
14
|
+
|
15
|
+
# with subfolders for commands and helpers
|
16
|
+
%w|commands helpers|.each do |thing|
|
17
|
+
Dir.mkdir(File.join(plugin_path, thing))
|
18
|
+
end
|
19
|
+
|
20
|
+
# and a metadata file called '<name>.plugin'
|
21
|
+
plugin_file = params['name'] + '.plugin'
|
22
|
+
FileUtils.touch(File.join(plugin_path, plugin_file))
|
23
|
+
|
24
|
+
@op.reset
|
25
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
dependency :core
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'net/scp'
|
2
|
+
|
3
|
+
param! 'machine'
|
4
|
+
param 'user'
|
5
|
+
param! 'local_path'
|
6
|
+
param! 'remote_path'
|
7
|
+
|
8
|
+
run do |machine, local_path, remote_path, params|
|
9
|
+
user = params.has_key?('user') ? params['user'] : ENV['USER']
|
10
|
+
Net::SCP.upload!(params['machine'], user, local_path, remote_path)
|
11
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'net/ssh'
|
2
|
+
|
3
|
+
param! 'machine'
|
4
|
+
param! 'command', :default_param => true
|
5
|
+
param 'user' #, :default => ENV['USER']
|
6
|
+
param 'key_file', :multi => true
|
7
|
+
|
8
|
+
run do |params|
|
9
|
+
machine_name = params['machine']
|
10
|
+
user = params.has_key?('user') ? params['user'] : ENV['USER']
|
11
|
+
|
12
|
+
options = {}
|
13
|
+
if params.has_key? 'key_file'
|
14
|
+
options[:keys] = params['key_file']
|
15
|
+
end
|
16
|
+
Net::SSH.start(machine_name, user, options) do |ssh|
|
17
|
+
ssh.exec! params['command']
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
depends :core
|
data/lib/vop/shell.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'vop'
|
2
|
+
require 'vop/shell/vop_shell_backend'
|
3
|
+
require 'vop/shell/base_shell'
|
4
|
+
|
5
|
+
require 'docopt'
|
6
|
+
require 'pp'
|
7
|
+
|
8
|
+
module Vop
|
9
|
+
|
10
|
+
class Shell
|
11
|
+
|
12
|
+
USAGE = <<DOCOPT
|
13
|
+
virtualop
|
14
|
+
|
15
|
+
Usage:
|
16
|
+
vop [options]
|
17
|
+
|
18
|
+
Options:
|
19
|
+
-h --help show this help screen
|
20
|
+
-v --verbose enable debug output
|
21
|
+
-e --execute=<command> to run a command directly
|
22
|
+
|
23
|
+
DOCOPT
|
24
|
+
|
25
|
+
attr_reader :options
|
26
|
+
attr_reader :op
|
27
|
+
|
28
|
+
def initialize(vop = nil, options = {})
|
29
|
+
@op = vop || Vop.new
|
30
|
+
@options = options
|
31
|
+
|
32
|
+
backend = VopShellBackend.new(@op, :color_prompt => true)
|
33
|
+
@base_shell = BaseShell.new(backend)
|
34
|
+
end
|
35
|
+
|
36
|
+
def execute(string)
|
37
|
+
@base_shell.backend.process_input(string)
|
38
|
+
end
|
39
|
+
|
40
|
+
def run_cli
|
41
|
+
@base_shell.run
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.setup()
|
45
|
+
options = Docopt::docopt(USAGE, {:help => true})
|
46
|
+
|
47
|
+
vop = Vop.new(options)
|
48
|
+
return Shell.new(vop, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# responsible for what should happen when the user interacts with the shell
|
2
|
+
# provides tab completion options and processes the user's input
|
3
|
+
class Backend
|
4
|
+
|
5
|
+
# is called whenever the user submits a command (hitting enter)
|
6
|
+
def process_input(command_line)
|
7
|
+
raise "not implemented in abstract Backend!"
|
8
|
+
end
|
9
|
+
|
10
|
+
# is called whenever the user requests tab completion
|
11
|
+
# should return an array of completion proposals
|
12
|
+
def complete(word)
|
13
|
+
raise "not implemented in abstract Backend!"
|
14
|
+
end
|
15
|
+
|
16
|
+
def prompt
|
17
|
+
">"
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_ctrl_c
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def show_banner
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'readline'
|
2
|
+
|
3
|
+
# This class is an abstract implementation of a command shell
|
4
|
+
# It handles command completion and history functions.
|
5
|
+
# For the actual business logic, you need to pass it an implementation of ShellBackend
|
6
|
+
class BaseShell
|
7
|
+
attr_reader :backend
|
8
|
+
|
9
|
+
def initialize(backend)
|
10
|
+
@logger = $logger
|
11
|
+
@backend = backend
|
12
|
+
|
13
|
+
at_exit { console.close }
|
14
|
+
|
15
|
+
trap("INT") {
|
16
|
+
Thread.kill(@thread)
|
17
|
+
@backend.process_ctrl_c
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
class SimpleConsole
|
22
|
+
def initialize(input = $stdin)
|
23
|
+
@input = input
|
24
|
+
end
|
25
|
+
|
26
|
+
def readline
|
27
|
+
begin
|
28
|
+
line = @input.readline
|
29
|
+
line.chomp! if line
|
30
|
+
line
|
31
|
+
rescue EOFError
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def close
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class ReadlineConsole
|
41
|
+
HISTORY_FILE = ".vop_history"
|
42
|
+
MAX_HISTORY = 200
|
43
|
+
|
44
|
+
def history_path
|
45
|
+
File.join(ENV['HOME'] || ENV['USERPROFILE'], HISTORY_FILE)
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(shell)
|
49
|
+
@shell = shell
|
50
|
+
|
51
|
+
if File.exist?(history_path)
|
52
|
+
hist = File.readlines(history_path).map{|line| line.chomp}
|
53
|
+
Readline::HISTORY.push(*hist)
|
54
|
+
end
|
55
|
+
|
56
|
+
#Readline.basic_word_break_characters = " \t\n\\`@><=;|&{([+*%"
|
57
|
+
|
58
|
+
# see http://stackoverflow.com/questions/13876024/how-to-write-a-ruby-command-line-app-that-supports-tab-completion#13876556
|
59
|
+
Readline.completer_word_break_characters = ""
|
60
|
+
|
61
|
+
Readline.completion_append_character = nil
|
62
|
+
Readline.completion_proc = @shell.backend.method(:complete).to_proc
|
63
|
+
end
|
64
|
+
|
65
|
+
def close
|
66
|
+
open(history_path, "wb") do |f|
|
67
|
+
history = Readline::HISTORY.to_a
|
68
|
+
if history.size > MAX_HISTORY
|
69
|
+
history = history[history.size - MAX_HISTORY, MAX_HISTORY]
|
70
|
+
end
|
71
|
+
history.each{|line| f.puts(line)}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def readline
|
76
|
+
line = Readline.readline(@shell.backend.prompt, true)
|
77
|
+
Readline::HISTORY.pop if /^\s*$/ =~ line
|
78
|
+
line
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def console
|
83
|
+
@console ||= $stdin.tty? ? ReadlineConsole.new(self) : SimpleConsole.new
|
84
|
+
end
|
85
|
+
|
86
|
+
def run
|
87
|
+
backend.show_banner
|
88
|
+
loop do
|
89
|
+
@thread = Thread.new {
|
90
|
+
line = console.readline
|
91
|
+
|
92
|
+
if line
|
93
|
+
backend.process_input line
|
94
|
+
end
|
95
|
+
}
|
96
|
+
begin
|
97
|
+
@thread.join
|
98
|
+
rescue
|
99
|
+
error = $!
|
100
|
+
if error == "exit"
|
101
|
+
Kernel.exit
|
102
|
+
else
|
103
|
+
$stderr.puts "error: >>#{error}<<"
|
104
|
+
$stderr.puts error.backtrace.join("\n")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
$stderr.puts "Exiting shell..."
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'terminal-table'
|
3
|
+
|
4
|
+
def format_output(command, data)
|
5
|
+
if data.is_a? Array
|
6
|
+
first_row = data.first
|
7
|
+
if first_row.is_a? Hash
|
8
|
+
# show all columns unless defined otherwise in the command
|
9
|
+
columns_to_display = first_row.keys
|
10
|
+
if command.show_options.include? :columns
|
11
|
+
columns_to_display = command.show_options[:columns]
|
12
|
+
end
|
13
|
+
column_headers = columns_to_display
|
14
|
+
|
15
|
+
rearranged = [] # array of hashes -> array of arrays
|
16
|
+
data.each do |row|
|
17
|
+
values = []
|
18
|
+
columns_to_display.each do |key|
|
19
|
+
values << row[key]
|
20
|
+
end
|
21
|
+
rearranged << values
|
22
|
+
end
|
23
|
+
|
24
|
+
begin
|
25
|
+
rearranged.sort_by! { |row| row.first }
|
26
|
+
rescue
|
27
|
+
puts "[WARN] ran into trouble sorting the result (by the first column); results may be not quite sorted."
|
28
|
+
begin
|
29
|
+
rearranged.sort_by! { |row| row.first || "zaphod" }
|
30
|
+
rescue
|
31
|
+
puts "[SHRUG] could not sort even when accounting for potential nil values, giving up."
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
puts Terminal::Table.new rows: rearranged, headings: column_headers
|
36
|
+
else
|
37
|
+
puts data.join("\n")
|
38
|
+
end
|
39
|
+
elsif data.is_a? Hash
|
40
|
+
data.each do |k,v|
|
41
|
+
puts "#{k} : #{v}"
|
42
|
+
end
|
43
|
+
else
|
44
|
+
puts data
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'vop/shell/backend'
|
2
|
+
require 'vop/shell/formatter'
|
3
|
+
|
4
|
+
class VopShellBackend < Backend
|
5
|
+
|
6
|
+
def initialize(op, options = {})
|
7
|
+
@op = op
|
8
|
+
@options = options
|
9
|
+
@local_context = {}
|
10
|
+
|
11
|
+
reset_to_command_mode
|
12
|
+
end
|
13
|
+
|
14
|
+
def context
|
15
|
+
@local_context
|
16
|
+
end
|
17
|
+
|
18
|
+
def reset_to_command_mode
|
19
|
+
# this shell has two modes that determine the available tab completion proposals
|
20
|
+
# command_mode
|
21
|
+
# we're waiting for the user to pick a command that should be executed
|
22
|
+
# parameter mode
|
23
|
+
# the command to execute has already been selected, but the user needs to specify additional parameters
|
24
|
+
# we'll start in the mode where no command has been selected yet
|
25
|
+
@command_selected = nil
|
26
|
+
|
27
|
+
# if the user selected a command already, we'll have to collect parameters for this command until
|
28
|
+
# we've got all mandatory parameters so that we can execute the command
|
29
|
+
@collected_values = Hash.new { |h,k| h[k] = [] }
|
30
|
+
|
31
|
+
@missing_params = []
|
32
|
+
|
33
|
+
@current_param = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def process_ctrl_c
|
37
|
+
puts "\n"
|
38
|
+
if @command_selected
|
39
|
+
reset_to_command_mode
|
40
|
+
else
|
41
|
+
Kernel.exit
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_prompt(p)
|
46
|
+
@prompt = p
|
47
|
+
end
|
48
|
+
|
49
|
+
def prompt
|
50
|
+
@command_selected && @current_param ?
|
51
|
+
"#{@command_selected.short_name}.#{@current_param[:name]} ? " :
|
52
|
+
@prompt || '>> '
|
53
|
+
end
|
54
|
+
|
55
|
+
def show_banner
|
56
|
+
s = @options[:banner]
|
57
|
+
puts s if s
|
58
|
+
end
|
59
|
+
|
60
|
+
def complete(word)
|
61
|
+
$logger.debug "completing #{word}"
|
62
|
+
|
63
|
+
command_list = @op.commands.keys
|
64
|
+
|
65
|
+
list = []
|
66
|
+
|
67
|
+
parts = nil
|
68
|
+
|
69
|
+
if @command_selected
|
70
|
+
#$logger.debug("asking for lookup values for command '#{@command_selected.name}' and param '#{@current_param[:name]}'")
|
71
|
+
list = @command_selected.lookup(@current_param[:name], @collected_values)
|
72
|
+
else
|
73
|
+
begin
|
74
|
+
(parts, command, param_values) = parse_command_string(word)
|
75
|
+
|
76
|
+
if command
|
77
|
+
$logger.debug "command selected (#{command.name}), fetching param lookups"
|
78
|
+
|
79
|
+
# all lookup values for a default_param (if exists)
|
80
|
+
if command.default_param
|
81
|
+
list += command.lookup(command.default_param[:name], @collected_values)
|
82
|
+
$logger.debug "added lookups for default param, list now #{list.length} elements"
|
83
|
+
end
|
84
|
+
|
85
|
+
# names of all params that have not been specified yet or are :multi
|
86
|
+
command.params.each do |param|
|
87
|
+
if not param_values.keys.include? param[:name] || param[:multi]
|
88
|
+
list << param[:name]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
else
|
93
|
+
$logger.debug "no command selected yet, returning command list"
|
94
|
+
list = command_list
|
95
|
+
end
|
96
|
+
rescue => e
|
97
|
+
$logger.debug "can't parse >>#{word}<< : #{e.message}"
|
98
|
+
$logger.debug e.backtrace
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
the_filter = parts ? parts.last : word
|
103
|
+
if the_filter
|
104
|
+
$logger.debug "filtering completion list against : #{the_filter}"
|
105
|
+
list.delete_if do |x|
|
106
|
+
x[0...the_filter.size] != the_filter
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
prefix = ''
|
111
|
+
if parts
|
112
|
+
prefix = parts.length > 1 ? parts[0..-2].join(" ").strip : ''
|
113
|
+
end
|
114
|
+
if $logger.debug?
|
115
|
+
more_text = list.length > 1 ? " (and #{list.length-1} more)" : ''
|
116
|
+
$logger.debug "completion from >#{word}< to #{prefix} + #{list.first}#{more_text}"
|
117
|
+
end
|
118
|
+
list.map do |x|
|
119
|
+
[prefix, x].join(' ').strip
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def parse_command_string(command_line, presets = {})
|
124
|
+
parts = command_line.split.map { |x| x.chomp.strip }
|
125
|
+
(command_name, *params) = parts
|
126
|
+
command = @op.commands[command_name]
|
127
|
+
|
128
|
+
param_values = Hash.new { |h,k| h[k] = [] }
|
129
|
+
presets.each do |k,v|
|
130
|
+
param_values[k] = [v]
|
131
|
+
end
|
132
|
+
if params
|
133
|
+
params.each do |param|
|
134
|
+
if param =~ /(.+?)=(.+)/ then
|
135
|
+
# --> named param
|
136
|
+
key = $1
|
137
|
+
value = $2
|
138
|
+
else
|
139
|
+
# --> unnamed param
|
140
|
+
value = param
|
141
|
+
if command
|
142
|
+
default_param = command.default_param
|
143
|
+
if default_param != nil then
|
144
|
+
key = default_param[:name]
|
145
|
+
$logger.debug "collecting value '#{value}' for default param '#{default_param[:name]}'"
|
146
|
+
else
|
147
|
+
$logger.debug "ignoring param '#{value}' because there's no default param"
|
148
|
+
end
|
149
|
+
else
|
150
|
+
# can't process an unnamed param unless we've got a command
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
if key
|
155
|
+
param_values[key] << value
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
[parts, command, param_values]
|
160
|
+
end
|
161
|
+
|
162
|
+
def process_input(command_line)
|
163
|
+
$logger.debug "+++ process_input #{command_line} +++"
|
164
|
+
if @command_selected
|
165
|
+
# we're in parameter processing mode - so check which parameter
|
166
|
+
# we've got now and switch modes if necessary
|
167
|
+
|
168
|
+
# we might have been waiting for multiple param values - check if the user finished
|
169
|
+
# adding values by entering an empty string as value
|
170
|
+
if @current_param && (@current_param[:multi] and command_line == "") then
|
171
|
+
@missing_params.shift
|
172
|
+
execute_command_if_possible
|
173
|
+
else
|
174
|
+
# TODO check +command_line+ against lookups/general validity?
|
175
|
+
@collected_values[@current_param[:name]] << command_line
|
176
|
+
if @current_param[:multi] then
|
177
|
+
$logger.debug "param '#{@current_param[:name]}' expects multiple values...deferring mode switching"
|
178
|
+
else
|
179
|
+
@missing_params.shift
|
180
|
+
execute_command_if_possible
|
181
|
+
end
|
182
|
+
end
|
183
|
+
else
|
184
|
+
(unused, @command_selected, values) = parse_command_string(command_line, @local_context)
|
185
|
+
|
186
|
+
if @command_selected
|
187
|
+
values.each do |key, value_list|
|
188
|
+
begin
|
189
|
+
value_list.each do |value|
|
190
|
+
@current_param = @command_selected.param(key)
|
191
|
+
if @current_param
|
192
|
+
@collected_values[@current_param[:name]] << value
|
193
|
+
else
|
194
|
+
# TODO handle extra params?
|
195
|
+
end
|
196
|
+
end
|
197
|
+
rescue Exception => ex
|
198
|
+
# TODO broken (error: undefined method `accepts_extra_params' for Vop::Command machines.select_machine:Vop::Command)
|
199
|
+
if @command_selected && false && @command_selected.accepts_extra_params
|
200
|
+
puts "collecting value for extra param : #{key} => #{value}"
|
201
|
+
@collected_values["extra_params"] = {} unless @collected_values.has_key?("extra_params")
|
202
|
+
@collected_values["extra_params"][key] = Array.new if @collected_values["extra_params"][key] == nil
|
203
|
+
@collected_values["extra_params"][key] << value
|
204
|
+
else
|
205
|
+
#puts "ignoring parameter value '#{value_list}' for param '#{key}' : " + ex.to_s
|
206
|
+
raise ex
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
execute_command_if_possible
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def execute_command_if_possible
|
218
|
+
mandatory = @command_selected.mandatory_params
|
219
|
+
@missing_params = mandatory.select { |p| ! @collected_values.include? p[:name] }
|
220
|
+
|
221
|
+
if @missing_params.size > 0
|
222
|
+
@current_param = @missing_params.first
|
223
|
+
else
|
224
|
+
execute_command
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def execute_command
|
229
|
+
command = @command_selected
|
230
|
+
$logger.debug "vop_shell_backend executing command '#{command.short_name}'"
|
231
|
+
|
232
|
+
begin
|
233
|
+
extras = {
|
234
|
+
'shell' => self
|
235
|
+
}
|
236
|
+
(response, context) = @op.execute_command(command.short_name, @collected_values, extras)
|
237
|
+
|
238
|
+
if command.short_name == 'exit'
|
239
|
+
$logger.info "exiting on user request"
|
240
|
+
Kernel.exit(0)
|
241
|
+
end
|
242
|
+
|
243
|
+
if context
|
244
|
+
if context['prompt']
|
245
|
+
set_prompt context['prompt']
|
246
|
+
end
|
247
|
+
|
248
|
+
@local_context.merge! context
|
249
|
+
end
|
250
|
+
|
251
|
+
format_output(command, response)
|
252
|
+
ensure
|
253
|
+
reset_to_command_mode
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|