bolt 0.17.1 → 0.17.2

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 (224) hide show
  1. checksums.yaml +4 -4
  2. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +25 -13
  3. data/lib/bolt/cli.rb +45 -15
  4. data/lib/bolt/config.rb +48 -132
  5. data/lib/bolt/executor.rb +3 -10
  6. data/lib/bolt/inventory.rb +15 -1
  7. data/lib/bolt/puppetdb.rb +11 -0
  8. data/lib/bolt/puppetdb/client.rb +68 -0
  9. data/lib/bolt/puppetdb/config.rb +76 -0
  10. data/lib/bolt/target.rb +5 -4
  11. data/lib/bolt/transport/base.rb +11 -2
  12. data/lib/bolt/transport/local.rb +11 -5
  13. data/lib/bolt/transport/orch.rb +16 -5
  14. data/lib/bolt/transport/ssh.rb +32 -1
  15. data/lib/bolt/transport/ssh/connection.rb +17 -10
  16. data/lib/bolt/transport/winrm.rb +18 -1
  17. data/lib/bolt/transport/winrm/connection.rb +15 -16
  18. data/lib/bolt/util.rb +15 -0
  19. data/lib/bolt/version.rb +1 -1
  20. data/lib/bolt_ext/puppetdb_inventory.rb +5 -135
  21. data/vendored/facter/lib/facter/ec2/rest.rb +1 -1
  22. data/vendored/hiera/lib/hiera/version.rb +1 -1
  23. data/vendored/puppet/lib/puppet/application/agent.rb +1 -3
  24. data/vendored/puppet/lib/puppet/application/apply.rb +2 -4
  25. data/vendored/puppet/lib/puppet/application/cert.rb +6 -1
  26. data/vendored/puppet/lib/puppet/application/device.rb +100 -13
  27. data/vendored/puppet/lib/puppet/application/facts.rb +5 -0
  28. data/vendored/puppet/lib/puppet/application/lookup.rb +11 -1
  29. data/vendored/puppet/lib/puppet/configurer.rb +17 -4
  30. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
  31. data/vendored/puppet/lib/puppet/datatypes.rb +1 -1
  32. data/vendored/puppet/lib/puppet/defaults.rb +1 -1
  33. data/vendored/puppet/lib/puppet/environments.rb +2 -2
  34. data/vendored/puppet/lib/puppet/error.rb +6 -3
  35. data/vendored/puppet/lib/puppet/external/dot.rb +0 -7
  36. data/vendored/puppet/lib/puppet/external/nagios/parser.rb +1 -1
  37. data/vendored/puppet/lib/puppet/face/config.rb +41 -8
  38. data/vendored/puppet/lib/puppet/face/epp.rb +30 -5
  39. data/vendored/puppet/lib/puppet/face/facts.rb +49 -0
  40. data/vendored/puppet/lib/puppet/face/help.rb +33 -35
  41. data/vendored/puppet/lib/puppet/face/man.rb +55 -12
  42. data/vendored/puppet/lib/puppet/face/parser.rb +30 -3
  43. data/vendored/puppet/lib/puppet/file_bucket/file.rb +0 -2
  44. data/vendored/puppet/lib/puppet/file_serving/base.rb +10 -10
  45. data/vendored/puppet/lib/puppet/functions.rb +1 -3
  46. data/vendored/puppet/lib/puppet/functions/alert.rb +1 -1
  47. data/vendored/puppet/lib/puppet/functions/all.rb +6 -6
  48. data/vendored/puppet/lib/puppet/functions/annotate.rb +10 -10
  49. data/vendored/puppet/lib/puppet/functions/any.rb +6 -6
  50. data/vendored/puppet/lib/puppet/functions/assert_type.rb +4 -4
  51. data/vendored/puppet/lib/puppet/functions/binary_file.rb +14 -2
  52. data/vendored/puppet/lib/puppet/functions/break.rb +31 -2
  53. data/vendored/puppet/lib/puppet/functions/call.rb +4 -4
  54. data/vendored/puppet/lib/puppet/functions/contain.rb +19 -3
  55. data/vendored/puppet/lib/puppet/functions/convert_to.rb +6 -5
  56. data/vendored/puppet/lib/puppet/functions/crit.rb +1 -1
  57. data/vendored/puppet/lib/puppet/functions/debug.rb +1 -1
  58. data/vendored/puppet/lib/puppet/functions/defined.rb +11 -9
  59. data/vendored/puppet/lib/puppet/functions/dig.rb +26 -2
  60. data/vendored/puppet/lib/puppet/functions/each.rb +8 -8
  61. data/vendored/puppet/lib/puppet/functions/emerg.rb +1 -1
  62. data/vendored/puppet/lib/puppet/functions/empty.rb +79 -0
  63. data/vendored/puppet/lib/puppet/functions/err.rb +1 -1
  64. data/vendored/puppet/lib/puppet/functions/filter.rb +7 -7
  65. data/vendored/puppet/lib/puppet/functions/find_file.rb +15 -1
  66. data/vendored/puppet/lib/puppet/functions/flatten.rb +64 -0
  67. data/vendored/puppet/lib/puppet/functions/hiera.rb +6 -6
  68. data/vendored/puppet/lib/puppet/functions/hiera_array.rb +6 -6
  69. data/vendored/puppet/lib/puppet/functions/hiera_hash.rb +6 -6
  70. data/vendored/puppet/lib/puppet/functions/hiera_include.rb +8 -8
  71. data/vendored/puppet/lib/puppet/functions/include.rb +28 -2
  72. data/vendored/puppet/lib/puppet/functions/info.rb +1 -1
  73. data/vendored/puppet/lib/puppet/functions/inline_epp.rb +2 -2
  74. data/vendored/puppet/lib/puppet/functions/join.rb +56 -0
  75. data/vendored/puppet/lib/puppet/functions/keys.rb +25 -0
  76. data/vendored/puppet/lib/puppet/functions/length.rb +44 -0
  77. data/vendored/puppet/lib/puppet/functions/lest.rb +39 -1
  78. data/vendored/puppet/lib/puppet/functions/map.rb +10 -9
  79. data/vendored/puppet/lib/puppet/functions/match.rb +6 -6
  80. data/vendored/puppet/lib/puppet/functions/new.rb +995 -2
  81. data/vendored/puppet/lib/puppet/functions/next.rb +1 -1
  82. data/vendored/puppet/lib/puppet/functions/notice.rb +1 -1
  83. data/vendored/puppet/lib/puppet/functions/reduce.rb +6 -6
  84. data/vendored/puppet/lib/puppet/functions/regsubst.rb +9 -3
  85. data/vendored/puppet/lib/puppet/functions/require.rb +36 -2
  86. data/vendored/puppet/lib/puppet/functions/return.rb +1 -1
  87. data/vendored/puppet/lib/puppet/functions/reverse_each.rb +71 -2
  88. data/vendored/puppet/lib/puppet/functions/slice.rb +23 -9
  89. data/vendored/puppet/lib/puppet/functions/split.rb +12 -10
  90. data/vendored/puppet/lib/puppet/functions/step.rb +73 -1
  91. data/vendored/puppet/lib/puppet/functions/strftime.rb +176 -2
  92. data/vendored/puppet/lib/puppet/functions/then.rb +65 -2
  93. data/vendored/puppet/lib/puppet/functions/tree_each.rb +19 -19
  94. data/vendored/puppet/lib/puppet/functions/type.rb +42 -1
  95. data/vendored/puppet/lib/puppet/functions/unique.rb +13 -13
  96. data/vendored/puppet/lib/puppet/functions/unwrap.rb +8 -4
  97. data/vendored/puppet/lib/puppet/functions/values.rb +25 -0
  98. data/vendored/puppet/lib/puppet/functions/versioncmp.rb +1 -1
  99. data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
  100. data/vendored/puppet/lib/puppet/functions/with.rb +6 -4
  101. data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +1 -1
  102. data/vendored/puppet/lib/puppet/indirector/facts/facter.rb +1 -3
  103. data/vendored/puppet/lib/puppet/indirector/facts/rest.rb +21 -0
  104. data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +0 -4
  105. data/vendored/puppet/lib/puppet/indirector/file_content/http.rb +3 -1
  106. data/vendored/puppet/lib/puppet/indirector/indirection.rb +5 -3
  107. data/vendored/puppet/lib/puppet/indirector/request.rb +6 -2
  108. data/vendored/puppet/lib/puppet/module/task.rb +2 -2
  109. data/vendored/puppet/lib/puppet/module_tool/tar/mini.rb +57 -4
  110. data/vendored/puppet/lib/puppet/network/authconfig.rb +1 -1
  111. data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +1 -0
  112. data/vendored/puppet/lib/puppet/network/resolver.rb +1 -2
  113. data/vendored/puppet/lib/puppet/node.rb +4 -3
  114. data/vendored/puppet/lib/puppet/parser/compiler.rb +12 -5
  115. data/vendored/puppet/lib/puppet/parser/compiler/catalog_validator/env_relationship_validator.rb +1 -1
  116. data/vendored/puppet/lib/puppet/parser/functions/fqdn_rand.rb +15 -4
  117. data/vendored/puppet/lib/puppet/parser/functions/new.rb +31 -46
  118. data/vendored/puppet/lib/puppet/parser/parser_factory.rb +1 -1
  119. data/vendored/puppet/lib/puppet/parser/resource.rb +1 -1
  120. data/vendored/puppet/lib/puppet/parser/type_loader.rb +11 -11
  121. data/vendored/puppet/lib/puppet/pops/evaluator/closure.rb +1 -1
  122. data/vendored/puppet/lib/puppet/pops/evaluator/collector_transformer.rb +1 -1
  123. data/vendored/puppet/lib/puppet/pops/evaluator/epp_evaluator.rb +2 -2
  124. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_resource_support.rb +2 -2
  125. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +5 -2
  126. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +1 -1
  127. data/vendored/puppet/lib/puppet/pops/issue_reporter.rb +18 -1
  128. data/vendored/puppet/lib/puppet/pops/issues.rb +6 -3
  129. data/vendored/puppet/lib/puppet/pops/loader/ruby_data_type_instantiator.rb +1 -2
  130. data/vendored/puppet/lib/puppet/pops/loader/ruby_function_instantiator.rb +1 -2
  131. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +4 -4
  132. data/vendored/puppet/lib/puppet/pops/loader/type_definition_instantiator.rb +4 -1
  133. data/vendored/puppet/lib/puppet/pops/loaders.rb +18 -7
  134. data/vendored/puppet/lib/puppet/pops/lookup/global_data_provider.rb +1 -1
  135. data/vendored/puppet/lib/puppet/pops/model/factory.rb +6 -3
  136. data/vendored/puppet/lib/puppet/pops/model/model_tree_dumper.rb +4 -0
  137. data/vendored/puppet/lib/puppet/pops/model/pn_transformer.rb +400 -0
  138. data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +1 -1
  139. data/vendored/puppet/lib/puppet/pops/parser/heredoc_support.rb +1 -1
  140. data/vendored/puppet/lib/puppet/pops/parser/lexer_support.rb +3 -2
  141. data/vendored/puppet/lib/puppet/pops/parser/locator.rb +0 -2
  142. data/vendored/puppet/lib/puppet/pops/parser/pn_parser.rb +316 -0
  143. data/vendored/puppet/lib/puppet/pops/pcore.rb +17 -17
  144. data/vendored/puppet/lib/puppet/pops/pn.rb +236 -0
  145. data/vendored/puppet/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
  146. data/vendored/puppet/lib/puppet/pops/types/class_loader.rb +6 -3
  147. data/vendored/puppet/lib/puppet/pops/types/implementation_registry.rb +28 -35
  148. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -3
  149. data/vendored/puppet/lib/puppet/pops/types/p_timespan_type.rb +2 -2
  150. data/vendored/puppet/lib/puppet/pops/types/p_type_set_type.rb +24 -1
  151. data/vendored/puppet/lib/puppet/pops/types/ruby_generator.rb +3 -4
  152. data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +1 -1
  153. data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +0 -4
  154. data/vendored/puppet/lib/puppet/pops/types/type_mismatch_describer.rb +1 -1
  155. data/vendored/puppet/lib/puppet/pops/types/type_parser.rb +14 -7
  156. data/vendored/puppet/lib/puppet/pops/types/types.rb +1 -1
  157. data/vendored/puppet/lib/puppet/pops/utils.rb +2 -2
  158. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +6 -2
  159. data/vendored/puppet/lib/puppet/provider/group/groupadd.rb +3 -1
  160. data/vendored/puppet/lib/puppet/provider/group/windows_adsi.rb +4 -7
  161. data/vendored/puppet/lib/puppet/provider/nameservice.rb +3 -3
  162. data/vendored/puppet/lib/puppet/provider/package/dnf.rb +1 -1
  163. data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
  164. data/vendored/puppet/lib/puppet/provider/package/pacman.rb +4 -4
  165. data/vendored/puppet/lib/puppet/provider/package/pip.rb +3 -3
  166. data/vendored/puppet/lib/puppet/provider/package/pkgdmg.rb +3 -3
  167. data/vendored/puppet/lib/puppet/provider/package/pkgutil.rb +2 -2
  168. data/vendored/puppet/lib/puppet/provider/package/portage.rb +9 -9
  169. data/vendored/puppet/lib/puppet/provider/package/zypper.rb +2 -2
  170. data/vendored/puppet/lib/puppet/provider/service/base.rb +1 -1
  171. data/vendored/puppet/lib/puppet/provider/service/smf.rb +3 -2
  172. data/vendored/puppet/lib/puppet/provider/user/useradd.rb +6 -2
  173. data/vendored/puppet/lib/puppet/provider/user/windows_adsi.rb +1 -1
  174. data/vendored/puppet/lib/puppet/provider/zfs/zfs.rb +3 -2
  175. data/vendored/puppet/lib/puppet/reference/configuration.rb +2 -0
  176. data/vendored/puppet/lib/puppet/reference/type.rb +11 -11
  177. data/vendored/puppet/lib/puppet/resource.rb +1 -1
  178. data/vendored/puppet/lib/puppet/resource/capability_finder.rb +2 -2
  179. data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -2
  180. data/vendored/puppet/lib/puppet/resource/status.rb +9 -2
  181. data/vendored/puppet/lib/puppet/resource/type.rb +1 -1
  182. data/vendored/puppet/lib/puppet/settings.rb +31 -19
  183. data/vendored/puppet/lib/puppet/settings/base_setting.rb +5 -0
  184. data/vendored/puppet/lib/puppet/settings/config_file.rb +1 -1
  185. data/vendored/puppet/lib/puppet/settings/ttl_setting.rb +5 -0
  186. data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +2 -2
  187. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +0 -2
  188. data/vendored/puppet/lib/puppet/transaction/additional_resource_generator.rb +2 -2
  189. data/vendored/puppet/lib/puppet/transaction/event.rb +1 -1
  190. data/vendored/puppet/lib/puppet/transaction/report.rb +1 -1
  191. data/vendored/puppet/lib/puppet/type.rb +9 -13
  192. data/vendored/puppet/lib/puppet/type/augeas.rb +2 -2
  193. data/vendored/puppet/lib/puppet/type/cron.rb +11 -6
  194. data/vendored/puppet/lib/puppet/type/exec.rb +1 -1
  195. data/vendored/puppet/lib/puppet/type/file.rb +4 -5
  196. data/vendored/puppet/lib/puppet/type/host.rb +1 -1
  197. data/vendored/puppet/lib/puppet/type/k5login.rb +30 -54
  198. data/vendored/puppet/lib/puppet/type/package.rb +3 -3
  199. data/vendored/puppet/lib/puppet/type/schedule.rb +12 -12
  200. data/vendored/puppet/lib/puppet/type/scheduled_task.rb +2 -2
  201. data/vendored/puppet/lib/puppet/type/ssh_authorized_key.rb +5 -5
  202. data/vendored/puppet/lib/puppet/type/sshkey.rb +2 -2
  203. data/vendored/puppet/lib/puppet/type/tidy.rb +9 -2
  204. data/vendored/puppet/lib/puppet/type/user.rb +1 -1
  205. data/vendored/puppet/lib/puppet/type/yumrepo.rb +25 -4
  206. data/vendored/puppet/lib/puppet/type/zfs.rb +4 -0
  207. data/vendored/puppet/lib/puppet/util.rb +0 -4
  208. data/vendored/puppet/lib/puppet/util/backups.rb +1 -1
  209. data/vendored/puppet/lib/puppet/util/http_proxy.rb +4 -2
  210. data/vendored/puppet/lib/puppet/util/inifile.rb +3 -4
  211. data/vendored/puppet/lib/puppet/util/log.rb +2 -5
  212. data/vendored/puppet/lib/puppet/util/network_device/cisco/facts.rb +1 -1
  213. data/vendored/puppet/lib/puppet/util/reference.rb +1 -8
  214. data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
  215. data/vendored/puppet/lib/puppet/util/warnings.rb +0 -2
  216. data/vendored/puppet/lib/puppet/util/windows/adsi.rb +15 -18
  217. data/vendored/puppet/lib/puppet/util/windows/com.rb +2 -1
  218. data/vendored/puppet/lib/puppet/util/windows/file.rb +2 -2
  219. data/vendored/puppet/lib/puppet/util/windows/principal.rb +7 -6
  220. data/vendored/puppet/lib/puppet/util/windows/sid.rb +60 -7
  221. data/vendored/puppet/lib/puppet/util/windows/taskscheduler.rb +0 -9
  222. data/vendored/puppet/lib/puppet/version.rb +1 -1
  223. data/vendored/puppet/lib/puppet_pal.rb +53 -48
  224. metadata +15 -2
