puppet 6.21.1-x64-mingw32 → 6.22.1-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +24 -18
  4. data/ext/project_data.yaml +2 -2
  5. data/lib/puppet/application/ssl.rb +11 -0
  6. data/lib/puppet/defaults.rb +22 -2
  7. data/lib/puppet/environments.rb +16 -1
  8. data/lib/puppet/face/facts.rb +128 -30
  9. data/lib/puppet/file_system/memory_file.rb +8 -1
  10. data/lib/puppet/file_system/windows.rb +2 -0
  11. data/lib/puppet/functions/partition.rb +8 -0
  12. data/lib/puppet/indirector/facts/facter.rb +24 -3
  13. data/lib/puppet/network/formats.rb +67 -0
  14. data/lib/puppet/network/http/factory.rb +4 -0
  15. data/lib/puppet/provider/package/dnfmodule.rb +1 -1
  16. data/lib/puppet/provider/service/systemd.rb +1 -1
  17. data/lib/puppet/provider/user/useradd.rb +1 -1
  18. data/lib/puppet/settings/environment_conf.rb +1 -0
  19. data/lib/puppet/util/fact_dif.rb +36 -17
  20. data/lib/puppet/util/monkey_patches.rb +7 -0
  21. data/lib/puppet/util/windows/adsi.rb +46 -0
  22. data/lib/puppet/util/windows/api_types.rb +1 -1
  23. data/lib/puppet/util/windows/principal.rb +9 -2
  24. data/lib/puppet/util/windows/sid.rb +4 -2
  25. data/lib/puppet/version.rb +1 -1
  26. data/locales/puppet.pot +139 -87
  27. data/man/man5/puppet.conf.5 +11 -3
  28. data/man/man8/puppet-agent.8 +1 -1
  29. data/man/man8/puppet-apply.8 +1 -1
  30. data/man/man8/puppet-catalog.8 +1 -1
  31. data/man/man8/puppet-config.8 +1 -1
  32. data/man/man8/puppet-describe.8 +1 -1
  33. data/man/man8/puppet-device.8 +1 -1
  34. data/man/man8/puppet-doc.8 +1 -1
  35. data/man/man8/puppet-epp.8 +1 -1
  36. data/man/man8/puppet-facts.8 +60 -2
  37. data/man/man8/puppet-filebucket.8 +1 -1
  38. data/man/man8/puppet-generate.8 +1 -1
  39. data/man/man8/puppet-help.8 +1 -1
  40. data/man/man8/puppet-key.8 +1 -1
  41. data/man/man8/puppet-lookup.8 +1 -1
  42. data/man/man8/puppet-man.8 +1 -1
  43. data/man/man8/puppet-module.8 +1 -1
  44. data/man/man8/puppet-node.8 +1 -1
  45. data/man/man8/puppet-parser.8 +1 -1
  46. data/man/man8/puppet-plugin.8 +1 -1
  47. data/man/man8/puppet-report.8 +1 -1
  48. data/man/man8/puppet-resource.8 +1 -1
  49. data/man/man8/puppet-script.8 +1 -1
  50. data/man/man8/puppet-ssl.8 +5 -1
  51. data/man/man8/puppet-status.8 +1 -1
  52. data/man/man8/puppet.8 +2 -2
  53. data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services_vendor_preset +9 -0
  54. data/spec/integration/application/plugin_spec.rb +1 -1
  55. data/spec/integration/http/client_spec.rb +12 -0
  56. data/spec/integration/indirector/direct_file_server_spec.rb +1 -3
  57. data/spec/integration/util/windows/adsi_spec.rb +18 -0
  58. data/spec/integration/util/windows/principal_spec.rb +21 -0
  59. data/spec/integration/util/windows/registry_spec.rb +6 -0
  60. data/spec/spec_helper.rb +11 -1
  61. data/spec/unit/application/facts_spec.rb +482 -3
  62. data/spec/unit/application/ssl_spec.rb +23 -0
  63. data/spec/unit/defaults_spec.rb +16 -0
  64. data/spec/unit/environments_spec.rb +164 -88
  65. data/spec/unit/face/facts_spec.rb +4 -0
  66. data/spec/unit/file_system_spec.rb +9 -0
  67. data/spec/unit/indirector/facts/facter_spec.rb +95 -0
  68. data/spec/unit/network/formats_spec.rb +41 -0
  69. data/spec/unit/network/http/factory_spec.rb +19 -0
  70. data/spec/unit/provider/package/dnfmodule_spec.rb +10 -1
  71. data/spec/unit/provider/service/systemd_spec.rb +11 -0
  72. data/spec/unit/provider/user/useradd_spec.rb +18 -3
  73. data/spec/unit/resource/catalog_spec.rb +1 -1
  74. data/spec/unit/util/windows/sid_spec.rb +6 -0
  75. metadata +12 -8
  76. data/spec/lib/matchers/include.rb +0 -27
  77. data/spec/lib/matchers/include_spec.rb +0 -32
