From 730456b402fb7cf4182938c41403214112c5933c Mon Sep 17 00:00:00 2001 From: s-hamann <10639154+s-hamann@users.noreply.github.com> Date: Thu, 16 May 2019 17:41:08 +0000 Subject: [PATCH] Add seed parameter to random_mac filter (#51841) --- docs/docsite/rst/user_guide/playbooks_filters.rst | 4 ++++ lib/ansible/plugins/filter/core.py | 10 +++++++--- test/integration/targets/filters/tasks/main.yml | 6 ++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/docsite/rst/user_guide/playbooks_filters.rst b/docs/docsite/rst/user_guide/playbooks_filters.rst index 6b55c0d48f4..f7af25c143d 100644 --- a/docs/docsite/rst/user_guide/playbooks_filters.rst +++ b/docs/docsite/rst/user_guide/playbooks_filters.rst @@ -378,6 +378,10 @@ To get a random MAC address from a string prefix starting with '52:54:00':: Note that if anything is wrong with the prefix string, the filter will issue an error. +As of Ansible version 2.9, it's also possible to initialize the random number generator from a seed. This way, you can create random-but-idempotent MAC addresses:: + + "{{ '52:54:00' | random_mac(seed=inventory_hostname) }}" + .. _random_filter: Random Number Filter diff --git a/lib/ansible/plugins/filter/core.py b/lib/ansible/plugins/filter/core.py index 4ceb4a6c81e..dc19b2649fa 100644 --- a/lib/ansible/plugins/filter/core.py +++ b/lib/ansible/plugins/filter/core.py @@ -36,7 +36,7 @@ import yaml import datetime from functools import partial -from random import Random, SystemRandom, shuffle, randint +from random import Random, SystemRandom, shuffle from jinja2.filters import environmentfilter, do_groupby as _do_groupby @@ -533,7 +533,7 @@ def list_of_dict_key_value_elements_to_dict(mylist, key_name='key', value_name=' return dict((item[key_name], item[value_name]) for item in mylist) -def random_mac(value): +def random_mac(value, seed=None): ''' takes string prefix, and return it completed with random bytes to get a complete 6 bytes MAC address ''' @@ -558,8 +558,12 @@ def random_mac(value): if len(err): raise AnsibleFilterError('Invalid value (%s) for random_mac: %s' % (value, err)) + if seed is None: + r = SystemRandom() + else: + r = Random(seed) # Generate random int between x1000000000 and xFFFFFFFFFF - v = randint(68719476736, 1099511627775) + v = r.randint(68719476736, 1099511627775) # Select first n chars to complement input prefix remain = 2 * (6 - len(mac_items)) rnd = ('%x' % v)[:remain] diff --git a/test/integration/targets/filters/tasks/main.yml b/test/integration/targets/filters/tasks/main.yml index b5b59a7691e..e6a37a2b1e0 100644 --- a/test/integration/targets/filters/tasks/main.yml +++ b/test/integration/targets/filters/tasks/main.yml @@ -242,6 +242,12 @@ - "'00:00:00:00:00' | random_mac is match('^00:00:00:00:00:[a-f0-9][a-f0-9]$')" - "'00:00:00' | random_mac != '00:00:00' | random_mac" +- name: Verify random_mac filter with seed + assert: + that: + - "'00:00:00' | random_mac(seed='test') == '00:00:00' | random_mac(seed='test')" + - "'00:00:00' | random_mac(seed='test') != '00:00:00' | random_mac(seed='another_test')" + - name: Verify that union can be chained vars: unions: '{{ [1,2,3]|union([4,5])|union([6,7]) }}'