train 2.1.7 → 2.1.13

Sign up to get free protection for your applications and to get access to all the features.
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)