a4tools 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.bundle/install.log +38 -0
  3. data/.gitignore +2 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +38 -0
  6. data/a4tools.gemspec +38 -0
  7. data/bin/deploy_latest_clients +32 -0
  8. data/bin/devsite_config_server +48 -0
  9. data/bin/netshell +23 -0
  10. data/bin/update_server +101 -0
  11. data/bin/usher +54 -0
  12. data/lib/a4tools.rb +61 -0
  13. data/lib/a4tools/version.rb +3 -0
  14. data/lib/acres_client.rb +376 -0
  15. data/lib/clients/caching_client.rb +151 -0
  16. data/lib/clients/deployment_client.rb +53 -0
  17. data/lib/clients/kai_config_client.rb +39 -0
  18. data/lib/clients/usher_client.rb +72 -0
  19. data/lib/clients/usher_mgmt_client.rb +201 -0
  20. data/lib/event_manager.rb +24 -0
  21. data/lib/events.json +1 -0
  22. data/lib/net_shell/builtin_command.rb +312 -0
  23. data/lib/net_shell/builtin_commands/build.rb +251 -0
  24. data/lib/net_shell/builtin_commands/cd.rb +12 -0
  25. data/lib/net_shell/builtin_commands/connect.rb +122 -0
  26. data/lib/net_shell/builtin_commands/deploy.rb +280 -0
  27. data/lib/net_shell/builtin_commands/disconnect.rb +15 -0
  28. data/lib/net_shell/builtin_commands/excerpt.rb +97 -0
  29. data/lib/net_shell/builtin_commands/exit.rb +7 -0
  30. data/lib/net_shell/builtin_commands/get.rb +38 -0
  31. data/lib/net_shell/builtin_commands/help.rb +40 -0
  32. data/lib/net_shell/builtin_commands/host.rb +126 -0
  33. data/lib/net_shell/builtin_commands/inject.rb +42 -0
  34. data/lib/net_shell/builtin_commands/jsoncache.rb +80 -0
  35. data/lib/net_shell/builtin_commands/kai_event.rb +151 -0
  36. data/lib/net_shell/builtin_commands/persist.rb +24 -0
  37. data/lib/net_shell/builtin_commands/pwd.rb +6 -0
  38. data/lib/net_shell/builtin_commands/recap.rb +188 -0
  39. data/lib/net_shell/builtin_commands/references.rb +63 -0
  40. data/lib/net_shell/builtin_commands/select.rb +36 -0
  41. data/lib/net_shell/builtin_commands/send.rb +74 -0
  42. data/lib/net_shell/builtin_commands/set.rb +29 -0
  43. data/lib/net_shell/builtin_commands/show.rb +183 -0
  44. data/lib/net_shell/builtin_commands/site.rb +122 -0
  45. data/lib/net_shell/builtin_commands/ssh.rb +62 -0
  46. data/lib/net_shell/builtin_commands/talk.rb +90 -0
  47. data/lib/net_shell/builtin_commands/translate.rb +45 -0
  48. data/lib/net_shell/builtin_commands/unset.rb +14 -0
  49. data/lib/net_shell/builtin_commands/usher.rb +55 -0
  50. data/lib/net_shell/builtin_commands/usher_device.rb +39 -0
  51. data/lib/net_shell/builtin_commands/usher_site.rb +245 -0
  52. data/lib/net_shell/builtin_commands/usherm_connect.rb +21 -0
  53. data/lib/net_shell/colors.rb +149 -0
  54. data/lib/net_shell/command.rb +97 -0
  55. data/lib/net_shell/io.rb +132 -0
  56. data/lib/net_shell/net_shell.rb +396 -0
  57. data/lib/net_shell/prompt.rb +335 -0
  58. data/lib/object_builder/definitions/app_info_for_script.rb +83 -0
  59. data/lib/object_builder/definitions/connection_request.rb +28 -0
  60. data/lib/object_builder/definitions/device_info_for_system.rb +37 -0
  61. data/lib/object_builder/object_builder.rb +145 -0
  62. data/lib/talk.json +1 -0
  63. data/lib/talk_consumer.rb +235 -0
  64. 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,7 @@
1
+ category "Shell management"
2
+ description "Exits netshell"
3
+
4
+ run do
5
+ status = args.length >= 2 ? args[1].to_i : 0
6
+ exit status
7
+ 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
+