a )g<@@sddlmZmZmZeZddlZddlZddlZddl Z ddl m Z ddl mZddlmZddlmZmZddlmZddlmZdd lmZmZdd lmZeZd d gZd Z dd Z!Gdd d eZ"Gddde"Z#dS))absolute_importdivisionprint_functionN)abstractmethodwraps) constants)to_bytesto_text) AnsiblePlugin)Display)connection_loaderget_shell_plugin) unfrackpathConnectionBaseensure_connecticstfdd}|S)Ncs$|js||g|Ri|SN) _connected_connect)selfargskwargsfuncG/usr/lib/python3.9/site-packages/ansible/plugins/connection/__init__.pywrapped szensure_connect..wrappedr)rrrrrrscseZdZdZdZdZdZdZdZdZ dZ dZ dZ d$fdd Z dd Zed d Zed d ZeddZeeddZeddZeed%ddZeeddZeeddZeddZddZddZd d!Zd"d#ZZ S)&rz> A base class for connections to contain common code. FT)Ncstt|t|ds||_t|ds.||_t|ds>t|_t|dsNd|_d|_ d|_ d|_d|_ ||_ |j s|j r~|j n t|dd}t||jjd|_ d|_dS)N _play_context _new_stdin_displayrFZ _shell_type) shell_type executable)superr__init__hasattrrrdisplayr rZ success_keyprompt _socket_path_shellshellgetattrrr"become)r play_context new_stdinr*rrr! __class__rrr$>s$    zConnectionBase.__init__cCs ||_dSr)r,)rpluginrrrset_become_plugin]sz ConnectionBase.set_become_plugincCs|jS)zYRead-only property holding whether the connection to the remote host is active or closed.)rrrrr connected`szConnectionBase.connectedcCs|jS)zJRead-only property holding the connection socket path for this remote host)r(r3rrr socket_patheszConnectionBase.socket_pathcCsddt|DS)z Takes a string like '-o Foo=1 -o Bar="foo bar"' and returns a list ['-o', 'Foo=1', '-o', 'Bar=foo bar'] that can be added to the argument list. The list will not contain any empty elements. cSs g|]}|rt|qSr)stripr ).0xrrr rz2ConnectionBase._split_ssh_args..)shlexsplit)Z argstringrrr_split_ssh_argsjszConnectionBase._split_ssh_argscCsdS)z@String used to identify this Connection class from other classesNrr3rrr transporttszConnectionBase.transportcCsdS)z/Connect to the host we've been initialized withNrr3rrrrzszConnectionBase._connectcCsdS)atRun a command on the remote host. :arg cmd: byte string containing the command :kwarg in_data: If set, this data is passed to the command's stdin. This is used to implement pipelining. Currently not all connection plugins implement pipelining. :kwarg sudoable: Tell the connection plugin if we're executing a command via a privilege escalation mechanism. This may affect how the connection plugin returns data. Note that not all connections can handle privilege escalation. :returns: a tuple of (return code, stdout, stderr) The return code is an int while stdout and stderr are both byte strings. When a command is executed, it goes through multiple commands to get there. It looks approximately like this:: [LocalShell] ConnectionCommand [UsersLoginShell (*)] ANSIBLE_SHELL_EXECUTABLE [(BecomeCommand ANSIBLE_SHELL_EXECUTABLE)] Command :LocalShell: Is optional. It is run locally to invoke the ``Connection Command``. In most instances, the ``ConnectionCommand`` can be invoked directly instead. The ssh connection plugin which can have values that need expanding locally specified via ssh_args is the sole known exception to this. Shell metacharacters in the command itself should be processed on the remote machine, not on the local machine so no shell is needed on the local machine. (Example, ``/bin/sh``) :ConnectionCommand: This is the command that connects us to the remote machine to run the rest of the command. ``ansible_user``, ``ansible_ssh_host`` and so forth are fed to this piece of the command to connect to the correct host (Examples ``ssh``, ``chroot``) :UsersLoginShell: This shell may or may not be created depending on the ConnectionCommand used by the connection plugin. This is the shell that the ``ansible_user`` has configured as their login shell. In traditional UNIX parlance, this is the last field of a user's ``/etc/passwd`` entry We do not specifically try to run the ``UsersLoginShell`` when we connect. Instead it is implicit in the actions that the ``ConnectionCommand`` takes when it connects to a remote machine. ``ansible_shell_type`` may be set to inform ansible of differences in how the ``UsersLoginShell`` handles things like quoting if a shell has different semantics than the Bourne shell. :ANSIBLE_SHELL_EXECUTABLE: This is the shell set via the inventory var ``ansible_shell_executable`` or via ``constants.DEFAULT_EXECUTABLE`` if the inventory var is not set. We explicitly invoke this shell so that we have predictable quoting rules at this point. ``ANSIBLE_SHELL_EXECUTABLE`` is only settable by the user because some sudo setups may only allow invoking a specific shell. (For instance, ``/bin/bash`` may be allowed but ``/bin/sh``, our default, may not). We invoke this twice, once after the ``ConnectionCommand`` and once after the ``BecomeCommand``. After the ConnectionCommand, this is run by the ``UsersLoginShell``. After the ``BecomeCommand`` we specify that the ``ANSIBLE_SHELL_EXECUTABLE`` is being invoked directly. :BecomeComand ANSIBLE_SHELL_EXECUTABLE: Is the command that performs privilege escalation. Setting this up is performed by the action plugin prior to running ``exec_command``. So we just get passed :param:`cmd` which has the BecomeCommand already added. (Examples: sudo, su) If we have a BecomeCommand then we will invoke a ANSIBLE_SHELL_EXECUTABLE shell inside of it so that we have a consistent view of quoting. :Command: Is the command we're actually trying to run remotely. (Examples: mkdir -p $HOME/.ansible, python $HOME/.ansible/tmp-script-file) NrrcmdZin_dataZsudoablerrr exec_command~sBzConnectionBase.exec_commandcCsdS)$Transfer a file from local to remoteNrrZin_pathZout_pathrrrput_fileszConnectionBase.put_filecCsdS)zlFetch a file from remote to local; callers are expected to have pre-created the directory chain for out_pathNrrCrrr fetch_fileszConnectionBase.fetch_filecCsdS)zTerminate the connectionNrr3rrrcloseszConnectionBase.closecCsV|jj}tjdt|f|jjdt|tj tjdt|f|jjddS)Nz)CONNECTION: pid %d waiting for lock on %dhostz&CONNECTION: pid %d acquired lock on %d) rconnection_lockfdr&vvvvosgetpid remote_addrfcntllockfZLOCK_EXrfrrrconnection_lockszConnectionBase.connection_lockcCs8|jj}t|tjtjdt|f|jj ddS)Nz&CONNECTION: pid %d released lock on %drG) rrIrNrOZLOCK_UNr&rJrKrLrMrPrrrconnection_unlocksz ConnectionBase.connection_unlockcCstddS)Nz,Reset is not implemented for this connection)r&warningr3rrrresetszConnectionBase.resetc CstjD]}d}||vrqnd|vsd|vr.qn|dkr>|j}n|dkrP|jj}nxtjd|j|}|rv||d}nRd|vrtjD]>\}}||vrzt |j |}WqWqt yYqYq0q|durt d |||||<qdS) z Adds 'magic' variables relating to connections to the variable dictionary provided. In case users need to access from the play, this is a legacy from runner. NpasswordpasswdZansible_connectionZansible_shell_type connectionrr,zSet connection var {0} to {1})CZCOMMON_CONNECTION_VARSZ _load_namer)ZconfigZget_plugin_options_from_var get_optionZMAGIC_VARIABLE_MAPPINGitemsr+rAttributeErrorr&debugformat)rZ variablesZvarnamevalueoptionsZpropZvar_listrrr update_varss0      zConnectionBase.update_vars)N)NT)!__name__ __module__ __qualname____doc__Zhas_pipeliningZhas_native_asyncZalways_pipeline_modulesZhas_ttyZ!module_implementation_preferencesZallow_executableZsupports_persistenceforce_persistenceZ default_userr$r2propertyr4r5 staticmethodr=rr>rrrArDrErFrRrSrUra __classcell__rrr/rr(sL     B   cseZdZdZdZdZfddZddZddd Zd d Z d d Z ddZ ddZ ddZ ddZdfdd ZddZddZZS)NetworkConnectionBasez5 A base class for network-style connections. Tcsttt|j||g|Ri|g|_d|_|jj|_t d|d|_ |j i|_ d|_ | d|_|dS)NFlocalz /dev/null)NNNZansible_playbook_pid)r#rjr$ _messages _conn_closedrZ network_osZ _network_osr get_local set_options _sub_pluginZ_cached_variables_ansible_playbook_pid_update_connection_state)rr-r.rrr/rrr$s    zNetworkConnectionBase.__init__cCsnz |j|WStyh|dsP|jd}|rPt||d}|durP|YStd|jj|fYn0dS)N_objz!'%s' object has no attribute '%s') __dict__KeyError startswithrqrnr+r\r0rb)rnamer1methodrrr __getattr__#s     z!NetworkConnectionBase.__getattr__NcCs|j|||Sr)rorAr?rrrrA/sz"NetworkConnectionBase.exec_commandcCs|j||fdS)a Adds a message to the queue of messages waiting to be pushed back to the controller process. :arg level: A string which can either be the name of a method in display, or 'log'. When the messages are returned to task_executor, a value of log will correspond to ``display.display(message, log_only=True)``, while another value will call ``display.[level](message)`` N)rlappend)rlevelmessagerrr queue_message2sz#NetworkConnectionBase.queue_messagecCs|jg}|_|Sr)rl)rmessagesrrr pop_messages<sz"NetworkConnectionBase.pop_messagescCs|j||S)rB)rorDrCrrrrD@szNetworkConnectionBase.put_filecCs|j||S)z!Fetch a file from remote to local)rorErCrrrrEDsz NetworkConnectionBase.fetch_filecCs0|jr |dd|j||dddS)z& Reset the connection rJz2resetting persistent connection for socket_path %sz!reset call on connection instanceN)r(rrFr3rrrrUHszNetworkConnectionBase.resetcCsd|_|jrd|_dS)NTF)rmrr3rrrrFQszNetworkConnectionBase.closecstt|j|||d|drZd|jj}ttd}|durJ|d|7}|dd||j dr|j d d krz|j dj|||dWnt yYn0dS) N) task_keys var_optionsdirectpersistent_log_messageszOPersistent connection logging is enabled for %s. This will log ALL interactionsZDEFAULT_LOG_PATHz to %srTzP%s and WILL NOT redact sensitive configuration like passwords. USE WITH CAUTION!rutypeZexternal) r#rjrprZrrMr+rYrrqrnr\)rrrrrTZlogpathr/rrrpVs     z!NetworkConnectionBase.set_optionscCsjtjddd}||jj|jj|jj|jj|j}t t j }t |t |d}t j|rfd|_||_dS)ac Reconstruct the connection socket_path and check if it exists If the socket path exists then the connection is active and set both the _socket_path value to the path and the _connected value to True. If the socket path doesn't exist, leave the socket path value to None and the _connected value to False sshT)Z class_only)Z directoryN)r rnZ_create_control_pathrrMportZ remote_userrXrrrrYZPERSISTENT_CONTROL_PATH_DIRdictrKpathexistsrr()rrZ control_pathZtmp_pathr5rrrrses     z.NetworkConnectionBase._update_connection_statecCs|dr|d|dS)Nrlog)rZr)rr~rrr _log_messages|s z#NetworkConnectionBase._log_messages)NT)NNN)rbrcrdrerfZ_remote_is_localr$r{rArrrDrErUrFrprsrrirrr/rrj s    rj)$Z __future__rrrrZ __metaclass__rNrKr;typingtabcr functoolsrZansiblerrYZansible.module_utils._textr r Zansible.pluginsr Zansible.utils.displayr Zansible.plugins.loaderr rZansible.utils.pathrr&__all__BUFSIZErrrjrrrrs(       b