Source code for test_plugins.util

# -*- coding: utf-8 -*-

"""Validations and variable handling utilities."""
import grp
import requests
import os
import pwd
import re

from ansible.module_utils._text import to_bytes
from ansible.module_utils._text import to_text
from collections import Sequence
from jinja2.exceptions import UndefinedError as JinjaUndefinedError

"""
.. module:: util
    :noindex:
    :platform: Linux
    :synopsis:  Applies validations and assert variable status.

.. moduleauthor:: constrict0r <constrict0r@protonmail.com>
"""


[docs]class TestModule(object): """Test filters for validations and variable handling."""
[docs] def tests(self): """Define available test filters. Returns: dict: Collection of available tests filters. """ return { 'user_root': self.user_root, 'variable_boolean': self.variable_boolean, 'variable_boolean_true': self.variable_boolean_true, 'variable_collection': self.variable_collection, 'variable_empty': self.variable_empty, 'variable_path': self.variable_path, 'variable_url': self.variable_url, 'variable_url_existent': self.variable_url_existent, } # pragma: no cover
[docs] def user_root(self, username=None): """Verifies if an user can become sudo or not. If the username is not defined or empty, False will be returned. Args: username (str): Username to check. Returns: bool: True if the user can become sudo, False otherwise. """ if not username: return False # pragma: no cover # Verify if /etc/sudoers.d/username file exists. if os.path.exists('/etc/sudoers.d/' + username): return True # pragma: no cover # Get current user groups. groups = [g.gr_name for g in grp.getgrall() if username in g.gr_mem] gid = pwd.getpwnam(username).pw_gid groups.append(grp.getgrgid(gid).gr_name) if 'sudo' in groups or 'root' in groups: return True # pragma: no cover return False # pragma: no cover
[docs] def variable_boolean(self, value): """Verifies if a variable is boolean or not. Args: value (str): Variable to test. Returns: bool: True if variable is of type boolean, false otherwise. """ if not self.variable_empty(value): text_value = to_text(value) if not self.variable_collection(text_value): if isinstance(text_value, (bool)): return True # pragma: no cover text_value = text_value.lower() if text_value == 'false' or text_value == 'true': return True # pragma: no cover elif text_value == 'yes' or text_value == 'no': return True # pragma: no cover return False # pragma: no cover
[docs] def variable_boolean_true(self, value): """Verifies if a variable is boolean and its value is True. Args: value (str): Variable to test. Returns: bool: True if variable is of type boolean and its value is True, false otherwise. """ if self.variable_boolean(value): text_value = to_text(value) text_value = text_value.lower() if text_value == 'true' or text_value == 'yes': return True # pragma: no cover return False # pragma: no cover
[docs] def variable_collection(self, value): """Verifies if a variable is a collection or not. To this function, an empty variable is not considered a collection. Args: value (str): Variable to test. Returns: bool: True if variable is a non-empty collection, False otherwise. """ if not self.variable_empty(value): text_value = to_text(value) if isinstance(text_value, (bool)): return False # pragma: no cover if isinstance(value, Sequence): collection_regexes = [ r'\[(.*)\]', r'\{(.*)\}', ] collection_regex = re.compile('|' . join(collection_regexes), re.IGNORECASE) search_result = re.search(collection_regex, text_value) if search_result: return True # pragma: no cover return False # pragma: no cover
[docs] def variable_empty(self, value): """Verifies if a variable is empty or not. Args: value (str): Variable to test. Returns: bool: True if the variable is a non-empty, False otherwise. """ # Python defined. try: value except NameError: # pragma: no cover return True # pragma: no cover except KeyError: # pragma: no cover return True # pragma: no cover # None. if value is None: return True # pragma: no cover # Jinja defined and null. try: text_value = to_text(value) except JinjaUndefinedError: # pragma: no cover return True # pragma: no cover except ValueError: # pragma: no cover return True # pragma: no cover if text_value == 'None': return True # pragma: no cover # Ansible null. if text_value == 'null': return True # pragma: no cover # Empty. if text_value == '': return True # pragma: no cover # Avoid Ansible error: 'undefined_variable' is undefined. if 'VARIABLE IS NOT DEFINED!' in text_value: return True # pragma: no cover # Don't allow jinja variables inside value, possibly undefined. if '{{' in text_value: return True # pragma: no cover # Empty collection. if isinstance(value, Sequence): collection_regexes = [ r'\[(.*)\]', r'\{(.*)\}', ] collection_regex = re.compile('|' . join(collection_regexes), re.IGNORECASE) search_result = re.search(collection_regex, text_value) if search_result: if str(str(search_result.group(0))) == '[]' or \ str(str(search_result.group(0))) == '{}': return True # pragma: no cover return False # pragma: no cover
[docs] def variable_path(self, value): """Verifies if a variable is an existing file or not. Args: value (str): Variable to test. Returns: bool: True if variable is an existing file path, False otherwise. """ if not self.variable_empty(value): text_value = to_text(value) if not self.variable_collection(text_value): if not self.variable_boolean(text_value): if os.path.exists(to_bytes(text_value, 'utf-8')): return True # pragma: no cover return False # pragma: no cover
[docs] def variable_url(self, value): """Verifies if a variable is a valid URL. Args: value (str): Variable to test. Returns: bool: True if variable is a valid URL, False otherwise. """ # Django URL regex: https://is.gd/VcqRWa. url_regex = re.compile( r'^https?://' r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' r'localhost|' r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' r'(?::\d+)?' r'(?:/?|[/?]\S+)$', re.IGNORECASE) if not self.variable_empty(value): text_value = to_text(value) if not self.variable_collection(text_value): if not self.variable_boolean(text_value): if url_regex.search(text_value): return True # pragma: no cover return False # pragma: no cover
[docs] def variable_url_existent(self, value): """Verifies if a variable is an existent URL. Is recommended to use URL pointing to single files, not index or main. Args: value (str): Variable to test. Returns: bool: True if variable is an existent URL, False otherwise. """ if not self.variable_empty(value): text_value = to_text(value) if not self.variable_collection(text_value): if not self.variable_boolean(text_value): if self.variable_url(text_value): request = requests.get(text_value) if request.status_code == 200: return True # pragma: no cover return False # pragma: no cover