vop 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|