octocatalog-diff 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/.version +1 -0
  3. data/LICENSE +20 -0
  4. data/README.md +82 -0
  5. data/bin/octocatalog-diff +75 -0
  6. data/doc/advanced-bootstrap.md +33 -0
  7. data/doc/advanced-cache-dir.md +24 -0
  8. data/doc/advanced-catalog-only.md +37 -0
  9. data/doc/advanced-ci.md +13 -0
  10. data/doc/advanced-dynamic-ignores.md +123 -0
  11. data/doc/advanced-future-parser.md +11 -0
  12. data/doc/advanced-ignores.md +224 -0
  13. data/doc/advanced-output-formats.md +96 -0
  14. data/doc/advanced-output-hacks.md +45 -0
  15. data/doc/advanced-override-facts.md +67 -0
  16. data/doc/advanced-pe-enc.md +52 -0
  17. data/doc/advanced-puppet-master.md +50 -0
  18. data/doc/advanced-puppet-versions.md +9 -0
  19. data/doc/advanced-storeconfigs.md +72 -0
  20. data/doc/advanced-using-without-git.md +15 -0
  21. data/doc/advanced.md +43 -0
  22. data/doc/basic.md +70 -0
  23. data/doc/configuration-enc.md +69 -0
  24. data/doc/configuration-hiera.md +103 -0
  25. data/doc/configuration-puppetdb.md +49 -0
  26. data/doc/configuration.md +51 -0
  27. data/doc/dev/README.md +1 -0
  28. data/doc/dev/coverage.md +34 -0
  29. data/doc/dev/how-to-add-options.md +83 -0
  30. data/doc/dev/integration-tests.md +63 -0
  31. data/doc/dev/releasing.md +19 -0
  32. data/doc/installation.md +49 -0
  33. data/doc/limitations.md +34 -0
  34. data/doc/optionsref.md +947 -0
  35. data/doc/requirements.md +16 -0
  36. data/doc/roadmap.md +26 -0
  37. data/doc/similar.md +17 -0
  38. data/doc/troubleshooting.md +54 -0
  39. data/lib/octocatalog-diff.rb +12 -0
  40. data/lib/octocatalog-diff/bootstrap.rb +53 -0
  41. data/lib/octocatalog-diff/catalog-diff/cli.rb +205 -0
  42. data/lib/octocatalog-diff/catalog-diff/cli/catalogs.rb +240 -0
  43. data/lib/octocatalog-diff/catalog-diff/cli/diffs.rb +145 -0
  44. data/lib/octocatalog-diff/catalog-diff/cli/helpers/fact_override.rb +99 -0
  45. data/lib/octocatalog-diff/catalog-diff/cli/options.rb +173 -0
  46. data/lib/octocatalog-diff/catalog-diff/cli/options/basedir.rb +14 -0
  47. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrap_environment.rb +18 -0
  48. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrap_script.rb +14 -0
  49. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrap_then_exit.rb +12 -0
  50. data/lib/octocatalog-diff/catalog-diff/cli/options/bootstrapped_dirs.rb +18 -0
  51. data/lib/octocatalog-diff/catalog-diff/cli/options/cached_master_dir.rb +21 -0
  52. data/lib/octocatalog-diff/catalog-diff/cli/options/catalog_only.rb +14 -0
  53. data/lib/octocatalog-diff/catalog-diff/cli/options/color.rb +13 -0
  54. data/lib/octocatalog-diff/catalog-diff/cli/options/compare_file_text.rb +15 -0
  55. data/lib/octocatalog-diff/catalog-diff/cli/options/debug.rb +12 -0
  56. data/lib/octocatalog-diff/catalog-diff/cli/options/display_datatype_changes.rb +16 -0
  57. data/lib/octocatalog-diff/catalog-diff/cli/options/display_detail_add.rb +12 -0
  58. data/lib/octocatalog-diff/catalog-diff/cli/options/display_source_file_line.rb +12 -0
  59. data/lib/octocatalog-diff/catalog-diff/cli/options/enc.rb +31 -0
  60. data/lib/octocatalog-diff/catalog-diff/cli/options/existing_catalogs.rb +25 -0
  61. data/lib/octocatalog-diff/catalog-diff/cli/options/fact_file.rb +23 -0
  62. data/lib/octocatalog-diff/catalog-diff/cli/options/fact_override.rb +19 -0
  63. data/lib/octocatalog-diff/catalog-diff/cli/options/facts_terminus.rb +16 -0
  64. data/lib/octocatalog-diff/catalog-diff/cli/options/from_puppetdb.rb +13 -0
  65. data/lib/octocatalog-diff/catalog-diff/cli/options/header.rb +24 -0
  66. data/lib/octocatalog-diff/catalog-diff/cli/options/hiera_config.rb +18 -0
  67. data/lib/octocatalog-diff/catalog-diff/cli/options/hiera_path_strip.rb +12 -0
  68. data/lib/octocatalog-diff/catalog-diff/cli/options/hostname.rb +13 -0
  69. data/lib/octocatalog-diff/catalog-diff/cli/options/ignore.rb +24 -0
  70. data/lib/octocatalog-diff/catalog-diff/cli/options/ignore_attr.rb +16 -0
  71. data/lib/octocatalog-diff/catalog-diff/cli/options/ignore_tags.rb +23 -0
  72. data/lib/octocatalog-diff/catalog-diff/cli/options/include_tags.rb +12 -0
  73. data/lib/octocatalog-diff/catalog-diff/cli/options/master_cache_branch.rb +12 -0
  74. data/lib/octocatalog-diff/catalog-diff/cli/options/output_file.rb +15 -0
  75. data/lib/octocatalog-diff/catalog-diff/cli/options/output_format.rb +15 -0
  76. data/lib/octocatalog-diff/catalog-diff/cli/options/parallel.rb +12 -0
  77. data/lib/octocatalog-diff/catalog-diff/cli/options/parser.rb +48 -0
  78. data/lib/octocatalog-diff/catalog-diff/cli/options/pass_env_vars.rb +19 -0
  79. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_ssl_ca.rb +15 -0
  80. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_ssl_client_cert.rb +14 -0
  81. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_ssl_client_key.rb +14 -0
  82. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_token.rb +15 -0
  83. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_token_file.rb +17 -0
  84. data/lib/octocatalog-diff/catalog-diff/cli/options/pe_enc_url.rb +19 -0
  85. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_binary.rb +16 -0
  86. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master.rb +16 -0
  87. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_api_version.rb +20 -0
  88. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_ca.rb +19 -0
  89. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_client_cert.rb +19 -0
  90. data/lib/octocatalog-diff/catalog-diff/cli/options/puppet_master_ssl_client_key.rb +19 -0
  91. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_ca.rb +15 -0
  92. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_cert.rb +14 -0
  93. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_key.rb +14 -0
  94. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_password.rb +14 -0
  95. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_ssl_client_password_file.rb +13 -0
  96. data/lib/octocatalog-diff/catalog-diff/cli/options/puppetdb_url.rb +18 -0
  97. data/lib/octocatalog-diff/catalog-diff/cli/options/quiet.rb +12 -0
  98. data/lib/octocatalog-diff/catalog-diff/cli/options/retry_failed_catalog.rb +13 -0
  99. data/lib/octocatalog-diff/catalog-diff/cli/options/safe_to_delete_cached_master_dir.rb +15 -0
  100. data/lib/octocatalog-diff/catalog-diff/cli/options/storeconfigs.rb +12 -0
  101. data/lib/octocatalog-diff/catalog-diff/cli/options/suppress_absent_file_details.rb +14 -0
  102. data/lib/octocatalog-diff/catalog-diff/cli/options/to_from_branch.rb +16 -0
  103. data/lib/octocatalog-diff/catalog-diff/cli/printer.rb +52 -0
  104. data/lib/octocatalog-diff/catalog-diff/differ.rb +615 -0
  105. data/lib/octocatalog-diff/catalog-diff/display.rb +125 -0
  106. data/lib/octocatalog-diff/catalog-diff/display/json.rb +25 -0
  107. data/lib/octocatalog-diff/catalog-diff/display/text.rb +452 -0
  108. data/lib/octocatalog-diff/catalog-util/bootstrap.rb +145 -0
  109. data/lib/octocatalog-diff/catalog-util/builddir.rb +289 -0
  110. data/lib/octocatalog-diff/catalog-util/cached_master_directory.rb +169 -0
  111. data/lib/octocatalog-diff/catalog-util/command.rb +96 -0
  112. data/lib/octocatalog-diff/catalog-util/enc.rb +77 -0
  113. data/lib/octocatalog-diff/catalog-util/enc/noop.rb +22 -0
  114. data/lib/octocatalog-diff/catalog-util/enc/pe.rb +99 -0
  115. data/lib/octocatalog-diff/catalog-util/enc/pe/v1.rb +61 -0
  116. data/lib/octocatalog-diff/catalog-util/enc/script.rb +88 -0
  117. data/lib/octocatalog-diff/catalog-util/facts.rb +89 -0
  118. data/lib/octocatalog-diff/catalog-util/fileresources.rb +83 -0
  119. data/lib/octocatalog-diff/catalog-util/git.rb +65 -0
  120. data/lib/octocatalog-diff/catalog.rb +209 -0
  121. data/lib/octocatalog-diff/catalog/computed.rb +205 -0
  122. data/lib/octocatalog-diff/catalog/json.rb +30 -0
  123. data/lib/octocatalog-diff/catalog/noop.rb +19 -0
  124. data/lib/octocatalog-diff/catalog/puppetdb.rb +82 -0
  125. data/lib/octocatalog-diff/catalog/puppetmaster.rb +121 -0
  126. data/lib/octocatalog-diff/external/pson/LICENSE +17 -0
  127. data/lib/octocatalog-diff/external/pson/README.md +20 -0
  128. data/lib/octocatalog-diff/external/pson/common.rb +370 -0
  129. data/lib/octocatalog-diff/external/pson/pure.rb +15 -0
  130. data/lib/octocatalog-diff/external/pson/pure/generator.rb +395 -0
  131. data/lib/octocatalog-diff/external/pson/pure/parser.rb +307 -0
  132. data/lib/octocatalog-diff/external/pson/version.rb +8 -0
  133. data/lib/octocatalog-diff/facts.rb +125 -0
  134. data/lib/octocatalog-diff/facts/json.rb +20 -0
  135. data/lib/octocatalog-diff/facts/puppetdb.rb +59 -0
  136. data/lib/octocatalog-diff/facts/yaml.rb +29 -0
  137. data/lib/octocatalog-diff/puppetdb.rb +163 -0
  138. data/lib/octocatalog-diff/util/colored.rb +20 -0
  139. data/lib/octocatalog-diff/util/httparty.rb +158 -0
  140. data/lib/octocatalog-diff/util/parallel.rb +170 -0
  141. data/lib/octocatalog-diff/util/puppetversion.rb +24 -0
  142. data/lib/octocatalog-diff/version.rb +7 -0
  143. metadata +386 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 884750a5cc423f972506a90a43ea39afde1ec405