@@ -7,7 +7,24 @@ module Bolt
7
7
  -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass
8
8
  ].freeze
9
9
 
10
- def initialize(_config)
10
+ def self.options
11
+ %w[port user password connect-timeout ssl tmpdir cacert extensions]
12
+ end
13
+
14
+ def self.validate(options)
15
+ ssl_flag = options['ssl']
16
+ unless !!ssl_flag == ssl_flag
17
+ raise Bolt::CLIError, 'ssl option must be a Boolean true or false'
18
+ end
19
+
20
+ timeout_value = options['connect-timeout']
21
+ unless timeout_value.is_a?(Integer) || timeout_value.nil?
22
+ error_msg = "connect-timeout value must be an Integer, received #{timeout_value}:#{timeout_value.class}"
23
+ raise Bolt::CLIError, error_msg
24
+ end
25
+ end
26
+
27
+ def initialize
11
28
  super
12
29
  require 'winrm'
13
30
  require 'winrm-fs'
@@ -7,13 +7,18 @@ module Bolt
7
7
  class Connection
8
8
  attr_reader :logger, :target
9
9
 
10
+ DEFAULT_EXTENSIONS = ['.ps1', '.rb', '.pp'].freeze
11
+
10
12
  def initialize(target)
11
13
  @target = target
