bolt 2.1.0 → 2.2.0

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/Puppetfile +5 -5
  3. data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +1 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +1 -1
  5. data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +1 -1
  6. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +1 -1
  7. data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
  8. data/lib/bolt/applicator.rb +2 -2
  9. data/lib/bolt/bolt_option_parser.rb +1 -1
  10. data/lib/bolt/cli.rb +1 -1
  11. data/lib/bolt/config.rb +201 -206
  12. data/lib/bolt/config/transport/base.rb +142 -0
  13. data/lib/bolt/config/transport/docker.rb +42 -0
  14. data/lib/bolt/config/transport/local.rb +73 -0
  15. data/lib/bolt/config/transport/orch.rb +47 -0
  16. data/lib/bolt/config/transport/remote.rb +25 -0
  17. data/lib/bolt/config/transport/ssh.rb +105 -0
  18. data/lib/bolt/config/transport/winrm.rb +80 -0
  19. data/lib/bolt/executor.rb +17 -0
  20. data/lib/bolt/inventory.rb +12 -5
  21. data/lib/bolt/inventory/group.rb +1 -1
  22. data/lib/bolt/inventory/inventory.rb +16 -22
  23. data/lib/bolt/inventory/target.rb +26 -29
  24. data/lib/bolt/plugin.rb +5 -5
  25. data/lib/bolt/plugin/module.rb +1 -1
  26. data/lib/bolt/plugin/pkcs7.rb +1 -1
  27. data/lib/bolt/result.rb +1 -1
  28. data/lib/bolt/target.rb +5 -2
  29. data/lib/bolt/transport/base.rb +0 -18
  30. data/lib/bolt/transport/docker.rb +0 -26
  31. data/lib/bolt/transport/local.rb +0 -30
  32. data/lib/bolt/transport/local_windows.rb +4 -36
  33. data/lib/bolt/transport/orch.rb +0 -20
  34. data/lib/bolt/transport/remote.rb +0 -20
  35. data/lib/bolt/transport/ssh.rb +0 -85
  36. data/lib/bolt/transport/sudoable.rb +0 -7
  37. data/lib/bolt/transport/winrm.rb +0 -66
  38. data/lib/bolt/util.rb +11 -0
  39. data/lib/bolt/version.rb +1 -1
  40. data/lib/bolt_server/transport_app.rb +1 -0
  41. data/lib/bolt_spec/plans.rb +1 -1
  42. data/lib/bolt_spec/plans/action_stubs/command_stub.rb +1 -1
  43. data/lib/bolt_spec/plans/action_stubs/script_stub.rb +1 -1
  44. data/lib/bolt_spec/plans/action_stubs/task_stub.rb +2 -2
  45. data/lib/bolt_spec/plans/action_stubs/upload_stub.rb +1 -1
  46. data/lib/bolt_spec/run.rb +1 -1
  47. data/libexec/apply_catalog.rb +1 -1
  48. data/libexec/custom_facts.rb +1 -1
  49. data/libexec/query_resources.rb +1 -1
  50. metadata +9 -2
@@ -21,30 +21,10 @@ module Bolt
21
21
 
22
22
  attr_writer :plan_context
23
23
 
24
- OPTIONS = {
25
- "cacert" => "The path to the CA certificate.",
26
- "host" => "Host name.",
27
- "job-poll-interval" => "Set interval to poll orchestrator for job status.",
28
- "job-poll-timeout" => "Set time to wait for orchestrator job status.",
29
- "service-url" => "The URL of the orchestrator API.",
30
- "task-environment" => "The environment the orchestrator loads task code from.",
31
- "token-file" => "The path to the token file."
32
- }.freeze
33
-
34
- def self.options
35
- OPTIONS.keys
36
- end
37
-
38
- def self.default_options
39
- { 'task-environment' => 'production' }
40
- end
41
-
42
24
  def provided_features
43
25
  ['puppet-agent']
44
26
  end
45
27
 
