bolt 0.23.0 → 0.24.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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +5 -2
  3. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +5 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +5 -8
  5. data/lib/bolt/applicator.rb +11 -8
  6. data/lib/bolt/boltdir.rb +13 -5
  7. data/lib/bolt/catalog.rb +22 -47
  8. data/lib/bolt/config.rb +1 -26
  9. data/lib/bolt/executor.rb +1 -1
  10. data/lib/bolt/outputter.rb +0 -9
  11. data/lib/bolt/outputter/human.rb +29 -14
  12. data/lib/bolt/outputter/json.rb +12 -1
  13. data/lib/bolt/pal.rb +12 -10
  14. data/lib/bolt/target.rb +0 -6
  15. data/lib/bolt/task.rb +53 -10
  16. data/lib/bolt/transport/base.rb +1 -6
  17. data/lib/bolt/transport/local.rb +11 -13
  18. data/lib/bolt/transport/local/shell.rb +2 -2
  19. data/lib/bolt/transport/ssh.rb +16 -11
  20. data/lib/bolt/transport/winrm.rb +8 -11
  21. data/lib/bolt/version.rb +1 -1
  22. data/lib/bolt_ext/schemas/task.json +12 -5
  23. data/libexec/apply_catalog.rb +3 -1
  24. data/libexec/bolt_catalog +4 -0
  25. data/vendored/puppet/lib/puppet.rb +2 -1
  26. data/vendored/puppet/lib/puppet/application/agent.rb +2 -6
  27. data/vendored/puppet/lib/puppet/application/apply.rb +100 -60
  28. data/vendored/puppet/lib/puppet/application/cert.rb +26 -291
  29. data/vendored/puppet/lib/puppet/application/device.rb +0 -5
  30. data/vendored/puppet/lib/puppet/application/lookup.rb +1 -1
  31. data/vendored/puppet/lib/puppet/application/ssl.rb +133 -0
  32. data/vendored/puppet/lib/puppet/application_support.rb +1 -2
  33. data/vendored/puppet/lib/puppet/configurer.rb +34 -50
  34. data/vendored/puppet/lib/puppet/configurer/downloader.rb +1 -1
  35. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
  36. data/vendored/puppet/lib/puppet/daemon.rb +1 -1
  37. data/vendored/puppet/lib/puppet/defaults.rb +40 -117
  38. data/vendored/puppet/lib/puppet/face/epp.rb +2 -2
  39. data/vendored/puppet/lib/puppet/face/help.rb +21 -7
  40. data/vendored/puppet/lib/puppet/face/node/clean.rb +14 -10
  41. data/vendored/puppet/lib/puppet/feature/base.rb +7 -23
  42. data/vendored/puppet/lib/puppet/feature/eventlog.rb +1 -1
  43. data/vendored/puppet/lib/puppet/file_serving/base.rb +2 -2
  44. data/vendored/puppet/lib/puppet/file_serving/fileset.rb +1 -1
  45. data/vendored/puppet/lib/puppet/file_serving/metadata.rb +2 -2
  46. data/vendored/puppet/lib/puppet/functions.rb +133 -0
  47. data/vendored/puppet/lib/puppet/functions/eyaml_lookup_key.rb +4 -5
  48. data/vendored/puppet/lib/puppet/functions/filter.rb +7 -6
  49. data/vendored/puppet/lib/puppet/functions/new.rb +37 -53
  50. data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
  51. data/vendored/puppet/lib/puppet/functions/yaml_data.rb +4 -5
  52. data/vendored/puppet/lib/puppet/gettext/config.rb +1 -1
  53. data/vendored/puppet/lib/puppet/graph.rb +0 -2
  54. data/vendored/puppet/lib/puppet/indirector/catalog/json.rb +14 -3
  55. data/vendored/puppet/lib/puppet/indirector/catalog/yaml.rb +0 -16
  56. data/vendored/puppet/lib/puppet/indirector/certificate/file.rb +0 -1
  57. data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +4 -2
  58. data/vendored/puppet/lib/puppet/indirector/key/file.rb +1 -6
  59. data/vendored/puppet/lib/puppet/indirector/node/exec.rb +1 -3
  60. data/vendored/puppet/lib/puppet/indirector/node/yaml.rb +0 -6
  61. data/vendored/puppet/lib/puppet/indirector/request.rb +1 -1
  62. data/vendored/puppet/lib/puppet/indirector/ssl_file.rb +3 -44
  63. data/vendored/puppet/lib/puppet/indirector/yaml.rb +4 -4
  64. data/vendored/puppet/lib/puppet/info_service/task_information_service.rb +7 -3
  65. data/vendored/puppet/lib/puppet/loaders.rb +1 -0
  66. data/vendored/puppet/lib/puppet/module/task.rb +198 -29
  67. data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  68. data/vendored/puppet/lib/puppet/network/format_support.rb +13 -8
  69. data/vendored/puppet/lib/puppet/network/formats.rb +93 -2
  70. data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +10 -3
  71. data/vendored/puppet/lib/puppet/node/facts.rb +11 -1
  72. data/vendored/puppet/lib/puppet/parser/catalog_compiler.rb +56 -0
  73. data/vendored/puppet/lib/puppet/parser/compiler.rb +3 -1
  74. data/vendored/puppet/lib/puppet/parser/functions.rb +3 -1
  75. data/vendored/puppet/lib/puppet/parser/functions/filter.rb +1 -1
  76. data/vendored/puppet/lib/puppet/parser/functions/generate.rb +1 -1
  77. data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +12 -1
  78. data/vendored/puppet/lib/puppet/parser/functions/tagged.rb +1 -4
  79. data/vendored/puppet/lib/puppet/parser/scope.rb +1 -1
  80. data/vendored/puppet/lib/puppet/parser/script_compiler.rb +7 -2
  81. data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  82. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_converter.rb +23 -4
  83. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +3 -4
  84. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +4 -0
  85. data/vendored/puppet/lib/puppet/pops/issues.rb +8 -0
  86. data/vendored/puppet/lib/puppet/pops/loader/loader.rb +2 -2
  87. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +3 -1
  88. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +30 -9
  89. data/vendored/puppet/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +62 -0
  90. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -1
  91. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +13 -70
  92. data/vendored/puppet/lib/puppet/pops/loaders.rb +19 -29
  93. data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +1 -1
  94. data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +4 -1
  95. data/vendored/puppet/lib/puppet/pops/pcore.rb +10 -33
  96. data/vendored/puppet/lib/puppet/pops/serialization.rb +2 -0
  97. data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +2 -1
  98. data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +11 -3
  99. data/vendored/puppet/lib/puppet/pops/serialization/to_stringified_converter.rb +226 -0
  100. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
  101. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +97 -47
  102. data/vendored/puppet/lib/puppet/pops/validation/validator_factory_4_0.rb +7 -8
  103. data/vendored/puppet/lib/puppet/property/keyvalue.rb +70 -8
  104. data/vendored/puppet/lib/puppet/provider/aix_object.rb +483 -0
  105. data/vendored/puppet/lib/puppet/provider/file/windows.rb +1 -1
  106. data/vendored/puppet/lib/puppet/provider/group/aix.rb +51 -112
  107. data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
  108. data/vendored/puppet/lib/puppet/provider/package/pip.rb +1 -1
  109. data/vendored/puppet/lib/puppet/provider/package/puppet_gem.rb +1 -1
  110. data/vendored/puppet/lib/puppet/provider/package/rpm.rb +1 -1
  111. data/vendored/puppet/lib/puppet/provider/package/windows/package.rb +1 -1
  112. data/vendored/puppet/lib/puppet/provider/package/zypper.rb +1 -1
  113. data/vendored/puppet/lib/puppet/provider/service/systemd.rb +1 -1
  114. data/vendored/puppet/lib/puppet/provider/service/windows.rb +37 -40
  115. data/vendored/puppet/lib/puppet/provider/user/aix.rb +142 -254
  116. data/vendored/puppet/lib/puppet/resource.rb +20 -3
  117. data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -12
  118. data/vendored/puppet/lib/puppet/rest/routes.rb +97 -34
  119. data/vendored/puppet/lib/puppet/settings.rb +1 -1
  120. data/vendored/puppet/lib/puppet/settings/file_setting.rb +1 -1
  121. data/vendored/puppet/lib/puppet/ssl/base.rb +1 -9
  122. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +1 -13
  123. data/vendored/puppet/lib/puppet/ssl/certificate_request_attributes.rb +1 -1
  124. data/vendored/puppet/lib/puppet/ssl/host.rb +114 -232
  125. data/vendored/puppet/lib/puppet/ssl/key.rb +1 -5
  126. data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
  127. data/vendored/puppet/lib/puppet/test/test_helper.rb +0 -4
  128. data/vendored/puppet/lib/puppet/transaction/event.rb +3 -7
  129. data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
  130. data/vendored/puppet/lib/puppet/type/exec.rb +18 -16
  131. data/vendored/puppet/lib/puppet/type/file.rb +3 -3
  132. data/vendored/puppet/lib/puppet/type/file/source.rb +20 -7
  133. data/vendored/puppet/lib/puppet/type/group.rb +3 -5
  134. data/vendored/puppet/lib/puppet/type/notify.rb +1 -1
  135. data/vendored/puppet/lib/puppet/type/package.rb +2 -5
  136. data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
  137. data/vendored/puppet/lib/puppet/type/service.rb +3 -6
  138. data/vendored/puppet/lib/puppet/type/tidy.rb +1 -1
  139. data/vendored/puppet/lib/puppet/type/user.rb +13 -20
  140. data/vendored/puppet/lib/puppet/util.rb +8 -9
  141. data/vendored/puppet/lib/puppet/util/execution.rb +3 -3
  142. data/vendored/puppet/lib/puppet/util/feature.rb +61 -39
  143. data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
  144. data/vendored/puppet/lib/puppet/util/rdoc.rb +1 -1
  145. data/vendored/puppet/lib/puppet/util/run_mode.rb +1 -1
  146. data/vendored/puppet/lib/puppet/util/storage.rb +1 -1
  147. data/vendored/puppet/lib/puppet/util/suidmanager.rb +7 -5
  148. data/vendored/puppet/lib/puppet/util/tag_set.rb +1 -1
  149. data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
  150. data/vendored/puppet/lib/puppet/util/windows.rb +18 -2
  151. data/vendored/puppet/lib/puppet/util/windows/adsi.rb +154 -205
  152. data/vendored/puppet/lib/puppet/util/windows/service.rb +770 -0
  153. data/vendored/puppet/lib/puppet/util/yaml.rb +41 -5
  154. data/vendored/puppet/lib/puppet/version.rb +1 -1
  155. data/vendored/puppet/lib/puppet_pal.rb +280 -24
  156. metadata +8 -38
  157. data/lib/bolt/catalog/compiler.rb +0 -48
  158. data/lib/bolt/catalog/loaders.rb +0 -19
  159. data/vendored/puppet/lib/puppet/application/ca.rb +0 -11
  160. data/vendored/puppet/lib/puppet/application/certificate.rb +0 -17
  161. data/vendored/puppet/lib/puppet/application/certificate_request.rb +0 -7
  162. data/vendored/puppet/lib/puppet/application/certificate_revocation_list.rb +0 -7
  163. data/vendored/puppet/lib/puppet/face/ca.rb +0 -266
  164. data/vendored/puppet/lib/puppet/face/certificate.rb +0 -167
  165. data/vendored/puppet/lib/puppet/face/certificate_request.rb +0 -56
  166. data/vendored/puppet/lib/puppet/face/certificate_revocation_list.rb +0 -56
  167. data/vendored/puppet/lib/puppet/graph/random_prioritizer.rb +0 -16
  168. data/vendored/puppet/lib/puppet/graph/title_hash_prioritizer.rb +0 -16
  169. data/vendored/puppet/lib/puppet/indirector/certificate/ca.rb +0 -9
  170. data/vendored/puppet/lib/puppet/indirector/certificate/disabled_ca.rb +0 -22
  171. data/vendored/puppet/lib/puppet/indirector/certificate_request/ca.rb +0 -22
  172. data/vendored/puppet/lib/puppet/indirector/certificate_request/disabled_ca.rb +0 -22
  173. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/ca.rb +0 -8
  174. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/disabled_ca.rb +0 -22
  175. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/file.rb +0 -8
  176. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/rest.rb +0 -11
  177. data/vendored/puppet/lib/puppet/indirector/certificate_status.rb +0 -4
  178. data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +0 -91
  179. data/vendored/puppet/lib/puppet/indirector/certificate_status/rest.rb +0 -11
  180. data/vendored/puppet/lib/puppet/indirector/key/ca.rb +0 -16
  181. data/vendored/puppet/lib/puppet/indirector/key/disabled_ca.rb +0 -22
  182. data/vendored/puppet/lib/puppet/indirector/ldap.rb +0 -86
  183. data/vendored/puppet/lib/puppet/indirector/node/ldap.rb +0 -275
  184. data/vendored/puppet/lib/puppet/provider/aixobject.rb +0 -392
  185. data/vendored/puppet/lib/puppet/provider/cron/crontab.rb +0 -297
  186. data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +0 -475
  187. data/vendored/puppet/lib/puppet/ssl/certificate_authority/autosign_command.rb +0 -45
  188. data/vendored/puppet/lib/puppet/ssl/certificate_authority/interface.rb +0 -324
  189. data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +0 -219
  190. data/vendored/puppet/lib/puppet/ssl/certificate_revocation_list.rb +0 -111
  191. data/vendored/puppet/lib/puppet/ssl/inventory.rb +0 -55
  192. data/vendored/puppet/lib/puppet/type/cron.rb +0 -480