12
14
 
13
- default_port = target.options[:ssl] ? HTTPS_PORT : HTTP_PORT
15
+ default_port = target.options['ssl'] ? HTTPS_PORT : HTTP_PORT
14
16
  @port = @target.port || default_port
15
17
  @user = @target.user
16
- @extensions = DEFAULT_EXTENSIONS.to_set.merge(target.options[:extensions] || [])
18
+
19
+ # Accept a single entry or a list, ensure each is prefixed with '.'
20
+ extensions = [target.options['extensions'] || []].flatten.map { |ext| ext[0] != '.' ? '.' + ext : ext }
21
+ @extensions = DEFAULT_EXTENSIONS.to_set.merge(extensions)
17
22
 
18
23
  @logger = Logging.logger[@target.host]
19
24
  end
@@ -22,7 +27,7 @@ module Bolt
22
27
  HTTPS_PORT = 5986
23
28
 
24
29
  def connect
25
- if target.options[:ssl]
30
+ if target.options['ssl']
26
31
  scheme = 'https'
27
32
  transport = :ssl
28
33
  else
@@ -35,9 +40,9 @@ module Bolt
35
40
  password: target.password,
36
41
  retry_limit: 1,
37
42
  transport: transport,
38
- ca_trust_path: target.options[:cacert] }
43
+ ca_trust_path: target.options['cacert'] }
39
44
 
