a ì)gã @sddlmZmZmZeZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlmZmZmZddlmZddlmZmZddlmZddlmZddlmZdd lmZ dd l!m"Z"dd l#m$Z$m%Z%m&Z&dd l'm(Z(dd l)m*Z*m+Z+ddl,m-Z-ddl.m/Z/ddl0m1Z1ddl2Z3ddl4Z3e/ƒZ5e1dgd¢ƒZ6dZ7dZ8dZ9dZ:dZ;dZe j? @e j? AeB¡dd¡ZCdZDdZEdZFd ZGd!d"„ZHejIr¢eDZJneHeDƒZJe j? Ae j? Ae j? AeB¡¡¡ZKe  Ld#e  MeK¡¡ZNe  Ld$¡ZOe  Ld%¡ZPGd&d'„d'ejQƒZRd(d)„ZSeTƒd*fd+d,„ZUGd-d.„d.ƒZVGd/d0„d0eVƒZWGd1d2„d2eVƒZXd3d4„ZYd5d6„ZZd7d8„Z[d9d:„Z\dDd;d<„Z]d=d>„Z^dEd@dA„Z_dFdBdC„Z`dS)Gé)Úabsolute_importÚdivisionÚprint_functionN)ÚASTÚImportÚ ImportFrom)ÚBytesIO)Ú __version__Ú __author__)Ú constants)Ú AnsibleError)Ú!InterpreterDiscoveryRequiredError)Úmodule_manifest)ÚAnsibleJSONEncoder)Úto_bytesÚto_textÚ to_native)Úmodule_utils_loader)Ú_get_collection_metadataÚ_nested_dict_get)Úaction_write_locks)ÚDisplay)Ú namedtupleÚModuleUtilsProcessEntry)Ú name_partsÚ is_ambiguousZhas_redirected_childÚ is_optionals"#<>s"<>"s)"<>"s# POWERSHELL_COMMONs$<>s<>z# -*- coding: utf-8 -*-s# -*- coding: utf-8 -*-z..Ú module_utilsaÞ.%(shebang)s %(coding)s _ANSIBALLZ_WRAPPER = True # For test-module.py script to tell this is a ANSIBALLZ_WRAPPER # This code is part of Ansible, but is an independent component. # The code in this particular templatable string, and this templatable string # only, is BSD licensed. Modules which end up using this snippet, which is # dynamically combined together by Ansible still belong to the author of the # module, and they may assign their own license to the complete work. # # Copyright (c), James Cammarata, 2016 # Copyright (c), Toshio Kuratomi, 2016 # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. def _ansiballz_main(): import os import os.path # Access to the working directory is required by Python when using pipelining, as well as for the coverage module. # Some platforms, such as macOS, may not allow querying the working directory when using become to drop privileges. try: os.getcwd() except OSError: try: os.chdir(os.path.expanduser('~')) except OSError: os.chdir('/') %(rlimit)s import sys import __main__ # For some distros and python versions we pick up this script in the temporary # directory. This leads to problems when the ansible module masks a python # library that another import needs. We have not figured out what about the # specific distros and python versions causes this to behave differently. # # Tested distros: # Fedora23 with python3.4 Works # Ubuntu15.10 with python2.7 Works # Ubuntu15.10 with python3.4 Fails without this # Ubuntu16.04.1 with python3.5 Fails without this # To test on another platform: # * use the copy module (since this shadows the stdlib copy module) # * Turn off pipelining # * Make sure that the destination file does not exist # * ansible ubuntu16-test -m copy -a 'src=/etc/motd dest=/var/tmp/m' # This will traceback in shutil. Looking at the complete traceback will show # that shutil is importing copy which finds the ansible module instead of the # stdlib module scriptdir = None try: scriptdir = os.path.dirname(os.path.realpath(__main__.__file__)) except (AttributeError, OSError): # Some platforms don't set __file__ when reading from stdin # OSX raises OSError if using abspath() in a directory we don't have # permission to read (realpath calls abspath) pass # Strip cwd from sys.path to avoid potential permissions issues excludes = set(('', '.', scriptdir)) sys.path = [p for p in sys.path if p not in excludes] import base64 import runpy import shutil import tempfile import zipfile if sys.version_info < (3,): PY3 = False else: PY3 = True ZIPDATA = """%(zipdata)s""" # Note: temp_path isn't needed once we switch to zipimport def invoke_module(modlib_path, temp_path, json_params): # When installed via setuptools (including python setup.py install), # ansible may be installed with an easy-install.pth file. That file # may load the system-wide install of ansible rather than the one in # the module. sitecustomize is the only way to override that setting. z = zipfile.ZipFile(modlib_path, mode='a') # py3: modlib_path will be text, py2: it's bytes. Need bytes at the end sitecustomize = u'import sys\nsys.path.insert(0,"%%s")\n' %% modlib_path sitecustomize = sitecustomize.encode('utf-8') # Use a ZipInfo to work around zipfile limitation on hosts with # clocks set to a pre-1980 year (for instance, Raspberry Pi) zinfo = zipfile.ZipInfo() zinfo.filename = 'sitecustomize.py' zinfo.date_time = ( %(year)i, %(month)i, %(day)i, %(hour)i, %(minute)i, %(second)i) z.writestr(zinfo, sitecustomize) z.close() # Put the zipped up module_utils we got from the controller first in the python path so that we # can monkeypatch the right basic sys.path.insert(0, modlib_path) # Monkeypatch the parameters into basic from ansible.module_utils import basic basic._ANSIBLE_ARGS = json_params %(coverage)s # Run the module! By importing it as '__main__', it thinks it is executing as a script runpy.run_module(mod_name='%(module_fqn)s', init_globals=dict(_module_fqn='%(module_fqn)s', _modlib_path=modlib_path), run_name='__main__', alter_sys=True) # Ansible modules must exit themselves print('{"msg": "New-style module did not handle its own exit", "failed": true}') sys.exit(1) def debug(command, zipped_mod, json_params): # The code here normally doesn't run. It's only used for debugging on the # remote machine. # # The subcommands in this function make it easier to debug ansiballz # modules. Here's the basic steps: # # Run ansible with the environment variable: ANSIBLE_KEEP_REMOTE_FILES=1 and -vvv # to save the module file remotely:: # $ ANSIBLE_KEEP_REMOTE_FILES=1 ansible host1 -m ping -a 'data=october' -vvv # # Part of the verbose output will tell you where on the remote machine the # module was written to:: # [...] # SSH: EXEC ssh -C -q -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o # PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o # ControlPath=/home/badger/.ansible/cp/ansible-ssh-%%h-%%p-%%r -tt rhel7 '/bin/sh -c '"'"'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 # LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/badger/.ansible/tmp/ansible-tmp-1461173013.93-9076457629738/ping'"'"'' # [...] # # Login to the remote machine and run the module file via from the previous # step with the explode subcommand to extract the module payload into # source files:: # $ ssh host1 # $ /usr/bin/python /home/badger/.ansible/tmp/ansible-tmp-1461173013.93-9076457629738/ping explode # Module expanded into: # /home/badger/.ansible/tmp/ansible-tmp-1461173408.08-279692652635227/ansible # # You can now edit the source files to instrument the code or experiment with # different parameter values. When you're ready to run the code you've modified # (instead of the code from the actual zipped module), use the execute subcommand like this:: # $ /usr/bin/python /home/badger/.ansible/tmp/ansible-tmp-1461173013.93-9076457629738/ping execute # Okay to use __file__ here because we're running from a kept file basedir = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'debug_dir') args_path = os.path.join(basedir, 'args') if command == 'explode': # transform the ZIPDATA into an exploded directory of code and then # print the path to the code. This is an easy way for people to look # at the code on the remote machine for debugging it in that # environment z = zipfile.ZipFile(zipped_mod) for filename in z.namelist(): if filename.startswith('/'): raise Exception('Something wrong with this module zip file: should not contain absolute paths') dest_filename = os.path.join(basedir, filename) if dest_filename.endswith(os.path.sep) and not os.path.exists(dest_filename): os.makedirs(dest_filename) else: directory = os.path.dirname(dest_filename) if not os.path.exists(directory): os.makedirs(directory) f = open(dest_filename, 'wb') f.write(z.read(filename)) f.close() # write the args file f = open(args_path, 'wb') f.write(json_params) f.close() print('Module expanded into:') print('%%s' %% basedir) exitcode = 0 elif command == 'execute': # Execute the exploded code instead of executing the module from the # embedded ZIPDATA. This allows people to easily run their modified # code on the remote machine to see how changes will affect it. # Set pythonpath to the debug dir sys.path.insert(0, basedir) # read in the args file which the user may have modified with open(args_path, 'rb') as f: json_params = f.read() # Monkeypatch the parameters into basic from ansible.module_utils import basic basic._ANSIBLE_ARGS = json_params # Run the module! By importing it as '__main__', it thinks it is executing as a script runpy.run_module(mod_name='%(module_fqn)s', init_globals=None, run_name='__main__', alter_sys=True) # Ansible modules must exit themselves print('{"msg": "New-style module did not handle its own exit", "failed": true}') sys.exit(1) else: print('WARNING: Unknown debug command. Doing nothing.') exitcode = 0 return exitcode # # See comments in the debug() method for information on debugging # ANSIBALLZ_PARAMS = %(params)s if PY3: ANSIBALLZ_PARAMS = ANSIBALLZ_PARAMS.encode('utf-8') try: # There's a race condition with the controller removing the # remote_tmpdir and this module executing under async. So we cannot # store this in remote_tmpdir (use system tempdir instead) # Only need to use [ansible_module]_payload_ in the temp_path until we move to zipimport # (this helps ansible-test produce coverage stats) temp_path = tempfile.mkdtemp(prefix='ansible_%(ansible_module)s_payload_') zipped_mod = os.path.join(temp_path, 'ansible_%(ansible_module)s_payload.zip') with open(zipped_mod, 'wb') as modlib: modlib.write(base64.b64decode(ZIPDATA)) if len(sys.argv) == 2: exitcode = debug(sys.argv[1], zipped_mod, ANSIBALLZ_PARAMS) else: # Note: temp_path isn't needed once we switch to zipimport invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS) finally: try: shutil.rmtree(temp_path) except (NameError, OSError): # tempdir creation probably failed pass sys.exit(exitcode) if __name__ == '__main__': _ansiballz_main() a os.environ['COVERAGE_FILE'] = '%(coverage_output)s=python-%%s=coverage' %% '.'.join(str(v) for v in sys.version_info[:2]) import atexit try: import coverage except ImportError: print('{"msg": "Could not import `coverage` module.", "failed": true}') sys.exit(1) cov = coverage.Coverage(config_file='%(coverage_config)s') def atexit_coverage(): cov.stop() cov.save() atexit.register(atexit_coverage) cov.start() aŽ try: if PY3: import importlib.util if importlib.util.find_spec('coverage') is None: raise ImportError else: import imp imp.find_module('coverage') except ImportError: print('{"msg": "Could not find `coverage` module.", "failed": true}') sys.exit(1) aÔ import resource existing_soft, existing_hard = resource.getrlimit(resource.RLIMIT_NOFILE) # adjust soft limit subject to existing hard limit requested_soft = min(existing_hard, %(rlimit_nofile)d) if requested_soft != existing_soft: try: resource.setrlimit(resource.RLIMIT_NOFILE, (requested_soft, existing_hard)) except ValueError: # some platforms (eg macOS) lie about their hard limit pass cCs>g}| ¡D]&}| ¡}|r | d¡r(q | |¡q d |¡S)Nú#Ú )Ú splitlinesÚstripÚ startswithÚappendÚjoin)ÚsourceÚbufÚlineÚl©r)úB/usr/lib/python3.9/site-packages/ansible/executor/module_common.pyÚ_strip_commentsˆs  r+z*%s/(?Pansible/modules/.*)\.(py|ps1)$zH/(?Pansible_collections/[^/]+/[^/]+/plugins/modules/.*)\.(py|ps1)$sý(?:from +\.{2,} *module_utils.* +import |from +ansible_collections\.[^.]+\.[^.]+\.plugins\.module_utils.* +import |import +ansible_collections\.[^.]+\.[^.]+\.plugins\.module_utils.*|from +ansible\.module_utils.* +import |import +ansible\.module_utils\.)cs:eZdZd ‡fdd„ Zdd„ZeZdd„Zdd „Z‡ZS) ÚModuleDepFinderFcsXtt|ƒj|i|¤Ž||_tƒ|_tƒ|_||_||_t |j t |j i|_ | |¡dS)aÝ Walk the ast tree for the python module. :arg module_fqn: The fully qualified name to reach this module in dotted notation. example: ansible.module_utils.basic :arg is_pkg_init: Inform the finder it's looking at a package init (eg __init__.py) to allow relative import expansion to use the proper package level without having imported it locally first. Save submodule[.submoduleN][.identifier] into self.submodules when they are from ansible.module_utils or ansible_collections packages self.submodules will end up with tuples like: - ('ansible', 'module_utils', 'basic',) - ('ansible', 'module_utils', 'urls', 'fetch_url') - ('ansible', 'module_utils', 'database', 'postgres') - ('ansible', 'module_utils', 'database', 'postgres', 'quote') - ('ansible', 'module_utils', 'database', 'postgres', 'quote') - ('ansible_collections', 'my_ns', 'my_col', 'plugins', 'module_utils', 'foo') It's up to calling code to determine whether the final element of the tuple are module names or something else (function, class, or variable names) .. seealso:: :python3:class:`ast.NodeVisitor` N)Úsuperr,Ú__init__Ú_treeÚsetÚ submodulesÚoptional_importsÚ module_fqnÚ is_pkg_initrÚ visit_ImportrÚvisit_ImportFromÚ _visit_mapÚvisit)Úselfr3Útreer4ÚargsÚkwargs©Ú __class__r)r*r.·sþzModuleDepFinder.__init__cCsn|j}|j}t |¡D]R\}}t|tƒr|D]:}t|ttfƒrT||_||j |ƒq,t|t ƒr,||ƒq,qdS)zÕOverridden ``generic_visit`` that makes some assumptions about our use case, and improves performance by calling visitors directly instead of calling ``visit`` to offload calling visitors. N) Ú generic_visitr7ÚastZ iter_fieldsÚ isinstanceÚlistrrÚparentr>r)r9Únoder?Z visit_mapZfieldÚvalueÚitemr)r)r*r?Üs  zModuleDepFinder.generic_visitcCsf|jD]P}|j d¡s"|j d¡rt|j d¡ƒ}|j |¡|j|jkr|j  |¡q|  |¡dS)zÖ Handle import ansible.module_utils.MODLIB[.MODLIBn] [as asname] We save these as interesting submodules when the imported library is in ansible.module_utils or ansible.collections zansible.module_utils.úansible_collections.Ú.N) ÚnamesÚnamer"ÚtupleÚsplitr1ÚaddrCr/r2r?)r9rDÚaliasÚpy_modr)r)r*r5îs   ÿ  zModuleDepFinder.visit_ImportcCs>|jdkr||jr |j dp&dn|j }|jrtt|j d¡ƒ}|jr`d |d|…|jf¡}qzd |d|…¡}q‚|j}n|j}d}|jdjdkr¤|j   d¡nF|  d¡r¾t| d¡ƒ}n,|  d¡rê|  d ¡sÚd |vrêt| d¡ƒ}n|r0|jD]8}|j   ||jf¡|j |jkrö|j  ||jf¡qö| |¡dS) a  Handle from ansible.module_utils.MODLIB import [.MODLIBn] [as asname] Also has to handle relative imports We save these as interesting submodules when the imported library is in ansible.module_utils or ansible.collections réNrHÚ_six)rQzansible.module_utilsrGzplugins.module_utilsz.plugins.module_utils.)Úlevelr4r3rKrLÚmoduler$rIrJr1rMr"ÚendswithrCr/r2r?)r9rDZlevel_slice_offsetÚpartsZ node_modulerOrNr)r)r*r6ÿs.     z ModuleDepFinder.visit_ImportFrom)F) Ú__name__Ú __module__Ú __qualname__r.r?r8r5r6Ú __classcell__r)r)r=r*r,¶s %r,cCsVtj |¡s tdtj |¡ƒ‚t|dƒ}| ¡}Wdƒn1sH0Y|S)Nz1imported module support code does not exist at %sÚrb)ÚosÚpathÚexistsr ÚabspathÚopenÚread)r\ÚfdÚdatar)r)r*Ú_slurpAs   &rcFc Cstj |¡ ¡}d|}d| ¡}d}|dkrº|r>|d}qÖtj |¡rªtjj||d} |  |  ¡¡}|rt|dvr¸d|} |  d i¡} | | vr t d ||d ‚q¸| | }qÖt d |d d ‚n||vrÖ|  |  |¡ ¡¡}|sÞ|}d  |¡} |rþ| dd  |¡} | |fS)za Handles the different ways ansible allows overriding the shebang target for a module. zansible_%s_interpreterzINTERPRETER_%sNÚpythonZansible_playbook_python©Z variables)ÚautoÚ auto_legacyZ auto_silentZauto_legacy_silentzdiscovered_interpreter_%sZ ansible_factszinterpreter discovery needed)Úinterpreter_nameZdiscovery_modezinterpreter discovery requiredrgz#!{0}ú )r[r\Úbasenamer!ÚupperÚCÚconfigZget_configuration_definitionÚget_config_valueÚtemplateÚgetr Úformatr$) Ú interpreterÚ task_varsÚtemplarr;Úremote_is_localrhZinterpreter_configZinterpreter_config_keyZinterpreter_outZinterpreter_from_configZdiscovered_interpreter_configZfacts_from_task_varsÚshebangr)r)r*Ú _get_shebangIs2       rwc@sTeZdZddd„Zedd„ƒZdd„Zdd „Zd d „Zd d „Z ddd„Z dd„Z dS)ÚModuleUtilLocatorBaseFcCsr||_||_||_d|_d|_||_d|_d|_d|_d|_ |rft |  |¡ƒdkrf||dd…g|_ n|g|_ dS)NFÚrPéÿÿÿÿ) Z _is_ambiguousÚ_child_is_redirectedÚ _is_optionalÚfoundÚ redirectedÚ fq_name_partsÚ source_codeÚ output_pathÚ is_packageÚ_collection_nameÚlenÚ!_get_module_utils_remainder_partsÚcandidate_names©r9rrÚchild_is_redirectedrr)r)r*r.ƒszModuleUtilLocatorBase.__init__cCsdd„|jDƒS)NcSsg|]}d |¡‘qS)rH)r$)Ú.0Únr)r)r*Ú šóz@ModuleUtilLocatorBase.candidate_names_joined..)r†)r9r)r)r*Úcandidate_names_joined˜sz,ModuleUtilLocatorBase.candidate_names_joinedc CsÂ| |¡}|sdSzt|jƒ}WnVtyv}z>|jrDWYd}~dStd d |¡|jt|ƒ¡ƒ‚WYd}~n d}~00t |ddd |¡gƒ}|s–dS|  d¡}|du}|s¶|  d¡}|r|  d¡}|  d ¡} |  d ¡} d  d |¡¡} | rþ| d  | ¡7} n| d7} t   | | |||j¡d |vr¾d|_ d |¡} d|_|d } |  d¡sš|  d¡}t|ƒdkrvtd | | ¡ƒ‚d |d|dd |dd…¡¡} t  d | | ¡¡| | | ¡|_dSdS)NFzGerror processing module_util {0} loading redirected collection {1}: {2}rHZplugin_routingrZ tombstoneZ deprecationÚ removal_dateÚremoval_versionÚ warning_textz module_util {0} has been removedz ({0})ZredirectTÚansible_collectionsézinvalid redirect for {0}: {1}z4ansible_collections.{0}.{1}.plugins.module_utils.{2}rrPéz"redirecting module_util {0} to {1})r…rrƒÚ ValueErrorr|r rqr$rrrpÚdisplayÚ deprecatedr~r‚r"rLr„Ú ExceptionZvvvÚ_generate_redirect_shim_sourcer€)r9rZmodule_utils_relative_partsZcollection_metadataÚveZ routing_entryZ dep_or_tsZremovedrŽrrÚmsgZ source_pkgZredirect_target_pkgZ split_fqcnr)r)r*Ú_handle_redirectœsZ ÿ         ýz&ModuleUtilLocatorBase._handle_redirectcCsgS)Nr)©r9rr)r)r*r…×sz7ModuleUtilLocatorBase._get_module_utils_remainder_partscCsd | |¡¡S)NrH)r$r…rœr)r)r*Ú_get_module_utils_remainderÛsz1ModuleUtilLocatorBase._get_module_utils_remaindercCsdS)NFr)rœr)r)r*Ú _find_moduleßsz"ModuleUtilLocatorBase._find_moduleTcCsŒ|jD]6}|r| |¡rqV| |¡r*qV|s| |¡rqVq|jrRd|_d|_ndS|jrf|d}n|}d|_tjj |Žd|_ ||_ dS)NTry)r.ú.py) r†r›ržr{r‚r€r}r[r\r$rr)r9Úredirect_firstZcandidate_name_partsÚ path_partsr)r)r*Ú_locateâs"   zModuleUtilLocatorBase._locatecCs d ||¡S)Nz8 import sys import {1} as mod sys.modules['{0}'] = mod )rq)r9Zfq_source_moduleZfq_target_moduler)r)r*r˜üsûz4ModuleUtilLocatorBase._generate_redirect_shim_sourceN)FFF)T) rVrWrXr.Úpropertyrr›r…rržr¢r˜r)r)r)r*rx‚s  ; rxcs.eZdZd ‡fdd„ Zdd„Zdd„Z‡ZS) ÚLegacyModuleUtilLocatorFNcsftt|ƒ |||¡|dd…dkr2td |¡ƒ‚|ddkrJd}|g|_||_d|_|jdd dS) Nrr“©Úansiblerz=this class can only locate from ansible.module_utils, got {0}Úsix)r¦rr§zansible.builtinF)r ) r-r¤r.r—rqr†Ú _mu_pathsrƒr¢)r9rrÚmu_pathsrˆr=r)r*r.s z LegacyModuleUtilLocator.__init__cCs |dd…S)Nr“r)rœr)r)r*r…sz9LegacyModuleUtilLocator._get_module_utils_remainder_partscs˜| |¡‰tˆƒdkr|j}n‡fdd„|jDƒ}tjj d |¡|¡|_}|dur†t j   |j ¡dtjj vr†|j  d¡|_|j }ndSt|ƒ|_dS)NrPcs(g|] }tjj|gˆdd…¢RŽ‘qS)Nrz)r[r\r$©r‰Úp©Zrel_name_partsr)r*r‹"rŒz8LegacyModuleUtilLocator._find_module..rHú /__init__.pyFT)r…r„r¨Ú importlibÚ machineryÚ PathFinderÚ find_specr$Ú_infor[r\ÚsplitextÚoriginÚSOURCE_SUFFIXESrTr‚rcr€)r9rÚpathsÚinfor\r)r¬r*ržs   ÿ" z$LegacyModuleUtilLocator._find_module)FNF)rVrWrXr.r…ržrYr)r)r=r*r¤sr¤cs.eZdZd‡fdd„ Zdd„Zdd„Z‡ZS) ÚCollectionModuleUtilLocatorFcs|tt|ƒ ||||¡|ddkr2td |¡ƒ‚n*t|ƒdkr\|dd…dkr\td |¡ƒ‚d  |d d…¡|_| ¡dS) Nrr‘zMCollectionModuleUtilLocator can only locate from ansible_collections, got {0}ér’é)ZpluginsrzoCollectionModuleUtilLocator can only locate below ansible_collections.(ns).(coll).plugins.module_utils, got {0}rHrP) r-r¸r.r—rqr„r$rƒr¢r‡r=r)r*r.2s ÿz$CollectionModuleUtilLocator.__init__cCsÊt|ƒdkrd|_d|_dSd |dd…¡}tjj|dd…Ž}d}zt |ttj |d¡ƒ¡}Wnt yvYn0|durˆd|_n,zt |t|dƒ¡}Wnt y²Yn0|durÀd S||_dS) Nr¹ryTrHrr’z __init__.pyrŸF) r„r€r‚r$r[r\ÚpkgutilÚget_datarÚ ImportError)r9rZcollection_pkg_nameZresource_base_pathÚsrcr)r)r*rž?s*   z(CollectionModuleUtilLocator._find_modulecCs |dd…S)Nrºr)rœr)r)r*r…esz=CollectionModuleUtilLocator._get_module_utils_remainder_parts)FFF)rVrWrXr.ržr…rYr)r)r=r*r¸1s &r¸c s²dttƒdttƒddfddœ‰dd„tjd d Dƒ}| t¡zt|d d tj ƒ}Wn:t t fy”}zt d ||j fƒ‚WYd}~n d}~00t||ƒ‰‡fdd„ˆjDƒ}| tdd d d d¡|rh| ¡| d¡\}} } } |ˆvrôqÊ|dd…dkrt|| || d} n2|ddkr8t|| | | d} nt d|g¡qÊ| jsp| rZqÊd || j¡} t | ƒ‚| jˆvr~qÊzt| jd d tj ƒ}Wn>t t fyÒ}z t d | j|j fƒ‚WYd}~n d}~00td | j¡|| jƒ‰| ‡‡fdd„ˆjDƒ¡| j| jfˆ| j<g}| jdd…D]:}| |¡t |ƒ}|ˆvr*| t|d | j!| d¡q*qʈD]@}ˆ|d}| "|ˆ|d¡t#|dd }t $d!|¡qldS)"aó Using ModuleDepFinder, make sure we have all of the module_utils files that the module and its module_utils files needs. (no longer actually recursive) :arg name: Name of the python module we're examining :arg module_fqn: Fully qualified name of the python module we're scanning :arg module_data: string Python code of the module we're scanning :arg zf: An open :python:class:`zipfile.ZipFile` object that holds the Ansible module payload which we're assembling sUfrom pkgutil import extend_path __path__=extend_path(__path__,__name__) __version__="s" __author__="s" zansible/__init__.py)sHfrom pkgutil import extend_path __path__=extend_path(__path__,__name__) z ansible/module_utils/__init__.py))r¦r¥cSsg|]}tj |¡r|‘qSr))r[r\Úisdirrªr)r)r*r‹†rŒz$recursive_finder..F)Úsubdirsz ÚexeczUnable to import %s due to %sNcs"g|]}t|dd|ˆjvd‘qS)TF©r©rr2©r‰Úm)Úfinderr)r*r‹“rŒ)r¦rZbasicrÂrr“r¥)rr©rˆr‘)rrˆrz=ModuleDepFinder improperly found a non-module_utils import %szFCould not find imported module support code for {0}. Looked for ({1})rHc3s,|]$}|ˆvrt|dd|ˆjvdVqdS)TFrÂNrÃrÄ©rÆZpy_module_cacher)r*Ú Âs ÿz#recursive_finder..rzrPÚsurrogate_or_strict©ÚerrorszIncluding module_utils file %s)%rr r rZ _get_pathsr#Ú_MODULE_UTILS_PATHÚcompiler@Z PyCF_ONLY_ASTÚ SyntaxErrorÚIndentationErrorr ršr,r1rÚsortÚpopr¤r¸r•Úwarningr}rqrrr€r$r‚ÚextendrrKr~ÚwritestrrZvvvvv)rJr3Ú module_dataÚzfZmodule_utils_pathsr:ÚeZmodules_to_processZpy_module_namerrˆrZ module_inforšZaccumulated_pkg_nameÚpkgZnormalized_nameZpy_module_file_nameZmu_filer)rÇr*Úrecursive_finderis„þýýýûù  ( ÿÿÿ *ÿ    rÙcCsDttgd¢ƒttddƒƒtdgƒBƒ}|dd…}t| d|¡ƒS)N)ééé é é é éé ééi)Ú bytearrayr0ÚrangeÚboolÚ translate)Ú b_module_dataZ textcharsÚstartr)r)r*Ú _is_binaryØs( rêcCsXd}t |¡}|st |¡}|rL| d¡}d|vr:tdƒ‚d | d¡¡}ntdƒ‚|S)ap Get the fully qualified name for an ansible module based on its pathname remote_module_fqn is the fully qualified name. Like ansible.modules.system.ping Or ansible_collections.Namespace.Collection_name.plugins.modules.ping .. warning:: This function is for ansible modules only. It won't work for other things (non-module plugins, etc) Nr\rHz7Module name (or path) was not a valid python identifierú/z1Unable to determine module's fully qualified name)ÚCORE_LIBRARY_PATH_REÚsearchÚCOLLECTION_PATH_REÚgroupr”r$rL)Ú module_pathÚremote_module_fqnÚmatchr\r)r)r*Ú_get_ansible_module_fqnÞs    róc Cs| d¡}d |¡d}| ||¡|ddkrj> ?¡}(| .t@tAt|||||tB|(jC|(jD|(jE|(jF|(jG|(jH|'|$d7ƒ¡| +¡}nÆ|dkrd8}tI J|||| ||| | | | |||¡ }n”|d kr$t@tj|tddƒ})t@t|)ƒƒ}*| tKt@ttLƒƒ¡}| tM|*¡}| tNt@d9 tjO¡ƒ¡}| t|)¡}d:t@| ;d;tjP¡d,d-}+| d<|+¡}|||fS)=z– Given the source of the module, convert it to a Jinja2 template to insert module code and return whether it's a new or old style module. ÚoldÚbinaryÚnewrds(from ansible.module_utils.basic import *Z powershells,#Requires -Module Ansible.ModuleUtils.Legacys#Requires -Modules#Requires -Versions#AnsibleRequires -OSVersions#AnsibleRequires -Powershells#AnsibleRequires -CSharpUtilZjsonargss WANT_JSONÚnon_native_want_jsonN)rørûrùz)ANSIBALLZ: Could not determine module FQNzansible.modules.%s)ZANSIBLE_MODULE_ARGST)ÚclsZ vault_to_textzDUnable to pass options to module, they must be JSON serializable: %szOBad module compression string specified: %s. Using ZIP_STORED (no compression)Zansiballz_cachez%s-%sz"ANSIBALLZ: using cached module: %srZzANSIBALLZ: Using lock for %sz$ANSIBALLZ: Using generic lock for %szANSIBALLZ: Acquiring lockzANSIBALLZ: Lock acquired: %szANSIBALLZ: Creating moduleÚw)ÚmodeÚ compressionz&ANSIBALLZ: Writing module into payloadzANSIBALLZ: Writing modulez-partÚwbzANSIBALLZ: Renaming modulezANSIBALLZ: Done creating modulez$ANSIBALLZ: Reading module after lockzvA different worker process failed to create module file. Look at traceback for that process for debugging information.rÉrÊz/usr/bin/python©ruZPYTHON_MODULE_RLIMIT_NOFILEre)Ú rlimit_nofileryZ_ANSIBLE_COVERAGE_CONFIGZ_ANSIBLE_COVERAGE_OUTPUT)Úcoverage_configÚcoverage_output)ÚzipdataZansible_moduler3ÚparamsrvZcodingÚyearÚmonthÚdayÚhourÚminuteÚsecondÚcoverageÚrlimitz #!powershellú,ssyslog.Zansible_syslog_facilityssyslog.LOG_USER)QrêÚREPLACERÚreplaceÚNEW_STYLE_PYTHON_MODULE_REríÚREPLACER_WINDOWSÚreÚ IGNORECASEÚREPLACER_JSONARGSrrór”r•ÚdebugÚdictÚreprÚjsonÚdumpsrÚ TypeErrorr rÚgetattrÚzipfileÚAttributeErrorrÒÚ ZIP_STOREDr[r\r$rlZDEFAULT_LOCAL_TMPr]r_r`rÚidÚZipFilerÙr÷ÚcloseÚbase64Z b64encodeÚgetvalueÚmakedirsÚOSErrorÚwriteÚrenameÚIOErrorrÚ_extract_interpreterrwrmrnrAÚintroÚANSIBALLZ_RLIMIT_TEMPLATEÚenvironrpÚANSIBALLZ_COVERAGE_TEMPLATEÚ!ANSIBALLZ_COVERAGE_CHECK_TEMPLATEÚdatetimeZutcnowrÚACTIVE_ANSIBALLZ_TEMPLATEÚENCODING_STRINGrrr r r r Ú ps_manifestZ_create_powershell_wrapperÚREPLACER_VERSIONr ÚREPLACER_COMPLEXÚREPLACER_SELINUXZDEFAULT_SELINUX_SPECIAL_FSZDEFAULT_SYSLOG_FACILITY),Ú module_namerèrðÚ module_argsrsrtÚmodule_compressionÚ async_timeoutÚbecomeÚ become_methodÚ become_userÚbecome_passwordÚ become_flagsÚ environmentruZmodule_substyleÚ module_stylervÚoutputrñrZpython_repred_paramsr×Zcompression_methodZ lookup_pathZcached_module_filenamerrÕÚlockZ zipoutputrÖÚfZ o_interpreterZo_argsrrrrrrr ZnowZmodule_args_jsonZpython_repred_argsZfacilityr)r)r*Ú_find_module_utilss.  ÿþýü     &  ,        * *   ,    ÿ   þ   ò    ý     rFcCsrd}g}| dd¡}|d d¡rj|d ¡}t t|dd…dd¡}d d „|Dƒ}|d}|dd…}||fS) z– Used to extract shebang expression from binary module data and return a text string with the shebang, or None if no shebang is detected. Nó rPrs#!r“rÉrÊcSsg|]}t|dd‘qS)rÉrÊ)r)r‰Úar)r)r*r‹#rŒz(_extract_interpreter..)rLr"r!Úshlexr)rèrrr;Úb_linesZ b_shebangZ cli_splitr)r)r*r+s   r+r cCs(|dur in|}| durin| } t|dƒ}| ¡}Wdƒn1sH0Yt||||||||||| | | | | d\}}}|dkr˜||t|ddfS|durt|ƒ\}}|durt||||| d\}}| dd ¡}||krôt|d dd |d <tj   |¡  d ¡r|  d t ¡d |¡}|||fS)a Used to insert chunks of code into modules before transfer rather than doing regular python imports. This allows for more efficient transfer in a non-bootstrapping scenario by not moving extra files over the wire and also takes care of embedding arguments in the transferred modules. This version is done in such a way that local imports can still be used in the module code, so IDEs don't have to be aware of what is going on. Example: from ansible.module_utils.basic import * ... will result in the insertion of basic.py into the module from the module_utils/ directory in the source tree. For powershell, this code effectively no-ops, as the exec wrapper requires access to a number of properties not available here. NrZ)r;r<r=r>r?r@rArurùZpassthru)Ú nonstringrrGrPrÉ)rËrKrrd)r_r`rFrr+rwrLrr[r\rjr"ÚinsertÚb_ENCODING_STRINGr$)r8rðr9rtrsr:r;r<r=r>r?r@rArurErèrBrvrrr;Znew_interpreterrJr)r)r*Ú modify_module*s, &ý       rNc Csô|r|d}n|}|dur0d}tj||dd|durNd}tj|dg}n | |g¡}i} i} t|tƒr€|D]} |  | ¡qp| | ¡} | D]@} |  d¡rŽ|   d¡d} | |vrŽ|  |  d| ¡pÆi  ¡¡qŽ|  |  |i¡  ¡¡|  |¡| S) NrzzÁFinding module_defaults for the action %s. The caller passed a list of redirected action names, which is deprecated. The task's resolved action should be provided as the first argument instead.z2.16)ÚversionzˆFinding module_defaults for action %s. The caller has not passed the action_groups, so any that may include this action will be ignored.)ršzgroup/zgroup/%s) r•r–rÒrprArBÚupdateror"rLÚcopy) Úactionr;ÚdefaultsrtZredirected_namesZ action_groupsZresolved_action_nameršZ group_namesZtmp_argsZmodule_defaultsÚdefaultZ group_namer)r)r*Úget_action_args_with_defaultsds6 ÿÿ       rU)F) Nr rFNNNNNF)NN)aZ __future__rrrÚtypeZ __metaclass__r@r$r1rr[rIrrr»rrrÚiorZansible.releaser r r¦r rlZansible.errorsr Z&ansible.executor.interpreter_discoveryr Zansible.executor.powershellrr4Z ansible.module_utils.common.jsonrZ+ansible.module_utils.common.text.convertersrrrZansible.plugins.loaderrZ2ansible.utils.collection_loader._collection_finderrrZansible.executorrZansible.utils.displayrÚ collectionsrÚimportlib.utilr®Úimportlib.machineryr•rrr5r6rrr7r3rMr\r$ÚdirnameÚ__file__rÌZANSIBALLZ_TEMPLATEr/r0r-r+ZDEFAULT_KEEP_REMOTE_FILESr2Z site_packagesrÍÚescaperìrîrZ NodeVisitorr,rcrKrwrxr¤r¸rÙrêrór÷rFr+rNrUr)r)r)r*Ús’            þ  9*8o!ÿ yÿ :