Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

resolve dictionary key or parameter variable in Ansible

Tags:

In Ansible, if I try to use a variable as a parameter name, or a key name, it is never resolved. For example, if I have {{ some_var }}: true, or:

template: "{{ resolve_me_to_src }}": "some_src"

the variables will just be used literally and never resolve. My specific use case is using this with the ec2 module, where some of my tag names are stored as variables:

- name: Provision a set of instances
  ec2:
    group: "{{ aws_security_group }}"
    instance_type: "{{ aws_instance_type }}"
    image: "{{ aws_ami_id }}"
    region: "{{ aws_region }}"
    vpc_subnet_id: "{{ aws_vpc_subnet_id }}"
    key_name: "{{ aws_key_name }}"
    wait: true
    count: "{{ num_machines }}"
    instance_tags: { "{{ some_tag }}": "{{ some_value }}", "{{ other_tag }}": "{{ other_value }}" }

Is there any way around this? Can I mark that I want to force evaluation somehow?

like image 756
Eli Avatar asked Jan 06 '15 19:01

Eli


People also ask

What are different types of variables in ansible?

Variable Scopes Ansible has 3 main scopes: Global: this is set by config, environment variables and the command line. Play: each play and contained structures, vars entries, include_vars, role defaults and vars. Host: variables directly associated to a host, like inventory, facts or registered task outputs.

How do you pass variables in ansible playbook?

The easiest way to pass Pass Variables value to Ansible Playbook in the command line is using the extra variables parameter of the “ansible-playbook” command. This is very useful to combine your Ansible Playbook with some pre-existent automation or script.

How do you assign variables in ansible?

You can define these variables in your playbooks, in your inventory, in re-usable files or roles, or at the command line. You can also create variables during a playbook run by registering the return value or values of a task as a new variable.

How do you pass multiple vars in ansible?

To pass a value to nodes, use the --extra-vars or -e option while running the Ansible playbook, as seen below. This ensures you avoid accidental running of the playbook against hardcoded hosts.


1 Answers

Will this work for you?

(rc=0)$ cat training.yml
- hosts: localhost
  tags: so5
  gather_facts: False
  vars: [
      k1: 'key1',
      k2: 'key2',
      d1: "{
        '{{k1}}': 'value1',
        '{{k2}}': 'value2',
      }",
    ]
  tasks:
  - debug: msg="{{item}}"
    with_dict: "{{d1}}"


(rc=0)$ ansible-playbook training.yml -t so5

PLAY [localhost] **************************************************************** 

PLAY [localhost] **************************************************************** 

TASK: [debug msg="{{item}}"] ************************************************** 
ok: [localhost] => (item={'key': 'key2', 'value': 'value2'}) => {
    "item": {
        "key": "key2", 
        "value": "value2"
    }, 
    "msg": "{'value': 'value2', 'key': 'key2'}"
}
ok: [localhost] => (item={'key': 'key1', 'value': 'value1'}) => {
    "item": {
        "key": "key1", 
        "value": "value1"
    }, 
    "msg": "{'value': 'value1', 'key': 'key1'}"
}

PLAY RECAP ******************************************************************** 
localhost                    : ok=1    changed=0    unreachable=0    failed=0   

(rc=0)$

Trick is to wrap dict declaration with double quotes. Ansible applies this undocumented (but consistant) and crappy translation (ansible's equivalent of shell variable expantion) to most (not all) YAML values (everything RHS of ':') in the playbook. It is some combination putting these strings through Jinja2-engine, Python-interpreter and ansible-engine in some unknown order.

like image 187
Kashyap Avatar answered Oct 09 '22 00:10

Kashyap