Search code examples
python-3.xansiblevmware

I wanted to deploy multiple VMs from ansible, from values given by the enduser


I wanted to deploy multiple VMS from my ansible-playbook, so I used split function and I am getting the error of dict does not have user_inout error. Please have a look at my code.

Code:

  - name: os system 
    pause:
      prompt: |
      Which os do you want to use?
         1- Windows Server
         2- CentOS_7
         3- CentOs_8
         4- Ubuntu
         5- Others
    register: os_system
  - set_fact:
       o_name: "{{ os_system.user_input.split(',') }}"  
  - name: Domain Decision
    pause:
     prompt: Do you want your PC in Domain
    register: decision
    when:  'item|string  == "1"'
    with_items:
     - "{{ o_name }}" 
  - set_fact:
     dec: "{{ decision.user_input.split(',') }}"
      

Now my real issue, if the user chooses option 1,2 then it will be split by set_fact for os_system and according to that input it will decide for the domain decision my main issue is that while the task is at set_fact for the decision, it will give me the error like this:

Error: fatal: [x.x.x.x]: FAILED! => { "msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'user_input'\n\nThe error appears to be in '/home/x.x.x.x/sites/playbook.yml': line 82, column 6, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - set_fact:\n ^ here\n" }

IF I remove the loop from task domain decision, then set_fact works very perfectly.


Solution

  • When you want to collect user input, it can be in two ways:

    • Interactive (prompted), using vars_prompt.
    • Through variables (non-prompted). For example, you could have users create a file with variables and load with vars_file.

    I would prefer the second approach if possible.

    However, to get user input interactively through prompts:

    - hosts: my_hosts
    
      vars_prompt:
      - name: os_system
        prompt: |
          Which os do you want to use?
             1- Windows Server
             2- CentOS_7
             3- CentOs_8
             4- Ubuntu
             5- Others
        private: no      
    
      tasks:
      - set_fact:
          o_name: "{{ os_system.split(',') }}"
    

    You should note that by splitting the input of 1,2 - you will not get OS name. You will again have to set a fact based on the number (1 = Windows Server). IMHO this is unnecessary complication.

    A much better option would be to have users create a variables file like below:

    my_vars.yml:

    os_choices:
      - { name: Windows Server, domain: yes }
      - { name: CentOS_7, domain: no }
    

    And load it in play using:

    - hosts: my_hosts
      vars_file:
        - my_vars.yml