46
- def self.validate(options); end
47
-
48
28
  def initialize(*args)
49
29
  # lazy-load expensive gem code
50
30
  require 'orchestrator_client'
@@ -6,26 +6,6 @@ require 'bolt/transport/base'
6
6
  module Bolt
7
7
  module Transport
8
8
  class Remote < Base
9
- OPTIONS = {
10
- "run-on" => "The proxy target that the task executes on."
11
- }.freeze
12
-
13
- # The options for the remote transport not defined.
14
- def self.filter_options(unfiltered)
15
- unfiltered
16
- end
17
-
18
- def self.default_options
19
- { 'run-on' => 'localhost' }
20
- end
21
-
22
- def self.validate(options)
23
- # This will fail when validating global config
24
- # unless options['device-type']
25
- # raise Bolt::ValidationError, 'Must specify device-type for devices'
26
- # end
27
- end
28
-
29
9
  # TODO: this should have access to inventory so target doesn't have to
30
10
  def initialize(executor)
31
11
  super()
@@ -8,95 +8,10 @@ require 'shellwords'
8
8
  module Bolt
9
9
  module Transport
10
10
  class SSH < Sudoable
11
- OPTIONS = {
12
- "connect-timeout" => "How long to wait when establishing connections.",
13
- "disconnect-timeout" => "How long to wait before force-closing a connection.",
14
- "host" => "Host name.",
15
- "host-key-check" => "Whether to perform host key validation when connecting.",
16
- "interpreters" => "A map of an extension name to the absolute path of an executable, "\
17
- "enabling you to override the shebang defined in a task executable. The "\
18
- "extension can optionally be specified with the `.` character (`.py` and "\
19
- "`py` both map to a task executable `task.py`) and the extension is case "\
20
- "sensitive. When a target's name is `localhost`, Ruby tasks run with the "\
21
- "Bolt Ruby interpreter by default.",
22
- "load-config" => "Whether to load system SSH configuration.",
23
- "password" => "Login password.",
24
- "port" => "Connection port.",
25
- "private-key" => "Either the path to the private key file to use for authentication, or a "\
26
- "hash with the key `key-data` and the contents of the private key.",
27
- "proxyjump" => "A jump host to proxy connections through, and an optional user to "\
28
- "connect with.",
29
- "run-as" => "A different user to run commands as after login.",
30
- "run-as-command" => "The command to elevate permissions. Bolt appends the user and command "\
31
- "strings to the configured `run-as-command` before running it on the "\
32
- "target. This command must not require an interactive password prompt, "\
33
- "and the `sudo-password` option is ignored when `run-as-command` is "\
34
- "specified. The `run-as-command` must be specified as an array.",
35
- "script-dir" => "The subdirectory of the tmpdir to use in place of a randomized "\
36
- "subdirectory for uploading and executing temporary files on the "\
37
- "target. It's expected that this directory already exists as a subdir "\
38
- "of tmpdir, which is either configured or defaults to `/tmp`.",
39
- "sudo-executable" => "The executable to use when escalating to the configured `run-as` "\
40
- "user. This is useful when you want to escalate using the configured "\
41
- "`sudo-password`, since `run-as-command` does not use `sudo-password` "\
42
- "or support prompting. The command executed on the target is "\
43
- "`<sudo-executable> -S -u <user> -p custom_bolt_prompt <command>`. "\
44
- "**This option is experimental.**",
45
- "sudo-password" => "Password to use when changing users via `run-as`.",
46
- "tmpdir" => "The directory to upload and execute temporary files on the target.",
47
- "tty" => "Request a pseudo tty for the session. This option is generally "\
48
- "only used in conjunction with the `run-as` option when the sudoers "\
49
- "policy requires a `tty`.",
50
- "user" => "Login user."
51
- }.freeze
52
-
53
- def self.options
54
- OPTIONS.keys
55
- end
56
-
57
- def self.default_options
58
- {
59
- 'connect-timeout' => 10,
60
- 'tty' => false,
61
- 'load-config' => true,
62
- 'disconnect-timeout' => 5
63
- }
64
- end
65
-
66
11
  def provided_features