40
- Timeout.timeout(target.options[:connect_timeout]) do
45
+ Timeout.timeout(target.options['connect-timeout']) do
41
46
  @connection = ::WinRM::Connection.new(options)
42
47
  transport_logger = Logging.logger[::WinRM]
43
48
  transport_logger.level = :warn
@@ -50,11 +55,11 @@ module Bolt
50
55
  rescue Timeout::Error
51
56
  # If we're using the default port with SSL, a timeout probably means the
52
57
  # host doesn't support SSL.
53
- if target.options[:ssl] && @port == HTTPS_PORT
54
- theres_your_problem = "\nUse --no-ssl if this host isn't configured to use SSL for WinRM"
58
+ if target.options['ssl'] && @port == HTTPS_PORT
59
+ the_problem = "\nUse --no-ssl if this host isn't configured to use SSL for WinRM"
55
60
  end
56
61
  raise Bolt::Node::ConnectError.new(
57
- "Timeout after #{target.options[:connect_timeout]} seconds connecting to #{endpoint}#{theres_your_problem}",
62
+ "Timeout after #{target.options['connect-timeout']} seconds connecting to #{endpoint}#{the_problem}",
58
63
  'CONNECT_ERROR'
59
64
  )
60
65
  rescue ::WinRM::WinRMAuthorizationError
