puppet 6.21.0-x64-mingw32 → 6.24.0-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 (217) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +5 -5
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +29 -23
  5. data/README.md +4 -4
  6. data/ext/osx/puppet.plist +2 -0
  7. data/ext/project_data.yaml +3 -2
  8. data/lib/puppet.rb +3 -3
  9. data/lib/puppet/application/agent.rb +12 -5
  10. data/lib/puppet/application/apply.rb +2 -1
  11. data/lib/puppet/application/device.rb +2 -1
  12. data/lib/puppet/application/filebucket.rb +1 -0
  13. data/lib/puppet/application/resource.rb +17 -3
  14. data/lib/puppet/application/script.rb +2 -1
  15. data/lib/puppet/application/ssl.rb +12 -0
  16. data/lib/puppet/configurer/downloader.rb +2 -1
  17. data/lib/puppet/defaults.rb +27 -5
  18. data/lib/puppet/environments.rb +26 -1
  19. data/lib/puppet/face/facts.rb +128 -30
  20. data/lib/puppet/face/help/action.erb +1 -0
  21. data/lib/puppet/face/help/face.erb +1 -0
  22. data/lib/puppet/face/node/clean.rb +11 -0
  23. data/lib/puppet/file_serving/fileset.rb +14 -2
  24. data/lib/puppet/file_system/file_impl.rb +1 -1
  25. data/lib/puppet/file_system/memory_file.rb +8 -1
  26. data/lib/puppet/file_system/windows.rb +4 -2
  27. data/lib/puppet/forge.rb +3 -3
  28. data/lib/puppet/functions/all.rb +1 -1
  29. data/lib/puppet/functions/camelcase.rb +1 -1
  30. data/lib/puppet/functions/capitalize.rb +2 -2
  31. data/lib/puppet/functions/downcase.rb +2 -2
  32. data/lib/puppet/functions/empty.rb +8 -0
  33. data/lib/puppet/functions/get.rb +5 -5
  34. data/lib/puppet/functions/group_by.rb +13 -5
  35. data/lib/puppet/functions/lest.rb +1 -1
  36. data/lib/puppet/functions/new.rb +100 -100
  37. data/lib/puppet/functions/partition.rb +12 -4
  38. data/lib/puppet/functions/require.rb +5 -5
  39. data/lib/puppet/functions/sort.rb +3 -3
  40. data/lib/puppet/functions/strftime.rb +1 -0
  41. data/lib/puppet/functions/tree_each.rb +7 -9
  42. data/lib/puppet/functions/type.rb +4 -4
  43. data/lib/puppet/functions/unwrap.rb +17 -2
  44. data/lib/puppet/functions/upcase.rb +2 -2
  45. data/lib/puppet/http/resolver/server_list.rb +15 -4
  46. data/lib/puppet/http/service/compiler.rb +69 -0
  47. data/lib/puppet/http/service/file_server.rb +2 -1
  48. data/lib/puppet/indirector/catalog/compiler.rb +1 -0
  49. data/lib/puppet/indirector/facts/facter.rb +24 -3
  50. data/lib/puppet/indirector/file_metadata/rest.rb +1 -0
  51. data/lib/puppet/indirector/resource/ral.rb +6 -1
  52. data/lib/puppet/interface/documentation.rb +1 -0
  53. data/lib/puppet/module_tool/applications/installer.rb +4 -0
  54. data/lib/puppet/module_tool/errors/shared.rb +17 -0
  55. data/lib/puppet/network/formats.rb +67 -0
  56. data/lib/puppet/network/http/factory.rb +4 -0
  57. data/lib/puppet/parser/functions/fqdn_rand.rb +14 -6
  58. data/lib/puppet/pops/types/p_sem_ver_type.rb +8 -2
  59. data/lib/puppet/pops/types/p_sensitive_type.rb +10 -0
  60. data/lib/puppet/pops/types/type_mismatch_describer.rb +1 -1
  61. data/lib/puppet/provider/exec/posix.rb +16 -4
  62. data/lib/puppet/provider/package/dnfmodule.rb +1 -1
  63. data/lib/puppet/provider/package/nim.rb +11 -6
  64. data/lib/puppet/provider/package/pip.rb +15 -3
  65. data/lib/puppet/provider/parsedfile.rb +3 -0
  66. data/lib/puppet/provider/service/systemd.rb +14 -4
  67. data/lib/puppet/provider/service/windows.rb +38 -0
  68. data/lib/puppet/provider/user/directoryservice.rb +25 -12
  69. data/lib/puppet/provider/user/useradd.rb +9 -2
  70. data/lib/puppet/reference/configuration.rb +1 -1
  71. data/lib/puppet/settings.rb +30 -7
  72. data/lib/puppet/settings/environment_conf.rb +1 -0
  73. data/lib/puppet/transaction/additional_resource_generator.rb +1 -1
  74. data/lib/puppet/type/exec.rb +16 -3
  75. data/lib/puppet/type/file.rb +19 -1
  76. data/lib/puppet/type/file/mode.rb +6 -0
  77. data/lib/puppet/type/file/selcontext.rb +1 -1
  78. data/lib/puppet/type/service.rb +18 -38
  79. data/lib/puppet/type/tidy.rb +22 -3
  80. data/lib/puppet/type/user.rb +38 -20
  81. data/lib/puppet/util/fact_dif.rb +36 -17
  82. data/lib/puppet/util/monkey_patches.rb +7 -0
  83. data/lib/puppet/util/selinux.rb +30 -4
  84. data/lib/puppet/util/symbolic_file_mode.rb +29 -17
  85. data/lib/puppet/util/windows/adsi.rb +46 -0
  86. data/lib/puppet/util/windows/api_types.rb +1 -1
  87. data/lib/puppet/util/windows/principal.rb +9 -2
  88. data/lib/puppet/util/windows/sid.rb +6 -2
  89. data/lib/puppet/version.rb +1 -1
  90. data/locales/puppet.pot +360 -280
  91. data/man/man5/puppet.conf.5 +279 -251
  92. data/man/man8/puppet-agent.8 +1 -1
  93. data/man/man8/puppet-apply.8 +1 -1
  94. data/man/man8/puppet-catalog.8 +9 -9
  95. data/man/man8/puppet-config.8 +1 -1
  96. data/man/man8/puppet-describe.8 +1 -1
  97. data/man/man8/puppet-device.8 +1 -1
  98. data/man/man8/puppet-doc.8 +1 -1
  99. data/man/man8/puppet-epp.8 +1 -1
  100. data/man/man8/puppet-facts.8 +65 -7
  101. data/man/man8/puppet-filebucket.8 +1 -1
  102. data/man/man8/puppet-generate.8 +1 -1
  103. data/man/man8/puppet-help.8 +1 -1
  104. data/man/man8/puppet-key.8 +7 -7
  105. data/man/man8/puppet-lookup.8 +1 -1
  106. data/man/man8/puppet-man.8 +1 -1
  107. data/man/man8/puppet-module.8 +1 -1
  108. data/man/man8/puppet-node.8 +5 -5
  109. data/man/man8/puppet-parser.8 +1 -1
  110. data/man/man8/puppet-plugin.8 +1 -1
  111. data/man/man8/puppet-report.8 +5 -5
  112. data/man/man8/puppet-resource.8 +1 -1
  113. data/man/man8/puppet-script.8 +1 -1
  114. data/man/man8/puppet-ssl.8 +5 -1
  115. data/man/man8/puppet-status.8 +4 -4
  116. data/man/man8/puppet.8 +2 -2
  117. data/spec/fixtures/ssl/127.0.0.1-key.pem +107 -57
  118. data/spec/fixtures/ssl/127.0.0.1.pem +52 -31
  119. data/spec/fixtures/ssl/bad-basic-constraints.pem +57 -35
  120. data/spec/fixtures/ssl/bad-int-basic-constraints.pem +57 -35
  121. data/spec/fixtures/ssl/ca.pem +57 -35
  122. data/spec/fixtures/ssl/crl.pem +28 -18
  123. data/spec/fixtures/ssl/ec-key.pem +11 -11
  124. data/spec/fixtures/ssl/ec.pem +33 -24
  125. data/spec/fixtures/ssl/encrypted-ec-key.pem +12 -12
  126. data/spec/fixtures/ssl/encrypted-key.pem +108 -58
  127. data/spec/fixtures/ssl/intermediate-agent-crl.pem +28 -19
  128. data/spec/fixtures/ssl/intermediate-agent.pem +57 -36
  129. data/spec/fixtures/ssl/intermediate-crl.pem +31 -21
  130. data/spec/fixtures/ssl/intermediate.pem +57 -36
  131. data/spec/fixtures/ssl/oid-key.pem +117 -0
  132. data/spec/fixtures/ssl/oid.pem +69 -0
  133. data/spec/fixtures/ssl/pluto-key.pem +107 -57
  134. data/spec/fixtures/ssl/pluto.pem +52 -30
  135. data/spec/fixtures/ssl/request-key.pem +107 -57
  136. data/spec/fixtures/ssl/request.pem +47 -26
  137. data/spec/fixtures/ssl/revoked-key.pem +107 -57
  138. data/spec/fixtures/ssl/revoked.pem +52 -30
  139. data/spec/fixtures/ssl/signed-key.pem +107 -57
  140. data/spec/fixtures/ssl/signed.pem +52 -30
  141. data/spec/fixtures/ssl/tampered-cert.pem +52 -30
  142. data/spec/fixtures/ssl/tampered-csr.pem +47 -26
  143. data/spec/fixtures/ssl/trusted_oid_mapping.yaml +5 -0
  144. data/spec/fixtures/ssl/unknown-127.0.0.1-key.pem +107 -57
  145. data/spec/fixtures/ssl/unknown-127.0.0.1.pem +50 -29
  146. data/spec/fixtures/ssl/unknown-ca-key.pem +107 -57
  147. data/spec/fixtures/ssl/unknown-ca.pem +55 -33
  148. data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services_vendor_preset +9 -0
  149. data/spec/integration/application/filebucket_spec.rb +11 -0
  150. data/spec/integration/application/module_spec.rb +21 -0
  151. data/spec/integration/application/plugin_spec.rb +1 -1
  152. data/spec/integration/application/resource_spec.rb +64 -0
  153. data/spec/integration/application/ssl_spec.rb +20 -0
  154. data/spec/integration/environments/settings_interpolation_spec.rb +0 -4
  155. data/spec/integration/http/client_spec.rb +12 -0
  156. data/spec/integration/indirector/direct_file_server_spec.rb +1 -3
  157. data/spec/integration/indirector/facts/facter_spec.rb +90 -36
  158. data/spec/integration/type/exec_spec.rb +70 -45
  159. data/spec/integration/util/windows/adsi_spec.rb +18 -0
  160. data/spec/integration/util/windows/principal_spec.rb +21 -0
  161. data/spec/integration/util/windows/registry_spec.rb +6 -0
  162. data/spec/lib/puppet/test_ca.rb +7 -2
  163. data/spec/lib/puppet_spec/settings.rb +1 -0
  164. data/spec/spec_helper.rb +11 -1
  165. data/spec/unit/application/agent_spec.rb +7 -2
  166. data/spec/unit/application/facts_spec.rb +482 -3
  167. data/spec/unit/application/ssl_spec.rb +23 -0
  168. data/spec/unit/configurer/downloader_spec.rb +6 -0
  169. data/spec/unit/configurer_spec.rb +23 -0
  170. data/spec/unit/defaults_spec.rb +16 -0
  171. data/spec/unit/environments_spec.rb +199 -88
  172. data/spec/unit/face/facts_spec.rb +4 -0
  173. data/spec/unit/file_serving/fileset_spec.rb +60 -0
  174. data/spec/unit/file_system_spec.rb +15 -0
  175. data/spec/unit/functions/assert_type_spec.rb +1 -1
  176. data/spec/unit/functions/empty_spec.rb +10 -0
  177. data/spec/unit/functions/unwrap_spec.rb +8 -0
  178. data/spec/unit/functions4_spec.rb +2 -2
  179. data/spec/unit/gettext/config_spec.rb +12 -0
  180. data/spec/unit/http/service/compiler_spec.rb +123 -0
  181. data/spec/unit/indirector/catalog/compiler_spec.rb +14 -10
  182. data/spec/unit/indirector/facts/facter_spec.rb +95 -0
  183. data/spec/unit/indirector/resource/ral_spec.rb +40 -75
  184. data/spec/unit/module_tool/applications/installer_spec.rb +12 -0
  185. data/spec/unit/network/formats_spec.rb +41 -0
  186. data/spec/unit/network/http/factory_spec.rb +19 -0
  187. data/spec/unit/parser/functions/fqdn_rand_spec.rb +15 -1
  188. data/spec/unit/parser/templatewrapper_spec.rb +12 -2
  189. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +18 -0
  190. data/spec/unit/pops/types/p_sensitive_type_spec.rb +18 -0
  191. data/spec/unit/provider/package/dnfmodule_spec.rb +10 -1
  192. data/spec/unit/provider/package/nim_spec.rb +42 -0
  193. data/spec/unit/provider/package/pip_spec.rb +37 -0
  194. data/spec/unit/provider/parsedfile_spec.rb +10 -0
  195. data/spec/unit/provider/service/init_spec.rb +1 -0
  196. data/spec/unit/provider/service/openwrt_spec.rb +3 -1
  197. data/spec/unit/provider/service/systemd_spec.rb +53 -8
  198. data/spec/unit/provider/service/windows_spec.rb +202 -0
  199. data/spec/unit/provider/user/directoryservice_spec.rb +67 -35
  200. data/spec/unit/provider/user/useradd_spec.rb +21 -6
  201. data/spec/unit/resource/catalog_spec.rb +1 -1
  202. data/spec/unit/settings_spec.rb +97 -56
  203. data/spec/unit/ssl/state_machine_spec.rb +19 -5
  204. data/spec/unit/transaction/additional_resource_generator_spec.rb +0 -2
  205. data/spec/unit/transaction_spec.rb +18 -20
  206. data/spec/unit/type/exec_spec.rb +76 -29
  207. data/spec/unit/type/file/selinux_spec.rb +3 -3
  208. data/spec/unit/type/file/source_spec.rb +4 -4
  209. data/spec/unit/type/service_spec.rb +59 -188
  210. data/spec/unit/type/tidy_spec.rb +24 -7
  211. data/spec/unit/type/user_spec.rb +45 -0
  212. data/spec/unit/util/selinux_spec.rb +87 -16
  213. data/spec/unit/util/windows/sid_spec.rb +41 -0
  214. data/tasks/generate_cert_fixtures.rake +12 -3
  215. metadata +24 -9
  216. data/spec/lib/matchers/include.rb +0 -27
  217. data/spec/lib/matchers/include_spec.rb +0 -32
