octocatalog-diff 1.6.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 90eb139ff8685aa8906b164f1d3bc869efce0a9a8b0711c4f5b575bcd7d9d18f
4
- data.tar.gz: 92b5fcd9820cff4e19e02d9748774627a3569d4b1775c321a15bfc8d5fb19bda
3
+ metadata.gz: b99c2e5da4209a2779ec55c745b43a274c0983f00bc5ec41452bf19636818f9a
4
+ data.tar.gz: 1ebb9bc86ff2ab9dab9e6529a2f862ddc15447c859d7e1e2120ef8e177220c58
5
5
  SHA512:
6
- metadata.gz: ab5c43c7a9de9d437ce4249b7cbe8b4d07b1cfc5b858deb4b26a2f1021245b49279e02ddc53f412e7d17f58bc27c461921f614650c20055cd11442f8b827e42c
7
- data.tar.gz: caa52478aa06d0b51ea00686281d21e808afd1c78330fb17a53492c092836f5000365d2ae1880f0aac5f5577c6ba7d9d27708ecd6f4d6c8f6a0440dd4243b398
6
+ metadata.gz: b9c7f405b7d219817088a1f29126335270245d5d1f8084a07e26b50b817adfb5b6019ed92edac55250ce611253cc418fee9a53a0cf9f065b73e3b89be1523809
7
+ data.tar.gz: 0054faec251c287be47947f73314fbcd30d5d3b4af240488fe97665247e5af7100561b908027a84dd9994853036a05330d82ab8da12ab2519437c5ec9a5101bc
data/.version CHANGED
@@ -1 +1 @@
1
- 1.6.0
1
+ 2.0.0
data/README.md CHANGED
@@ -23,7 +23,7 @@ There are some [limitations](doc/limitations.md) to a catalog-based approach, me
23
23
  `octocatalog-diff` is currently able to get catalogs by the following methods:
24
24
  - Compile catalog via the command line with a Puppet agent on your machine (as GitHub uses the tool internally)
25
25
  - Obtain catalog over the network from PuppetDB
26
- - Obtain catalog over the network using the API to query a Puppet Master / PuppetServer (Puppet 3.x and 4.x supported)
26
+ - Obtain catalog over the network using the API to query a Puppet Master / PuppetServer (Puppet 3.x through 6.x supported)
27
27
  - Read catalog from a JSON file
28
28
 
29
29
  ## Example
@@ -8,6 +8,16 @@
8
8
  </tr>
9
9
  </thead><tbody>
10
10
 
11
+ <tr valign=top>
12
+ <td>2.0.0</td>
13
+ <td>2020-01-12</td>
14
+ <li><a href="https://github.com/github/octocatalog-diff/pull/226">#226</a>: (Enhancement) Add Puppet 6 support</li>
15
+ <li><a href="https://github.com/github/octocatalog-diff/pull/228">#228</a>: (Enhancement) Add Puppetserver catalog v4 API support</li>
16
+ <li><a href="https://github.com/github/octocatalog-diff/pull/229">#229</a>: (Enhancement) Add support for PE package inventory facts</li>
17
+ <li><a href="https://github.com/github/octocatalog-diff/pull/230">#230</a>: (Enhancement) Add set quality comparison to ignore filter</li>
18
+ </td>
19
+ </tr>
20
+
11
21
  <tr valign=top>
12
22
  <td>1.6.0</td>
13
23
  <td>2019-10-31</td>
@@ -222,3 +222,13 @@ File[/tmp/foo] =>
222
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
223
 
224
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.
225
+
226
+ #### Ignoring attributes which have identical elements but in arbitrary order
227
+
228
+ You can ignore attributes where both the values in both the old and new catalogs are arrays and the arrays
229
+ contain identical elements but in arbitrary order. Basically, you can ignore a parameter where the values
230
+ have set equality.
231
+
232
+ To ignore any parameters named `foo` with values having set equality, you would use:
233
+
234
+ --ignore 'My::Custom::Resource[*]::parameters::foo=s>='
@@ -8,7 +8,11 @@ Please note the following caveats:
8
8
 
9
9
  0. You will need to deploy your Puppet code to an environment on your Puppet Master prior to running `octocatalog-diff` for that environment. `octocatalog-diff` does not deploy code for you.
10
10
 
