get value from manual grains doesn't work currently - jinja2

trying to get Grains value in Jinja template but i dont know how to get it to work..
i'm traing to get fqdn and manually added grain (appfqdn)
here is the jinja
{%- set SERVERNAME = grains['fqdn'] -%}
{%- set APPTIER = grains['appfqdn'] -%}
the result of first line work very well. i get the fqdn of the server.
2nd one doesn't. i got it like this: [u'client02.lab.home']
as you can see there is u and ' and []
not sure how to grab it correctly.
also when i grab the value on salt master manfully with json format output. this is hop i get it.
salt 'client03.lab.home' grains.item fqdn --out json
{
"client03.lab.home": {
"fqdn": "client03.lab.home"
}
}
salt 'client03.lab.home' grains.item appfqdn --out json
{
"client03.lab.home": {
"appfqdn": [
"client02.lab.home"
]
}
}
not sure how to use jinja to get the value correctly without the single quot, the u and brackets..
Thank you

I found the the solution.
{%- set APPTIER = grains['appfqdn'][0] -%}
was able to to get the right result.

Related

How to pass variable while calling macros in post hook?

Currently I am calling macros in such a way:
"post_hook":["{{macros_append('string1','string2')}}"]})}}
I want to call it as
"post_hook":["{{macros_append(var1,var2)}}"]})}}
I have already tried setting variable before config like
{% set var1='value' %}
"post_hook":["{{macros_append(var1,var2)}}"]})}}
But this does not work. It does not take any value while calling macros.
This doesn't work because dbt is parsing the jinja of your post-hook in a different context from the model file. In short, the post-hook needs to stand on its own.
This is true of all configs. The hints are:
post_hook takes a list of strings. Those strings later get templated by the jinja templater. (this is why you quote them and nest the curlies! you should never really nest curlies otherwise)
Configs can also get passed in through .yml files, etc., which is partially why the templating is deferred
Your question omits the actual call to the config macro, which makes this a little more clear:
{{
config({
"post_hook": ["{{macros_append('string1','string2')}}"]
})
}}
So what are we to do? You could use jinja to build the string that gets passed into the config block. This is hacky and ugly, but it works:
(Note that ~ is the jinja string concatenation operator.)
{% set var1 = "string1" %}
{% set var2 = "string2" %}
{{
config({
"post_hook": ["{{ macros_append(" ~ var1 ~ "," ~ var2 ~ ") }}"]
})
}}
A slightly cleaner version of this would be to define the whole macro call in a variable, so you don't have to do the concatenation:
{% set my_hook = "{{ macros_append('string1', 'string2') }}" %}
{{
config({
"post_hook": [my_hook]
})
}}
A Better Way
Another option is to use the var() macro, which allows you to access a global variable in the jinja context. You define these global variables in your dbt_project.yml file:
...
vars:
var1: string1
var2: string2
and then you can access them with {{ var('var1') }} from any process that is templating jinja. In the case of your config block, that would look like:
{{
config({
"post_hook": ["{{ macros_append(var('var1'), var('var2')) }}"]
})
}}
Note that the post-hook here is just a string that contains the string "var('var1')", but that's fine, since the templater will fill that in later, when the string is templated.

jinja2 navigate dynamically to json object [duplicate]

This question already has answers here:
How can I use Ansible nested variable?
(2 answers)
Closed 4 years ago.
My question looks trivial but I already spend some hours on it.
How to dynamically navigate into a json variable, with jinja2.
ex: I get
ansible_lvm.vgs:
"vgs": {
"vgdata": {
"free_g": "16",
"size_g": "0"
},
"vgswap": {
"free_g": "0",
"size_g": "00"
}
}
In a jinja2 structure I would like to get "free_g" attribut for "vgdata":
None of the code hereafter works:
{% set my_vg_name = 'vg_data' %}
{% set my_vg_size = ansible_lvm.vgs.(my_vg_name).free_g %}
{% set my_vg_size = ansible_lvm.vgs.{{my_vg_name}}.free_g %}
{% set my_vg_size = ansible_lvm.vgs|selectattr(my_vg_name, 'free_g') %}
Thanks for your help,
So, I hope that code snippet at the top is just an example, and not really what you are using, since it's malformed JSON. And I hope you are not actually asking the vgs object for vg_data when the key is vgdata, because that will never end well.
That aside:
You access dict objects in python using vgs[my_vg_name] syntax, or if you aren't sure that vgs contains that key, vgs.get(my_vg_name, {}) to provide an empty dict as the default if vgs does not contain a key whose value is in the my_vg_name variable.
Perhaps it's just a bad question, but if you always want vgdata.free_g then why the dynamic access at all?

