octocatalog-diff 0.5.6 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.version +1 -1
  3. data/doc/CHANGELOG.md +23 -5
  4. data/doc/advanced-bootstrap.md +25 -0
  5. data/doc/advanced-catalog-validation.md +41 -0
  6. data/doc/advanced-environments.md +93 -0
  7. data/doc/advanced-hiera-path-stripping.md +2 -0
  8. data/doc/advanced.md +2 -0
  9. data/doc/configuration-enc.md +34 -0
  10. data/doc/dev/releasing.md +40 -2
  11. data/doc/dev/run-from-branch.md +62 -0
  12. data/doc/installation.md +6 -0
  13. data/doc/optionsref.md +84 -22
  14. data/lib/octocatalog-diff/bootstrap.rb +2 -0
  15. data/lib/octocatalog-diff/catalog-diff/cli.rb +4 -1
  16. data/lib/octocatalog-diff/catalog-diff/cli/catalogs.rb +8 -2
  17. data/lib/octocatalog-diff/catalog-diff/cli/diffs.rb +2 -0
  18. data/lib/octocatalog-diff/catalog-diff/cli/helpers/fact_override.rb +3 -2
  19. data/lib/octocatalog-diff/catalog-diff/cli/options.rb +14 -2
  20. data/lib/octocatalog-diff/catalog-diff/cli/options/basedir.rb +2 -0
  21. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrap_current.rb +2 -0
  22. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrap_environment.rb +2 -0
  23. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrap_script.rb +2 -0
  24. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrap_then_exit.rb +2 -0
  25. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrapped_dirs.rb +2 -0
  26. data/lib/octocatalog-diff/catalog-diff/cli/options/cached_master_dir.rb +2 -0
  27. data/lib/octocatalog-diff/catalog-diff/cli/options/catalog_only.rb +2 -0
  28. data/lib/octocatalog-diff/catalog-diff/cli/options/color.rb +2 -0
  29. data/lib/octocatalog-diff/catalog-diff/cli/options/command_line.rb +19 -0
  30. data/lib/octocatalog-diff/catalog-diff/cli/options/compare_file_text.rb +2 -0
  31. data/lib/octocatalog-diff/catalog-diff/cli/options/create_symlinks.rb +20 -0
  32. data/lib/octocatalog-diff/catalog-diff/cli/options/debug.rb +2 -0
  33. data/lib/octocatalog-diff/catalog-diff/cli/options/debug_bootstrap.rb +2 -0
  34. data/lib/octocatalog-diff/catalog-diff/cli/options/display_datatype_changes.rb +2 -0
  35. data/lib/octocatalog-diff/catalog-diff/cli/options/display_detail_add.rb +2 -0
  36. data/lib/octocatalog-diff/catalog-diff/cli/options/display_source_file_line.rb +2 -0
  37. data/lib/octocatalog-diff/catalog-diff/cli/options/enc.rb +2 -0
  38. data/lib/octocatalog-diff/catalog-diff/cli/options/environment.rb +19 -0
  39. data/lib/octocatalog-diff/catalog-diff/cli/options/existing_catalogs.rb +2 -0
  40. data/lib/octocatalog-diff/catalog-diff/cli/options/fact_file.rb +2 -0
  41. data/lib/octocatalog-diff/catalog-diff/cli/options/fact_override.rb +2 -0
  42. data/lib/octocatalog-diff/catalog-diff/cli/options/facts_terminus.rb +2 -0
  43. data/lib/octocatalog-diff/catalog-diff/cli/options/from_puppetdb.rb +2 -0
  44. data/lib/octocatalog-diff/catalog-diff/cli/options/header.rb +2 -0
  45. data/lib/octocatalog-diff/catalog-diff/cli/options/hiera_config.rb +2 -0
  46. data/lib/octocatalog-diff/catalog-diff/cli/options/hiera_path.rb +2 -0
  47. data/lib/octocatalog-diff/catalog-diff/cli/options/hiera_path_strip.rb +2 -0
  48. data/lib/octocatalog-diff/catalog-diff/cli/options/hostname.rb +2 -0
  49. data/lib/octocatalog-diff/catalog-diff/cli/options/ignore.rb +2 -0
  50. data/lib/octocatalog-diff/catalog-diff/cli/options/ignore_attr.rb +2 -0
  51. data/lib/octocatalog-diff/catalog-diff/cli/options/ignore_tags.rb +2 -0
  52. data/lib/octocatalog-diff/catalog-diff/cli/options/include_tags.rb +2 -0
  53. data/lib/octocatalog-diff/catalog-diff/cli/options/master_cache_branch.rb +2 -0
  54. data/lib/octocatalog-diff/catalog-diff/cli/options/output_file.rb +2 -0
  55. data/lib/octocatalog-diff/catalog-diff/cli/options/output_format.rb +2 -0
  56. data/lib/octocatalog-diff/catalog-diff/cli/options/parallel.rb +2 -0
  57. data/lib/octocatalog-diff/catalog-diff/cli/options/parser.rb +2 -0
  58. data/lib/octocatalog-diff/catalog-diff/cli/options/pass_env_vars.rb +2 -0
  59. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_ssl_ca.rb +2 -0
  60. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_ssl_client_cert.rb +2 -0
  61. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_ssl_client_key.rb +2 -0
  62. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_token.rb +2 -0
  63. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_token_file.rb +2 -0
  64. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_url.rb +2 -0
  65. data/lib/octocatalog-diff/catalog-diff/cli/options/preserve_environments.rb +16 -0
  66. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_binary.rb +2 -0
  67. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master.rb +2 -0
  68. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_api_version.rb +2 -0
  69. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_ca.rb +2 -0
  70. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_client_cert.rb +2 -0
  71. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_client_key.rb +2 -0
  72. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_api_version.rb +14 -0
  73. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_ca.rb +2 -0
  74. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_cert.rb +2 -0
  75. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_key.rb +2 -0
  76. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_password.rb +2 -0
  77. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_password_file.rb +2 -0
  78. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_url.rb +2 -0
  79. data/lib/octocatalog-diff/catalog-diff/cli/options/quiet.rb +2 -0
  80. data/lib/octocatalog-diff/catalog-diff/cli/options/retry_failed_catalog.rb +2 -0
  81. data/lib/octocatalog-diff/catalog-diff/cli/options/safe_to_delete_cached_master_dir.rb +2 -0
  82. data/lib/octocatalog-diff/catalog-diff/cli/options/storeconfigs.rb +2 -0
  83. data/lib/octocatalog-diff/catalog-diff/cli/options/suppress_absent_file_details.rb +2 -0
  84. data/lib/octocatalog-diff/catalog-diff/cli/options/to_from_branch.rb +2 -0
  85. data/lib/octocatalog-diff/catalog-diff/cli/options/validate_references.rb +27 -0
  86. data/lib/octocatalog-diff/catalog-diff/cli/printer.rb +2 -0
  87. data/lib/octocatalog-diff/catalog-diff/differ.rb +2 -0
  88. data/lib/octocatalog-diff/catalog-diff/display.rb +2 -0
  89. data/lib/octocatalog-diff/catalog-diff/display/json.rb +2 -0
  90. data/lib/octocatalog-diff/catalog-diff/display/text.rb +2 -0
  91. data/lib/octocatalog-diff/catalog-util/bootstrap.rb +7 -1
  92. data/lib/octocatalog-diff/catalog-util/builddir.rb +49 -13
  93. data/lib/octocatalog-diff/catalog-util/cached_master_directory.rb +2 -0
  94. data/lib/octocatalog-diff/catalog-util/command.rb +61 -1
  95. data/lib/octocatalog-diff/catalog-util/enc.rb +2 -0
  96. data/lib/octocatalog-diff/catalog-util/enc/noop.rb +2 -0
  97. data/lib/octocatalog-diff/catalog-util/enc/pe.rb +2 -0
  98. data/lib/octocatalog-diff/catalog-util/enc/pe/v1.rb +2 -0
  99. data/lib/octocatalog-diff/catalog-util/enc/script.rb +3 -1
  100. data/lib/octocatalog-diff/catalog-util/facts.rb +2 -0
  101. data/lib/octocatalog-diff/catalog-util/fileresources.rb +19 -14
  102. data/lib/octocatalog-diff/catalog-util/git.rb +2 -0
  103. data/lib/octocatalog-diff/catalog.rb +75 -2
  104. data/lib/octocatalog-diff/catalog/computed.rb +16 -0
  105. data/lib/octocatalog-diff/catalog/json.rb +2 -0
  106. data/lib/octocatalog-diff/catalog/noop.rb +2 -0
  107. data/lib/octocatalog-diff/catalog/puppetdb.rb +2 -0
  108. data/lib/octocatalog-diff/catalog/puppetmaster.rb +8 -2
  109. data/lib/octocatalog-diff/facts.rb +2 -0
  110. data/lib/octocatalog-diff/facts/json.rb +2 -0
  111. data/lib/octocatalog-diff/facts/puppetdb.rb +10 -1
  112. data/lib/octocatalog-diff/facts/yaml.rb +2 -0
  113. data/lib/octocatalog-diff/puppetdb.rb +2 -0
  114. data/lib/octocatalog-diff/util/colored.rb +2 -0
  115. data/lib/octocatalog-diff/util/httparty.rb +2 -0
  116. data/lib/octocatalog-diff/util/parallel.rb +4 -1
  117. data/lib/octocatalog-diff/util/puppetversion.rb +2 -0
  118. data/lib/octocatalog-diff/version.rb +2 -0
  119. metadata +11 -2
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'enc/noop'
2
4
  require_relative 'enc/pe'
