Ori.livneh has submitted this change and it was merged. Change subject: ordered_yaml(): fix for Ruby 1.8 ......................................................................
ordered_yaml(): fix for Ruby 1.8 This patch reverts I62605c2a2, restoring the previous (and known-good) version of ordered_json(). It also fixes the implementation of ordered_yaml(), which didn't work properly with Ruby 1.8. Hash keys in Ruby 1.8 are not sorted in insertion order, so it's not sufficient to recursively copy keys in sorted order into a new hash. Instead, we patch the .each_pair method to iterate on keys in sorted order. We only do this for hashes we create. Change-Id: Ieb08e604ef3552c928c78aab2d44a7bae7966dd6 --- M modules/wmflib/lib/puppet/parser/functions/ordered_json.rb D modules/wmflib/lib/puppet/parser/functions/ordered_yaml.rb A modules/wmflib/lib/puppet/parser/functions/ordered_yaml.rb 3 files changed, 65 insertions(+), 23 deletions(-) Approvals: Ori.livneh: Looks good to me, approved jenkins-bot: Verified diff --git a/modules/wmflib/lib/puppet/parser/functions/ordered_json.rb b/modules/wmflib/lib/puppet/parser/functions/ordered_json.rb index 2881495..c241444 100644 --- a/modules/wmflib/lib/puppet/parser/functions/ordered_json.rb +++ b/modules/wmflib/lib/puppet/parser/functions/ordered_json.rb @@ -1,33 +1,43 @@ -# == Functions: ordered_json(), ordered_yaml() +# == Function: ordered_json # -# Emit a hash as JSON or YAML with keys (both shallow and deep) sorted -# in lexicographical order. +# Serialize a hash into JSON with lexicographically sorted keys. # -require 'json' -require 'yaml' - -def sort_keys_recursive(value) - # Prepare a value for JSON or YAML serialization by sorting its keys - # (if it is a hash) and the keys of any hash object that is contained - # within the value. Returns a new value. - case value +# Because the order of keys in Ruby 1.8 hashes is undefined, 'to_pson' +# is not idempotent: i.e., the serialized form of the same hash object +# can vary from one invocation to the next. This causes problems +# whenever a JSON-serialized hash is included in a file template, +# because the variations in key order are picked up as file updates by +# Puppet, causing Puppet to replace the file and refresh dependent +# resources on every run. +# +# Copyright 2014 Ori Livneh +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +def ordered_json(o) + case o when Array - value.map { |elem| sort_keys_recursive(elem) } + '[' + o.map { |x| ordered_json(x) }.join(', ') + ']' when Hash - value.sort.inject({}) { |h, (k, v)| h[k] = sort_keys_recursive(v); h } - when 'true', 'false' - value == 'true' - when :undef - nil + '{' + o.sort.map { |k,v| k.to_pson + ': ' + ordered_json(v) }.join(', ') + '}' else - value.include?('.') ? Float(value) : Integer(value) rescue value + o.include?('.') ? Float(o).to_s : Integer(o).to_s rescue o.to_pson end end module Puppet::Parser::Functions - {:ordered_json => :to_json, :ordered_yaml => :to_yaml}.each do |func, method| - newfunction(func, :type => :rvalue, :arity => 1) do |args| - sort_keys_recursive(args.first).send(method).gsub(/^---\s*/, '') << "\n" - end + newfunction(:ordered_json, :type => :rvalue) do |args| + fail 'ordered_json() requires an argument' if args.empty? + ordered_json(args.inject(:merge)) end end diff --git a/modules/wmflib/lib/puppet/parser/functions/ordered_yaml.rb b/modules/wmflib/lib/puppet/parser/functions/ordered_yaml.rb deleted file mode 120000 index f6b7e00..0000000 --- a/modules/wmflib/lib/puppet/parser/functions/ordered_yaml.rb +++ /dev/null @@ -1 +0,0 @@ -ordered_json.rb \ No newline at end of file diff --git a/modules/wmflib/lib/puppet/parser/functions/ordered_yaml.rb b/modules/wmflib/lib/puppet/parser/functions/ordered_yaml.rb new file mode 100644 index 0000000..2e2b188 --- /dev/null +++ b/modules/wmflib/lib/puppet/parser/functions/ordered_yaml.rb @@ -0,0 +1,33 @@ +# == Function: ordered_yaml() +# +# Emit a hash as YAML with keys (both shallow and deep) in sorted order. +# +require "puppet/util/zaml.rb" + +def sort_keys_recursive(value) + # Prepare a value for YAML serialization by sorting its keys (if it is + # a hash) and the keys of any hash object that is contained within the + # value. Returns a new value. + case value + when Array + value.map { |elem| sort_keys_recursive(elem) } + when Hash + map = {} + def map.each_pair + map.sort.each { |p| yield p } + end + value.sort.inject(map) { |h, (k, v)| h[k] = sort_keys_recursive(v); h } + when 'true', 'false' + value == 'true' + when :undef + nil + else + value.include?('.') ? Float(value) : Integer(value) rescue value + end +end + +module Puppet::Parser::Functions + newfunction(:ordered_yaml, :type => :rvalue, :arity => 1) do |args| + ZAML.dump(sort_keys_recursive(args.first)).gsub(/^---\s*/, '') << "\n" + end +end -- To view, visit https://gerrit.wikimedia.org/r/154366 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ieb08e604ef3552c928c78aab2d44a7bae7966dd6 Gerrit-PatchSet: 4 Gerrit-Project: operations/puppet Gerrit-Branch: production Gerrit-Owner: Ori.livneh <o...@wikimedia.org> Gerrit-Reviewer: BBlack <bbl...@wikimedia.org> Gerrit-Reviewer: Ori.livneh <o...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits