bolt 0.16.0 → 0.16.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bolt/cli.rb +32 -17
  3. data/lib/bolt/config.rb +12 -31
  4. data/lib/bolt/error.rb +18 -7
  5. data/lib/bolt/executor.rb +3 -3
  6. data/lib/bolt/inventory.rb +101 -0
  7. data/lib/bolt/inventory/group.rb +127 -0
  8. data/lib/bolt/node.rb +10 -9
  9. data/lib/bolt/node/ssh.rb +86 -69
  10. data/lib/bolt/node/winrm.rb +3 -3
  11. data/lib/bolt/outputter/human.rb +1 -1
  12. data/lib/bolt/pal.rb +17 -11
  13. data/lib/bolt/result.rb +9 -4
  14. data/lib/bolt/target.rb +26 -11
  15. data/lib/bolt/util.rb +54 -0
  16. data/lib/bolt/version.rb +1 -1
  17. data/modules/boltlib/lib/puppet/functions/fail_plan.rb +27 -0
  18. data/modules/boltlib/lib/puppet/functions/file_upload.rb +4 -4
  19. data/modules/boltlib/lib/puppet/functions/run_command.rb +3 -3
  20. data/modules/boltlib/lib/puppet/functions/run_plan.rb +18 -4
  21. data/modules/boltlib/lib/puppet/functions/run_script.rb +5 -2
  22. data/modules/boltlib/lib/puppet/functions/run_task.rb +3 -3
  23. data/vendored/puppet/lib/puppet/datatypes/error.rb +5 -3
  24. data/vendored/puppet/lib/puppet/datatypes/impl/error.rb +10 -12
  25. data/vendored/puppet/lib/puppet/defaults.rb +33 -25
  26. data/vendored/puppet/lib/puppet/etc.rb +2 -2
  27. data/vendored/puppet/lib/puppet/external/pson/pure/generator.rb +1 -1
  28. data/vendored/puppet/lib/puppet/external/pson/pure/parser.rb +1 -1
  29. data/vendored/puppet/lib/puppet/face/config.rb +45 -0
  30. data/vendored/puppet/lib/puppet/face/module/generate.rb +5 -0
  31. data/vendored/puppet/lib/puppet/functions/annotate.rb +1 -1
  32. data/vendored/puppet/lib/puppet/functions/any.rb +1 -1
  33. data/vendored/puppet/lib/puppet/generate/type.rb +1 -1
  34. data/vendored/puppet/lib/puppet/gettext/config.rb +2 -2
  35. data/vendored/puppet/lib/puppet/gettext/stubs.rb +1 -1
  36. data/vendored/puppet/lib/puppet/interface/action.rb +11 -0
  37. data/vendored/puppet/lib/puppet/interface/action_builder.rb +8 -0
  38. data/vendored/puppet/lib/puppet/network/authstore.rb +1 -1
  39. data/vendored/puppet/lib/puppet/network/http/connection.rb +1 -1
  40. data/vendored/puppet/lib/puppet/parameter/boolean.rb +1 -1
  41. data/vendored/puppet/lib/puppet/parser/ast/branch.rb +1 -1
  42. data/vendored/puppet/lib/puppet/parser/functions/new.rb +1 -1
  43. data/vendored/puppet/lib/puppet/parser/functions/reverse_each.rb +1 -1
  44. data/vendored/puppet/lib/puppet/pops/evaluator/compare_operator.rb +1 -1
  45. data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +3 -3
  46. data/vendored/puppet/lib/puppet/pops/evaluator/literal_evaluator.rb +1 -1
  47. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_converter.rb +1 -1
  48. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +1 -1
  49. data/vendored/puppet/lib/puppet/pops/issues.rb +1 -1
  50. data/vendored/puppet/lib/puppet/pops/loader/loader.rb +1 -1
  51. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +1 -1
  52. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +3 -5
  53. data/vendored/puppet/lib/puppet/pops/loader/puppet_resource_type_impl_instantiator.rb +1 -1
  54. data/vendored/puppet/lib/puppet/pops/loader/runtime3_type_loader.rb +1 -1
  55. data/vendored/puppet/lib/puppet/pops/loaders.rb +40 -1
  56. data/vendored/puppet/lib/puppet/pops/lookup/interpolation.rb +1 -1
  57. data/vendored/puppet/lib/puppet/pops/model/tree_dumper.rb +1 -1
  58. data/vendored/puppet/lib/puppet/pops/parser/epp_support.rb +1 -1
  59. data/vendored/puppet/lib/puppet/pops/parser/interpolation_support.rb +1 -1
  60. data/vendored/puppet/lib/puppet/pops/parser/lexer2.rb +1 -1
  61. data/vendored/puppet/lib/puppet/pops/parser/lexer_support.rb +2 -2
  62. data/vendored/puppet/lib/puppet/pops/parser/locatable.rb +1 -1
  63. data/vendored/puppet/lib/puppet/pops/parser/locator.rb +2 -6
  64. data/vendored/puppet/lib/puppet/pops/resource/param.rb +1 -1
  65. data/vendored/puppet/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
  66. data/vendored/puppet/lib/puppet/pops/types/iterable.rb +1 -1
  67. data/vendored/puppet/lib/puppet/pops/types/tree_iterators.rb +5 -1
  68. data/vendored/puppet/lib/puppet/pops/types/type_acceptor.rb +1 -1
  69. data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +1 -1
  70. data/vendored/puppet/lib/puppet/pops/types/type_with_members.rb +1 -1
  71. data/vendored/puppet/lib/puppet/pops/types/types.rb +1 -1
  72. data/vendored/puppet/lib/puppet/provider/package/yum.rb +1 -1
  73. data/vendored/puppet/lib/puppet/provider/service/redhat.rb +3 -2
  74. data/vendored/puppet/lib/puppet/provider/service/systemd.rb +1 -1
  75. data/vendored/puppet/lib/puppet/provider/ssh_authorized_key/parsed.rb +1 -1
  76. data/vendored/puppet/lib/puppet/resource/type.rb +1 -1
  77. data/vendored/puppet/lib/puppet/settings/base_setting.rb +1 -1
  78. data/vendored/puppet/lib/puppet/settings/ini_file.rb +33 -12
  79. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +2 -2
  80. data/vendored/puppet/lib/puppet/transaction.rb +37 -14
  81. data/vendored/puppet/lib/puppet/type/cron.rb +1 -1
  82. data/vendored/puppet/lib/puppet/type/file/checksum.rb +6 -0
  83. data/vendored/puppet/lib/puppet/type/mount.rb +0 -9
  84. data/vendored/puppet/lib/puppet/util/character_encoding.rb +2 -2
  85. data/vendored/puppet/lib/puppet/util/network_device/cisco/device.rb +5 -5
  86. data/vendored/puppet/lib/puppet/util/rdoc/generators/puppet_generator.rb +1 -1
  87. data/vendored/puppet/lib/puppet/util/windows/process.rb +1 -1
  88. data/vendored/puppet/lib/puppet/vendor/pathspec/lib/pathspec/gitignorespec.rb +18 -18
  89. data/vendored/puppet/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet/version.rb +2 -2
  90. data/vendored/puppet/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet/version_range.rb +5 -5
  91. metadata +20 -2
data/lib/bolt/node.rb CHANGED
@@ -8,8 +8,8 @@ module Bolt
8
8
  STDIN_METHODS = %w[both stdin].freeze
9
9
  ENVIRONMENT_METHODS = %w[both environment].freeze
10
10
 
11
- def self.from_target(target, **kwargs)
12
- klass = case target.protocol || kwargs[:config][:transport]
11
+ def self.from_target(target)
12
+ klass = case target.protocol
13
13
  when 'winrm'
14
14
  Bolt::WinRM
15
15
  when 'pcp'
@@ -17,19 +17,19 @@ module Bolt
17
17
  else
18
18
  Bolt::SSH
19
19
  end
20
- klass.new(target, **kwargs)
20
+ klass.new(target)
21
21
  end
22
22
 
23
23
  def self.initialize_transport(_logger); end
24
24
 
25
25
  attr_reader :logger, :user, :password, :connect_timeout, :target, :run_as
26
26
 
27
- def initialize(target, config: Bolt::Config.new)
27
+ def initialize(target)
28
28
  @target = target
29
29
 
30
- transport_conf = config[:transports][protocol.to_sym]
31
- @user = @target.user || transport_conf[:user]
32
- @password = @target.password || transport_conf[:password]
30
+ transport_conf = target.options
31
+ @user = @target.user
32
+ @password = @target.password
33
33
  @key = transport_conf[:key]
34
34
  @cacert = transport_conf[:cacert]
35
35
  @tty = transport_conf[:tty]
@@ -38,6 +38,7 @@ module Bolt
38
38
  @connect_timeout = transport_conf[:connect_timeout]
39
39
  @sudo_password = transport_conf[:sudo_password]
40
40
  @run_as = transport_conf[:run_as]
41
+ @conf_run_as = transport_conf[:run_as]
41
42
  @tmpdir = transport_conf[:tmpdir]
42
43
  @service_url = transport_conf[:service_url]
43
44
  @token_file = transport_conf[:token_file]
@@ -51,8 +52,8 @@ module Bolt
51
52
  @target.uri
52
53
  end
53
54
 
54
- def upload(_source, _destination)
55
- raise NotImplementedError, 'transports must implement upload(source, destination)'
55
+ def upload(_source, _destination, _options = nil)
56
+ raise NotImplementedError, 'transports must implement upload(source, destination, options = nil)'
56
57
  end
57
58
 
58
59
  def run_command(_command, _options = nil)
data/lib/bolt/node/ssh.rb CHANGED
@@ -7,6 +7,37 @@ require 'bolt/node/output'
7
7
 
8
8
  module Bolt
9
9
  class SSH < Node
10
+ class RemoteTempdir
11
+ def initialize(node, path)
12
+ @node = node
13
+ @owner = node.user
14
+ @path = path
15
+ @logger = node.logger
16
+ end
17
+
18
+ def to_s
19
+ @path
20
+ end
21
+
22
+ def chown(owner)
23
+ return if owner.nil? || owner == @owner
24
+
25
+ @owner = owner
26
+ result = @node.execute("chown -R '#{@owner}': '#{@path}'", sudoable: true, run_as: 'root')
27
+ if result.exit_code != 0
28
+ message = "Could not change owner of '#{@path}' to #{@owner}: #{result.stderr.string}"
29
+ raise Bolt::Node::FileError.new(message, 'CHOWN_ERROR')
30
+ end
31
+ end
32
+
33
+ def delete
34
+ result = @node.execute("rm -rf '#{@path}'", sudoable: true, run_as: @owner)
35
+ if result.exit_code != 0
36
+ @logger.warn("Failed to clean up tempdir '#{@path}': #{result.stderr.string}")
37
+ end
38
+ end
39
+ end
40
+
10
41
  def self.initialize_transport(logger)
11
42
  require 'net/ssh/krb'
12
43
  rescue LoadError
@@ -15,9 +46,9 @@ module Bolt
15
46
  }
16
47
  end
17
48
 
18
- def initialize(target, **kwargs)
19
- super(target, **kwargs)
20
- @conf_run_as = @run_as
49
+ def initialize(target)
50
+ super(target)
51
+ @user = @user || Net::SSH::Config.for(target.host)[:user] || Etc.getlogin
21
52
  end
22
53
 
23
54
  def protocol
@@ -133,14 +164,10 @@ module Bolt
133
164
 
134
165
  def execute(command, sudoable: false, **options)
135
166
  result_output = Bolt::Node::Output.new
136
- use_sudo = sudoable && @run_as
167
+ run_as = options[:run_as] || @run_as
168
+ use_sudo = sudoable && run_as && @user != run_as
137
169
  if use_sudo
138
- user_clause = if @run_as
139
- "-u #{@run_as}"
140
- else
141
- ''
142
- end
143
- command = "sudo -S #{user_clause} -p '#{sudo_prompt}' #{command}"
170
+ command = "sudo -S -u #{run_as} -p '#{sudo_prompt}' #{command}"
144
171
  end
145
172
 
146
173
  @logger.debug { "Executing: #{command}" }
@@ -191,9 +218,23 @@ module Bolt
191
218
  result_output
192
219
  end
193
220
 
194
- def upload(source, destination)
195
- write_remote_file(source, destination)
221
+ def upload(source, destination, options = {})
222
+ @run_as = options['_run_as'] || @conf_run_as
223
+ with_remote_tempdir do |dir|
224
+ basename = File.basename(destination)
225
+ tmpfile = "#{dir}/#{basename}"
226
+ write_remote_file(source, tmpfile)
227
+ # pass over file ownership if we're using run-as to be a different user
228
+ dir.chown(@run_as)
229
+ result = execute("mv '#{tmpfile}' '#{destination}'", sudoable: true)
230
+ if result.exit_code != 0
231
+ message = "Could not move temporary file '#{tmpfile}' to #{destination}: #{result.stderr.string}"
232
+ raise FileError.new(message, 'MV_ERROR')
233
+ end
234
+ end
196
235
  Bolt::Result.for_upload(@target, source, destination)