@@ -61,12 +61,6 @@ module Bolt
61
61
  end
62
62
  private :parse
63
63
 
64
- def select_impl(task, additional_features = [])
65
- available_features = features + additional_features
66
- suitable_impl = task.implementations.find { |impl| Set.new(impl['requirements']).subset?(available_features) }
67
- return suitable_impl['path'] if suitable_impl
68
- end
69
-
70
64
  def features
71
65
  if @inventory
72
66
  @inventory.features(self)
@@ -1,23 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
+ # Represents a Task.
5
+ # @file and @files are mutually exclusive.
6
+ # @name [String] name of the task
7
+ # @file [Hash, nil] containing `filename` and `file_content`
8
+ # @files [Array<Hash>] where each entry includes `name` and `path`
9
+ # @metadata [Hash] task metadata
4
10
  Task = Struct.new(
5
11
  :name,
6
- :implementations,
7
- :input_method,
8
12
  :file,
13
+ :files,
9
14
  :metadata
10
15
  ) do
11
16
 
12
- TASK_DEFAULTS = {
13
- implementations: {},
14
- input_method: 'both',
15
- metadata: {}
16
- }.freeze
17
-
18
17
  def initialize(task)
19
- super()
20
- TASK_DEFAULTS.merge(task).each { |k, v| self[k] = v }
18
+ super(nil, nil, [], {})
19
+
20
+ task.reject { |k, _| k == 'parameters' }.each { |k, v| self[k] = v }
21
+ end
22
+
23
+ def description
24
+ metadata['description']
25
+ end
26
+
27
+ def parameters
28
+ metadata['parameters']
29
+ end
30
+
31
+ def supports_noop
32
+ metadata['supports_noop']
33
+ end
34
+
35
+ def file_map
36
+ @file_map ||= files.each_with_object({}) { |file, hsh| hsh[file['name']] = file['path'] }
37
+ end
38
+ private :file_map
39
+
40
+ # Returns a hash of implementation name, path to executable, input method (if defined),
41
+ # and any additional files (name and path)
42
+ def select_implementation(target, additional_features = [])
43
+ raise 'select_implementation only supported with multiple files' if files.nil? || files.empty?
44
+
45
+ impl = if (impls = metadata['implementations'])
46
+ available_features = target.features + additional_features
47
+ impl = impls.find { |imp| Set.new(imp['requirements']).subset?(available_features) }
48
+ raise "No suitable implementation of #{name} for #{target.name}" unless impl
49
+ impl = impl.dup
50
+ impl['path'] = file_map[impl['name']]
51
+ impl.delete('requirements')
52
+ impl
53
+ else
54
+ files.first.dup
55
+ end
56
+
57
+ inmethod = impl['input_method'] || metadata['input_method']
58
+ impl['input_method'] = inmethod unless inmethod.nil?
59
+
60
+ mfiles = impl.fetch('files', []) + metadata.fetch('files', [])
61
+ impl['files'] = mfiles.map { |file| { 'name' => file, 'path' => file_map[file] } } unless mfiles.empty?
62
+
63
+ impl
21
64
  end
