diff --git a/changelogs/fragments/random_string_avoid.yml b/changelogs/fragments/random_string_avoid.yml index eccb07bb74..60eaf397d8 100644 --- a/changelogs/fragments/random_string_avoid.yml +++ b/changelogs/fragments/random_string_avoid.yml @@ -1,3 +1,3 @@ --- -bugfixes: - - random_string - allow user to set avoid_special_first and avoid_special_last (https://github.com/ansible-collections/community.general/issues/11816, https://github.com/ansible-collections/community.general/pull/11819). +minor_changes: + - random_string lookup plugin - allow user to set ``avoid_special_first`` and ``avoid_special_last`` (https://github.com/ansible-collections/community.general/issues/11816, https://github.com/ansible-collections/community.general/pull/11819). diff --git a/plugins/lookup/random_string.py b/plugins/lookup/random_string.py index 665b3d5ba8..4f5e0bf453 100644 --- a/plugins/lookup/random_string.py +++ b/plugins/lookup/random_string.py @@ -171,12 +171,12 @@ EXAMPLES = r""" - name: Generate random string with avoid_special_first debug: var: query('community.general.random_string', avoid_special_first=true) - # Example result: ['Uan0hUiX5kVG'] + # Example result: ['U@n0hUiX5kVG'] - name: Generate random string with avoid_special_last debug: var: query('community.general.random_string', avoid_special_last=true) - # Example result: ['Uan0hUiX5kVG'] + # Example result: ['U@n0hUiX5kVG'] """ RETURN = r""" @@ -267,7 +267,13 @@ class LookupModule(LookupBase): min_lower = self.get_option("min_lower") min_upper = self.get_option("min_upper") min_special = self.get_option("min_special") - if length < min_numeric + min_lower + min_upper + min_special: + min_non_special = min_numeric + min_lower + min_upper + if avoid_special_first and avoid_special_last: + min_non_special += 2 + elif avoid_special_first or avoid_special_last: + min_non_special += 1 + + if length < min_special + min_non_special: raise AnsibleLookupError("Minimum requirements exceed total length, please increase the length") # Ensure minimum requirements @@ -281,6 +287,10 @@ class LookupModule(LookupBase): # Fill remaining length remaining_length = length - len(result) + if min_non_special <= remaining_length: + # atleast one non-special character + available_chars_set = available_chars_set.replace(special_chars, '') + result += [random_generator.choice(available_chars_set) for dummy in range(remaining_length)] # Shuffle to avoid predictable pattern diff --git a/tests/integration/targets/lookup_random_string/test.yml b/tests/integration/targets/lookup_random_string/test.yml index 55a3abafc4..52d581ac6b 100644 --- a/tests/integration/targets/lookup_random_string/test.yml +++ b/tests/integration/targets/lookup_random_string/test.yml @@ -25,6 +25,7 @@ result15: "{{ query('community.general.random_string', seed='1234') }}" result16: "{{ query('community.general.random_string', avoid_special_first=true) }}" result17: "{{ query('community.general.random_string', avoid_special_last=true) }}" + result18: "{{ query('community.general.random_string', length=10, avoid_special_first=true, avoid_special_last=true, min_special=8) }}" - name: Raise error when impossible constraints are provided set_fact: @@ -44,6 +45,14 @@ ignore_errors: true register: override_all_special_characters_avoid_special_last_error + - name: Raise error when impossible constraints are provided + set_fact: + error: "{{ query('community.general.random_string', length=10, avoid_special_first=true, avoid_special_last=true, min_special=9) }}" + ignore_errors: true + register: len_10_avoid_special_first_avoid_special_last_min_special_9 + + - debug: + var: len_10_avoid_special_first_avoid_special_last_min_special_9 - name: Check results assert: that: @@ -68,7 +77,14 @@ - impossible_result is failed - "'Available characters cannot' in impossible_result.msg" - result15[0] == result14[0] + - result16[0][0] not in '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' + - result17[0][-1] not in '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' + - result18[0] | length == 10 + - result18[0][0] not in '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' + - result18[0][-1] not in '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' - override_all_special_characters_avoid_special_first_error is failed - "'No character satisfies the constraints for avoid_special_first' in override_all_special_characters_avoid_special_first_error.msg" - override_all_special_characters_avoid_special_last_error is failed - "'No character satisfies the constraints for avoid_special_last' in override_all_special_characters_avoid_special_last_error.msg" + - len_10_avoid_special_first_avoid_special_last_min_special_9 is failed + - "'Minimum requirements exceed total length, please increase the length' in len_10_avoid_special_first_avoid_special_last_min_special_9.msg"