bolt_train_runner 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05f808a49cf3ef42710f71a26af756cfad964f9daaa7f836183d1942b090a448
4
- data.tar.gz: f60aa528888c02cd384536dd5d22f01238ea24847120cf972614c7f1fe4b51c0
3
+ metadata.gz: 0e80ec83f70924cb436ed6b458742180e1427d50e749485f2e4dac40bd61b4e5
4
+ data.tar.gz: 8df15fb1607cfd47767ebe616e6bbc4742da7b5a20793962a4d7a49424fc94b2
5
5
  SHA512:
6
- metadata.gz: 925a32c0daf73b6f07a95c9916662a3b3a162d153f4cceeb239e23f07a20c173579a5bbe9dc5f3698ff12ea8a8b2b764f200809fafe2868829778b291f7470a7
7
- data.tar.gz: 207ed2b67aafae90d742b4bf801ae661059393e9aa18b74af9e8b81cc1fd2d21c3c2b10a9fc47e7aa8bb8f61aec8bd44dfbc510b9d63ab76d83e7e3b20251d59
6
+ metadata.gz: c0294c14f12dbec5b0e7889535c135ead63b426c2a72db2add19e495169d90c5a85e9c375d4c918dd34b4bbb96aaad03ed4514f8c859d8197275c3e34c01dc06
7
+ data.tar.gz: d1229742d9593cc036830cbf2bd089d3f1cbb99945bdc0e0e4853a5ea92cadd60d074d1060f0ac3708f62f00e1319bd16512e59c5effa8602cec8611d60808fc
@@ -4,6 +4,7 @@ require 'rubygems'
4
4
  require 'colorize'
5
5
  require 'bolt_train_runner/comms'
6
6
  require 'bolt_train_runner/session_runner'
7
+ require 'bolt_train_runner/log'
7
8
 
8
9
  # Load all commands
9
10
  Dir[File.join(File.absolute_path(__dir__) + '/bolt_train_runner/commands') + "/**/*.rb"].each do |file|
@@ -12,13 +13,11 @@ end
12
13
 
13
14
  # TODO:
14
15
  # Add a lot more error handling
15
- # Add thread for consuming session files and issuing commands
16
16
  # Figure out best way to verify commands worked given that responses from JMRI are async
17
17
  # Figure out why it gets multiple messages back each time
18
18
  # Make debug output show what method/command the output is from
19
19
  # Make debug output not screw with the console prompt
20
- # Changing debug on or off and reconnecting doesn't actually seem to work to change debug level
21
- # Add a way to log to a file in addition to the console
20
+ # Add more user control over logging (where it goes, log level, etc.)
22
21
 
23
22
 
24
23
  class BoltTrainRunner
@@ -26,59 +25,60 @@ class BoltTrainRunner
26
25
  def run
27
26
  comms = nil
28
27
  session_runner = nil
29
- puts 'Welcome to the Bolty McBoltTrain Runner! Choo choo!'.cyan
30
- puts 'To list all commands, enter "help"'.cyan
31
- puts 'For help with a specific command, enter "<command> help"'.cyan
32
- puts 'First order of business: run "connect" to connect to the JMRI server'.cyan
28
+ log = Log.new
29
+ log.help('Welcome to the Bolty McBoltTrain Runner! Choo choo!')
30
+ log.help('To list all commands, enter "help"')
31
+ log.help('For help with a specific command, enter "<command> help"')
32
+ log.help('First order of business: run "connect" to connect to the JMRI server')
33
+
33
34
  loop do
34
35
  print '> '
35
36
  input = gets.chomp
36
37
  args = input.split(' ')
37
38
  command = args.shift
39
+ log.info_file("Console command: #{input}")
38
40
 
39
41
  case command
40
42
  when /^help$/i
41
- help
42
- when Commands.respond_to?(command)
43
- puts 'Commands can run this'
43
+ help(log)
44
44
  when /^connect$/i
45
- newcomms = Commands.connect(args)
45
+ newcomms = Commands.connect(args, log)
46
46
  comms = newcomms if newcomms
47
47
  when /^disconnect$/i
48
48
  session_runner.stop if session_runner
49
49
  session_runner = nil