@@ -55,6 +55,24 @@ describe Puppet::Util::Windows::ADSI::User,
55
55
  end
56
56
  end
57
57
  end
58
+
59
+ describe '.current_user_name_with_format' do
60
+ context 'when desired format is NameSamCompatible' do
61
+ it 'should get the same user name as the current_user_name method but fully qualified' do
62
+ user_name = Puppet::Util::Windows::ADSI::User.current_user_name
63
+ fully_qualified_user_name = Puppet::Util::Windows::ADSI::User.current_sam_compatible_user_name
64
+
65
+ expect(fully_qualified_user_name).to match(/^.+\\#{user_name}$/)
66
+ end
67
+
68
+ it 'should have the same SID as with the current_user_name method' do
69
+ user_name = Puppet::Util::Windows::ADSI::User.current_user_name
70
+ fully_qualified_user_name = Puppet::Util::Windows::ADSI::User.current_sam_compatible_user_name
71
+
72
+ expect(Puppet::Util::Windows::SID.name_to_sid(user_name)).to eq(Puppet::Util::Windows::SID.name_to_sid(fully_qualified_user_name))
73
+ end
74
+ end
75
+ end
58
76
  end
59
77
 
60
78
  describe Puppet::Util::Windows::ADSI::Group,
@@ -7,6 +7,7 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet::Util::Platform.wi
7
7
  let (:system_bytes) { [1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0] }
8
8
  let (:null_sid_bytes) { [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }
9
9
  let (:administrator_bytes) { [1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 32, 2, 0, 0] }
10
+ let (:all_application_packages_bytes) { [1, 2, 0, 0, 0, 0, 0, 15, 2, 0, 0, 0, 1, 0, 0, 0] }
10
11
  let (:computer_sid) { Puppet::Util::Windows::SID.name_to_principal(Puppet::Util::Windows::ADSI.computer_name) }
11
12
  # BUILTIN is localized on German Windows, but not French
12
13
  # looking this up like this dilutes the values of the tests as we're comparing two mechanisms
@@ -121,6 +122,26 @@ describe Puppet::Util::Windows::SID::Principal, :if => Puppet::Util::Platform.wi
121
122
  expect(principal.to_s).to eq(builtin_localized)
122
123
  end
123
124
 
125
+ it "should always sanitize the account name first" do
126
+ expect(Puppet::Util::Windows::SID::Principal).to receive(:sanitize_account_name).with('NT AUTHORITY\\SYSTEM').and_call_original
127
+ Puppet::Util::Windows::SID::Principal.lookup_account_name('NT AUTHORITY\\SYSTEM')
128
+ end
129
+
130
+ it "should be able to create an instance from an account name prefixed by APPLICATION PACKAGE AUTHORITY" do
131
+ principal = Puppet::Util::Windows::SID::Principal.lookup_account_name('APPLICATION PACKAGE AUTHORITY\\ALL APPLICATION PACKAGES')
132
+ expect(principal.account).to eq('ALL APPLICATION PACKAGES')
133
+ expect(principal.sid_bytes).to eq(all_application_packages_bytes)
134
+ expect(principal.sid).to eq('S-1-15-2-1')
135
+ expect(principal.domain).to eq('APPLICATION PACKAGE AUTHORITY')
136
+ expect(principal.domain_account).to eq('APPLICATION PACKAGE AUTHORITY\\ALL APPLICATION PACKAGES')
137
+ expect(principal.account_type).to eq(:SidTypeWellKnownGroup)
138
+ expect(principal.to_s).to eq('APPLICATION PACKAGE AUTHORITY\\ALL APPLICATION PACKAGES')
139
+ end
140
+
141
+ it "should fail without proper account name sanitization when it is prefixed by APPLICATION PACKAGE AUTHORITY" do
142
+ given_account_name = 'APPLICATION PACKAGE AUTHORITY\\ALL APPLICATION PACKAGES'
143
+ expect { Puppet::Util::Windows::SID::Principal.lookup_account_name(nil, false, given_account_name) }.to raise_error(Puppet::Util::Windows::Error, /No mapping between account names and security IDs was done./)
144
+ end
124
145
  end
125
146
 
126
147
  describe ".lookup_account_sid" do
@@ -263,6 +263,12 @@ describe Puppet::Util::Windows::Registry do
263
263
  type: Win32::Registry::REG_EXPAND_SZ,
264
264
  value: "\0\0\0reg expand string",
265
265
  expected_value: ""
266
+ },
267
+ {
268
+ name: 'REG_EXPAND_SZ_2',
269
+ type: Win32::Registry::REG_EXPAND_SZ,
270
+ value: "1\x002\x003\x004\x00\x00\x00\x90\xD8UoY".force_encoding("UTF-16LE"),
271
+ expected_value: "1234"
266
272
  }
267
273
  ].each do |pair|