3
5
  require_relative 'enc/script'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OctocatalogDiff
2
4
  module CatalogUtil
3
5
  class ENC
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'pe/v1'
2
4
  require_relative '../../util/httparty'
3
5
  require_relative '../facts'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'uri'
3
5
  require 'yaml'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
  require 'open3'
3
5
  require 'shellwords'
@@ -79,7 +81,7 @@ module OctocatalogDiff
79
81
  def script_path(enc, tempdir)
80
82
  return enc if enc.start_with? '/'
81
83
  raise ArgumentError, 'OctocatalogDiff::CatalogUtil::ENC::Script#new requires :tempdir' unless tempdir.is_a?(String)
82
- return File.join(tempdir, enc) if enc =~ %r{^environments/production/}
84
+ return File.join(tempdir, enc) if enc =~ %r{^environments/[^/]+/}
83
85
  File.join(tempdir, 'environments', 'production', enc)
84
86
  end
85
87
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../facts'
2
4
 
3
5
  module OctocatalogDiff
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'digest'
2
4
 
3
5
  module OctocatalogDiff
@@ -11,9 +13,9 @@ module OctocatalogDiff
11
13
  # Public method: Convert file resources to text. See the description of the class
12
14
  # just above for details.
13
15
  # @param obj [OctocatalogDiff::Catalog] Catalog object (will be modified)
