Ansible is great, I love it! But my first encounter with it
was not pleasant, in fact, it was painful: I was seriously confused by its
syntax, it looks so simple but it has so many small traps that can easily trip
you, and when you fall, the error messages are sometimes mysterious.
It took me a while to get used to the peculiarities of
Ansible syntax, and in this blog, I will share my hard-learn lessons.
All tests are conducted with Ansible:
vagrant@ctrl:/elkcloud/ansible$ ansible
--version
ansible 2.0.2.0 (detached HEAD 7e05cc4e74) last updated
2016/04/25 18:29:09 (GMT +800)
Whitespaces
There are places that there must be whitespaces, and there
are places that there must not be whitespaces.
#there
mustn't be whitespaces surrounding = in set_fact
-
name: set a variable
set_fact: v1="abc1"
tags: [t1]
#there mustn't be whitespaces surrounding =
in debug
#otherwise, Ansible will throw an error
complaining about syntax
-
debug: var=v1
tags: [t1]
#if there are whitespaces surrounding =
#debug it will output:
#"v2": "VARIABLE IS NOT
DEFINED!"
-
name: set a variable
set_fact: v2 = "abc2"
tags: [t1]
-
debug: var=v2
tags: [t1]
#there must be whitespace after : in set_fact
#otherwise Ansible will throw an error
complaining about syntax
-
name: set a variable
set_fact:
v3: "abc3"
v4: "abc4"
tags: [t1]
when to use {{variable }}
I used to be tripped by this big time, until I figured out
this: {{ variable }} de-references
the variable, meaning, {{ variable }}
gets the variable value; you should use {{
variable }} when you set_fact,
or concat a string; you should use variable
in almost everywhere else.
Debugging in Ansible typically uses debug task, be careful of its usage. debug var=variable, requires a variable,
not a variable value, in other words, you shouldn’t use debug var={{variable}}. Here is a piece of code
demonstrating this:
-
name: set var1
set_fact:
var1: "abc"
tags: [t2]
# "var1": "abc"
-
debug: var=var1
tags: [t2]
#set_fact should assign a value to a varialbe
-
name: set var2
set_fact:
var2: "{{var1}}"
tags: [t2]
# "var2": "abc"
-
debug: var=var2
tags: [t2]
# debug: var should use the variable, if use the value, debug will
treat the value as a variable and try to dereference it
#"abc": "VARIABLE IS NOT
DEFINED!"
-
debug: var={{var2}}
tags: [t2]
-
name: set var3
set_fact:
var3: var1
tags: [t2]
#if set_fact assigns a variable to a variable, Ansible is not able to
deference to get the value
#"var3": "var1"
-
debug: var=var3
tags: [t2]
#if set_fact assigns a variable to a variable, Ansible is
not able to deference to get the value
# "msg": "var1"
-
debug: msg={{var3}}
tags: [t2]
#if set_fact assigns a variable to a variable, Ansible is
not able to deference to get the value
#stdout: var1
-
name: check variable dereference
shell: echo {{ var3 }}
tags: [t2]
Some part of this seems already counter-intuitive, when
there are nested variables, some logic seems even more counter-intuitive.
- name: set a nested var
set_fact:
nestedvars:
dbs:
nodes:
localhost: ["a","b","c"]
tags: [t3]
-
name: set v
set_fact:
v: "dbs"
tags: [t3]
#"nestedvars[v].nodes.localhost":
[
#
"a",
#
"b",
#
"c"
# ]
-
debug: var=nestedvars.{{v}}.nodes.{{inventory_hostname}}
tags: [t3]
#"nestedvars[v].nodes.localhost":
[
#
"a",
#
"b",
#
"c"
# ]
-
debug: var=nestedvars[v].nodes.{{inventory_hostname}}
tags: [t3]
#
"nestedvars[v].nodes[inventory_hostname]": [
# "a",
#
"b",
#
"c"
#
]
-
debug: var=nestedvars[v].nodes[inventory_hostname]
tags: [t3]
#nestedvars.v.nodes.localhost":
"VARIABLE IS NOT DEFINED!
-
debug: var=nestedvars.v.nodes.{{inventory_hostname}}
tags: [t3]
So far so good, but when nested variables are used with with_items, the logic is not
consistent:
#nestedvars.dbs.nodes.localhost
- name:
echo item1
shell: echo {{item}}
with_items:
nestedvars.{{v}}.nodes.{{inventory_hostname}}
tags: [t3]
#nestedvars[v].nodes.localhost
-
name: echo item2
shell: echo {{item}}
with_items:
nestedvars[v].nodes.{{inventory_hostname}}
tags: [t3]
#nestedvars.dbs.nodes[inventory_hostname]
-
name: echo item3
shell: echo {{item}}
with_items: nestedvars.{{ v
}}.nodes[inventory_hostname]
tags: [t3]
#changed: [localhost] => (item=a)
#changed: [localhost] => (item=b)
#changed: [localhost] => (item=c)
-
name: echo item4
shell: echo {{item}}
with_items:
nestedvars[v].nodes[inventory_hostname]
tags: [t3]
The rule of thumb seems to be: when use a nested variable
with with_items, if the key is a
variable, use [key_variable],
not {{key_variable}}.This rule of thumb seems rather arbitrary, but remembering it
saves me a lot of confusion.
One more arbitrary rule of them is: delegate_to must be used with a value, not a variable.
No comments:
Post a Comment