268
274
  it 'reads up to the first wide null' do
data/spec/spec_helper.rb CHANGED
@@ -160,10 +160,20 @@ RSpec.configure do |config|
160
160
  PUPPET_FACTER_2_GCE_URL = %r{^http://metadata/computeMetadata/v1(beta1)?}.freeze
161
161
  PUPPET_FACTER_3_GCE_URL = "http://metadata.google.internal/computeMetadata/v1/?recursive=true&alt=json".freeze
162
162
 
163
+ # Facter azure metadata endpoint
164
+ PUPPET_FACTER_AZ_URL = "http://169.254.169.254/metadata/instance?api-version=2020-09-01"
165
+
166
+ # Facter EC2 endpoint
167
+ PUPPET_FACTER_EC2_METADATA_URL = 'http://169.254.169.254/latest/meta-data/'
168
+ PUPPET_FACTER_EC2_USERDATA_URL = 'http://169.254.169.254/latest/user-data/'
169
+
163
170
  config.around :each do |example|
164
- # Ignore requests from Facter GCE fact in Travis
171
+ # Ignore requests from Facter to external services
165
172
  stub_request(:get, PUPPET_FACTER_2_GCE_URL)
166
173
  stub_request(:get, PUPPET_FACTER_3_GCE_URL)
174
+ stub_request(:get, PUPPET_FACTER_AZ_URL)
175
+ stub_request(:get, PUPPET_FACTER_EC2_METADATA_URL)
176
+ stub_request(:get, PUPPET_FACTER_EC2_USERDATA_URL)
167
177
 
168
178
  # Enable VCR if the example is tagged with `:vcr` metadata.
169
179
  if example.metadata[:vcr]
@@ -3,7 +3,7 @@ require 'puppet/application/facts'
3
3
 
4
4
  describe Puppet::Application::Facts do
5
5
  let(:app) { Puppet::Application[:facts] }
6
- let(:values) { {"filesystems" => "apfs,autofs,devfs", "macaddress" => "64:52:11:22:03:25"} }
6
+ let(:values) { {"filesystems" => "apfs,autofs,devfs", "macaddress" => "64:52:11:22:03:2e"} }
7
7
 
8
8
  before :each do
9
9
  Puppet::Node::Facts.indirection.terminus_class = :memory
@@ -21,7 +21,7 @@ describe Puppet::Application::Facts do
21
21
  name: whatever
22
22
  values:
23
23
  filesystems: apfs,autofs,devfs
24
- macaddress: "64:52:11:22:03:25"
24
+ macaddress: "64:52:11:22:03:2e"
25
25
  END
26
26
 
27
27
  expect {
@@ -42,7 +42,7 @@ describe Puppet::Application::Facts do
42
42
  name: #{Puppet[:certname]}
43
43
  values:
44
44
  filesystems: apfs,autofs,devfs
45
- macaddress: "64:52:11:22:03:25"
45
+ macaddress: "64:52:11:22:03:2e"
46
46
  END
47
47
 
48
48
  expect {
@@ -50,4 +50,483 @@ describe Puppet::Application::Facts do
50
50
  }.to exit_with(0)
51
51
  .and output(expected).to_stdout
52
52
  end
53
+
54
+ context 'when show action is called' do
55
+ let(:expected) { <<~END }
56
+ {
57
+ "filesystems": "apfs,autofs,devfs",
58
+ "macaddress": "64:52:11:22:03:2e"
59
+ }
60
+ END
61
+
62
+ before :each do
63
+ Puppet::Node::Facts.indirection.terminus_class = :facter
64
+ allow(Facter).to receive(:resolve).and_return(values)
65
+ app.command_line.args = %w{show}
66
+ end
67
+
68
+ it 'correctly displays facts with default formatting' do
69
+ expect {
70
+ app.run
71
+ }.to exit_with(0)
72
+ .and output(expected).to_stdout
73
+ end
74
+
75
+ it 'displays a single fact value' do
76
+ app.command_line.args << 'filesystems' << '--value-only'
77
+ expect {
78
+ app.run
79
+ }.to exit_with(0)
80
+ .and output("apfs,autofs,devfs\n").to_stdout
81
+ end
82
+
83
+ it "warns and ignores value-only when multiple fact names are specified" do
84
+ app.command_line.args << 'filesystems' << 'macaddress' << '--value-only'
85
+ expect {
86
+ app.run
87
+ }.to exit_with(0)
88
+ .and output(expected).to_stdout
89
+ .and output(/it can only be used when querying for a single fact/).to_stderr
90
+ end
91
+
92
+ {
93
+ "type_hash" => [{'a' => 2}, "{\n \"a\": 2\n}"],
94
+ "type_array" => [[], "[\n\n]"],
95
+ "type_string" => ["str", "str"],
96
+ "type_int" => [1, "1"],
97
+ "type_float" => [1.0, "1.0"],
98
+ "type_true" => [true, "true"],
99
+ "type_false" => [false, "false"],
100
+ "type_nil" => [nil, ""],
101
+ "type_sym" => [:sym, "sym"]
102
+ }.each_pair do |name, values|
103
+ it "renders '#{name}' as '#{values.last}'" do
104
+ fact_value = values.first
105
+ fact_output = values.last
106
+
107
+ allow(Facter).to receive(:resolve).and_return({name => fact_value})
108
+
109
+ app.command_line.args << name << '--value-only'
110
+ expect {
111
+ app.run
112
+ }.to exit_with(0)
113
+ .and output("#{fact_output}\n").to_stdout
114
+ end
115
+ end
116
+ end
117
+
118
+ context 'when diff action is called' do
119
+ let(:facter3_facts) { <<~END }
120
+ {
121
+ "hypervisors": {
122
+ "vmware": {
123
+ "version": ""
124
+ }
125
+ },
126
+ "networking": {
127
+ "interfaces": {
128
+ "lo": {
129
+ "bindings6": [
130
+ {
131
+ "network": "::1"
132
+ }
133
+ ]
134
+ },
135
+ "em0.1": {
136
+ "ip": "0.0.0.0"
137
+ }
138
+ }
139
+ },
140
+ "macaddress": "64:52:11:22:03:2e",
141
+ "obsolete_fact": "true",
142
+ "mountpoints": {
143
+ "/var": {
144
+ "options": [
145
+ "noatime",
146
+ "journaled",
147
+ "nobrowse"
148
+ ]
149
+ }
150
+ }
151
+ }
152
+ END
153
+
154
+ let(:facter4_facts) { <<~END }
155
+ {
156
+ "hypervisors": {
157
+ "vmware": {
158
+ "version": "ESXi 6.7"
159
+ }
160
+ },
161
+ "networking": {
162
+ "interfaces": {
163
+ "lo": {
164
+ "bindings6": [
165
+ {
166
+ "network": "::1",
167
+ "scope6": "host"
168
+ }
169
+ ]
170
+ },
171
+ "em0.1": {
172
+ "ip": "127.0.0.1"
173
+ }
174
+ }
175
+ },
176
+ "macaddress": "64:52:11:22:03:2e",
177
+ "mountpoints": {
178
+ "/var": {
179
+ "options": [
180
+ "noatime",
181
+ "nobrowse",
182
+ "journaled"
183
+ ]
184
+ }
185
+ }
186
+ }
187
+ END
188
+
189
+ before :each do
190
+ Puppet::Node::Facts.indirection.terminus_class = :facter
191
+ app.command_line.args = %w{diff}
192
+
193
+ allow(Facter).to receive(:value).with('facterversion').and_return('3.99.0')
194
+ allow(Puppet::Util::Execution).to receive(:execute).with(/puppet facts show --no-facterng/, combine:false).and_return(facter3_facts)
195
+ allow(Puppet::Util::Execution).to receive(:execute).with(/puppet facts show --facterng/, combine:false).and_return(facter4_facts)
196
+ end
197
+
198
+ # Workaround for YAML issue on Ubuntu where null values get space as key
199
+ let(:regex) { false }
200
+ shared_examples_for 'correctly rendering output' do |render_format|
201
+ it 'correctly displays output' do
202
+ app.command_line.args << '--structured' if structured
203
+ app.command_line.args << '--exclude' << exclude if exclude
204
+ app.command_line.args << '--render-as' << render_format if render_format
205
+ expect {
206
+ app.run
207
+ }.to exit_with(0)
208
+ .and output(regex ? /#{expected_output}/ : expected_output).to_stdout
209
+ end
210
+ end
211
+
212
+ context 'when no exclude regex is provided via CLI' do
213
+ let(:exclude) { nil }
214
+ context 'when structured is requested' do
215
+ let(:structured) { true }
216
+ context 'when rendering is set to default' do
217
+ let(:expected_output) { <<~END }
218
+ {
219
+ "hypervisors": {
220
+ "vmware": {
221
+ "version": {
222
+ "new_value": "ESXi 6.7",
223
+ "old_value": ""
224
+ }
225
+ }
226
+ },
227
+ "mountpoints": {
228
+ "/var": {
229
+ "options": {
230
+ "1": {
231
+ "new_value": "nobrowse",
232
+ "old_value": "journaled"
233
+ },
234
+ "2": {
235
+ "new_value": "journaled",
236
+ "old_value": "nobrowse"
237
+ }
238
+ }
239
+ }
240
+ },
241
+ "networking": {
242
+ "interfaces": {
243
+ "em0.1": {
244
+ "ip": {
245
+ "new_value": "127.0.0.1",
246
+ "old_value": "0.0.0.0"
247
+ }
248
+ },
249
+ "lo": {
250
+ "bindings6": {
251
+ "0": {
252
+ "scope6": {
253
+ "new_value": "host",
254
+ "old_value": null
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
260
+ },
261
+ "obsolete_fact": {
262
+ "new_value": null,
263
+ "old_value": "true"
264
+ }
265
+ }
266
+ END
267
+
268
+ it_behaves_like 'correctly rendering output'
269
+ end
270
+
271
+ context 'when rendering is set to yaml' do
272
+ # Workaround for YAML issue on Ubuntu where null values get space as key
273
+ let(:regex) { true }
274
+ let(:expected_output) { <<~END }
275
+ ---
276
+ hypervisors:
277
+ vmware:
278
+ version:
279
+ :new_value: ESXi 6\.7
280
+ :old_value: ''
281
+ mountpoints:
282
+ "/var":
283
+ options:
284
+ 1:
285
+ :new_value: nobrowse
286
+ :old_value: journaled
287
+ 2:
288
+ :new_value: journaled
289
+ :old_value: nobrowse
290
+ networking:
291
+ interfaces:
292
+ em0\.1:
293
+ ip:
294
+ :new_value: 127\.0\.0\.1
295
+ :old_value: 0\.0\.0\.0
296
+ lo:
297
+ bindings6:
298
+ 0:
299
+ scope6:
300
+ :new_value: host
301
+ :old_value:\s?
302
+ obsolete_fact:
303
+ :new_value:\s?
304
+ :old_value: 'true'
305
+ END
306
+
307
+ it_behaves_like 'correctly rendering output', 'yaml'
308
+ end
309
+
310
+ context 'when rendering is set to json' do
311
+ let(:expected_output) { <<~END }
312
+ {"hypervisors":{"vmware":{"version":{"new_value":"ESXi 6.7","old_value":""}}},\
313
+ "mountpoints":{"/var":{"options":{"1":{"new_value":"nobrowse","old_value":"journaled"},\
314
+ "2":{"new_value":"journaled","old_value":"nobrowse"}}}},"networking":{"interfaces":\
315
+ {"em0.1":{"ip":{"new_value":"127.0.0.1","old_value":"0.0.0.0"}},"lo":{"bindings6":\
316
+ {"0":{"scope6":{"new_value":"host","old_value":null}}}}}},"obsolete_fact":\
317
+ {"new_value":null,"old_value":"true"}}
318
+ END
319
+
320
+ it_behaves_like 'correctly rendering output', 'json'
321
+ end
322
+ end
323
+
324
+ context 'when structured is not requested' do
325
+ let(:structured) { false }
326
+ context 'when rendering is set to default' do
327
+ let(:expected_output) { <<~END }
328
+ {
329
+ "hypervisors.vmware.version": {
330
+ "new_value": "ESXi 6.7",
331
+ "old_value": ""
332
+ },
333
+ "mountpoints./var.options.1": {
334
+ "new_value": "nobrowse",
335
+ "old_value": "journaled"
336
+ },
337
+ "mountpoints./var.options.2": {
338
+ "new_value": "journaled",
339
+ "old_value": "nobrowse"
340
+ },
341
+ "networking.interfaces.\\"em0.1\\".ip": {
342
+ "new_value": "127.0.0.1",
343
+ "old_value": "0.0.0.0"
344
+ },
345
+ "networking.interfaces.lo.bindings6.0.scope6": {
346
+ "new_value": "host",
347
+ "old_value": null
348
+ },
349
+ "obsolete_fact": {
350
+ "new_value": null,
351
+ "old_value": "true"
352
+ }
353
+ }
354
+ END
355
+
356
+ it_behaves_like 'correctly rendering output'
357
+ end
358
+
359
+ context 'when rendering is set to yaml' do
360
+ # Workaround for YAML issue on Ubuntu where null values get space as key
361
+ let(:regex) { true }
362
+ let(:expected_output) { <<~END }
363
+ ---
364
+ hypervisors\.vmware\.version:
365
+ :new_value: ESXi 6\.7
366
+ :old_value: ''
367
+ mountpoints\./var\.options\.1:
368
+ :new_value: nobrowse
369
+ :old_value: journaled
370
+ mountpoints\./var\.options\.2:
371
+ :new_value: journaled
372
+ :old_value: nobrowse
373
+ networking\.interfaces\."em0\.1"\.ip:
374
+ :new_value: 127\.0\.0\.1
375
+ :old_value: 0\.0\.0\.0
376
+ networking\.interfaces\.lo\.bindings6\.0\.scope6:
377
+ :new_value: host
378
+ :old_value:\s?
379
+ obsolete_fact:
380
+ :new_value:\s?
381
+ :old_value: 'true'
382
+ END
383
+
384
+ it_behaves_like 'correctly rendering output', 'yaml'
385
+ end
386
+
387
+ context 'when rendering is set to json' do
388
+ let(:expected_output) { <<~END }
389
+ {"hypervisors.vmware.version":{"new_value":"ESXi 6.7","old_value":""},\
390
+ "mountpoints./var.options.1":{"new_value":"nobrowse","old_value":"journaled"},\
391
+ "mountpoints./var.options.2":{"new_value":"journaled","old_value":"nobrowse"},\
392
+ "networking.interfaces.\\"em0.1\\".ip":{"new_value":"127.0.0.1",\
393
+ "old_value":"0.0.0.0"},"networking.interfaces.lo.bindings6.0.scope6":\
394
+ {"new_value":"host","old_value":null},"obsolete_fact":{"new_value":null,\
395
+ "old_value":"true"}}
396
+ END
397
+
398
+ it_behaves_like 'correctly rendering output', 'json'
399
+ end
400
+ end
401
+ end
402
+
403
+ context 'when unwanted facts are excluded from diff via CLI option' do
404
+ let(:exclude) { '^mountpoints\./var\.options.*$|^obsolete_fact$|^hypervisors' }
405
+ context 'when structured is requested' do
406
+ let(:structured) { true }
407
+ context 'when rendering is set to default' do
408
+ let(:expected_output) { <<~END }
409
+ {
410
+ "networking": {
411
+ "interfaces": {
412
+ "em0.1": {
413
+ "ip": {
414
+ "new_value": "127.0.0.1",
415
+ "old_value": "0.0.0.0"
416
+ }
417
+ },
418
+ "lo": {
419
+ "bindings6": {
420
+ "0": {
421
+ "scope6": {
422
+ "new_value": "host",
423
+ "old_value": null
424
+ }
425
+ }
426
+ }
427
+ }
428
+ }
429
+ }
430
+ }
431
+ END
432
+
433
+ it_behaves_like 'correctly rendering output'
434
+ end
435
+
436
+ context 'when rendering is set to yaml' do
437
+ # Workaround for YAML issue on Ubuntu where null values get space as key
438
+ let(:regex) { true }
439
+ let(:expected_output) { <<~END }
440
+ ---
441
+ networking:
442
+ interfaces:
443
+ em0\.1:
444
+ ip:
445
+ :new_value: 127\.0\.0\.1
446
+ :old_value: 0\.0\.0\.0
447
+ lo:
448
+ bindings6:
449
+ 0:
450
+ scope6:
451
+ :new_value: host
452
+ :old_value:\s?
453
+ END
454
+
455
+ it_behaves_like 'correctly rendering output', 'yaml'
456
+ end
457
+
458
+ context 'when rendering is set to json' do
459
+ let(:expected_output) { <<~END }
460
+ {"networking":{"interfaces":{"em0.1":{"ip":{"new_value":"127.0.0.1",\
461
+ "old_value":"0.0.0.0"}},"lo":{"bindings6":{"0":{"scope6":{"new_value":\
462
+ "host","old_value":null}}}}}}}
463
+ END
464
+
465
+ it_behaves_like 'correctly rendering output', 'json'
466
+ end
467
+ end
468
+
469
+ context 'when structured is not requested' do
470
+ let(:structured) { false }
471
+ context 'when rendering is set to default' do
472
+ let(:expected_output) { <<~END }
473
+ {
474
+ "networking.interfaces.\\"em0.1\\".ip": {
475
+ "new_value": "127.0.0.1",
476
+ "old_value": "0.0.0.0"
477
+ },
478
+ "networking.interfaces.lo.bindings6.0.scope6": {
479
+ "new_value": "host",
480
+ "old_value": null
481
+ }
482
+ }
483
+ END
484
+
485
+ it_behaves_like 'correctly rendering output'
486
+ end
487
+
488
+ context 'when rendering is set to yaml' do
489
+ # Workaround for YAML issue on Ubuntu where null values get space as key
490
+ let(:regex) { true }
491
+ let(:expected_output) { <<~END }
492
+ ---
493
+ networking\.interfaces\."em0\.1"\.ip:
494
+ :new_value: 127\.0\.0\.1
495
+ :old_value: 0\.0\.0\.0
496
+ networking\.interfaces\.lo\.bindings6\.0\.scope6:
497
+ :new_value: host
498
+ :old_value:\s?
499
+ END
500
+
501
+ it_behaves_like 'correctly rendering output', 'yaml'
502
+ end
503
+
504
+ context 'when rendering is set to json' do
505
+ let(:expected_output) { <<~END }
506
+ {"networking.interfaces.\\"em0.1\\".ip":{"new_value":"127.0.0.1",\
507
+ "old_value":"0.0.0.0"},"networking.interfaces.lo.bindings6.0.scope6":\
508
+ {"new_value":"host","old_value":null}}
509
+ END
510
+
511
+ it_behaves_like 'correctly rendering output', 'json'
512
+ end
513
+ end
514
+ end
515
+ end
516
+
517
+ context 'when default action is called' do
518
+ before :each do
519
+ Puppet::Node::Facts.indirection.terminus_class = :memory
520
+ facts = Puppet::Node::Facts.new('whatever', values)
521
+ Puppet::Node::Facts.indirection.save(facts)
522
+ end
523
+
524
+ it 'calls find action' do
525
+ expect {
526
+ app.run
527
+ }.to exit_with(0)
528
+ .and output(anything).to_stdout
529
+ expect(app.action.name).to eq(:find)
530
+ end
531
+ end
53
532
  end