TPeters
Flight Engineer
Flight Engineer
  • 1,001 Views

What exactly is a "vars: " block?

Jump to solution

I am confused what kind of beast a "vars: " block in a playbook is.

Apparently both these are legal syntax:

  vars:

    my_var: "my_value"

which looks like a dictionary; but also:

  vars:

    - my_var: "my_value"

which looks like a list.

In contrast, vars_files must be a list even with a single entry:

  vars_files:

    - /wherever/it/is

 

 

 

1 Solution

Accepted Solutions
Travis
Moderator
Moderator
  • 976 Views

@TPeters -

I want to provide a tiny bit more information directly related to your question on VARS Block.

So there are multiple ways to provide variables to Ansible (depending on the type some of them are automatic). When providing these variables (outside of the special variables and variables defined in inventory or the command line), there are two methods for specifying or providing variables directly in a playbook. Those two methods are vars: and vars_files: both of which provide the ability to instruct the playbook that you've defined variables.

One of the things I emphasize when delivering a course (especially the intro Ansible course) everything in Ansible is a List/Dictionary and from there, you just build out and expand using a comination of Lists/Dictionaries. At the play level, I emphasize the playbook directives are key: value pairs belonging to the play at the first indentation level. Depending on the key, the value can be a single value (most likely a string), a list, or a dictionary value.

At the play level we have name, hosts, vars, vars_files, tasks, roles, pre-tasks, post-tasks, and handlers. Yes, there are some other special things we can put in there to override configuration files and users and things, but those are the top ones.The tasks and the vars_files are always expecting the items as a list of tasks or files to process and handle (again, these will be lists and possibly lists of dictionaries). If you think about a task, the indentation level in there is essentially a list of dictionaries (key: value pairs). Where a task must always have a module, but it is generally recommended it has a name prior to the module and then the next indentation is the dictionary items that go with the module (key: value pairs) needed to make the module function as intended.

So why is the vars: block confusing ...? Simply put, this is the way for Ansible to get variables for your playbook. These variables can be many things and there is a single vars: block defined for each play. That means it must accept a list of variable values. What is more, as you pointed out some variables can be dictionaries, so vars: must also accept a dictionary. Therefore, when you boil even a regular variable definition down and you think to look at it conceptually, even a basic variable can be viewed as a dictionary.

For example:

my_pkg: vim

The my_pkg is the variable name, but you could also look at it as the KEY for the dictionary. The value for the variable is vim but it could also be looked at as the dictionary value for the KEY.

So if you approach things this way, the vars: block accepts a list of dictionaries. When there is only one thing specified, you don't need the "-" for the list.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#where-to-set-variabl...

Variables are DICTIONARIES as you hopefully can see using the reference above. Keep in mind ... variable precedence the highest is the "extra variable" specified on the command line ... it is done with -e  "key=value" so hoping that also helps illustrate the point on variables being treated like a dictionary.

To expand things further from your example ...

vars:
    my_var: 
      - "my_value1"
      - "my_value2"
      - "my_value3"

You can take your DICTIONARY variable and now the my_var values are actually a list (think of my_var) as maybe being packages to install. So again, the vars: block in the playbook is a very powerful option of defining variables for tasks and roles. 

As you work more with Ansible, you will most likely find yourself beginning to use host/group variables in inventory and having only a minimum number of variables in the playbook. This is how I work with larger teams. For my demos, I almost always put things in a vars: block or vars_files: to make it easier to figure things out and understand, but as you work with larger projects and maybe take the DO374 you will soon see the power and advantages of using inventory group/host variables.

Hope this along with @Chetan_Tiwary_ 's answer helps clear things up.

 

@Trevor_Chandler - I know you like interesting conversations so I thought this might be a good read for you.

Travis Michette, RHCA XIII
https://rhtapps.redhat.com/verify?certId=111-134-086
SENIOR TECHNICAL INSTRUCTOR / CERTIFIED INSTRUCTOR AND EXAMINER
Red Hat Certification + Training

View solution in original post

6 Replies
Chetan_Tiwary_
Moderator
Moderator
  • 987 Views

Hello @TPeters !
Ansible variables are like chameleons of configuration. They adapt and shift based on your needs, allowing you to customize, flex, and reuse playbooks and roles across different environments. No need of hardcoding details - variables can  let you manage complex tasks with the same playbook, on any system, in multiple contexts. 