22
65
  end
23
66
  end
@@ -162,12 +162,7 @@ module Bolt
162
162
  end
163
163
 
164
164
  def from_api?(task)
165
- if task.respond_to? :file
166
- unless task.file.nil?
167
- return true
168
- end
169
- end
170
- false
165
+ !task.file.nil?
171
166
  end
172
167
 
173
168
  # Transports should override this method with their own implementation of running a command.
@@ -31,9 +31,7 @@ module Bolt
31
31
  def in_tmpdir(base)
32
32
  args = base ? [nil, base] : []
33
33
  Dir.mktmpdir(*args) do |dir|
34
- Dir.chdir(dir) do
35
- yield dir
36
- end
34
+ yield dir
37
35
  end
38
36
  end
39
37
  private :in_tmpdir
@@ -49,7 +47,7 @@ module Bolt
49
47
  dest = File.join(dir, File.basename(script))
50
48
  copy_file(script, dest)
51
49
  File.chmod(0o750, dest)
52
- yield dest
50
+ yield dest, dir
53
51
  end
54
52
  end
55
53
  private :with_tmpscript
@@ -60,14 +58,14 @@ module Bolt
60
58
  end
61
59
 
62
60
  def run_command(target, command, _options = {})
63
- in_tmpdir(target.options['tmpdir']) do |_|
64
- output = @conn.execute(command, {})
61
+ in_tmpdir(target.options['tmpdir']) do |dir|
62
+ output = @conn.execute(command, dir: dir)
65
63
  Bolt::Result.for_command(target, output.stdout.string, output.stderr.string, output.exit_code)