14
- def self.convert_file_resources(obj)
16
+ def self.convert_file_resources(obj, environment = 'production')
15
17
  return unless obj.valid? && obj.compilation_dir.is_a?(String) && !obj.compilation_dir.empty?
16
- _convert_file_resources(obj.resources, obj.compilation_dir)
18
+ _convert_file_resources(obj.resources, obj.compilation_dir, environment)
17
19
  begin
18
20
  obj.catalog_json = ::JSON.generate(obj.catalog)
19
21
  rescue ::JSON::GeneratorError => exc
@@ -43,20 +45,23 @@ module OctocatalogDiff
43
45
  end
44
46
 
45
47
  # Internal method: Parse environment.conf to find the modulepath
46
- # @param compilation_dir [String] Compilation directory
48
+ # @param dir [String] Directory in which to look for environment.conf
47
49
  # @return [Array] Module paths
48
- def self.module_path(compilation_dir)
49
- environment_conf = File.join(compilation_dir, 'environment.conf')
50
- unless File.file?(environment_conf)
51
- return [File.join(compilation_dir, 'modules')]
52
- end
50
+ def self.module_path(dir)
51
+ environment_conf = File.join(dir, 'environment.conf')
52
+ return [File.join(dir, 'modules')] unless File.file?(environment_conf)
53
53
 