50
- Commands.disconnect(comms)
50
+ Commands.disconnect(comms, log)
51
51
  comms = nil
52
52
  when /^sessions$/i
53
- session_runner = Commands.sessions(args, comms, session_runner)
53
+ session_runner = Commands.sessions(args, comms, session_runner, log)
54
54
  when /^debug$/i
55
- Commands.debug(args)
55
+ Commands.debug(args, log)
56
56
  when /^exit$/i
57
- Commands.exit_program(comms, session_runner)
57
+ Commands.exit_program(comms, session_runner, log)
58
58
  else
59
59
  if Commands.respond_to?(command)
60
60
  # The commands for directly manipulating the train should all
61
61
  # accept "args" and "comms" parameters. Because the CLI will pass
62
62
  # in args as an array and the session runner will pass in a hash,
63
63
  # these commands must be able to handle both.
64
- Commands.send(command.to_sym, args, comms)
64
+ Commands.send(command.to_sym, args, comms, log)
65
65
  else
66
- puts "Unknown command: #{command}".red
66
+ log.warn("Unknown command: #{command}")
67
67
  end
68
68
  end
69
69
  end
70
70
  end
71
71
 
72
- def help
73
- puts 'Available commands:'.cyan
74
- puts 'help - This help text'.cyan
75
- puts 'connect - Connect to the Bolt Train JMRI JSON server'.cyan
76
- puts 'disconnect - Disconnect from the JMRI server'.cyan
77
- puts 'power - Turn power on or off to the train'.cyan
78
- puts 'throttle - Set throttle to a value between 0 and 10'.cyan
79
- puts 'move - Move the train in the given direction at the given speed for a certain length of time'.cyan
80
- puts 'stop - Stop the train'.cyan
81
- puts 'exit - Exit program'.cyan
72
+ def help(log)
73
+ log.help('Available commands:')
74
+ log.help('help - This help text')
75
+ log.help('connect - Connect to the Bolt Train JMRI JSON server')
76
+ log.help('disconnect - Disconnect from the JMRI server')
77
+ log.help('power - Turn power on or off to the train')
78
+ log.help('throttle - Set throttle to a value between 0 and 10')
79
+ log.help('move - Move the train in the given direction at the given speed for a certain length of time')
80
+ log.help('stop - Stop the train')
81
+ log.help('exit - Exit program')
82
82
  end
83
83
 
84
84
  end
@@ -1,23 +1,25 @@
1
1
  require 'bolt_train_runner/conf'
2
2
  require 'bolt_train_runner/comms'
3
- require 'colorize'
3
+ require 'bolt_train_runner/log'
4
4
 
5
5
  module Commands
6
- def self.connect(args)
6
+ def self.connect(args, log)
7
7
  conf = Conf.load_conf
8
8
  if !args.empty? && args[0] =~ /help/i
9
- puts 'Command: connect'.cyan
10
- puts 'Syntax: connect [server:port]'.cyan
11
- puts 'If called with no argument, it will attempt to use the last specified server:port'.cyan
12
- puts 'If this is the first time connect was called with no arguments, it will prompt you for the server and port'.cyan
9
+ log.help('Command: connect')
10
+ log.help('Syntax: connect [server:port]')
11
+ log.help('If called with no argument, it will attempt to use the last specified server:port')
12
+ log.help('If this is the first time connect was called with no arguments, it will prompt you for the server and port')
13
13
  return
14
14
  end
15
15
  if args.empty?
16
16
  server = conf['server']
17
17
  unless server
18
- print 'Please enter server:port [10.0.7.82:12080] > '
18
+ prompt = 'Please enter server:port [10.0.7.82:12080] > '
19
+ print prompt
19
20
  server = gets.chomp
20
21
  server = '10.0.7.82:12080' if server.empty?
22
+ log.info_file("#{prompt} #{server}")
21
23
  end
22
24
  else
23
25
  server = args[0]
@@ -25,9 +27,9 @@ module Commands
25
27
  conf['server'] = server
26
28
  Conf.save_conf(conf)
27
29
 
28
- puts "Connecting to ws://#{server}/json/".green
29
- comms = Comms.new(server)
30
- puts "Connected".green
30
+ log.info("Connecting to ws://#{server}/json/")
31
+ comms = Comms.new(server, log)
32
+ log.info("Connected")
31
33
  return comms