66
64
  end
67
65
  end
68
66
 
69
67
  def run_script(target, script, arguments, _options = {})
70
- with_tmpscript(File.absolute_path(script), target.options['tmpdir']) do |file|
68
+ with_tmpscript(File.absolute_path(script), target.options['tmpdir']) do |file, dir|
71
69
  logger.debug "Running '#{file}' with #{arguments}"
72
70
 
73
71
  # unpack any Sensitive data AFTER we log
@@ -77,27 +75,27 @@ module Bolt
77
75
  # argument as the entire command string for script paths containing spaces.
78
76
  arguments = ['']
79
77
  end
80
- output = @conn.execute(file, *arguments, {})
78
+ output = @conn.execute(file, *arguments, dir: dir)
81
79
  Bolt::Result.for_command(target, output.stdout.string, output.stderr.string, output.exit_code)
82
80
  end
83
81
  end
84
82
 
85
83
  def run_task(target, task, arguments, _options = {})
86
- executable = target.select_impl(task, PROVIDED_FEATURES)
87
- raise "No suitable implementation of #{task.name} for #{target.name}" unless executable
84
+ implementation = task.select_implementation(target, PROVIDED_FEATURES)
85
+ executable = implementation['path']
86
+ input_method = implementation['input_method'] || 'both'
88
87
 
