Search code examples
ansibleyamlswitch-statementnetwork-programmingfirewall

How to skip vars_prompt if variables exist within import_playbook?


I have this playbook script to execute some basic task on the switch and firewall.

Requirement :

  • Case 1. User need to execute the parent script to perform all basic task on child 1 and child 2.
  • Case 2. User need to execute directly on the child 1 to perform basic task.
  • Case 3. User need to execute directly on the child 2 to perform basic task.

Information :

  • Parent script host only localhost.
  • Child 1 script hosts are multiple switch.
  • Child 2 script hosts are multiple firewall.

Parent : test_dummy_sw_fw.yml

- hosts: localhost
  become: no
  gather_facts: no

  vars_prompt:
    - name: ansible_user
      prompt: "Enter Username"
      private: no
    - name: ansible_password
      prompt: "Enter Password"
      private: yes

- name: Execute Script on Switch
  import_playbook: test_dummy_sw.yml

- name: Execute Script on Firewall
  import_playbook: test_dummy_fw.yml

Child 1 / Switch : test_dummy_sw.yml

- hosts: Switch
  become: no
  gather_facts: no
  
  vars_prompt:
    - name: ansible_user
      prompt: "Enter Username"
      private: no
    - name: ansible_password
      prompt: "Enter Password"
      private: yes
  
  tasks:
    - name: Interface Config
      ios_config:
        lines:
          - description Testing Switch
        parents: "interface Gi0/0"  
      register: print_output

    - debug: var=print_output

Child 2 / Firewall : test_dummy_fw.yml

- hosts: Firewall
  become: no
  gather_facts: no
  
  vars_prompt:
    - name: ansible_user
      prompt: "Enter Username"
      private: no
    - name: ansible_password
      prompt: "Enter Password"
      private: yes
  
  tasks:
    - name: Interface Config
      asa_config:
        lines:
          - description Testing Firewall
        parents: "interface Ethernet1"  
      register: print_output

    - debug: var=print_output

I want to create a script to skip the prompt when a variable has been set in a parent playbook. I've also tried this on the playbook, but Ansible still prompts for the variable in the child playbook.

Parent :

- hosts: localhost
  become: no
  gather_facts: no

  vars_prompt:
    - name: ansible_user
      prompt: "Enter Username"
      private: no
    - name: ansible_password
      prompt: "Enter Password"
      private: yes

  tasks:
  - set_fact:
      ansible_user: "{{ ansible_user }}"
      ansible_password: "{{ ansible_password }}"

- name: Execute Script on Switch
  import_playbook: test_dummy_switch.yml
  vars:
    ansible_user: "{{ ansible_user|d('default') }}"
    ansible_password: "{{ ansible_password|d('default') }}"
        
- name: Execute Script on Firewall
  import_playbook: test_dummy_fw.yml
  vars:
    ansible_user: "{{ ansible_user|d('default') }}"
    ansible_password: "{{ ansible_password|d('default') }}"

Is there any way to ensure that Ansible recognizes that the variable already exists and skips the prompt without using extra variables ? Because the requirement of this script are only needed to prompt once for username and password.


Solution

  • Thanks to Vladimir Botka, i got some inspiration from his answer.

    Its been resolved using the script below.

    Parent Script : test_dummy_sw_fw.yml

    - hosts: localhost
      become: no
      gather_facts: no
    
      vars_prompt:
        - name: username
          prompt: "Enter Username (Local/TACACS)"
          private: no
        - name: password
          prompt: "Enter Password"
          private: yes
    
      tasks:
      
      - set_fact:
            ansible_user: "{{ username }}"
            ansible_password: "{{ password }}"
    
    # Test Script on Switch
    
    - name: Execute Script on Switch
      import_playbook: test_dummy_switch.yml
        
    # Test Script on Firewall
    
    - name: Execute Script on Firewall
      import_playbook: test_dummy_fw.yml
    

    Child 1 / Switch : test_dummy_sw.yml

    - hosts: localhost
      become: no
      gather_facts: no
    
      pre_tasks:
    
        - when: ansible_user is undefined
          block:
            - pause:
                prompt: Enter Username (Local/TACACS)
              register: username
            - set_fact: ansible_user="{{ username.user_input }}"
    
        - when: ansible_password is undefined
          block:
            - pause:
                prompt: Enter Password
                echo: false
              register: password
            - set_fact: ansible_password="{{password.user_input }}"
        
    - hosts: Switch
      become: no
      gather_facts: no
    
      tasks:
        - set_fact: 
            ansible_user: "{{ hostvars['localhost']['ansible_user'] }}"
            ansible_password: "{{ hostvars['localhost']['ansible_password'] }}"
        
        - name: Interface up/down - SDL1
          ios_config:
            lines:
              - description Testing Switch
            parents: "interface Gi0/0"    
          register: print_output
          
        - debug: var=print_output
    
     
    

    Child 2 / Firewall : test_dummy_fw.yml

    - hosts: localhost
      become: no
      gather_facts: no
    
      pre_tasks:
    
        - when: ansible_user is undefined
          block:
            - pause:
                prompt: Enter Username (Local/TACACS)
              register: username
            - set_fact: ansible_user="{{ username.user_input }}"
    
        - when: ansible_password is undefined
          block:
            - pause:
                prompt: Enter Password
                echo: false
              register: password
            - set_fact: ansible_password="{{password.user_input }}"
    
    - hosts: Firewall
      become: no
      gather_facts: no
      
      vars_files:
        - if_dummy_asa.yml
    
      tasks:
        - set_fact: 
            ansible_user: "{{ hostvars['localhost']['ansible_user'] }}"
            ansible_password: "{{ hostvars['localhost']['ansible_password'] }}"
    
        - name: Interface Config on Firewall
          asa_config:
            lines:
              - description Testing Firewall
            parents: "interface Ethernet1"  
          register: print_output
    
        - debug: var=print_output
    

    When we executed the Ansible script on parents it will only prompt the credentials once because the credentials has been set previously on Parent Script, so prompt will be ignored on child script.

    When we executed directly on child there will be a prompt since the credentials of ansible_user and ansible_password is not defined on parents.