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,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
+