89
88
  # unpack any Sensitive data, write it to a separate variable because
90
89
  # we log 'arguments' below
91
90
  unwrapped_arguments = unwrap_sensitive_args(arguments)
92
- input_method = task.input_method || "both"
93
91
  stdin = STDIN_METHODS.include?(input_method) ? JSON.dump(unwrapped_arguments) : nil
94
92
  env = ENVIRONMENT_METHODS.include?(input_method) ? envify_params(unwrapped_arguments) : nil
95
93
 
96
- with_tmpscript(executable, target.options['tmpdir']) do |script|
94
+ with_tmpscript(executable, target.options['tmpdir']) do |script, dir|
97
95
  # log the arguments with sensitive data redacted, do NOT log unwrapped_arguments
98
96
  logger.debug("Running '#{script}' with #{arguments}")
99
97
 
100
- output = @conn.execute(script, stdin: stdin, env: env)
98
+ output = @conn.execute(script, stdin: stdin, env: env, dir: dir)
101
99
  Bolt::Result.for_task(target, output.stdout.string, output.stderr.string, output.exit_code)
102
100
  end
103
101
  end
@@ -11,9 +11,9 @@ module Bolt
11
11
  command = [options[:env]] + command if options[:env]
12
12
 
13
13
  if options[:stdin]
14
- stdout, stderr, rc = Open3.capture3(*command, stdin_data: options[:stdin])
14
+ stdout, stderr, rc = Open3.capture3(*command, stdin_data: options[:stdin], chdir: options[:dir])
15
15
  else
16
- stdout, stderr, rc = Open3.capture3(*command)
16
+ stdout, stderr, rc = Open3.capture3(*command, chdir: options[:dir])
17
17
  end
18
18
 
19
19
  result_output = Bolt::Node::Output.new
@@ -121,9 +121,19 @@ module Bolt
121
121
  end
122
122
 
123
123
  def run_task(target, task, arguments, options = {})
124
+ if from_api?(task)
125
+ executable = task.file['filename']
126
+ file_content = Base64.decode64(task.file['file_content'])
127
+ input_method = task.metadata['input_method']
128
+ else
129
+ implementation = task.select_implementation(target, PROVIDED_FEATURES)
130
+ executable = implementation['path']
131
+ input_method = implementation['input_method']
132
+ end
133
+ input_method ||= 'both'
134
+
124
135
  # unpack any Sensitive data
125
136
  arguments = unwrap_sensitive_args(arguments)
126
- input_method = task.input_method || "both"
127
137
  with_connection(target, options.fetch('_load_config', true)) do |conn|
128
138
  conn.running_as(options['_run_as']) do
129
139
  stdin, output = nil
@@ -140,17 +150,12 @@ module Bolt
140
150
  end
141
151
 
142
152
  conn.with_remote_tempdir do |dir|
143
- if from_api?(task)
144
- filename = task.file['filename']
145
- remote_task_path = conn.write_executable_from_content(dir,
146
- Base64.decode64(task.file['file_content']),
147
- filename)
148
- else
149
- executable = target.select_impl(task, PROVIDED_FEATURES)
150
- raise "No suitable implementation of #{task.name} for #{target.name}" unless executable
153
+ remote_task_path = if from_api?(task)
154
+ conn.write_executable_from_content(dir, file_content, executable)
155
+ else
156
+ conn.write_remote_executable(dir, executable)
157
+ end
151
158
 
152
- remote_task_path = conn.write_remote_executable(dir, executable)
153
- end
154
159
  if conn.run_as && stdin
155
160
  wrapper = make_wrapper_stringio(remote_task_path, stdin)
156
161
  remote_wrapper_path = conn.write_remote_executable(dir, wrapper, 'wrapper.sh')
