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,74 @@
|
|
1
|
+
category "Protocol manipulation"
|
2
|
+
description "Send a request to the remote server"
|
3
|
+
|
4
|
+
usage [
|
5
|
+
" send a raw message to the server",
|
6
|
+
"interface method send a message to the server, wrapped with a JSON-RPC request for the specified method"
|
7
|
+
]
|
8
|
+
|
9
|
+
validate { args.length == 1 || args.length == 3 }
|
10
|
+
|
11
|
+
help <<-EOS
|
12
|
+
Messages are supplied as JSON via stdin. Messages can therefore be read using input redirection or piped from another command, like #{"build".style(:command)} or #{"cached".style(:command)}.
|
13
|
+
EOS
|
14
|
+
|
15
|
+
tab 1 do
|
16
|
+
set = talk.definition[:protocol].inject([]) do |set, proto|
|
17
|
+
set + proto[:method].select { |method| talk.name_similar?(method[:name], args[2] || "") }
|
18
|
+
end
|
19
|
+
|
20
|
+
set.map { |m| m[:name] }
|
21
|
+
end
|
22
|
+
|
23
|
+
opt :no_inject, "Don't automatically inject the current connection token"
|
24
|
+
opt :dry, "Don't send the message; just print what would be sent to the console"
|
25
|
+
opt :spam, "Send the message repeatedly", :type => :integer, :default => 1
|
26
|
+
opt :spam_interval, "Time to wait between spams in milliseconds", :type => :integer, :default => 1000
|
27
|
+
|
28
|
+
run do
|
29
|
+
return show_error("must connect first") if @shell.shared[:client].nil?
|
30
|
+
@shell.allow_alerts
|
31
|
+
|
32
|
+
message = input.read_all
|
33
|
+
index = 0
|
34
|
+
|
35
|
+
params[:spam].times do
|
36
|
+
index = index + 1
|
37
|
+
if args.length == 3 then
|
38
|
+
send_wrapped(message)
|
39
|
+
else
|
40
|
+
send_raw(message)
|
41
|
+
end
|
42
|
+
|
43
|
+
puts "Sending message #{index} of #{params[:spam]}" if params[:spam] > 1
|
44
|
+
sleep params[:spam_interval] * 1.0/1000.0 if index < params[:spam]
|
45
|
+
end
|
46
|
+
|
47
|
+
""
|
48
|
+
end
|
49
|
+
|
50
|
+
def send_raw(message)
|
51
|
+
send(message)
|
52
|
+
end
|
53
|
+
|
54
|
+
def send_wrapped(message)
|
55
|
+
message = symbolify(JSON.parse(message)) if message.is_a? String
|
56
|
+
method, protocol = talk.method_named(args[2])
|
57
|
+
return show_error("#{args[1]}: unknown method") if method.nil?
|
58
|
+
cls = talk.class_named(method[:request])
|
59
|
+
return show_error("#{args[1]}: unable to locate request class") if cls.nil?
|
60
|
+
|
61
|
+
client.inject_token(message) unless params[:no_inject]
|
62
|
+
jsonrpc = client.jsonrpc_message(method[:name], args[1], talk.guess_class(message), message)
|
63
|
+
|
64
|
+
message = JSON.generate(jsonrpc)
|
65
|
+
send(message)
|
66
|
+
end
|
67
|
+
|
68
|
+
def send(message)
|
69
|
+
if params[:dry] then
|
70
|
+
puts message
|
71
|
+
else
|
72
|
+
client.send_message(message)
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
category "Shell management"
|
2
|
+
description "Set environment variables"
|
3
|
+
usage "variable value"
|
4
|
+
|
5
|
+
help <<-EOS
|
6
|
+
Sets an environment variable to a specified value. Environment variables may also be set by creating
|
7
|
+
~/.netshell/env
|
8
|
+
|
9
|
+
At shell initialization, this directory (if it exists) will be scanned. For each filename in the directory, an environment variable with that name will be created, and populated with the contents of that file.
|
10
|
+
|
11
|
+
Environment variables are NOT imported from your system's native shell.
|
12
|
+
EOS
|
13
|
+
|
14
|
+
validate { args.length == 2 or args.length == 3 }
|
15
|
+
|
16
|
+
tab(0) do
|
17
|
+
@shell.env.keys
|
18
|
+
end
|
19
|
+
|
20
|
+
run do
|
21
|
+
value = if args.length == 3 then
|
22
|
+
args[2 .. -1].join(" ")
|
23
|
+
else
|
24
|
+
@input.read_all.chomp
|
25
|
+
end
|
26
|
+
@shell.set_env(args[1].to_sym, value)
|
27
|
+
""
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,183 @@
|
|
1
|
+
category "Talk"
|
2
|
+
description "Show details for a Talk entity"
|
3
|
+
usage [
|
4
|
+
"entity show information about an entity",
|
5
|
+
"enumeration constant show information about a constant in a particular enumeration",
|
6
|
+
"glossary term show information about a term in a particular glossary",
|
7
|
+
"class field show information about a class in a particular field",
|
8
|
+
"protocol method show information about a method in a particular protocol"
|
9
|
+
]
|
10
|
+
|
11
|
+
help "Displays Talk information about a specified entity. Entities can be classes, glossaries, enumerations, protocols, constants, fields, terms, or methods."
|
12
|
+
|
13
|
+
validate { args.length <= 3 }
|
14
|
+
|
15
|
+
tab 0 do
|
16
|
+
talk.things_named_like(args.last).map { |thing| talk.truncated_name thing[:name] } rescue []
|
17
|
+
end
|
18
|
+
|
19
|
+
opt :class, "List all classes"
|
20
|
+
opt :enumeration, "List all enumerations"
|
21
|
+
opt :glossary, "List all glossaries"
|
22
|
+
opt :protocol, "List all protocols"
|
23
|
+
opt :recurse, "List all entities referenced by queried entity"
|
24
|
+
opt :reverse, "List entities in reverse (with original query at top)"
|
25
|
+
|
26
|
+
run do
|
27
|
+
if args.length > 1 then
|
28
|
+
@subqueries = []
|
29
|
+
top_level = show(args[1 .. -1])
|
30
|
+
return show_error("#{args[1 .. -1].join(' ')}: symbol not found") if top_level.nil?
|
31
|
+
|
32
|
+
sections = [ top_level ]
|
33
|
+
|
34
|
+
if params[:recurse] then
|
35
|
+
until @subqueries.empty? do
|
36
|
+
query = @subqueries.first
|
37
|
+
@subqueries = @subqueries[1..-1]
|
38
|
+
sections.push show([query])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
sections.reverse! unless params[:reverse]
|
43
|
+
sections.each do |section|
|
44
|
+
puts section
|
45
|
+
end
|
46
|
+
""
|
47
|
+
else
|
48
|
+
show_list
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
###
|
53
|
+
|
54
|
+
def add_queries(*new_queries)
|
55
|
+
@subqueries ||= []
|
56
|
+
@seen ||= {}
|
57
|
+
new_queries.each do |q|
|
58
|
+
next if q == "none" # given by methods
|
59
|
+
@subqueries.push q unless @seen.has_key? q
|
60
|
+
@seen[q] = true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def show_list
|
65
|
+
s = ""
|
66
|
+
query_for_params.each do |section|
|
67
|
+
next if talk.definition[section].nil?
|
68
|
+
s += descriptions[section] + " (#{talk.definition[section].length})\n"
|
69
|
+
s += (talk.definition[section].map { |item| "\t#{item[:name].style(style_for_section(section))}\n\t#{item[:description]}\n" }).join("\n") + "\n\n"
|
70
|
+
end
|
71
|
+
s
|
72
|
+
end
|
73
|
+
|
74
|
+
def query_for_params
|
75
|
+
query = []
|
76
|
+
options = [ :class, :enumeration, :glossary, :protocol ]
|
77
|
+
options.each { |opt| query.push(opt) if params[opt] }
|
78
|
+
|
79
|
+
query = options if query.empty?
|
80
|
+
query
|
81
|
+
end
|
82
|
+
|
83
|
+
def style_for_section(section)
|
84
|
+
case section
|
85
|
+
when :class
|
86
|
+
:class
|
87
|
+
when :protocol
|
88
|
+
:protocol_name
|
89
|
+
when :enumeration, :glossary
|
90
|
+
:collection_name
|
91
|
+
else
|
92
|
+
:none
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def descriptions
|
97
|
+
{ class:"Classes", glossary:"Glossaries", enumeration:"Enumerations", protocol:"Protocols" }
|
98
|
+
end
|
99
|
+
|
100
|
+
def list(query)
|
101
|
+
query = [ :class, :enumeration, :glossary, :protocol ] if query.empty?
|
102
|
+
query.map! { |e| e.to_sym }
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
|
108
|
+
def show_field(query)
|
109
|
+
return nil if query.length < 2
|
110
|
+
cls = (query[0].is_a? Hash) ? query[0] : talk.class_named(query[0])
|
111
|
+
return nil if cls.nil?
|
112
|
+
field = talk.field_named(cls, query[1])
|
113
|
+
return nil if field.nil?
|
114
|
+
|
115
|
+
add_queries(field[:type].first)
|
116
|
+
|
117
|
+
"Field #{field[:name]}: #{(field[:type].map { |t| talk.truncated_name t }).join('')}\n\tClass #{cls[:name]}\n\t#{field[:description]}\n"
|
118
|
+
end
|
119
|
+
|
120
|
+
def show_class(query)
|
121
|
+
cls = (query[0].is_a? Hash) ? query[0] : talk.class_named(query[0])
|
122
|
+
return nil if cls.nil?
|
123
|
+
|
124
|
+
fields = cls[:field].map do |f|
|
125
|
+
add_queries(f[:type].first)
|
126
|
+
"\t#{f[:name].style(:field_name)}, #{(f[:type].map { |t| talk.truncated_name t }).join('').style(:field_datatype)}\n\t\t#{f[:description]}\n"
|
127
|
+
end
|
128
|
+
|
129
|
+
"Class #{cls[:name].style(:class)}\n\t#{cls[:description]}\n\n" + fields.join("\n")
|
130
|
+
end
|
131
|
+
|
132
|
+
def origin_line(method)
|
133
|
+
return "Asynchronous from server\n\t\t".style(:origin) if method[:origin] == "server"
|
134
|
+
return ""
|
135
|
+
end
|
136
|
+
|
137
|
+
def show_protocol(query)
|
138
|
+
proto = (query[0].is_a? Hash) ? query[0] : talk.protocol_named(query[0])
|
139
|
+
return nil if proto.nil?
|
140
|
+
|
141
|
+
methods = proto[:method].map do |m|
|
142
|
+
add_queries(m[:request], m[:response])
|
143
|
+
"\t#{m[:name].style(:method_name)}: #{m[:request].style(:class)} -> #{m[:response].style(:class)}\n\t\t#{origin_line(m)}#{m[:description]}\n"
|
144
|
+
end
|
145
|
+
|
146
|
+
"Protocol #{proto[:name].style(:protocol_name)}\n\t#{proto[:description]}\n" + methods.join("\n")
|
147
|
+
end
|
148
|
+
|
149
|
+
def show_method(query)
|
150
|
+
method, protocol = (query.length == 1) ? talk.method_named(query[0], nil) : talk.method_named(query[1], query[0])
|
151
|
+
return nil if method.nil?
|
152
|
+
|
153
|
+
add_queries(method[:request], method[:response])
|
154
|
+
"Method #{method[:name].style(:method_name)}: #{method[:request].style(:class)} -> #{method[:response].style(:class)}\n\tProtocol #{protocol[:name].style(:protocol_name)}\n\t#{method[:description]}\n\n"
|
155
|
+
end
|
156
|
+
|
157
|
+
def show_constant(query)
|
158
|
+
constant, container = (query.length > 1) ? talk.constant_named(query[1], query[0]) : talk.constant_named(query[0], nil)
|
159
|
+
return nil if constant.nil?
|
160
|
+
|
161
|
+
origin = (container.has_key? :term) ? "Glossary #{container[:name]}" : "Enumeration #{container[:name]}"
|
162
|
+
|
163
|
+
"Constant #{constant[:name].style(:constant_name)}: #{constant[:value].to_s.style(:constant_value)}\n\t#{origin}\n\t#{constant[:description]}\n\n"
|
164
|
+
end
|
165
|
+
|
166
|
+
def show_glossary(query)
|
167
|
+
glossary = (query[0].is_a? Hash) ? query[0] : talk.glossary_named(query[0])
|
168
|
+
return nil if glossary.nil?
|
169
|
+
|
170
|
+
"Glossary #{glossary[:name].style(:collection_name)}\n\t#{glossary[:description]}\n\n" + (glossary[:term].map { |t| "\t#{t[:name].style(:constant_name)} (\"#{t[:value].style(:constant_value)}\")\n\t\t#{t[:description]}\n"}).join("\n")
|
171
|
+
end
|
172
|
+
|
173
|
+
def show_enumeration(query)
|
174
|
+
enumeration = (query[0].is_a? Hash) ? query[0] : talk.enumeration_named(query[0])
|
175
|
+
return nil if enumeration.nil?
|
176
|
+
|
177
|
+
"Enumeration #{enumeration[:name].style(:collection_name)}\n\t#{enumeration[:description]}\n\n" + (enumeration[:constant].map { |c| "\t#{c[:value].to_i.to_s.style(:constant_value)} #{c[:name].style(:constant_name)}\n\t\t#{c[:description]}\n"}).join("\n")
|
178
|
+
end
|
179
|
+
|
180
|
+
def show(query)
|
181
|
+
show_field(query) || show_method(query) || show_class(query) || show_protocol(query) || show_constant(query) || show_glossary(query) || show_enumeration(query)
|
182
|
+
end
|
183
|
+
|
@@ -0,0 +1,122 @@
|
|
1
|
+
category "Usher"
|
2
|
+
description "List everything about a site"
|
3
|
+
usage "siteId1 siteId2 ..."
|
4
|
+
|
5
|
+
opt :no_deploy, "Do not show deployment information"
|
6
|
+
|
7
|
+
tab do
|
8
|
+
sites = (usherm[:usherSystemId][:usherSites].map { |site| site[:idSite] } +
|
9
|
+
usherm[:usherSystemId][:usherSites].map { |site| site[:name] }) rescue []
|
10
|
+
sites.reject { |site| args.include? site.to_s }
|
11
|
+
end
|
12
|
+
|
13
|
+
run do
|
14
|
+
usherm.ensure_fresh
|
15
|
+
deployment.ensure_fresh
|
16
|
+
if args.length >= 2 then
|
17
|
+
args[1..-1].each do |arg|
|
18
|
+
site_id = site_id_for_arg(arg)
|
19
|
+
if site_id.nil? then
|
20
|
+
puts "Unknown site '#{site_id}'"
|
21
|
+
next
|
22
|
+
end
|
23
|
+
|
24
|
+
show_site(site_id)
|
25
|
+
puts
|
26
|
+
end
|
27
|
+
else
|
28
|
+
show_all_sites
|
29
|
+
end
|
30
|
+
|
31
|
+
""
|
32
|
+
end
|
33
|
+
|
34
|
+
###
|
35
|
+
|
36
|
+
def site_id_for_arg(arg)
|
37
|
+
return arg.to_i if arg.is_a? Fixnum or arg.match(/^[0-9]+$/)
|
38
|
+
usherm[:usherSystemId][:usherSites].each { |site| return site[:idSite] if site[:name] == arg }
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def show_all_sites
|
43
|
+
sites = (usherm[:usherSystemId][:usherSites].map { |site| site[:idSite] }).sort
|
44
|
+
sites.each do |site_id|
|
45
|
+
site = usherm.site_with_id(site_id)
|
46
|
+
site_id_str = sprintf("%6d", site_id).style(:id)
|
47
|
+
puts "##{site_id_str}: #{site[:name]} (#{site[:siteDescription]})"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def show_site(site_id)
|
52
|
+
site = usherm.site_with_id(site_id)
|
53
|
+
show_usher_site(site_id, site)
|
54
|
+
show_host_info(site_id)
|
55
|
+
show_publications(deployment.query(:buildPublicationList,site_id)) unless params[:no_deploy]
|
56
|
+
end
|
57
|
+
|
58
|
+
def yes_no(b)
|
59
|
+
b ? "yes" : "no"
|
60
|
+
end
|
61
|
+
|
62
|
+
def timestamp(ts)
|
63
|
+
DateTime.strptime(ts.to_s,'%s').strftime("%Y-%m-%d %H:%M:%S").style(:timestamp)
|
64
|
+
end
|
65
|
+
|
66
|
+
def expiration(mod)
|
67
|
+
mod[:permanent] ? "Never" : timestamp(mod[:expiration])
|
68
|
+
end
|
69
|
+
|
70
|
+
def show_usher_site(site_id, site)
|
71
|
+
if site.nil?
|
72
|
+
puts "Site #{site_id.to_s.style(:id)}: Unknown (not in usher)"
|
73
|
+
return
|
74
|
+
end
|
75
|
+
|
76
|
+
puts "Site".style(:heading) +" #{site[:idSite].to_s.style(:id)}: #{site[:name]} (#{site[:siteDescription]})"
|
77
|
+
puts "\t Timezone: #{site[:zoneinfoId].style(:timezone)}"
|
78
|
+
mod = site[:moduleProvision]
|
79
|
+
if mod then
|
80
|
+
mask = sprintf("%16x", mod[:modules]).style(:mask)
|
81
|
+
puts "\t Modules: #{mask}"
|
82
|
+
puts "\t Max machines: #{mod[:maxAllowedMachines]}"
|
83
|
+
puts "\t Active: #{yes_no(mod[:active])}"
|
84
|
+
puts "\tPermanent license: #{yes_no(mod[:permanent])}"
|
85
|
+
puts "\t Expiration: #{expiration(mod)}"
|
86
|
+
puts "\t Renewal attempts: #{mod[:renewalAttemtps]}"
|
87
|
+
end
|
88
|
+
site[:siteRange].each do |range|
|
89
|
+
puts "\t CIDR: #{range[:cidrBlock].style(:cidr)} #{range[:siteRangeDescription]}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def show_host_info(site_id)
|
94
|
+
puts "\tHosts".style(:heading)
|
95
|
+
usherm.providers_for_site(site_id).each do |provider|
|
96
|
+
host = usherm.host_with_id(provider[:idSystemHost])
|
97
|
+
product = sprintf("%20s", provider[:product]).style(:product)
|
98
|
+
puts "\t\t#{product}: #{host[:hostName].style(:host)}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def show_publications(publications)
|
103
|
+
puts "\tDeployments".style(:heading)
|
104
|
+
publications[:orders].keys.sort.each do |app|
|
105
|
+
next if params[:app] and not talk.name_matches?(app, params[:app])
|
106
|
+
list_site_app(app.to_s, publications[:orders][app])
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def list_site_app(app, orders)
|
111
|
+
pub = orders.first
|
112
|
+
return if params[:jeb] and pub[:buildInfo][:buildId] != params[:jeb]
|
113
|
+
return if params[:commit] and pub[:buildInfo][:commitId] != params[:commit]
|
114
|
+
return if params[:branch] and not(pub[:buildInfo][:branches].include? params[:branch])
|
115
|
+
puts "\t\t#{timestamp(pub[:publicationTime])} #{app.style(:class)} -- #{build_info(pub[:buildInfo])}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def build_info(build)
|
119
|
+
name = build[:buildId].style(:build_name)
|
120
|
+
branches = build[:branches].join(",").style(:branch)
|
121
|
+
"#{name} [#{branches}]"
|
122
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
category "System administration"
|
5
|
+
description "Open an SSH connection to the specified host."
|
6
|
+
usage "host [user]"
|
7
|
+
|
8
|
+
help "Opens an SSH session to the specified host. No command line arguments are passed."
|
9
|
+
|
10
|
+
validate do
|
11
|
+
return "must connect usherm first" if usherm.nil?
|
12
|
+
args.length == 2
|
13
|
+
end
|
14
|
+
|
15
|
+
tab 0 do
|
16
|
+
(usherm[:usherSystemId][:systemHosts].map { |host| host_supports_ssh?(host) ? host[:hostName] : nil }).compact rescue []
|
17
|
+
end
|
18
|
+
|
19
|
+
run do
|
20
|
+
params = parse_params(args)
|
21
|
+
usherm.ensure_fresh
|
22
|
+
acl = usherm.acl_for_service(params[:host], "ssh")
|
23
|
+
return show_error("#{params[:host]}: usher does not list ssh ACL for host") unless acl
|
24
|
+
try_acl(params, acl) ? "" : "#{args[0]}: #{params[:host]}: unable to connect to host on any address"
|
25
|
+
end
|
26
|
+
|
27
|
+
###
|
28
|
+
|
29
|
+
def try_acl(params, acl)
|
30
|
+
host = usherm.host_named(params[:host])
|
31
|
+
service = usherm.service_for_id(acl[:idService])
|
32
|
+
options = [
|
33
|
+
{ host:host[:ipAddrInt], port:service[:port] },
|
34
|
+
{ host:host[:ipAddrExt], port:acl[:port] }
|
35
|
+
]
|
36
|
+
|
37
|
+
result = try_connection_options(options)
|
38
|
+
unless result.nil? then
|
39
|
+
process = fork { exec "ssh -l #{params[:user]} -p #{result[:port]} #{result[:ip]}" }
|
40
|
+
Process.waitpid(process)
|
41
|
+
end
|
42
|
+
|
43
|
+
not result.nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def host_supports_ssh?(host)
|
47
|
+
not usherm.acl_for_service(host, "ssh").nil?
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse_params(args)
|
51
|
+
if args.length == 3
|
52
|
+
return { host:args[1], user:args[2] }
|
53
|
+
else
|
54
|
+
if args[1].include? "@" then
|
55
|
+
comps = args[1].split("@")
|
56
|
+
return { host:comps[1], user:comps[0] }
|
57
|
+
else
|
58
|
+
return { host:args[1], user:"acres4" }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|