32
34
  end
33
35
  end
@@ -1,24 +1,24 @@
1
- require 'colorize'
2
1
  require 'bolt_train_runner/conf'
2
+ require 'bolt_train_runner/log'
3
3
 
4
4
  module Commands
5
- def self.debug(args)
5
+ def self.debug(args, log)
6
6
  if args.empty? || args[0] =~ /help/i
7
- puts 'Command: debug'.cyan
8
- puts 'Syntax: debug <on|off>'.cyan
7
+ log.help('Command: debug')
8
+ log.help('Syntax: debug <on|off>')
9
9
  #Should fix this at some point
10
- puts 'Turns debug logging on or off. Will require disconnecting and reconnecting to take effect.'.cyan
11
- puts 'Choice will be persistent across program invocations.'.cyan
10
+ log.help('Turns debug logging on or off. Choice will be persistent across program invocations.')
12
11
  return
13
12
  end
14
13
  state = args[0]
15
14
  if !['on','off'].include?(state)
16
- puts 'Debug must be called with either "on" or "off"'.red
15
+ log.error('Debug must be called with either "on" or "off"')
17
16
  return
18
17
  end
19
18
  conf = Conf.load_conf
20
19
  conf['debug'] = state == 'on'
21
20
  Conf.save_conf(conf)
22
- puts "Debug mode #{state}".green
21
+ state == 'on' ? log.set_console_level('DEBUG') : log.set_console_level('INFO')
22
+ log.info("Debug mode #{state}")
23
23
  end
24
24
  end
@@ -1,13 +1,13 @@
1
1
  require 'bolt_train_runner/comms'
2
- require 'colorize'
2
+ require 'bolt_train_runner/log'
3
3
 
4
4
  module Commands
5
- def self.disconnect(comms)
5
+ def self.disconnect(comms, log)
6
6
  if comms.nil?
7
- puts 'Not currently connected'.red
7
+ log.error('Not currently connected')
8
8
  return
9
9
  end
10
10
  comms.disconnect
11
- puts 'Disconnected'.green
11
+ log.info('Disconnected')
12
12
  end
13
13
  end
@@ -1,11 +1,12 @@
1
- require 'colorize'
2
1
  require 'bolt_train_runner/comms'
2
+ require 'bolt_train_runner/log'
3
3
 
4
4
  module Commands
5
- def self.exit_program(comms, session_runner)
5
+ def self.exit_program(comms, session_runner, log)
6
6
  session_runner.stop if session_runner
7
7
  comms.disconnect if comms
8
- puts 'Seeya later!'.green
8
+ log.info('Seeya later!')
9
+ log.close
9
10
  exit 0
10
11
  end
11
12
  end
@@ -1,19 +1,19 @@
1
1
  require 'bolt_train_runner/comms'
2
2
  require 'bolt_train_runner/commands/throttle'
3
3
  require 'bolt_train_runner/commands/stop'
4
- require 'colorize'
4
+ require 'bolt_train_runner/log'
5
5
 
6
6
  module Commands
7
- def self.move(args, comms)
7
+ def self.move(args, comms, log)
8
8
  unless comms
9
- puts 'Please connect first'.red
9
+ log.error('Please connect first')
10
10
  return
11
11
  end
12
12
  if args.empty? || args[0] =~ /help/i
13
- puts 'Command: move'.cyan
14
- puts 'Syntax: move <forward|reverse> <speed 0-10> <time 1-60>'.cyan
15
- puts 'Move the train the given direction at the given speed for the given number of seconds'.cyan
16
- puts 'Note that the power must be on first'.cyan
13
+ log.help('Command: move')
14
+ log.help('Syntax: move <forward|reverse> <speed 0-10> <time 1-60>')
15
+ log.help('Move the train the given direction at the given speed for the given number of seconds')
16
+ log.help('Note that the power must be on first')
17
17
  return
18
18
  end
19
19
 
@@ -27,28 +27,29 @@ module Commands
27
27
  end
28
28
 
29
29
  unless direction && speed && time
