train 2.1.7 → 2.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/train.rb +20 -20
  3. data/lib/train/errors.rb +1 -1
  4. data/lib/train/extras.rb +2 -2
  5. data/lib/train/extras/command_wrapper.rb +24 -24
  6. data/lib/train/extras/stat.rb +27 -27
  7. data/lib/train/file.rb +30 -30
  8. data/lib/train/file/local.rb +8 -8
  9. data/lib/train/file/local/unix.rb +5 -5
  10. data/lib/train/file/local/windows.rb +1 -1
  11. data/lib/train/file/remote.rb +8 -8
  12. data/lib/train/file/remote/aix.rb +1 -1
  13. data/lib/train/file/remote/linux.rb +2 -2
  14. data/lib/train/file/remote/qnx.rb +8 -8
  15. data/lib/train/file/remote/unix.rb +10 -14
  16. data/lib/train/file/remote/windows.rb +5 -5
  17. data/lib/train/globals.rb +1 -1
  18. data/lib/train/options.rb +8 -8
  19. data/lib/train/platforms.rb +8 -8
  20. data/lib/train/platforms/common.rb +1 -1
  21. data/lib/train/platforms/detect/helpers/os_common.rb +36 -32
  22. data/lib/train/platforms/detect/helpers/os_linux.rb +12 -12
  23. data/lib/train/platforms/detect/helpers/os_windows.rb +27 -29
  24. data/lib/train/platforms/detect/scanner.rb +4 -4
  25. data/lib/train/platforms/detect/specifications/api.rb +8 -8
  26. data/lib/train/platforms/detect/specifications/os.rb +252 -252
  27. data/lib/train/platforms/detect/uuid.rb +5 -7
  28. data/lib/train/platforms/platform.rb +9 -5
  29. data/lib/train/plugin_test_helper.rb +12 -12
  30. data/lib/train/plugins.rb +5 -5
  31. data/lib/train/plugins/base_connection.rb +13 -13
  32. data/lib/train/plugins/transport.rb +7 -7
  33. data/lib/train/transports/azure.rb +23 -23
  34. data/lib/train/transports/cisco_ios_connection.rb +20 -20
  35. data/lib/train/transports/clients/azure/graph_rbac.rb +2 -2
  36. data/lib/train/transports/clients/azure/vault.rb +4 -4
  37. data/lib/train/transports/docker.rb +4 -10
  38. data/lib/train/transports/gcp.rb +23 -23
  39. data/lib/train/transports/helpers/azure/file_credentials.rb +8 -8
  40. data/lib/train/transports/helpers/azure/file_parser.rb +1 -1
  41. data/lib/train/transports/helpers/azure/subscription_number_file_parser.rb +1 -1
  42. data/lib/train/transports/local.rb +22 -22
  43. data/lib/train/transports/mock.rb +33 -35
  44. data/lib/train/transports/ssh.rb +47 -47
  45. data/lib/train/transports/ssh_connection.rb +28 -28
  46. data/lib/train/transports/vmware.rb +32 -34
  47. data/lib/train/transports/winrm.rb +37 -37
  48. data/lib/train/transports/winrm_connection.rb +12 -12
  49. data/lib/train/version.rb +1 -1
  50. metadata +2 -2
@@ -18,9 +18,9 @@
18
18
  # See the License for the specific language governing permissions and
19
19
  # limitations under the License.
20
20
 
21
- require 'net/ssh'
22
- require 'net/scp'
23
- require 'train/errors'
21
+ require "net/ssh"
22
+ require "net/scp"
23
+ require "train/errors"
24
24
 
25
25
  module Train::Transports
26
26
  # Wrapped exception for any internally raised SSH-related errors.
@@ -34,10 +34,10 @@ module Train::Transports
34
34
  #
35
35
  # @author Fletcher Nichol <fnichol@nichol.ca>
36
36
  class SSH < Train.plugin(1) # rubocop:disable Metrics/ClassLength
37
- name 'ssh'
37
+ name "ssh"
38
38
 
39
- require 'train/transports/ssh_connection'
40
- require 'train/transports/cisco_ios_connection'
39
+ require "train/transports/ssh_connection"
40
+ require "train/transports/cisco_ios_connection"
41
41
 
42
42
  # add options for submodules
43
43
  include_options Train::Extras::CommandWrapper
@@ -45,7 +45,7 @@ module Train::Transports
45
45
  # common target configuration
46
46
  option :host, required: true
47
47
  option :port, default: 22, required: true
