-
Type:
Bug
-
Status: Done
-
Priority:
Blocker
-
Resolution: Fixed
-
Affects Version/s: 3.11.0b1
-
Labels:
Mustache template rendering duplicates data with
Expected output:
# Mustache duplication issue test # Test1 Data = v1 Data = v2 # Test2 Data = v1 Data = v2 Other data = v3 Other data = v4
Produced output (note data duplication in Test2 series):
# Mustache duplication issue test # Test1 Data = v1 Data = v2 # Test2 Data = v1 Data = v2 Other data = v3 Other data = v4 Data = v1 Data = v2 Other data = v3 Other data = v4
This was discussed on #cfengine. Here is the chat log excerpt:
14:38| TedZ| OK, I'll look at just JSON then 14:43| TedZ| OK, I see it. When you iterate over a key-value container, you iterate over every key and value pair. 14:43| TedZ| so your template for test 2 sees two keys and iterates twice. 14:44| TedZ| simply change test2 to an array wrapping the key-value container: "test2": [{ 14:44| TedZ| "data": [ 14:44| TedZ| "v1", 14:44| TedZ| "v2" 14:44| TedZ| ], 14:44| TedZ| "otherdata": [ 14:44| TedZ| "v3", 14:44| TedZ| "v4" 14:44| TedZ| ] 14:44| TedZ| }] 14:44| TedZ| 14:44| TedZ| sorry for the paste, I didn't mean to flood 14:45| * neilhwatson head hurts 14:45| cfbot| If you write your own CFEngine policy make it as reusable as possible. 14:46| dsx| ok, why that worked in 3.6? 14:46| TedZ| dsx is iterating over test2. test2 has two things in it. So the template iterates twice. 14:46| neilhwatson| What if the template had stated test2.data rather than data? 14:47| TedZ| dsx: not sure, my guess is that it was a bug in 3.6. I would check the official Mustache spec to be sure about this, but I think I'm right. 14:47| TedZ| neilhwatson: test2.data inside the test2 iteration would look for test2.test2.data 14:49| dsx| TedZ: as far as I know, mustache came from JS world, and in JS iterating over a map would essentially iterate over map keys 14:52| TedZ| right, so the behavior is correct and my workaround seems the best way forward. 14:59| dsx| TedZ: no, behavior is not correct. also, if you have time and curiosity, here is the official demo: http://mustache.github.io/#demo and here is template and data to put in: http://hastebin.com/efawofifew.txt 15:06| TedZ| dsx: at this point I'd take your example and open a ticket. It seems like we have a disagreement on the official spec. From https://mustache.github.io/mustache.5.html I am certain non-empty lists are rendered sequentially, but it's not clear if key-value containers are treated as lists, and they don't have a specific iteration behavior. We're not going to resolve it here, but I think we've at least understood the problem.
Some policy for CFE-2125
bundle agent main { vars: "data" data => '{ "object0": { "object0-0": { "object0-0-0": [ "v1", "v2" ] }, "object0-1": { "object0-1-0": [ "v1", "v2" ], "object0-1-1": [ "v3", "v4" ] } }, "object1": [ "object1-val1", "object1-val2" ], "non-false": { "color": "blue" }, "false": false }'; # Iterate over top object rendering keys with custom extension. -top- is # also a custom extension "iterate_object_keys" string => "# Iterate over custom -top- object rendering keys with custom extension `@`. {{#-top-}}{{@}} {{/-top-}}"; "at_also_iterate_array_vals" string => "# Iterate over array rendering keys (postion) with custom variable `@`. {{#object1}}Iterate array key {{@}} = {{.}} {{/object1}}"; "iterate_array_vals" string => "# Iterate over array rendering keys with standard variable `.` {{#object1}}Data = {{.}} {{/object1}}"; "iterate_deep_array_vals" string => "# Iterate over deep/nested array rendering keys with standard variable `.` {{#object0.object0-0.object0-0-0}}object0.object0-0.object0-0-0 = {{.}} {{/object0.object0-0.object0-0-0}}"; # Use non-false value as context for single rendering of block "deep_object_no_sub_objects" string => "# Use a deep object reference to provide the context for the template {{#object0.object0-1.object0-1-0}}object0-1-0 Key {{@}}, object0-1-0 Value {{.}} {{/object0.object0-1.object0-1-0}}"; # Use non-false value as context for single rendering of block "template" string => "# This should not print twice! Why should it NOT behave like deep_object_no_sub_objects above {{#object0.object0-1}} {{#object0-1-0}}object0-1-0 Key {{@}}, object0-1-0 Value {{.}} {{/object0-1-0}}{{/object0.object0-1}}"; reports: "CFEngine $(sys.cf_version)"; "# Data.$(const.n)$(with)" with => string_mustache( '{{%-top-}}', @(data) ); "$(with)" with => string_mustache( $(iterate_object_keys), @(data) ); "$(with)" with => string_mustache( $(at_also_iterate_array_vals), @(data) ); "$(with)" with => string_mustache( $(iterate_array_vals), @(data) ); "$(with)" with => string_mustache( $(iterate_deep_array_vals), @(data) ); "$(with)" with => string_mustache( $(deep_object_no_sub_objects), @(data) ); "$(with)" with => string_mustache( $(template), @(data) ); }
R: CFEngine 3.11.0 R: # Data. { "false": false, "non-false": { "color": "blue" }, "object0": { "object0-0": { "object0-0-0": [ "v1", "v2" ] }, "object0-1": { "object0-1-0": [ "v1", "v2" ], "object0-1-1": [ "v3", "v4" ] } }, "object1": [ "object1-val1", "object1-val2" ] } R: # Iterate over custom -top- object rendering keys with custom extension `@`. object0 object1 non-false false R: # Iterate over array rendering keys (postion) with custom variable `@`. Iterate array key 0 = object1-val1 Iterate array key 1 = object1-val2 R: # Iterate over array rendering keys with standard variable `.` Data = object1-val1 Data = object1-val2 R: # Iterate over deep/nested array rendering keys with standard variable `.` object0.object0-0.object0-0-0 = v1 object0.object0-0.object0-0-0 = v2 R: # Use a deep object reference to provide the context for the template object0-1-0 Key 0, object0-1-0 Value v1 object0-1-0 Key 1, object0-1-0 Value v2 R: # This should not print twice! Why should it NOT behave like deep_object_no_sub_objects above object0-1-0 Key 0, object0-1-0 Value v1 object0-1-0 Key 1, object0-1-0 Value v2 object0-1-0 Key 0, object0-1-0 Value v1 object0-1-0 Key 1, object0-1-0 Value v2
- relates to
-
CFE-1565 Mustache sections can only take a boolean or a container (array or map) value
-
- To Do
-