30
- puts 'Please provide direction, speed, and time'.red
30
+ log.error('Please provide direction, speed, and time')
31
31
  return
32
32
  end
33
33
  speed = speed.to_i
34
34
  time = time.to_i
35
+ direction = direction == 'f' ? 'forward' : direction == 'r' ? 'reverse' : direction
35
36
  unless ['forward','reverse'].include?(direction)
36
- puts 'Please provide "forward" or "reverse" for direction'.red
37
+ log.error('Please provide "forward" or "reverse" for direction')
37
38
  return
38
39
  end
39
40
  if speed < 0 or speed > 10
40
- puts 'Please select a speed between 0 and 10'.red
41
+ log.error('Please select a speed between 0 and 10')
41
42
  return
42
43
  end
43
44
  if time < 1 or time > 60
44
- puts 'Please select a time between 1 and 60 seconds'.red
45
+ log.error('Please select a time between 1 and 60 seconds')
45
46
  return
46
47
  end
47
48
 
48
- puts "Moving train #{direction} direction at speed #{speed} for #{time} seconds...".green
49
- Commands.throttle([speed,direction],comms)
49
+ log.info("Moving train #{direction} direction at speed #{speed} for #{time} seconds...")
50
+ Commands.throttle([speed, direction], comms, log)
50
51
  sleep(time)
51
- Commands.stop(nil, comms)
52
- puts 'Move complete'.green
52
+ Commands.stop(nil, comms, log)
53
+ log.info('Move complete')
53
54
  end
54
55
  end
@@ -1,16 +1,16 @@
1
1
  require 'bolt_train_runner/comms'
2
- require 'colorize'
2
+ require 'bolt_train_runner/log'
3
3
 
4
4
  module Commands
5
- def self.power(args, comms)
5
+ def self.power(args, comms, log)
6
6
  unless comms
7
- puts 'Please connect first'.red
7
+ log.error('Please connect first')
8
8
  return
9
9
  end
10
10
  if args.empty? || args[0] =~ /help/i
11
- puts 'Command: power'.cyan
12
- puts 'Syntax: power <on|off>'.cyan
13
- puts 'Turns power to the train on or off. Must first be connected.'.cyan
11
+ log.help('Command: power')
12
+ log.help('Syntax: power <on|off>')
13
+ log.help('Turns power to the train on or off. Must first be connected.')
14
14
  return
15
15
  end
16
16
 
@@ -21,7 +21,7 @@ module Commands
21
21
  end
22
22
 
23
23
  unless ['on','off'].include?(state)
24
- puts 'Please provide either "on" or "off"'.red
24
+ log.error('Please provide either "on" or "off"')
25
25
  return
26
26
  end
27
27
 
@@ -36,6 +36,6 @@ module Commands
36
36
  }
37
37
  }
38
38
  comms.send_message(message)
39
- puts "Power #{state}".green
39
+ log.info("Power #{state}")
40
40
  end
41
41
  end
@@ -1,37 +1,37 @@
1
- require 'colorize'
2
1
  require 'bolt_train_runner/conf'
3
2
  require 'bolt_train_runner/session_runner'
3
+ require 'bolt_train_runner/log'
4
4
 
5
5
  module Commands
6
- def self.sessions(args, comms, session_runner)
6
+ def self.sessions(args, comms, session_runner, log)
7
7
  if args.empty? || args[0] =~ /help/i
8
- puts 'Command: sessions'.cyan
9
- puts 'Syntax: sessions <start|stop>'.cyan
10
- puts 'Start or stop the thread that monitors the sessions folder for sessions files. When running, this thread'.cyan
11
- puts 'will automatically execute the commands contained in sessions files generated by the bolt-train-api server'.cyan
12
- puts 'as they appear in the folder.'.cyan
8
+ log.help('Command: sessions')
9
+ log.help('Syntax: sessions <start|stop>')
10
+ log.help('Start or stop the thread that monitors the sessions folder for sessions files. When running, this thread')
11
+ log.help('will automatically execute the commands contained in sessions files generated by the bolt-train-api server')
12
+ log.help('as they appear in the folder.')
13
13
  return
14
14
  end
15
15
 
16
16
  state = args[0]
17
17
  starting = state == 'start'
