Ansible - Advanced shell command execution syntax

495 views
Skip to first unread message

Imran Khan

unread,
Aug 22, 2014, 12:47:59 AM8/22/14
to ansible...@googlegroups.com

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 Cleints that you want to configure
      private: False
      defualt: "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 sepearately?

Henry Finucane

unread,
Aug 22, 2014, 1:40:56 AM8/22/14
to ansible...@googlegroups.com
As an aside, you can do math in Jinja2-

- name: bashless math
set_fact:
IPOctet: "{{ 4*(ServerIPRange/epcrange)+IPOctet }}"

will do something approaching what you want.

If you want to get the actual shell-out working, something like this
is going to be enlightening:

- name: local action math
local_action: shell echo "{{ServerIPRange}}/{{epcrange}}+{{IPOctet}}" | bc
with_sequence: start=1 end=4
register: result
- debug: var=result

"debug: var=result" will dump a pretty-printed JSON structure, so
you'll know what's available, and what you can use. You should try it
with & without the with_sequence.
> --
> You received this message because you are subscribed to the Google Groups
> "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to ansible-proje...@googlegroups.com.
> To post to this group, send email to ansible...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/ansible-project/0b34e611-ab2c-45b6-88a9-2caf26ed5504%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
-----------------------
| Henry Finucane
| "I hear aphorisms are popular"
-----------------------

Imran Khan

unread,
Aug 22, 2014, 2:17:25 AM8/22/14
to ansible...@googlegroups.com
Thank you for your quick reply:
But this works, but not in a loop!

    - name: bashless math
      set_fact:
        IPOctet: "{{ (ServerIPRange|int/epcrange|int)+IPOctet|int }}"
      with_sequence: start=1 end=4
      register: IPOctet

this wont work either:

    - name: bashless math
      set_fact:
        IPOctet: "{{ (ServerIPRange|int/epcrange|int)+IPOctet|int }}"
      register: IPOctet
      with_sequence: start=1 end=4
      register: my_ip_octet

I need to save the value in IPOctet repetitively 

Imran Khan

unread,
Aug 22, 2014, 2:19:21 AM8/22/14
to ansible...@googlegroups.com
Again this will save the same value 4 times!

  - name: local action math 
    local_action: shell echo "{{ServerIPRange}}/{{epcrange}}+{{IPOctet}}" | bc 
    with_sequence: start=1 end=4 
    register: result 
  - debug: var=resu

On Thursday, August 21, 2014 10:40:56 PM UTC-7, Henry Finucane wrote:

Michael DeHaan

unread,
Aug 22, 2014, 7:24:21 AM8/22/14
to ansible...@googlegroups.com
There's a bugfix PR for that which I need to test.

You can of course still do this as a shell command too, right now.

What problem are you having at the shell?


Message has been deleted

Imran Khan

unread,
Aug 22, 2014, 8:05:33 AM8/22/14
to ansible...@googlegroups.com
The shell command only does the calculation once and stores the same value in each loop iteration. I want it to run the command by using the last calculated value, which is supposedly not happening for me. Can the jinj2 sum or replace filters be of any help ?

Michael DeHaan

unread,
Aug 22, 2014, 8:06:08 AM8/22/14
to ansible...@googlegroups.com
I'm not understanding what "run the command using the last calculated value" means, unfortunately.




On Fri, Aug 22, 2014 at 8:05 AM, Imran Khan <khan.im...@gmail.com> wrote:
The shell command only does the calculation once and stores the same value in each loop iteration. I want it to run the command by using the last calculated value, which is supposedly not happening for me. Can the jinj2 sum or replace filters be of any help ?

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Imran Khan

unread,
Aug 22, 2014, 8:44:10 AM8/22/14
to ansible...@googlegroups.com
Well I just want a loop, that does the following:
 IPOctet=$(echo "$ServerIPRange/$epcrange+$IPOctet" | bc)

