puppet 7.23.0 → 7.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +5 -5
  3. data/Gemfile +2 -2
  4. data/Gemfile.lock +50 -47
  5. data/ext/project_data.yaml +1 -1
  6. data/lib/puppet/application/face_base.rb +2 -1
  7. data/lib/puppet/defaults.rb +22 -0
  8. data/lib/puppet/environments.rb +9 -0
  9. data/lib/puppet/functions/each.rb +11 -13
  10. data/lib/puppet/functions/filter.rb +5 -13
  11. data/lib/puppet/functions/map.rb +7 -8
  12. data/lib/puppet/indirector/catalog/json.rb +8 -3
  13. data/lib/puppet/interface/action.rb +3 -3
  14. data/lib/puppet/interface/documentation.rb +2 -2
  15. data/lib/puppet/interface/option.rb +3 -4
  16. data/lib/puppet/module/plan.rb +1 -1
  17. data/lib/puppet/module/task.rb +1 -1
  18. data/lib/puppet/module.rb +1 -1
  19. data/lib/puppet/network/http/api/indirected_routes.rb +10 -4
  20. data/lib/puppet/node/environment.rb +38 -0
  21. data/lib/puppet/node.rb +2 -2
  22. data/lib/puppet/pops/evaluator/relationship_operator.rb +1 -1
  23. data/lib/puppet/pops/functions/function.rb +1 -3
  24. data/lib/puppet/pops/loader/dependency_loader.rb +1 -4
  25. data/lib/puppet/pops/loader/loader_paths.rb +1 -3
  26. data/lib/puppet/pops/loader/module_loaders.rb +1 -1
  27. data/lib/puppet/pops/loaders.rb +6 -2
  28. data/lib/puppet/pops/lookup/context.rb +3 -4
  29. data/lib/puppet/pops/lookup/hiera_config.rb +1 -1
  30. data/lib/puppet/resource.rb +4 -0
  31. data/lib/puppet/settings/base_setting.rb +3 -2
  32. data/lib/puppet/settings.rb +0 -1
  33. data/lib/puppet/thread_local.rb +1 -4
  34. data/lib/puppet/type/file/ctime.rb +1 -1
  35. data/lib/puppet/type/file/mtime.rb +1 -1
  36. data/lib/puppet/util/log.rb +2 -2
  37. data/lib/puppet/version.rb +1 -1
  38. data/man/man5/puppet.conf.5 +21 -2
  39. data/man/man8/puppet-agent.8 +1 -1
  40. data/man/man8/puppet-apply.8 +1 -1
  41. data/man/man8/puppet-catalog.8 +1 -1
  42. data/man/man8/puppet-config.8 +1 -1
  43. data/man/man8/puppet-describe.8 +1 -1
  44. data/man/man8/puppet-device.8 +1 -1
  45. data/man/man8/puppet-doc.8 +1 -1
  46. data/man/man8/puppet-epp.8 +1 -1
  47. data/man/man8/puppet-facts.8 +1 -1
  48. data/man/man8/puppet-filebucket.8 +1 -1
  49. data/man/man8/puppet-generate.8 +1 -1
  50. data/man/man8/puppet-help.8 +1 -1
  51. data/man/man8/puppet-lookup.8 +1 -1
  52. data/man/man8/puppet-module.8 +1 -1
  53. data/man/man8/puppet-node.8 +1 -1
  54. data/man/man8/puppet-parser.8 +1 -1
  55. data/man/man8/puppet-plugin.8 +1 -1
  56. data/man/man8/puppet-report.8 +1 -1
  57. data/man/man8/puppet-resource.8 +1 -1
  58. data/man/man8/puppet-script.8 +1 -1
  59. data/man/man8/puppet-ssl.8 +1 -1
  60. data/man/man8/puppet.8 +2 -2
  61. data/spec/fixtures/integration/application/module/environments/direnv/modules/nginx/README +3 -0
  62. data/spec/fixtures/integration/application/module/environments/direnv/modules/nginx/manifests/init.pp +17 -0
  63. data/spec/fixtures/integration/application/module/environments/direnv/modules/nginx/metadata.json +20 -0
  64. data/spec/integration/application/module_spec.rb +141 -0
  65. data/spec/unit/environments_spec.rb +9 -0
  66. data/spec/unit/network/http/api/indirected_routes_spec.rb +28 -0
  67. data/spec/unit/node/environment_spec.rb +41 -0
  68. data/spec/unit/parser/resource_spec.rb +9 -0
  69. data/spec/unit/type/file/ctime_spec.rb +1 -1
  70. data/spec/unit/type/file/mtime_spec.rb +1 -1
  71. metadata +9 -9
