Move random_mac into its own file (#67000)
* Move random_mac into its own file This is likely to be the only filter which is not included in ansible-base. So it needs to be in its own file.
This commit is contained in:
parent
ef1fd19c00
commit
f5e194cbcd
5 changed files with 135 additions and 99 deletions
|
@ -544,43 +544,6 @@ 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)
|
return dict((item[key_name], item[value_name]) for item in mylist)
|
||||||
|
|
||||||
|
|
||||||
def random_mac(value, seed=None):
|
|
||||||
''' 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))
|
|
||||||
|
|
||||||
if seed is None:
|
|
||||||
r = SystemRandom()
|
|
||||||
else:
|
|
||||||
r = Random(seed)
|
|
||||||
# Generate random int between x1000000000 and xFFFFFFFFFF
|
|
||||||
v = r.randint(68719476736, 1099511627775)
|
|
||||||
# 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)
|
|
||||||
|
|
||||||
|
|
||||||
def path_join(paths):
|
def path_join(paths):
|
||||||
''' takes a sequence or a string, and return a concatenation
|
''' takes a sequence or a string, and return a concatenation
|
||||||
of the different members '''
|
of the different members '''
|
||||||
|
@ -684,7 +647,4 @@ class FilterModule(object):
|
||||||
'dict2items': dict_to_list_of_dict_key_value_elements,
|
'dict2items': dict_to_list_of_dict_key_value_elements,
|
||||||
'items2dict': list_of_dict_key_value_elements_to_dict,
|
'items2dict': list_of_dict_key_value_elements_to_dict,
|
||||||
'subelements': subelements,
|
'subelements': subelements,
|
||||||
|
|
||||||
# Misc
|
|
||||||
'random_mac': random_mac,
|
|
||||||
}
|
}
|
||||||
|
|
73
lib/ansible/plugins/filter/random_mac.py
Normal file
73
lib/ansible/plugins/filter/random_mac.py
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
# (c) 2020 Ansible Project
|
||||||
|
#
|
||||||
|
# This file is part of Ansible
|
||||||
|
#
|
||||||
|
# Ansible is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Ansible is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Make coding more python3-ish
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import re
|
||||||
|
from random import Random, SystemRandom
|
||||||
|
|
||||||
|
from ansible.errors import AnsibleFilterError
|
||||||
|
from ansible.module_utils.six import string_types
|
||||||
|
|
||||||
|
|
||||||
|
def random_mac(value, seed=None):
|
||||||
|
''' 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 not mac:
|
||||||
|
err += ",empty item"
|
||||||
|
continue
|
||||||
|
if not re.match('[a-f0-9]{2}', mac):
|
||||||
|
err += ",%s not hexa byte" % mac
|
||||||
|
err = err.strip(',')
|
||||||
|
|
||||||
|
if 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 = r.randint(68719476736, 1099511627775)
|
||||||
|
# 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:
|
||||||
|
''' Ansible jinja2 filters '''
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
'random_mac': random_mac,
|
||||||
|
}
|
|
@ -136,65 +136,6 @@
|
||||||
- "'Ansible - くらとみ\n' | b64encode(encoding='utf-16-le') == 'QQBuAHMAaQBiAGwAZQAgAC0AIABPMIkwaDB/MAoA'"
|
- "'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' | random_mac is match('^00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
|
|
||||||
- "'00:00' | random_mac is match('^00:00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
|
|
||||||
- "'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: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: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: Ensure dict2items works with hostvars
|
|
||||||
debug:
|
|
||||||
msg: "{{ item.key }}"
|
|
||||||
loop: "{{ hostvars|dict2items }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.key }}"
|
|
||||||
|
|
||||||
- name: Ensure combining two dictionaries containing undefined variables provides a helpful error
|
- name: Ensure combining two dictionaries containing undefined variables provides a helpful error
|
||||||
block:
|
block:
|
||||||
- set_fact:
|
- set_fact:
|
||||||
|
|
3
test/integration/targets/filter_random_mac/aliases
Normal file
3
test/integration/targets/filter_random_mac/aliases
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
shippable/posix/group2
|
||||||
|
skip/python2.6 # filters are controller only, and we no longer support Python 2.6 on the controller
|
||||||
|
skip/aix
|
59
test/integration/targets/filter_random_mac/tasks/main.yml
Normal file
59
test/integration/targets/filter_random_mac/tasks/main.yml
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
# test code for filters
|
||||||
|
# Copyright: (c) 2014, Michael DeHaan <michael.dehaan@gmail.com>
|
||||||
|
# Copyright: (c) 2019, Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
output_dir: "{{ lookup('env', 'OUTPUT_DIR') }}"
|
||||||
|
|
||||||
|
- 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' | random_mac is match('^00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
|
||||||
|
- "'00:00' | random_mac is match('^00:00:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]:[a-f0-9][a-f0-9]$')"
|
||||||
|
- "'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: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: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')"
|
Loading…
Add table
Reference in a new issue