How do I set register a variable to persist between plays in ansible?

前端 未结 3 1730
傲寒
傲寒 2020-12-02 07:49

I have an ansible playbook, where I\'d like a variable I register on one machine to be available on another.

In my case, I\'d like to run a command on localhos

相关标签:
3条回答
  • 2020-12-02 08:10

    The problem you're running into is that you're trying to reference facts/variables of one host from those of another host. You need to keep in mind that in Ansible, the variable app_git_sha1 assigned to the host localhost is distinct from the variable app_git_sha1 assigned to the host main or any other host. If you want to access one hosts facts/variables from another host then you need to explicitly reference it via the hostvars variable. There's a bit more of a discussion on this in this question.

    Suppose you have a playbook like this:

    - hosts: localhost
      tasks:   
        - command: /bin/echo "this is a test"
          register: foo
    
    
    - hosts: localhost
      tasks:
        - debug: var=foo
    

    This will work because you're referencing the host localhost and localhosts's instance of the variable foo in both plays. The output of this playbook is something like this:

    PLAY [localhost] **************************************************************
    
    GATHERING FACTS ***************************************************************
    ok: [localhost]
    
    TASK: [command /bin/echo "this is a test"] ************************************
    changed: [localhost]
    
    PLAY [localhost] **************************************************************
    
    GATHERING FACTS ***************************************************************
    ok: [localhost]
    
    TASK: [debug var=foo] *********************************************************
    ok: [localhost] => {
        "var": {
            "foo": {
                "changed": true,
                "cmd": [
                    "/bin/echo",
                    "this is a test"
                ],
                "delta": "0:00:00.004585",
                "end": "2015-11-24 20:49:27.462609",
                "invocation": {
                    "module_args": "/bin/echo \"this is a test\"",
                    "module_complex_args": {},
                    "module_name": "command"
                },
                "rc": 0,
                "start": "2015-11-24 20:49:27.458024",
                "stderr": "",
                "stdout": "this is a test",
                "stdout_lines": [
                    "this is a test"
                ],
                "warnings": []
            }
        }
    }
    

    If you modify this playbook slightly to run the first play on one host and the second play on a different host, you'll get the error that you encountered. The solution is to use Ansible's built-in hostvars variable to have the second host explicitly reference the first hosts variable. So modify the first example like this:

    - hosts: localhost
      tasks:
    
        - command: /bin/echo "this is a test"
          register: foo
    
    
    - hosts: anotherhost
      tasks:
        - debug: var=foo
          when: foo is defined
    
        - debug: var=hostvars['localhost']['foo']
          when: hostvars['localhost']['foo'] is defined
    

    The output of this playbook shows that the first task is skipped because foo is not defined by the host anotherhost. But the second task succeeds because it's explicitly referencing localhosts's instance of the variable foo:

    TASK: [debug var=foo] *********************************************************
    skipping: [anotherhost]
    
    TASK: [debug var=hostvars['localhost']['foo']] **************************
    ok: ['anotherhost'] => {
        "var": {
            "hostvars['localhost']['foo']": {
                "changed": true,
                "cmd": [
                    "/bin/echo",
                    "this is a test"
                ],
                "delta": "0:00:00.005950",
                "end": "2015-11-24 20:54:04.319147",
                "invocation": {
                    "module_args": "/bin/echo \"this is a test\"",
                    "module_complex_args": {},
                    "module_name": "command"
                },
                "rc": 0,
                "start": "2015-11-24 20:54:04.313197",
                "stderr": "",
                "stdout": "this is a test",
                "stdout_lines": [
                    "this is a test"
                ],
                "warnings": []
            }
        }
    }
    

    So, in a nutshell, you want to modify the variable references in your main playbook to reference the localhost variables in this manner:

    {{ hostvars['localhost']['app_git_sha1'] }}
    
    0 讨论(0)
  • 2020-12-02 08:21

    Use a dummy host and its variables

    For example to pass K8S token and hash from the master to the workers.

    On master

    - name: "Cluster token"
      shell: kubeadm token list | cut -d ' ' -f1 | sed -n '2p'
      register: K8S_TOKEN
    
    - name: "CA Hash"
      shell: openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
      register: K8S_MASTER_CA_HASH
    
    - name: "Add K8S Token and Hash to dummy host"
      add_host:
        name:   "K8S_TOKEN_HOLDER"
        token:  "{{ K8S_TOKEN.stdout }}"
        hash:   "{{ K8S_MASTER_CA_HASH.stdout }}"
    
    - name:
      debug:
        msg: "[Master] K8S_TOKEN_HOLDER K8S token is {{ hostvars['K8S_TOKEN_HOLDER']['token'] }}"
    
    - name:
      debug:
        msg: "[Master] K8S_TOKEN_HOLDER K8S Hash is  {{ hostvars['K8S_TOKEN_HOLDER']['hash'] }}"
    

    On worker

    - name:
      debug:
        msg: "[Worker] K8S_TOKEN_HOLDER K8S token is {{ hostvars['K8S_TOKEN_HOLDER']['token'] }}"
    
    - name:
      debug:
        msg: "[Worker] K8S_TOKEN_HOLDER K8S Hash is  {{ hostvars['K8S_TOKEN_HOLDER']['hash'] }}"
    
    - name: "Kubeadmn join"
      shell: >
        kubeadm join --token={{ hostvars['K8S_TOKEN_HOLDER']['token'] }}
        --discovery-token-ca-cert-hash sha256:{{ hostvars['K8S_TOKEN_HOLDER']['hash'] }}
        {{K8S_MASTER_NODE_IP}}:{{K8S_API_SERCURE_PORT}}
    
    0 讨论(0)
  • 2020-12-02 08:22

    I have had similar issues with even the same host but across different plays. This thing to remember is facts not variables the things persistent across plays. Here is how I get round the problem.

    #!/usr/local/bin/ansible-playbook --inventory=./inventories/ec2.py
    ---
    - name: "TearDown Infrastructure !!!!!!!"
      hosts: localhost
      gather_facts: no
      vars:
        aws_state: absent
      vars_prompt:
        - name: "aws_region"
          prompt: "Enter AWS Region:"
          default: 'eu-west-2'
      tasks:
        - name: Make vars persistant
          set_fact:
            aws_region: "{{aws_region}}"
            aws_state: "{{aws_state}}"
    
    
    
    
    - name: "TearDown Infrastructure hosts !!!!!!!"
      hosts: monitoring.ec2
      connection: local
      gather_facts: no
      tasks:
        - name: set the facts per host
          set_fact:
            aws_region: "{{hostvars['localhost']['aws_region']}}"
            aws_state: "{{hostvars['localhost']['aws_state']}}"
    
    
        - debug:
            msg="state {{aws_state}} region {{aws_region}} id {{ ec2_id }} "
    
    - name: last few bits
      hosts: localhost
      gather_facts: no
      tasks:
        - debug:
            msg="state {{aws_state}} region {{aws_region}} "
    

    results in

    Enter AWS Region: [eu-west-2]:
    
    
    PLAY [TearDown Infrastructure !!!!!!!] ***************************************************************************************************************************************************************************************************
    
    TASK [Make vars persistant] **************************************************************************************************************************************************************************************************************
    ok: [localhost]
    
    PLAY [TearDown Infrastructure hosts !!!!!!!] *********************************************************************************************************************************************************************************************
    
    TASK [set the facts per host] ************************************************************************************************************************************************************************************************************
    ok: [XXXXXXXXXXXXXXXXX]
    
    TASK [debug] *****************************************************************************************************************************************************************************************************************************
    ok: [XXXXXXXXXXX] => {
        "changed": false,
        "msg": "state absent region eu-west-2 id i-0XXXXX1 "
    }
    
    PLAY [last few bits] *********************************************************************************************************************************************************************************************************************
    
    
    TASK [debug] *****************************************************************************************************************************************************************************************************************************
    ok: [localhost] => {
        "changed": false,
        "msg": "state absent region eu-west-2 "
    }
    
    PLAY RECAP *******************************************************************************************************************************************************************************************************************************
    XXXXXXXXXXXXX              : ok=2    changed=0    unreachable=0    failed=0
    localhost                  : ok=2    changed=0    unreachable=0    failed=0
    
    0 讨论(0)
提交回复
热议问题