[openstack-dev] [heat][yaql] Deep merge map of lists?

Jiří Stránský jistr at redhat.com
Tue Aug 30 16:18:49 UTC 2016


On 30.8.2016 18:02, Steven Hardy wrote:
> On Tue, Aug 30, 2016 at 04:10:47PM +0200, Jiří Stránský wrote:
>>
>> On 30.8.2016 10:17, Steven Hardy wrote:
>>
>> <snip>
>>
>>> Yeah, that gets us closer, but we do need to handle more than one value
>>> (list entry) per key, e.g:
>>>
>>>          data:
>>>            l:
>>>              - "gnocchi_metricd_node_names": ["a0", "a1", "a2"]
>>>                "tripleo_packages_node_names": ["a0", "a1", "a2"]
>>>              - "nova_compute_node_names": ["b0"]
>>>                "tripleo_packages_node_names": ["b0"]
>>>
>>> Output needs to be like:
>>>
>>>              "gnocchi_metricd_node_names": ["a0", "a1", "a2"]
>>>              "tripleo_packages_node_names": ["a0", "a1", "a2", "b0"]
>>>              "nova_compute_node_names": ["b0"]
>>>
>>
>> Hoping this could do it:
>>
>> [stack at instack ~]$ cat yaq.yaml
>> heat_template_version: 2016-10-14
>>
>> outputs:
>>   debug:
>>     value:
>>       yaql:
>>         expression: $.data.l.reduce($1.mergeWith($2))
>>         data:
>>           l:
>>             - "gnocchi_metricd_node_names": ["a0", "a1", "a2"]
>>               "tripleo_packages_node_names": ["a0", "a1", "a2"]
>>             - "nova_compute_node_names": ["b0"]
>>               "tripleo_packages_node_names": ["b0"]
>
> Thanks for this!
>
> Unfortunately I dont think it works with more than two list items:
>
>   debug_tripleo2:
>     value:
>       yaql:
>         expression: $.data.l.reduce($1.mergeWith($2))
>         data:
>           l:
>             - "gnocchi_metricd_node_names": ["overcloud-controller-0",
>               "overcloud-controller-1", "overcloud-controller-2"]
>               "tripleo_packages_node_names": ["overcloud-controller-0", "overcloud-controller-1", "overcloud-controller-2"]
>             - "nova_compute_node_names": ["overcloud-compute-0"]
>               "tripleo_packages_node_names": ["overcloud-compute-0"]
>               "tripleo_packages_node_names2": ["overcloud-compute-0"]
>             - "ceph_osd_node_names": ["overcloud-cephstorage-0"]
>               "tripleo_packages_node_names": ["overcloud-cephstorage-0"]
>               "tripleo_packages_node_names2": ["overcloud-cephstorage-0"]
>
> $ heat output-show foo5 debug_tripleo2
> stack output show" instead
> Output error: can only concatenate tuple (not "list") to tuple
>
> I've not dug too deeply yet, but assuming that's a yaql error vs a heat bug
> it looks like it won't work.

Hmm yea that's strange, because YAQL has a test case for reduce() with 5 
items:

https://github.com/openstack/yaql/blob/f71a0305089997cbfa5ff00f660920711b04f39e/yaql/tests/test_queries.py#L337-L339

Anyway, good that we have the solution below that works :)

Jirka

>
> However I did find an approach earler with therve which seems to do what is
> needed:
>
>  debug_tripleo:
>     value:
>       yaql:
>         # $.selectMany($.items()).groupBy($[0], $[1][0])
>         # reduce($1 + $2)')
>         # dict($.selectMany($.items()).groupBy($[0], $[1], [$[0],
>         # $[1].flatten()]))
>         expression: dict($.data.l.selectMany($.items()).groupBy($[0], $[1],
> [$[0], $[1].flatten()]))
>         data:
>           l:
>             - "gnocchi_metricd_node_names": ["overcloud-controller-0",
>               "overcloud-controller-1", "overcloud-controller-2"]
>               "tripleo_packages_node_names": ["overcloud-controller-0", "overcloud-controller-1", "overcloud-controller-2"]
>               "tripleo_packages_node_names2": ["overcloud-controller-0", "overcloud-controller-1", "overcloud-controller-2"]
>             - "nova_compute_node_names": ["overcloud-compute-0"]
>               "tripleo_packages_node_names": ["overcloud-compute-0"]
>               "tripleo_packages_node_names2": ["overcloud-compute-0"]
>             - "ceph_osd_node_names": ["overcloud-cephstorage-0"]
>               "tripleo_packages_node_names": ["overcloud-cephstorage-0"]
>               "tripleo_packages_node_names2": ["overcloud-cephstorage-0"]
>
> Output:
>
> $ heat output-show foo5 debug_tripleo
> stack output show" instead
> {
>   "gnocchi_metricd_node_names": [
>     "overcloud-controller-0",
>     "overcloud-controller-1",
>     "overcloud-controller-2"
>   ],
>   "tripleo_packages_node_names": [
>     "overcloud-controller-0",
>     "overcloud-controller-1",
>     "overcloud-controller-2",
>     "overcloud-compute-0",
>     "overcloud-cephstorage-0"
>   ],
>   "ceph_osd_node_names": [
>     "overcloud-cephstorage-0"
>   ],
>   "tripleo_packages_node_names2": [
>     "overcloud-controller-0",
>     "overcloud-controller-1",
>     "overcloud-controller-2",
>     "overcloud-compute-0",
>     "overcloud-cephstorage-0"
>   ],
>   "nova_compute_node_names": [
>     "overcloud-compute-0"
>   ]
> }
>
> It's a bit complex, but I think it will work as a stopgap solution until we
> can land a map_deep_merge function for heat (further yaql optimizations
> welcome! :)
>
> Thanks!
>
> Steve
>
> __________________________________________________________________________
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: OpenStack-dev-request at lists.openstack.org?subject:unsubscribe
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>




More information about the OpenStack-dev mailing list