@@ -108,19 +108,18 @@ catch
108
108
 
109
109
  def run_task(target, task, arguments, _options = {})
110
110
  if from_api?(task)
111
- task.input_method = powershell_file?(task["file"]["filename"]) ? 'powershell' : 'both'
112
- executable = { filename: task["file"]["filename"],
113
- file_content: StringIO.new(Base64.decode64(task.file['file_content'])) }
111
+ executable = task.file['filename']
112
+ file_content = StringIO.new(Base64.decode64(task.file['file_content']))
113
+ input_method = task.metadata['input_method']
114
114
  else
115
- executable = target.select_impl(task, PROVIDED_FEATURES)
116
- raise "No suitable implementation of #{task.name} for #{target.name}" unless executable
115
+ implementation = task.select_implementation(target, PROVIDED_FEATURES)
116
+ executable = implementation['path']
117
+ input_method = implementation['input_method']
117
118
  end
119
+ input_method ||= powershell_file?(executable) ? 'powershell' : 'both'
118
120
 
119
121
  # unpack any Sensitive data
120
122
  arguments = unwrap_sensitive_args(arguments)
121
-
122
- input_method = task.input_method
123
- input_method ||= powershell_file?(executable) ? 'powershell' : 'both'
124
123
  with_connection(target) do |conn|
125
124
  if STDIN_METHODS.include?(input_method)
126
125
  stdin = JSON.dump(arguments)
@@ -138,9 +137,7 @@ catch
138
137
 
139
138
  conn.with_remote_tempdir do |dir|
140
139
  remote_task_path = if from_api?(task)
141
- conn.write_executable_from_content(dir,
142
- executable[:file_content],
143
- executable[:filename])
140
+ conn.write_executable_from_content(dir, file_content, executable)
144
141
  else
145
142
  conn.write_remote_executable(dir, executable)
146
143
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '0.23.0'
4
+ VERSION = '0.24.0'
5
5
  end
@@ -4,11 +4,10 @@
4
4
  "title": "Task",
5
5
  "description": "Task schema for bolt-server",
6
6
  "type": "object",
7
- "description": "The task is a JSON object which includes the following keys",
8
7
  "properties": {
9
8
  "name": {
10
9
  "type": "string",
11
- "description": "Task name"
10
+ "description": "Task name"
12
11
  },
13
12
  "metadata": {
14
13
  "type": "object",
@@ -29,11 +28,19 @@
29
28
  "type": {
30
29
  "type": "string",
31
30
  "description": "The type the parameter should accept"
31
+ },
32
+ "sensitive": {
33
+ "description": "Whether the task runner should treat the parameter value as sensitive",
34
+ "type": "boolean"
32
35
  }
33
36
  }
37
+ },
38
+ "input_method": {
39
+ "type": "string",
40
+ "enum": ["stdin", "environment", "powershell"],
41
+ "description": "What input method should be used to pass params to the task"
34
42
  }
35
- },
36
- "additionalProperties": false
43
+ }
37
44
  },
38
45
  "file": {
39
46
  "type": "object",
@@ -54,4 +61,4 @@
54
61
  },
55
62
  "required": ["name", "file"],
56
63
  "additionalProperties": false
57
- }
64
+ }
@@ -66,7 +66,9 @@ begin
66
66
  Puppet::Transaction::Report.new('apply')
67
67
  end
68
68
 
69
- Puppet.override(current_environment: env, loaders: Puppet::Pops::Loaders.new(env)) do
69
+ Puppet.override(current_environment: env,
70
+ environments: Puppet::Environments::Static.new(env),
71
+ loaders: Puppet::Pops::Loaders.new(env)) do
70
72
  catalog = Puppet::Resource::Catalog.from_data_hash(args['catalog']).to_ral
71
73
  catalog.environment = env.name.to_s
72
74
  catalog.environment_instance = env
@@ -42,6 +42,10 @@ elsif command == "compile"
42
42
  JSON.parse(STDIN.read)
43
43
  end
44
44
  catalog = Bolt::Catalog.new.compile_catalog(request)
45
+ # This seems to be a string in ruby 2.3
46
+ if catalog.is_a?(String)
47
+ catalog = JSON.parse(catalog)
48
+ end
45
49
  puts JSON.pretty_generate(catalog)
46
50
  else
47
51
  puts "USAGE: run 'bolt_catalog compile' with a request on STDIN " \
@@ -208,7 +208,8 @@ module Puppet
208
208
  Puppet::Network::HTTP::NoCachePool.new
209
209
  },
210
210
  :ssl_host => proc { Puppet::SSL::Host.localhost },
211
- :plugins => proc { Puppet::Plugins::Configuration.load_plugins }
211
+ :plugins => proc { Puppet::Plugins::Configuration.load_plugins },
212
+ :rich_data => false
212
213
  }
