octocatalog-diff 1.5.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/.version +1 -1
  3. data/README.md +4 -4
  4. data/doc/CHANGELOG.md +49 -0
  5. data/doc/advanced-filter.md +23 -0
  6. data/doc/advanced-ignores.md +10 -0
  7. data/doc/advanced-puppet-master.md +23 -5
  8. data/doc/configuration-puppetdb.md +11 -0
  9. data/doc/dev/api/v1/calls/catalog-diff.md +6 -2
  10. data/doc/dev/api/v1/objects/diff.md +3 -3
  11. data/doc/dev/releasing.md +1 -1
  12. data/doc/limitations.md +9 -9
  13. data/doc/optionsref.md +167 -11
  14. data/doc/requirements.md +6 -2
  15. data/lib/octocatalog-diff/catalog-diff/differ.rb +29 -4
  16. data/lib/octocatalog-diff/catalog-diff/filter.rb +2 -1
  17. data/lib/octocatalog-diff/catalog-diff/filter/compilation_dir.rb +29 -25
  18. data/lib/octocatalog-diff/catalog-diff/filter/single_item_array.rb +44 -0
  19. data/lib/octocatalog-diff/catalog-util/builddir.rb +3 -3
  20. data/lib/octocatalog-diff/catalog-util/command.rb +25 -3
  21. data/lib/octocatalog-diff/catalog-util/fileresources.rb +1 -1
  22. data/lib/octocatalog-diff/catalog.rb +22 -4
  23. data/lib/octocatalog-diff/catalog/computed.rb +2 -1
  24. data/lib/octocatalog-diff/catalog/puppetmaster.rb +43 -5
  25. data/lib/octocatalog-diff/cli.rb +36 -5
  26. data/lib/octocatalog-diff/cli/options.rb +39 -3
  27. data/lib/octocatalog-diff/cli/options/hostname.rb +13 -2
  28. data/lib/octocatalog-diff/cli/options/pe_enc_token_file.rb +1 -1
  29. data/lib/octocatalog-diff/cli/options/puppet_master_api_version.rb +2 -2
  30. data/lib/octocatalog-diff/cli/options/puppet_master_token.rb +20 -0
  31. data/lib/octocatalog-diff/cli/options/puppet_master_token_file.rb +35 -0
  32. data/lib/octocatalog-diff/cli/options/puppet_master_update_catalog.rb +20 -0
  33. data/lib/octocatalog-diff/cli/options/puppet_master_update_facts.rb +20 -0
  34. data/lib/octocatalog-diff/cli/options/puppetdb_package_inventory.rb +18 -0
  35. data/lib/octocatalog-diff/cli/options/puppetdb_token.rb +17 -0
  36. data/lib/octocatalog-diff/cli/options/puppetdb_token_file.rb +21 -0
  37. data/lib/octocatalog-diff/facts/puppetdb.rb +43 -2
  38. data/lib/octocatalog-diff/puppetdb.rb +5 -1
  39. data/lib/octocatalog-diff/util/parallel.rb +20 -16
  40. data/lib/octocatalog-diff/util/util.rb +2 -0
  41. data/scripts/env/env.sh +1 -1
  42. data/scripts/git-extract/git-extract.sh +1 -1
  43. data/scripts/puppet/puppet.sh +1 -1
  44. metadata +37 -30
@@ -2,10 +2,14 @@
2
2
 
3
3
  To run `octocatalog-diff` you will need these basics:
4
4
 
