# https://github.com/ansible/ansible/issues/43462 if hasattr(pexpect, 'spawn'): argspec = getargspec(pexpect.spawn.__init__) if 'echo' in argspec.args: HAS_PEXPECT = True except ImportError as e: pass # used to try and parse the hostname and detect if IPv6 is being used try: import ipaddress HAS_IPADDRESS = True except ImportError: HAS_IPADDRESS = False display = Display() class Connection(ConnectionBase): '''WinRM connections over HTTP/HTTPS.''' transport = 'winrm' module_implementation_preferences = ('.ps1', '.exe', '') become_methods = ['runas'] allow_executable = False has_pipelining = True allow_extras = True def __init__(self, *args, **kwargs): self.always_pipeline_modules = True
# try: # from __main__ import display # except ImportError: # from ansible.utils.display import Display # display = Display() # # This means that the verbosity-parameter of display _always_ default to # zero. There is no sane way to overwrite this. Within a normal ansible # setup __main__ corresponds to the current executable (e.g. "ansible-playbook"), # which creates a Display instance based on the cli parameters (-v, -vv, ...). # # This has to happen before anything from ansible is imported! import __main__ from ansible.utils.display import Display __main__.display = Display() import ansible.constants from ansible.executor.playbook_executor import PlaybookExecutor from ansible.parsing.dataloader import DataLoader from ansible.plugins.callback import CallbackBase import ansible.release ANSIBLE_VERSION = LooseVersion(ansible.release.__version__) if ANSIBLE_VERSION < LooseVersion('2.4.0'): from ansible.inventory import Inventory from ansible.vars import VariableManager else: from ansible.inventory.manager import InventoryManager from ansible.vars.manager import VariableManager
def display(*args, **kwargs): """Set up display function for Ansible v2""" display_instance = Display() display_instance.display(*args, **kwargs)
def run(self, terms, variables=None, **kwargs): netbox_api_token = kwargs.get("token") netbox_api_endpoint = kwargs.get("api_endpoint") netbox_ssl_verify = kwargs.get("validate_certs") netbox_private_key_file = kwargs.get("key_file") netbox_api_filter = kwargs.get("api_filter") netbox_raw_return = kwargs.get("raw_data") if not isinstance(terms, list): terms = [terms] try: netbox = pynetbox.api( netbox_api_endpoint, token=netbox_api_token if netbox_api_token else None, ssl_verify=netbox_ssl_verify, private_key_file=netbox_private_key_file, ) except FileNotFoundError: raise AnsibleError( "%s cannot be found. Please make sure file exists." % netbox_private_key_file) results = [] for term in terms: try: endpoint = get_endpoint(netbox, term) except KeyError: raise AnsibleError( "Unrecognised term %s. Check documentation" % term) Display().vvvv( u"Netbox lookup for %s to %s using token %s filter %s" % (term, netbox_api_endpoint, netbox_api_token, netbox_api_filter)) if netbox_api_filter: args_split = split_args(netbox_api_filter) args = [parse_kv(x) for x in args_split] filter = {} for arg in args: for k, v in arg.items(): if k not in filter: filter[k] = list() filter[k].append(v) else: filter[k].append(v) Display().vvvv("filter is %s" % filter) for res in endpoint.filter(**filter): Display().vvvvv(pformat(dict(res))) if netbox_raw_return: results.append(dict(res)) else: key = dict(res)["id"] result = {key: dict(res)} results.extend(self._flatten_hash_to_list(result)) else: for res in endpoint.all(): Display().vvvvv(pformat(dict(res))) if netbox_raw_return: results.append(dict(res)) else: key = dict(res)["id"] result = {key: dict(res)} results.extend(self._flatten_hash_to_list(result)) return results
- device_metadata: - cores: 1 # filter devices with interface in the specified space filter: - device_intf_space: AWS # use metadata for grouping, the group key1 will contain # subgroup for each value (eg key1_on and key1_off) group_metadata: - key1 - key2 ''' DISPLAY = Display() class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable): """ dynamic inventory module for EfficientIP Device Manager""" NAME = 'community.general.efficientip' sds = None space = None device_filter = [] limit = 0 group_metadata = [] group_metadata_val = [] def __init__(self): """ initialize the inventory module """
def defined(value, test_value=None, var_type=None, fail_action=None, var_name=None): """ defined - Ansible test plugin to test if a variable is defined and not none Arista.avd.defined will test value if defined and is not none and return true or false. If test_value is supplied, the value must also pass == test_value to return true. If var_type is supplied, the value must also be of the specified class/type If fail_action is 'warning' a warning will be emitted on failure. If fail_action is 'error' an error will be emitted on failure and the task will fail. If var_name is supplied it will be used in the warning and error messages to ease troubleshooting. Examples: 1. Test if var is defined and not none: {% if spanning_tree is arista.avd.defined %} ... {% endif %} 2. Test if variable is defined, not none and has value "something" {% if extremely_long_variable_name is arista.avd.defined("something") %} ... {% endif %} 3. Test if variable is defined and of not print a warning message with the variable name {% if my_dict.my_list[12].my_var is arista.avd.defined(fail_action='warning', var_name='my_dict.my_list[12].my_var' %} Parameters ---------- value : any Value to test from ansible test_value : any, optional Value to test in addition of defined and not none, by default None var_type : ['float', 'int', 'str', 'list', 'dict', 'tuple'], optional Type or Class to test for fail_action : ['warning', 'error'], optional Optional action if test fails to emit a Warning or Error var_name : <string>, optional Optional string to use as variable name in warning or error messages Returns ------- boolean True if variable matches criteria, False in other cases. """ if isinstance(value, Undefined) or value is None: # Invalid value - return false if str(fail_action).lower() == 'warning': if var_name is not None: Display().warning( f"{var_name} was expected but not set. Output may be incorrect or incomplete!" ) else: Display().warning( "A variable was expected but not set. Output may be incorrect or incomplete!" ) elif str(fail_action).lower() == 'error': if var_name is not None: raise AnsibleError(f"{var_name} was expected but not set!") else: raise AnsibleError("A variable was expected but not set!") return False elif test_value is not None and value != test_value: # Valid value but not matching the optional argument if str(fail_action).lower() == 'warning': if var_name is not None: Display().warning( f"{var_name} was set to {value} but we expected {test_value}. Output may be incorrect or incomplete!" ) else: Display().warning( f"A variable was set to {value} but we expected {test_value}. Output may be incorrect or incomplete!" ) elif str(fail_action).lower() == 'error': if var_name is not None: raise AnsibleError( f"{var_name} was set to {value} but we expected {test_value}!" ) else: raise AnsibleError( f"A variable was set to {value} but we expected {test_value}!" ) return False elif str(var_type).lower() in [ 'float', 'int', 'str', 'list', 'dict', 'tuple' ] and str(var_type).lower() != type(value).__name__: # Invalid class - return false if str(fail_action).lower() == 'warning': if var_name is not None: Display().warning( f"{var_name} was a {type(value).__name__} but we expected a {str(var_type).lower()}. Output may be incorrect or incomplete!" ) else: Display().warning( f"A variable was a {type(value).__name__} but we expected a {str(var_type).lower()}. Output may be incorrect or incomplete!" ) elif str(fail_action).lower() == 'error': if var_name is not None: raise AnsibleError( f"{var_name} was a {type(value).__name__} but we expected a {str(var_type).lower()}!" ) else: raise AnsibleError( f"A variable was a {type(value).__name__} but we expected a {str(var_type).lower()}!" ) return False else: # Valid value and is matching optional argument if provided - return true return True
def display(*args, **kwargs): display_instance = Display() display_instance.display(*args, **kwargs)
import difflib import warnings from copy import deepcopy from ansible.compat.six import string_types from ansible import constants as C from ansible.vars import strip_internal_keys from ansible.utils.color import stringc from ansible.utils.unicode import to_unicode try: from __main__ import display as global_display except ImportError: from ansible.utils.display import Display global_display = Display() __all__ = ["CallbackBase"] try: from __main__ import cli except ImportError: # using API w/o cli cli = False class CallbackBase: ''' This is a base ansible callback class that does nothing. New callbacks should use this class as a base and override any callback methods they wish to execute custom actions.
# We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr)) if color == CONST.COLOR_ERROR: logger.error(msg2) else: logger.info(msg2) import ansible.utils.display as default_display default_display.logger = logger default_display.Display.display = fabric_ansible_display from ansible.utils.display import Display display = Display(verbosity) from ansible.parsing.dataloader import DataLoader from ansible.vars.manager import VariableManager from ansible.inventory.manager import InventoryManager from ansible.executor.playbook_executor import PlaybookExecutor from job_manager.job_messages import MsgBundle from job_manager.job_manager_logger import job_mgr_logger JM_LOGGER = job_mgr_logger("FabricAnsible") class PlaybookHelper(object): def get_plugin_output(self, pbex): output_json = pbex._tqm._variable_manager._nonpersistent_fact_cache[ 'localhost'].get('output')
def __init__(self, username, playbook, private_key_file, inventory_data, extra_vars, become_pass, verbosity=0, search_filter=None): """ Args: username: string, username of user running the playbook playbook: string, full playbook path eg. /tmp/my_pb.yml private_key_file: string, private key file inventory_data: dict, inventory data extra_vars: dict, Ansible extra vars, key = variable name become_pass: string, become password verbosity: integer, verbosity level search_filter: string, hosts/groups to match """ self.playbook = playbook self.username = username self.inventory_data = inventory_data self.extra_vars = extra_vars self.search_filter = search_filter self.options = Options() self.options.private_key_file = private_key_file self.options.verbosity = verbosity self.options.connection = 'ssh' # Need a connection type "smart" or "ssh" self.options.become = True self.options.become_method = 'sudo' self.options.become_user = '******' # Set global verbosity self.display = Display() self.display.verbosity = self.options.verbosity # Executor appears to have it's own verbosity object/setting as well playbook_executor.verbosity = self.options.verbosity # Become Pass Needed if not logging in as user root passwords = {'become_pass': become_pass} # Gets data from YAML/JSON files self.loader = DataLoader() # ORIGNAL on line 1 #self.loader.set_vault_password(os.environ['VAULT_PASS']) self.loader.set_vault_password('secret') # All the variables from all the various places self.variable_manager = VariableManager() # Set of hosts hosts = set() # Load group variable for group in self.inventory_data: if group != '_meta': for host in self.inventory_data[group]['hosts']: host_obj = Host(host) hosts.add(host) for var in self.inventory_data[group]['vars']: self.variable_manager.set_host_variable( host_obj, var, self.inventory_data[group]['vars'][var]) # Load host variables for host in self.inventory_data['_meta']['hostvars']: for var in self.inventory_data['_meta']['hostvars'][host]: host_obj = Host(host) self.variable_manager.set_host_variable( host_obj, var, self.inventory_data['_meta']['hostvars'][host][var]) self.variable_manager.extra_vars = self.extra_vars # Set inventory, using most of above objects self.inventory = Inventory(loader=self.loader, variable_manager=self.variable_manager, host_list=list(hosts)) self.variable_manager.set_inventory(self.inventory) # Setup playbook executor, but don't run until run() called self.pbex = playbook_executor.PlaybookExecutor( playbooks=[self.playbook], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options, passwords=passwords)
class ActionModule(ActionBase): #pylint: disable=R0903 """ The action module class """ display = Display() def _get_network_os(self, task_vars): if 'network_os' in self._task.args and self._task.args['network_os']: self.display.vvvv('Getting network OS from task argument') network_os = self._task.args['network_os'] elif self._play_context.network_os: self.display.vvvv('Getting network OS from inventory') network_os = self._play_context.network_os elif ('network_os' in task_vars.get('ansible_facts', {}) and task_vars['ansible_facts']['network_os']): self.display.vvvv('Getting network OS from fact') network_os = task_vars['ansible_facts']['network_os'] else: raise AnsibleError( 'ansible_network_os must be specified on this host.') return network_os def _get_os_resource(self, network_os, resource): parsers = [ p for p in parser_loader.all() if p.PARSER_METADATA['network_os'] == network_os and p.PARSER_METADATA['resource'] == resource ] if not parsers: self.display.warning( "No parser available for resource %s for network os %s" % (resource, network_os)) return None return parsers[0] def _run_command(self, command, task_vars): socket_path = getattr(self._connection, 'socket_path') or task_vars.get('ansible_socket') connection = Connection(socket_path) try: output = connection.get(command) except ConnectionError as exc: raise AnsibleError(to_text(exc)) return output @staticmethod def _command_map(): command_map = {} parsers = [p.PARSER_METADATA for p in parser_loader.all()] for parser in parsers: if not parser['resource'] in command_map: command_map[parser['resource']] = {} if not os in command_map[parser['resource']]: command_map[parser['resource']][parser['network_os']] = [] command_map[parser['resource']][parser['network_os']].append( parser['commands']) return command_map @staticmethod def _validate_args(args): provided = set(list(args.keys())) valid_args = set( ['resources', 'update_facts', 'fact_key', '_return_command_map']) extras = provided - valid_args if extras: raise AnsibleError( "The following arguments are not supported: %s" % ','.join(extras)) def run(self, tmp=None, task_vars=None): self.display.verbosity = self._play_context.verbosity self._validate_args(self._task.args) result = super(ActionModule, self).run(tmp, task_vars) if '_return_command_map' in self._task.args and self._task.args[ '_return_command_map']: result.update({'command_map': self._command_map()}) return result network_os = self._get_network_os(task_vars) facts = {} if 'resources' in self._task.args and self._task.args['resources']: resources = self._task.args['resources'] else: resources = [ p.PARSER_METADATA['resource'] for p in parser_loader.all() if p.PARSER_METADATA['network_os'] == network_os ] for resource in resources: if 'name' in resource: resource_name = resource['name'] else: resource_name = resource parser = self._get_os_resource(network_os, resource_name) if parser: if 'output' in resource: outputs = resource['output'] else: outputs = [] for command in parser.PARSER_METADATA['commands']: outputs.append(self._run_command(command, task_vars)) objs = parser.parse(outputs) facts.update( json.loads(json.dumps(objs, sort_keys=True, cls=ToFacts))) if 'update_facts' in self._task.args: result.update( {'ansible_facts': { self._task.args['fact_key']: facts }}) result.update({'results': facts}) return result
def __init__(self, playbook, inventory, run_data, start_at_task, step, private_key_file, become_pass, verbosity=0): self.run_data = run_data self.options = Options() self.options.listtags = False self.options.listtasks = False self.options.listhosts = False self.options.syntax = False self.options.check = False self.options.diff = False self.options.start_at_task = start_at_task self.options.step = step self.options.private_key_file = private_key_file self.options.verbosity = verbosity self.options.connection = 'ssh' # Need a connection type "smart" or "ssh" self.options.become = False self.options.become_method = 'sudo' self.options.become_user = '******' self.options.remote_user = '******' # Set global verbosity self.display = Display() self.display.verbosity = self.options.verbosity # Executor appears to have it's own # verbosity object/setting as well #playbook_executor.verbosity = self.options.verbosity # Become Pass Needed if not logging in as user root passwords = {'become_pass': become_pass} # Gets data from YAML/JSON files self.loader = DataLoader() # self.loader.set_vault_password(os.environ['VAULT_PASS']) # All the variables from all the various places # Parse hosts, I haven't found a good way to # pass hosts in without using a parsed template :( # (Maybe you know how?) # self.hosts = NamedTemporaryFile(delete=False) # self.hosts.write("""[run_hosts] # %s # """ % hostnames) # self.hosts.close() # This was my attempt to pass in hosts directly. # # Also Note: In py2.7, "isinstance(foo, str)" is valid for # latin chars only. Luckily, hostnames are # ascii-only, which overlaps latin charset ## if isinstance(hostnames, str): ## hostnames = {"customers": {"hosts": [hostnames]}} # Set inventory, using most of above objects inventory_dir = '/etc/ansible/inventory' inventory_source = "%s/%s" % (inventory_dir, inventory) self.inventory = InventoryManager(loader=self.loader, sources=inventory_source) self.variable_manager = VariableManager(loader=self.loader, inventory=self.inventory) if self.run_data: self.variable_manager.extra_vars = self.run_data['extra_vars'] self.options.tags = self.run_data['tags'] # Playbook to run. Assumes it is # local to this python file pb_dir = '/etc/ansible/playbooks' playbook = "%s/%s" % (pb_dir, playbook) print(playbook) # Setup playbook executor, but don't run until run() called self.pbex = playbook_executor.PlaybookExecutor( playbooks=[playbook], inventory=self.inventory, variable_manager=self.variable_manager, loader=self.loader, options=self.options.get_config(), passwords=passwords)