a4tools 1.2.7
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/.bundle/install.log +38 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +38 -0
- data/a4tools.gemspec +38 -0
- data/bin/deploy_latest_clients +32 -0
- data/bin/devsite_config_server +48 -0
- data/bin/netshell +23 -0
- data/bin/update_server +101 -0
- data/bin/usher +54 -0
- data/lib/a4tools.rb +61 -0
- data/lib/a4tools/version.rb +3 -0
- data/lib/acres_client.rb +376 -0
- data/lib/clients/caching_client.rb +151 -0
- data/lib/clients/deployment_client.rb +53 -0
- data/lib/clients/kai_config_client.rb +39 -0
- data/lib/clients/usher_client.rb +72 -0
- data/lib/clients/usher_mgmt_client.rb +201 -0
- data/lib/event_manager.rb +24 -0
- data/lib/events.json +1 -0
- data/lib/net_shell/builtin_command.rb +312 -0
- data/lib/net_shell/builtin_commands/build.rb +251 -0
- data/lib/net_shell/builtin_commands/cd.rb +12 -0
- data/lib/net_shell/builtin_commands/connect.rb +122 -0
- data/lib/net_shell/builtin_commands/deploy.rb +280 -0
- data/lib/net_shell/builtin_commands/disconnect.rb +15 -0
- data/lib/net_shell/builtin_commands/excerpt.rb +97 -0
- data/lib/net_shell/builtin_commands/exit.rb +7 -0
- data/lib/net_shell/builtin_commands/get.rb +38 -0
- data/lib/net_shell/builtin_commands/help.rb +40 -0
- data/lib/net_shell/builtin_commands/host.rb +126 -0
- data/lib/net_shell/builtin_commands/inject.rb +42 -0
- data/lib/net_shell/builtin_commands/jsoncache.rb +80 -0
- data/lib/net_shell/builtin_commands/kai_event.rb +151 -0
- data/lib/net_shell/builtin_commands/persist.rb +24 -0
- data/lib/net_shell/builtin_commands/pwd.rb +6 -0
- data/lib/net_shell/builtin_commands/recap.rb +188 -0
- data/lib/net_shell/builtin_commands/references.rb +63 -0
- data/lib/net_shell/builtin_commands/select.rb +36 -0
- data/lib/net_shell/builtin_commands/send.rb +74 -0
- data/lib/net_shell/builtin_commands/set.rb +29 -0
- data/lib/net_shell/builtin_commands/show.rb +183 -0
- data/lib/net_shell/builtin_commands/site.rb +122 -0
- data/lib/net_shell/builtin_commands/ssh.rb +62 -0
- data/lib/net_shell/builtin_commands/talk.rb +90 -0
- data/lib/net_shell/builtin_commands/translate.rb +45 -0
- data/lib/net_shell/builtin_commands/unset.rb +14 -0
- data/lib/net_shell/builtin_commands/usher.rb +55 -0
- data/lib/net_shell/builtin_commands/usher_device.rb +39 -0
- data/lib/net_shell/builtin_commands/usher_site.rb +245 -0
- data/lib/net_shell/builtin_commands/usherm_connect.rb +21 -0
- data/lib/net_shell/colors.rb +149 -0
- data/lib/net_shell/command.rb +97 -0
- data/lib/net_shell/io.rb +132 -0
- data/lib/net_shell/net_shell.rb +396 -0
- data/lib/net_shell/prompt.rb +335 -0
- data/lib/object_builder/definitions/app_info_for_script.rb +83 -0
- data/lib/object_builder/definitions/connection_request.rb +28 -0
- data/lib/object_builder/definitions/device_info_for_system.rb +37 -0
- data/lib/object_builder/object_builder.rb +145 -0
- data/lib/talk.json +1 -0
- data/lib/talk_consumer.rb +235 -0
- metadata +279 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
category "Usher"
|
2
|
+
description "Connect to UsherM"
|
3
|
+
usage "[username] [password]"
|
4
|
+
|
5
|
+
help <<-EOS
|
6
|
+
Connects to UsherM server. This connection is not related to the connection opened in #{"connect".style(:command)}; only the #{"usherm".style(:command)} family of commands make use of this connection.
|
7
|
+
|
8
|
+
If username and password are omitted, they are defaulted from the #{"usherm_user".style(:environment)} and #{"usherm_pass".style(:environment)} environment variables, if set.
|
9
|
+
|
10
|
+
If the #{"usherm_user".style(:environment)} and #{"usherm_pass".style(:environment)} environment variables are set when the shell starts, this connection is created automatically.
|
11
|
+
EOS
|
12
|
+
|
13
|
+
run do
|
14
|
+
cmd_user = args[1] rescue nil
|
15
|
+
cmd_pass = args[2] rescue nil
|
16
|
+
username = cmd_user || @shell.get_env(:usherm_user)
|
17
|
+
password = cmd_pass || @shell.get_env(:usherm_pass)
|
18
|
+
return show_error(usage_msg) unless password
|
19
|
+
@shell.set_client(:usherm, UsherMgmtClient.new(nil, username, password))
|
20
|
+
""
|
21
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
|
3
|
+
class String
|
4
|
+
def style_category
|
5
|
+
return self.colorize(:blue).bold
|
6
|
+
end
|
7
|
+
|
8
|
+
def style_class
|
9
|
+
return self.colorize(:light_black) if self == "none"
|
10
|
+
|
11
|
+
comps = split(".")
|
12
|
+
(comps.map do |comp|
|
13
|
+
if comp == comps.last then
|
14
|
+
comp.colorize(:red).bold
|
15
|
+
else
|
16
|
+
comp.colorize(:light_black)
|
17
|
+
end
|
18
|
+
|
19
|
+
end).join(".")
|
20
|
+
end
|
21
|
+
|
22
|
+
def style_constant_name
|
23
|
+
self.colorize(:red)
|
24
|
+
end
|
25
|
+
|
26
|
+
def style_constant_value
|
27
|
+
self.colorize(:green).bold
|
28
|
+
end
|
29
|
+
|
30
|
+
def style_collection_name
|
31
|
+
comps = split(".")
|
32
|
+
(comps.map do |comp|
|
33
|
+
if comp == comps.last then
|
34
|
+
comp.colorize(:green).bold
|
35
|
+
else
|
36
|
+
comp.colorize(:light_black)
|
37
|
+
end
|
38
|
+
|
39
|
+
end).join(".")
|
40
|
+
end
|
41
|
+
|
42
|
+
def style_protocol_name
|
43
|
+
self.colorize(:light_blue).bold
|
44
|
+
end
|
45
|
+
|
46
|
+
def style_method_name
|
47
|
+
self.colorize(:blue)
|
48
|
+
end
|
49
|
+
|
50
|
+
def style_field_name
|
51
|
+
self.colorize(:red)
|
52
|
+
end
|
53
|
+
|
54
|
+
def style_field_datatype
|
55
|
+
self.colorize(:magenta)
|
56
|
+
end
|
57
|
+
|
58
|
+
def style_origin
|
59
|
+
self.colorize(:magenta)
|
60
|
+
end
|
61
|
+
|
62
|
+
def style_command
|
63
|
+
self.colorize(:magenta).bold
|
64
|
+
end
|
65
|
+
|
66
|
+
def style_environment
|
67
|
+
self.colorize(:red)
|
68
|
+
end
|
69
|
+
|
70
|
+
def style_datacenter
|
71
|
+
self.colorize(:green)
|
72
|
+
end
|
73
|
+
|
74
|
+
def style_host
|
75
|
+
self.colorize(:red)
|
76
|
+
end
|
77
|
+
|
78
|
+
def style_ip
|
79
|
+
self.colorize(:blue)
|
80
|
+
end
|
81
|
+
|
82
|
+
def style_service
|
83
|
+
self.colorize(:magenta)
|
84
|
+
end
|
85
|
+
|
86
|
+
def style_product
|
87
|
+
self.colorize(:red).bold
|
88
|
+
end
|
89
|
+
|
90
|
+
def style_event_code
|
91
|
+
self.colorize(:blue).bold
|
92
|
+
end
|
93
|
+
|
94
|
+
def style_event_key
|
95
|
+
self.colorize(:red)
|
96
|
+
end
|
97
|
+
|
98
|
+
def style_error
|
99
|
+
self.colorize(:red).bold
|
100
|
+
end
|
101
|
+
|
102
|
+
def style_userdefined
|
103
|
+
self.colorize(:light_black).bold
|
104
|
+
end
|
105
|
+
|
106
|
+
def style_id
|
107
|
+
self.colorize(:green)
|
108
|
+
end
|
109
|
+
|
110
|
+
def style_build_name
|
111
|
+
self.bold
|
112
|
+
end
|
113
|
+
|
114
|
+
def style_branch
|
115
|
+
self.colorize(:red)
|
116
|
+
end
|
117
|
+
|
118
|
+
def style_timestamp
|
119
|
+
self.colorize(:blue)
|
120
|
+
end
|
121
|
+
|
122
|
+
def style_author
|
123
|
+
self.colorize(:light_black)
|
124
|
+
end
|
125
|
+
|
126
|
+
def style_cidr
|
127
|
+
ip, whack = self.split("/")
|
128
|
+
return self.colorize(:red) if ip.nil? or whack.nil?
|
129
|
+
ip.colorize(:red) + "/" + whack.colorize(:magenta)
|
130
|
+
end
|
131
|
+
|
132
|
+
def style_heading
|
133
|
+
self.bold
|
134
|
+
end
|
135
|
+
|
136
|
+
def style_client
|
137
|
+
self.bold
|
138
|
+
end
|
139
|
+
|
140
|
+
def style(type)
|
141
|
+
method = ("style_" + type.to_s).to_sym
|
142
|
+
return send(method) if self.methods.include?(method)
|
143
|
+
self
|
144
|
+
end
|
145
|
+
|
146
|
+
def unstyle
|
147
|
+
self.uncolorize
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'trollop'
|
2
|
+
|
3
|
+
module A4Tools
|
4
|
+
class Command
|
5
|
+
attr_accessor :args, :input, :output, :error, :shell
|
6
|
+
attr_reader :status
|
7
|
+
|
8
|
+
def initialize(args, input=nil, output=nil, error=nil, shell=nil)
|
9
|
+
@input = input || StandardInput.new
|
10
|
+
@output = output || StandardOutput.new
|
11
|
+
@error = error || StandardOutput.new
|
12
|
+
@args = args
|
13
|
+
@shell = shell
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_built_in?
|
17
|
+
built_in_methods.include? args[0].to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_built_in
|
21
|
+
built_in = @shell.built_in(args[0]).new(@shell)
|
22
|
+
built_in.execute(@input, @output, @error, args)
|
23
|
+
|
24
|
+
@status = built_in.status
|
25
|
+
end
|
26
|
+
|
27
|
+
def built_in_methods
|
28
|
+
@shell.built_ins
|
29
|
+
end
|
30
|
+
|
31
|
+
def tab_complete_built_in
|
32
|
+
case args.length
|
33
|
+
when 0..1
|
34
|
+
built_in_methods
|
35
|
+
else
|
36
|
+
@shell.tab_complete_built_in(args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_option_set
|
41
|
+
if args.length <= 1 or is_built_in?
|
42
|
+
tab_complete_built_in.map { |opt| opt.to_s || "" }
|
43
|
+
else
|
44
|
+
[]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def tab_complete
|
49
|
+
fragment = args.last || ""
|
50
|
+
get_option_set.select { |opt| opt.to_s.start_with? fragment }
|
51
|
+
end
|
52
|
+
|
53
|
+
def make_commandline(args)
|
54
|
+
(args.map do |arg|
|
55
|
+
if arg.match(/\s/).nil? then
|
56
|
+
arg
|
57
|
+
else
|
58
|
+
arg.shellescape
|
59
|
+
end
|
60
|
+
end).join(" ")
|
61
|
+
end
|
62
|
+
|
63
|
+
def run_external
|
64
|
+
begin
|
65
|
+
cmdline = make_commandline(args)
|
66
|
+
Open3.popen3(cmdline) do |stdin, stdout, stderr, wait_thr|
|
67
|
+
begin
|
68
|
+
pid = wait_thr[:pid]
|
69
|
+
|
70
|
+
stdin.write(@input.read)
|
71
|
+
stdin.close
|
72
|
+
|
73
|
+
@status = wait_thr.value
|
74
|
+
|
75
|
+
@output.write(stdout.read)
|
76
|
+
stdout.close
|
77
|
+
stderr.close
|
78
|
+
rescue Errno::EPIPE
|
79
|
+
@error.write("-netshell: #{args[0]}: #{stderr.read}\n")
|
80
|
+
@status = 127
|
81
|
+
end
|
82
|
+
end
|
83
|
+
rescue Errno::ENOENT
|
84
|
+
@output.write("-netshell: #{args[0]}: command not found\n")
|
85
|
+
@status = 127
|
86
|
+
end
|
87
|
+
|
88
|
+
@status
|
89
|
+
end
|
90
|
+
|
91
|
+
def run
|
92
|
+
return "" if args.empty? or args[0].nil?
|
93
|
+
return run_built_in if is_built_in?
|
94
|
+
return run_external
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/net_shell/io.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
class StringBuffer
|
4
|
+
attr_accessor :string
|
5
|
+
def initialize
|
6
|
+
@string = ""
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
module A4Tools
|
12
|
+
class StandardOutput
|
13
|
+
attr_accessor :color
|
14
|
+
|
15
|
+
def write(s)
|
16
|
+
s = s.unstyle unless @color
|
17
|
+
$stdout.write s.gsub("\t", " ").gsub("\n","\r\n")
|
18
|
+
end
|
19
|
+
|
20
|
+
def close
|
21
|
+
end
|
22
|
+
|
23
|
+
def print(s="")
|
24
|
+
write s.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def puts(s="")
|
28
|
+
write s.to_s+"\n"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class PipeBuffer
|
33
|
+
attr_accessor :color
|
34
|
+
attr_reader :buffer
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@buffer = ""
|
38
|
+
end
|
39
|
+
|
40
|
+
def read
|
41
|
+
@color ? @buffer : @buffer.unstyle
|
42
|
+
end
|
43
|
+
|
44
|
+
def read_all
|
45
|
+
@color ? @buffer : @buffer.unstyle
|
46
|
+
end
|
47
|
+
|
48
|
+
def write(s)
|
49
|
+
@buffer += s
|
50
|
+
end
|
51
|
+
|
52
|
+
def puts(s)
|
53
|
+
if s.is_a? Array then
|
54
|
+
s.each { |e| puts e.to_s }
|
55
|
+
else
|
56
|
+
write(s.to_s+"\n")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def printf(s, *a)
|
61
|
+
write(sprintf(s.to_s, *a))
|
62
|
+
end
|
63
|
+
|
64
|
+
def print(s="")
|
65
|
+
write(s.to_s)
|
66
|
+
end
|
67
|
+
|
68
|
+
def close
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class FileOverwriteOutput < StandardOutput
|
73
|
+
def initialize(filename)
|
74
|
+
@filename = filename
|
75
|
+
end
|
76
|
+
|
77
|
+
def access_type
|
78
|
+
"w"
|
79
|
+
end
|
80
|
+
|
81
|
+
def write(s)
|
82
|
+
s = s.unstyle unless @color
|
83
|
+
@fd ||= File.open(@filename, access_type)
|
84
|
+
@fd.write(s)
|
85
|
+
@fd.flush
|
86
|
+
end
|
87
|
+
|
88
|
+
def close
|
89
|
+
@fd.close
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class FileAppendOutput < FileOverwriteOutput
|
94
|
+
def access_type
|
95
|
+
"a"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class StandardInput
|
100
|
+
def read
|
101
|
+
begin
|
102
|
+
STDIN.read_nonblock(256)
|
103
|
+
rescue IO::WaitReadable
|
104
|
+
""
|
105
|
+
rescue EOFError
|
106
|
+
nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def read_all
|
111
|
+
buffer = ""
|
112
|
+
while (line = read) != nil
|
113
|
+
buffer += line
|
114
|
+
end
|
115
|
+
buffer.chomp
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class FileReadInput
|
120
|
+
def initialize(filename)
|
121
|
+
@filename = filename
|
122
|
+
end
|
123
|
+
|
124
|
+
def read
|
125
|
+
IO.read(@filename)
|
126
|
+
end
|
127
|
+
|
128
|
+
def read_all
|
129
|
+
IO.read(@filename)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,396 @@
|
|
1
|
+
require 'io/console'
|
2
|
+
require 'net_shell/command'
|
3
|
+
require 'net_shell/io'
|
4
|
+
require 'net_shell/colors'
|
5
|
+
require 'net_shell/prompt'
|
6
|
+
require 'net_shell/builtin_command.rb'
|
7
|
+
require 'digest/sha1'
|
8
|
+
require 'shellwords'
|
9
|
+
|
10
|
+
module A4Tools
|
11
|
+
class NetShell
|
12
|
+
attr_accessor :env, :shared, :processing
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@history = []
|
16
|
+
@env = {}
|
17
|
+
@shared = { traffic:[] }
|
18
|
+
$config = @env
|
19
|
+
$localtalk = File.join(config_dir, "talk.json")
|
20
|
+
|
21
|
+
set_env(:color, "1")
|
22
|
+
set_env(:show_async, "1")
|
23
|
+
set_env(:serial, stored_serial)
|
24
|
+
|
25
|
+
read_env
|
26
|
+
setup_builtins
|
27
|
+
setup_support
|
28
|
+
end
|
29
|
+
|
30
|
+
###
|
31
|
+
# Netshell setup
|
32
|
+
###
|
33
|
+
|
34
|
+
def setup_support
|
35
|
+
setup_stored_json
|
36
|
+
setup_deployment_connection
|
37
|
+
setup_usherm_connection
|
38
|
+
end
|
39
|
+
|
40
|
+
def setup_stored_json
|
41
|
+
ObjectBuilder.load_path(shelldir(:json))
|
42
|
+
end
|
43
|
+
|
44
|
+
def config_dir
|
45
|
+
path = File.expand_path("~/.netshell")
|
46
|
+
Dir.mkdir(path) unless File.directory? path
|
47
|
+
path
|
48
|
+
end
|
49
|
+
|
50
|
+
def shelldir(dir)
|
51
|
+
path = File.join(config_dir, dir.to_s)
|
52
|
+
Dir.mkdir(path) unless File.directory? path
|
53
|
+
path
|
54
|
+
end
|
55
|
+
|
56
|
+
###
|
57
|
+
# Built-in commands
|
58
|
+
###
|
59
|
+
|
60
|
+
def allow_alerts(allow=true)
|
61
|
+
@allow_alerts = true
|
62
|
+
end
|
63
|
+
|
64
|
+
def setup_builtins
|
65
|
+
@built_ins ||= {}
|
66
|
+
dir = File.expand_path("builtin_commands", File.dirname(__FILE__))
|
67
|
+
all = load_builtins_from_directory(dir, false) + load_builtins_from_directory(shelldir(:bin), true)
|
68
|
+
@built_ins.delete_if { |command, subclass| not(all.include? subclass) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def load_builtins_from_directory(dir, userdef)
|
72
|
+
Dir[File.join(dir, "*.rb")].map do |file|
|
73
|
+
subclass = built_in(File.basename(file, ".rb"))
|
74
|
+
if subclass.nil? or subclass.sha1 != Digest::SHA1.hexdigest(IO.read(file))
|
75
|
+
subclass = BuiltinCommand.load_command(file, userdef)
|
76
|
+
register_built_in(subclass.command, subclass)
|
77
|
+
end
|
78
|
+
subclass
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def has_built_in?(name)
|
83
|
+
return built_in(name) != nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def built_in(name)
|
87
|
+
@built_ins[name.to_sym]
|
88
|
+
end
|
89
|
+
|
90
|
+
def built_ins(full=false)
|
91
|
+
full ? @built_ins.values : @built_ins.keys
|
92
|
+
end
|
93
|
+
|
94
|
+
def register_built_in(command, cls)
|
95
|
+
@built_ins[command.to_sym] = cls
|
96
|
+
end
|
97
|
+
|
98
|
+
def tab_complete_built_in(args)
|
99
|
+
return [] unless has_built_in?(args[0])
|
100
|
+
|
101
|
+
built_in = built_in(args[0]).new(self)
|
102
|
+
built_in.parse(args)
|
103
|
+
built_in.tab
|
104
|
+
end
|
105
|
+
|
106
|
+
###
|
107
|
+
# Environment management
|
108
|
+
###
|
109
|
+
|
110
|
+
def path_for_env(key)
|
111
|
+
File.join(shelldir(:env), key)
|
112
|
+
end
|
113
|
+
|
114
|
+
def persist_env(*keys)
|
115
|
+
keys = @env.keys if keys.empty?
|
116
|
+
keys = keys[0] if keys[0].is_a? Array
|
117
|
+
|
118
|
+
present = keys.reject { |key| get_env(key).nil? }
|
119
|
+
absent = keys.select { |key| get_env(key).nil? }
|
120
|
+
present.each { |key| File.write(path_for_env(key), get_env(key)) }
|
121
|
+
unpersist_env(absent)
|
122
|
+
end
|
123
|
+
|
124
|
+
def unpersist_env(*keys)
|
125
|
+
keys = keys[0] if keys[0].is_a? Array
|
126
|
+
keys.each do |key|
|
127
|
+
path = path_for_env(key)
|
128
|
+
File.delete(path) if File.exist? path
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def read_env
|
133
|
+
Dir[File.join(shelldir(:env), "*")].each { |file| set_env(File.basename(file), File.open(file).read.chomp) }
|
134
|
+
end
|
135
|
+
|
136
|
+
def set_env(key, value)
|
137
|
+
if value.nil?
|
138
|
+
@env.delete(key.to_sym)
|
139
|
+
else
|
140
|
+
@env[key.to_sym] = value
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_env(key)
|
145
|
+
@env[key.to_sym]
|
146
|
+
end
|
147
|
+
|
148
|
+
def env_is_true?(key)
|
149
|
+
value = get_env(key)
|
150
|
+
value != nil and value != "0"
|
151
|
+
end
|
152
|
+
|
153
|
+
###
|
154
|
+
# Shared variables
|
155
|
+
###
|
156
|
+
|
157
|
+
def username
|
158
|
+
@env[:usherm_user]
|
159
|
+
end
|
160
|
+
|
161
|
+
def password
|
162
|
+
@env[:usherm_pass]
|
163
|
+
end
|
164
|
+
|
165
|
+
def setup_usherm_connection
|
166
|
+
return if username.nil? or password.nil?
|
167
|
+
set_client(:usherm, UsherMgmtClient.new(nil, username, password))
|
168
|
+
puts "\rAutomatically connecting to Usher as #{username}"
|
169
|
+
end
|
170
|
+
|
171
|
+
def setup_deployment_connection
|
172
|
+
return if username.nil? or password.nil?
|
173
|
+
set_client(:deployment, DeploymentClient.new("http://deployments.acres4.net:8080/deployment/json?wrap", username, password))
|
174
|
+
puts "\rAutomatically connecting to Deployment as #{username}"
|
175
|
+
end
|
176
|
+
|
177
|
+
def clients
|
178
|
+
@clients.keys
|
179
|
+
end
|
180
|
+
|
181
|
+
def client(key)
|
182
|
+
@clients[key.to_sym]
|
183
|
+
end
|
184
|
+
|
185
|
+
def set_client(key, client)
|
186
|
+
@clients ||= {}
|
187
|
+
@clients[key] = client
|
188
|
+
client.refresh_async rescue ""
|
189
|
+
client.on(:error) { |trigger, message| alert("#{key.to_s}: #{message}") }
|
190
|
+
end
|
191
|
+
|
192
|
+
def set_active_client(key)
|
193
|
+
@shared[:client] = @clients[key.to_sym]
|
194
|
+
end
|
195
|
+
|
196
|
+
def active_client
|
197
|
+
@shared[:client]
|
198
|
+
end
|
199
|
+
|
200
|
+
def active_client_name
|
201
|
+
@clients.each { |key, client| return key if client == @shared[:client] }
|
202
|
+
nil
|
203
|
+
end
|
204
|
+
|
205
|
+
###
|
206
|
+
# Command prompt
|
207
|
+
###
|
208
|
+
|
209
|
+
def bad_command(args)
|
210
|
+
"Unrecognized command: #{args[0]}"
|
211
|
+
end
|
212
|
+
|
213
|
+
def is_input_redirect?(arg)
|
214
|
+
arg == "<"
|
215
|
+
end
|
216
|
+
|
217
|
+
def is_output_redirect?(arg)
|
218
|
+
[ ">", ">>" ].include? arg
|
219
|
+
end
|
220
|
+
|
221
|
+
def is_redirect?(arg)
|
222
|
+
is_input_redirect?(arg) || is_output_redirect?(arg)
|
223
|
+
end
|
224
|
+
|
225
|
+
def get_input(args)
|
226
|
+
index = args.find_index { |arg| is_input_redirect? arg }
|
227
|
+
return StandardInput.new if (index.nil? or index > args.length - 2)
|
228
|
+
|
229
|
+
case args[index]
|
230
|
+
when "<"
|
231
|
+
FileReadInput.new(args[index+1])
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def get_output(args)
|
236
|
+
index = args.find_index { |arg| is_output_redirect? arg }
|
237
|
+
default = StandardOutput.new
|
238
|
+
default.color = @env[:color] != "0"
|
239
|
+
return default if (index.nil? or index > args.length - 2)
|
240
|
+
|
241
|
+
case args[index]
|
242
|
+
when ">"
|
243
|
+
FileOverwriteOutput.new(args[index+1])
|
244
|
+
when ">>"
|
245
|
+
puts "Appending to #{args[index+1]}"
|
246
|
+
FileAppendOutput.new(args[index+1])
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def get_error(args)
|
251
|
+
error = StandardOutput.new
|
252
|
+
error.color = @env[:color] != "0"
|
253
|
+
error
|
254
|
+
end
|
255
|
+
|
256
|
+
def clean_args(args)
|
257
|
+
index = args.find_index { |arg| is_redirect? arg }
|
258
|
+
return args if index.nil?
|
259
|
+
args[0 .. index-1]
|
260
|
+
end
|
261
|
+
|
262
|
+
def split_args(cmdline)
|
263
|
+
return [] if cmdline.nil? or cmdline.empty?
|
264
|
+
cmdline.gsub(/`\b/, "\"`").gsub(/\b`/, "`\"").shellsplit_partial
|
265
|
+
end
|
266
|
+
|
267
|
+
def process_backtick(line)
|
268
|
+
line = line[1..-2] if line[0] == '`' and line[-1] == '`'
|
269
|
+
cmd = command_for_line(line)
|
270
|
+
cmd.input = StandardInput.new
|
271
|
+
cmd.output = PipeBuffer.new
|
272
|
+
cmd.run
|
273
|
+
cmd.output.read.chomp
|
274
|
+
end
|
275
|
+
|
276
|
+
def transform_args(args)
|
277
|
+
args.map do |arg|
|
278
|
+
if arg[0] == "$" then
|
279
|
+
get_env(arg[1..-1]) || ""
|
280
|
+
elsif arg[0] == '`' and arg[-1] == '`' then
|
281
|
+
process_backtick(arg)
|
282
|
+
else
|
283
|
+
arg
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def command_for_line(cmdline, allow_trailing_space=false)
|
289
|
+
cmdline ||= ""
|
290
|
+
args = transform_args(split_args(cmdline))
|
291
|
+
args.push "" if allow_trailing_space and cmdline.match(/\s+$/)
|
292
|
+
Command.new(clean_args(args), get_input(args), get_output(args), get_error(args), self)
|
293
|
+
end
|
294
|
+
|
295
|
+
def exec(cmdline)
|
296
|
+
return if cmdline.match(/^\s+$/)
|
297
|
+
commands = cmdline.split("|").map { |subcommand| command_for_line(subcommand) }
|
298
|
+
|
299
|
+
last_cmd = nil
|
300
|
+
commands.each do |cmd|
|
301
|
+
cmd.input = last_cmd.output unless last_cmd.nil?
|
302
|
+
cmd.output = PipeBuffer.new unless cmd == commands.last
|
303
|
+
break if cmd.run != 0
|
304
|
+
last_cmd = cmd
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
def add_to_alert_queue(msg)
|
309
|
+
@alert_queue ||= []
|
310
|
+
@alert_queue.push(msg)
|
311
|
+
end
|
312
|
+
|
313
|
+
def flush_alert_queue
|
314
|
+
return if @alert_queue.nil?
|
315
|
+
@alert_queue.each { |alert_msg| alert(alert_msg) }
|
316
|
+
@alert_queue = nil
|
317
|
+
end
|
318
|
+
|
319
|
+
def alert(msg)
|
320
|
+
if @processing and not @allow_alerts
|
321
|
+
add_to_alert_queue(msg)
|
322
|
+
return
|
323
|
+
end
|
324
|
+
|
325
|
+
@prompt.clear_line
|
326
|
+
@prompt.refresh_prompt
|
327
|
+
puts "\r#{msg}"
|
328
|
+
@prompt.redraw_line if @alert_queue.nil? and not @processing
|
329
|
+
end
|
330
|
+
|
331
|
+
def prompt_text
|
332
|
+
client = self.shared[:client]
|
333
|
+
return "net> " if client.nil? or not client.ready
|
334
|
+
return "#{client.uri}> " if client.server_info.nil?
|
335
|
+
|
336
|
+
"#{client.uri} #{client.server_info[:appName]}> "
|
337
|
+
end
|
338
|
+
|
339
|
+
def enter
|
340
|
+
@prompt = Prompt.new(:history_file => File.join(config_dir, "history"))
|
341
|
+
@prompt.tab = lambda do |cmdline|
|
342
|
+
setup_builtins
|
343
|
+
command_for_line(cmdline.split("|").last, true).tab_complete
|
344
|
+
end
|
345
|
+
@prompt.prompt = lambda { prompt_text }
|
346
|
+
@processing = false
|
347
|
+
|
348
|
+
while(true) do
|
349
|
+
line = @prompt.read_line
|
350
|
+
setup_builtins
|
351
|
+
@processing = true
|
352
|
+
@allow_alerts = false
|
353
|
+
exec(line)
|
354
|
+
@processing = false
|
355
|
+
flush_alert_queue
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
###
|
360
|
+
# Network listener
|
361
|
+
###
|
362
|
+
|
363
|
+
def wrap_message(message, sender)
|
364
|
+
{ time: Time.now, sender: sender, message: message }
|
365
|
+
end
|
366
|
+
|
367
|
+
def notify_outgoing_message(client, message)
|
368
|
+
end
|
369
|
+
|
370
|
+
def notify_connect(client)
|
371
|
+
return unless client == active_client
|
372
|
+
end
|
373
|
+
|
374
|
+
def notify_disconnect(client)
|
375
|
+
return unless client == active_client
|
376
|
+
alert("Disconnected from #{client.uri}")
|
377
|
+
end
|
378
|
+
|
379
|
+
def notify_incoming_message(client, message)
|
380
|
+
return unless client == active_client
|
381
|
+
alert("server:".magenta + " #{message}") if env_is_true?(:show_async)
|
382
|
+
end
|
383
|
+
|
384
|
+
def stored_serial
|
385
|
+
file = File.join(config_dir, "serial")
|
386
|
+
|
387
|
+
begin
|
388
|
+
return IO.read(file)
|
389
|
+
rescue
|
390
|
+
serial = Digest::SHA1.hexdigest(Random.new.bytes(16)).to_s
|
391
|
+
File.write(file, serial) rescue nil
|
392
|
+
return serial
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|