@@ -20,6 +20,7 @@ module PuppetSpec::Settings
20
20
  end.freeze
21
21
 
22
22
  def set_puppet_conf(confdir, settings)
23
+ FileUtils.mkdir_p(confdir)
23
24
  write_file(File.join(confdir, "puppet.conf"), settings)
24
25
  end
25
26
 
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]
@@ -546,11 +546,16 @@ describe Puppet::Application::Agent do
546
546
  @puppetd.options[:digest] = :MD5
547
547
  end
548
548
 
549
+ def expected_fingerprint(name, x509)
550
+ digest = OpenSSL::Digest.new(name).hexdigest(x509.to_der)
551
+ digest.scan(/../).join(':').upcase
552
+ end
553
+
549
554
  it "should fingerprint the certificate if it exists" do
550
555
  cert = cert_fixture('signed.pem')
551
556
  allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_return(cert)
552
557
 
553
- expect(@puppetd).to receive(:puts).with('(MD5) E2:BA:9A:EF:20:A8:7D:10:8D:82:9A:61:5D:FD:5B:33')
558
+ expect(@puppetd).to receive(:puts).with("(MD5) #{expected_fingerprint('md5', cert)}")
554
559
 
555
560
  @puppetd.fingerprint
556
561
  end
@@ -560,7 +565,7 @@ describe Puppet::Application::Agent do
560
565
  allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_return(nil)
561
566
  allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_request).and_return(request)
562
567
 
563
- expect(@puppetd).to receive(:puts).with('(MD5) B8:4C:FB:31:AE:17:86:E3:AD:53:97:CA:F6:3C:4A:CB')
568
+ expect(@puppetd).to receive(:puts).with("(MD5) #{expected_fingerprint('md5', request)}")
564
569
 
565
570
  @puppetd.fingerprint
566
571
  end
@@ -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