11
- 0. You will need to configure authorization for one or more whitelisted certificates on your Puppet Master. The default permissions allow a node to retrieve its own catalog via the API, but you need a certificate for `octocatalog-diff` that permits it to retrieve any catalog. See the [Certificate authorization](#certificate-authorization) section below.
11
+ 0. You will need to configure authorization for one or more whitelisted certificates on your Puppet Master. The default permissions allow a node to retrieve its own catalog via the API, but you need a certificate for `octocatalog-diff` that permits it to retrieve any catalog. See the [Certificate authorization](#certificate-authorization) section below. If you are using Puppet Enterprise and use
12
+ the Puppet Master v4 API you may also use a Puppet Enterprise RBAC token. The user owning the token will need the "Puppet Server Compile catalogs for remote nodes" permission.
13
+ See the [PE RBAC Token Authorization](#pe-rbac-token-authorization) section below.
14
+
15
+ 0. If you are using the v2 or v3 PuppetServer APIs with Octocatalog-Diff to compile catalogs, then those catalogs and facts will be automatically stored in PuppetDB. However, when using the v4 PuppetServer API with Octocatalog-Diff, facts and catalogs are *not* automatically stored in PuppetDB - persistence is optional and may be enabled with the appropriate Octocatalog-Diff CLI flag. If your environment depends on the accuracy of exported resources or facts in PuppetDB, you may wish to upgrade and use the V4 API, to avoid unintentional side-effects.
12
16
 
13
17
  ## Command line options
14
18
 
@@ -18,11 +22,15 @@ The following command line options are used to retrieve a catalog from a Puppet
18
22
  | ------ | ----------- |
19
23
  | `-f ENVIRONMENT` | Environment name to use for the "from" catalog |
20
24
  | `-t ENVIRONMENT` | Environment name to use for the "to" catalog |
21
- | `--puppet-master HOSTNAME:PORT | The hostname and port number of the Puppet Master. (By default the port used by Puppet Master is 8140.) |
22
- | `--puppet-master-api-version VERSION | The API version used by the Puppet Master. API versions 2 and 3 are supported. Puppet Master 3.x uses API version 2, and the PuppetServer for Puppet 4.x uses API version 3. By default, API version 3 is used, so you only need to set this option if you are using Puppet Master 3.x. |
25
+ | `--puppet-master HOSTNAME:PORT` | The hostname and port number of the Puppet Master. (By default the port used by Puppet Master is 8140.) |
26
+ | `--puppet-master-api-version VERSION` | The API version used by the Puppet Master. API versions 2, 3,and 4 are supported. Puppet Master 3.x uses API version 2, and the PuppetServer for Puppet 4.x uses API version 3. PuppetServer 6.3.0 introduced the optional use of the v4 API but still fully supports the v3 API. By default, API version 3 is used, so you only need to set this option if you are using Puppet Master 3.x or wish to use the newer v4 API with PuppetServer 6. |
23
27
  | `--puppet-master-ssl-ca PATH` | Path to the CA certificate (public portion of certificate only) for your Puppet Master. This file will be on your Puppet Master and all Puppet agents. You can find it by running `puppet config print cacert` on any Puppet-managed host. |
24
- | `--puppet-master-ssl-client-cert PATH` | Path to the client certificate. Please see the section below on certificate authentication. |
25
- | `--puppet-master-ssl-client-key PATH` | Path to the client private key. Please see the section below on certificate authentication. |
28
+ | `--puppet-master-ssl-client-cert PATH` | Path to the client certificate. Please see the section below on certificate authentication. This can be omitted if using PE RBAC token based auth with the v4 API. |
29
+ | `--puppet-master-ssl-client-key PATH` | Path to the client private key. Please see the section below on certificate authentication. This can be omitted if using PE RBAC token based auth with the v4 API. |
30
+ | `--puppet-master-token STRING` | A PE RBAC token used to authenticate a v4 catalog compile, in lieu of using certificate authentication. Please see the section below on token authentication. |
31
+ | `--puppet-master-token-file PATH` | A path to a file containing a PE RBAC token used to authenticate a v4 catalog compile, in lieu of using certificate authentication. If this and `--puppet-master-token` are both specified, `--puppet-master-token` will be used instead. Please see the section below on token authentication. |
32
+ | `--puppet-master-update-catalog` | When using the v4 API, instruct the PuppetServer to update the catalog generated from the compile in its PuppetDB instance. When using v2 and v3 APIs the catalog is always updated and this option is ignored. |
33
+ | `--puppet-master-update-facts` | When using the v4 API, instruct the PuppetServer to update the facts used during the compile in its PuppetDB instance. When using v2 and v3 APIs the facts are always updated and this option is ignored. |
26
34
 
27
35
  If you wish to use a different Puppet Master to compile the "to" and "from" catalogs, you may prefix any of the `--puppet-master...` options with `to` or `from`. For example, perhaps you are testing an upgrade from Puppet 3.x to 4.x. You could use:
28
36
 
@@ -48,3 +56,13 @@ allow $1
48
56
  ```
49
57
 
50
58
  Please follow the instructions for the version of Puppet Master, PuppetServer, or Puppet Enterprise that you are using in order to generate and authorize the certificates.
59
+
60
+ ## PE RBAC Token authorization
61
+
62
+ In newer versions of Puppet Enterprise you can authenticate using a valid PE RBAC token with appropriate permissions as long as it is authorized in the PuppetServer `auth.conf` file.
63
+
64
+ By default this permission is enabled and controlled by the `puppet_enterprise::master::tk_authz::allow_rbac_catalog_compile` Hiera setting.
65
+
66
+ The user the token was issued to must have the `puppetserver:compile_catalogs:*` permission.
67
+
68
+ Note: A Puppet catalog may contain unencrypted secrets, even ones marked as `Sensitive`. In order to perform its job, Octocatalog-Diff needs access to the catalog. By granting a user the above RBAC permission you are granting them the ability to retrieve and view the complete catalog resulting from a compile, including any included secrets.
@@ -67,3 +67,11 @@ SSL support is enabled via any of the `--puppetdb-ssl-...` command line options
67
67
  - The CA certificate should be the public certificate of the CA that signed your PuppetDB server's certificate. This file can be found in `/etc/puppetlabs/puppetdb/ssl/ca.pem` on a PuppetDB server. Since this is a public certificate, it is safe (and recommended) to distribute this file to any clients that may connect to this PuppetDB instance.
68
68
 
69
69
  - The client keypair (key, certificate, and optionally password) should be generated individually for each client. You should NOT copy SSL keypairs from your PuppetDB server (or anywhere else) to your clients. If you are using `octocatalog-diff` on a system that is managed by Puppet, you may wish to use the same SSL credentials that the system uses to authenticate to Puppet. With recent versions of the Puppet agent, those certificates are found in `/etc/puppetlabs/puppet/ssl`.
70
+
71
+ # Puppet Enterprise PuppetDB Package Inventory
72
+
73
+ Puppet Enterprise customers have an optional package inventory feature which can be enabled. When this feature is enabled an inventory of all system packages
74
+ is performed and uploaded as a fact which is then processed and stored independently of the normal Facter data in PuppetDB. Most environments won't need
75
+ to replicate the package inventory facts for testing with Octocatalog-Diff but if you want the package inventory data (if present) to be included
76
+ in the facts retrieved from PuppetDB by Octocatalog-Diff you should specify the `--puppetdb-package-inventory` flag. When enabled, this flag will instruct
77
+ Octocatalog-Diff to retrieve any package data found for a node from PuppetDB and include it in the facts used during the Octocatalog-Diff compile.
@@ -37,6 +37,8 @@ Usage: octocatalog-diff [command line options]
37
37
  --fact-file STRING Override fact globally
38
38
  --to-fact-file STRING Override fact for the to branch
39
39
  --from-fact-file STRING Override fact for the from branch
40
+ --[no-]puppetdb-package-inventory
41
+ Include Puppet Enterprise package inventory data, if found
40
42
  --save-catalog STRING Save intermediate catalogs into files globally
41
43
  --to-save-catalog STRING Save intermediate catalogs into files for the to branch
42
44
  --from-save-catalog STRING Save intermediate catalogs into files for the from branch
@@ -87,7 +89,18 @@ Usage: octocatalog-diff [command line options]
87
89
  --puppet-binary STRING Full path to puppet binary globally
88
90
  --to-puppet-binary STRING Full path to puppet binary for the to branch
89
91
  --from-puppet-binary STRING Full path to puppet binary for the from branch
92
+ --puppet-master-token-file STRING
93
+ File containing PE RBAC token to authenticate to the Puppetserver API v4 globally
94
+ --to-puppet-master-token-file STRING
95
+ File containing PE RBAC token to authenticate to the Puppetserver API v4 for the to branch
96
+ --from-puppet-master-token-file STRING
97
+ File containing PE RBAC token to authenticate to the Puppetserver API v4 for the from branch
90
98
  --facts-terminus STRING Facts terminus: one of yaml, facter
99
+ --puppet-master-token STRING PE RBAC token to authenticate to the Puppetserver API v4 globally
100
+ --to-puppet-master-token STRING
101
+ PE RBAC token to authenticate to the Puppetserver API v4 for the to branch
102
+ --from-puppet-master-token STRING
103
+ PE RBAC token to authenticate to the Puppetserver API v4 for the from branch
91
104
  --puppetdb-token TOKEN Token to access the PuppetDB API
92
105
  --puppetdb-token-file PATH Path containing token for PuppetDB API, relative or absolute
93
106
  --puppetdb-url URL PuppetDB base URL
@@ -111,11 +124,23 @@ Usage: octocatalog-diff [command line options]
111
124
  --to-puppet-master STRING Hostname or Hostname:PortNumber for Puppet Master for the to branch
112
125
  --from-puppet-master STRING Hostname or Hostname:PortNumber for Puppet Master for the from branch
113
126
  --puppet-master-api-version STRING
114
- Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x) globally
127
+ Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x, 4 for Puppet Server >= 6.3.0) globally
115
128
  --to-puppet-master-api-version STRING
116
- Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x) for the to branch
129
+ Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x, 4 for Puppet Server >= 6.3.0) for the to branch
117
130
  --from-puppet-master-api-version STRING
118
- Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x) for the from branch
131
+ Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x, 4 for Puppet Server >= 6.3.0) for the from branch
132
+ --[no-]puppet-master-update-catalog
133
+ Update catalog in PuppetDB when using Puppetmaster API version 4 globally
134
+ --[no-]to-puppet-master-update-catalog
135
+ Update catalog in PuppetDB when using Puppetmaster API version 4 for the to branch
136
+ --[no-]from-puppet-master-update-catalog
137
+ Update catalog in PuppetDB when using Puppetmaster API version 4 for the from branch
138
+ --[no-]puppet-master-update-facts
139
+ Update facts in PuppetDB when using Puppetmaster API version 4 globally
140
+ --[no-]to-puppet-master-update-facts
141
+ Update facts in PuppetDB when using Puppetmaster API version 4 for the to branch
142
+ --[no-]from-puppet-master-update-facts
143
+ Update facts in PuppetDB when using Puppetmaster API version 4 for the from branch
119
144
  --puppet-master-ssl-ca STRING
120
145
  Full path to CA certificate that signed the Puppet Master certificate globally
121
146
  --to-puppet-master-ssl-ca STRING
@@ -719,7 +744,7 @@ Puppet control repo template, the value of this should be 'hieradata', which is
719
744
  <pre><code>--from-puppet-master-api-version STRING</code></pre>
720
745
  </td>
721
746
  <td valign=top>
722
- Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x) for the from branch
747
+ Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x, 4 for Puppet Server >= 6.3.0) for the from branch
723
748
  </td>
724
749
  <td valign=top>
725
750
  Specify the API version to use for the Puppet Master. This makes it possible to authenticate to a
@@ -781,6 +806,32 @@ This timeout is specified in seconds. (<a href="../lib/octocatalog-diff/cli/opti
781
806
  </td>
782
807
  </tr>
783
808
 
809
+ <tr>
810
+ <td valign=top>
811
+ <pre><code>--from-puppet-master-token STRING</code></pre>
812
+ </td>
813
+ <td valign=top>
814
+ PE RBAC token to authenticate to the Puppetserver API v4 for the from branch
815
+ </td>
816
+ <td valign=top>
817
+ Specify a PE RBAC token used to authenticate to Puppetserver for v4
818
+ catalog API calls. (<a href="../lib/octocatalog-diff/cli/options/puppet_master_token.rb">puppet_master_token.rb</a>)
819
+ </td>
820
+ </tr>
821
+
822
+ <tr>
823
+ <td valign=top>
824
+ <pre><code>--from-puppet-master-token-file STRING</code></pre>
825
+ </td>
826
+ <td valign=top>
827
+ File containing PE RBAC token to authenticate to the Puppetserver API v4 for the from branch
828
+ </td>
829
+ <td valign=top>
830
+ Specify a path to a file containing a PE RBAC token used to authenticate to the
831
+ Puppetserver for a v4 catalog API call. (<a href="../lib/octocatalog-diff/cli/options/puppet_master_token_file.rb">puppet_master_token_file.rb</a>)
832
+ </td>
833
+ </tr>
834
+
784
835
  <tr>
785
836
  <td valign=top>
786
837
  <pre><code>--from-puppetdb
@@ -1239,7 +1290,7 @@ to work correctly. (<a href="../lib/octocatalog-diff/cli/options/preserve_enviro
1239
1290
  <pre><code>--puppet-master-api-version STRING</code></pre>
1240
1291
  </td>
1241
1292
  <td valign=top>
1242
- Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x) globally
1293
+ Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x, 4 for Puppet Server >= 6.3.0) globally
1243
1294
  </td>
1244
1295
  <td valign=top>
1245
1296
  Specify the API version to use for the Puppet Master. This makes it possible to authenticate to a
@@ -1301,6 +1352,32 @@ This timeout is specified in seconds. (<a href="../lib/octocatalog-diff/cli/opti
1301
1352
  </td>
1302
1353
  </tr>
1303
1354
 
1355
+ <tr>
1356
+ <td valign=top>
1357
+ <pre><code>--puppet-master-token STRING</code></pre>
1358
+ </td>
1359
+ <td valign=top>
1360
+ PE RBAC token to authenticate to the Puppetserver API v4 globally
1361
+ </td>
1362
+ <td valign=top>
1363
+ Specify a PE RBAC token used to authenticate to Puppetserver for v4
1364
+ catalog API calls. (<a href="../lib/octocatalog-diff/cli/options/puppet_master_token.rb">puppet_master_token.rb</a>)
1365
+ </td>
1366
+ </tr>
1367
+
1368
+ <tr>
1369
+ <td valign=top>
1370
+ <pre><code>--puppet-master-token-file STRING</code></pre>
1371
+ </td>
1372
+ <td valign=top>
1373
+ File containing PE RBAC token to authenticate to the Puppetserver API v4 globally
1374
+ </td>
1375
+ <td valign=top>
1376
+ Specify a path to a file containing a PE RBAC token used to authenticate to the
1377
+ Puppetserver for a v4 catalog API call. (<a href="../lib/octocatalog-diff/cli/options/puppet_master_token_file.rb">puppet_master_token_file.rb</a>)
1378
+ </td>
1379
+ </tr>
1380
+
1304
1381
  <tr>
1305
1382
  <td valign=top>
1306
1383
  <pre><code>--puppetdb-api-version N</code></pre>
@@ -1314,6 +1391,23 @@ the default. (<a href="../lib/octocatalog-diff/cli/options/puppetdb_api_version.
1314
1391
  </td>
1315
1392
  </tr>
1316
1393
 
1394
+ <tr>
1395
+ <td valign=top>
1396
+ <pre><code>--puppetdb-package-inventory
1397
+ --no-puppetdb-package-inventory </code></pre>
1398
+ </td>
1399
+ <td valign=top>
1400
+ Include Puppet Enterprise package inventory data, if found
1401
+ </td>
1402
+ <td valign=top>
1403
+ When pulling facts from PuppetDB in a Puppet Enterprise environment, also include
1404
+ the Puppet Enterprise Package Inventory data in the fact results, if available.
1405
+ Generally you should not need to specify this, but including the package inventory
1406
+ data will produce a more accurate set of input facts for environments using
1407
+ package inventory. (<a href="../lib/octocatalog-diff/cli/options/puppetdb_package_inventory.rb">puppetdb_package_inventory.rb</a>)
1408
+ </td>
1409
+ </tr>
1410
+
1317
1411
  <tr>
1318
1412
  <td valign=top>
1319
1413
  <pre><code>--puppetdb-ssl-ca FILENAME</code></pre>
@@ -1687,7 +1781,7 @@ Puppet control repo template, the value of this should be 'hieradata', which is
1687
1781
  <pre><code>--to-puppet-master-api-version STRING</code></pre>
1688
1782
  </td>
1689
1783
  <td valign=top>
1690
- Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x) for the to branch
1784
+ Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x, 4 for Puppet Server >= 6.3.0) for the to branch
1691
1785
  </td>
1692
1786
  <td valign=top>
1693
1787
  Specify the API version to use for the Puppet Master. This makes it possible to authenticate to a
@@ -1749,6 +1843,32 @@ This timeout is specified in seconds. (<a href="../lib/octocatalog-diff/cli/opti
1749
1843
  </td>
1750
1844
  </tr>
1751
1845
 
1846
+ <tr>
1847
+ <td valign=top>
1848
+ <pre><code>--to-puppet-master-token STRING</code></pre>
1849
+ </td>
1850
+ <td valign=top>
1851
+ PE RBAC token to authenticate to the Puppetserver API v4 for the to branch
1852
+ </td>
1853
+ <td valign=top>
1854
+ Specify a PE RBAC token used to authenticate to Puppetserver for v4
1855
+ catalog API calls. (<a href="../lib/octocatalog-diff/cli/options/puppet_master_token.rb">puppet_master_token.rb</a>)
1856
+ </td>
1857
+ </tr>
1858
+
1859
+ <tr>
1860
+ <td valign=top>
1861
+ <pre><code>--to-puppet-master-token-file STRING</code></pre>
1862
+ </td>
1863
+ <td valign=top>
1864
+ File containing PE RBAC token to authenticate to the Puppetserver API v4 for the to branch
1865
+ </td>
1866
+ <td valign=top>
1867
+ Specify a path to a file containing a PE RBAC token used to authenticate to the
1868
+ Puppetserver for a v4 catalog API call. (<a href="../lib/octocatalog-diff/cli/options/puppet_master_token_file.rb">puppet_master_token_file.rb</a>)
1869
+ </td>
1870
+ </tr>
1871
+
1752
1872
  <tr>
1753
1873
  <td valign=top>
1754
1874
  <pre><code>--to-save-catalog STRING</code></pre>
@@ -340,7 +340,8 @@ module OctocatalogDiff
340
340
  # =-> Attribute must have been removed and equal this
341
341
  # =~> Change must match regexp (one line of change matching is sufficient)
342
342
  # =&> Change must match regexp (all lines of change MUST match regexp)
343
- if rule_attr =~ /\A(.+?)(=[\-\+~&]?>)(.+)/m
343
+ # =s> Change must be array and contain identical elements, ignoring order
344
+ if rule_attr =~ /\A(.+?)(=[\-\+~&s]?>)(.+)/m
344
345
  rule_attr = Regexp.last_match(1)
345
346
  operator = Regexp.last_match(2)
346
347
  value = Regexp.last_match(3)
@@ -361,6 +362,9 @@ module OctocatalogDiff
361
362
  raise RegexpError, "Invalid ignore regexp for #{key}: #{exc.message}"
362
363
  end
363
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) }
364
368
  end
365
369
  end
366
370
 
@@ -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.
@@ -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
@@ -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
@@ -103,6 +103,7 @@ module OctocatalogDiff
103
103
  datatype = opts.fetch(:datatype, '')
104
104
  return option_globally_or_per_branch_string(opts) if datatype.is_a?(String)
105
105
  return option_globally_or_per_branch_array(opts) if datatype.is_a?(Array)
106
+ return option_globally_or_per_branch_boolean(opts) if datatype.is_a?(TrueClass) || datatype.is_a?(FalseClass)
106
107
  raise ArgumentError, "option_globally_or_per_branch not equipped to handle #{datatype.class}"
107
108
  end
108
109
 
@@ -177,6 +178,40 @@ module OctocatalogDiff
177
178
  end
178
179
  end
179
180
 
181
+ # See description of `option_globally_or_per_branch`. This implements the logic for a boolean value.
182
+ # @param :parser [OptionParser object] The OptionParser argument
183
+ # @param :options [Hash] Options hash being constructed; this is modified in this method.
184
+ # @param :cli_name [String] Name of option on command line (e.g. puppet-binary)
185
+ # @param :option_name [Symbol] Name of option in the options hash (e.g. :puppet_binary)
186
+ # @param :desc [String] Description of option on the command line; will have "for the XX branch" appended
187
+ def self.option_globally_or_per_branch_boolean(opts)
188
+ parser = opts.fetch(:parser)
189
+ options = opts.fetch(:options)
190
+ cli_name = opts.fetch(:cli_name)
191
+ option_name = opts.fetch(:option_name)
192
+ desc = opts.fetch(:desc)
193
+
194
+ flag = cli_name
195
+ from_option = "from_#{option_name}".to_sym
196
+ to_option = "to_#{option_name}".to_sym
197
+ parser.on("--[no-]#{flag}", "#{desc} globally") do |x|
198
+ translated = translate_option(opts[:translator], x)
199
+ options[to_option] = translated
200
+ options[from_option] = translated
201
+ post_process(opts[:post_process], options)
202
+ end
203
+ parser.on("--[no-]to-#{flag}", "#{desc} for the to branch") do |x|
204
+ translated = translate_option(opts[:translator], x)
205
+ options[to_option] = translated
206
+ post_process(opts[:post_process], options)
207
+ end
208
+ parser.on("--[no-]from-#{flag}", "#{desc} for the from branch") do |x|
209
+ translated = translate_option(opts[:translator], x)
210
+ options[from_option] = translated
211
+ post_process(opts[:post_process], options)
212
+ end
213
+ end
214
+
180
215
  # If a validator was provided, run the validator on the supplied value. The validator is expected to
181
216
  # throw an error if there is a problem. Note that the validator runs *before* the translator if both
182
217
  # a validator and translator are supplied.
@@ -14,8 +14,8 @@ OctocatalogDiff::Cli::Options::Option.newoption(:puppet_master_api_version) do
14
14
  options: options,
15
15
  cli_name: 'puppet-master-api-version',
16
16
  option_name: 'puppet_master_api_version',
17
- desc: 'Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x)',
18
- validator: ->(x) { x =~ /^[23]$/ || raise(ArgumentError, 'Only API versions 2 and 3 are supported') },
17
+ desc: 'Puppet Master API version (2 for Puppet 3.x, 3 for Puppet 4.x, 4 for Puppet Server >= 6.3.0)',
18
+ validator: ->(x) { x =~ /^[234]$/ || raise(ArgumentError, 'Only API versions 2, 3, and 4 are supported') },
19
19
  translator: ->(x) { x.to_i }
20
20
  )
21
21
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Specify a PE RBAC token used to authenticate to Puppetserver for v4
4
+ # catalog API calls.
5
+ # @param parser [OptionParser object] The OptionParser argument
6
+ # @param options [Hash] Options hash being constructed; this is modified in this method.
7
+ OctocatalogDiff::Cli::Options::Option.newoption(:puppet_master_token) do
8
+ has_weight 310
9
+
10
+ def parse(parser, options)
11
+ OctocatalogDiff::Cli::Options.option_globally_or_per_branch(
12
+ parser: parser,
13
+ options: options,
14
+ datatype: '',
15
+ cli_name: 'puppet-master-token',
16
+ option_name: 'puppet_master_token',
17
+ desc: 'PE RBAC token to authenticate to the Puppetserver API v4'
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Specify a path to a file containing a PE RBAC token used to authenticate to the
4
+ # Puppetserver for a v4 catalog API call.
5
+ # @param parser [OptionParser object] The OptionParser argument
6
+ # @param options [Hash] Options hash being constructed; this is modified in this method.
7
+ OctocatalogDiff::Cli::Options::Option.newoption(:puppet_master_token_file) do
8
+ has_weight 300
9
+
10
+ def parse(parser, options)
11
+ OctocatalogDiff::Cli::Options.option_globally_or_per_branch(
12
+ parser: parser,
13
+ options: options,
14
+ datatype: '',
15
+ cli_name: 'puppet-master-token-file',
16
+ option_name: 'puppet_master_token_file',
17
+ desc: 'File containing PE RBAC token to authenticate to the Puppetserver API v4',
18
+ translator: ->(x) { x.start_with?('/', '~') ? x : File.join(options[:basedir], x) },
19
+ post_process: lambda do |opts|
20
+ %w(to from).each do |prefix|
21
+ fileopt = "#{prefix}_puppet_master_token_file".to_sym
22
+ tokenopt = "#{prefix}_puppet_master_token".to_sym
23
+
24
+ tokenfile = opts[fileopt]
25
+ next if tokenfile.nil?
26
+
27
+ raise(Errno::ENOENT, "Token file #{tokenfile} is not readable") unless File.readable?(tokenfile)
28
+
29
+ token = File.read(tokenfile).strip
30
+ opts[tokenopt] ||= token
31
+ end
32
+ end
33
+ )
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Specify if, when using the Puppetserver v4 catalog API, the Puppetserver should
4
+ # update the catalog in PuppetDB.
5
+ # @param parser [OptionParser object] The OptionParser argument
6
+ # @param options [Hash] Options hash being constructed; this is modified in this method.
7
+ OctocatalogDiff::Cli::Options::Option.newoption(:puppet_master_update_catalog) do
8
+ has_weight 320
9
+
10
+ def parse(parser, options)
11
+ OctocatalogDiff::Cli::Options.option_globally_or_per_branch(
12
+ parser: parser,
13
+ options: options,
14
+ datatype: false,
15
+ cli_name: 'puppet-master-update-catalog',
16
+ option_name: 'puppet_master_update_catalog',
17
+ desc: 'Update catalog in PuppetDB when using Puppetmaster API version 4'
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Specify if, when using the Puppetserver v4 catalog API, the Puppetserver should
4
+ # update the facts in PuppetDB.
5
+ # @param parser [OptionParser object] The OptionParser argument
6
+ # @param options [Hash] Options hash being constructed; this is modified in this method.
7
+ OctocatalogDiff::Cli::Options::Option.newoption(:puppet_master_update_facts) do
8
+ has_weight 320
9
+
10
+ def parse(parser, options)
11
+ OctocatalogDiff::Cli::Options.option_globally_or_per_branch(
12
+ parser: parser,
13
+ options: options,
14
+ datatype: false,
15
+ cli_name: 'puppet-master-update-facts',
16
+ option_name: 'puppet_master_update_facts',
17
+ desc: 'Update facts in PuppetDB when using Puppetmaster API version 4'
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # When pulling facts from PuppetDB in a Puppet Enterprise environment, also include
4
+ # the Puppet Enterprise Package Inventory data in the fact results, if available.
5
+ # Generally you should not need to specify this, but including the package inventory
6
+ # data will produce a more accurate set of input facts for environments using
7
+ # package inventory.
8
+ # @param parser [OptionParser object] The OptionParser argument
9
+ # @param options [Hash] Options hash being constructed; this is modified in this method.
10
+ OctocatalogDiff::Cli::Options::Option.newoption(:puppetdb_package_inventory) do
11
+ has_weight 150
12
+
13
+ def parse(parser, options)
14
+ parser.on('--[no-]puppetdb-package-inventory', 'Include Puppet Enterprise package inventory data, if found') do |x|
15
+ options[:puppetdb_package_inventory] = x
16
+ end
17
+ end
18
+ end
@@ -36,6 +36,7 @@ module OctocatalogDiff
36
36
  exception_class = nil
37
37
  exception_message = nil
38
38
  obj_to_return = nil
39
+ packages = nil
39
40
  (retries + 1).times do
40
41
  begin
41
42
  result = puppetdb.get(uri)
@@ -61,8 +62,48 @@ module OctocatalogDiff
61
62
  exception_message = "Fact retrieval failed for node #{node} from PuppetDB (#{exc.message})"
62
63
  end
63
64
  end
64
- return obj_to_return unless obj_to_return.nil?
65
- raise exception_class, exception_message
65
+
66
+ raise exception_class, exception_message if obj_to_return.nil?
67
+
68
+ return obj_to_return if puppetdb_api_version < 4 || (!options[:puppetdb_package_inventory])
69
+
70
+ (retries + 1).times do
71
+ begin
72
+ result = puppetdb.get("/pdb/query/v4/package-inventory/#{node}")
73
+ packages = {}
74
+ result.each do |pkg|
75
+ key = "#{pkg['package_name']}+#{pkg['provider']}"
76
+ # Need to handle the situation where a package has multiple versions installed.
77
+ # The _puppet_inventory_1 hash lists them separated by "; ".
78
+ if packages.key?(key)
79
+ packages[key]['version'] += "; #{pkg['version']}"
80
+ else
81
+ packages[key] = pkg
82
+ end
83
+ end
84
+ break
85
+ rescue OctocatalogDiff::Errors::PuppetDBConnectionError => exc
86
+ exception_class = OctocatalogDiff::Errors::FactSourceError
87
+ exception_message = "Package inventory retrieval failed (#{exc.class}) (#{exc.message})"
88
+ # This is not expected to occur, but we'll leave it just in case. A query to package-inventory
89
+ # for a non-existant node returns a 200 OK with an empty list of packages:
90
+ rescue OctocatalogDiff::Errors::PuppetDBNodeNotFoundError
91
+ packages = {}
92
+ rescue OctocatalogDiff::Errors::PuppetDBGenericError => exc
93
+ exception_class = OctocatalogDiff::Errors::FactRetrievalError
94
+ exception_message = "Package inventory retrieval failed for node #{node} from PuppetDB (#{exc.message})"
95
+ end
96
+ end
97
+
98
+ raise exception_class, exception_message if packages.nil?
99
+
100
+ unless packages.empty?
101
+ obj_to_return['values']['_puppet_inventory_1'] = {
102
+ 'packages' => packages.values.map { |pkg| [pkg['package_name'], pkg['version'], pkg['provider']] }
103
+ }
104
+ end
105
+
106
+ obj_to_return
66
107
  end
67
108
  end
68
109
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: octocatalog-diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub, Inc.
8
8
  - Kevin Paulisse
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-10-31 00:00:00.000000000 Z
12
+ date: 2021-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: diffy
@@ -358,7 +358,12 @@ files:
358
358
  - lib/octocatalog-diff/cli/options/puppet_master_ssl_client_cert.rb
359
359
  - lib/octocatalog-diff/cli/options/puppet_master_ssl_client_key.rb
360
360
  - lib/octocatalog-diff/cli/options/puppet_master_timeout.rb
361
+ - lib/octocatalog-diff/cli/options/puppet_master_token.rb
362
+ - lib/octocatalog-diff/cli/options/puppet_master_token_file.rb
363
+ - lib/octocatalog-diff/cli/options/puppet_master_update_catalog.rb
364
+ - lib/octocatalog-diff/cli/options/puppet_master_update_facts.rb
361
365
  - lib/octocatalog-diff/cli/options/puppetdb_api_version.rb
366
+ - lib/octocatalog-diff/cli/options/puppetdb_package_inventory.rb
362
367
  - lib/octocatalog-diff/cli/options/puppetdb_ssl_ca.rb
363
368
  - lib/octocatalog-diff/cli/options/puppetdb_ssl_client_cert.rb
364
369
  - lib/octocatalog-diff/cli/options/puppetdb_ssl_client_key.rb
@@ -405,7 +410,7 @@ homepage: https://github.com/github/octocatalog-diff
405
410
  licenses:
406
411
  - MIT
407
412
  metadata: {}
408
- post_install_message:
413
+ post_install_message:
409
414
  rdoc_options: []
410
415
  require_paths:
411
416
  - lib
@@ -420,8 +425,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
420
425
  - !ruby/object:Gem::Version
421
426
  version: '0'
422
427
  requirements: []
423
- rubygems_version: 3.0.6
424
- signing_key:
428
+ rubygems_version: 3.0.3
429
+ signing_key:
425
430
  specification_version: 4
426
431
  summary: Compile Puppet catalogs from 2 branches, versions, etc., and compare them.
427
432
  test_files: []