train-core 2.1.19 → 3.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49c2854136c56c84e5c6faf50ab984a40147044da89fcfa9d18c00c9dba45b37
4
- data.tar.gz: ecea91c8b628a255c768e99101998c2da73fbbb8bb423102e9ede66d41e504ec
3
+ metadata.gz: fc412482ed0f718b661526c4322fb9820f78a00cc6ae134016a26c2760678875
4
+ data.tar.gz: 15f5e5fb64c8a5ae82f00998c77c0e8022ee3c7f4e29224e15025638278e7e3f
5
5
  SHA512:
6
- metadata.gz: 0b02727f361fbfadb0c0f1a1557b962cffbc834eb2d4fa418910f26fb6f70ddd4ea737a07aaf4079c188030f99e2d28477e71a6e534c86b6687157de36032bea
7
- data.tar.gz: c936b2736c1c6de03b859e4be7dae31c40e33f3c136970676621374a10c86f5b982b6c05bd9fc3e4f6d7faf2bef19c47bc79ab86ef83d5152af11bbeb5812aa6
6
+ metadata.gz: 2d2095822f7c5fac05329fb14f39f16c0da669441990dffef2614fe6549d9b520adba18063538b40a5960a54dbc3fd711452ae9530d4387b5f40f366d93aaaf7
7
+ data.tar.gz: 8854eb8744b9046c8c166b9e6d162fa6deb2e311adf2db8f2670706f066907564f5b6ad9876fde9a9fd6eab94392bc3deb9bb8a321f005e2a808b7e635d7a1dc
@@ -12,7 +12,11 @@ module Train::Platforms::Detect::Helpers
12
12
  end
13
13
 
14
14
  def winrm?
15
- @backend.class.to_s == "Train::Transports::WinRM::Connection"
15
+ backend_name == "TrainPlugins::WinRM::Connection"
16
+ end
17
+
18
+ def backend_name
19
+ @backend.class.name
16
20
  end
17
21
 
18
22
  def unix_file_contents(path)
@@ -236,7 +236,10 @@ module Train::Platforms::Detect::Specifications
236
236
  # suse family
237
237
  plat.family("suse").in_family("linux")
238
238
  .detect do
239
- unless (suse = unix_file_contents("/etc/SuSE-release")).nil?
239
+ if linux_os_release && linux_os_release["ID_LIKE"] =~ /suse/i
240
+ @platform[:release] = linux_os_release["VERSION"]
241
+ true
242
+ elsif !(suse = unix_file_contents("/etc/SuSE-release")).nil?
240
243
  # https://rubular.com/r/UKaYWolCYFMfp1
241
244
  version = suse.scan(/VERSION = (\d+)\nPATCHLEVEL = (\d+)/).flatten.join(".")
242
245
  # https://rubular.com/r/b5PN3hZDxa5amV
@@ -247,11 +250,13 @@ module Train::Platforms::Detect::Specifications
247
250
  end
248
251
  plat.name("opensuse").title("OpenSUSE Linux").in_family("suse")
249
252
  .detect do
250
- true if unix_file_contents("/etc/SuSE-release") =~ /^opensuse/i
253
+ true if (linux_os_release && linux_os_release["NAME"] =~ /^opensuse/i) ||
254
+ unix_file_contents("/etc/SuSE-release") =~ /^opensuse/i
251
255
  end
252
256
  plat.name("suse").title("Suse Linux").in_family("suse")
253
257
  .detect do
254
- true if unix_file_contents("/etc/SuSE-release") =~ /suse/i
258
+ true if (linux_os_release && linux_os_release["NAME"] =~ /^sles/i) ||
259
+ unix_file_contents("/etc/SuSE-release") =~ /suse/i
255
260
  end
256
261
 
257
262
  # arch
data/lib/train/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  # Author:: Dominik Richter (<dominik.richter@gmail.com>)
4
4
 
5
5
  module Train
6
- VERSION = "2.1.19".freeze
6
+ VERSION = "3.0.1".freeze
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: train-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.19
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-23 00:00:00.000000000 Z
11
+ date: 2019-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -90,34 +90,6 @@ dependencies:
90
90
  - - "<"
