Ansible: how to construct a variable from another variable and then fetch it's value

前端 未结 10 447
我寻月下人不归
我寻月下人不归 2020-12-02 22:50

Here is my problem I need to use one variable \'target_host\' and then append \'_host\' to it\'s value to get another variable name whose value I need. If you look at my pl

相关标签:
10条回答
  • 2020-12-02 22:51

    You have two ways to choose:
    1. General using.

    vars:
        - target_host: smtp
        - smtp: smtp.max.com
    tasks: 
        - name: testing
            debug: msg={{ target_host }}
        - name: testing
            debug: msg={{ smtp }}
        - name: testing
            debug: msg={{ vars[target_host] }}
    

    2. Using fact

    tasks: 
        - set_fact: target_host=smtp
        - set_fact: smtp=smtp.max.com
        - name: testing
            debug: msg={{ target_host }}
        - name: testing
            debug: msg={{ smtp }}
        - name: testing
            debug: msg={{hostvars[inventory_hostname][target_host]}}
    
    0 讨论(0)
  • 2020-12-02 22:55

    If you have a variable like

    vars: myvar: xxx xxx_var: anothervalue

    the working Ansible syntax:

    - debug: msg={{ vars[myvar + '_var'] }}

    will give you the analogue of:

    - debug: msg={{ xxx_var }}

    0 讨论(0)
  • 2020-12-02 22:56

    You can try global array var:

    regions:
      us-east-1:
        endpoint: rds.us-east-1.amazonaws.com
      cn-north-1:
        endpoint: rds.cn-north-1.amazonaws.com.cn
      cn-northwest-1:
        endpoint: rds.cn-northwest-1.amazonaws.com.cn
    

    And use it to get value depending of another:

    region_endpoint: "{{ regions[region].endpoint}}"
    

    In your case:

    target_host:
      imap:
        host: imap.max.com
      smtp:
        host: smtp.max.com
    

    then:

    region_endpoint: "{{ target_host[service].host}}"
    
    0 讨论(0)
  • 2020-12-02 23:05

    There are many answers above. It helped me a lot. But i have not found a single answer how to keep these variable in vars-> main.yml file. So you have to create a dictionary in vars-> main.yml file.

    vars -> main.yml file

    cassandra_version: 2.1.16
    file_sha_cassandra: "apache-cassandra-{{ cassandra_version }}_sha256"
    # Create Dictionary here
    cassandra:
        apache-cassandra-2.1.16_sha256: "sha256: checksum_of_file"
        ##Add more variable
    

    Now you have to call this in task -> main.yml file:

    ---
      - name: Down load Cassandra Binaries
        get_url:
           url: "file_url"
           dest: "{{ base_directory }}"
           checksum: "{{ cassandra[file_sha_cassandra] }}"
           timeout: 800
    
    0 讨论(0)
  • 2020-12-02 23:08

    You can use "hostvars" to pass the variable, host facts can be loaded from group vars or host vars

    yml

    ---
    - name: "Play to for dynamic groups"
      hosts: x0
      vars:
        - target_host: smtp
      tasks:
        - set_fact: smtp_host="smtp.max.com"
        - set_fact: host_var_name={{target_host}}_host
        - set_fact: dym_target_host={{hostvars[inventory_hostname][host_var_name]}}
    
        - name: testing
          debug: msg={{ target_host }}
        - name: testing
          debug: msg={{ smtp_host }}
        - name: testing
          debug: msg={{ target_host }}_host
        - name: testing
          debug: msg={{ dym_target_host }}
    

    output:

    PLAY [Play to for dynamic groups] *********************************************
    
    GATHERING FACTS ***************************************************************
    ok: [x0]
    
    TASK: [set_fact smtp_host="smtp.max.com"] *************************************
    ok: [x0]
    
    TASK: [set_fact host_var_name=smtp_host] **************************************
    ok: [x0]
    
    TASK: [set_fact dym_target_host={{hostvars[inventory_hostname][host_var_name]}}] ***
    ok: [x0]
    
    TASK: [testing] ***************************************************************
    ok: [x0] => {
        "msg": "smtp"
    }
    
    TASK: [testing] ***************************************************************
    ok: [x0] => {
        "msg": "smtp.max.com"
    }
    
    TASK: [testing] ***************************************************************
    ok: [x0] => {
        "msg": "smtp_host"
    }
    
    TASK: [testing] ***************************************************************
    ok: [x0] => {
        "msg": "smtp.max.com"
    }
    
    PLAY RECAP ********************************************************************
    x0                         : ok=8    changed=0    unreachable=0    failed=0
    
    0 讨论(0)
  • 2020-12-02 23:09

    You need to put quotes around it:

    - hosts: local
      vars: [ target_host: smtp ]
      tasks:
        debug: msg="{{ target_host }}_host"
    

    -- edit --

    Kashyap I need to go one more level than this. Imagine there is another variable 'smtp_host' and I want to construct that variable at runtime using another variable(target_host) and attaching a string '_host' to it. = {{ {{ target_host }}_host }} – Max

    My bad. Didn't read carefully enough.

    This (AFAIK) isn't possible. The primary limitation that stops us doing this (no matter how you spin it), is 'variable expansion' in ansible is a single pass process and what you want requires multiple-passes.

    Only [seriously hacky] ways I can think of are:

    • Create the playbook dynamically from your playbook using template and execute it.
    • I heard that Jinja2 engine does multi-pass evaluation. May be if you put these strings in a template and then use the lookup('template', ...) filter. Unfortunately I have no experience with Jinja2 templates so not quite sure if this is even an option.
    0 讨论(0)
提交回复
热议问题