18
18
  if !['start','stop'].include?(state)
19
- puts 'Please provide either "start" or "stop"'.red
19
+ log.error('Please provide either "start" or "stop"')
20
20
  return
21
21
  end
22
22
 
23
23
  unless comms
24
- puts 'Please connect first'.red
24
+ log.error('Please connect first')
25
25
  return
26
26
  end
27
27
 
28
28
  if starting and session_runner
29
- puts 'Session runner thread already started'.yellow
29
+ log.warn('Session runner thread already started')
30
30
  return session_runner
31
31
  end
32
32
 
33
33
  if !starting and !session_runner
34
- puts 'No session runner thread currently running'.yellow
34
+ log.warn('No session runner thread currently running')
35
35
  return nil
36
36
  end
37
37
 
@@ -45,15 +45,17 @@ module Commands
45
45
  session_dir = conf['session_dir']
46
46
  unless session_dir
47
47
  # This should be changed to pick up BOLT_TRAIN_QUEUE_DIR automatically
48
- print 'Please enter directory for session files [/tmp/bolt-train-queue] > '
48
+ prompt = 'Please enter directory for session files [/tmp/bolt-train-queue] > '
49
+ print prompt
49
50
  session_dir = gets.chomp
50
51
  session_dir = '/tmp/bolt-train-queue' if session_dir.empty?
51
52
  conf['session_dir'] = session_dir
52
53
  Conf.save_conf(conf)
54
+ log.info_file("#{prompt} #{session_dir}")
53
55
  end
54
56
  end
55
57
 
56
- runner = SessionRunner.new(comms, session_dir)
58
+ runner = SessionRunner.new(comms, session_dir, log)
57
59
  runner.start
58
60
  return runner
59
61
  else
@@ -1,12 +1,12 @@
1
- require 'colorize'
2
1
  require 'bolt_train_runner/commands/throttle'
2
+ require 'bolt_train_runner/log'
3
3
 
4
4
  module Commands
5
- def self.stop(_args, comms)
5
+ def self.stop(_args, comms, log)
6
6
  unless comms
7
- puts 'Please connect first'.red
7
+ log.error('Please connect first')
8
8
  return
9
9
  end
10
- Commands.throttle([0],comms)
10
+ Commands.throttle([0], comms, log)
11
11
  end
12
12
  end
@@ -1,17 +1,17 @@
1
1
  require 'bolt_train_runner/comms'
2
- require 'colorize'
2
+ require 'bolt_train_runner/log'
3
3
 
4
4
  module Commands
5
- def self.throttle(args, comms)
5
+ def self.throttle(args, comms, log)
6
6
  unless comms
7
- puts 'Please connect first'.red
7
+ log.error('Please connect first')
8
8
  return
9
9
  end
10
10
  if args.empty? || args[0] =~ /help/i
11
- puts 'Command: throttle'.cyan
12
- puts 'Syntax: throttle <0-10> [forward|reverse]'.cyan
13
- puts 'Sets the throttle to the given level, between 0 and 10. May optionally provide a direction.'.cyan
14
- puts 'Note that power must be on first for this to take effect.'.cyan
11
+ log.help('Command: throttle')
12
+ log.help('Syntax: throttle <0-10> [forward|reverse]')
13
+ log.help('Sets the throttle to the given level, between 0 and 10. May optionally provide a direction.')
14
+ log.help('Note that power must be on first for this to take effect.')
15
15
  return
16
16
  end
17
17
 
@@ -24,12 +24,12 @@ module Commands
24
24
 
25
25
  speed = speed.to_i
26
26
  if speed < 0 or speed > 10
27
- puts 'Please select a speed between 0 and 10'.red
27
+ log.error('Please select a speed between 0 and 10')
28
28
  return
29
29
  end
30
30
 
31
31
  unless direction.nil? || ['forward','reverse'].include?(direction)
32
- puts 'Direction must be either "forward" or "reverse"'.red
32
+ log.error('Direction must be either "forward" or "reverse"')
33
33
  return
34
34
  end
35
35
 
@@ -45,6 +45,6 @@ module Commands
45
45
  message['data']['forward'] = direction == 'forward' if direction
46
46
  comms.send_message(message)
