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

Reply via email to