4
+ data.tar.gz: 2374a0483c93b1a65fd94f986819c5564a96dd3c
5
+ SHA512:
6
+ metadata.gz: 739226ba6430412af00c3fe3ca91cced879a9b3aaa836cea7f418c50eae5f2b740335a3a066bc41b7e034f510021a7bd8f169b0b683d67bbf04f742e8ae5aee3
7
+ data.tar.gz: 16f3bb672a86f60aa3edb541ae2189fca978b9d9be4b754de48f3ce4b61c441a23baff521561f64fdb883f41848400d84df70bae5b2f83eef5252baf27e6820b
@@ -0,0 +1 @@
1
+ 0.5.1
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 GitHub Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,82 @@
1
+ # octocatalog-diff
2
+
3
+ #### Compile Puppet catalogs from 2 branches, versions, etc., and compare them <img src="/doc/images/octocatolog-diff-logo.png" align="right" height=126 width=240>
4
+
5
+ `octocatalog-diff` is a tool that enables developers to be more efficient when testing changes to Puppet manifests. It is most commonly used to display differences in Puppet catalogs between stable and development branches. It does not require a working Puppet master (or puppetserver), so it is often run by developers on their workstations and in Continuous Integration environments.
6
+
7
+ At GitHub, we manage thousands of nodes with a Puppet code base containing 500,000+ lines of code from over 200 contributors. We run `octocatalog-diff` thousands of times per day as part of Continuous Integration testing, and developers run it on their workstations as they are working with the code.
8
+
9
+ `octocatalog-diff` is written in Ruby and is distributed as a gem. It runs on Mac OS and Unix/Linux platforms.
10
+
11
+ It is under active development at this time. We suspect that with the initial release, some people who try it out could be using configurations of Puppet that we haven't experienced within our environment. We are eager to identify and fix as many of these as we can to expand the compatibility of this tool as much as possible.
12
+
13
+ ## How?
14
+
15
+ Traditional Puppet development generally takes one of two forms. Frequently, developers will test changes by running a Puppet agent (perhaps in `--noop` mode) to see if the desired change has resulted on an actual system. Others will use formal testing methodologies, such as `rspec-puppet` or the beaker framework to validate Puppet code.
16
+
17
+ `octocatalog-diff` uses a different pattern. In its most common invocation, it compiles Puppet catalogs for both the stable branch (e.g. master) and the development branch, and then compares them. It filters out attributes or resources that have no effect on ultimate state of the target system (e.g. tags) and displays the remaining differences. Using this strategy, one can get feedback on changes without deploying Puppet code to a server and conducting a full Puppet run, and this tool works even if test coverage is incomplete.
18
+
19
+ There are some [limitations](doc/limitations.md) to a catalog-based approach, meaning it will never completely replace unit, integration, or deployment testing. However, it does provide substantial time savings in both the development and testing cycle. In this repository, we provide example scripts for using `octocatalog-diff` in development and CI environments.
20
+
21
+ `octocatalog-diff` is currently able to get catalogs by the following methods:
22
+ - Compile catalog via the command line with a Puppet agent on your machine (as GitHub uses the tool internally)
23
+ - Obtain catalog over the network from PuppetDB
24
+ - Obtain catalog over the network using the API to query a Puppet Master / PuppetServer (Puppet 3.x and 4.x supported)
25
+ - Read catalog from a JSON file
26
+
27
+ ## Example
28
+
29
+ Here is simulated output from running `octocatalog-diff` to compare the Puppet catalog changes between the master branch and the Puppet code in the current working directory:
30
+
31
+ <img src="doc/images/screenshot1.png" alt="[octocatalog-diff screenshot]">
32
+
33
+ The example above reflects the changes in the Puppet catalog from switching an underlying device for a mounted file system.
34
+
35
+ ## Documentation
36
+
37
+ ### Installation and use in a development environment
38
+
39
+ - [Installation](/doc/installation.md)
40
+ - [Configuration](/doc/configuration.md)
41
+ - [Basic command line usage](/doc/basic.md)
42
+ - [Advanced command line usage](/doc/advanced.md)
43
+ - [Troubleshooting](/doc/troubleshooting.md)
44
+
45
+ ### Installation and use for CI
46
+
47
+ - [Setting up octocatalog-diff in CI](/doc/advanced-ci.md)
48
+
49
+ ### Technical details
50
+
51
+ - [Requirements](/doc/requirements.md)
52
+ - [Limitations](/doc/limitations.md)
53
+ - [List of all command line options](/doc/optionsref.md)
54
+
55
+ ### Project
56
+
57
+ - [Roadmap](/doc/roadmap.md)
58
+ - [Similar tools](/doc/similar.md)
59
+ - [Contributing](/.github/CONTRIBUTING.md)
60
+ - [Developer documentation](/doc/dev)
61
+
62
+ ## What's in a name?
63
+
64
+ During its original development at GitHub, this tool was simply called `catalog-diff`. However, there is already a [Puppet module with that name](https://forge.puppet.com/zack/catalog_diff) and we didn't want to create any confusion (in fact, a case could be made to use both approaches). So, we named the tool `octocatalog-diff` because who doesn't like the [octocat](https://octodex.github.com/)? Then one day in chat, someone referred to the tool as ":octocat:alog-diff", and that moniker caught on for electronic communication.
65
+
66
+ ## Contributing
67
+
68
+ Please see our [contributing document](/.github/CONTRIBUTING.md) if you would like to participate!
69
+
70
+ ## Getting help
71
+
72
+ If you have a problem or suggestion, please [open an issue](https://github.com/github/octocatalog-diff/issues/new) in this repository, and we will do our best to help. Please note that this project adheres to the [Open Code of Conduct](http://todogroup.org/opencodeofconduct/#GitHub%20Octocatalog-Diff/opensource@github.com).
73
+
74
+ ## License
75
+
76
+ `octocatalog-diff` is licensed under the [MIT license](LICENSE).
77
+
78
+ It requires 3rd party ruby gems found [here](/vendor/cache). It also includes portions of other open source projects [here](/lib/octocatalog-diff/external/pson), [here](/spec/octocatalog-diff/fixtures/repos/default/modules/stdlib), [here](/spec/octocatalog-diff/support/httparty) and [here](/spec/octocatalog-diff/tests/external/pson). All 3rd party code and required gems are licensed either as MIT or Apache 2.0.
79
+
80
+ ## Authors
81
+
82
+ `octocatalog-diff` was designed and authored by [Kevin Paulisse](https://github.com/kpaulisse) and is now maintained, reviewed, and tested by the Site Reliability Engineering team at GitHub.
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ENV['OCTOCATALOG_DIFF_DEVELOPER_PATH']
4
+ # Mostly used for internal testing, to allow pointing of a "real" octocatalog-diff install
5
+ # at code being developed live.
6
+ rel = File.expand_path(ENV['OCTOCATALOG_DIFF_DEVELOPER_PATH'], File.dirname(__FILE__))
7
+ abs = File.expand_path(ENV['OCTOCATALOG_DIFF_DEVELOPER_PATH'])
8
+ if File.directory?(abs) && File.file?(File.join(abs, 'lib', 'octocatalog-diff.rb'))
9
+ require File.join(abs, 'lib', 'octocatalog-diff')
10
+ elsif File.directory?(rel) && File.file?(File.join(rel, 'lib', 'octocatalog-diff.rb'))
11
+ require File.join(rel, 'lib', 'octocatalog-diff')
12
+ else
13
+ raise Errno::ENOENT, "Unable to resolve #{ENV['OCTOCATALOG_DIFF_DEVELOPER_PATH']} (tried #{abs} then #{rel})"
14
+ end
15
+ elsif File.file?(File.expand_path('../lib/octocatalog-diff.rb', File.dirname(__FILE__)))
16
+ require_relative '../lib/octocatalog-diff'
17
+ else
18
+ require 'octocatalog-diff'
19
+ end
20
+
21
+ config_test = ARGV.include?('--config-test')
22
+
23
+ paths = [
24
+ ENV['OCTOCATALOG_DIFF_CONFIG_FILE'],
25
+ File.join(Dir.pwd, '.octocatalog-diff.cfg.rb'),
26
+ File.join(ENV['HOME'], '.octocatalog-diff.cfg.rb'),
27
+ '/opt/puppetlabs/octocatalog-diff/octocatalog-diff.cfg.rb',
28
+ '/usr/local/etc/octocatalog-diff.cfg.rb',
29
+ '/etc/octocatalog-diff.cfg.rb'
30
+ ]
31
+
32
+ cfgfile = nil
33
+
34
+ paths.each do |path|
35
+ next if path.nil?
36
+ puts "Looking for config in: #{path}" if config_test
37
+ next unless File.file?(path)
38
+ begin
39
+ cfgfile = path
40
+ puts "Loading config: #{path}" if config_test
41
+ require path
42
+ rescue => exc
43
+ STDERR.puts "#{exc.class} error with #{path}: #{exc.message}\n#{exc.backtrace}"
44
+ exit 1
45
+ end
46
+ break
47
+ end
48
+
49
+ options = {}
50
+
51
+ if cfgfile
52
+ begin
53
+ options = OctocatalogDiff::Config.config
54
+ rescue => exc
55
+ STDERR.puts "#{exc.class} error with #{cfgfile}: #{exc.message}\n#{exc.backtrace}"
56
+ exit 1
57
+ end
58
+ unless options.is_a?(Hash)
59
+ STDERR.puts "Configuration must be Hash not #{options.class}!"
60
+ exit 1
61
+ end
62
+ if config_test
63
+ options.each do |key, val|
64
+ puts ":#{key} => (#{val.class}) #{val.inspect}"
65
+ end
66
+ exit 0
67
+ end
68
+ elsif config_test
69
+ STDERR.puts 'No configuration files found'
70
+ exit 1
71
+ end
72
+
73
+ argv = ARGV.dup
74
+ exit_code = OctocatalogDiff::CatalogDiff::Cli.cli(argv, Logger.new(STDERR), options)
75
+ exit(exit_code)
@@ -0,0 +1,33 @@
1
+ # Bootstrapping your Puppet checkout
2
+
3
+ For many implementations of Puppet, an intermediate step is required between checking out code from a repository and having that code be ready to be served via a Puppet Master server. For example, you may need to run `bundler` to install gems or `librarian-puppet` to download Puppet modules. This document will refer to this process -- whatever it may mean for your particular use case -- as *bootstrapping*.
4
+
5
+ ## Bootstrapping with `octocatalog-diff`
6
+
7
+ Since `octocatalog-diff` integrates closely with your git repository, we provide a mechanism to allow you to perform your bootstrapping between the checkout of the branch and the build of the catalog.
8
+
9
+ The `--bootstrap-script` option takes a string parameter consisting of either:
10
+
11
+ - An absolute path, starting with `/`
12
+ - A path relative to your Puppet checkout, not starting with `/`
13
+
14
+ For example, if you have a script named `script/bootstrap.sh` in a subdirectory of your Puppet repository, you could instruct `octocatalog-diff` to use this script for bootstrap by specifying:
15
+
16
+ ```
17
+ octocatalog-diff --bootstrap-script script/bootstrap.sh ...
18
+ ```
19
+
20
+ If you have your bootstrap script at a known location on the system (not stored in your Puppet repository), you can refer to it with an absolute path.
21
+
22
+ ```
23
+ octocatalog-diff --bootstrap-script /etc/puppetlabs/repo-bootstrap.sh ...
24
+ ```
25
+
26
+ ## Configuring bootstrapping via the configuration file
27
+
28
+ The [example configuration file](/examples/octocatalog-diff.cfg.rb) contains an example setting for the bootstrap script.
29
+
30
+ ```
31
+ # settings[:bootstrap_script] = '/etc/puppetlabs/repo-bootstrap.sh' # Absolute path
32
+ # settings[:bootstrap_script] = 'script/bootstrap' # Relative path
33
+ ```
@@ -0,0 +1,24 @@
1
+ # Enabling the cache directory
2
+
3
+ If you are running `octocatalog-diff` on your workstation, enabling the cache directory can support faster runs by:
4
+
5
+ - Bootstrapping the `master` branch and saving that in a directory, so that you do not need to bootstrap the `master` branch each time you run `octocatalog-diff`.
6
+ - Saving the `master` catalog for each node, so that for the second and subsequent difference calculation, this catalog does not need to be re-computed.
7
+
8
+ We recommend that you configure these settings in your [configuration file](/doc/configuration.md), although it is possible to specify these settings on the command line as well.
9
+
10
+ ## Cache directory options
11
+
12
+ There are two options that pertain to the cache directory:
13
+
14
+ - `--cached-master-dir DIRECTORY_PATH`
15
+
16
+ This is the full path to the directory where the bootstrapped master directory will reside. Please note that this directory will be created if it doesn't exist, but for the directory to be created, *its parent directory must already exist*. You will receive an error message if you specify a directory path that is not a directory, or cannot be created as a directory.
17
+
18
+ Note that a subdirectory called `.catalogs` will be created within the chosen directory paths, and compiled `master` catalogs for nodes will be stored therein.
19
+
20
+ - `--safe-to-delete-cached-master-dir DIRECTORY_PATH`
21
+
22
+ If you want to allow `octocatalog-diff` to delete the cached master directory when it becomes stale, set this option. If you do not set this option, and the cached master directory becomes stale, an error will be raised.
23
+
24
+ Historically, this was separated from `--cached-master-dir` to provide a separation between routine behavior (creating files and catalogs) and destructive behavior (deleting an entire directory).
@@ -0,0 +1,37 @@
1
+ # Building catalogs instead of diffing catalogs
2
+
3
+ `octocatalog-diff` is designed primarily to build two catalogs and compare them. However, it can also simply generate the catalog without performing comparisons.
4
+
5
+ ## Usage
6
+
7
+ The `--catalog-only` command line flag triggers the following behavior:
8
+
9
+ - The compiled catalog (not the difference) is written to the screen or stored in a file
10
+ - Only the "to" branch is relevant (the "from" branch is not touched)
11
+ - Options that control [output formats](/doc/advanced-output-formats.md), such as color and JSON format, do not apply
12
+ - The `-o FILENAME` option will write the catalog to the indicated file rather than displaying it on screen
13
+
14
+ ## Examples
15
+
16
+ Building a catalog for a node from the current working directory and displaying on screen:
17
+
18
+ ```
19
+ octocatalog-diff -n some-node.example.com --catalog-only
20
+ ```
21
+
22
+ Building a catalog for a node from a specific branch and saving to a file:
23
+
24
+ ```
25
+ octocatalog-diff -n some-node.example.com -t my-branch -o /tmp/some-node.json --catalog-only
26
+ ```
27
+
28
+ As part of a CI job, testing whether a catalog for a particular host compiles:
29
+
30
+ ```
31
+ octocatalog-diff -n some-node.example.com -o /dev/null --catalog-only
32
+ if [ $? -eq 0 ]; then
33
+ echo "Pass"
34
+ else
35
+ echo "Fail"
36
+ fi
37
+ ```
@@ -0,0 +1,13 @@
1
+ # Using `octocatalog-diff` in CI
2
+
3
+ ## Catalog compilation check
4
+
5
+ Compile the catalog for several important hosts, and ensure that all catalogs successfully compile before permitting the merge. This is a pass/fail check.
6
+
7
+ - [Sample rspec file for catalog compilation test](/examples/ci/puppet_catalogs_spec.rb)
8
+
9
+ ## Catalog difference analysis
10
+
11
+ Compute the difference between the proposed code and the base branch across a number of hosts. This is more than just a pass/fail check, as a human should review the results to ensure that the differences are expected.
12
+
13
+ - [Sample rspec file for catalog difference analysis](/examples/ci/puppet_catalog_diff_spec.rb)
@@ -0,0 +1,123 @@
1
+ # Dynamic Ignoring Based On Tags
2
+
3
+ Using the `--ignore-tags` command line option, it is possible to ignore all resources with particular Puppet tags. This allows dynamic ignoring of wrappers or other resources that are not of interest.
4
+
5
+ ## Getting Started
6
+
7
+ To use ignored tags, you first need to decide what the name of your tag will be. The standard is `ignored_octocatalog_diff`.
8
+
9
+ When you are writing Puppet code, you can tag a particular resource as being of no interest to `octocatalog-diff`.
10
+
11
+ ```
12
+ class foo {
13
+ file { '/etc/foo':
14
+ ensure => file,
15
+ source => 'puppet:///modules/foo/etc/foo',
16
+ tag => [ 'ignored_octocatalog_diff' ],
17
+ }
18
+ }
19
+ ```
20
+
21
+ You can also tag a resource that is a custom defined type.
22
+
23
+ ```
24
+ class foo {
25
+ foo::customfile { '/etc/foo':
26
+ source => 'puppet:///modules/foo/etc/foo',
27
+ tag => [ 'ignored_octocatalog_diff__foo__customfile' ],
28
+ }
29
+ }
30
+
31
+ define foo::customfile (
32
+ String $source,
33
+ ) {
34
+ file { $name:
35
+ ensure => file,
36
+ source => $source,
37
+ }
38
+ }
39
+ ```
40
+
41
+ Finally, you can tag an entire defined type.
42
+
43
+ ```
44
+ class foo {
45
+ foo::customfile { '/etc/foo':
46
+ source => 'puppet:///modules/foo/etc/foo',
47
+ }
48
+ }
49
+
50
+ define foo::customfile (
51
+ String $source,
52
+ ) {
53
+ tag 'ignored_octocatalog_diff__foo__customfile'
54
+
55
+ file { $name:
56
+ ensure => file,
57
+ source => $source,
58
+ }
59
+ }
60
+ ```
61
+
62
+ When octocatalog-diff processes the ignore-tag, it will ignore a resource if either of the following is true:
63
+
64
+ - The resource has a tag exactly matching the ignore-tag. For the default tag name, this means a resource has the tag `ignored_octocatalog_diff`.
65
+
66
+ - The resource has a tag that matches the ignore-tag joined to the type with two underscores (where the type is in lower case and non-alphanumeric characters are replaced with underscores). This means that when the ignore-tag is `ignored_octocatalog_diff`, octocatalog-diff would ignore a file resource with a tag of `ignored_octocatalog_diff__file`, but would not ignore an exec resource with that same tag.
67
+
68
+ The reasoning for the second syntax is explained in [caveats](#caveats).
69
+
70
+ ## Usage
71
+
72
+ To ignore one tag:
73
+
74
+ ```
75
+ octocatalog-diff --ignore-tags ignored_octocatalog_diff ...
76
+ ```
77
+
78
+ To ignore multiple tags:
79
+
80
+ ```
81
+ octocatalog-diff --ignore-tags ignored_octocatalog_diff --ignore-tags second_tag ...
82
+ ```
83
+
84
+ To disable all ignoring of tags:
85
+
86
+ ```
87
+ octocatalog-diff --no-ignore-tags ...
88
+ ```
89
+
90
+ ## Caveats
91
+
92
+ When you tag a resource or defined type, Puppet will propagate that tag to *all* descendent resources.
93
+
94
+ In this example, the tag `ignored_octocatalog_diff__foo__customfile` is propagated to the `foo::customfile` resource and to the file resource. However, octocatalog-diff will ignore only the `foo::customfile`, and will not ignore the file resource.
95
+
96
+ ```
97
+ define foo::customfile (
98
+ String $source,
99
+ ) {
100
+ tag 'ignored_octocatalog_diff__foo__customfile'
101
+
102
+ file { $name:
103
+ ensure => file,
104
+ source => $source,
105
+ }
106
+ }
107
+ ```
108
+
109
+ :warning: If you were to do the following, not only would changes to `foo::customfile` parameters be ignored, but changes to the file resource would be ignored as well! That's because both `foo::customfile` and the file would have the tag `ignored_octocatalog_diff`, because the tag set in the defined type propagates to all descendent resources.
110
+
111
+ ```
112
+ define foo::customfile (
113
+ String $source,
114
+ ) {
115
+ # DO NOT DO THIS!!!
116
+ tag 'ignored_octocatalog_diff'
117
+
118
+ file { $name:
119
+ ensure => file,
120
+ source => $source,
121
+ }
122
+ }
123
+ ```
@@ -0,0 +1,11 @@
1
+ # Enabling the future parser
2
+
3
+ The [future parser](https://docs.puppet.com/puppet/3.8/reference/experiments_future.html) is a feature in Puppet 3.8 designed to provide functionally identical to the Puppet language in Puppet 4.0.
4
+
5
+ You can use these options to enable the future parser for the "from" catalog, the "to" catalog, or both catalogs:
6
+
7
+ - `--parser-from future` will enable the future parser for the "from" catalog
8
+ - `--parser-to future` will enable the future parser for the "to" catalog
9
+ - `--parser future` will enable the future parser for both the "from" catalog and the "to" catalog
10
+
11
+ Note that you can also enable the future parser by creating a file named `environment.conf` in the base directory of your Puppet checkout. When `octocatalog-diff` computes the catalog from this directory, Puppet will read this file and act upon it accordingly.
@@ -0,0 +1,224 @@
1
+ # Ignoring certain changes from the command line
2
+
3
+ `octocatalog-diff` provides a means to ignore certain changes in the displayed output. You may choose to ignore a change because you know it has no effect on the system. Or perhaps you are aware that the change is being made (perhaps in many different places) and you want to suppress it so other changes will not be lost in the noise.
4
+
5
+ ## Built-in ignores
6
+
7
+ `octocatalog-diff` automatically ignores any changes to the following:
8
+
9
+ - Classes and class parameters. Classes themselves are structures to contain resources, but do not themselves trigger actions on agents. Resources in classes are reported on, but the actual classes themselves, and parameters associated with the classes, are not.
10
+ - Tags. Tags are useful for classification and collecting resources, but tags themselves do not trigger actions on agents. If you would like to see changes to tags, you can use `--no-ignore-tags`. Please note that tags are sorted alphabetically before comparison, so differences to the order of the tags will not ever show as a difference.
11
+ - Resource attributes: `before` and `require`. These attributes control ordering on the agent, but we have found that displaying them in the diff has little value because the target resources are not often seen. If you are looking to visualize your infrastructure, Puppet Enterprise [now has that feature](https://puppet.com/blog/visualize-your-infrastructure-models). Please note: `octocatalog-diff` does display changes to `subscribe` and `notify` parameters.
12
+
13
+ ## Ignoring via the `--ignore` command line option
14
+
15
+ If you specify multiple `--ignore` options, they are OR'd. In other words, if a change matches *any* of the ignored conditions, it is ignored.
16
+
17
+ ### Ignoring by type
18
+
19
+ If you wish to ignore all changes to a certain resource type, use this syntax. For example, if you wanted to ignore all changes to 'exec' you would use:
20
+
21
+ --ignore 'Exec[*]'
22
+
23
+ Or to ignore changes to a custom defined type, you would use:
24
+
25
+ --ignore 'Your::Custom::Type[*]'
26
+
27
+ The matching is case insensitive, so `--ignore Exec[*]` and `--ignore exec[*]` are equivalent.
28
+
29
+ ### Ignoring by type and title
30
+
31
+ If you wish to ignore all changes to a certain resource identified by its type and title, use this syntax. For example, to ignore all changes to your `/etc/motd` file you would use:
32
+
33
+ --ignore 'File[/etc/motd]'
34
+
35
+ You can use wildcards in the title. Wildcards can be placed at the beginning, in the middle, or at the end of the title. You can also use multiple wildcards. `*` is the only wildcard supported, and it matches 0 or more characters. For example:
36
+
37
+ --ignore 'File[*]' - Ignores all files
38
+ --ignore 'File[/etc/foo/*]' - Ignores all files in or under '/etc/foo'
39
+ --ignore 'File[*/foo]' - Ignores files named 'foo' anywhere in the file system
40
+ --ignore 'File[/etc/*/foo]' - Ignores files named 'foo' in subdirectories of '/etc/'
41
+ --ignore 'File[/etc/*/foo/*]' - Ignores all files under subdirectories named 'foo' under '/etc'
42
+
43
+ Note that unlike on a unix system, `*` here matches any character, including "dot files." Therefore `--ignore File[/home/joe/*]` *would* ignore changes made, for example, to `/home/joe/.bashrc`.
44
+
45
+ :warning: Do not put quotes of any kind in the ignore (e.g. `File['/etc/passwd']`) as these will be interpreted literally.
46
+
47
+ ### Ignoring by attribute
48
+
49
+ If you wish to ignore all changes to a particular attribute regardless of the resource with which it is associated, use this syntax. For example, if you wanted to ignore all changes to an attribute called `i_dont_care_about_this` you would use:
50
+
51
+ --ignore-attr 'i_dont_care_about_this'
52
+
53
+ That syntax will ignore a key `i_dont_care_about_this` *anywhere* it appears in the data structure -- top level key, last key, or something in between.
54
+
55
+ If you want more control over where in the data structure the key appears, you can use '::' to separate multiple layers. For example, if your resource looked like this:
56
+
57
+ {
58
+ "type": "File",
59
+ "title": "/tmp/foo",
60
+ "parameters": {
61
+ "owner": "root",
62
+ "i_dont_care_about_this": "foo bar"
63
+ }
64
+ }
65
+
66
+ You could use the following syntax to suppress `i_dont_care_about_this` only as it appears in the parameters hash using:
67
+
68
+ --ignore-attr 'parameters::i_dont_care_about_this'
69
+
70
+ If you want to specify that you are starting from the top of the data structure, prepend `::` to the attribute. For example:
71
+
72
+ --ignore-attr '::parameters::i_dont_care_about_this'
73
+
74
+ The difference between this syntax and the one appearing immediately before it is as follows. With the leading `::` it forces the attribute match to start at the top level of the data structure. Without the leading `::`, *any* place in the data structure where a key named `parameters` was a hash containing a key named `i_dont_care_about_this` would be matched. Typically there is not a deep level of nesting in Puppet catalogs so this distinction is minimal. However, multiple levels of nesting can occur when hashes are passed as parameters within Puppet manifests.
75
+
76
+ TIP: For most attributes you wish to ignore, you should start with `::parameters` which is the standard top-level data structure within each catalog resource. As such, the remaining examples in this section will use this syntax.
77
+
78
+ Functionally, `--ignore-attr 'FOO'` is equivalent to `--ignore '*[*]FOO'`, but that's less elegant. The prior example *could* be rewritten as:
79
+
80
+ --ignore '*[*]::parameters::i_dont_care_about_this'
81
+
82
+ ### Ignoring by type, title, and attribute
83
+
84
+ `octocatalog-diff` allows you to ignore attributes that belong only to a specified type, or type + title.
85
+
86
+ For example, maybe you want to ignore ownership changes to your `/tmp/foo` file. You could use the following syntax:
87
+
88
+ --ignore 'File[/tmp/foo]::parameters::owner'
89
+
90
+ You can use wildcards `*` in the resource title as described previously. For example, to ignore owner changes for all files in the `/tmp` directory you could use:
91
+
92
+ --ignore 'File[/tmp/*]::parameters::owner'
93
+
94
+ ### Ignoring by type, title, and attribute with conditions
95
+
96
+ These functions allow you to ignore attributes, but only if the values of the attributes themselves or nature of the changes satisfy certain conditions.
97
+
98
+ #### Ignoring additions and removals but not changes
99
+
100
+ You can ignore resources that were added to the catalog. This syntax will *not* display an entry for any file in `/tmp` that was brand new in the new catalog. However, if the file resource existed in the old catalog and something changed, that's a change and not an addition, so it will display. For example:
101
+
102
+ --ignore 'File[/tmp/*]+'
103
+
104
+ The above will suppress this change because it's strictly an addition:
105
+
106
+ + File[/tmp/brand-new-file]
107
+
108
+ The above will NOT suppress this change because the resource existed before and changed:
109
+
110
+ ~~~~~~~~
111
+ + File[/tmp/my-file] =>
112
+ parameters =>
113
+ owner =>
114
+ - root
115
+ + new-owner
116
+ ~~~~~~~~
117
+
118
+ Similarly, you can ignore resources that were entirely removed from the catalog.
119
+
120
+ --ignore 'File[/tmp/*]-'
121
+
122
+ And, you can ignore resources that were either entirely removed or entirely added:
123
+
124
+ ~~~~~~~~
125
+ --ignore 'File[/tmp/*]+-'
126
+ (or, equivalently)
127
+ --ignore 'File[/tmp/*]+' --ignore 'File[/tmp/*]-'
128
+ ~~~~~~~~
129
+
130
+ #### Ignoring for a specific value of an attribute
131
+
132
+ You can ignore changes to an attribute when the value of the attribute matches a specific string or pattern.
133
+
134
+ When you use this syntax, the tool will ignore the change if the specified value applies to the attribute in *either* the old catalog or the new catalog. To ignore all changes to file owners, if the file owner was root before or the file owner is now root, you could use the `=>` matcher:
135
+
136
+ --ignore 'File[/tmp/*]::parameters::owner=>root'
137
+
138
+ You can also use a regular expression. For example, to ignore changes if a file's content change includes "ice cream" you could use the `=~>` regular expression matcher:
139
+
140
+ ---ignore 'File[/tmp/*]::parameters::content=~>ice cream'
141
+
142
+ #### Ignoring attributes that were added or removed
143
+
144
+ Similar to ignoring resources that were added or removed, you can also ignore attributes that were added or removed by prefixing the attribute name with a `+` or `-`.
145
+
146
+ To ignore any new parameters named `foo` (i.e., where no attribute named `foo` was defined in the old catalog, but it is defined in the new catalog), you would use:
147
+
148
+ --ignore 'My::Custom::Resource[*]+::parameters::foo'
149
+
150
+ Similarly, to ignore the removal of the parameter named `foo` (i.e., where `foo` was defined in the old catalog, but is not defined in the new catalog), you would use:
151
+
152
+ --ignore 'My::Custom::Resource[*]-::parameters::foo'
153
+
154
+ It is possible to combine this condition with the attribute value check defined above. For example, to ignore a new parameter `foo` with value `bar`:
155
+
156
+ --ignore 'My::Custom::Resource[*]+::parameters::foo=>bar'
157
+
158
+ #### Ignoring attribute values but only in the new catalog or the old catalog
159
+
160
+ Commonly, you will wish to suppress changes if an attribute is a certain value in the new catalog (or perhaps, a certain value in the old catalog). Say for example that you want to ignore any files that are now owned by root, but you will want to know about files that were owned by root and are now owned by somebody else. `=>root` would match files that were owned by root in the old catalog too but changed to somebody else in the new catalog, so that is too broad.
161
+
162
+ The `=+>` operator performs a string match only in the new catalog, and `=->` performs a string match only in the new catalog. This will ignore any file resources under `/tmp` where the owner has changed, and the new owner is root:
163
+
164
+ --ignore 'File[/tmp/*]::parameters::owner=+>root'
165
+
166
+ As a similar example, perhaps you have terminated a user joe, and need to reassign ownership of his files to someone else. You want to ignore any files that were previously owned by joe, but you do want to know about files that you've accidentally reassigned *to* joe (because you don't believe there should be any). To ignore files owned by joe in the old catalog, where the new owner is someone other than joe:
167
+
168
+ --ignore 'File[/tmp/*]::parameters::owner=->joe'
169
+
170
+ If you need to use regular expressions, note that *changed lines* are preceded by `+` or `-` due to the `diff` implementation. More complicated, but equally functional, representations of the above commands are, respectively:
171
+
172
+ --ignore 'File[/tmp/*]::parameters::owner=~>^\+root$'
173
+
174
+ --ignore 'File[/tmp/*]::parameters::owner=~>^-joe$'
175
+
176
+ :warning: Be sure to escape your literal '+' in the regular expression!
177
+
178
+ Note that this syntax differs from `--ignore 'File[/tmp/*]+::...'` described in the prior section. The `+` or `-` between the title and the attribute indicates that the attribute must be brand new or completely removed; this will not ignore changes. Whereas using a `+` or `-` in the predicate of a string matcher will match changes between the catalogs.
179
+
180
+ If you want to ignore changes where the attribute value exactly matches certain value in the old catalog, and exactly matches a certain other value in the new catalog, this is possible using the encompassing regular expressions described in the next section. You cannot combine `=+>` and `=->` in the same ignore condition.
181
+
182
+ #### Ignoring attributes whose changes are encompassed by a regular expression
183
+
184
+ It is possible to ignore changes only if *all* changed lines are matched by a regular expression. This is useful to suppress expected changes to an attribute, while still surfacing unexpected changes.
185
+
186
+ As an example, consider that two catalogs defined the content of a file, which had this difference:
187
+
188
+ ~~~~~~~~
189
+ File[/tmp/foo] =>
190
+ parameters =>
191
+ content =>
192
+ @@ -1,4 +1,4 @@
193
+ # This file is managed by Puppet. DO NOT EDIT.
194
+ -This is the line in the old catalog that I do not care about
195
+ +This is the line in the new catalog that I do not care about
196
+ This line is very important
197
+ ~~~~~~~~
198
+
199
+ Suppose that you do not care to see this change. You can use the `=&>` operator to specify *one* regular expression that must match *all* lines that are changed. (You do not need to worry about the `@@ -1,4 +1,4 @@` line, as that's an artifact of the `diff` process, and is not considered in the analysis.)
200
+
201
+ One implementation of ignoring the line in question could be:
202
+
203
+ --ignore 'File[/tmp/foo]::parameters::content=&>^(-This is the line in the old catalog that I do not care about)|(\+This is the line in the new catalog that I do not care about)$'
204
+
205
+ If you aren't concerned about an edge case such as "This is the line in the new catalog that I do not care about" appearing in the old catalog, you could condense this to:
206
+
207
+ --ignore 'File[/tmp/foo]::parameters::content=&>^[\-\+]This is the line in the (old|new) catalog that I do not care about$'
208
+
209
+ Consider now that the change to the file looked like this instead:
210
+
211
+ ~~~~~~~~
212
+ File[/tmp/foo] =>
213
+ parameters =>
214
+ content =>
215
+ @@ -1,4 +1,4 @@
216
+ # This file is managed by Puppet. DO NOT EDIT.
217
+ -This is the line in the old catalog that I do not care about
218
+ +This is the line in the new catalog that I do not care about
219
+ -This line is very important
220
+ ~~~~~~~~
221
+
222
+ In this case, the very important line was removed from the catalog, and you want to know about this. Ignoring `File[/tmp/foo]::parameters::content` would have suppressed this (because all changes to that attribute are ignored). Also ignoring `File[/tmp/foo]::parameters::content=~>This is the line in the new catalog that I do not care about$` would have also suppressed this (because the regular expression was matched for *one* of the lines). However, the two examples with `=&>` in this section would *not* have suppressed this change, because it is no longer the case that *all* changes in the file matched the regular expression.
223
+
224
+ :warning: All lines are stripped of leading and trailing spaces before the regular expression match is tried. This stripping of whitespace is done *only* for this comparison stage, and does not affect the display of any results.