47
47
  direction_string = direction.nil? ? '' : " with direction #{direction}"
48
- puts "Throttle set to #{speed}#{direction_string}".green
48
+ log.info("Throttle set to #{speed}#{direction_string}")
49
49
  end
50
50
  end
@@ -1,7 +1,8 @@
1
1
  require 'websocket-client-simple'
2
2
  require 'json'
3
- require 'colorize'
4
3
  require 'bolt_train_runner/conf'
4
+ require 'bolt_train_runner/log'
5
+ require 'pry-byebug'
5
6
 
6
7
  # Sending and receiving responses is a little bit funky
7
8
  # Since we have to receive messages asynchronously, and because
@@ -17,16 +18,17 @@ class Comms
17
18
  @heartbeat_thread = nil
18
19
  @consumer_thread = nil
19
20
  @kill_threads = false
21
+ @log = nil
20
22
 
21
- def initialize(server)
22
- debug = Conf.debug
23
- @ws = WebSocket::Client::Simple.connect("ws://#{server}/json/")
24
- @ws.on :message do |msg|
23
+ def initialize(server, log)
24
+ @log = log
25
+ @ws = WebSocket::Client::Simple.connect("ws://#{server}/json/", @log)
26
+ @ws.on :message do |msg, logger|
25
27
  data = JSON.parse(msg.data)
26
- puts "Received #{data}" if (data['type'] != 'hello') if debug
28
+ logger.debug("Received #{data}\n> ")
27
29
  end
28
- @ws.on :error do |e|
29
- puts "Error from Websocket: #{e}".red
30
+ @ws.on :error do |e, logger|
31
+ logger.error("Error from Websocket: #{e}")
30
32
  end
31
33
 
32
34
  @heartbeat_thread = Thread.new { run_heartbeat }
@@ -54,9 +56,8 @@ class Comms
54
56
  # Expects a hash with the correctly formed message, which
55
57
  # will get transformed to a JSON string by this function
56
58
  def send_message(message)
57
- debug = Conf.debug
58
59
  message = JSON.generate(message)
59
- puts "Sending #{message}" if debug
60
+ @log.debug("Sending #{message}")
60
61
  @ws.send(message)
61
62
  end
62
63
 
@@ -3,7 +3,9 @@ require 'yaml'
3
3
  class Conf
4
4
  attr_reader :CONFFILE
5
5
 
6
- CONFFILE = File.expand_path('~/.bolttrain.conf')
6
+ CONFFILE = File.expand_path('~/.bolttrain/config')
7
+ CONFDIR = File.split(CONFFILE)[0]
8
+ Dir.mkdir(CONFDIR) unless File.exist?(CONFDIR)
7
9
  File.write(CONFFILE, "---\n{}") unless File.exist?(CONFFILE)
8
10
 
9
11
  def self.load_conf