@@ -86,4 +86,145 @@ describe 'puppet module', unless: Puppet::Util::Platform.jruby? do
86
86
  end
87
87
  end
88
88
  end
89
+
90
+ context 'install' do
91
+ it 'lists a module in a non-default directory environment' do
92
+ Puppet.initialize_settings(['-E', 'direnv'])
93
+ Puppet[:color] = false
94
+ Puppet[:environmentpath] = File.join(my_fixture_dir, 'environments')
95
+
96
+ expect {
97
+ app.command_line.args = ['list']
98
+ app.run
99
+ }.to exit_with(0)
100
+ .and output(Regexp.new("└── pmtacceptance-nginx".encode(Encoding.default_external), Regexp::MULTILINE)).to_stdout
101
+ end
102
+ end
103
+
104
+ context 'changes' do
105
+ let(:tmp) { tmpdir('module_changes') }
106
+
107
+ before :each do
108
+ Puppet.initialize_settings(['-E', 'direnv'])
109
+ Puppet[:color] = false
110
+ end
111
+
112
+ def use_local_fixture
113
+ Puppet[:environmentpath] = File.join(my_fixture_dir, 'environments')
114
+ end
115
+
116
+ def create_working_copy
117
+ Puppet[:environmentpath] = File.join(tmp, 'environments')
118
+ FileUtils.cp_r(File.join(my_fixture_dir, 'environments'), tmp)
119
+ end
120
+
121
+ it 'reports an error when the install path is invalid' do
122
+ use_local_fixture
123
+
124
+ pattern = Regexp.new([
125
+ %Q{.*Error: Could not find a valid module at "#{tmp}/nginx".*},
126
+ %Q{.*Error: Try 'puppet help module changes' for usage.*},
127
+ ].join("\n"), Regexp::MULTILINE)
128
+
129
+ expect {
130
+ app.command_line.args = ['changes', File.join(tmp, 'nginx')]
131
+ app.run
132
+ }.to exit_with(1)
133
+ .and output(pattern).to_stderr
134
+ end
135
+
136
+ it 'reports when checksums are missing from metadata.json' do
137
+ create_working_copy
138
+
139
+ # overwrite checksums in metadata.json
140
+ nginx_dir = File.join(tmp, 'environments', 'direnv', 'modules', 'nginx')
141
+ File.write(File.join(nginx_dir, 'metadata.json'), <<~END)
142
+ {
143
+ "name": "pmtacceptance/nginx",
144
+ "version": "0.0.1"
145
+ }
146
+ END
147
+
148
+ pattern = Regexp.new([
149
+ %Q{.*Error: No file containing checksums found.*},
150
+ %Q{.*Error: Try 'puppet help module changes' for usage.*},
151
+ ].join("\n"), Regexp::MULTILINE)
152
+
153
+ expect {
154
+ app.command_line.args = ['changes', nginx_dir]
155
+ app.run
156
+ }.to exit_with(1)
157
+ .and output(pattern).to_stderr
158
+ end
159
+
160
+ it 'reports module not found when metadata.json is missing' do
161
+ create_working_copy
162
+
163
+ # overwrite checksums in metadata.json
164
+ nginx_dir = File.join(tmp, 'environments', 'direnv', 'modules', 'nginx')
165
+ File.unlink(File.join(nginx_dir, 'metadata.json'))
166
+
167
+ pattern = Regexp.new([
168
+ %Q{.*Error: Could not find a valid module at.*},
169
+ %Q{.*Error: Try 'puppet help module changes' for usage.*},
170
+ ].join("\n"), Regexp::MULTILINE)
171
+
172
+ expect {
173
+ app.command_line.args = ['changes', nginx_dir]
174
+ app.run
175
+ }.to exit_with(1)
176
+ .and output(pattern).to_stderr
177
+ end
178
+
179
+ it 'reports when a file is modified' do
180
+ create_working_copy
181
+
182
+ # overwrite README so checksum doesn't match
183
+ nginx_dir = File.join(tmp, 'environments', 'direnv', 'modules', 'nginx')
184
+ File.write(File.join(nginx_dir, 'README'), '')
185
+
186
+ pattern = Regexp.new([
187
+ %Q{.*Warning: 1 files modified.*},
188
+ ].join("\n"), Regexp::MULTILINE)
189
+
190
+ expect {
191
+ app.command_line.args = ['changes', nginx_dir]
192
+ app.run
193
+ }.to exit_with(0)
194
+ .and output(%r{README}).to_stdout
195
+ .and output(pattern).to_stderr
196
+ end
197
+
198
+ it 'reports when a file is missing' do
199
+ create_working_copy
200
+
201
+ # delete README so checksum doesn't match
202
+ nginx_dir = File.join(tmp, 'environments', 'direnv', 'modules', 'nginx')
203
+ File.unlink(File.join(nginx_dir, 'README'))
204
+
205
+ # odd that it says modified
206
+ pattern = Regexp.new([
207
+ %Q{.*Warning: 1 files modified.*},
208
+ ].join("\n"), Regexp::MULTILINE)
209
+
210
+ expect {
211
+ app.command_line.args = ['changes', nginx_dir]
212
+ app.run
213
+ }.to exit_with(0)
214
+ .and output(%r{README}).to_stdout
215
+ .and output(pattern).to_stderr
216
+ end
217
+
218
+ it 'reports when there are no changes' do
219
+ use_local_fixture
220
+
221
+ nginx_dir = File.join(Puppet[:environmentpath], 'direnv', 'modules', 'nginx')
222
+
223
+ expect {
224
+ app.command_line.args = ['changes', nginx_dir]
225
+ app.run
226
+ }.to exit_with(0)
227
+ .and output(/No modified files/).to_stdout
228
+ end
229
+ end
89
230
  end