67
12
  ['shell']
68
13
  end
69
14
 
70
- def self.validate(options)
71
- validate_sudo_options(options)
72
-
73
- host_key = options['host-key-check']
74
- unless host_key.nil? || !!host_key == host_key
75
- raise Bolt::ValidationError, 'host-key-check option must be a Boolean true or false'
76
- end
77
-
78
- if (key_opt = options['private-key'])
79
- unless key_opt.instance_of?(String) || (key_opt.instance_of?(Hash) && key_opt.include?('key-data'))
80
- raise Bolt::ValidationError,
81
- "private-key option must be the path to a private key file or a hash containing the 'key-data'"
82
- end
83
- end
84
-
85
- %w[connect-timeout disconnect-timeout].each do |timeout|
86
- timeout_value = options[timeout]
87
- unless timeout_value.is_a?(Integer) || timeout_value.nil?
88
- error_msg = "#{timeout} value must be an Integer, received #{timeout_value}:#{timeout_value.class}"
89
- raise Bolt::ValidationError, error_msg
90
- end
91
- end
92
-
93
- if (dir_opt = options['script-dir'])
94
- unless dir_opt.is_a?(String) && !dir_opt.empty?
95
- raise Bolt::ValidationError, "script-dir option must be a non-empty string"
96
- end
97
- end
98
- end
99
-
100
15
  def initialize
101
16
  super
102
17
 
@@ -6,13 +6,6 @@ require 'bolt/transport/base'
6
6
  module Bolt
7
7
  module Transport
8
8
  class Sudoable < Base
9
- def self.validate_sudo_options(options)
10
- run_as_cmd = options['run-as-command']
11
- if run_as_cmd && (!run_as_cmd.is_a?(Array) || run_as_cmd.any? { |n| !n.is_a?(String) })
12
- raise Bolt::ValidationError, "run-as-command must be an Array of Strings, received #{run_as_cmd}"
13
- end
14
- end
15
-
16
9
  def self.sudo_prompt
17
10
  '[sudo] Bolt needs to run as another user, password: '
18
11
  end
@@ -7,46 +7,6 @@ require 'bolt/transport/powershell'
7
7
  module Bolt
8
8
  module Transport
9
9
  class WinRM < Base
10
- OPTIONS = {
11
- "cacert" => "The path to the CA certificate.",
12
- "connect-timeout" => "How long Bolt should wait when establishing connections.",
13
- "extensions" => "List of file extensions that are accepted for scripts or tasks. "\
14
- "Scripts with these file extensions rely on the target's file type "\
15
- "association to run. For example, if Python is installed on the system, "\
16
- "a `.py` script runs with `python.exe`. The extensions `.ps1`, `.rb`, and "\
17
- "`.pp` are always allowed and run via hard-coded executables.",
18
- "file-protocol" => "Which file transfer protocol to use. Either `winrm` or `smb`. Using `smb` is "\
19
- "recommended for large file transfers.",
20
- "host" => "Host name.",
21
- "interpreters" => "A map of an extension name to the absolute path of an executable, "\
22
- "enabling you to override the shebang defined in a task executable. The "\
23
- "extension can optionally be specified with the `.` character (`.py` and "\
24
- "`py` both map to a task executable `task.py`) and the extension is case "\
25
- "sensitive. When a target's name is `localhost`, Ruby tasks run with the "\
26
- "Bolt Ruby interpreter by default.",
27
- "password" => "Login password. **Required unless using Kerberos.**",
28
- "port" => "Connection port.",
29
- "realm" => "Kerberos realm (Active Directory domain) to authenticate against.",
30
- "smb-port" => "With file-protocol set to smb, this is the port to establish a connection on.",
31
- "ssl" => "When true, Bolt uses secure https connections for WinRM.",
32
- "ssl-verify" => "When true, verifies the targets certificate matches the cacert.",
33
- "tmpdir" => "The directory to upload and execute temporary files on the target.",
34
- "user" => "Login user. **Required unless using Kerberos.**"
35
- }.freeze
36
-
37
- def self.options
38
- OPTIONS.keys
39
- end
40
-
41
- def self.default_options
42
- {
43
- 'connect-timeout' => 10,
44
- 'ssl' => true,
45
- 'ssl-verify' => true,
46
- 'file-protocol' => 'winrm'
47
- }
48
- end
49
-
50
10
  def provided_features