48
- option :user, default: 'root', required: true
48
+ option :user, default: "root", required: true
49
49
  option :key_files, default: nil
50
50
  option :password, default: nil
51
51
 
@@ -60,7 +60,7 @@ module Train::Transports
60
60
  option :pty, default: false
61
61
  option :proxy_command, default: nil
62
62
  option :bastion_host, default: nil
63
- option :bastion_user, default: 'root'
63
+ option :bastion_user, default: "root"
64
64
  option :bastion_port, default: 22
65
65
  option :non_interactive, default: false
66
66
  option :verify_host_key, default: false
@@ -89,34 +89,34 @@ module Train::Transports
89
89
  super(options)
90
90
 
91
91
  key_files = Array(options[:key_files])
92
- options[:auth_methods] ||= ['none']
92
+ options[:auth_methods] ||= ["none"]
93
93
 
94
94
  unless key_files.empty?
95
- options[:auth_methods].push('publickey')
95
+ options[:auth_methods].push("publickey")
96
96
  options[:keys_only] = true if options[:password].nil?
97
97
  options[:key_files] = key_files
98
98
  end
99
99
 
100
100
  unless options[:password].nil?
101
- options[:auth_methods].push('password', 'keyboard-interactive')
101
+ options[:auth_methods].push("password", "keyboard-interactive")
102
102
  end
103
103
 
104
- if options[:auth_methods] == ['none']
104
+ if options[:auth_methods] == ["none"]
105
105
  if ssh_known_identities.empty?
106
- fail Train::ClientError,
107
- 'Your SSH Agent has no keys added, and you have not specified a password or a key file'
106
+ raise Train::ClientError,
107
+ "Your SSH Agent has no keys added, and you have not specified a password or a key file"
108
108
  else
109
- logger.debug('[SSH] Using Agent keys as no password or key file have been specified')
110
- options[:auth_methods].push('publickey')
109
+ logger.debug("[SSH] Using Agent keys as no password or key file have been specified")
110
+ options[:auth_methods].push("publickey")
111
111
  end
112
112
  end
113
113
 
114
114
  if options[:pty]
115
- logger.warn('[SSH] PTY requested: stderr will be merged into stdout')
115
+ logger.warn("[SSH] PTY requested: stderr will be merged into stdout")
116
116
  end
117
117
 
118
118
  if [options[:proxy_command], options[:bastion_host]].all? { |type| !type.nil? }
119
- fail Train::ClientError, 'Only one of proxy_command or bastion_host needs to be specified'
119
+ raise Train::ClientError, "Only one of proxy_command or bastion_host needs to be specified"
120
120
  end
121
121
 
122
122
  super
@@ -142,30 +142,30 @@ module Train::Transports
142
142
  # @api private
143
143
  def connection_options(opts)
144
144
  connection_options = {
145
- logger: logger,
146
- user_known_hosts_file: '/dev/null',
147
- hostname: opts[:host],
148
- port: opts[:port],
149
- username: opts[:user],
150
- compression: opts[:compression],
151
- compression_level: opts[:compression_level],
152
- keepalive: opts[:keepalive],
153
- keepalive_interval: opts[:keepalive_interval],
154
- timeout: opts[:connection_timeout],
155
- connection_retries: opts[:connection_retries],
145
+ logger: logger,
146
+ user_known_hosts_file: "/dev/null",
147
+ hostname: opts[:host],
148
+ port: opts[:port],
149
+ username: opts[:user],
150
+ compression: opts[:compression],
151
+ compression_level: opts[:compression_level],
152
+ keepalive: opts[:keepalive],
153
+ keepalive_interval: opts[:keepalive_interval],
154
+ timeout: opts[:connection_timeout],
155
+ connection_retries: opts[:connection_retries],
156
156
  connection_retry_sleep: opts[:connection_retry_sleep],
157
- max_wait_until_ready: opts[:max_wait_until_ready],
158
- auth_methods: opts[:auth_methods],
159
- keys_only: opts[:keys_only],
160
- keys: opts[:key_files],
161
- password: opts[:password],
162
- forward_agent: opts[:forward_agent],
163
- proxy_command: opts[:proxy_command],
164
- bastion_host: opts[:bastion_host],
165
- bastion_user: opts[:bastion_user],
166
- bastion_port: opts[:bastion_port],
167
- non_interactive: opts[:non_interactive],
168
- transport_options: opts,
157
+ max_wait_until_ready: opts[:max_wait_until_ready],
158
+ auth_methods: opts[:auth_methods],
159
+ keys_only: opts[:keys_only],
160
+ keys: opts[:key_files],
161
+ password: opts[:password],
162
+ forward_agent: opts[:forward_agent],
163
+ proxy_command: opts[:proxy_command],
164
+ bastion_host: opts[:bastion_host],
165
+ bastion_user: opts[:bastion_user],
166
+ bastion_port: opts[:bastion_port],
167
+ non_interactive: opts[:non_interactive],
168
+ transport_options: opts,
169
169
  }
