a4tools 1.2.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|