51
11
  ['powershell']
52
12
  end
@@ -56,32 +16,6 @@ module Bolt
56
16
  input_method
57
17
  end
58
18
 
59
- def self.validate(options)
60
- ssl_flag = options['ssl']
61
- unless !!ssl_flag == ssl_flag
62
- raise Bolt::ValidationError, 'ssl option must be a Boolean true or false'
63
- end
64
-
65
- if ssl_flag && (options['file-protocol'] == 'smb')
66
- raise Bolt::ValidationError, 'SMB file transfers are not allowed with SSL enabled'
67
- end
68
-
69
- if ssl_flag && (ca_path = options['cacert'])
70
- Bolt::Util.validate_file('cacert', ca_path)
71
- end
72
-
73
- ssl_verify_flag = options['ssl-verify']
74
- unless !!ssl_verify_flag == ssl_verify_flag
75
- raise Bolt::ValidationError, 'ssl-verify option must be a Boolean true or false'
76
- end
77
-
78
- timeout_value = options['connect-timeout']
79
- unless timeout_value.is_a?(Integer) || timeout_value.nil?
80
- error_msg = "connect-timeout value must be an Integer, received #{timeout_value}:#{timeout_value.class}"
81
- raise Bolt::ValidationError, error_msg
82
- end
83
- end
84
-
85
19
  def initialize
86
20
  super
87
21
  require 'winrm'
@@ -238,6 +238,17 @@ module Bolt
238
238
  def symbolize_top_level_keys(hsh)
239
239
  hsh.each_with_object({}) { |(k, v), h| k.is_a?(String) ? h[k.to_sym] = v : h[k] = v }
240
240
  end
241
+
242
+ # Recursively searches a data structure for plugin references
243
+ def references?(input)
244
+ if input.is_a?(Hash)
245
+ input.key?('_plugin') || input.values.any? { |v| references?(v) }
246
+ elsif input.is_a?(Array)
247
+ input.any? { |v| references?(v) }
248
+ else
249
+ false
250
+ end
251
+ end
241
252
  end
242
253
  end
243
254
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '2.1.0'
4
+ VERSION = '2.2.0'
5
5
  end
@@ -4,6 +4,7 @@ require 'sinatra'
4
4
  require 'addressable/uri'
5
5
  require 'bolt'
6
6
  require 'bolt/error'
7
+ require 'bolt/inventory'
7
8
  require 'bolt/target'
8
9
  require 'bolt_server/file_cache'
9
10
  require 'bolt/task/puppet_server'
@@ -181,7 +181,7 @@ module BoltSpec
181
181
  end
182
182
 
183
183
  def inventory
184
- @inventory ||= Bolt::Inventory.create_version(inventory_data, config, plugins)
184
+ @inventory ||= Bolt::Inventory.create_version(inventory_data, config.transport, config.transports, plugins)
185
185
  end
186
186
 
187
187
  # Provided as a class so expectations can be placed on it.
@@ -36,7 +36,7 @@ module BoltSpec
36
36
 
37
37
  def with_params(params)
38
38
  @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
39
- .map { |k, v| [k.sub(/^_/, '').to_sym, v] }.to_h
39
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
40
40
  self
41
41
  end
42
42
  end
@@ -44,7 +44,7 @@ module BoltSpec
44
44
  @invocation[:params] = params
45
45
  @invocation[:arguments] = params['arguments']
46
46
  @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
47
- .map { |k, v| [k.sub(/^_/, '').to_sym, v] }.to_h
47
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
48
48
  self
