octocatalog-diff 1.5.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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