5
- - Ruby 2.0 through 2.4 (we test octocatalog-diff with Ruby 2.0, 2.1, 2.2, 2.3, and 2.4)
5
+ - An appropriate Puppet version and [corresponding ruby version](https://puppet.com/docs/puppet/5.4/system_requirements.html)
6
+ - Puppet 5.x officially supports Ruby 2.4
7
+ - Puppet 4.x officially supports Ruby 2.1, but seems to work fine with later versions as well
8
+ - Puppet 3.8.7 -- we attempt to maintain compatibility in `octocatalog-diff` to facilitate upgrades even though this version is no longer supported by Puppet
9
+ - We don't officially support Puppet 3.8.6 or before
6
10
  - Mac OS, Linux, or other Unix-line operating system (Windows is not supported)
7
11
  - Ability to install gems, e.g. with [rbenv](https://github.com/rbenv/rbenv) or [rvm](https://rvm.io/), or root privileges to install into the system Ruby
8
- - Puppet agent for [Linux](https://docs.puppet.com/puppet/latest/reference/install_linux.html) or [Mac OS X](https://docs.puppet.com/puppet/latest/reference/install_osx.html), or installed as a gem (we support Puppet 3.8.7 and all versions of Puppet 4.x)
12
+ - Puppet agent for [Linux](https://docs.puppet.com/puppet/latest/reference/install_linux.html) or [Mac OS X](https://docs.puppet.com/puppet/latest/reference/install_osx.html), or installed as a gem
9
13
 
10
14
  We recommend that you also have the following to get the most out of `octocatalog-diff`, but these are not absolute requirements:
11
15
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'diffy'
4
+ require 'digest'
4
5
  require 'hashdiff'
5
6
  require 'json'
6
7
  require 'set'
@@ -11,6 +12,8 @@ require_relative '../errors'
11
12
  require_relative '../util/util'
12
13
  require_relative 'filter'
13
14
 
15
+ HashDiff = Hashdiff unless defined? HashDiff
16
+
14
17
  module OctocatalogDiff
15
18
  module CatalogDiff
16
19
  # Calculate the difference between two Puppet catalogs.
@@ -263,7 +266,7 @@ module OctocatalogDiff
263
266
 
264
267
  # Handle parameters
265
268
  if k == 'parameters'
266
- cleansed_param = cleanse_parameters_hash(v)
269
+ cleansed_param = cleanse_parameters_hash(v, resource.fetch('sensitive_parameters', []))
267
270
  hsh[k] = cleansed_param unless cleansed_param.nil? || cleansed_param.empty?
268
271
  elsif k == 'tags'
269
272
  # The order of tags is unimportant. Sort this array to avoid false diffs if order changes.
@@ -294,10 +297,13 @@ module OctocatalogDiff
294
297
  # Use diffy to get only the lines that have changed in a text object.
295
298
  # As we iterate through the diff, jump out if we have our answer: either
296
299
  # true if '=~>' finds ANY match, or false if '=&>' fails to find a match.
297
- Diffy::Diff.new(old_val, new_val, context: 0).each do |line|
300
+ diffy_result = Diffy::Diff.new(old_val, new_val, context: 0)
301
+ newline_alerts = diffy_result.count { |line| line.strip == '\' }
302
+ diffy_result.each do |line|
298
303
  if regex.match(line.strip)
299
304
  return true if operator == '=~>'
300
305
  elsif operator == '=&>'
306
+ next if line.strip == '\' && newline_alerts == 2
301
307
  return false
302
308
  end
303
309
  end
@@ -334,7 +340,8 @@ module OctocatalogDiff
334
340
  # =-> Attribute must have been removed and equal this
335
341
  # =~> Change must match regexp (one line of change matching is sufficient)
336
342
  # =&> Change must match regexp (all lines of change MUST match regexp)
337
- if rule_attr =~ /\A(.+?)(=[\-\+~&]?>)(.+)/m
343
+ # =s> Change must be array and contain identical elements, ignoring order
344
+ if rule_attr =~ /\A(.+?)(=[\-\+~&s]?>)(.+)/m
338
345
  rule_attr = Regexp.last_match(1)
339
346
  operator = Regexp.last_match(2)
340
347
  value = Regexp.last_match(3)
@@ -355,6 +362,9 @@ module OctocatalogDiff
355
362
  raise RegexpError, "Invalid ignore regexp for #{key}: #{exc.message}"
356
363
  end
357
364
  matcher = ->(x, y) { regexp_operator_match?(operator, my_regex, x, y) }
365
+ elsif operator == '=s>'
366
+ raise ArgumentError, "Invalid ignore option for =s>, must be '='" unless value == '='
367
+ matcher = ->(x, y) { x.is_a?(Array) && y.is_a?(Array) && Set.new(x) == Set.new(y) }
358
368
  end
359
369
  end
360
370
 
@@ -394,6 +404,13 @@ module OctocatalogDiff
394
404
  return false unless rule[:title].casecmp(hsh[:title]).zero?
395
405
  end
396
406
 
407
+ # If rule[:attr] is a regular expression, handle that case here.
408
+ if rule[:attr].is_a?(Regexp)
409
+ return false unless hsh[:attr].is_a?(String)
410
+ return false unless rule[:attr].match(hsh[:attr])
411
+ return ignore_match_true(hsh, rule)
412
+ end
413
+
397
414
  # Special 'attributes': Ignore specific diff types (+ add, - remove, ~ and ! change)
398
415
  if rule[:attr] =~ /\A[\-\+~!]+\Z/
399
416
  return ignore_match_true(hsh, rule) if rule[:attr].include?(diff_type)
@@ -446,10 +463,18 @@ module OctocatalogDiff
446
463
 
447
464
  # Cleanse parameters of filtered attributes.
448
465
  # @param parameters_hash [Hash] Hash of parameters
466
+ # @param sensitive_parameters [Array] Array of sensitive parameters
449
467
  # @return [Hash] Cleaned parameters hash (original input hash is not altered)
450
- def cleanse_parameters_hash(parameters_hash)
468
+ def cleanse_parameters_hash(parameters_hash, sensitive_parameters)
451
469
  result = parameters_hash.dup
452
470
 
471
+ # hides sensitive params. We still need to know if there's a going to
472
+ # be a diff, so we hash the value.
473
+ sensitive_parameters.each do |p|
474
+ md5 = Digest::MD5.hexdigest Marshal.dump(result[p])
475
+ result[p] = 'Sensitive [md5sum ' + md5 + ']'
476
+ end
477
+
453
478
  # 'before' and 'require' handle internal Puppet ordering but do not affect what
454
479
  # happens on the target machine. Don't consider these for the purpose of catalog diff.
455
480
  result.delete('before')
@@ -2,6 +2,7 @@ require_relative '../api/v1/diff'
2
2
  require_relative 'filter/absent_file'
3
3
  require_relative 'filter/compilation_dir'
4
4
  require_relative 'filter/json'
5
+ require_relative 'filter/single_item_array'
5
6
  require_relative 'filter/yaml'
6
7
 
7
8
  require 'stringio'
@@ -13,7 +14,7 @@ module OctocatalogDiff
13
14
  attr_accessor :logger
14
15
 
15
16
  # List the available filters here (by class name) for use in the validator method.
16
- AVAILABLE_FILTERS = %w(AbsentFile CompilationDir JSON YAML).freeze
17
+ AVAILABLE_FILTERS = %w(AbsentFile CompilationDir JSON SingleItemArray YAML).freeze
17
18
 
18
19
  # Public: Determine whether a particular filter exists. This can be used to validate
19
20
  # a user-submitted filter.
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../filter'
4
+ require_relative '../../util/util'
4
5
 
5
6
  module OctocatalogDiff
6
7
  module CatalogDiff
@@ -35,43 +36,46 @@ module OctocatalogDiff
35
36
 
36
37
  # Check for a change where the difference in a parameter exactly corresponds to the difference in the
37
38
  # compilation directory.
38
- if diff.change? && (diff.old_value.is_a?(String) || diff.new_value.is_a?(String))
39
- from_before = nil
40
- from_after = nil
41
- from_match = false
42
- to_before = nil
43
- to_after = nil
44
- to_match = false
39
+ if diff.change?
40
+ o = remove_compilation_dir(diff.old_value, dir2)
41
+ n = remove_compilation_dir(diff.new_value, dir1)
45
42
 
46
- if diff.old_value =~ /^(.*)#{dir2}(.*)$/m
47
- from_before = Regexp.last_match(1) || ''
48
- from_after = Regexp.last_match(2) || ''
49
- from_match = true
50
- end
51
-
52
- if diff.new_value =~ /^(.*)#{dir1}(.*)$/m
53
- to_before = Regexp.last_match(1) || ''
54
- to_after = Regexp.last_match(2) || ''
55
- to_match = true
56
- end
57
-
58
- if from_match && to_match && to_before == from_before && to_after == from_after
43
+ if o != diff.old_value || n != diff.new_value
59
44
  message = "Resource key #{diff.type}[#{diff.title}] #{diff.structure.join(' => ')}"
60
- message += ' appears to depend on catalog compilation directory. Suppressed from results.'
45
+ message += ' may depend on catalog compilation directory, but there may be differences.'
46
+ message += ' This is included in results for now, but please verify.'
61
47
  @logger.warn message
62
- return true
63
48
  end
64
49
 
65
- if from_match || to_match
50
+ if o == n
66
51
  message = "Resource key #{diff.type}[#{diff.title}] #{diff.structure.join(' => ')}"
67
- message += ' may depend on catalog compilation directory, but there may be differences.'
68
- message += ' This is included in results for now, but please verify.'
52
+ message += ' appears to depend on catalog compilation directory. Suppressed from results.'
69
53
  @logger.warn message
54
+ return true
70
55
  end
71
56
  end
72
57
 
73
58
  false
74
59
  end
60
+
61
+ def remove_compilation_dir(v, dir)
62
+ value = OctocatalogDiff::Util::Util.deep_dup(v)
63
+ traverse(value) do |e|
64
+ e.gsub!(dir, '') if e.respond_to?(:gsub!)
65
+ end
66
+ value
67
+ end
68
+
69
+ def traverse(a)
70
+ case a
71
+ when Array
72
+ a.map { |v| traverse(v, &Proc.new) }
73
+ when Hash
74
+ traverse(a.values, &Proc.new)
75
+ else
76
+ yield a
77
+ end
78
+ end
75
79
  end
76
80
  end
77
81
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../filter'
4
+
5
+ module OctocatalogDiff
6
+ module CatalogDiff
7
+ class Filter
8
+ # Filter out changes in parameters when one catalog has a parameter that's an object and
9
+ # the other catalog has that same parameter as an array containing the same object.
10
+ # For example, under this filter, the following is not a change:
11
+ # catalog1: notify => "Service[foo]"
12
+ # catalog2: notify => ["Service[foo]"]
13
+ class SingleItemArray < OctocatalogDiff::CatalogDiff::Filter
14
+ # Public: Implement the filter for single-item arrays whose item exactly matches the
15
+ # item that's not in an array in the other catalog.
16
+ #
17
+ # @param diff [OctocatalogDiff::API::V1::Diff] Difference
18
+ # @param _options [Hash] Additional options (there are none for this filter)
19
+ # @return [Boolean] true if this should be filtered out, false otherwise
20
+ def filtered?(diff, _options = {})
21
+ # Skip additions or removals - focus only on changes
22
+ return false unless diff.change?
23
+ old_value = diff.old_value
24
+ new_value = diff.new_value
25
+
26
+ # Skip unless there is a single-item array under consideration
27
+ return false unless
28
+ (old_value.is_a?(Array) && old_value.size == 1) ||
29
+ (new_value.is_a?(Array) && new_value.size == 1)
30
+
31
+ # Skip if both the old value and new value are arrays
32
+ return false if old_value.is_a?(Array) && new_value.is_a?(Array)
33
+
34
+ # Do comparison
35
+ if old_value.is_a?(Array)
36
+ old_value.first == new_value
37
+ else
38
+ new_value.first == old_value
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -149,13 +149,13 @@ module OctocatalogDiff
149
149
  raise ArgumentError, 'Called install_fact_file without node, or with an empty node'
150
150
  end
151
151
 
152
- facts = if options[:fact_file]
152
+ facts = if options[:facts].is_a?(OctocatalogDiff::Facts)
153
+ options[:facts].dup
154
+ elsif options[:fact_file]
153
155
  raise Errno::ENOENT, "Fact file #{options[:fact_file]} does not exist" unless File.file?(options[:fact_file])
154
156
  fact_file_opts = { fact_file_string: File.read(options[:fact_file]) }
155
157
  fact_file_opts[:backend] = Regexp.last_match(1).to_sym if options[:fact_file] =~ /.*\.(\w+)$/
156
158
  OctocatalogDiff::Facts.new(fact_file_opts)
157
- elsif options[:facts].is_a?(OctocatalogDiff::Facts)
158
- options[:facts].dup
159
159
  else
160
160
  raise ArgumentError, 'No facts passed to "install_fact_file" method'
161
161
  end
@@ -54,9 +54,21 @@ module OctocatalogDiff
54
54
  raise ArgumentError, 'Puppet binary was not supplied' if @puppet_binary.nil?
55
55
  raise Errno::ENOENT, "Puppet binary #{@puppet_binary} doesn't exist" unless File.file?(@puppet_binary)
56
56
 
57
+ puppet_version = Gem::Version.new(@options[:puppet_version])
58
+
57
59
  # Node to compile
58
60
  cmdline = []
59
- cmdline.concat ['master', '--compile', Shellwords.escape(@node)]
61
+ # The 'puppet master --compile' command was removed in Puppet 6.x and replaced in
62
+ # Puppet 6.5 with an identically functioning 'puppet catalog compile' command.
63
+ # From versions 6.0.0 until 6.5.0 there is no compatible invocation method.
64
+ if puppet_version < Gem::Version.new('6.0.0')
65
+ cmdline.concat ['master', '--compile', Shellwords.escape(@node)]
66
+ elsif puppet_version < Gem::Version.new('6.5.0')
67
+ raise OctocatalogDiff::Errors::PuppetVersionError,
68
+ 'Octocatalog-diff does not support Puppet versions >= 6.0.0 and < 6.5.0'
69
+ else
70
+ cmdline.concat ['catalog', 'compile', Shellwords.escape(@node)]
71
+ end
60
72
 
61
73
  # storeconfigs?
62
74
  if @options[:storeconfigs]
@@ -93,11 +105,21 @@ module OctocatalogDiff
93
105
  # Some typical options for puppet
94
106
  cmdline.concat %w(
95
107
  --no-daemonize
96
- --no-ca
97
108
  --color=false
98
- --config_version="/bin/echo catalogscript"
99
109
  )
100
110
 
111
+ if puppet_version < Gem::Version.new('6.0.0')
112
+ # This config_version parameter causes an error when run with Puppet 6.x. Per
113
+ # the Puppet configuration settings docs, the below config_version argument
114
+ # may not actually be valid, but for backward compatibility's sake we'll keep it
115
+ # for the versions it has always worked with:
116
+ cmdline.concat ['--config_version="/bin/echo catalogscript"']
117
+
118
+ # The 'ca' configuration option was removed in Puppet 6, but we'll keep it
119
+ # for older versions:
120
+ cmdline.concat ['--no-ca']
121
+ end
122
+
101
123
  # Add environment - only make this variable if preserve_environments is used.
102
124
  # If preserve_environments is not used, the hard-coded 'production' here matches
103
125
  # up with the symlink created under the temporary directory structure.
@@ -59,7 +59,7 @@ module OctocatalogDiff
59
59
  result = []
60
60
  Regexp.last_match(1).split(/:/).map(&:strip).each do |path|
61
61
  next if path.start_with?('$')
62
- result << File.expand_path(path, dir)
62
+ result.concat(Dir.glob(File.expand_path(path, dir)))
63
63
  end
64
64
  result
65
65
  else
@@ -191,6 +191,8 @@ module OctocatalogDiff
191
191
  build
192
192
  raise OctocatalogDiff::Errors::CatalogError, 'Catalog does not appear to have been built' if !valid? && error_message.nil?
193
193
  raise OctocatalogDiff::Errors::CatalogError, error_message unless valid?
194
+ # Handle the structure returned by the /puppet/v4/catalog Puppetserver endpoint:
195
+ return @catalog['catalog']['resources'] if @catalog['catalog'].is_a?(Hash) && @catalog['catalog']['resources'].is_a?(Array)
194
196
  return @catalog['data']['resources'] if @catalog['data'].is_a?(Hash) && @catalog['data']['resources'].is_a?(Array)
195
197
  return @catalog['resources'] if @catalog['resources'].is_a?(Array)
196
198
  # This is a bug condition
@@ -304,20 +306,36 @@ module OctocatalogDiff
304
306
  unless res =~ /\A([\w:]+)\[(.+)\]\z/
305
307
  raise ArgumentError, "Resource #{res} is not in the expected format"
306
308
  end
307
- resource(type: Regexp.last_match(1), title: Regexp.last_match(2)).nil?
309
+
310
+ type = Regexp.last_match(1)
311
+ title = normalized_title(Regexp.last_match(2), type)
312
+ resource(type: type, title: title).nil?
308
313
  end
309
314
  end
310
315
 
316
+ # Private method: Given a title string, normalize it according to the rules
317
+ # used by puppet 4.10.x for file resource title normalization:
318
+ # https://github.com/puppetlabs/puppet/blob/4.10.x/lib/puppet/type/file.rb#L42
319
+ def normalized_title(title_string, type)
320
+ return title_string if type != 'File'
321
+
322
+ matches = title_string.match(%r{^(?<normalized_path>/|.+:/|.*[^/])/*\Z}m)
323
+ matches[:normalized_path] || title_string
324
+ end
325
+
311
326
  # Private method: Build the resource hash to be used used for O(1) lookups by type and title.
312
327
  # This method is called the first time the resource hash is accessed.
313
328
  def build_resource_hash
314
329
  @resource_hash = {}
315
330
  resources.each do |resource|
316
331
  @resource_hash[resource['type']] ||= {}
317
- @resource_hash[resource['type']][resource['title']] = resource
318
332
 
319
- if resource.key?('parameters') && resource['parameters'].key?('alias')
320
- @resource_hash[resource['type']][resource['parameters']['alias']] = resource
333
+ title = normalized_title(resource['title'], resource['type'])
334
+ @resource_hash[resource['type']][title] = resource
335
+
336
+ if resource.key?('parameters')
337
+ @resource_hash[resource['type']][resource['parameters']['alias']] = resource if resource['parameters'].key?('alias')
338
+ @resource_hash[resource['type']][resource['parameters']['name']] = resource if resource['parameters'].key?('name')
321
339
  end
322
340
  end
323
341
  end
@@ -147,7 +147,8 @@ module OctocatalogDiff
147
147
  puppet_binary: @puppet_binary,
148
148
  fact_file: @builddir.fact_file,
149
149
  dir: @builddir.tempdir,
150
- enc: @builddir.enc
150
+ enc: @builddir.enc,
151
+ puppet_version: puppet_version
151
152
  )
152
153
  OctocatalogDiff::CatalogUtil::Command.new(command_opts)
153
154
  end
@@ -62,16 +62,19 @@ module OctocatalogDiff
62
62
  fetch_catalog(logger)
63
63
  end
64
64
 
65
- # Returns a hash of parameters for each supported version of the Puppet Server Catalog API.
65
+ # Returns a hash of parameters for the requested version of the Puppet Server Catalog API.
66
66
  # @return [Hash] Hash of parameters
67
67
  #
68
68
  # Note: The double escaping of the facts here is implemented to correspond to a long standing
69
69
  # bug in the Puppet code. See https://github.com/puppetlabs/puppet/pull/1818 and
70
70
  # https://docs.puppet.com/puppet/latest/http_api/http_catalog.html#parameters for explanation.
71
- def puppet_catalog_api
72
- {
71
+ def puppet_catalog_api(version)
72
+ api_style = {
73
73
  2 => {
74
74
  url: "https://#{@options[:puppet_master]}/#{@options[:branch]}/catalog/#{@node}",
75
+ headers: {
76
+ 'Accept' => 'text/pson'
77
+ },
75
78
  parameters: {
76
79
  'facts_format' => 'pson',
77
80
  'facts' => CGI.escape(@facts.fudge_timestamp.without('trusted').to_pson),
@@ -80,24 +83,59 @@ module OctocatalogDiff
80
83
  },
81
84
  3 => {
82
85
  url: "https://#{@options[:puppet_master]}/puppet/v3/catalog/#{@node}",
86
+ headers: {
87
+ 'Accept' => 'text/pson'
88
+ },
83
89
  parameters: {
84
90
  'environment' => @options[:branch],
85
91
  'facts_format' => 'pson',
86
92
  'facts' => CGI.escape(@facts.fudge_timestamp.without('trusted').to_pson),
87
93
  'transaction_uuid' => SecureRandom.uuid
88
94
  }
95
+ },
96
+ 4 => {
97
+ url: "https://#{@options[:puppet_master]}/puppet/v4/catalog",
98
+ headers: {
99
+ 'Content-Type' => 'application/json'
100
+ },
101
+ parameters: {
102
+ 'certname' => @node,
103
+ 'persistence' => {
104
+ 'facts' => @options[:puppet_master_update_facts] || false,
105
+ 'catalog' => @options[:puppet_master_update_catalog] || false
106
+ },
107
+ 'environment' => @options[:branch],
108
+ 'facts' => { 'values' => @facts.facts['values'] },
109
+ 'options' => {
110
+ 'prefer_requested_environment' => true,
111
+ 'capture_logs' => false,
112
+ 'log_level' => 'warning'
113
+ },
114
+ 'transaction_uuid' => SecureRandom.uuid
115
+ }
89
116
  }
90
117
  }
118
+
119
+ params = api_style[version]
120
+ return nil if params.nil?
121
+
122
+ unless @options[:puppet_master_token].nil?
123
+ params[:headers]['X-Authentication'] = @options[:puppet_master_token]
124
+ end
125
+
126
+ params[:parameters] = params[:parameters].to_json if version >= 4
127
+
128
+ params
91
129
  end
92
130
 
93
131
  # Fetch catalog by contacting the Puppet master, sending the facts, and asking for the catalog. When the
94
132
  # catalog is returned in PSON format, parse it to JSON and then set appropriate variables.
95
133
  def fetch_catalog(logger)
96
134
  api_version = @options[:puppet_master_api_version] || DEFAULT_PUPPET_SERVER_API
97
- api = puppet_catalog_api[api_version]
135
+ api = puppet_catalog_api(api_version)
98
136
  raise ArgumentError, "Unsupported or invalid API version #{api_version}" unless api.is_a?(Hash)
99
137
 
100
- more_options = { headers: { 'Accept' => 'text/pson' }, timeout: @timeout }
138
+ more_options = { headers: api[:headers], timeout: @timeout }
101
139
  post_hash = api[:parameters]
102
140
 
103
141
  response = nil