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,15 @@
|
|
1
|
+
category "Protocol manipulation"
|
2
|
+
description "Disconnect from remote server"
|
3
|
+
help <<-EOS
|
4
|
+
Immediately disconnects from the remote server, closing open websockets if appropriate.
|
5
|
+
EOS
|
6
|
+
|
7
|
+
validate do
|
8
|
+
return "must connect first" if client.nil?
|
9
|
+
end
|
10
|
+
|
11
|
+
run do
|
12
|
+
client.disconnect
|
13
|
+
""
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
category "Protocol manipulation"
|
2
|
+
description "Access an individual field in a JSON object"
|
3
|
+
usage "field_path"
|
4
|
+
|
5
|
+
help "Finds a field path inside a JSON object supplied over standard input. For example, use 'tok.rand' to find the 'rand' field inside the 'tok' object inside the object."
|
6
|
+
|
7
|
+
validate { args.length <= 2 }
|
8
|
+
|
9
|
+
tab :type do
|
10
|
+
talk.definition[:class].map { |defn| talk.truncated_name(defn[:name]) }
|
11
|
+
end
|
12
|
+
|
13
|
+
tab :class do
|
14
|
+
talk.definition[:class].map { |defn| talk.truncated_name(defn[:name]) }
|
15
|
+
end
|
16
|
+
|
17
|
+
opt :class, "Excerpt the first field of the given class name", :type => :string
|
18
|
+
opt :no_hint, "Do not force result object to contain an __class field"
|
19
|
+
opt :type, "Assume the object has the specified type", :type => :string
|
20
|
+
opt :no_bypass, "Do not automatically bypass JSONRPCRequest, JSONRPCResponse and NamedObjectWrapper toplevels"
|
21
|
+
|
22
|
+
run do
|
23
|
+
object, type = toplevel_value
|
24
|
+
return show_error("Invalid JSON") if object.nil?
|
25
|
+
|
26
|
+
data, type = talk.locate_data(object, args[1], params[:type])
|
27
|
+
return show_error("Unable to locate field in JSON.") if data.nil?
|
28
|
+
|
29
|
+
result = if data.is_a? Hash or data.is_a? Array then
|
30
|
+
unless params[:class].nil?
|
31
|
+
data = find_class(params[:class], data, type)
|
32
|
+
return show_error("Unable to locate class type in JSON") if data.nil?
|
33
|
+
type = params[:class]
|
34
|
+
end
|
35
|
+
data[:__class] = talk.expand_name(type) if data.is_a? Hash and not params[:no_hint]
|
36
|
+
JSON.generate(data)
|
37
|
+
else
|
38
|
+
data
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
###
|
43
|
+
|
44
|
+
def find_class(target, data, type=nil)
|
45
|
+
return find_class_in_array(target, data, type) if data.is_a? Array
|
46
|
+
|
47
|
+
type ||= talk.guess_class(data)
|
48
|
+
cls = talk.class_named(type) rescue nil
|
49
|
+
|
50
|
+
if cls.nil? then
|
51
|
+
data.each do |key, value|
|
52
|
+
searchval = find_class(target, value)
|
53
|
+
return searchval unless searchval.nil?
|
54
|
+
end
|
55
|
+
else
|
56
|
+
cls[:field].each do |field|
|
57
|
+
value = data[field[:name].to_sym]
|
58
|
+
fieldtype = talk.expand_name(field[:type].first)
|
59
|
+
next if value.nil? or fieldtype.nil?
|
60
|
+
return value if talk.name_matches?(fieldtype, target)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def find_class_in_array(target, data, type)
|
68
|
+
data.each do |datum|
|
69
|
+
result = find_class(target, datum, type)
|
70
|
+
return result unless result.nil?
|
71
|
+
end
|
72
|
+
|
73
|
+
return nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def toplevel_value
|
77
|
+
json = @input.read_all
|
78
|
+
object = symbolify(JSON.parse(json)) rescue nil
|
79
|
+
type = (talk.expand_name(params[:type]) rescue nil) || talk.guess_class(object) rescue nil
|
80
|
+
|
81
|
+
return nil if type.nil? or object.nil?
|
82
|
+
return [object, type] if params[:no_bypass]
|
83
|
+
return bypass(object, type)
|
84
|
+
end
|
85
|
+
|
86
|
+
def bypass(object, type)
|
87
|
+
case type
|
88
|
+
when "com.acres4.common.info.NamedObjectWrapper"
|
89
|
+
return bypass(object[:body], object[:className])
|
90
|
+
when "com.acres4.common.info.JSONRPCRequest"
|
91
|
+
return bypass(object[:params], talk.guess_class(object[:params]))
|
92
|
+
when "com.acres4.common.info.JSONRPCResponse"
|
93
|
+
return bypass(object[:result], talk.guess_class(object[:result]))
|
94
|
+
else
|
95
|
+
return [object, type]
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
category "Shell management"
|
2
|
+
description "Get contents of environment variables"
|
3
|
+
usage "[variable_name]"
|
4
|
+
help <<-EOS
|
5
|
+
List the value of environment variable ENV, or all environment variables if not specified.
|
6
|
+
|
7
|
+
Environment variables are NOT imported from your system's native shell.
|
8
|
+
EOS
|
9
|
+
|
10
|
+
validate do
|
11
|
+
case args.length
|
12
|
+
when 1
|
13
|
+
true
|
14
|
+
when 2
|
15
|
+
if @shell.get_env(args[1]).nil?
|
16
|
+
"#{args[1]}: key not set"
|
17
|
+
else
|
18
|
+
true
|
19
|
+
end
|
20
|
+
else
|
21
|
+
false
|
22
|
+
end
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
tab 0 do
|
27
|
+
@shell.env.keys
|
28
|
+
end
|
29
|
+
|
30
|
+
run do
|
31
|
+
if args.length == 2 then
|
32
|
+
@shell.get_env(args[1])
|
33
|
+
else
|
34
|
+
list = []
|
35
|
+
@shell.env.each { |key, value| list.push "#{key.to_s.style(:environment)}: \"#{value.to_s.bold}\"" }
|
36
|
+
list.join("\n")
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
category "Shell management"
|
2
|
+
description "Show help for a command"
|
3
|
+
|
4
|
+
tab 0 do
|
5
|
+
@shell.built_ins
|
6
|
+
end
|
7
|
+
|
8
|
+
help <<-EOS
|
9
|
+
Show help for a specific built-in command, or outline all built-in commands if none is available.
|
10
|
+
EOS
|
11
|
+
|
12
|
+
run { args.length == 1 ? list_all_commands : list_command(args[1]) }
|
13
|
+
|
14
|
+
###
|
15
|
+
|
16
|
+
def list_all_commands
|
17
|
+
(categories.map { |cat| list_category(cat) }).join("\n\n")
|
18
|
+
end
|
19
|
+
|
20
|
+
def list_command(name)
|
21
|
+
return show_error("#{name}: command not found") unless @shell.has_built_in?(name)
|
22
|
+
cmd = @shell.built_in(name).new(@shell)
|
23
|
+
cmd.educate
|
24
|
+
end
|
25
|
+
|
26
|
+
def categories
|
27
|
+
(@shell.built_ins.map { |name| @shell.built_in(name).category_text }).sort.uniq
|
28
|
+
end
|
29
|
+
|
30
|
+
def list_category(category)
|
31
|
+
commands = @shell.built_ins.select { |name| @shell.built_in(name).category_text == category }
|
32
|
+
cat = category.style(:category)
|
33
|
+
cmds = (commands.sort.map do |name|
|
34
|
+
cmd = @shell.built_in(name).new(@shell)
|
35
|
+
usermark = cmd.user_defined? ? "@".style(:userdefined) : " "
|
36
|
+
"#{sprintf("%25s", name.to_s).style(:command)}#{usermark} -- #{cmd.description}"
|
37
|
+
end).join("\n")
|
38
|
+
|
39
|
+
[cat, cmds].join("\n")
|
40
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
category "Usher"
|
2
|
+
description "Show information about Usher hosts"
|
3
|
+
usage "hostname"
|
4
|
+
help <<-EOS
|
5
|
+
Shows information for a given usher host. If no usher host is specified, lists all hosts.
|
6
|
+
EOS
|
7
|
+
|
8
|
+
validate do
|
9
|
+
return show_error("must connect usherm first") if usherm.nil?
|
10
|
+
args.length < 3
|
11
|
+
end
|
12
|
+
|
13
|
+
tab 0 do
|
14
|
+
(usherm[:usherSystemId][:systemHosts].map { |host| host[:hostName] }) rescue []
|
15
|
+
end
|
16
|
+
|
17
|
+
run do
|
18
|
+
usherm.ensure_fresh
|
19
|
+
if args.length == 1 then
|
20
|
+
(usherm[:usherSystemId][:systemHosts].map do |host|
|
21
|
+
concise_host(host)
|
22
|
+
end).join("\n")
|
23
|
+
elsif args.length == 2 then
|
24
|
+
host = usherm.host_named(args[1])
|
25
|
+
return show_error("#{args[1]}: unknown host") if host.nil?
|
26
|
+
verbose_host(host)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
###
|
31
|
+
|
32
|
+
def string_for_range(start, last, params={})
|
33
|
+
if start == last then
|
34
|
+
last
|
35
|
+
else
|
36
|
+
"#{start}-#{last}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def collapse_ranges(elements)
|
41
|
+
return "None" if elements.nil? or elements.empty?
|
42
|
+
elements = (elements.map { |element| element.to_i }).sort
|
43
|
+
|
44
|
+
ranges = []
|
45
|
+
start = elements.first
|
46
|
+
last = nil
|
47
|
+
|
48
|
+
elements.each do |element|
|
49
|
+
if not(last.nil?) and element != last + 1
|
50
|
+
ranges.push(string_for_range(start, last))
|
51
|
+
start = element
|
52
|
+
end
|
53
|
+
last = element
|
54
|
+
end
|
55
|
+
|
56
|
+
ranges.push(string_for_range(start, last))
|
57
|
+
ranges.join(", ")
|
58
|
+
end
|
59
|
+
|
60
|
+
def provider_line(id_provider)
|
61
|
+
provider = usherm.provider(id_provider)
|
62
|
+
return "Non-existent provider #{id_provider}" if provider.nil?
|
63
|
+
return nil if provider[:isSpecial]
|
64
|
+
|
65
|
+
sites = collapse_ranges(provider[:idSites])
|
66
|
+
|
67
|
+
ipLines = ["Internal", "External"].map do |zone|
|
68
|
+
hosts = provider["usherHosts#{zone}".to_sym] || []
|
69
|
+
zone + ": " + if hosts.empty? then
|
70
|
+
"None"
|
71
|
+
else
|
72
|
+
urls = hosts.map { |host| host[:url] }
|
73
|
+
urls.join(", ")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
out = "\t\t#{provider[:product].style(:product)}: Site #{sites}\n"
|
78
|
+
out += (ipLines.map { |line| "\t\t\t#{line}"}).join("\n") + "\n"
|
79
|
+
out
|
80
|
+
end
|
81
|
+
|
82
|
+
def acl_line(acl)
|
83
|
+
service = usherm.service_for_id(acl[:idService])
|
84
|
+
return "Non-existent service #{acl[:idService]}" if service.nil?
|
85
|
+
|
86
|
+
proto = service[:isUdp] ? "UDP" : "TCP"
|
87
|
+
external_addr = [acl[:ip], acl[:port]].compact.join(":")
|
88
|
+
"\t\t#{service[:name].style(:service)}, #{proto} #{service[:port]} (#{external_addr} external)"
|
89
|
+
end
|
90
|
+
|
91
|
+
def verbose_host(host)
|
92
|
+
datacenter = usherm.datacenter(host[:idDataCenter])
|
93
|
+
out = "Host #{host[:hostName].style(:host)} (#{host[:idSystemHost]})\n"
|
94
|
+
out += "\tInternal #{host[:ipAddrInt].style(:ip)}\n"
|
95
|
+
out += "\tExternal #{host[:ipAddrExt].style(:ip)}\n"
|
96
|
+
if datacenter.nil?
|
97
|
+
out += "\tDatacenter: not found in usher (#{host[:idDataCenter]})\n"
|
98
|
+
else
|
99
|
+
out += "\tDatacenter: #{datacenter[:dataCenterName].style(:datacenter)} (#{host[:idDataCenter]})\n"
|
100
|
+
end
|
101
|
+
out += "\tHost environment: #{usherm.env_type(host[:systemHostEnvironment])}\n"
|
102
|
+
out += "\tUsher system type: #{usherm.system_type(host[:usherResponseType])}\n"
|
103
|
+
out += (host[:providers].map { |id_provider| provider_line(id_provider) }).compact.join("\n")
|
104
|
+
|
105
|
+
out += "\tACLs:\n"
|
106
|
+
acls = usherm.acls_for_host_id(host[:idSystemHost])
|
107
|
+
if acls.empty?
|
108
|
+
out += "\t\tNo ACLs for this host."
|
109
|
+
else
|
110
|
+
out += (acls.map { |acl| acl_line(acl) }).compact.join("\n")
|
111
|
+
end
|
112
|
+
|
113
|
+
out
|
114
|
+
end
|
115
|
+
|
116
|
+
def concise_host(host)
|
117
|
+
datacenter = usherm.datacenter(host[:idDataCenter])
|
118
|
+
dcnote = if datacenter.nil?
|
119
|
+
"unknown (#{host[:idDataCenter]})"
|
120
|
+
else
|
121
|
+
"#{datacenter[:dataCenterName].style(:datacenter)}"
|
122
|
+
end
|
123
|
+
|
124
|
+
"#{host[:hostName].style(:host)} -- #{dcnote} #{usherm.env_type(host[:systemHostEnvironment])}"
|
125
|
+
end
|
126
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
category "Protocol manipulation"
|
2
|
+
description "Inject a JSON string from the command line into another JSON object from STDIN"
|
3
|
+
usage "field_path json"
|
4
|
+
|
5
|
+
validate { args.length == 3 }
|
6
|
+
|
7
|
+
run do
|
8
|
+
path = args[1].split(".")
|
9
|
+
last = path.pop
|
10
|
+
json = @input.read_all
|
11
|
+
|
12
|
+
parent = nil
|
13
|
+
toplevel = object = symbolify(JSON.parse(json)) rescue nil
|
14
|
+
injected = JSON.parse(args[2]) rescue args[2]
|
15
|
+
|
16
|
+
return show_error("Invalid source object") if injected.nil?
|
17
|
+
return show_error("Invalid replacement object") if injected.nil?
|
18
|
+
|
19
|
+
until path.empty? do
|
20
|
+
field_name = path.first
|
21
|
+
path = path[1..-1]
|
22
|
+
object = field_value(object, field_name)
|
23
|
+
return show_error("Path not in JSON object") if object.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
return json if object.nil?
|
27
|
+
object[last.to_sym] = injected
|
28
|
+
toplevel.to_json
|
29
|
+
end
|
30
|
+
|
31
|
+
###
|
32
|
+
|
33
|
+
def field_value(object, field_name)
|
34
|
+
m = field_name.to_s.match(/^([a-zA-Z0-9_]+)\[([0-9]+)\]$/)
|
35
|
+
if m.nil? then
|
36
|
+
return object[field_name.to_sym] rescue nil
|
37
|
+
else
|
38
|
+
name = m[1]
|
39
|
+
value = object[name.to_sym][m[2].to_i] rescue nil
|
40
|
+
return value
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
category "Protocol manipulation"
|
2
|
+
description "Access a pre-cached request object"
|
3
|
+
usage "[identifier]"
|
4
|
+
help <<-EOS
|
5
|
+
Reading cache
|
6
|
+
#{command.style(:command)} builds object instances based on definitions. These definitions can either be Ruby scripts providing dynamic content, or JSON strings with static content.
|
7
|
+
|
8
|
+
The definitions included by default are located in lib/object_builder/definitions, and the filenames reflect the identifiers used by #{command.style(:command)}. Adding a file to this directory will cause it to be included automatically. Files ending in .rb will be interpreted as ruby scripts; all others will be treated as raw JSON.
|
9
|
+
|
10
|
+
Writing cache
|
11
|
+
Using the --store option #{command.style(:command)} can write objects to the cache.
|
12
|
+
EOS
|
13
|
+
|
14
|
+
validate do
|
15
|
+
return args.length <= 3 if params[:store]
|
16
|
+
return args.length == 2 if params[:persist]
|
17
|
+
args.length <= 2
|
18
|
+
end
|
19
|
+
|
20
|
+
tab 0 do
|
21
|
+
(ObjectBuilder.identifiers_like(args[1]).map { |id| id.to_s }) + ObjectBuilder.supported_classes
|
22
|
+
end
|
23
|
+
|
24
|
+
opt :store, "Store a JSON object supplied on STDIN to the specified identifier", :type => :string
|
25
|
+
opt :persist, "Write an identifier to disk"
|
26
|
+
opt :field, "Read a specific field from the JSON string", :type => :string
|
27
|
+
opt :type, "Assume the top-level datatype is of a specified type", :type => :string
|
28
|
+
|
29
|
+
run do
|
30
|
+
return store if params[:store]
|
31
|
+
return persist if params[:persist]
|
32
|
+
read
|
33
|
+
end
|
34
|
+
|
35
|
+
###
|
36
|
+
|
37
|
+
def acquire_object
|
38
|
+
obj = JSON.parse(@input.read_all) rescue nil
|
39
|
+
talk.locate_data(obj, params[:field], params[:type]) rescue nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def store
|
43
|
+
description = args[1] rescue "Defined from console"
|
44
|
+
obj, type = acquire_object
|
45
|
+
return show_error("Unable to acquire field from JSON") if obj.nil?
|
46
|
+
|
47
|
+
obj[:__class] = type unless type.nil?
|
48
|
+
|
49
|
+
ObjectBuilder.load_object(obj, params[:store], description)
|
50
|
+
""
|
51
|
+
end
|
52
|
+
|
53
|
+
def persist
|
54
|
+
builder = ObjectBuilder[args[1]]
|
55
|
+
return show_error("#{args[1]}: no such identifier") if builder.nil?
|
56
|
+
File.write(File.join(@shell.shelldir(:json), args[1]), builder.value.to_json)
|
57
|
+
""
|
58
|
+
end
|
59
|
+
|
60
|
+
def read
|
61
|
+
if args.length == 1 then
|
62
|
+
builders = ObjectBuilder.builders
|
63
|
+
return show_error("no builders defined") if builders.empty?
|
64
|
+
return show_builder_list(builders)
|
65
|
+
end
|
66
|
+
|
67
|
+
builder = ObjectBuilder[args[1]]
|
68
|
+
return builder.value.to_json unless builder.nil?
|
69
|
+
|
70
|
+
builders = ObjectBuilder.builders_for_name(args[1])
|
71
|
+
return "#{args[0]}: #{args[1]}: no such identifier or class in cache" if builders.empty?
|
72
|
+
show_builder_list(builders)
|
73
|
+
end
|
74
|
+
|
75
|
+
def show_builder_list(builders)
|
76
|
+
(builders.map do |builder|
|
77
|
+
"#{builder.name.to_s.style(:class)} #{builder.identifier.to_s.green}: #{builder.description}"
|
78
|
+
end).join("\n")
|
79
|
+
end
|
80
|
+
|