Add random_mac string filter (#39775)

Add new filter to generate random MAC addresses from
string prefix. See docs/docsite/rst/user_guide/playbooks_filters.rst
for more detailed infos.
This commit is contained in:
Olivier Bourdon 2018-06-21 22:56:54 +02:00 committed by Adam Miller
parent 5880404151
commit 06b73ff8f1
4 changed files with 102 additions and 2 deletions

View file

@ -0,0 +1,6 @@
---
minor_changes:
- Added new filter to generate random MAC addresses from a given
string acting as a prefix. Refer to the appropriate entry
which has been added to user_guide playbook_filters.rst
document.

View file

@ -243,6 +243,22 @@ An example of using this filter with ``loop``::
key: "{{ lookup('file', item.1) }}"
loop: "{{ users|subelements('authorized') }}"
.. _random_mac_filter:
Random Mac Address Filter
`````````````````````````
.. versionadded:: 2.6
This filter can be used to generate a random MAC address from a string prefix.
To get a random MAC address from a string prefix starting with '52:54:00'::
"{{ '52:54:00'|random_mac }}"
# => '52:54:00:ef:1c:03'
Note that if anything is wrong with the prefix string, the filter will issue an error.
.. _random_filter:
Random Number Filter

View file

@ -37,7 +37,7 @@ import yaml
from collections import MutableMapping, MutableSequence
import datetime
from functools import partial
from random import Random, SystemRandom, shuffle
from random import Random, SystemRandom, shuffle, random
from jinja2.filters import environmentfilter, do_groupby as _do_groupby
@ -532,6 +532,39 @@ def dict_to_list_of_dict_key_value_elements(mydict):
return ret
def random_mac(value):
''' takes string prefix, and return it completed with random bytes
to get a complete 6 bytes MAC address '''
if not isinstance(value, string_types):
raise AnsibleFilterError('Invalid value type (%s) for random_mac (%s)' % (type(value), value))
value = value.lower()
mac_items = value.split(':')
if len(mac_items) > 5:
raise AnsibleFilterError('Invalid value (%s) for random_mac: 5 colon(:) separated items max' % value)
err = ""
for mac in mac_items:
if len(mac) == 0:
err += ",empty item"
continue
if not re.match('[a-f0-9]{2}', mac):
err += ",%s not hexa byte" % mac
err = err.strip(',')
if len(err):
raise AnsibleFilterError('Invalid value (%s) for random_mac: %s' % (value, err))
# Generate random float and make it int
v = int(random() * 10.0**10)
# Select first n chars to complement input prefix
remain = 2 * (6 - len(mac_items))
rnd = ('%x' % v)[:remain]
return value + re.sub(r'(..)', r':\1', rnd)
class FilterModule(object):
''' Ansible core jinja2 filters '''
@ -621,4 +654,7 @@ class FilterModule(object):
'flatten': flatten,
'dict2items': dict_to_list_of_dict_key_value_elements,
'subelements': subelements,
# Misc
'random_mac': random_mac,
}

View file

@ -192,4 +192,46 @@
- "'Ansible - くらとみ\n' | b64encode == 'QW5zaWJsZSAtIOOBj+OCieOBqOOBvwo='"
- "'QW5zaWJsZSAtIOOBj+OCieOBqOOBvwo=' | b64decode == 'Ansible - くらとみ\n'"
- "'Ansible - くらとみ\n' | b64encode(encoding='utf-16-le') == 'QQBuAHMAaQBiAGwAZQAgAC0AIABPMIkwaDB/MAoA'"
- "'QQBuAHMAaQBiAGwAZQAgAC0AIABPMIkwaDB/MAoA' | b64decode(encoding='utf-16-le') == 'Ansible - くらとみ\n'"
- "'QQBuAHMAaQBiAGwAZQAgAC0AIABPMIkwaDB/MAoA' | b64decode(encoding='utf-16-le') == 'Ansible - くらとみ\n'"
- name: Test random_mac filter bad argument type
debug:
var: "0 | random_mac"
register: _bad_random_mac_filter
ignore_errors: yes
- name: Verify random_mac filter showed a bad argument type error message
assert:
that:
- _bad_random_mac_filter is failed
- "_bad_random_mac_filter.msg is match('Invalid value type (.*int.*) for random_mac .*')"
- name: Test random_mac filter bad argument value
debug:
var: "'dummy' | random_mac"
register: _bad_random_mac_filter
ignore_errors: yes
- name: Verify random_mac filter showed a bad argument value error message
assert:
that:
- _bad_random_mac_filter is failed
- "_bad_random_mac_filter.msg is match('Invalid value (.*) for random_mac: .* not hexa byte')"
- name: Test random_mac filter prefix too big
debug:
var: "'00:00:00:00:00:00' | random_mac"
register: _bad_random_mac_filter
ignore_errors: yes
- name: Verify random_mac filter showed a prefix too big error message
assert:
that:
- _bad_random_mac_filter is failed
- "_bad_random_mac_filter.msg is match('Invalid value (.*) for random_mac: 5 colon.* separated items max')"
- name: Verify random_mac filter
assert:
that:
- "'00:00:00' | random_mac is match('^00:00:00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
- "'00:00:00' | random_mac != '00:00:00' | random_mac"