213
214
  end
214
215
 
@@ -426,12 +426,8 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
426
426
  Puppet::Resource::Catalog.indirection.cache_class = Puppet[:catalog_cache_terminus]
427
427
  end
428
428
 
429
- if options[:fingerprint]
430
- # in fingerprint mode we just need
431
- # access to the local files and we don't need a ca
432
- Puppet::SSL::Host.ca_location = :none
433
- else
434
- Puppet::SSL::Host.ca_location = :remote
429
+ # In fingerprint mode we don't need to set up the whole agent
430
+ unless options[:fingerprint]
435
431
  setup_agent
436
432
  end
437
433
  end
@@ -173,6 +173,11 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
173
173
  else
174
174
  main
175
175
  end
176
+ ensure
177
+ if @profiler
178
+ Puppet::Util::Profiler.remove_profiler(@profiler)
179
+ @profiler.shutdown
180
+ end
176
181
  end
177
182
 
178
183
  def apply
@@ -189,53 +194,15 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
189
194
  end
190
195
 
191
196
  def main
192
- # Set our code or file to use.
193
- if options[:code] or command_line.args.length == 0
194
- Puppet[:code] = options[:code] || STDIN.read
195
- else
196
- manifest = command_line.args.shift
197
- raise _("Could not find file %{manifest}") % { manifest: manifest } unless Puppet::FileSystem.exist?(manifest)
198
- Puppet.warning(_("Only one file can be applied per run. Skipping %{files}") % { files: command_line.args.join(', ') }) if command_line.args.size > 0
199
- end
200
-
201
- # splay if needed
202
- splay
197
+ manifest = get_manifest() # Get either a manifest or nil if apply should use content of Puppet[:code]
198
+ splay # splay if needed
199
+ facts = get_facts() # facts or nil
200
+ node = get_node() # node or error
201
+ apply_environment = get_configured_environment(node, manifest)
203
202
 
204
- unless Puppet[:node_name_fact].empty?
205
- # Collect our facts.
206
- unless facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
207
- raise _("Could not find facts for %{node}") % { node: Puppet[:node_name_value] }
208
- end
209
-
210
- Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
211
- facts.name = Puppet[:node_name_value]
212
- end
213
-
214
- # Find our Node
215
- unless node = Puppet::Node.indirection.find(Puppet[:node_name_value])
216
- raise _("Could not find node %{node}") % { node: Puppet[:node_name_value] }
217
- end
218
-
219
- configured_environment = node.environment || Puppet.lookup(:current_environment)
220
-
221
- apply_environment = manifest ?
222
- configured_environment.override_with(:manifest => manifest) :
223
- configured_environment
224
-
225
- # Modify the node descriptor to use the special apply_environment.
226
- # It is based on the actual environment from the node, or the locally
227
- # configured environment if the node does not specify one.
228
- # If a manifest file is passed on the command line, it overrides
229
- # the :manifest setting of the apply_environment.
230
- node.environment = apply_environment
231
-
232
- #TRANSLATORS "puppet apply" is a program command and should not be translated
203
+ # TRANSLATORS "puppet apply" is a program command and should not be translated
233
204
  Puppet.override({:current_environment => apply_environment}, _("For puppet apply")) do
234
- # Merge in the facts.
235
- node.merge(facts.values) if facts
236
-
237
- # Add server facts so $server_facts[environment] exists when doing a puppet apply
238
- node.add_server_facts({})
205
+ configure_node_facts(node, facts)
239
206
 
240
207
  # Allow users to load the classes that puppet agent creates.
241
208
  if options[:loadclasses]
@@ -273,7 +240,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
273
240
  exit_status = Puppet.override(:loaders => Puppet::Pops::Loaders.new(apply_environment)) do
274
241
 
275
242
  # Resolve all deferred values and replace them / mutate the catalog
276
- Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node, node.facts, catalog)
243
+ Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog)
277
244
 
278
245
  # Translate it to a RAL catalog
279
246
  catalog = catalog.to_ral
@@ -287,7 +254,6 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
287
254
  catalog.write_resource_file
288
255
  end
289
256
 
290
- #exit_status = Puppet.override(:loaders => Puppet::Pops::Loaders.new(apply_environment)) { apply_catalog(catalog) }
291
257
  apply_catalog(catalog)
292
258
  end
293
259
  if not exit_status
@@ -302,12 +268,6 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
302
268
  exit(1)
303
269
  end
304
270
  end
305
-
306
- ensure
307
- if @profiler
308
- Puppet::Util::Profiler.remove_profiler(@profiler)
309
- @profiler.shutdown
310
- end
311
271
  end
312
272
 
313
273
  # Enable all of the most common test options.