Totally depends upon how you want to define it and use it.

You can have :   List, dictionary, nested , string, integer, magic , connection, special, runtime, play , block, registering & extra variables .

And yes, vars_files  that is a list of  include variables defined in external file/s.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html 

 

0 Kudos
Travis
Moderator
Moderator
  • 977 Views

@TPeters -

I want to provide a tiny bit more information directly related to your question on VARS Block.

So there are multiple ways to provide variables to Ansible (depending on the type some of them are automatic). When providing these variables (outside of the special variables and variables defined in inventory or the command line), there are two methods for specifying or providing variables directly in a playbook. Those two methods are vars: and vars_files: both of which provide the ability to instruct the playbook that you've defined variables.

One of the things I emphasize when delivering a course (especially the intro Ansible course) everything in Ansible is a List/Dictionary and from there, you just build out and expand using a comination of Lists/Dictionaries. At the play level, I emphasize the playbook directives are key: value pairs belonging to the play at the first indentation level. Depending on the key, the value can be a single value (most likely a string), a list, or a dictionary value.

At the play level we have name, hosts, vars, vars_files, tasks, roles, pre-tasks, post-tasks, and handlers. Yes, there are some other special things we can put in there to override configuration files and users and things, but those are the top ones.The tasks and the vars_files are always expecting the items as a list of tasks or files to process and handle (again, these will be lists and possibly lists of dictionaries). If you think about a task, the indentation level in there is essentially a list of dictionaries (key: value pairs). Where a task must always have a module, but it is generally recommended it has a name prior to the module and then the next indentation is the dictionary items that go with the module (key: value pairs) needed to make the module function as intended.

So why is the vars: block confusing ...? Simply put, this is the way for Ansible to get variables for your playbook. These variables can be many things and there is a single vars: block defined for each play. That means it must accept a list of variable values. What is more, as you pointed out some variables can be dictionaries, so vars: must also accept a dictionary. Therefore, when you boil even a regular variable definition down and you think to look at it conceptually, even a basic variable can be viewed as a dictionary.

For example:

my_pkg: vim

The my_pkg is the variable name, but you could also look at it as the KEY for the dictionary. The value for the variable is vim but it could also be looked at as the dictionary value for the KEY.

So if you approach things this way, the vars: block accepts a list of dictionaries. When there is only one thing specified, you don't need the "-" for the list.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#where-to-set-variabl...

Variables are DICTIONARIES as you hopefully can see using the reference above. Keep in mind ... variable precedence the highest is the "extra variable" specified on the command line ... it is done with -e  "key=value" so hoping that also helps illustrate the point on variables being treated like a dictionary.

To expand things further from your example ...

vars:
    my_var: 
      - "my_value1"
      - "my_value2"
      - "my_value3"

You can take your DICTIONARY variable and now the my_var values are actually a list (think of my_var) as maybe being packages to install. So again, the vars: block in the playbook is a very powerful option of defining variables for tasks and roles. 

As you work more with Ansible, you will most likely find yourself beginning to use host/group variables in inventory and having only a minimum number of variables in the playbook. This is how I work with larger teams. For my demos, I almost always put things in a vars: block or vars_files: to make it easier to figure things out and understand, but as you work with larger projects and maybe take the DO374 you will soon see the power and advantages of using inventory group/host variables.

Hope this along with @Chetan_Tiwary_ 's answer helps clear things up.

 

@Trevor_Chandler - I know you like interesting conversations so I thought this might be a good read for you.

Travis Michette, RHCA XIII
https://rhtapps.redhat.com/verify?certId=111-134-086
SENIOR TECHNICAL INSTRUCTOR / CERTIFIED INSTRUCTOR AND EXAMINER
Red Hat Certification + Training
Travis
Moderator
Moderator
  • 970 Views

@TPeters 

Thank you for the question. I went ahead and created one more item here for this post and I will cross-post to your other variables question. The playbook here shows a couple different variable definitions (single item, a list, and a dictionary). The tasks show how to extract information from these variables as well as some variables that aren't specified that @Chetan_Tiwary_ mentioned. The other thing that I am showing is how to get the variable type which can be important.