170
170
  # disable host key verification. The hash key and value to use
171
171
  # depends on the version of net-ssh in use.
@@ -203,20 +203,20 @@ module Train::Transports
203
203
  # 5.0+ style
204
204
  {
205
205
  # It's not a boolean anymore.
206
- 'true' => :always,
207
- 'false' => :never,
206
+ "true" => :always,
207
+ "false" => :never,
208
208
  true => :always,
209
209
  false => :never,
210
210
  # May be correct value, but strings from JSON config
211
- 'always' => :always,
212
- 'never' => :never,
211
+ "always" => :always,
212
+ "never" => :never,
213
213
  nil => :never,
214
214
  }.fetch(given, given)
215
215
  else
216
216
  # up to 4.2 style
217
217
  {
218
- 'true' => true,
219
- 'false' => false,
218
+ "true" => true,
219
+ "false" => false,
220
220
  nil => false,
221
221
  }.fetch(given, given)
222
222
  end
@@ -18,9 +18,9 @@
18
18
  # See the License for the specific language governing permissions and
19
19
  # limitations under the License.
20
20
 
21
- require 'net/ssh'
22
- require 'net/scp'
23
- require 'timeout'
21
+ require "net/ssh"
22
+ require "net/scp"
23
+ require "timeout"
24
24
 
25
25
  class Train::Transports::SSH
26
26
  # A Connection instance can be generated and re-generated, given new
@@ -63,17 +63,17 @@ class Train::Transports::SSH
63
63
  end
64
64
 
65
65
  def ssh_opts
66
- level = logger.debug? ? 'VERBOSE' : 'ERROR'
67
- fwd_agent = options[:forward_agent] ? 'yes' : 'no'
66
+ level = logger.debug? ? "VERBOSE" : "ERROR"
67
+ fwd_agent = options[:forward_agent] ? "yes" : "no"
68
68
 
69
69
  args = %w{ -o UserKnownHostsFile=/dev/null }
70
70
  args += %w{ -o StrictHostKeyChecking=no }
71
71
  args += %w{ -o IdentitiesOnly=yes } if options[:keys]
72
72
  args += %w{ -o BatchMode=yes } if options[:non_interactive]
