Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ansible - Advanced shell command execution format

I have 3 variables named IPOctet, ServerIPRange and epcrange. If I perform the following operation in my terminal, it works perfectly

IPOctet=$(echo "$ServerIPRange/$epcrange+$IPOctet" | bc)

How to I do something similar in a ansible inside a task, for e.g

---
- hosts: localhost
  gather_facts: False

  vars_prompt:
    - name: epcrange
      prompt: Enter the number of EPCs that you want to configure
      private: False
      default: "1"
    - name: serverrange
      prompt: Enter the number of Clients that you want to configure
      private: False
      default: "1"
    - name: ServerIPRange
      prompt: Enter the ServerIP range
      private: False
      default: '128'
    - name: LastIPOctet
      prompt: Enter The last Octet of the IP you just entered
      private: False
      default: '10'

  pre_tasks:


    - name: Set some facts
      set_fact:
        ServerIP1: "{{ServerIP}}"
        ServerIPRange1: "{{ServerIPRange}}"
        IPOctet: "{{LastIPOctet}}"

    - name: local action math
      local_action: shell {{IPOctet}}=$(echo "${{ServerIPRange}}/${{epcrange}}+${{IPOctet}}" | bc)  # Proper Syntax?
      with_sequence: start=1 end=4
      register: result
      ignore_errors: yes

What is the proper syntax for this command? Maybe using shell echo "......." . I just need to save the contents of this command into the IPOctet variable and IPOctet will change with each loop iteration and the results should be stored in my result register

P.S: how can I access the individual items in the array separately?

Edit: Is anything like this possible, currently it just does the calculation once and stores it 4 times in the register...

- name: bashless math
  set_fact:
    IPOctet: "{{ (ServerIPRange|int/epcrange|int)+IPOctet|int }}"
  register: IPOctet
  with_sequence: "start=1 end={{stop}} "
  register: my_ip_octet
like image 511
Khan Avatar asked Aug 21 '14 20:08

Khan


People also ask

What format does Ansible ad hoc command returns the output?

Use the -o option to display the output of Ansible ad hoc commands in a single line format.

What is the difference between shell and command in Ansible?

The shell module executes commands in nodes or Shell scripts. Another dedicated Ansible module is Script that transfers the Shell script from the control machine to the remote server and executes it. In the command module, the given command executes on all selected nodes.


1 Answers

  1. Your terminal expression reassigns the IPOctet shell variable, so it gives a different result each time it is executed. This is fine, but difficult to reproduce in Ansible:

    $ IPOctet=10 ServerIPRange=128 epcrange=1
    $ IPOctet=$(echo "$ServerIPRange/$epcrange+$IPOctet" | bc); echo $IPOctet
    138
    
    $ IPOctet=$(echo "$ServerIPRange/$epcrange+$IPOctet" | bc); echo $IPOctet
    266
    
  2. The syntax: "shell {{IPOctet}}=$(echo ..." does NOT assign to the Ansible variable. The shell attempts to execute a command like "10=138", which is not found.

  3. When register is used within a loop, the target variable is not set until the loop completes - so your expression always sees the original value for {{IPOctet}}.

  4. A solution is to run the whole loop as a single shell command:

    - name: local action math2
      local_action: shell IPOctet={{IPOctet}}; for i in 1 2 3 4; do IPOctet=$(expr {{ServerIPRange}} / {{epcrange}} + $IPOctet); echo $IPOctet; done
      register: result
    

    NOTE: I've used the expr command rather than bc, but the results are the same.

  5. You can iterate over these results using result.stdout_lines:

    - name: iterate results
      local_action: debug msg={{item}}
      with_items: result.stdout_lines
    
like image 141
Derek Baum Avatar answered Sep 27 '22 21:09

Derek Baum