236
+ ensure
237
+ @run_as = @conf_run_as
197
238
  end
198
239
 
199
240
  def write_remote_file(source, destination)
@@ -203,7 +244,6 @@ module Bolt
203
244
  end
204
245
 
205
246
  def make_tempdir
206
- tmppath = nil
207
247
  if @tmpdir
208
248
  tmppath = "#{@tmpdir}/#{SecureRandom.uuid}"
209
249
  command = "mkdir -m 700 #{tmppath}"
@@ -214,33 +254,31 @@ module Bolt
214
254
  if result.exit_code != 0
215
255
  raise FileError.new("Could not make tempdir: #{result.stderr.string}", 'TEMPDIR_ERROR')
216
256
  end
217
- tmppath || result.stdout.string.chomp
257
+ path = tmppath || result.stdout.string.chomp
258
+ RemoteTempdir.new(self, path)
218
259
  end
219
260
 
261
+ # A helper to create and delete a tempdir on the remote system. Yields the
262
+ # directory name.
220
263
  def with_remote_tempdir
221
264
  dir = make_tempdir
222
- begin
223
- yield dir
224
- ensure
225
- output = execute("rm -rf '#{dir}'")
226
- if output.exit_code != 0
227
- logger.warn("Failed to clean up tempdir '#{dir}': #{output.stderr.string}")
228
- end
229
- end
265
+ yield dir
266
+ ensure
267
+ dir.delete if dir
230
268
  end
231
269
 
232
- def with_remote_script(dir, file)
233
- remote_path = "#{dir}/#{File.basename(file)}"
270
+ def write_remote_executable(dir, file, filename = nil)
271
+ filename ||= File.basename(file)
272
+ remote_path = "#{dir}/#{filename}"
234
273
  write_remote_file(file, remote_path)
235
274
  make_executable(remote_path)
236
- yield remote_path
275
+ remote_path
237
276
  end
238
277
 
239
- def with_remote_file(file)
240
- with_remote_tempdir do |dir|
241
- with_remote_script(dir, file) do |remote_path|
242
- yield remote_path
243
- end
278
+ def make_executable(path)
279
+ result = execute("chmod u+x '#{path}'")
280
+ if result.exit_code != 0
281
+ raise FileError.new("Could not make file '#{path}' executable: #{result.stderr.string}", 'CHMOD_ERROR')
244
282
  end
245
283
  end
246
284
 
@@ -253,35 +291,6 @@ EOF
253
291
  SCRIPT
254
292
  end
255
293
 
256
- def make_executable(path)
257
- result = execute("chmod u+x '#{path}'")
258
- if result.exit_code != 0
259
- raise FileError.new("Could not make file '#{path}' executable: #{result.stderr.string}", 'CHMOD_ERROR')
260
- end
261
- end
262
-
263
- def with_task_wrapper(remote_task, dir, stdin)
264
- wrapper = make_wrapper_stringio(remote_task, stdin)
265
- command = "#{dir}/wrapper.sh"
266
- write_remote_file(wrapper, command)
267
- make_executable(command)
268
- yield command
269
- end
270
-
271
- def with_remote_task(task_file, stdin)
272
- with_remote_tempdir do |dir|
273
- with_remote_script(dir, task_file) do |remote_task|
274
- if stdin
275
- with_task_wrapper(remote_task, dir, stdin) do |command|
276
- yield command
277
- end
278
- else
279
- yield remote_task
280
- end
281
- end
282
- end
283
- end
284
-
285
294
  def run_command(command, options = {})
286
295
  @run_as = options['_run_as'] || @conf_run_as
287
296
  output = execute(command, sudoable: true)
@@ -292,7 +301,9 @@ SCRIPT
292
301
 
293
302
  def run_script(script, arguments, options = {})
294
303
  @run_as = options['_run_as'] || @conf_run_as
295
- with_remote_file(script) do |remote_path|
304
+ with_remote_tempdir do |dir|
305
+ remote_path = write_remote_executable(dir, script)
306
+ dir.chown(@run_as)
296
307
  output = execute("'#{remote_path}' #{Shellwords.join(arguments)}",
297
308
  sudoable: true)