73
- args += %W( -o LogLevel=#{level} )
74
- args += %W( -o ForwardAgent=#{fwd_agent} ) if options.key?(:forward_agent)
73
+ args += %W{ -o LogLevel=#{level} }
74
+ args += %W{ -o ForwardAgent=#{fwd_agent} } if options.key?(:forward_agent)
75
75
  Array(options[:keys]).each do |ssh_key|
76
- args += %W( -i #{ssh_key} )
76
+ args += %W{ -i #{ssh_key} }
77
77
  end
78
78
  args
79
79
  end
@@ -86,19 +86,19 @@ class Train::Transports::SSH
86
86
  return @proxy_command unless @proxy_command.nil?
87
87
  args = %w{ ssh }
88
88
  args += ssh_opts
89
- args += %W( #{@bastion_user}@#{@bastion_host} )
90
- args += %W( -p #{@bastion_port} )
89
+ args += %W{ #{@bastion_user}@#{@bastion_host} }
90
+ args += %W{ -p #{@bastion_port} }
91
91
  args += %w{ -W %h:%p }
92
- args.join(' ')
92
+ args.join(" ")
93
93
  end
94
94
 
95
95
  # (see Base::Connection#login_command)
96
96
  def login_command
97
97
  args = ssh_opts
98
- args += %W( -o ProxyCommand='#{generate_proxy_command}' ) if check_proxy
99
- args += %W( -p #{@port} )
100
- args += %W( #{@username}@#{@hostname} )
101
- LoginCommand.new('ssh', args)
98
+ args += %W{ -o ProxyCommand='#{generate_proxy_command}' } if check_proxy
99
+ args += %W{ -p #{@port} }
100
+ args += %W{ #{@username}@#{@hostname} }
101
+ LoginCommand.new("ssh", args)
102
102
  end
103
103
 
104
104
  # (see Base::Connection#upload)
@@ -138,7 +138,7 @@ class Train::Transports::SSH
138
138
  retries: @max_wait_until_ready / delay,
139
139
  delay: delay,
140
140
  message: "Waiting for SSH service on #{@hostname}:#{@port}, " \
141
- "retrying in #{delay} seconds",
141
+ "retrying in #{delay} seconds"
142
142
  )
143
143
  run_command(PING_COMMAND.dup)
144
144
  end
@@ -172,14 +172,14 @@ class Train::Transports::SSH
172
172
  def establish_connection(opts)
173
173
  logger.debug("[SSH] opening connection to #{self}")
174
174
  if check_proxy
175
- require 'net/ssh/proxy/command'
175
+ require "net/ssh/proxy/command"
176
176
  @options[:proxy] = Net::SSH::Proxy::Command.new(generate_proxy_command)
177
177
  end
178
178
  Net::SSH.start(@hostname, @username, @options.clone.delete_if { |_key, value| value.nil? })
179
179
  rescue *RESCUE_EXCEPTIONS_ON_ESTABLISH => e
180
180
  if (opts[:retries] -= 1) <= 0
181
181
  logger.warn("[SSH] connection failed, terminating (#{e.inspect})")
182
- raise Train::Transports::SSHFailed, 'SSH session could not be established'
182
+ raise Train::Transports::SSHFailed, "SSH session could not be established"
183
183
  end
184
184
 
185
185
  if opts[:message]
@@ -200,7 +200,7 @@ class Train::Transports::SSH
200
200
  Train::File::Remote::Aix.new(self, path)
201
201
  elsif os.solaris?
202
202
  Train::File::Remote::Unix.new(self, path)
203
- elsif os[:name] == 'qnx'
203
+ elsif os[:name] == "qnx"
204
204
  Train::File::Remote::Qnx.new(self, path)
205
205
  elsif os.windows?
206
206
  Train::File::Remote::Windows.new(self, path)
@@ -210,7 +210,7 @@ class Train::Transports::SSH
210
210
  end
211
211
 
212
212
  def run_command_via_connection(cmd, &data_handler)
213
- cmd.dup.force_encoding('binary') if cmd.respond_to?(:force_encoding)
213
+ cmd.dup.force_encoding("binary") if cmd.respond_to?(:force_encoding)
214
214
  logger.debug("[SSH] #{self} (#{cmd})")
215
215
 
216
216
  reset_session if session.closed?
@@ -228,7 +228,7 @@ class Train::Transports::SSH
228
228
  # transport. This retries the command if this is the case.
229
229
  # See:
230
230
  # https://github.com/inspec/train/pull/271
231
- logger.debug('[SSH] Possible Cisco IOS race condition, retrying command')
231
+ logger.debug("[SSH] Possible Cisco IOS race condition, retrying command")
232
232
 
233
233
  # Only attempt retry up to 5 times to avoid infinite loop
234
234
  @ios_cmd_retries += 1
@@ -246,7 +246,7 @@ class Train::Transports::SSH
246
246
  def session(retry_options = {})
247
247
  @session ||= establish_connection({
248
248
  retries: @connection_retries.to_i,
249
- delay: @connection_retry_sleep.to_i,
249
+ delay: @connection_retry_sleep.to_i,
250
250
  }.merge(retry_options))
251
251
  end
252
252
 
@@ -260,7 +260,7 @@ class Train::Transports::SSH
260
260
  # @api private
261
261
  def to_s
262
262
  options_to_print = @options.clone
263
- options_to_print[:password] = '<hidden>' if options_to_print.key?(:password)
263
+ options_to_print[:password] = "<hidden>" if options_to_print.key?(:password)
264
264
  "#{@username}@#{@hostname}<#{options_to_print.inspect}>"
265
265
  end
266
266
 
@@ -274,7 +274,7 @@ class Train::Transports::SSH
274
274
  #
275
275
  # @api private
276
276
  def execute_on_channel(cmd, &data_handler)
277
- stdout = stderr = ''
277
+ stdout = stderr = ""
278
278
  exit_status = nil
279
279
  session.open_channel do |channel|
280
280
  # wrap commands if that is configured
@@ -282,11 +282,11 @@ class Train::Transports::SSH
282
282
 
283
283
  if @transport_options[:pty]
284
284
  channel.request_pty do |_ch, success|
285
- fail Train::Transports::SSHPTYFailed, 'Requesting PTY failed' unless success
285
+ raise Train::Transports::SSHPTYFailed, "Requesting PTY failed" unless success
286
286
  end
287
287
  end
288
288
  channel.exec(cmd) do |_, success|
289
- abort 'Couldn\'t execute command on SSH.' unless success
289
+ abort "Couldn't execute command on SSH." unless success
290
290
  channel.on_data do |_, data|
291
291
  yield(data) unless data_handler.nil?
292
292
  stdout += data
@@ -297,11 +297,11 @@ class Train::Transports::SSH
297
297
  stderr += data
298
298
  end
299
299
 
300
- channel.on_request('exit-status') do |_, data|
300
+ channel.on_request("exit-status") do |_, data|
301
301
  exit_status = data.read_long
302
302
  end
303
303
 
304
- channel.on_request('exit-signal') do |_, data|
304
+ channel.on_request("exit-signal") do |_, data|
305
305
  exit_status = data.read_long
306
306
  end
307
307
  end
@@ -1,16 +1,16 @@
1
1
  # encoding: utf-8
2
- require 'train/plugins'
3
- require 'open3'
4
- require 'ostruct'
5
- require 'json'
6
- require 'mkmf'
2
+ require "train/plugins"
3
+ require "open3"
4
+ require "ostruct"
5
+ require "json"
6
+ require "mkmf"
7
7
 
8
8
  module Train::Transports
9
9
  class VMware < Train.plugin(1)
10
- name 'vmware'
11
- option :viserver, default: ENV['VISERVER']
12
- option :username, default: ENV['VISERVER_USERNAME']
13
- option :password, default: ENV['VISERVER_PASSWORD']
10
+ name "vmware"
11
+ option :viserver, default: proc { ENV["VISERVER"] }
12
+ option :username, default: proc { ENV["VISERVER_USERNAME"] }
13
+ option :password, default: proc { ENV["VISERVER_PASSWORD"] }
14
14
  option :insecure, default: false
15
15
 
16
16
  def connection(_ = nil)
@@ -18,7 +18,7 @@ module Train::Transports
18
18
  end
19
19
 
20
20
  class Connection < BaseConnection # rubocop:disable ClassLength
21
- POWERSHELL_PROMPT_REGEX = /PS\s.*> $/
21
+ POWERSHELL_PROMPT_REGEX = /PS\s.*> $/.freeze
22
22
 
23
23
  def initialize(options)
24
24
  super(options)
@@ -29,18 +29,18 @@ module Train::Transports
29
29
  @username = options[:username]
30
30
  @viserver = options[:viserver]
31
31
  @session = nil
32
- @stdout_buffer = ''
33
- @stderr_buffer = ''
32
+ @stdout_buffer = ""
33
+ @stderr_buffer = ""
34
34
 
35
35
  @powershell_binary = detect_powershell_binary
36
36
 
37
37
  if @powershell_binary == :powershell
38
- require 'train/transports/local'
38
+ require "train/transports/local"
39
39
  @powershell = Train::Transports::Local::Connection.new(options)
40
40
  end
41
41
 
42
42
  if options[:insecure] == true
43
- run_command_via_connection('Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Scope Session -Confirm:$False')
43
+ run_command_via_connection("Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Scope Session -Confirm:$False")
44
44
  end
45
45
 
46
46
  @platform_details = {
@@ -58,11 +58,11 @@ module Train::Transports
58
58
  message = "Unable to connect to VIServer at #{options[:viserver]}. "
59
59
  case result.stderr
60
60
  when /Invalid server certificate/
61
- message += 'Certification verification failed. Please use `--insecure` or set `Set-PowerCLIConfiguration -InvalidCertificateAction Ignore` in PowerShell'
61
+ message += "Certification verification failed. Please use `--insecure` or set `Set-PowerCLIConfiguration -InvalidCertificateAction Ignore` in PowerShell"
62
62
  when /incorrect user name or password/
63
- message += 'Incorrect username or password'
63
+ message += "Incorrect username or password"
64
64
  else
65
- message += result.stderr.gsub(/-Password .*\s/, '-Password REDACTED')
65
+ message += result.stderr.gsub(/-Password .*\s/, "-Password REDACTED")
66
66
  end
67
67
 
68
68
  raise message
@@ -70,7 +70,7 @@ module Train::Transports
70
70
  end
71
71
 
72
72
  def platform
73
- force_platform!('vmware', @platform_details)
73
+ force_platform!("vmware", @platform_details)
74
74
  end
75
75
 
76
76
  def run_command_via_connection(cmd, &_data_handler)
@@ -78,8 +78,8 @@ module Train::Transports
78
78
  result = parse_pwsh_output(cmd)
79
79
 
80
80
  # Attach exit status to result
81
- exit_status = parse_pwsh_output('echo $?').stdout.chomp
82
- result.exit_status = exit_status == 'True' ? 0 : 1
81
+ exit_status = parse_pwsh_output("echo $?").stdout.chomp
82
+ result.exit_status = exit_status == "True" ? 0 : 1
83
83
 
84
84
  result
85
85
  else
@@ -88,7 +88,7 @@ module Train::Transports
88
88
  end
89
89
 
90
90
  def unique_identifier
91
- uuid_command = '(Get-VMHost | Get-View).hardware.systeminfo.uuid'
91
+ uuid_command = "(Get-VMHost | Get-View).hardware.systeminfo.uuid"
92
92
  run_command_via_connection(uuid_command).stdout.chomp
93
93
  end
94
94
 
@@ -99,26 +99,24 @@ module Train::Transports
99
99
  private
100
100
 
101
101
  def detect_powershell_binary
102
- if find_executable0('pwsh')
102
+ if find_executable0("pwsh")
103
103
  :pwsh
104
- elsif find_executable0('powershell')
104
+ elsif find_executable0("powershell")
105
105
  :powershell
106
106
  else
107
- raise 'Cannot find PowerShell binary, is `pwsh` installed?'
107
+ raise "Cannot find PowerShell binary, is `pwsh` installed?"
108
108
  end
109
109
  end
110
110
 
111
111
  # Read from stdout pipe until prompt is received
112
112
  def flush_stdout(pipe)
113
- while @stdout_buffer !~ POWERSHELL_PROMPT_REGEX
114
- @stdout_buffer += pipe.read_nonblock(1)
115
- end
113
+ @stdout_buffer += pipe.read_nonblock(1) while @stdout_buffer !~ POWERSHELL_PROMPT_REGEX
116
114
  @stdout_buffer
117
115
  rescue IO::EAGAINWaitReadable
118
116
  # We cannot know when the stdout pipe is finished so we keep reading
119
117
  retry
120
118
  ensure
121
- @stdout_buffer = ''
119
+ @stdout_buffer = ""
122
120
  end
123
121
 
124
122
  # This must be called after `flush_stdout` to ensure buffer is full
@@ -132,7 +130,7 @@ module Train::Transports
132
130
  # is unreadable.
133
131
  @stderr_buffer
134
132
  ensure
135
- @stderr_buffer = ''
133
+ @stderr_buffer = ""
136
134
  end
137
135
 
138
136
  def parse_pwsh_output(cmd)
@@ -141,10 +139,10 @@ module Train::Transports
141
139
  stdout = flush_stdout(session.stdout)
142
140
 
143
141
  # Remove stdin from stdout (including trailing newline)
144
- stdout.slice!(0, cmd.length+1)
142
+ stdout.slice!(0, cmd.length + 1)
145
143
 
146
144
  # Remove prompt from stdout
147
- stdout.gsub!(POWERSHELL_PROMPT_REGEX, '')
145
+ stdout.gsub!(POWERSHELL_PROMPT_REGEX, "")
148
146
 
149
147
  # Grab stderr
150
148
  stderr = flush_stderr(session.stderr)
@@ -157,10 +155,10 @@ module Train::Transports
157
155
  end
158
156
 
159
157
  def powercli_version
160
- version_command = '[string](Get-Module -Name VMware.PowerCLI -ListAvailable | Select -ExpandProperty Version)'
158
+ version_command = "[string](Get-Module -Name VMware.PowerCLI -ListAvailable | Select -ExpandProperty Version)"
161
159
  result = run_command_via_connection(version_command)
162
160
  if result.stdout.empty? || result.exit_status != 0
163
- raise 'Unable to determine PowerCLI Module version, is it installed?'
161
+ raise "Unable to determine PowerCLI Module version, is it installed?"
164
162
  end
165
163
 
166
164
  result.stdout.chomp
@@ -169,7 +167,7 @@ module Train::Transports
169
167
  def session
170
168
  return @session unless @session.nil?
171
169
 
172
- stdin, stdout, stderr = Open3.popen3('pwsh')
170
+ stdin, stdout, stderr = Open3.popen3("pwsh")
173
171
 
174
172
  # Remove leading prompt and intro text
175
173
  flush_stdout(stdout)