@@ -0,0 +1,99 @@
1
+ require 'logger'
2
+ require 'colorize'
3
+ class Log
4
+
5
+ @loggers = []
6
+
7
+ def initialize(file='~/.bolttrain/runner.log', console_level='INFO', file_level='DEBUG')
8
+ file = File.expand_path(file)
9
+ dir = File.split(file)[0]
10
+ Dir.mkdir(dir) unless File.exist?(dir)
11
+ @console = Logger.new(STDOUT,
12
+ level: console_level,
13
+ formatter: proc { |sev, datetime, progname, msg| "#{msg}\n" })
14
+ @file = Logger.new(file, 'daily', level: file_level)
15
+ end
16
+
17
+ def set_console_level(level)
18
+ @console.level = level
19
+ end
20
+
21
+ def set_file_level(level)
22
+ @file.level = level
23
+ end
24
+
25
+ def debug(msg, console=true, file=true)
26
+ @console.debug(msg) if console
27
+ @file.debug(msg) if file
28
+ end
29
+
30
+ def debug_console(msg)
31
+ debug(msg, true, false)
32
+ end
33
+
34
+ def debug_file(msg)
35
+ debug(msg, false, true)
36
+ end
37
+
38
+ # Just for printing help text to the console. Doesn't need to be logged.
39
+ def help(msg)
40
+ @console.info(msg.cyan)
41
+ end
42
+
43
+ def info(msg, console=true, file=true)
44
+ @console.info(msg.green) if console
45
+ @file.info(msg) if file
46
+ end
47
+
48
+ def info_console(msg)
49
+ info(msg, true, false)
50
+ end
51
+
52
+ def info_file(msg)
53
+ info(msg, false, true)
54
+ end
55
+
56
+ def warn(msg, console=true, file=true)
57
+ @console.warn(msg.yellow) if console
58
+ @file.warn(msg) if file
59
+ end
60
+
61
+ def warn_console(msg)
62
+ warn(msg, true, false)
63
+ end
64
+
65
+ def warn_file(msg)
66
+ warn(msg, false, true)
67
+ end
68
+
69
+ def error(msg, console=true, file=true)
70
+ @console.error(msg.red) if console
71
+ @file.error(msg) if file
72
+ end
73
+
74
+ def error_console(msg)
75
+ error(msg, true, false)
76
+ end
77
+
78
+ def error_file(msg)
79
+ error(msg, false, true)
80
+ end
81
+
82
+ def fatal(msg, console=true, file=true)
83
+ @console.fatal(msg.red) if console
84
+ @file.fatal(msg) if file
85
+ end
86
+
87
+ def fatal_console(msg)
88
+ fatal(msg, true, false)
89
+ end
90
+
91
+ def fatal_file(msg)
92
+ fatal(msg, false, true)
93
+ end
94
+
95
+ def close
96
+ @console.close
97
+ @file.close
98
+ end
99
+ end
@@ -13,14 +13,16 @@ class SessionRunner
13
13
 
14
14
  @session_thread = nil
15
15
  @kill_thread = false
16
+ @log = nil
16
17
 
17
- def initialize(comms, session_dir)
18
+ def initialize(comms, session_dir, log)
18
19
  raise 'comms must not be nil' if comms.nil?
19
20
  raise 'session_dir must not be nil' if session_dir.nil?
20
21
  raise 'session_dir does not exist' unless File.exist?(session_dir)
21
22
 
22
23
  @session_dir = session_dir
23
24
  @comms = comms
25
+ @log = log
24
26
  end
25
27
 
26
28
  def start
@@ -29,7 +31,7 @@ class SessionRunner
29
31
 
30
32
  def stop
31
33
  @kill_thread = true
32
- puts 'Stopping Session Runner'.magenta
34
+ @log.info('Stopping Session Runner')
33
35
  @session_thread.join if @session_thread
34
36
  end
35
37
 
@@ -44,17 +46,17 @@ class SessionRunner
44
46
  end
45
47
  session = data['session']
46
48
  email = session['email']
47
- puts "[Session Runner] Starting session for #{email}".magenta
49
+ @log.info("[Session Runner] Starting session for #{email}")
48
50
  commands = session['commands']
49
51
  commands.each do |args|
50
52
  c = args['command']
51
53
  args.delete('command')
52
- puts "[Session Runner] Sending command #{c}".magenta
53
- puts "[Session Runner] Arguments = #{args}".magenta
54
- Commands.send(c, args, @comms)
54
+ @log.info("[Session Runner] Sending command #{c}")
55
+ @log.info("[Session Runner] Arguments = #{args}")
56
+ Commands.send(c, args, @comms, @log)
55
57
  end
56
58
  File.delete(f)
57
- puts "[Session Runner] Session for #{email} complete".magenta
59
+ @log.info("[Session Runner] Session for #{email} complete")
58
60
  end
59
61
  end
60
62
  end
