o nnh.p @sXddlmZddlZddlZddlZejdkr#eddej ddZ e dd Z e dd l mZdd l mZed Zeed krMededdlZddlZddlZddlZddlmZmZddlmZzddlmZddlmZeZWn eyZ ze!de ej"de#dWYdZ [ ndZ [ wwddlm$Z$ddl%m&Z'ddl(m)Z)m*Z*m+Z+ddl,m-Z-ddl.m/Z/ddl0m1Z1m2Z2ddl3m4Z4ddl5m6Z6ddl7m8Z8ddl9m:Z:m;Z;dd lZ>dd!l?m@Z@dd"lAmBZBdd#lCmDZDdd$lEmFZFdd%lGmHZHdd&lImJZJzddlKZKd'ZLWn eMy!d(ZLYnwGd)d*d*eZNdS)+) annotationsN) zSERROR: Ansible requires Python 3.10 or newer on the controller. Current version: %sc Csg}tjtjtjfD]$}z|}Wn tyYq wt|s.|t |ddp,d|q |r?t dd dd|DdS)zBCheck stdin/stdout/stderr to make sure they are using blocking IO.nameNz#%szbERROR: Ansible requires blocking IO on stdin/stdout/stderr. Non-blocking file handles detected: %sz, css|]}|VqdSN).0_iorr?/usr/local/lib/python3.10/dist-packages/ansible/cli/__init__.py %sz$check_blocking_io..) sysstdinstdoutstderrfileno Exceptionos get_blockingappendgetattr SystemExitjoin)handleshandlefdrrr check_blocking_ios   rc Cszttjdt\}}Wntjtfy$}ztd|d}~ww|r-|dvr3td|t }|dkrCtd|dS)zmSet the locale to the users default setting and ensure the locale and filesystem encoding are UTF-8. rzopt_helpr,rRprogrT CONFIG_FILEvconfig DEPRECATED deprecated) rYcli_collections_pathrkrr]altverr_r`rrr runs,    zCLI.runcCs(d|vrd|fS|dd}t|}|S)N@r\)splittuple)vault_idpartsretrrr split_vault_ids  zCLI.split_vault_idTcCsZ|pg}|pg}|D]}dtj|f}||q |s|s+|r+dtjdf}|||S)Nz%s@%sprompt_ask_vault_pass)rTDEFAULT_VAULT_IDENTITYr) vault_idsvault_password_filesask_vault_pass auto_prompt password_fileid_slugrrr build_vault_idss   zCLI.build_vault_idsc Csg}i}|pg}tjr|tj|r ddg|d<ddg|d<n dg|d<dg|d<tj||||d }d}} |D]} t| \} } | d vr| pJtj} t|| | d }z|Wnt yo}z t d | |fd}~wwd } || |f| |q9t d| z t| | |d}Wnt y}zt d| t|f|}WYd}~q9d}~wwz|Wnt y}zt d| t|f|}WYd}~q9d}~wwd } | r|| |fn|tj|f| |q9|r| s||S)Nz#New vault password (%(vault_id)s): z+Confirm new vault password (%(vault_id)s): promptzNew Vault password: zConfirm New Vault password: rwzVault password (%(vault_id)s): zVault password: )r|)rrw)prompt_formatsrsz'Error in vault password prompt (%s): %sTzReading vault password file: %s)filenamersloaderz*Error getting vault password file (%s): %sz-Error in vault password file loading (%s): %s)rTDEFAULT_VAULT_PASSWORD_FILErrMrrvrxrBloadr8rWrXset_vault_secretsvvvvvrCr>)rryrzr{create_new_passwordr| vault_secretsrlast_exceptionfound_vault_secret vault_id_slug vault_id_namevault_id_valuebuilt_vault_idprompted_vault_secretexcfile_vault_secretrrr setup_vault_secretss           zCLI.setup_vault_secretscCstj|d}|r t|}|S)N)r)getpassrK)rsecretrrr _get_secretBs zCLI._get_secretcCstj}d}d}d}tjrdn|d}zKd|}|dr'td}d|}n |d r2t|d }|d rFt|}|drE|dkrE|}n|d rVt|d }W||fSW||fSW||fStykY||fSw) z6 prompt for connection and become passwords if needed NrBECOME become_methodz %s password: ask_passzSSH password: z'%s password[defaults to SSH password]: connection_password_filebecome_ask_passbecome_password_file) r6rbrTAGNOSTIC_BECOME_PROMPTupperrMrget_password_from_fileEOFError)opsshpass becomepass become_promptbecome_prompt_methodrrr ask_passwordsJs8    zCLI.ask_passwordscCs|r |jdkr |jd|S)z check for conflicting options r\z.The number of processes (--forks) must be >= 1)forksrRerror)rYr runas_opts fork_optsrrr validate_conflictsis  zCLI.validate_conflictsrcCstj|j|||d|_dS)a_ Create an options parser for most ansible scripts Subclasses need to implement this method. They will usually call the base class's init_parser to create a basic version and then add their own options on top of that. An implementation will look something like this:: def init_parser(self): super(MyCLI, self).init_parser(usage="My Ansible CLI", inventory_opts=True) ansible.arguments.option_helpers.add_runas_options(self.parser) self.parser.add_option('--my-option', dest='my_option', action='store') )usagedescepilogN)recreate_base_parserrrR)rYrrrrrr init_parserrszCLI.init_parsercCs*t|dr |js dg|_t|dr1|jr1t}|jD]}|dD] }||q!qt||_t|drV|jrVt}|jD]}|dD] }||qFq?t||_t|drn|jdvrnt|drndd |j D|_ t|d r|j s|j rt |j t r|j g|_ d d |j D|_ |Stj|_ |S) a Process the command line args Subclasses need to implement this method. This method validates and transforms the command line arguments. It can be used to check whether conflicting values were given, whether filenames exist, etc. An implementation will look something like this:: def post_process_args(self, options): options = super(MyCLI, self).post_process_args(options) if options.addition and options.subtraction: raise AnsibleOptionsError('Only one of --addition and --subtraction can be specified') if isinstance(options.listofhosts, string_types): options.listofhosts = string_types.split(',') return options tagsall, skip_tagsaction)installdownloadrQcSsg|]}|dqS)/)rstrip)r pathrrr sz)CLI.post_process_args.. inventorycSs$g|]}d|vrt|ddn|qS)rF)followrI)r optrrr rs$)hasattrrsetrqaddstriplistrrrQSKIP_INVENTORY_DEFAULTSr isinstancer<rTDEFAULT_HOST_LIST)rYoptionsrtag_settagrrrr post_process_argss4      zCLI.post_process_argsc Cs|tr t|jz |j|jdd}Wnty8}z|jdkr3|jj dd|j dd}~ww| |}t |dS)aParse the command line args This method parses the command line arguments. It uses the parser stored in the self.parser attribute and saves the args and options in context.CLIARGS. Subclasses need to implement two helper methods, init_parser() and post_process_args() which are called from this function before and after parsing the arguments. r\Nrz %s)statusmessage)rHAS_ARGCOMPLETE argcomplete autocompleterR parse_argsrQrcodeexit format_helprr6_init_global_context)rYrexrrr ras    z CLI.parsec Cs|rt}nt}|d}|d}tt|D]}||dkr&d||<z t||||<Wqty9Yqwt|dkrOtt|dD]}|dqG| ||d|d|ddS)z" return full ansible version info r.rrr\r)stringfullmajorminorrevision) rer,rFrqrangelenintrrr)gitinfoansible_version_stringansible_versionansible_versionscounterrrr version_infos,       zCLI.version_infocCstjstj|dddStjr&tjdkrtj|dddSt|dStj ddtj tj d}| |j dkrBt|ddStj|dddS) z% find reasonable way to display text T) screen_onlywin32zless --version)shellrrrlessN) r risattyrWrMrNplatform pager_pipe subprocessPopenPIPE communicate returncode)textprrr pagers   z CLI.pagercCsldtjvr tjtjd<ztjtjdtjtj d}|j t |dWdSt y,YdSt y5YdSw)z pipe text through a pager rLESST)rrr)inputN)rMrN LESS_OPTSrenvironrrrr rrr=IOErrorKeyboardInterrupt)rcmdrrr rs    zCLI.pager_pipec Cstj}t}|dd}|r+||t||t_t|}|r+t d ||t_ t |d}tj}||}tj||t |d|ddd}||t||d|d  d }t||tjdd d }|||fS) NbasedirFz#running with default collection {0}ryrzr{)ryrzr{r|r flush_cache)rsourcescache)r)rrr)r6rbrArc set_basedirrDrGplaybook_pathsrHrWrXformatdefault_collectionrrTDEFAULT_VAULT_IDENTITY_LISTrMrrr;rLr) rrrrrydefault_vault_idsrrvariable_managerrrr _play_prereqss0      zCLI._play_prereqsrcCs^d}t|dkrtjr|tjvrtdd}||||}|s-|dur-td|S)NFrzpprovided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'TzSSpecified inventory, host pattern and/or --limit leaves us with no hosts to target.) r list_hostsrTLOCALHOST_WARNING LOCALHOSTrWrXsubsetr8)rr patternno_hostshostsrrr get_host_list;s    zCLI.get_host_listc Cs>t|}d}|dkrtjj}n}tj|std|t |rft dt ||g}z t j|t jt jd}WntyM}ztd||fd}~ww|\}}|jdkrctd||j|f|}n(zt|d}|}|Wnttfy}ztd ||fd}~ww|d }|std |t|S) N-z"The password file %s was not foundz!The password file %s is a script.)rrzProblem occurred when trying to run the password script %s (%s). If this is not a script, remove the executable bit from the file.rz4The password script %s returned an error (rc=%s): %srbz#Could not read password file %s: %ss z*Empty password was provided from file (%s))r=r rbufferreadrrexistsr8r@rWvvvvr>rrrOSErrorrropenrcloserrK) pwd_file b_pwd_filerrrr)rrfrrr rMsB         zCLI.get_password_from_filec Cs|durtj}zptdttj}z|jddWn%t yA}z|j t j kr7t d|t |ddfWYd}~n d}~wwtd|z dd |D}Wntymtd td t td }Yn w||}|}Wnty}z|jtjt |d dd}WYd}~nd}~wty}ztjt |d dd}WYd}~nd}~wty}ztjt |d dd}WYd}~nd}~wtytdd}YnstyR}zftjrttj}tjdt |d d|r |r2tjddkr2d }t|dr1tdt t |j!t |j!} t || kr1td| ntdd}tjdt t|dd}WYd}~nd}~wwt"|dS)Nz starting runi)modez'Failed to create the directory '%s': %ssurrogate_or_replaceerrorszCreated the '%s' directorycSsg|]}t|ddqS)surrogate_or_strictr)r>)r arrr rsz$CLI.cli_executor..zaCommand line args are not in utf-8, unable to continue. Ansible currently only understands utf-8zThe full traceback was: %sF) wrap_textr5r\zUser interrupted executioncz0Unexpected Exception, this is probably a bug: %s verbosityrorig_excz exception type: %sz original msg: %sz#to see the full traceback, use -vvvTzthe full traceback was: %s)log_only)#r argvrWdebugr1rT ANSIBLE_HOME expandusermkdirrerrnoEEXISTrXr> UnicodeErrorr traceback format_excror9rR print_helpr:r8rr DEFAULT_DEBUGboolr6rbrvvvtyper'r) clsrQ ansible_dirr exit_codeclir)have_cli_optionsr(r]rrr cli_executorwsz           zCLI.cli_executorr)NNT)NNFT)FF)rNN)F)r)__name__ __module__ __qualname____doc__rTriget_config_valuerNrrrZr0ro staticmethodrvrrrrrrrrarrrrrr classmethodr>rrrr rMvsV   $    e     <    (  )rM)O __future__rrrr rrrr, splitlinesrr+importlib.metadata#ansible.module_utils.compat.versionr-jinja2_versionr/rrr2abcr/r0pathlibr1ansibler2rTansible.utils.displayr3rWrr)printrrr6ansible.cli.argumentsr7reansible.errorsr8r9r:ansible.inventory.managerr;ansible.module_utils.sixr<+ansible.module_utils.common.text.convertersr=r>'ansible.module_utils.common.collectionsr? ansible.module_utils.common.filer@ansible.parsing.dataloaderrAansible.parsing.vaultrBrCansible.plugins.loaderrDrEansible.releaserFansible.utils.collection_loaderrG2ansible.utils.collection_loader._collection_finderrHansible.utils.pathrJansible.utils.unsafe_proxyrKansible.vars.managerrLrr ImportErrorrMrrrr s|