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,151 @@
1
+ category "Kai"
2
+ description "Generate machine events"
3
+ usage "[event_code machine_location]"
4
+
5
+ tab do
6
+ events.events.map { |event| event[:key] }
7
+ end
8
+
9
+ tab :machine do
10
+ machine_list
11
+ end
12
+
13
+ opt :amount, "Cash value associated with event. Used for jackpot and handpays.", :type => :integer
14
+ opt :tier, "Player tier level name", :type => :string
15
+ opt :first_name, "Player first name", :type => :string
16
+ opt :last_name, "Player last name", :type => :string
17
+ opt :employee, "Employee card ID", :type => :integer
18
+ opt :patron, "Patron card I", :type => :integer
19
+ opt :machine, "Machine location", :type => :string
20
+
21
+ opt :allow_duplicate, "Allow duplicate machines when spamming with random machine IDs"
22
+ opt :spam, "Spam the event repeatedly", :type => :integer, :default => 1
23
+ opt :spam_interval, "Specify number of seconds between spams in milliseconds", :type => :integer, :default => 1000
24
+
25
+ opt :list_names, "List Kai events, alphabetized by name"
26
+
27
+ run do
28
+ if args.length == 1 then
29
+ list = events.events
30
+ (list.sort! { |a,b| a[:key] <=> b[:key] }) if params[:list_names]
31
+ (events.events.map do |event|
32
+ code = sprintf("%5d", event[:code]).style(:event_code)
33
+ key = sprintf("%35s", event[:key].to_s).style(:event_key)
34
+
35
+ "#{code} #{key} -- #{event[:description]}"
36
+ end).join("\n")
37
+ else
38
+ machine = args[2] rescue random_machine
39
+ code = event_code(args[1])
40
+ return show_error("Unknown event code #{code}") if code.nil?
41
+ return show_error("Unable to connect QA test interface") unless qa.connect_if_needed
42
+ return show_error("Only have #{machine_list.length} machines to choose from; either reduce spam count or allow duplicates") if params[:spam] > machine_list.length and not params[:allow_duplicate]
43
+
44
+ index = 0
45
+ allowed_list = machine_list
46
+ params[:spam].times do
47
+ index = index + 1
48
+ machine = params[:machine] || allowed_list.sample
49
+ allowed_list.delete(machine) unless params[:allow_duplicate]
50
+
51
+ message = build_request(args[1..-2].sample, machine)
52
+ puts "Sending event #{index} of #{params[:spam]}: #{event_description(message)}"
53
+ send_event(message)
54
+ sleep params[:spam_interval] * 1.0/1000.0 unless index == params[:spam]
55
+ end
56
+
57
+ ""
58
+ end
59
+ end
60
+
61
+ ##
62
+
63
+ def event_description(event)
64
+ name = event_name(event[:eventList][0][:event][:idEventCode]) || event[:eventList][0][:event][:idEventCode]
65
+ location = event[:eventList][0][:location]
66
+ "#{name} @ #{location}"
67
+ end
68
+
69
+ def machine_list
70
+ @shell.client(:config).machines rescue []
71
+ end
72
+
73
+ def random_machine
74
+ machine_list.sample
75
+ end
76
+
77
+ def send_event(message)
78
+ qa.inject_token(message)
79
+ jsonrpc = qa.jsonrpc_message(:qaTestEvent, "qatest", nil, message)
80
+ qa.send_message(jsonrpc).body
81
+ end
82
+
83
+ def build_request(code, machine)
84
+ {
85
+ __class: "com.acres4.common.info.mercury.qatest.QATestEventRequest",
86
+ tok:nil,
87
+ eventList:[ qa_event_table_item(code, machine) ]
88
+ }
89
+ end
90
+
91
+ def qa_event_table_item(code, machine)
92
+ {
93
+ event:event_table_item(code),
94
+ location:machine
95
+ }
96
+ end
97
+
98
+ def event_table_item(code)
99
+ {
100
+ idEventCode:code,
101
+ hostEvent:host_event(code),
102
+ collectStats:false,
103
+ receiptTime:Time.now.to_i,
104
+ playerRating:player_rating
105
+ }
106
+ end
107
+
108
+ def host_event(code)
109
+ {
110
+ priKey:0,
111
+ hostDeviceId:nil,
112
+ eventCode:code.to_s,
113
+ idPatron:params[:patron] || 0,
114
+ idEmployee:params[:employee] || 0,
115
+ amount:params[:amount] || 0,
116
+ meters:nil,
117
+ eventTime:Time.now.to_i,
118
+ hostTime:Time.now.to_i
119
+ }
120
+ end
121
+
122
+ def player_rating
123
+ return nil unless params[:patron] or params[:firstName] or params[:lastName] or params[:loyaltyTierStr]
124
+
125
+ {
126
+ idPatron:params[:patron] || 0,
127
+ firstName:params[:first_name] || "Little",
128
+ lastName:params[:last_name] || "Timmy",
129
+ loyaltyTierStr:params[:tier] || "Wood"
130
+ }
131
+ end
132
+
133
+ def event_by_identifier(identifier)
134
+ identifier ||= args[1]
135
+ identifier = identifier.to_i if identifier.is_a? String and identifier.match(/^[0-9]+$/)
136
+ events.events.each do |event|
137
+ return event if(event[:key].to_s == identifier.to_s or event[:code] == identifier)
138
+ end
139
+
140
+ pp identifier
141
+ pp args[1]
142
+ nil
143
+ end
144
+
145
+ def event_code(identifier=nil)
146
+ event_by_identifier(identifier)[:code]
147
+ end
148
+
149
+ def event_name(identifier=nil)
150
+ event_by_identifier(identifier)[:key]
151
+ end
@@ -0,0 +1,24 @@
1
+ category "Shell management"
2
+ description "Persist an environment variable"
3
+ usage "variable1 variable2 ..."
4
+
5
+ help "Causes an evironment variable to persist between netshell sessions."
6
+
7
+ tab do
8
+ @shell.env.keys.reject { |key| args.include? key.to_s }
9
+ end
10
+
11
+ validate { (args.length >= 2 and not params[:all]) or (args.length == 1 and params[:all]) }
12
+
13
+ opt :all, "Persist all variables"
14
+
15
+ run do
16
+ variables = if params[:all]
17
+ [] # causes persist to save everything
18
+ else
19
+ args[1..-1]
20
+ end
21
+
22
+ @shell.persist_env(variables)
23
+ ""
24
+ end
@@ -0,0 +1,6 @@
1
+ category "Shell management"
2
+ description "Current working directory"
3
+ help "Display current directory."
4
+
5
+ validate { args.length == 1 }
6
+ run { Dir.pwd }
@@ -0,0 +1,188 @@
1
+ category "Protocol manipulation"
2
+ description "Print message history for current connection"
3
+ usage [
4
+ "#{command} show all messages",
5
+ "#{command} n show nth message before most recent",
6
+ "#{command} start end show messages from start to end"
7
+ ]
8
+
9
+ help <<-EOS
10
+ Examples:
11
+ List all messages
12
+ #{command}
13
+
14
+ List most recent message
15
+ #{command} 0
16
+
17
+ List most recent 3 messages
18
+ #{command} 2 0
19
+
20
+ List first message in conversation
21
+ #{command} -1
22
+
23
+ List first 5 messages in conversation
24
+ #{command} -5 -1
25
+ EOS
26
+
27
+ opt :client, "Recap this history for a client other than the active client", :type => :string
28
+ opt :summary, "Only list class names in text mode"
29
+ opt :json, "Output as JSON"
30
+ opt :raw, "Don't wrap JSON objects with metadata objects."
31
+ opt :array, "Force JSON to always be an array, even if only a single object is returned"
32
+ opt :reverse, "Index messages from end of conversation (so message 0 is most recent)"
33
+
34
+ validate do
35
+ return "Must have an active client" if client.nil? and not params[:client]
36
+ return "#{params[:client]}: unknown client" if params[:client] and not @shell.clients.include? params[:client].to_sym
37
+ true
38
+ end
39
+
40
+ tab :client do
41
+ @shell.clients
42
+ end
43
+
44
+ run { use_json? ? json_output : text_output }
45
+
46
+ ###
47
+
48
+ def target_client
49
+ params[:client] ? @shell.client(params[:client]) : client
50
+ end
51
+
52
+ def messages
53
+ messages = target_client.history
54
+ end
55
+
56
+ def range_for_args(args)
57
+ case args.length
58
+ when 0,1
59
+ range = (0 .. -1)
60
+ when 2
61
+ range = args[1].to_i .. args[1].to_i
62
+ when 3
63
+ low = [args[1], args[2]].min
64
+ high = [args[1], args[2]].max
65
+ range = low.to_i .. high.to_i
66
+ end
67
+ end
68
+
69
+ def sender(msg)
70
+ case msg[:sender]
71
+ when :client
72
+ "client".light_blue
73
+ when :server
74
+ "server".magenta
75
+ end
76
+ end
77
+
78
+ def timecode(msg)
79
+ delta = msg[:time] - target_client.start_time
80
+ all_seconds = delta.to_i
81
+
82
+ milliseconds = 1000.0*(delta - all_seconds)
83
+ hours = (all_seconds / 3660).to_i
84
+ minutes = ((all_seconds - 3660*hours) / 60).to_i
85
+ seconds = (all_seconds - 3600*hours - 60*minutes).to_i
86
+
87
+ return sprintf("%3d:%02d:%02d.%03d", hours, minutes, seconds, milliseconds).light_black
88
+ end
89
+
90
+ def text_output
91
+ index = -1
92
+ set = params[:reverse] ? messages : messages.reverse
93
+ (set.reverse[range_for_args(args)].map do |msg|
94
+ index += 1
95
+ index_str = sprintf("%3d", index)
96
+ "#{index_str} #{timecode(msg)} #{sender(msg)} #{render_text(msg[:message])}"
97
+ end).join("\n")
98
+ end
99
+
100
+ def json_output
101
+ set = params[:reverse] ? messages : messages.reverse
102
+ set = (set.reverse[range_for_args(args)].map do |msg|
103
+ if params[:raw] then
104
+ msg[:message]
105
+ else
106
+ msg.reject { |k,v| k == :raw }
107
+ end
108
+ end)
109
+
110
+ set = set[0] if set.length == 1 and not params[:array]
111
+ set.to_json
112
+ end
113
+
114
+ def use_json?
115
+ params[:json] or params[:raw] or params[:array]
116
+ end
117
+
118
+ def render_text(message)
119
+ if params[:summary] then
120
+ render_summary(message)
121
+ else
122
+ message.is_a?(Hash) ? JSON.generate(message) : message
123
+ end
124
+ end
125
+
126
+ def render_summary(message)
127
+ toplevel, cls = pick_toplevel(message)
128
+ puts toplevel if cls.nil?
129
+ cls ||= talk.guess_class(toplevel)
130
+ class_name = cls.style(:class) || "Unknown"
131
+ id_str = message[:id] ? sprintf("%3d", message[:id]) : " "
132
+
133
+ sprintf("%s %20s %s %s",
134
+ id_str.style(:id),
135
+ method(message).style(:method_name),
136
+ class_name.style(:class),
137
+ human_readable_size(message.to_json.length)
138
+ )
139
+ end
140
+
141
+ def human_readable_size(size)
142
+ titles = [ "B", "KiB", "MiB", "GiB", "TiB" ]
143
+ titles.each_index do |idx|
144
+ title = titles[idx]
145
+ unit = 1024**idx
146
+ boundary = 1024*unit
147
+ return "#{size/unit} #{title}" if size < boundary or title == titles.last
148
+ end
149
+ end
150
+
151
+ def method(message)
152
+ return message[:method] if message.has_key? :method
153
+ request = find_request_with_id(message[:id])
154
+ request[:method] rescue "unknown"
155
+ end
156
+
157
+ def find_request_with_id(id)
158
+ target_client.history.each do |msg|
159
+ next if msg[:message].nil? or msg[:message][:id].nil? or not(msg[:message].has_key? :params)
160
+ return msg[:message] if msg[:message][:id].to_i == id.to_i
161
+ end
162
+
163
+ nil
164
+ end
165
+
166
+ def pick_toplevel(message)
167
+ message = symbolify(JSON.parse(message)) if message.is_a? String
168
+ if message[:jsonrpc] == "2.0" then
169
+ return bypass(message, "com.acres4.common.info.JSONRPCRequest") if message.has_key? :params
170
+ return [message, "Error"] unless message[:error].nil?
171
+ return bypass(message, "com.acres4.common.info.JSONRPCResponse") if message.has_key? :result
172
+ end
173
+
174
+ [message, talk.guess_class(message)]
175
+ end
176
+
177
+ def bypass(object, type)
178
+ case type
179
+ when "com.acres4.common.info.NamedObjectWrapper"
180
+ return bypass(object[:body], object[:className])
181
+ when "com.acres4.common.info.JSONRPCRequest"
182
+ return bypass(object[:params], talk.guess_class(object[:params]))
183
+ when "com.acres4.common.info.JSONRPCResponse"
184
+ return bypass(object[:result], talk.guess_class(object[:result]))
185
+ else
186
+ return [object, type]
187
+ end
188
+ end
@@ -0,0 +1,63 @@
1
+ category "Talk"
2
+ description "Find references to a Talk class"
3
+ usage "class_name"
4
+ help "Lists all classes and protocols referencing a particular Talk class."
5
+
6
+ validate { args.length == 2 }
7
+
8
+ tab 0 do
9
+ talk.things_named_like(args[1], [:class]).map { |thing| talk.truncated_name thing[:name] }
10
+ end
11
+
12
+ run do
13
+ search_cls = talk.class_named(args[1])
14
+ return show_error("#{args[1]}: no such class in talk") if search_cls.nil?
15
+ full_name = search_cls[:name]
16
+
17
+ methods = list_methods(full_name)
18
+ fields = list_fields(full_name)
19
+
20
+ if methods.length > 0 then
21
+ puts "Methods (#{methods.length})"
22
+ methods.each { |method| show_method(method[:protocol], method[:method]) }
23
+ end
24
+
25
+ if fields.length > 0 then
26
+ puts "Fields (#{fields.length})"
27
+ fields.each { |field| show_field(field[:class], field[:field]) }
28
+ end
29
+
30
+ ""
31
+ end
32
+
33
+ ###
34
+
35
+ def list_methods(name)
36
+ methods = []
37
+ talk.definition[:protocol].each do |proto|
38
+ proto[:method].each do |method|
39
+ methods.push({protocol:proto, method:method}) if(talk.name_matches?(name, method[:request]) or talk.name_matches?(name, method[:response]))
40
+ end
41
+ end
42
+
43
+ methods
44
+ end
45
+
46
+ def list_fields(name)
47
+ fields = []
48
+ talk.definition[:class].each do |cls|
49
+ cls[:field].each do |field|
50
+ fields.push({class:cls, field:field}) if talk.name_matches?(name, field[:type].first)
51
+ end
52
+ end
53
+
54
+ fields
55
+ end
56
+
57
+ def show_method(protocol, method)
58
+ puts "\t#{protocol[:name].style(:protcol_name)}: #{method[:name].style(:method_name)} #{method[:request].style(:class)} -> #{method[:response].style(:class)}"
59
+ end
60
+
61
+ def show_field(cls, field)
62
+ puts "\t#{cls[:name].style(:class)}: #{field[:name].style(:field_name)}#{field[:type][1..-1].join("")}"
63
+ end
@@ -0,0 +1,36 @@
1
+ category "Protocol manipulation"
2
+ description "Select a connection for console"
3
+ usage "select [conenction]"
4
+
5
+
6
+ tab(0) { @shell.clients }
7
+
8
+ run do
9
+ if args.length == 1 then
10
+ (@shell.clients.sort.map { |key| render_client(key) }).join("\n")
11
+ else
12
+ return show_error("#{args[1]}: no such client") unless @shell.clients.include?(args[1].to_sym)
13
+ @shell.set_active_client(args[1])
14
+ ""
15
+ end
16
+ end
17
+
18
+ def render_client(key)
19
+ target = @shell.client(key)
20
+ fmt_key = sprintf("%20s", key.to_s)
21
+ host = usherm.host_for_url(target.uri) || "unknown host"
22
+ info = source_id(target)
23
+
24
+ "#{fmt_key.style(:target)}: #{info} #{target.uri.to_s.style(:url)} (#{host.style(:host)})"
25
+ end
26
+
27
+ def source_id(target)
28
+ app_info = target.server_info || {}
29
+ version = target.version || app_info[:currentTalkVersion]
30
+ protocol = sprintf("%-6s", (version || "")).style(:protocol_name)
31
+ name = sprintf("%20s", ((app_info[:appName] rescue nil) || "")).style(:name)
32
+ commit = sprintf("%7s", ((app_info[:sourceRevision][0..6] rescue nil) || "")).style(:commit)
33
+ branch = sprintf("%-30s", ((app_info[:supportingRevisions].first[:branches].first rescue nil) || "")).style(:branch)
34
+
35
+ "#{protocol} #{commit} #{branch}"
36
+ end