@@ -115,6 +115,15 @@ describe Puppet::Environments do
115
115
  end
116
116
  end
117
117
 
118
+ it "sets the environment's configured and resolved paths set when symlinked" do
119
+ loader_from(:filesystem => [directory_tree],
120
+ :directory => directory_tree.children.first) do |loader|
121
+ env = loader.get("symlinked_environment")
122
+ expect(env.resolved_path).to eq("#{FS.path_string(directory_tree)}/versioned_env")
123
+ expect(env.configured_path).to eq("#{FS.path_string(directory_tree)}/envdir/symlinked_environment")
124
+ end
125
+ end
126
+
118
127
  it "ignores symlinked environments when `:versioned_environment_dirs` is false" do
119
128
  Puppet[:versioned_environment_dirs] = false
120
129
  loader_from(:filesystem => [directory_tree],
@@ -182,6 +182,7 @@ describe Puppet::Network::HTTP::API::IndirectedRoutes do
182
182
  indirection.save(data, "my data")
183
183
  request = a_request_that_finds(data, :accept_header => "application/json, text/pson")
184
184
  allow(data).to receive(:to_json).and_raise(Puppet::Network::FormatHandler::FormatError, 'Could not render to Puppet::Network::Format[json]: source sequence is illegal/malformed utf-8')
185
+ expect(Puppet).to receive(:warning).with(/Failed to serialize Puppet::IndirectorTesting for 'my data': Could not render to Puppet::Network::Format\[json\]/)
185
186
 
186
187
  handler.call(request, response)
187
188
 
@@ -209,6 +210,19 @@ describe Puppet::Network::HTTP::API::IndirectedRoutes do
209
210
  handler.call(request, response)
210
211
  }.to raise_error(not_found_error)