298
309
  Bolt::Result.for_command(@target, output.stdout.string, output.stderr.string, output.exit_code)
@@ -318,16 +329,22 @@ SCRIPT
318
329
 
319
330
  command = export_args.empty? ? '' : "#{export_args} "
320
331
 
321
- if @run_as
322
- with_remote_task(task, stdin) do |remote_path|
323
- command += "'#{remote_path}'"
324
- output = execute(command, sudoable: true)
325
- end
326
- else
327
- with_remote_file(task) do |remote_path|
328
- command += "'#{remote_path}'"
329
- output = execute(command, stdin: stdin)
332
+ execute_options = {}
333
+
334
+ with_remote_tempdir do |dir|
335
+ remote_task_path = write_remote_executable(dir, task)
336
+ if @run_as && stdin
337
+ wrapper = make_wrapper_stringio(remote_task_path, stdin)
338
+ remote_wrapper_path = write_remote_executable(dir, wrapper, 'wrapper.sh')
339
+ command += "'#{remote_wrapper_path}'"
340
+ else
341
+ command += "'#{remote_task_path}'"
342
+ execute_options[:stdin] = stdin
330
343
  end
344
+ dir.chown(@run_as)
345
+
346
+ execute_options[:sudoable] = true if @run_as
347
+ output = execute(command, **execute_options)
331
348
  end
332
349
  Bolt::Result.for_task(@target, output.stdout.string,
333
350
  output.stderr.string,
@@ -19,8 +19,8 @@ module Bolt
19
19
  @target.port || default_port
20
20
  end
21
21
 
22
- def initialize(target, **kwargs)
23
- super(target, **kwargs)
22
+ def initialize(target)
23
+ super(target)
24
24
  @extensions = DEFAULT_EXTENSIONS.to_set.merge(@extensions || [])
25
25
  @logger.debug { "WinRM initialized for #{@extensions.to_a} extensions" }
26
26
  end
@@ -461,7 +461,7 @@ PS
461
461
  end
462
462
  end
463
463
 
464
- def upload(source, destination)
464
+ def upload(source, destination, _options = nil)
465
465
  write_remote_file(source, destination)
466
466
  Bolt::Result.for_upload(@target, source, destination)
467
467
  end
@@ -170,7 +170,7 @@ module Bolt
170
170
  def fatal_error(e)
171
171
  @stream.puts(colorize(:red, e.message))
172
172
  if e.is_a? Bolt::RunFailure
173
- @stream.puts ::JSON.pretty_generate(e.resultset)
173
+ @stream.puts ::JSON.pretty_generate(e.result_set)
174
174
  end
175
175
  end
176
176
  end
data/lib/bolt/pal.rb CHANGED
@@ -47,7 +47,13 @@ module Bolt
47
47
  r = Puppet::Pal.in_tmp_environment('bolt', modulepath: [BOLTLIB_PATH] + @config[:modulepath], facts: {}) do |pal|
48
48
  pal.with_script_compiler do |compiler|
49
49
  begin
50
- yield compiler
50
+ result = yield compiler
51
+ # TODO: remove after PUP-8441 adds to_json to Errors
52
+ # This hack won't handle nested errors
53
+ if result.is_a? Puppet::DataTypes::Error
54
+ result = result._pcore_init_hash
55
+ end
56
+ result
51
57
  rescue Puppet::PreformattedError => err
52
58
  # Puppet sometimes rescues exceptions notes the location and reraises
53
59
  # For now return the original error. Exception cause support was added in Ruby 2.1
@@ -79,12 +85,12 @@ module Bolt
79
85
  r
80
86
  end
81
87
 
82
- def with_bolt_executor(executor, &block)
83
- Puppet.override(bolt_executor: executor, &block)
88
+ def with_bolt_executor(executor, inventory, &block)
89
+ Puppet.override({ bolt_executor: executor, bolt_inventory: inventory }, &block)
84
90
  end
85
91
 
86
- def in_plan_compiler(executor)
87
- with_bolt_executor(executor) do
92
+ def in_plan_compiler(executor, inventory)
93
+ with_bolt_executor(executor, inventory) do
88
94
  with_puppet_settings do |opts|
89
95
  in_bolt_compiler(opts) do |compiler|
90
96
  yield compiler
@@ -93,8 +99,8 @@ module Bolt
93
99
  end
94
100
  end
95
101
 
96
- def in_task_compiler(executor)
97
- with_bolt_executor(executor) do
102
+ def in_task_compiler(executor, inventory)
103
+ with_bolt_executor(executor, inventory) do
98
104
  in_bolt_compiler do |compiler|
99
105
  yield compiler
100
106
  end
@@ -158,14 +164,14 @@ module Bolt
158
164
  }