91
91
  - !ruby/object:Gem::Version
92
92
  version: '3.0'
93
- - !ruby/object:Gem::Dependency
94
- name: winrm
95
- requirement: !ruby/object:Gem::Requirement
96
- requirements:
97
- - - "~>"
98
- - !ruby/object:Gem::Version
99
- version: '2.0'
100
- type: :runtime
101
- prerelease: false
102
- version_requirements: !ruby/object:Gem::Requirement
103
- requirements:
104
- - - "~>"
105
- - !ruby/object:Gem::Version
106
- version: '2.0'
107
- - !ruby/object:Gem::Dependency
108
- name: winrm-fs
109
- requirement: !ruby/object:Gem::Requirement
110
- requirements:
111
- - - "~>"
112
- - !ruby/object:Gem::Version
113
- version: '1.0'
114
- type: :runtime
115
- prerelease: false
116
- version_requirements: !ruby/object:Gem::Requirement
117
- requirements:
118
- - - "~>"
119
- - !ruby/object:Gem::Version
120
- version: '1.0'
121
93
  description: A minimal Train with a backends for ssh and winrm.
122
94
  email:
123
95
  - drichter@chef.io
@@ -164,8 +136,6 @@ files:
164
136
  - lib/train/transports/mock.rb
165
137
  - lib/train/transports/ssh.rb
166
138
  - lib/train/transports/ssh_connection.rb
167
- - lib/train/transports/winrm.rb
168
- - lib/train/transports/winrm_connection.rb
169
139
  - lib/train/version.rb
170
140
  homepage: https://github.com/inspec/train/
171
141
  licenses:
