Skip to content

Commit 1066460

Browse files
committed
(PUP-10928) Add allow_pson_serialization setting
Currently, Puppet will fall back to PSON when unable to serialize to JSON. This can cause issues since rich data types cannot be serialized via PSON. Due to this, PSON will eventually be depreceated and removed in future releases. This commit adds a setting, :allow_pson_serialization, which defaults to false in Puppet 7 and will default to true in Puppet 8. When set to false, a warning will be raised when falling back to PSON and when set to true, an error will be raised instead. This option affects both puppetserver's configuration management service responses and when the agent saves its cached catalog.
1 parent affec3c commit 1066460

File tree

4 files changed

+50
-5
lines changed

4 files changed

+50
-5
lines changed

lib/puppet/defaults.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,15 @@ def self.initialize_default_settings!(settings)
17111711
can be guaranteed to support this format, but it will be used for all
17121712
classes that support it.",
17131713
},
1714+
:allow_pson_serialization => {
1715+
:default => true,
1716+
:type => :boolean,
1717+
:desc => "Whether when unable to serialize to JSON or other formats,
1718+
Puppet falls back to PSON. This option affects both puppetserver's
1719+
configuration management service responses and when the agent saves its
1720+
cached catalog. This option is useful in preventing the loss of data because
1721+
rich data cannot be serialized via PSON.",
1722+
},
17141723
:agent_catalog_run_lockfile => {
17151724
:default => "$statedir/agent_catalog_run.lock",
17161725
:type => :string, # (#2888) Ensure this file is not added to the settings catalog.

lib/puppet/indirector/catalog/json.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@ def from_json(text)
1818
def to_json(object)
1919
object.render(json_format)
2020
rescue Puppet::Network::FormatHandler::FormatError => err
21-
Puppet.info(_("Unable to serialize catalog to json, retrying with pson"))
22-
Puppet.log_exception(err, err.message, level: :debug)
23-
object.render('pson').force_encoding(Encoding::BINARY)
21+
if Puppet[allow_pson_serialization]
22+
Puppet.info(_("Unable to serialize catalog to json, retrying with pson. PSON is deprecated and will be removed in a future release"))
23+
Puppet.log_exception(err, err.message, level: :debug)
24+
object.render('pson').force_encoding(Encoding::BINARY)
25+
else
26+
Puppet.info(_("Unable to serialize catalog to json, no other acceptable format"))
27+
Puppet.log_exception(err, err.message, level: :err)
28+
end
2429
end
2530

2631
private

lib/puppet/network/http/api/indirected_routes.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,13 @@ def first_response_formatter_for(model, request, key, &block)
192192
yield format
193193
true
194194
rescue Puppet::Network::FormatHandler::FormatError => err
195-
Puppet.warning(_("Failed to serialize %{model} for '%{key}': %{detail}") %
196-
{model: model, key: key, detail: err})
195+
msg = _("Failed to serialize %{model} for '%{key}': %{detail}") %
196+
{model: model, key: key, detail: err}
197+
if Puppet[:allow_pson_serialization]
198+
Puppet.warning(msg)
199+
else
200+
raise Puppet::Network::FormatHandler::FormatError.new(msg)
201+
end
197202
false
198203
end
199204
end

spec/unit/network/http/api/indirected_routes_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,19 @@
210210
handler.call(request, response)
211211
}.to raise_error(not_found_error)
212212
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
213226
end
214227

215228
describe "when searching for model instances" do
@@ -250,6 +263,19 @@
250263
%r{No supported formats are acceptable \(Accept: application/json, text/pson\)})
251264
end
252265

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+
253279
it "should return [] when searching returns an empty array" do
254280
request = a_request_that_searches(Puppet::IndirectorTesting.new("nothing"), :accept_header => "unknown, application/json")
255281

0 commit comments

Comments
 (0)