211
212
  end
213
+
214
+ it "should raise FormatError if tries to fallback and pson serialization is not allowed" do
215
+ Puppet[:allow_pson_serialization] = false
216
+ data = Puppet::IndirectorTesting.new("my data")
217
+ indirection.save(data, "my data")
218
+ request = a_request_that_finds(data, :accept_header => "unknown, text/pson")
219
+ allow(data).to receive(:to_pson).and_raise(Puppet::Network::FormatHandler::FormatError, 'Could not render to Puppet::Network::Format[pson]: source sequence is illegal/malformed utf-8')
220
+
221
+ expect {
222
+ handler.call(request, response)
223
+ }.to raise_error(Puppet::Network::FormatHandler::FormatError,
224
+ %r{Failed to serialize Puppet::IndirectorTesting for 'my data': Could not render to Puppet::Network::Format\[pson\]})
225
+ end
212
226
  end
213
227
 
214
228
  describe "when searching for model instances" do
@@ -228,6 +242,7 @@ describe Puppet::Network::HTTP::API::IndirectedRoutes do
228
242
  indirection.save(data, "my data")
229
243
  request = a_request_that_searches(Puppet::IndirectorTesting.new("my"), :accept_header => "application/json, text/pson")
230
244
  allow(data).to receive(:to_json).and_raise(Puppet::Network::FormatHandler::FormatError, 'Could not render to Puppet::Network::Format[json]: source sequence is illegal/malformed utf-8')
245
+ expect(Puppet).to receive(:warning).with(/Failed to serialize Puppet::IndirectorTesting for 'my': Could not render_multiple to Puppet::Network::Format\[json\]/)
231
246
 
232
247
  handler.call(request, response)
233
248
 
@@ -248,6 +263,19 @@ describe Puppet::Network::HTTP::API::IndirectedRoutes do
248
263
  %r{No supported formats are acceptable \(Accept: application/json, text/pson\)})
249
264
  end
250
265
 
266
+ it "raises FormatError if tries to fallback and pson serialization is not allowed" do
267
+ Puppet[:allow_pson_serialization] = false
268
+ data = Puppet::IndirectorTesting.new("my data")
269
+ indirection.save(data, "my data")
270
+ request = a_request_that_searches(Puppet::IndirectorTesting.new("my"), :accept_header => "unknown, text/pson")
271
+ allow(data).to receive(:to_pson).and_raise(Puppet::Network::FormatHandler::FormatError, 'Could not render to Puppet::Network::Format[pson]: source sequence is illegal/malformed utf-8')
272
+
273
+ expect {
274
+ handler.call(request, response)
275
+ }.to raise_error(Puppet::Network::FormatHandler::FormatError,
276
+ %r{Failed to serialize Puppet::IndirectorTesting for 'my': Could not render_multiple to Puppet::Network::Format\[pson\]})
277
+ end
278
+
251
279
  it "should return [] when searching returns an empty array" do
252
280
  request = a_request_that_searches(Puppet::IndirectorTesting.new("nothing"), :accept_header => "unknown, application/json")
253
281
 
@@ -40,6 +40,47 @@ describe Puppet::Node::Environment do
40
40
  expect(e.inspect).to match(%r{<Puppet::Node::Environment:\w* @name="test" @manifest="#{File.expand_path('/manifests/path')}" @modulepath="#{File.expand_path('/modules/path')}:#{File.expand_path('/other/modules')}" >})