https://github.com/tmichett/AnsiblePlaybooks/tree/master/Vars

Var_Demo_Playbook.yml is a simple playbook to show some variables and how to get values out of it as well as determine what type of variable it is. Sometimes I have a hard time reading JSON, so this is very useful on determining whether Ansible is seeing a list or a dictionary based on the variable passed.
 
Feel free to use any demos on the general AnsiblePlaybooks repository and also check out the https://github.com/tmichett/RH294 RH294 repository. I always add to both of these as I get questions in courses or sometimes questions from RHLC posts that I think are great use-cases to answer and illustrate what is happening. While a picture can be worth 1000 words, a good demo can lead to understanding. The RH294 should mostly be arranged with the current version RHEL 9.x of the course on AAP 2.2, but there may be some stray directories and demos where people asked a question and I haven't moved content to where it should go with course materials.
 
Hope these items help and keep in mind both of these repos are actively updated with each course or sometimes each new answer to a question in RHLC.

Travis Michette, RHCA XIII
https://rhtapps.redhat.com/verify?certId=111-134-086
SENIOR TECHNICAL INSTRUCTOR / CERTIFIED INSTRUCTOR AND EXAMINER
Red Hat Certification + Training
TPeters
Flight Engineer
Flight Engineer
  • 937 Views

@Chetan_Tiwary_ , @Travis : thank you for your extensive explanations and examples. Agreed that in Ansible everything is a list or a dictionary, or takes a list or a dictionary. What is confusing me is the dual nature of "vars: " (and possibly other keywords), that it can take both; e.g. in AnsiblePlaybooks/Vars/Var_Demo_Playbook.yml at master · tmichett/AnsiblePlaybooks · GitHub , under "vars: " there are 3 variables, but without preceding '- ' so here it is not a list but a dictionary of variables. But it can also take a list of variables. In contrast, "vars_files: " and "roles: " appear to require a list, I recall I've had error messages when I forgot the preceding '- ' for the role or file.

 

Travis
Moderator
Moderator
  • 908 Views

@TPeters -

So I'm not sure I can help much more and yes you have a point in vars being a little bit strange in how it works. The only thing I can say is it comes with experience and to look carefully at the documentation. 

I can also state that things defined as "lists" must be a list and have the "-" preceding them. I did another quick demo to show it works the same with the preceding "-" as you have mentioned to show that it is treated no differently. Again, this is how the vars directive works.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_intro.html 

https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html#yaml-syntax

https://www.redhat.com/sysadmin/ansible-pretasks-posttasks 

The "vars_files" can ONLY be a LIST of files. The "tasks",  pre_tasks, post_tasks, handlers, and roles are all "LISTS" of tasks so they need the preceding "-". Since the vars section can be either, there isn't an enforcement or anything one way or the other. However, it is possible to adopt a style to make it be easier and just use the preceding "-" even if you have a single variable item.

https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#playbook-keywor...

The above link should give you all the playbook keywords that are reserved. Specifically, it refers to vars as being "Dictionary/map of variables". That link provides keywords that are "reserved" for controlling Ansible behavior.

Creating variable names has the reference provided above regarding playbook keywords, but you must also know to be careful not to use Python keywords. The link provided below talks more about defining variables. One of the considerations with Python keywords is when we are referencing facts and returned values. That is what the [] notation is recommended over the "." notation for variable referencing.

https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html 

That's about all the insight I can provide on this as well as "official" references. At this point, you need to just know that the vars directive in the playbook acts the way it does and know that the YAML and linting rules can assist in writing the playbook. Know too you can also create your own rules when working with larger teams so that if you feel more comfortable with the preceding "-" that can be a playbook design and authoring rule you choose to implement.

 

Travis Michette, RHCA XIII
https://rhtapps.redhat.com/verify?certId=111-134-086
SENIOR TECHNICAL INSTRUCTOR / CERTIFIED INSTRUCTOR AND EXAMINER
Red Hat Certification + Training
TPeters
Flight Engineer
Flight Engineer
  • 843 Views

@Travis : again, thank you for extensive explanation and the links - I wasn't aware of the keyword overview page (in an appendix).  Much more than I've had to use so far.

 

Join the discussion
You must log in to join this conversation.