@@ -64,7 +69,7 @@ module Bolt
64
69
  )
65
70
  rescue OpenSSL::SSL::SSLError => e
66
71
  # If we're using SSL with the default non-SSL port, mention that as a likely problem
67
- if target.options[:ssl] && @port == HTTP_PORT
72
+ if target.options['ssl'] && @port == HTTP_PORT
68
73
  theres_your_problem = "\nAre you using SSL to connect to a non-SSL port?"
69
74
  end
70
75
  raise Bolt::Node::ConnectError.new(
@@ -419,12 +424,6 @@ exit $(Invoke-Interpreter @invokeArgs)
419
424
  PS
420
425
  end
421
426
 
422
- DEFAULT_EXTENSIONS = ['.ps1', '.rb', '.pp'].freeze
423
-
424
- PS_ARGS = %w[
425
- -NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass
426
- ].freeze
427
-
428
427
  def write_remote_file(source, destination)
429
428
  fs = ::WinRM::FS::FileManager.new(@connection)
430
429
  # TODO: raise FileError here if this fails
@@ -432,7 +431,7 @@ PS
432
431
  end
433
432
 
434
433
  def make_tempdir
435
- find_parent = target.options[:tmpdir] ? "\"#{target.options[:tmpdir]}\"" : '[System.IO.Path]::GetTempPath()'
434
+ find_parent = target.options['tmpdir'] ? "\"#{target.options['tmpdir']}\"" : '[System.IO.Path]::GetTempPath()'
436
435
  result = execute(<<-PS)
437
436
  $parent = #{find_parent}
438
437
  $name = [System.IO.Path]::GetRandomFileName()
@@ -43,6 +43,21 @@ module Bolt
43
43
  hash1.merge(hash2, &recursive_merge)
44
44
  end
45
45
 
46
+ # Accepts a Data object and returns a copy with all hash keys
47
+ # modifed by block. use &:to_s to stringify keys or :to_sym to symbolize them
48
+ def walk_keys(data, &block)
49
+ if data.is_a? Hash
50
+ data.each_with_object({}) do |(k, v), acc|
51
+ v = walk_keys(v, &block)
52
+ acc[yield(k)] = v
53
+ end
54
+ elsif data.is_a? Array
55
+ data.map { |v| walk_keys(v, &block) }
56
+ else
57
+ data
58
+ end
59
+ end
60
+
46
61
  # Performs a deep_clone, using an identical copy if the cloned structure contains multiple
47
62
  # references to the same object and prevents endless recursion.
48
63
  # Credit to Jan Molic via https://github.com/rubyworks/facets/blob/master/LICENSE.txt
@@ -1,3 +1,3 @@
1
1
  module Bolt
2
- VERSION = '0.17.1'.freeze
2
+ VERSION = '0.17.2'.freeze
3
3
  end
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'bolt/puppetdb/config'
3
4
  require 'json'
4
5
  require 'httpclient'
5
6
  require 'optparse'
@@ -7,137 +8,6 @@ require 'yaml'
7
8
 
8
9
  module Bolt
9
10
  class PuppetDBInventory
10
- class Client
11
- def self.from_config(config)
12
- uri = if config['server_urls'].is_a? String
13
- config['server_urls']
14
- else
15
- config['server_urls'].first
16
- end
17
- uri = URI.parse(uri)
18
- uri.port ||= 8081
19
-
20
- cacert = File.expand_path(config['cacert'])
21
- token = config.token
22
-
23
- cert = config['cert']
24
- key = config['key']
25
-
26
- new(uri, cacert, token: token, cert: cert, key: key)
27
- end
28
-
29
- def initialize(uri, cacert, token: nil, cert: nil, key: nil)
30
- @uri = uri
31
- @cacert = cacert
32
- @token = token
33
- @cert = cert
34
- @key = key
35
- end
36
-
37
- def query_certnames(query)
38
- return [] unless query
39
-
40
- body = JSON.generate(query: query)
41
-
42
- response = http_client.post("#{@uri}/pdb/query/v4", body: body, header: headers)
43
- if response.code != 200
44
- raise "Failed to query PuppetDB: #{response.body}"
45
- else
46
- results = JSON.parse(response.body)
47
- if results.first && !results.first.key?('certname')
48
- raise "Query results did not contain a 'certname' field: got #{results.first.keys.join(', ')}"
49
- end
50
- results.map { |result| result['certname'] }.uniq
51
- end
52
- end
53
-
54
- def http_client
55
- return @http if @http
56
- @http = HTTPClient.new
57
- @http.ssl_config.set_client_cert_file(@cert, @key)
58
- @http.ssl_config.add_trust_ca(@cacert)
59
-
60
- @http
61
- end
62
-
63
- def headers
64
- headers = { 'Content-Type' => 'application/json' }
65
- headers['X-Authentication'] = @token if @token
66
- headers
67
- end
68
- end
69
-
70
- class Config
71
- DEFAULT_TOKEN = File.expand_path('~/.puppetlabs/token')
72
- DEFAULT_CONFIG = File.expand_path('~/.puppetlabs/client-tools/puppetdb.conf')
73
-
74
- def initialize(config_file, options)
75
- @settings = load_config(config_file)
76
- @settings.merge!(options)
77
-
78
- expand_paths
79
- validate
80
- end
81
-
82
- def load_config(filename)
83
- if filename
84
- if File.exist?(filename)
85
- config = JSON.parse(File.read(filename))
86
- else
87
- raise "config file #{filename} does not exist"
88
- end
89
- elsif File.exist?(DEFAULT_CONFIG)
90
- config = JSON.parse(File.read(DEFAULT_CONFIG))
91
- else
92
- config = {}
93
- end
94
- config.fetch('puppetdb', {})
95
- end
96
-
97
- def token
98
- return @token if @token
99
- if @settings['token']
100
- File.read(@settings['token'])
101
- elsif File.exist?(DEFAULT_TOKEN)
102
- File.read(DEFAULT_TOKEN)
103
- end
104
- end
105
-
106
- def [](key)
107
- @settings[key]
108
- end
109
-
110
- def expand_paths
111
- %w[cacert cert key token].each do |file|
112
- @settings[file] = File.expand_path(@settings[file]) if @settings[file]
113
- end
114
- end
115
-
116
- def validate_file_exists(file)
117
- if @settings[file] && !File.exist?(@settings[file])
118
- raise "#{file} file #{@settings[file]} does not exist"
119
- end
120
- end
121
-
122
- def validate
123
- unless @settings['server_urls']
124
- raise "server_urls must be specified in the config file or with --url"
125
- end
126
- unless @settings['cacert']
127
- raise "cacert must be specified in the config file or with --cacert"
128
- end
129
-
130
- if (@settings['cert'] && !@settings['key']) ||
131
- (!@settings['cert'] && @settings['key'])
132
- raise "cert and key must be specified together"
133
- end
134
-
135
- validate_file_exists('cacert')
136
- validate_file_exists('cert')
137
- validate_file_exists('key')
138
- end
139
- end
140
-
141
11
  class CLI
142
12
  def initialize(args)
143
13
  @args = args
@@ -158,7 +28,7 @@ module Bolt
158
28
  end
159
29
  opts.on('--token-file TOKEN',
160
30
  "Path to the token file",
161
- "Default: #{Config::DEFAULT_TOKEN} if present") do |token|
31
+ "Default: #{Bolt::PuppetDB::Config::DEFAULT_TOKEN} if present") do |token|
162
32
  @cli_opts['token'] = token