159
165
  end
160
166
 
161
- def run_task(object, targets, params, executor, &eventblock)
162
- in_task_compiler(executor) do |compiler|
167
+ def run_task(object, targets, params, executor, inventory, &eventblock)
168
+ in_task_compiler(executor, inventory) do |compiler|
163
169
  compiler.call_function('run_task', object, targets, params, &eventblock)
164
170
  end
165
171
  end
166
172
 
167
- def run_plan(object, params, executor)
168
- in_plan_compiler(executor) do |compiler|
173
+ def run_plan(object, params, executor = nil, inventory = nil)
174
+ in_plan_compiler(executor, inventory) do |compiler|
169
175
  compiler.call_function('run_plan', object, params)
170
176
  end
171
177
  end
data/lib/bolt/result.rb CHANGED
@@ -109,6 +109,14 @@ module Bolt
109
109
  eql?(other)
110
110
  end
111
111
 
112
+ def to_json(opts = nil)
113
+ status_hash.to_json(opts)
114
+ end
115
+
116
+ def to_s
117
+ to_json
118
+ end
119
+
112
120
  # TODO: remove in favor of ok?
113
121
  def success?
114
122
  ok?
@@ -130,10 +138,7 @@ module Bolt
130
138
  # Is it crazy for this to behave differently outside a compiler?
131
139
  def error
132
140
  if error_hash
133
- Puppet::DataTypes::Error.new(error_hash['msg'],
134
- error_hash['kind'],
135
- nil, nil,
136
- error_hash['details'])
141
+ Puppet::DataTypes::Error.from_asserted_hash(error_hash)
137
142
 
138
143
  end
139
144
  end
data/lib/bolt/target.rb CHANGED
@@ -24,6 +24,21 @@ module Bolt
24
24
  @options = options || {}
25
25
  end
26
26
 
27
+ def update_conf(conf)
28
+ @protocol = conf[:transport]
29
+
30
+ t_conf = conf[:transports][protocol.to_sym]
31
+ # Override url methods
32
+ url_keys = %i[user password port]
33
+ @user = t_conf[:user]
34
+ @password = t_conf[:password]
35
+ @port = t_conf[:port]
36
+
37
+ @options = t_conf.reject { |k, _| url_keys.include?(k) }.merge(@options)
38
+
39
+ self
40
+ end
41
+
27
42
  def parse(string)
28
43
  if string =~ %r{^[^:]+://}
29
44
  Addressable::URI.parse(string)
@@ -35,7 +50,7 @@ module Bolt
35
50
  private :parse
36
51
 
37
52
  def eql?(other)
38
- self.class.equal?(other.class) && @uri == other.uri && @options == other.options
53
+ self.class.equal?(other.class) && @uri == other.uri
39
54
  end
40
55
  alias == eql?
41
56
 
@@ -51,30 +66,30 @@ module Bolt
51
66
  @uri_obj.hostname
52
67
  end
53
68
 
54
- def port
55
- @uri_obj.port
56
- end
57
-
58
69
  # name is currently just uri but should be be used instead to identify the
59
70
  # Target ouside the transport or uri options.
60
71
  def name
61
72
  uri
62
73
  end
63
74
 
75
+ def port
76
+ @uri_obj.port || @port
77
+ end
78
+
79
+ def protocol
80
+ @uri_obj.scheme || @protocol
81
+ end
82
+
64
83
  def user
65
84
  Addressable::URI.unencode_component(
66
- @uri_obj.user
85
+ @uri_obj.user || @user
67
86
  )
68
87
  end
69
88
 
70
89
  def password
71
90
  Addressable::URI.unencode_component(
72
- @uri_obj.password
91
+ @uri_obj.password || @password
73
92
  )
74
93
  end
75
-
76
- def protocol
77
- @uri_obj.scheme
78
- end
79
94
  end
80
95
  end