Hi,
I am wanting to use the environment
task parameter with dictionaries taken from two roles, e.g.
in roles/ruby/vars/main.yml
:
ruby_environment:
GEM_HOME: "/home/deploy/.gem/ruby/2.1.2"
PATH: "/home/deploy/.gem/ruby/2.1.2/bin:/opt/rubies/ruby-2.1.2/lib/ruby/gems/2.1.0/bin:/opt/rubies/ruby-2.1.2/bin"
in roles/rails/tasks/main.yml
, I am wanting to do something like this:
- name: execute bundler
command: bundle install --deployment
environment:
"{{ ruby_environment }}" merged with "RAILS_ENV: production"
Is this possible?
Thanks,
Steve
To add: would prefer not to use hash_behaviour = merge if possible.
I think this might be proposing something like a jinja2 filter that merges one hash with another and returns it.
I’m not aware of this, but some other folks go deeper than me.
I’m not opposed to a filter plugin function being added that does this being added if that makes sense.
I thought it might be possible to loop over each hash respectively and then create a new one with all of those.
That in particular, I’d think no.
What I’d really like might look something like
environment: “{{ dict1 | update(dict2) }}”
Anybody done anything like that with stock Jinja2-voodoo magic? If not, it’s about a two liner in filter_plugins/core.py to expose the native hash update function.
dict1 + dict2
I also have an update to ‘set theory’ that will allow you to do dict1|union(dict2)
So that’s a thing already with {{ dict1 + dict2 }}?
Nice.
Not really. Python doesn’t allow to merge two hashes using “{{ env1 + env2 }}”. Here’s what worked for me:
playbooks/filter_plugins/filters.py:
I think your filter plugin could be more easily written:
hash_a.update(hash_b)
perhaps?
If you send in a pull request, this seems reasonable to have as a core filter.
I’d probably call it ‘update’ if I’m correct on the above, which I think I am. If not, perhaps “merge”.
I could swear I had patched the union filter to use update when dicts were passed in, let me try this again.
Brian Coca
It would be nicer to have a filter for jinja2, but this works:
defaults.yml
d1:
k1: 1
d2:
k1: 2
k2: 3
tasks/main.yml
name: dbg
debug: msg=“{{d1}} {{d2}}”
set_fact:
d1: “{% do d1.update(d2) %}{{d1}}”
debug: msg=“{{d1[‘k1’]}}”
OUTPUT
TASK: [gnf_data | dbg] ********************************************************
ESTABLISH CONNECTION FOR USER: ubuntu
ok: [deploy-test-1] => {
“msg”: “{‘k1’: 1} {‘k2’: 3, ‘k1’: 2}”
}
TASK: [gnf_data | set_fact ] **************************************************
ESTABLISH CONNECTION FOR USER: ubuntu
ok: [deploy-test-1] => {“ansible_facts”: {“d1”: {“k1”: 2, “k2”: 3}}}
TASK: [gnf_data | debug msg=“{{d1[‘k1’]}}”] ***********************************
ESTABLISH CONNECTION FOR USER: ubuntu
ok: [deploy-test-1] => {
“msg”: “2”
}
T.N_T
(T.N. T.)
March 16, 2015, 2:39pm
12
I had exactly the same idea. Did anybody do a PR for this? I don’t see it in 1.9 nor in devel.
If nobody else has time for it I could do it. I think this is really a gap. Anyway this way is definitely more what they call pythonic than tweaking the union filter.
My code is simply:
`
`
def update(dic, odic):
dic.update(odic)
return dic
class FilterModule(object):
def filters(self):
return {
‘update’: update,
‘update_dict’: update,
‘merge_dict’: update
}
`
`
there is a hash_merge PR pending but it won't make it into 1.9.
T.N_T
(T.N. T.)
March 16, 2015, 5:09pm
14
Looks nice. And nice to know. Thank you!
kevin
August 21, 2015, 6:15pm
15
Looks like update doesn’t do a recursive hash merge. This might be the solution, https://www.xormedia.com/recursively-merge-dictionaries-in-python/
Is the best practice be to add this as a jinja filter?
vadyochik
(vadyochik)
August 26, 2016, 4:35pm
16