54
54
  # This doesn't support multi-line, continuations with backslash, etc.
55
55
  # Does it need to??
56
56
  if File.read(environment_conf) =~ /^modulepath\s*=\s*(.+)/
57
- Regexp.last_match(1).split(/:/).map(&:strip).reject { |x| x =~ /^\$/ }.map { |x| File.join(compilation_dir, x) }
57
+ result = []
58
+ Regexp.last_match(1).split(/:/).map(&:strip).each do |path|
59
+ next if path.start_with?('$')
60
+ result << File.expand_path(path, dir)
61
+ end
62
+ result
58
63
  else
59
- [File.join(compilation_dir, 'modules')]
64
+ [File.join(dir, 'modules')]
60
65
  end
61
66
  end
62
67
 
@@ -64,15 +69,15 @@ module OctocatalogDiff
64
69
  # required, or else this is a no-op. The passed-in array of resources is modified by this method.
65
70
  # @param resources [Array<Hash>] Array of catalog resources
66
71
  # @param compilation_dir [String] Compilation directory (so files can be looked up)
67
- def self._convert_file_resources(resources, compilation_dir)
72
+ def self._convert_file_resources(resources, compilation_dir, environment = 'production')
68
73
  # Calculate compilation directory. There is not explicit error checking here because
69
74
  # there is on-demand, explicit error checking for each file within the modification loop.
70
75
  return unless compilation_dir.is_a?(String) && compilation_dir != ''
71
76
 
72
- # Making sure that compilation_dir/environments/production/modules exists (and by inference,
73
- # that compilation_dir/environments/production is pointing at the right place). Otherwise, try to find
77
+ # Making sure that compilation_dir/environments/<env>/modules exists (and by inference,
78
+ # that compilation_dir/environments/<env> is pointing at the right place). Otherwise, try to find
74
79
  # compilation_dir/modules. If neither of those exist, this code can't run.
75
- env_dir = File.join(compilation_dir, 'environments', 'production')
80
+ env_dir = File.join(compilation_dir, 'environments', environment)
76
81
  modulepaths = module_path(env_dir) + module_path(compilation_dir)
77
82
  modulepaths.select! { |x| File.directory?(x) }
78
83
  return if modulepaths.empty?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
  require 'open3'
3
5
  require 'rugged'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'stringio'
3
5
 
@@ -19,6 +21,7 @@ module OctocatalogDiff
19
21
  # Error classes that we can throw
20
22
  class PuppetVersionError < RuntimeError; end
21
23
  class CatalogError < RuntimeError; end
24
+ class ReferenceValidationError < RuntimeError; end
22
25
 
23
26
  # Constructor
24
27
  # @param :backend [Symbol] If set, this will force a backend
@@ -71,10 +74,18 @@ module OctocatalogDiff
71
74
  # Perform post-generation processing of the catalog
72
75
  return unless valid?
73
76
  unless @catalog_obj.respond_to?(:convert_file_resources) && @catalog_obj.convert_file_resources == false
74
- OctocatalogDiff::CatalogUtil::FileResources.convert_file_resources(self) if @options.fetch(:compare_file_text, false)
77
+ if @options.fetch(:compare_file_text, false)
78
+ OctocatalogDiff::CatalogUtil::FileResources.convert_file_resources(self, environment)
79
+ end
75
80
  end
76
81
  end
77
82
 
83
+ # Compilation environment
84
+ # @return [String] Compilation environment (if set), else 'production' by default
85
+ def environment
86
+ @catalog_obj.respond_to?(:environment) ? @catalog_obj.environment : 'production'
87
+ end
88
+
78
89
  # For logging we may wish to know the backend being used
79
90
  # @return [String] Class of backend used
80
91
  def builder
@@ -155,7 +166,7 @@ module OctocatalogDiff
155
166
  # This is a bug condition
156
167
  # :nocov:
157
168
  raise "BUG: catalog has no data::resources or ::resources array. Please report this. #{@catalog.inspect}"
158
- # :nocov
169
+ # :nocov:
159
170
  end
160
171
 
161
172
  # This retrieves the number of retries necessary to compile the catalog. If the underlying catalog
@@ -171,8 +182,66 @@ module OctocatalogDiff
171
182
  !@catalog.nil?
172
183
  end
173
184
 
185
+ # Determine if all of the (before, notify, require, subscribe) targets are actually in the catalog.
186
+ # Raise a ReferenceValidationError for any found to be missing.
187
+ # Uses @options[:validate_references] to influence which references are checked.
188
+ def validate_references
189
+ # Skip out early if no reference validation has been requested.
190
+ unless @options[:validate_references].is_a?(Array) && @options[:validate_references].any?
191
+ return
192
+ end
193
+
194
+ # Iterate over all the resources and check each one that has one of the attributes being checked.
195
+ # Keep track of all references that are missing for ultimate inclusion in the error message.
196
+ missing = []
197
+ resources.each do |x|
198
+ @options[:validate_references].each do |r|
199
+ next unless x.key?('parameters')
200
+ next unless x['parameters'].key?(r)
201
+ missing_resources = resources_missing_from_catalog(x['parameters'][r])
202
+ next unless missing_resources.any?
203
+ missing.concat missing_resources.map { |missing_target| { source: x, target_type: r, target_value: missing_target } }
204
+ end
205
+ end
206
+ return if missing.empty?
207
+
208
+ # At this point there is at least one broken/missing reference. Format an error message and
209
+ # raise. Error message will look like this:
210
+ # ---
211
+ # Catalog has broken references: exec[subscribe caller 1] -> subscribe[Exec[subscribe target]];
212
+ # exec[subscribe caller 2] -> subscribe[Exec[subscribe target]]; exec[subscribe caller 2] ->
213
+ # subscribe[Exec[subscribe target 2]]
214
+ # ---
215
+ formatted_references = missing.map do |obj|
216
+ # obj[:target_value] can be a string or an array. If it's an array, create a
217
+ # separate error message per element of that array. This allows the total number
218
+ # of errors to be correct.
219
+ src = "#{obj[:source]['type'].downcase}[#{obj[:source]['title']}]"
220
+ target_val = obj[:target_value].is_a?(Array) ? obj[:target_value] : [obj[:target_value]]
221
+ target_val.map { |tv| "#{src} -> #{obj[:target_type].downcase}[#{tv}]" }
222
+ end
223
+ formatted_references.flatten!
224
+ plural = formatted_references.size == 1 ? '' : 's'
225
+ errors = formatted_references.join('; ')
226
+ raise ReferenceValidationError, "Catalog has broken reference#{plural}: #{errors}"
227
+ end
228
+
174
229
  private
175
230
 