49
49
  end
50
50
  end
@@ -23,7 +23,7 @@ module BoltSpec
23
23
  @calls += 1
24
24
  if @return_block
25
25
  # Merge arguments and options into params to match puppet function signature.
26
- params = options.map { |k, v| ["_#{k}", v] }.to_h
26
+ params = options.transform_keys { |k| "_#{k}" }
27
27
  params = params.merge(arguments)
28
28
 
29
29
  check_resultset(@return_block.call(targets: targets, task: task, params: params), task)
@@ -49,7 +49,7 @@ module BoltSpec
49
49
  @invocation[:params] = params
50
50
  @invocation[:arguments] = params.reject { |k, _v| k.start_with?('_') }
51
51
  @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
52
- .map { |k, v| [k.sub(/^_/, '').to_sym, v] }.to_h
52
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
53
53
  self
54
54
  end
55
55
  end
@@ -57,7 +57,7 @@ module BoltSpec
57
57
 
58
58
  def with_params(params)
59
59
  @invocation[:options] = params.select { |k, _v| k.start_with?('_') }
60
- .map { |k, v| [k.sub(/^_/, '').to_sym, v] }.to_h
60
+ .transform_keys { |k| k.sub(/^_/, '').to_sym }
61
61
  self
62
62
  end
63
63
  end
@@ -148,7 +148,7 @@ module BoltSpec
148
148
  end
149
149
 
150
150
  def inventory
151
- @inventory ||= Bolt::Inventory.create_version(@inventory_data, config, plugins)
151
+ @inventory ||= Bolt::Inventory.create_version(@inventory_data, config.transport, config.transports, plugins)
152
152
  end
153
153
 
154
154
  def plugins
@@ -68,7 +68,7 @@ begin
68
68
  end
69
69
 
70
70
  # Transport.connect will modify this hash!
71
- transport_conn_info = conn_info.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
71
+ transport_conn_info = conn_info.transform_keys(&:to_sym)
72
72
 
73
73
  transport = Puppet::ResourceApi::Transport.connect(type, transport_conn_info)
74
74
  Puppet::ResourceApi::Transport.inject_device(type, transport)
@@ -46,7 +46,7 @@ Dir.mktmpdir do |puppet_root|
46
46
  end
47
47
 
48
48
  # Transport.connect will modify this hash!
49
- transport_conn_info = conn_info.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
49
+ transport_conn_info = conn_info.transform_keys(&:to_sym)
50
50
  transport = Puppet::ResourceApi::Transport.connect(type, transport_conn_info)
51
51
  Puppet::ResourceApi::Transport.inject_device(type, transport)
52
52
 
@@ -53,7 +53,7 @@ Dir.mktmpdir do |puppet_root|
53
53
  end
54
54
 
55
55
  # Transport.connect will modify this hash!
56
- transport_conn_info = conn_info.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
56
+ transport_conn_info = conn_info.transform_keys(&:to_sym)
57
57
 
58
58
  transport = Puppet::ResourceApi::Transport.connect(type, transport_conn_info)
59
59
  Puppet::ResourceApi::Transport.inject_device(type, transport)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-02 00:00:00.000000000 Z
11
+ date: 2020-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -400,6 +400,13 @@ files:
400
400
  - lib/bolt/catalog/logging.rb
401
401
  - lib/bolt/cli.rb
402
402
  - lib/bolt/config.rb
403
+ - lib/bolt/config/transport/base.rb
404
+ - lib/bolt/config/transport/docker.rb
405
+ - lib/bolt/config/transport/local.rb
406
+ - lib/bolt/config/transport/orch.rb
407
+ - lib/bolt/config/transport/remote.rb
408
+ - lib/bolt/config/transport/ssh.rb
409
+ - lib/bolt/config/transport/winrm.rb
403
410
  - lib/bolt/error.rb
404
411
  - lib/bolt/executor.rb
405
412
  - lib/bolt/inventory.rb