@@ -1,207 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # Author:: Salim Afiune (<salim@afiunemaya.com.mx>)
4
- # Author:: Matt Wrock (<matt@mattwrock.com>)
5
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
6
- # Author:: Dominik Richter (<dominik.richter@gmail.com>)
7
- # Author:: Christoph Hartmann (<chris@lollyrock.com>)
8
- #
9
- # Copyright (C) 2014, Salim Afiune
10
- #
11
- # Licensed under the Apache License, Version 2.0 (the "License");
12
- # you may not use this file except in compliance with the License.
13
- # You may obtain a copy of the License at
14
- #
15
- # http://www.apache.org/licenses/LICENSE-2.0
16
- #
17
- # Unless required by applicable law or agreed to in writing, software
18
- # distributed under the License is distributed on an "AS IS" BASIS,
19
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
- # See the License for the specific language governing permissions and
21
- # limitations under the License.
22
-
23
- require "rbconfig"
24
- require "uri"
25
- require "train/errors"
26
-
27
- module Train::Transports
28
- # Wrapped exception for any internally raised WinRM-related errors.
29
- #
30
- # @author Fletcher Nichol <fnichol@nichol.ca>
31
- class WinRMFailed < Train::TransportError; end
32
-
33
- # A Transport which uses WinRM to execute commands and transfer files.
34
- #
35
- # @author Matt Wrock <matt@mattwrock.com>
36
- # @author Salim Afiune <salim@afiunemaya.com.mx>
37
- # @author Fletcher Nichol <fnichol@nichol.ca>
38
- class WinRM < Train.plugin(1) # rubocop:disable ClassLength
39
- name "winrm"
40
-
41
- require "train/transports/winrm_connection"
42
-
43
- # ref: https://github.com/winrb/winrm#transports
44
- SUPPORTED_WINRM_TRANSPORTS = %i{negotiate ssl plaintext kerberos}.freeze
45
-
46
- # common target configuration
47
- option :host, required: true
48
- option :port
49
- option :user, default: "administrator", required: true
50
- option :password, nil
51
- option :winrm_transport, default: :negotiate
52
- option :winrm_disable_sspi, default: false
53
- option :winrm_basic_auth_only, default: false
54
- option :path, default: "/wsman"
55
- option :ssl, default: false
56
- option :self_signed, default: false
57
-
58
- # additional winrm options
59
- option :rdp_port, default: 3389
60
- option :connection_retries, default: 5
61
- option :connection_retry_sleep, default: 1
62
- option :max_wait_until_ready, default: 600
63
- option :ssl_peer_fingerprint, default: nil
64
- option :kerberos_realm, default: nil
65
- option :kerberos_service, default: nil
66
- option :ca_trust_path, default: nil
67
- # The amount of time in SECONDS for which each operation must get an ack
68
- # from the winrm endpoint. Does not mean that the command has
69
- # completed in this time, only that the server has ack'd the request.
70
- option :operation_timeout, default: nil
71
-
72
- def initialize(opts)
73
- super(opts)
74
- load_needed_dependencies!
75
- end
76
-
77
- # (see Base#connection)
78
- def connection(state = nil, &block)
79
- opts = merge_options(options, state || {})
80
- validate_options(opts)
81
- conn_opts = connection_options(opts)
82
-
83
- if @connection && @connection_options == conn_opts
84
- reuse_connection(&block)
85
- else
86
- create_new_connection(conn_opts, &block)
87
- end
88
- end
89
-
90
- private
91
-
92
- def validate_options(opts)
93
- super(opts)
94
-
95
- # set scheme and port based on ssl activation
96
- scheme = opts[:ssl] ? "https" : "http"
97
- port = opts[:port]
98
- port = (opts[:ssl] ? 5986 : 5985) if port.nil?
99
- winrm_transport = opts[:winrm_transport].to_sym
100
- unless SUPPORTED_WINRM_TRANSPORTS.include?(winrm_transport)
101
- raise Train::ClientError, "Unsupported transport type: #{winrm_transport.inspect}"
102
- end
103
-
104
- # remove leading '/'
105
- path = (opts[:path] || "").sub(%r{^/+}, "")
106
-
107
- opts[:endpoint] = "#{scheme}://#{opts[:host]}:#{port}/#{path}"
108
- end
109
-
110
- WINRM_FS_SPEC_VERSION = "~> 1.0".freeze
111
-
112
- # Builds the hash of options needed by the Connection object on
113
- # construction.
114
- #
115
- # @param data [Hash] merged configuration and mutable state data
116
- # @return [Hash] hash of connection options
117
- # @api private
118
- def connection_options(opts)
119
- {
120
- logger: logger,
121
- transport: opts[:winrm_transport].to_sym,
122
- disable_sspi: opts[:winrm_disable_sspi],
123
- basic_auth_only: opts[:winrm_basic_auth_only],
124
- hostname: opts[:host],
125
- endpoint: opts[:endpoint],
126
- user: opts[:user],
127
- password: opts[:password],
128
- rdp_port: opts[:rdp_port],
129
- connection_retries: opts[:connection_retries],
130
- connection_retry_sleep: opts[:connection_retry_sleep],
131
- max_wait_until_ready: opts[:max_wait_until_ready],
132
- no_ssl_peer_verification: opts[:self_signed],
133
- realm: opts[:kerberos_realm],
134
- service: opts[:kerberos_service],
135
- ca_trust_path: opts[:ca_trust_path],
136
- ssl_peer_fingerprint: opts[:ssl_peer_fingerprint],
137
- }
138
- end
139
-
140
- # Creates a new WinRM Connection instance and save it for potential
141
- # future reuse.
142
- #
143
- # @param options [Hash] conneciton options
144
- # @return [WinRM::Connection] a WinRM Connection instance
145
- # @api private
146
- def create_new_connection(options, &block)
147
- if @connection
148
- logger.debug("[WinRM] shutting previous connection #{@connection}")
149
- @connection.close
150
- end
151
-
152
- @connection_options = options
153
- @connection = Connection.new(options, &block)
154
- end
155
-
156
- # (see Base#load_needed_dependencies!)
157
- def load_needed_dependencies!
158
- spec_version = WINRM_FS_SPEC_VERSION.dup
159
- logger.debug("winrm-fs requested," \
160
- " loading WinRM::FS gem (#{spec_version})")
161
- gem "winrm-fs", spec_version
162
- first_load = require "winrm-fs"
163
- load_winrm_transport!
164
-
165
- if first_load
166
- logger.debug("WinRM::FS library loaded")
167
- else
168
- logger.debug("WinRM::FS previously loaded")
169
- end
170
- rescue LoadError => e
171
- logger.fatal(
172
- "The `winrm-fs' gem is missing and must" \
173
- " be installed or cannot be properly activated. Run" \
174
- " `gem install winrm-fs --version '#{spec_version}'`" \
175
- " or add the following to your Gemfile if you are using Bundler:" \
176
- " `gem 'winrm-fs', '#{spec_version}'`."
177
- )
178
- raise Train::UserError,
179
- "Could not load or activate WinRM::FS (#{e.message})"
180
- end
181
-
182
- # Load WinRM::Transport code.
183
- #
184
- # @api private
185
- def load_winrm_transport!
186
- silence_warnings { require "winrm-fs" }
187
- end
188
-
189
- # Return the last saved WinRM connection instance.
190
- #
191
- # @return [Winrm::Connection] a WinRM Connection instance
192
- # @api private
193
- def reuse_connection
194
- logger.debug("[WinRM] reusing existing connection #{@connection}")
195
- yield @connection if block_given?
196
- @connection
197
- end
198
-
199
- def silence_warnings
200
- old_verbose = $VERBOSE
201
- $VERBOSE = nil
202
- yield
203
- ensure
204
- $VERBOSE = old_verbose
205
- end
206
- end
207
- end
@@ -1,202 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # Author:: Salim Afiune (<salim@afiunemaya.com.mx>)
4
- # Author:: Matt Wrock (<matt@mattwrock.com>)
5
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
6
- # Author:: Dominik Richter (<dominik.richter@gmail.com>)
7
- # Author:: Christoph Hartmann (<chris@lollyrock.com>)
8
- #
9
- # Copyright (C) 2014, Salim Afiune
10
- #
11
- # Licensed under the Apache License, Version 2.0 (the "License");
12
- # you may not use this file except in compliance with the License.
13
- # You may obtain a copy of the License at
14
- #
15
- # http://www.apache.org/licenses/LICENSE-2.0
16
- #
17
- # Unless required by applicable law or agreed to in writing, software
18
- # distributed under the License is distributed on an "AS IS" BASIS,
19
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
- # See the License for the specific language governing permissions and
21
- # limitations under the License.
22
-
23
- class Train::Transports::WinRM
24
- # A Connection instance can be generated and re-generated, given new
25
- # connection details such as connection port, hostname, credentials, etc.
26
- # This object is responsible for carrying out the actions on the remote
27
- # host such as executing commands, transferring files, etc.
28
- #
29
- # @author Fletcher Nichol <fnichol@nichol.ca>
30
- class Connection < BaseConnection # rubocop:disable Metrics/ClassLength
31
- attr_reader :hostname
32
- def initialize(options)
33
- super(options)
34
- @hostname = @options.delete(:hostname)
35
- @rdp_port = @options.delete(:rdp_port)
36
- @connection_retries = @options.delete(:connection_retries)
37
- @connection_retry_sleep = @options.delete(:connection_retry_sleep)
38
- @max_wait_until_ready = @options.delete(:max_wait_until_ready)
39
- @operation_timeout = @options.delete(:operation_timeout)
40
- end
41
-
42
- # (see Base::Connection#close)
43
- def close
44
- return if @session.nil?
45
-
46
- session.close
47
- ensure
48
- @session = nil
49
- end
50
-
51
- # (see Base::Connection#login_command)
52
- def login_command
53
- case RbConfig::CONFIG["host_os"]
54
- when /darwin/
55
- login_command_for_mac
56
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
57
- login_command_for_windows
58
- when /linux/
59
- login_command_for_linux
60
- else
61
- raise ActionFailed,
62
- "Remote login not supported in #{self.class} " \
63
- "from host OS '#{RbConfig::CONFIG["host_os"]}'."
64
- end
65
- end
66
-
67
- # (see Base::Connection#upload)
68
- def upload(locals, remote)
69
- file_manager.upload(locals, remote)
70
- end
71
-
72
- def download(remotes, local)
73
- Array(remotes).each do |remote|
74
- file_manager.download(remote, local)
75
- end
76
- end
77
-
78
- # (see Base::Connection#wait_until_ready)
79
- def wait_until_ready
80
- delay = 3
81
- session(
82
- retry_limit: @max_wait_until_ready / delay,
83
- retry_delay: delay
84
- )
85
- run_command_via_connection(PING_COMMAND.dup)
86
- end
87
-
88
- def uri
89
- "winrm://#{options[:user]}@#{options[:endpoint]}:#{@rdp_port}"
90
- end
91
-
92
- private
93
-
94
- PING_COMMAND = "Write-Host '[WinRM] Established\n'".freeze
95
-
96
- def file_via_connection(path)
97
- Train::File::Remote::Windows.new(self, path)
98
- end
99
-
100
- def run_command_via_connection(command, &data_handler)
101
- return if command.nil?
102
-
103
- logger.debug("[WinRM] #{self} (#{command})")
104
- out = ""
105
-
106
- response = session.run(command) do |stdout, _|
107
- yield(stdout) if data_handler && stdout
108
- out << stdout if stdout
109
- end
110
-
111
- CommandResult.new(out, response.stderr, response.exitcode)
112
- end
113
-
114
- # Create a local RDP document and return it
115
- #
116
- # @param opts [Hash] configuration options
117
- # @option opts [true,false] :mac whether or not the document is for a
118
- # Mac system
119
- # @api private
120
- def rdp_doc(opts = {})
121
- host = URI.parse(options[:endpoint]).host
122
- content = [
123
- "full address:s:#{host}:#{@rdp_port}",
124
- "prompt for credentials:i:1",
125
- "username:s:#{options[:user]}",
126
- ].join("\n")
127
-
128
- content.prepend("drivestoredirect:s:*\n") if opts[:mac]
129
-
130
- content
131
- end
132
-
133
- # @return [Winrm::FileManager] a file transporter
134
- # @api private
135
- def file_manager
136
- @file_manager ||= begin
137
- # Ensure @service is available:
138
- wait_until_ready
139
- WinRM::FS::FileManager.new(@service)
140
- end
141
- end
142
-
143
- # Builds a `LoginCommand` for use by Linux-based platforms.
144
- #
145
- # TODO: determine whether or not `desktop` exists
146
- #
147
- # @return [LoginCommand] a login command
148
- # @api private
149
- def login_command_for_linux
150
- args = %W{ -u #{options[:user]} }
151
- args += %W{ -p #{options[:pass]} } if options.key?(:pass)
152
- args += %W{ #{URI.parse(options[:endpoint]).host}:#{@rdp_port} }
153
- LoginCommand.new("rdesktop", args)
154
- end
155
-
156
- # Builds a `LoginCommand` for use by Mac-based platforms.
157
- #
158
- # @return [LoginCommand] a login command
159
- # @api private
160
- def login_command_for_mac
161
- LoginCommand.new("open", rdp_doc(mac: true))
162
- end
163
-
164
- # Builds a `LoginCommand` for use by Windows-based platforms.
165
- #
166
- # @return [LoginCommand] a login command
167
- # @api private
168
- def login_command_for_windows
169
- LoginCommand.new("mstsc", rdp_doc)
170
- end
171
-
172
- # Establishes a remote shell session, or establishes one when invoked
173
- # the first time.
174
- #
175
- # @param retry_options [Hash] retry options for the initial connection
176
- # @return [Winrm::CommandExecutor] the command executor session
177
- # @api private
178
- def session(retry_options = {})
179
- @session ||= begin
180
- opts = {
181
- retry_limit: @connection_retries.to_i,
182
- retry_delay: @connection_retry_sleep.to_i,
183
- }.merge(retry_options)
184
-
185
- opts[:operation_timeout] = @operation_timeout unless @operation_timeout.nil?
186
- @service = ::WinRM::Connection.new(options.merge(opts))
187
- @service.logger = logger
188
- @service.shell(:powershell)
189
- end
190
- end
191
-
192
- # String representation of object, reporting its connection details and
193
- # configuration.
194
- #
195
- # @api private
196
- def to_s
197
- options_to_print = @options.clone
198
- options_to_print[:password] = "<hidden>" if options_to_print.key?(:password)
199
- "#{@username}@#{@hostname}<#{options_to_print.inspect}>"
200
- end
201
- end
202
- end