231
+ # Private method: Given a list of resources to check, return the references from
232
+ # that list that are missing from the catalog. (An empty array returned would indicate
233
+ # all references are present in the catalog.)
234
+ # @param resources_to_check [String / Array] Resources to check
235
+ # @return [Array] References that are missing from catalog
236
+ def resources_missing_from_catalog(resources_to_check)
237
+ [resources_to_check].flatten.select do |res|
238
+ unless res =~ /\A([\w:]+)\[(.+)\]\z/
239
+ raise ArgumentError, "Resource #{res} is not in the expected format"
240
+ end
241
+ resource(type: Regexp.last_match(1), title: Regexp.last_match(2)).nil?
242
+ end
243
+ end
244
+
176
245
  # Private method: Choose backend based on passed-in options
177
246
  # @param options [Hash] Options passed into constructor
178
247
  # @return [Object] OctocatalogDiff::Catalog::<whatever> object
@@ -203,6 +272,10 @@ module OctocatalogDiff
203
272
  resources.each do |resource|
204
273
  @resource_hash[resource['type']] ||= {}
205
274
  @resource_hash[resource['type']][resource['title']] = resource
275
+
276
+ if resource.key?('parameters') && resource['parameters'].key?('alias')
277
+ @resource_hash[resource['type']][resource['parameters']['alias']] = resource
278
+ end
206
279
  end
207
280
  end
208
281
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fileutils'
2
4
  require 'json'
3
5
  require 'open3'
@@ -76,6 +78,11 @@ module OctocatalogDiff
76
78
  @builddir.tempdir
77
79
  end
78
80
 
81
+ # Environment used to compile catalog
82
+ def environment
83
+ @opts[:preserve_environments] ? @opts.fetch(:environment, 'production') : 'production'
84
+ end
85
+
79
86
  private
80
87
 
81
88
  # Private method: Clean up a checkout directory, if it exists
@@ -179,11 +186,20 @@ module OctocatalogDiff
179
186
  }
180
187
  end
181
188
 
189
+ # Private method: Make sure that the Puppet environment directory exists.
190
+ def assert_that_puppet_environment_directory_exists
191
+ target_dir = File.join(@builddir.tempdir, 'environments', environment)
192
+ return if File.directory?(target_dir)
193
+ raise Errno::ENOENT, "Environment directory #{target_dir} does not exist"
194
+ end
195
+
182
196
  # Private method: Runs puppet on the command line to compile the catalog
183
197
  # Exit code is 0 if catalog generation was successful, non-zero otherwise.
184
198
  # @param logger [Logger] Logger object
185
199
  # @return [Hash] { stdout: <catalog as JSON>, stderr: <error messages>, exitcode: <hopefully 0> }
186
200
  def run_puppet(logger)
201
+ assert_that_puppet_environment_directory_exists
202
+
187
203
  # Run 'cmd' with environment 'env' from directory 'dir'
188
204
  # First line of a successful result needs to be stripped off. It will look like:
189
205
  # Notice: Compiled catalog for xxx in environment production in 27.88 seconds
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  module OctocatalogDiff
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
 
3
5
  module OctocatalogDiff
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'stringio'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../catalog-util/facts'
2
4
  require_relative '../external/pson/pure'
3
5
  require_relative '../util/httparty'
@@ -68,13 +70,17 @@ module OctocatalogDiff
68
70
 
69
71
  # Returns a hash of parameters for each supported version of the Puppet Server Catalog API.
70
72
  # @return [Hash] Hash of parameters
73
+ #
74
+ # Note: The double escaping of the facts here is implemented to correspond to a long standing
75
+ # bug in the Puppet code. See https://github.com/puppetlabs/puppet/pull/1818 and
76
+ # https://docs.puppet.com/puppet/latest/http_api/http_catalog.html#parameters for explanation.
71
77
  def puppet_catalog_api