re-use pillar values in salt(-ssh)

I am currently getting familiar with salt and wonder how I could re-use the values of pillars in other places (sections) in .sls files.
In buildout, I would be able to reference a variable from another section with ${sectionname:varname} to re-use a once defined value. This is especially handy, when dealing with directories (basedir, appdir). buildout example:
['foo']
path = /highway/to/hell
['bar']
path = ${foo:path}/lastexit
When I try to reference another variable in an .sls file, even if it is in the same file, I get always None. salt example:
foo:
path: /highway/to/hell
bar:
path: {{ salt['pillar.get']('foo:path') }}/lastexit
salt-ssh minion1 pillar.get bar:path results in None/lastexit
I have the feeling, that I'm missing something here. Could someone point out, how one does re-use values in salt .sls
You can use jinja to assign a value, e.g.:
{% set base_path = salt['pillar.get']('foo:path','/highway/to/hell') %}
foo:
path: {{ base_path }}
bar:
path: {{ base_path }}/lastexit
In this case "/highway/to/hell" is set as a default in case no value is assigned in the pillar or no pillar is found. For more info, see https://docs.saltstack.com/en/latest/topics/jinja/index.html

Creating list of ip's in ansible using given range within jinja template

i want to generate a list of ip addresses (using range of last 8bits so 120-190 translates to x.x.x.120 - x.x.x.190) in defaults/main.yml in my role, and later use it to create new network interfaces and generate a new config file. I tried this approach:
defaults/main.yml:
ip_list: "{%for address_end in range(50,99)%} 192.168.0.{{address_end}}{%endfor%}"
conf_list: "{%for ip in ip_list%}server {{ip}}:6666 {%endfor%}"
and then to use it in template
template.conf.j2:
{% for conf_line in conf_list %}
{{conf_line}}
{% endfor %}
and all i got in generated config file was:
s
e
r
v
e
r
:
6
6
6
6
s
e
r
v
e
r
1
:
6
so my guess is that i'm not generating a list but just a long string and when I use for loop in template.conf.j2 I iterate over single chars. I tried using answer to this problem but all i got was syntax error. Any ideas for what might help me ?
You should format your vars as JSON lists if you want them to be lists.
1.1.1.1 2.2.2.2 3.3.3.3 is a string.
['1.1.1.1', '2.2.2.2', '3.3.3.3'] will be converted to list.
But there is alternative approach for you:
ip_list: "{{ lookup('sequence', 'start=50 count=12 format=192.168.0.%d', wantlist=True) }}"
conf_list: "{{ ip_list | map('regex_replace','(.*)','server \\1:6666') | list }}"
Kostantin answer was of much help, but i found just realized that generating config entries in my case could be solved in an less complex way. Instead of trying to iterate over list or a string variable variable in jinja template file template.conf.j2 like did with :
{% for conf_line in conf_list %}
{{conf_line}}
{% endfor %}
you could just enter insert new line signs while generating string in defaults/main.yml:
conf_list: "{%for ip in ip_list%}server {{ip}}:6666\n{%endfor%}"
and then just insert that whole string into a template.conf.j2 like this:
{{conf_line}}
nevertheless i have no other idea how to generate list of ip addresses other than the one Konstantin proposed.

How to grab a string before hyphen using Jinja2?

My variable is as such:
api-20150901r1_6.38
Using Jinja, I need a way to grab the string BEFORE the hyphen. There will always be one hyphen so I dont need to worry about multiple instances.
Assuming input_string is api-20150901r1_6.38
You can use set
{% set mylist = input_string.split('-') %}
This is your value "api" in this case
{{ mylist[0] }}