163
33
  end
164
34
  opts.on('--url URL', "The URL of the PuppetDB server to connect to") do |url|
@@ -166,7 +36,7 @@ module Bolt
166
36
  end
167
37
  opts.on('--config CONFIG',
168
38
  "The puppetdb.conf file to read configuration from",
169
- "Default: #{Config::DEFAULT_CONFIG} if present") do |file|
39
+ "Default: #{Bolt::PuppetDB::Config::DEFAULT_CONFIG} if present") do |file|
170
40
  @config_file = File.expand_path(file)
171
41
  end
172
42
  opts.on('--output FILE', '-o FILE',
@@ -211,8 +81,8 @@ query results.
211
81
  raise "Unknown argument(s) #{positional_args.join(', ')}"
212
82
  end
213
83
 
214
- config = Config.new(@config_file, @cli_opts)
215
- @puppetdb_client = Client.from_config(config)
84
+ config = Bolt::PuppetDB::Config.new(@config_file, @cli_opts)
85
+ @puppetdb_client = Bolt::PuppetDB::Client.from_config(config)
216
86
 
217
87
  unless File.readable?(inventory_file)
218
88
  raise "Can't read the inventory file #{inventory_file}"
@@ -25,7 +25,7 @@ module Facter
25
25
  attempts = 0
26
26
 
27
27
  begin
28
- open(@baseurl, :proxy => nil, :read_timeout => timeout).read
28
+ open(@baseurl, :proxy => nil, :read_timeout => timeout, :open_timeout => timeout).read
29
29
  able_to_connect = true
30
30
  rescue OpenURI::HTTPError => e
31
31
  if e.message.match /404 Not Found/i
@@ -7,7 +7,7 @@
7
7
 
8
8
 
9
9
  class Hiera
10
- VERSION = "3.4.2"
10
+ VERSION = "3.4.3"
11
11
 
12
12
  ##
13
13
  # version is a public API method intended to always provide a fast and
@@ -422,9 +422,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
422
422
  # we want the last report to be persisted locally
423
423
  Puppet::Transaction::Report.indirection.cache_class = :yaml
424
424
 
425
- if Puppet[:noop]
426
- Puppet::Resource::Catalog.indirection.cache_class = nil
427
- elsif Puppet[:catalog_cache_terminus]
425
+ if Puppet[:catalog_cache_terminus]
428
426
  Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
429
427
  end
430
428
 
@@ -245,7 +245,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
245
245
  $stderr.puts _("%{file} is not readable") % { file: file }
246
246
  exit(63)
247
247
  end
248
- node.classes = Puppet::FileSystem.read(file, :encoding => 'utf-8').split(/[\s\n]+/)
248
+ node.classes = Puppet::FileSystem.read(file, :encoding => 'utf-8').split(/[\s]+/)
249
249
  end
250
250
  end
251
251
 
@@ -322,9 +322,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
322
322
  Puppet.settings.use :main, :agent, :ssl
323
323
 
324
324
 
325
- if Puppet[:noop]
326
- Puppet::Resource::Catalog.indirection.cache_class = nil
327
- elsif Puppet[:catalog_cache_terminus]
325
+ if Puppet[:catalog_cache_terminus]
328
326
  Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
329
327
  end
330
328
 
@@ -268,7 +268,12 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
268
268
  hosts = command_line.args.collect { |h| h.downcase }
269
269
  end
270
270
  begin
271
- apply(@ca, :revoke, options.merge(:to => hosts)) if subcommand == :destroy
271
+ if subcommand == :destroy
272
+ raise _("Refusing to destroy all certs, provide an explicit list of certs to destroy") if hosts == :all
273
+
274
+ signed_hosts = hosts - @ca.waiting?
275
+ apply(@ca, :revoke, options.merge(:to => signed_hosts)) unless signed_hosts.empty?
276
+ end
272
277
  apply(@ca, subcommand, options.merge(:to => hosts, :digest => @digest))
273
278
  rescue => detail
274
279
  Puppet.log_exception(detail)
@@ -24,13 +24,16 @@ class Puppet::Application::Device < Puppet::Application
24
24
  end
25
25
 
26
26
  {
27
+ :apply => nil,
27
28
  :waitforcert => nil,
28
29
  :detailed_exitcodes => false,
29
30
  :verbose => false,
30
31
  :debug => false,
31
32
  :centrallogs => false,
32
33
  :setdest => false,
34
+ :resource => false,
33
35
  :target => nil,
36
+ :to_yaml => false,
34
37
  }.each do |opt,val|
35
38
  options[opt] = val
36
39
  end
@@ -40,12 +43,18 @@ class Puppet::Application::Device < Puppet::Application
40
43
 
41
44
  option("--centrallogging")
42
45
  option("--debug","-d")
46
+ option("--resource","-r")
47
+ option("--to_yaml","-y")
43
48
  option("--verbose","-v")
44
49
 
45
50
  option("--detailed-exitcodes") do |arg|
46
51
  options[:detailed_exitcodes] = true
47
52
  end
48
53
 
54
+ option("--apply MANIFEST") do |arg|
55
+ options[:apply] = arg.to_s
56
+ end
57
+
49
58
  option("--logdest DEST", "-l DEST") do |arg|
50
59
  handle_logdest_arg(arg)
51
60
  end
@@ -85,6 +94,7 @@ USAGE
85
94
  puppet device [-d|--debug] [--detailed-exitcodes] [--deviceconfig <file>]
86
95
  [-h|--help] [-l|--logdest syslog|<file>|console]
87
96
  [-v|--verbose] [-w|--waitforcert <seconds>]
97
+ [-a|--apply <file>] [-r|--resource <type> [name]]
88
98
  [-t|--target <device>] [--user=<user>] [-V|--version]
89
99
 
90
100
 
@@ -150,10 +160,21 @@ you can specify '--server <servername>' as an argument.
150
160
  appending nature of logging. It must be appended manually to make the content
151
161
  valid JSON.
152
162
 
163
+ * --apply:
164
+ Apply a manifest against a remote target. Target must be specified.
165
+
166
+ * --resource:
167
+ Displays a resource state as Puppet code, roughly equivalent to
168
+ `puppet resource`. Can be filterd by title. Requires --target be specified.
169
+
153
170
  * --target:
154
171
  Target a specific device/certificate in the device.conf. Doing so will perform a
155
172
  device run against only that device/certificate.
156
173
 
174
+ * --to_yaml:
175
+ Output found resources in yaml format, suitable to use with Hiera and
176
+ create_resources.
177
+
157
178
  * --user:
158
179
  The user to run as.
159
180
 
@@ -170,7 +191,7 @@ you can specify '--server <servername>' as an argument.
170
191
 
171
192
  EXAMPLE
172
193
  -------
173
- $ puppet device --server puppet.domain.com
194
+ $ puppet device --target remotehost --verbose
174
195
 
175
196
  AUTHOR
176
197
  ------
@@ -182,10 +203,24 @@ COPYRIGHT
182
203
  Copyright (c) 2011 Puppet Inc., LLC
183
204
  Licensed under the Apache 2.0 License
184
205
  HELP
185
- end
206
+ end
186
207
 
187
208
 
188
209
  def main
210
+ if options[:resource] and !options[:target]
211
+ Puppet.err _("resource command requires target")
212
+ exit(1)
213
+ end
214
+ unless options[:apply].nil?
215
+ if options[:target].nil?
216
+ Puppet.err _("missing argument: --target is required when using --apply")
217
+ exit(1)
218
+ end
219
+ unless File.file?(options[:apply])
220
+ Puppet.err _("%{file} does not exist, cannot apply") % { file: options[:apply] }
221
+ exit(1)
222
+ end
223
+ end
189
224
  vardir = Puppet[:vardir]
190
225
  confdir = Puppet[:confdir]
191
226
  certname = Puppet[:certname]
@@ -212,27 +247,61 @@ Licensed under the Apache 2.0 License
212
247
  # Handle nil scheme & port
213
248
  scheme = "#{device_url.scheme}://" if device_url.scheme
214
249
  port = ":#{device_url.port}" if device_url.port
215
- Puppet.info _("starting applying configuration to %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
216
250
 
217
251
  # override local $vardir and $certname
218
252
  Puppet[:confdir] = ::File.join(Puppet[:devicedir], device.name)
219
253
  Puppet[:vardir] = ::File.join(Puppet[:devicedir], device.name)
220
254
  Puppet[:certname] = device.name
221
255
 
222
- # this will reload and recompute default settings and create the devices sub vardir, or we hope so :-)
223
- Puppet.settings.use :main, :agent, :ssl
224
-
225
256
  # this init the device singleton, so that the facts terminus
226
257
  # and the various network_device provider can use it
227
258
  Puppet::Util::NetworkDevice.init(device)
228
259
 
229
- # ask for a ssl cert if needed, but at least
230
- # setup the ssl system for this device.
231
- setup_host
232
-
233
- require 'puppet/configurer'
234
- configurer = Puppet::Configurer.new
235
- configurer.run(:network_device => true, :pluginsync => Puppet::Configurer.should_pluginsync?)
260
+ if options[:resource]
261
+ type, name = parse_args(command_line.args)
262
+ Puppet.info _("retrieving resource: %{resource} from %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { resource: type, target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
263
+
264
+ resources = find_resources(type, name)
265
+
266
+ if options[:to_yaml]
267
+ text = resources.map do |resource|
268
+ resource.prune_parameters(:parameters_to_include => @extra_params).to_hierayaml.force_encoding(Encoding.default_external)
269
+ end.join("\n")
270
+ text.prepend("#{type.downcase}:\n")
271
+ else
272
+ text = resources.map do |resource|
273
+ resource.prune_parameters(:parameters_to_include => @extra_params).to_manifest.force_encoding(Encoding.default_external)
274
+ end.join("\n")
275
+ end
276
+ (puts text)
277
+ elsif options[:apply]
278
+ # avoid reporting to server
279
+ Puppet::Transaction::Report.indirection.terminus_class = :yaml
280
+ Puppet::Resource::Catalog.indirection.cache_class = nil
281
+
282
+ require 'puppet/application/apply'
283
+ begin
284
+
285
+ Puppet[:node_terminus] = :plain
286
+ Puppet[:catalog_terminus] = :compiler
287
+ Puppet[:catalog_cache_terminus] = nil
288
+ Puppet[:facts_terminus] = :network_device
289
+ Puppet.override(:network_device => true) do
290
+ Puppet::Application::Apply.new(Puppet::Util::CommandLine.new('puppet', ["apply", options[:apply]])).run_command
291
+ end
292
+ end
293
+ else
294
+ Puppet.info _("starting applying configuration to %{target} at %{scheme}%{url_host}%{port}%{url_path}") % { target: device.name, scheme: scheme, url_host: device_url.host, port: port, url_path: device_url.path }
295
+ # this will reload and recompute default settings and create the devices sub vardir
296
+ Puppet.settings.use :main, :agent, :ssl
297
+ # ask for a ssl cert if needed, but at least
298
+ # setup the ssl system for this device.
299
+ setup_host
300
+
301
+ require 'puppet/configurer'
302
+ configurer = Puppet::Configurer.new
303
+ configurer.run(:network_device => true, :pluginsync => Puppet::Configurer.should_pluginsync?)
304
+ end
236
305
  rescue => detail
237
306
  Puppet.log_exception(detail)
238
307
  # If we rescued an error, then we return 1 as the exit code
@@ -258,6 +327,24 @@ Licensed under the Apache 2.0 License
258
327
  end
259
328
  end
260
329
 
330
+ def parse_args(args)
331
+ type = args.shift or raise _("You must specify the type to display")
332
+ Puppet::Type.type(type) or raise _("Could not find type %{type}") % { type: type }
333
+ name = args.shift
334
+
335
+ [type, name]
336
+ end
337
+
338
+ def find_resources(type, name)
339
+ key = [type, name].join('/')
340
+
341
+ if name
342
+ [ Puppet::Resource.indirection.find( key ) ]
343
+ else
344
+ Puppet::Resource.indirection.search( key, {} )
345
+ end
346
+ end
347
+
261
348
  def setup_host
262
349
  @host = Puppet::SSL::Host.new
263
350
  waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])