72
78
  {
73
79
  2 => {
74
80
  url: "https://#{@options[:puppet_master]}/#{@options[:branch]}/catalog/#{@node}",
75
81
  parameters: {
76
82
  'facts_format' => 'pson',
77
- 'facts' => @facts.fudge_timestamp.without('trusted').to_pson,
83
+ 'facts' => CGI.escape(@facts.fudge_timestamp.without('trusted').to_pson),
78
84
  'transaction_uuid' => SecureRandom.uuid
79
85
  }
80
86
  },
@@ -83,7 +89,7 @@ module OctocatalogDiff
83
89
  parameters: {
84
90
  'environment' => @options[:branch],
85
91
  'facts_format' => 'pson',
86
- 'facts' => @facts.fudge_timestamp.without('trusted').to_pson,
92
+ 'facts' => CGI.escape(@facts.fudge_timestamp.without('trusted').to_pson),
87
93
  'transaction_uuid' => SecureRandom.uuid
88
94
  }
89
95
  }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'facts/json'
2
4
  require_relative 'facts/yaml'
3
5
  require_relative 'facts/puppetdb'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../facts'
2
4
 
3
5
  require 'json'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../facts'
2
4
  require_relative '../puppetdb'
3
5
  require 'yaml'
@@ -6,6 +8,12 @@ module OctocatalogDiff
6
8
  class Facts
7
9
  # Deal with facts in PuppetDB
8
10
  class PuppetDB
11
+ # Supporting multiple versions of the PuppetDB API.
12
+ PUPPETDB_QUERY_FACTS_URL = {
13
+ '3' => '/v3/nodes/<NODE>/facts',
14
+ '4' => '/pdb/query/v4/nodes/<NODE>/facts'
15
+ }.freeze
16
+
9
17
  # Retrieve facts from PuppetDB for a specified node.
10
18
  # @param :puppetdb_url [String|Array] => URL to PuppetDB
11
19
  # @param :retry [Fixnum] => Retry after timeout (default 0 retries, can be more)
@@ -15,7 +23,8 @@ module OctocatalogDiff
15
23
  # Set up some variables from options
16
24
  raise ArgumentError, 'puppetdb_url is required' unless options[:puppetdb_url].is_a?(String)
17
25
  raise ArgumentError, 'node must be a non-empty string' unless node.is_a?(String) && node != ''
18
- uri = "/pdb/query/v4/nodes/#{node}/facts"
26
+ puppetdb_api_version = options.fetch(:puppetdb_api_version, 4)
27
+ uri = PUPPETDB_QUERY_FACTS_URL.fetch(puppetdb_api_version.to_s).gsub('<NODE>', node)
19
28
  retries = options.fetch(:retry, 0).to_i
20
29
 
21
30
  # Construct puppetdb object and options
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../facts'
2
4
  require 'yaml'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'util/httparty'
2
4
 
3
5
  require 'uri'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Create colorizing methods in the 'String' class, but only if 'colors_enabled'
2
4
  # has been set.
3
5
  class String
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'httparty'
2
4
  require 'json'
3
5
  require_relative '../external/pson/pure'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Helper to use the 'parallel' gem to perform tasks
2
4
 
3
5
  require 'parallel'
@@ -20,6 +22,7 @@ module OctocatalogDiff
20
22
  @args = opts.fetch(:args, {})
21
23
  @description = opts[:description] || @method.name
22
24
  @validator = opts[:validator]
25
+ @validator_args = opts[:validator_args] || {}
23
26
  end
24
27
 
25
28
  def execute(logger = Logger.new(StringIO.new))
@@ -28,7 +31,7 @@ module OctocatalogDiff
28
31
 
29
32
  def validate(result, logger = Logger.new(StringIO.new))
30
33
  return true if @validator.nil?
31
- @validator.call(result, logger)
34
+ @validator.call(result, logger, @validator_args)
32
35
  end
33
36
  end
34
37
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Helper to determine the version of Puppet
2
4
 
3
5
  require 'fileutils'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OctocatalogDiff
2
4
  # Determine the version of octocatalog-diff
3
5
  class Version
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: octocatalog-diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub, Inc.
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-11-17 00:00:00.000000000 Z
12
+ date: 2017-01-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: diffy
@@ -226,8 +226,10 @@ files:
226
226
  - doc/advanced-bootstrap.md