41
41
  end
42
42
 
43
+ describe "externalizing filepaths" do
44
+ before(:each) do
45
+ env.resolved_path = "/opt/puppetlabs/envs/prod_123"
46
+ env.configured_path = "/etc/puppetlabs/envs/prod"
47
+
48
+ @vendored_manifest = "/opt/puppetlabs/vendored/modules/foo/manifests/init.pp"
49
+ @production_manifest = "/opt/puppetlabs/envs/prod_123/modules/foo/manifests/init.pp"
50
+ end
51
+
52
+ it "leaves paths alone if they do not match the resolved path" do
53
+ expect(env.externalize_path(@vendored_manifest)).to eq(@vendored_manifest)
54
+ end
55
+
56
+ it "leaves paths alone if resolved or configured paths are not set" do
57
+ env.resolved_path = nil
58
+ env.configured_path = nil
59
+ expect(env.externalize_path(@production_manifest)).to eq(@production_manifest)
60
+ end
61
+
62
+ it "replaces resolved paths with configured paths" do
63
+ externalized_path = env.externalize_path(@production_manifest)
64
+ expect(externalized_path).to eq("/etc/puppetlabs/envs/prod/modules/foo/manifests/init.pp")
65
+ end
66
+
67
+ it "handles nil" do
68
+ externalized_path = env.externalize_path(nil)
69
+ expect(externalized_path).to eq(nil)
70
+ end
71
+
72
+ it "appropriately handles mismatched trailing slashes" do
73
+ env.resolved_path = "/opt/puppetlabs/envs/prod_123/"
74
+ externalized_path = env.externalize_path(@production_manifest)
75
+ expect(externalized_path).to eq("/etc/puppetlabs/envs/prod/modules/foo/manifests/init.pp")
76
+ end
77
+
78
+ it "can be disabled with the `report_configured_environmentpath` setting" do
79
+ Puppet[:report_configured_environmentpath] = false
80
+ expect(env.externalize_path(@production_manifest)).to eq(@production_manifest)
81
+ end
82
+ end
83
+
43
84
  describe "equality" do
44
85
  it "works as a hash key" do
45
86
  base = Puppet::Node::Environment.create(:first, ["modules"], "manifests")
@@ -108,6 +108,15 @@ describe Puppet::Parser::Resource do
108
108
  }.to raise_error(ArgumentError, /Resources require a hash as last argument/)
109
109
  end
110
110
 
111
+ it "should attempt to externalize filepaths via the environment" do
112
+ environment = Puppet::Node::Environment.create(:testing, [])
113
+ expect(environment).to receive(:externalize_path).at_least(:once).and_return("foo")
114
+ Puppet[:code] = "notify { 'hello': }"
115
+ catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new 'anyone', environment: environment)
116
+ notify = catalog.resource('Notify[hello]')
117
+ expect(notify.file).to eq("foo")
118
+ end
119
+
111
120
  it "should set the reference correctly" do
112
121
  res = Puppet::Parser::Resource.new("resource", "testing", @arguments)
113
122
  expect(res.ref).to eq("Resource[testing]")
@@ -15,7 +15,7 @@ describe Puppet::Type.type(:file).attrclass(:ctime) do
15
15
  @resource[:audit] = [:ctime]
16
16
 
17
17
  # this .to_resource audit behavior is magical :-(
18
- expect(@resource.to_resource[:ctime]).to eq(Puppet::FileSystem.stat(@filename).ctime)
18
+ expect(@resource.to_resource[:ctime]).to eq(Puppet::FileSystem.stat(@filename).ctime.to_s)
19
19
  end
20
20
 
21
21
  it "should return absent if auditing an absent file" do
@@ -15,7 +15,7 @@ describe Puppet::Type.type(:file).attrclass(:mtime) do
15
15
  @resource[:audit] = [:mtime]
16
16
 