@@ -350,18 +310,98 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
350
310
  private
351
311
 
352
312
  def read_catalog(text)
353
- format = Puppet::Resource::Catalog.default_format
354
- begin
355
- catalog = Puppet::Resource::Catalog.convert_from(format, text)
356
- rescue => detail
357
- raise Puppet::Error, _("Could not deserialize catalog from %{format}: %{detail}") % { format: format, detail: detail }, detail.backtrace
358
- end
313
+ facts = get_facts()
314
+ node = get_node()
315
+ configured_environment = get_configured_environment(node)
316
+
317
+ # TRANSLATORS "puppet apply" is a program command and should not be translated
318
+ Puppet.override({:current_environment => configured_environment}, _("For puppet apply")) do
319
+ configure_node_facts(node, facts)
320
+
321
+ # NOTE: Does not set rich_data = true automatically (which would ensure always reading catalog with rich data
322
+ # on (seemingly the right thing to do)), but that would remove the ability to test what happens when a
323
+ # rich catalog is processed without rich_data being turned on.
324
+ format = Puppet::Resource::Catalog.default_format
325
+ begin
326
+ catalog = Puppet::Resource::Catalog.convert_from(format, text)
327
+ rescue => detail
328
+ raise Puppet::Error, _("Could not deserialize catalog from %{format}: %{detail}") % { format: format, detail: detail }, detail.backtrace
329
+ end
330
+ # Resolve all deferred values and replace them / mutate the catalog
331
+ Puppet::Pops::Evaluator::DeferredResolver.resolve_and_replace(node.facts, catalog)
359
332
 
360
- catalog.to_ral
333
+ catalog.to_ral
334
+ end
361
335
  end
362
336
 
363
337
  def apply_catalog(catalog)
364
338
  configurer = Puppet::Configurer.new
365
339
  configurer.run(:catalog => catalog, :pluginsync => false)
366
340
  end
341
+
342
+ # Returns facts or nil
343
+ #
344
+ def get_facts()
345
+ facts = nil
346
+ unless Puppet[:node_name_fact].empty?
347
+ # Collect our facts.
348
+ unless facts = Puppet::Node::Facts.indirection.find(Puppet[:node_name_value])
349
+ raise _("Could not find facts for %{node}") % { node: Puppet[:node_name_value] }
350
+ end
351
+
352
+ Puppet[:node_name_value] = facts.values[Puppet[:node_name_fact]]
353
+ facts.name = Puppet[:node_name_value]
354
+ end
355
+ facts
356
+ end
357
+
358
+ # Returns the node or raises and error if node not found.
359
+ #
360
+ def get_node()
361
+ node = Puppet::Node.indirection.find(Puppet[:node_name_value])
362
+ raise _("Could not find node %{node}") % { node: Puppet[:node_name_value] } unless node
363
+ node
364
+ end
365
+
366
+ # Returns either a manifest (filename) or nil if apply should use content of Puppet[:code]
367
+ #
368
+ def get_manifest()
369
+ manifest = nil
370
+ # Set our code or file to use.
371
+ if options[:code] or command_line.args.length == 0
372
+ Puppet[:code] = options[:code] || STDIN.read
373
+ else
374
+ manifest = command_line.args.shift
375
+ raise _("Could not find file %{manifest}") % { manifest: manifest } unless Puppet::FileSystem.exist?(manifest)
376
+ Puppet.warning(_("Only one file can be applied per run. Skipping %{files}") % { files: command_line.args.join(', ') }) if command_line.args.size > 0
377
+ end
378
+ manifest
379
+ end
380
+
381
+ # Returns a configured environment, if a manifest is given it overrides what is configured for the environment
382
+ # specified by the node (or the current_environment found in the Puppet context).
383
+ # The node's resolved environment is modified if needed.
384
+ #
385
+ def get_configured_environment(node, manifest = nil)
386
+ configured_environment = node.environment || Puppet.lookup(:current_environment)
387
+
388
+ apply_environment = manifest ?
389
+ configured_environment.override_with(:manifest => manifest) :
390
+ configured_environment
391
+
392
+ # Modify the node descriptor to use the special apply_environment.
393
+ # It is based on the actual environment from the node, or the locally
394
+ # configured environment if the node does not specify one.
395
+ # If a manifest file is passed on the command line, it overrides
396
+ # the :manifest setting of the apply_environment.
397
+ node.environment = apply_environment
398
+ apply_environment
399
+ end
400
+
401
+ # Mixes the facts into the node, and mixes in server facts
402
+ def configure_node_facts(node, facts)
403
+ node.merge(facts.values) if facts
404
+ # Add server facts so $server_facts[environment] exists when doing a puppet apply
405
+ node.add_server_facts({})
406
+ end
367
407
  end