@@ -1,3 +1,3 @@
1
1
  module BoltTrainRunner
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1,17 @@
1
+ # Forked from https://github.com/shokai/websocket-client-simple
2
+ # Credit to Sho Hashimoto
3
+
4
+ require 'event_emitter'
5
+ require 'websocket'
6
+ require 'socket'
7
+ require 'openssl'
8
+ require 'uri'
9
+
10
+ require 'websocket-client-simple/client'
11
+
12
+ module WebSocket
13
+ module Client
14
+ module Simple
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,107 @@
1
+ # Forked from https://github.com/shokai/websocket-client-simple
2
+ # Credit to Sho Hashimoto
3
+
4
+ module WebSocket
5
+ module Client
6
+ module Simple
7
+
8
+ def self.connect(url, options={}, logger)
9
+ client = ::WebSocket::Client::Simple::Client.new
10
+ yield client if block_given?
11
+ client.connect url, options, logger
12
+ return client
13
+ end
14
+
15
+ class Client
16
+ include EventEmitter
17
+ attr_reader :url, :handshake
18
+ attr_accessor :logger
19
+
20
+ def connect(url, options={}, logger)
21
+ return if @socket
22
+ @logger = logger
23
+ @url = url
24
+ uri = URI.parse url
25
+ @socket = TCPSocket.new(uri.host,
26
+ uri.port || (uri.scheme == 'wss' ? 443 : 80))
27
+ if ['https', 'wss'].include? uri.scheme
28
+ ctx = OpenSSL::SSL::SSLContext.new
29
+ ctx.ssl_version = options[:ssl_version] || 'SSLv23'
30
+ ctx.verify_mode = options[:verify_mode] || OpenSSL::SSL::VERIFY_NONE #use VERIFY_PEER for verification
31
+ cert_store = OpenSSL::X509::Store.new
32
+ cert_store.set_default_paths
33
+ ctx.cert_store = cert_store
34
+ @socket = ::OpenSSL::SSL::SSLSocket.new(@socket, ctx)
35
+ @socket.connect
36
+ end
37
+ @handshake = ::WebSocket::Handshake::Client.new :url => url, :headers => options[:headers]
38
+ @handshaked = false
39
+ @pipe_broken = false
40
+ frame = ::WebSocket::Frame::Incoming::Client.new
41
+ @closed = false
42
+ once :__close do |err|
43
+ close
44
+ emit :close, err
45
+ end
46
+
47
+ @thread = Thread.new do
48
+ while !@closed do
49
+ begin
50
+ unless recv_data = @socket.getc
51
+ sleep 1
52
+ next
53
+ end
54
+ unless @handshaked
55
+ @handshake << recv_data
56
+ if @handshake.finished?
57
+ @handshaked = true
58
+ emit :open, @logger
59
+ end
60
+ else
61
+ frame << recv_data
62
+ while msg = frame.next
63
+ emit :message, msg, @logger
64
+ end
65
+ end
66
+ rescue => e
67
+ emit :error, e, @logger
68
+ end
69
+ end
70
+ end
71
+
72
+ @socket.write @handshake.to_s
73
+ end
74
+
75
+ def send(data, opt={:type => :text})
76
+ return if !@handshaked or @closed
77
+ type = opt[:type]
78
+ frame = ::WebSocket::Frame::Outgoing::Client.new(:data => data, :type => type, :version => @handshake.version)
79
+ begin
80
+ @socket.write frame.to_s
81
+ rescue Errno::EPIPE => e
82
+ @pipe_broken = true
83
+ emit :__close, e
84
+ end
85
+ end
86
+
87
+ def close
88
+ return if @closed
89
+ if !@pipe_broken
90
+ send nil, :type => :close
91
+ end
92
+ @closed = true
93
+ @socket.close if @socket
94
+ @socket = nil
95
+ emit :__close
96
+ Thread.kill @thread if @thread
97
+ end
98
+
99
+ def open?
100
+ @handshake.finished? and !@closed
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
107
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bolt_train_runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Burgan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-23 00:00:00.000000000 Z
11
+ date: 2019-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -39,7 +39,21 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: websocket-client-simple
42
+ name: websocket
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: event_emitter
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
@@ -91,8 +105,11 @@ files:
91
105
  - lib/bolt_train_runner/commands/throttle.rb
92
106
  - lib/bolt_train_runner/comms.rb
93
107
  - lib/bolt_train_runner/conf.rb
108
+ - lib/bolt_train_runner/log.rb
94
109
  - lib/bolt_train_runner/session_runner.rb
95
110
  - lib/bolt_train_runner/version.rb
111
+ - lib/websocket-client-simple.rb
112
+ - lib/websocket-client-simple/client.rb
96
113
  homepage: https://github.com/puppetlabs/bolt-train-runner
97
114
  licenses:
98
115
  - MIT