as you can see IPOctet is added to $ServerIPRange/$epcrange and the result is SAVED in IPOctet
In each loop IPOctet is is say incremented by "x" and the result is saved in IPOctet again

What happens:
The loop runs the number of times but saves the same value in each loop iteration.
eg:
IPOctet="5"
ServerIPRange="16"
epcrange="2"
IPOctet= 5 + 16/2 = 13

In the next iteration the result should be
IPOctet= 13 + 8 = 21       //But what happens is that IPOctet stays constant at "13"

In the third iteration the result should be
IPOctet= 21 + 8 = 29                          //IPOctet is doesn't change, reamins 13 and will remain 13 no matter how many iterations of the loop are run


I hope I have got my point across. Now any suggestions on the solution ?



 

Henry Finucane

unread,
Aug 22, 2014, 1:27:42 PM8/22/14
to ansible...@googlegroups.com
On Thu, Aug 21, 2014 at 11:17 PM, Imran Khan <khan.im...@gmail.com> wrote:
> Thank you for your quick reply:
> But this works, but not in a loop!
>
> - name: bashless math
> set_fact:
> IPOctet: "{{ (ServerIPRange|int/epcrange|int)+IPOctet|int }}"
> with_sequence: start=1 end=4
> register: IPOctet

You may have missed a crucial bit of what I wrote- your algorithm
doesn't actually require any iteration. It decomposes into

IPrange/epcrange + (IPrange/epcrange + (IPrange/epcrange +
(IPrange/epcrange + LastIPOctet) ) )

which is the same thing as

4 * (IPrange/epcrange) + LastIPOctet
> https://groups.google.com/d/msgid/ansible-project/54de8cec-df98-4cf0-8f0f-fb8545fef391%40googlegroups.com.

Imran Khan

unread,
Aug 23, 2014, 1:09:26 PM8/23/14
to ansible...@googlegroups.com
I posted that code piece of code for explanation purposes only, loop iteration i.e. the stop value is not fixed and will vary each time depending on user input (it is taken from the user at run time using vars_prompt)

Please can you tell me how to do x=x+y with x=10(will change with each loop iteration) and y=5 (remains constant), inside a loop that runs ten any number of time

Matt Martz

unread,
Aug 23, 2014, 3:33:28 PM8/23/14
to ansible...@googlegroups.com
Isn't what you are doing mathematically equivalent to:

z = x + (y * iterations)

In which case, why do you need to store each result?  Why not just run the task where you want to use this value using with_sequence, and use this formula directly?

Such as this contrived example:

    - debug: msg="{{ IPOctet + (ServerIPRange//epcrange) * item|int }}"
      with_sequence: count="{{ iterations }}"

where IPOctet, ServerIPRange, epcrange, and iterations were defined such as:

  vars:
    IPOctet: 5
    ServerIPRange: 16
    epcrange: 2
    iterations: 5



For more options, visit https://groups.google.com/d/optout.

Henry Finucane

unread,
Aug 23, 2014, 4:23:12 PM8/23/14
to ansible...@googlegroups.com


On Aug 23, 2014 10:09 AM, "Imran Khan" <khan.im...@gmail.com> wrote:
>
> I posted that code piece of code for explanation purposes only, loop iteration i.e. the stop value is not fixed and will vary each time depending on user input (it is taken from the user at run time using vars_prompt)
>
> Please can you tell me how to do x=x+y with x=10(will change with each loop iteration) and y=5 (remains constant), inside a loop that runs ten any number of time

That decomposes the same way!

In any case, the yaml/jinja2 layer is generally the wrong layer to do logic in if your logic is going to get complicated. If you write a module, you can do anything python can do.

> To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/fe7b19c1-b4d7-4c35-98ca-55ed6a6f76aa%40googlegroups.com.

Imran Khan

unread,
Aug 24, 2014, 4:52:16 AM8/24/14
to ansible...@googlegroups.com

Nope, I can't use them like that, my playbook is very complex, with some tasks running on some hosts serially 
Reply all
Reply to author
Forward
0 new messages