17
17
  # this .to_resource audit behavior is magical :-(
18
- expect(@resource.to_resource[:mtime]).to eq(Puppet::FileSystem.stat(@filename).mtime)
18
+ expect(@resource.to_resource[:mtime]).to eq(Puppet::FileSystem.stat(@filename).mtime.to_s)
19
19
  end
20
20
 
21
21
  it "should return absent if auditing an absent file" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.23.0
4
+ version: 7.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet Labs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-07 00:00:00.000000000 Z
11
+ date: 2023-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: facter
@@ -133,9 +133,6 @@ dependencies:
133
133
  - - "~>"
134
134
  - !ruby/object:Gem::Version
135
135
  version: '1.0'
136
- - - "<"
137
- - !ruby/object:Gem::Version
138
- version: 1.2.0
139
136
  type: :runtime
140
137
  prerelease: false
141
138
  version_requirements: !ruby/object:Gem::Requirement
@@ -143,9 +140,6 @@ dependencies:
143
140
  - - "~>"
144
141
  - !ruby/object:Gem::Version
145
142
  version: '1.0'
146
- - - "<"
147
- - !ruby/object:Gem::Version
148
- version: 1.2.0
149
143
  - !ruby/object:Gem::Dependency
150
144
  name: deep_merge
151
145
  requirement: !ruby/object:Gem::Requirement
@@ -1295,6 +1289,9 @@ files:
1295
1289
  - spec/fixtures/integration/application/agent/lib/facter/agent_spec_role.rb
1296
1290
  - spec/fixtures/integration/application/apply/environments/spec/modules/amod/lib/puppet/provider/applytest/applytest.rb
1297
1291
  - spec/fixtures/integration/application/apply/environments/spec/modules/amod/lib/puppet/type/applytest.rb
1292
+ - spec/fixtures/integration/application/module/environments/direnv/modules/nginx/README
1293
+ - spec/fixtures/integration/application/module/environments/direnv/modules/nginx/manifests/init.pp
1294
+ - spec/fixtures/integration/application/module/environments/direnv/modules/nginx/metadata.json
1298
1295
  - spec/fixtures/integration/l10n/envs/prod/modules/demo/Gemfile
1299
1296
  - spec/fixtures/integration/l10n/envs/prod/modules/demo/Rakefile
1300
1297
  - spec/fixtures/integration/l10n/envs/prod/modules/demo/lib/puppet/functions/l10n.rb
@@ -2544,7 +2541,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
2544
2541
  - !ruby/object:Gem::Version
2545
2542
  version: 1.3.1
2546
2543
  requirements: []
2547
- rubygems_version: 3.1.6
2544
+ rubygems_version: 3.4.12
2548
2545
  signing_key:
2549
2546
  specification_version: 4
2550
2547
  summary: Puppet, an automated configuration management tool
@@ -2555,6 +2552,9 @@ test_files:
2555
2552
  - spec/fixtures/integration/application/agent/lib/facter/agent_spec_role.rb
2556
2553
  - spec/fixtures/integration/application/apply/environments/spec/modules/amod/lib/puppet/provider/applytest/applytest.rb
2557
2554
  - spec/fixtures/integration/application/apply/environments/spec/modules/amod/lib/puppet/type/applytest.rb
2555
+ - spec/fixtures/integration/application/module/environments/direnv/modules/nginx/README
2556
+ - spec/fixtures/integration/application/module/environments/direnv/modules/nginx/manifests/init.pp
2557
+ - spec/fixtures/integration/application/module/environments/direnv/modules/nginx/metadata.json
2558
2558
  - spec/fixtures/integration/l10n/envs/prod/modules/demo/Gemfile
2559
2559
  - spec/fixtures/integration/l10n/envs/prod/modules/demo/Rakefile
2560
2560
  - spec/fixtures/integration/l10n/envs/prod/modules/demo/lib/puppet/functions/l10n.rb