227
227
  - doc/advanced-cache-dir.md
228
228
  - doc/advanced-catalog-only.md
229
+ - doc/advanced-catalog-validation.md
229
230
  - doc/advanced-ci.md
230
231
  - doc/advanced-dynamic-ignores.md
232
+ - doc/advanced-environments.md
231
233
  - doc/advanced-future-parser.md
232
234
  - doc/advanced-hiera-path-stripping.md
233
235
  - doc/advanced-ignores.md
@@ -251,6 +253,7 @@ files:
251
253
  - doc/dev/how-to-add-options.md
252
254
  - doc/dev/integration-tests.md
253
255
  - doc/dev/releasing.md
256
+ - doc/dev/run-from-branch.md
254
257
  - doc/installation.md
255
258
  - doc/limitations.md
256
259
  - doc/optionsref.md
@@ -274,13 +277,16 @@ files:
274
277
  - lib/octocatalog-diff/catalog-diff/cli/options/cached_master_dir.rb
275
278
  - lib/octocatalog-diff/catalog-diff/cli/options/catalog_only.rb
276
279
  - lib/octocatalog-diff/catalog-diff/cli/options/color.rb
280
+ - lib/octocatalog-diff/catalog-diff/cli/options/command_line.rb
277
281
  - lib/octocatalog-diff/catalog-diff/cli/options/compare_file_text.rb
282
+ - lib/octocatalog-diff/catalog-diff/cli/options/create_symlinks.rb
278
283
  - lib/octocatalog-diff/catalog-diff/cli/options/debug.rb
279
284
  - lib/octocatalog-diff/catalog-diff/cli/options/debug_bootstrap.rb
280
285
  - lib/octocatalog-diff/catalog-diff/cli/options/display_datatype_changes.rb
281
286
  - lib/octocatalog-diff/catalog-diff/cli/options/display_detail_add.rb
282
287
  - lib/octocatalog-diff/catalog-diff/cli/options/display_source_file_line.rb
283
288
  - lib/octocatalog-diff/catalog-diff/cli/options/enc.rb
289
+ - lib/octocatalog-diff/catalog-diff/cli/options/environment.rb
284
290
  - lib/octocatalog-diff/catalog-diff/cli/options/existing_catalogs.rb
285
291
  - lib/octocatalog-diff/catalog-diff/cli/options/fact_file.rb
286
292
  - lib/octocatalog-diff/catalog-diff/cli/options/fact_override.rb
@@ -307,12 +313,14 @@ files:
307
313
  - lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_token.rb
308
314
  - lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_token_file.rb
309
315
  - lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_url.rb
316
+ - lib/octocatalog-diff/catalog-diff/cli/options/preserve_environments.rb
310
317
  - lib/octocatalog-diff/catalog-diff/cli/options/puppet_binary.rb
311
318
  - lib/octocatalog-diff/catalog-diff/cli/options/puppet_master.rb
312
319
  - lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_api_version.rb
313
320
  - lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_ca.rb
314
321
  - lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_client_cert.rb
315
322
  - lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_client_key.rb
323
+ - lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_api_version.rb
316
324
  - lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_ca.rb
317
325
  - lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_cert.rb
318
326
  - lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_key.rb
@@ -325,6 +333,7 @@ files:
325
333
  - lib/octocatalog-diff/catalog-diff/cli/options/storeconfigs.rb
326
334
  - lib/octocatalog-diff/catalog-diff/cli/options/suppress_absent_file_details.rb
327
335
  - lib/octocatalog-diff/catalog-diff/cli/options/to_from_branch.rb
336
+ - lib/octocatalog-diff/catalog-diff/cli/options/validate_references.rb
328
337
  - lib/octocatalog-diff/catalog-diff/cli/printer.rb
329
338
  - lib/octocatalog-diff/catalog-diff/differ.rb
330
339
  - lib/octocatalog-diff/catalog-diff/display.rb