2

I am trying to write a regular expression for a dynamic group in ansible-playbook for an sample ip range. if the address range is 172.30.0.(0 to 254).(0 to 254). My regex is like 172.30.[0-254].[0-254]. Is this correct ? Even though I have the hosts in the range, the tasks are being skipped and no groups are being formed.

tasks: - group_by: key=adda when: ansible_default_ipv4.network == '172.30.[0-254].[0-254]'

grouping picture

Gana Sagar
  • 131
  • 2
  • 13
  • Possible duplicate of [Regex: How to match IP address in RFC1918 private IPV4 address ranges (in Python)?](http://stackoverflow.com/questions/30674845/regex-how-to-match-ip-address-in-rfc1918-private-ipv4-address-ranges-in-python) – TessellatingHeckler Aug 02 '16 at 16:36
  • Please post code as text, not an image, in the future. – tedder42 Aug 05 '16 at 22:03

6 Answers6

2

When using the operator '==' then in python you are trying to find a matched string with the name '172.30.[0-254[.[0-254]'

In ansible you can use python expression like search or match.

So you need to type something like this:

when: ansible_default_ipv4.address | match("172.30.")

Did a test ansible playbook to verify it.

ebal
  • 365
  • 1
  • 4
2

If you compare networks, you shouldn't care about ranges!

tasks:
  - group_by: key=adda
    when: ansible_default_ipv4.network == '172.30.0.0'

This will (generally) match all hosts with IPs 172.30.0.1 - 172.30.255.255.

If you need to compare IP addresses, use ipaddr filter:

tasks:
  - group_by: key=adda
    when: ansible_default_ipv4.address | ipaddr('172.30.0.0/16') | ipaddr('bool')
Konstantin Suvorov
  • 65,183
  • 9
  • 162
  • 193
  • That means that python-netaddr is already installed to the ansible controller. – ebal Aug 02 '16 at 19:29
  • Thank you very much, I don't have python-netaddr installed so I tried what @ebal suggested and it worked. For some reason the network comparison still didn't work. I will also look at the ipaddr filter if required. – Gana Sagar Aug 03 '16 at 14:36
1

[0-225] is an incorrect regex. [] Define a range of character from one to another character in the ACII table and 255 is not an ASCII character.

replace it by (?:25[0-4]|2[0-4][0-9]|[01]?[0-9][0-9]?)

So the complete regex is :

173\.30\.(?:25[0-4]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-4]|2[0-4][0-9]|[01]?[0-9][0-9]?)

as this post said : Regex to match an IP address

Community
  • 1
  • 1
baddger964
  • 1,199
  • 9
  • 18
0

You probably want to use Jinja2 match filter to match regex:

Something like this:

---

- hosts: localhost
  gather_facts: no
  connection: local
  vars:
    ip_not_ok: '172.31.0.1'
    ip_ok: '172.30.0.1'
  tasks:
   - debug: msg='OK'
     when: ip_ok | match('172.30')

   - debug: msg='OK'
     when: ip_not_ok | match('172.30')
Vor
  • 33,215
  • 43
  • 135
  • 193
0

Regex isn't good tool for that.

from ipaddress import ip_address
import operator

def ip_check_range(ranges, s):
    return all(map(operator.contains,
        ranges,
        ip_address(s).packed
    ))

print(ip_check_range([[172], [30], range(255), range(255)], '172.30.1.2')) # => True
print(ip_check_range([[172], [30], range(255), range(255)], '172.30.1.255')) # => False

Alternatively, If you're on Python<3.3 and don't have ipaddress module:

def ip_check_range(ranges, s):
    ip = s.split('.')
    if len(ip) != 4:
        raise ValueError
    return all(map(operator.contains,
        ranges,
        (int(octet) for octet in ip)
    ))
GingerPlusPlus
  • 5,336
  • 1
  • 29
  • 52
0

I tried comparing networks it work out. So I tired what @ebel suggested and it worked the way I wanted. Thanks

enter image description here

Gana Sagar
  • 131
  • 2
  • 13