a
    `                     @   s   d Z ddlmZ ddlZddlmZ ddlmZ ddlmZ ddlm	Z	 ddl
mZ dd	l
mZ dd
l
mZ ddlm	Z eeZdd Zdd Zdd Zdd Ze Zdd Zdd Zg Zdd Zdd Zdd Zdd Zdd  Z d!d" Z!d#d$ Z"dS )%z;Facilities for implementing hooks that call shell commands.    )print_functionN)List)Set)errors)util)
filesystem)misc)osc                 C   s4   t | jd t | jd t | jd t | jd dS )z#Check hook commands are executable.ZpreZpostZdeployrenewN)validate_hookpre_hook	post_hookdeploy_hook
renew_hook)config r   9/usr/lib/python3/dist-packages/certbot/_internal/hooks.pyvalidate_hooks   s    r   c                 C   s.   t | s"t|  t | s"dS tj| S )zExtract the program run by a shell command.

    :param str shell_cmd: command to be executed

    :returns: basename of command or None if the command isn't found
    :rtype: str or None

    N)r   Z
exe_exists	plug_utilZpath_surgeryr	   pathbasename)	shell_cmdr   r   r   _prog   s
    	


r   c                 C   s\   | rX|  ddd }t|sXtjd }tj|r@d||}nd|||}t|dS )zCheck that a command provided as a hook is plausibly executable.

    :raises .errors.HookCommandNotFound: if the command is not found
    N   r   PATHz3{1}-hook command {0} exists, but is not executable.z>Unable to find {2}-hook command {0} in the PATH.
(PATH is {1}))	splitr   r	   environr   existsformatr   ZHookCommandNotFound)r   Z	hook_namecmdr   msgr   r   r   r   *   s    
r   c                 C   s>   | j dkr(| jr(t| jD ]}t| q| j}|r:t| dS )a  Run pre-hooks if they exist and haven't already been run.

    When Certbot is running with the renew subcommand, this function
    runs any hooks found in the config.renewal_pre_hooks_dir (if they
    have not already been run) followed by any pre-hook in the config.
    If hooks in config.renewal_pre_hooks_dir are run and the pre-hook in
    the config is a path to one of these scripts, it is not run twice.

    :param configuration.NamespaceConfig config: Certbot settings

    r
   N)verbdirectory_hooks
list_hooksZrenewal_pre_hooks_dir_run_pre_hook_if_necessaryr   )r   hookr   r   r   r   r   <   s    
r   c                 C   s.   | t v rtd|  ntd|  t |  dS )zRun the specified pre-hook if we haven't already.

    If we've already run this exact command before, a message is logged
    saying the pre-hook was skipped.

    :param str command: pre-hook to be run

    z*Pre-hook command already run, skipping: %szpre-hookN)executed_pre_hooksloggerinfo	_run_hookaddcommandr   r   r   r$   T   s    	
r$   c                 C   sN   | j }| jdkr<| jr.t| jD ]}t| q |rJt| n|rJtd| dS )a  Run post-hooks if defined.

    This function also registers any executables found in
    config.renewal_post_hooks_dir to be run when Certbot is used with
    the renew subcommand.

    If the verb is renew, we delay executing any post-hooks until
    :func:`run_saved_post_hooks` is called. In this case, this function
    registers all hooks found in config.renewal_post_hooks_dir to be
    called followed by any post-hook in the config. If the post-hook in
    the config is a path to an executable in the post-hook directory, it
    is not scheduled to be run twice.

    :param configuration.NamespaceConfig config: Certbot settings

    r
   	post-hookN)r   r!   r"   r#   Zrenewal_post_hooks_dir_run_eventuallyr)   )r   r   r%   r   r   r   r   d   s    


r   c                 C   s   | t vrt |  dS )zRegisters a post-hook to be run eventually.

    All commands given to this function will be run exactly once in the
    order they were given when :func:`run_saved_post_hooks` is called.

    :param str command: post-hook to register to be run

    N)
post_hooksappendr+   r   r   r   r.      s    	r.   c                  C   s   t D ]} td|  qdS )zGRun any post hooks that were saved up in the course of the 'renew' verbr-   N)r/   r)   )r   r   r   r   run_saved_post_hooks   s    r1   c                 C   s   | j rt| j ||| j dS )a  Run post-issuance hook if defined.

    :param configuration.NamespaceConfig config: Certbot settings
    :param domains: domains in the obtained certificate
    :type domains: `list` of `str`
    :param str lineage_path: live directory path for the new cert

    N)r   _run_deploy_hookdry_run)r   domainslineage_pathr   r   r   r      s    	r   c                 C   sl   t  }| jr6t| jD ]}t|||| j || q| jrh| j|v rVt	d| j nt| j||| j dS )a]  Run post-renewal hooks.

    This function runs any hooks found in
    config.renewal_deploy_hooks_dir followed by any renew-hook in the
    config. If the renew-hook in the config is a path to a script in
    config.renewal_deploy_hooks_dir, it is not run twice.

    If Certbot is doing a dry run, no hooks are run and messages are
    logged saying that they were skipped.

    :param configuration.NamespaceConfig config: Certbot settings
    :param domains: domains in the obtained certificate
    :type domains: `list` of `str`
    :param str lineage_path: live directory path for the new cert

    z0Skipping deploy-hook '%s' as it was already run.N)
setr"   r#   Zrenewal_deploy_hooks_dirr2   r3   r*   r   r'   r(   )r   r4   r5   Zexecuted_dir_hooksr%   r   r   r   r      s    
r   c                 C   s<   |rt d|  dS d|tjd< |tjd< td|  dS )a  Run the specified deploy-hook (if not doing a dry run).

    If dry_run is True, command is not run and a message is logged
    saying that it was skipped. If dry_run is False, the hook is run
    after setting the appropriate environment variables.

    :param str command: command to run as a deploy-hook
    :param domains: domains in the obtained certificate
    :type domains: `list` of `str`
    :param str lineage_path: live directory path for the new cert
    :param bool dry_run: True iff Certbot is doing a dry run

    z)Dry run: skipping deploy hook command: %sN ZRENEWED_DOMAINSZRENEWED_LINEAGEzdeploy-hook)r'   Zwarningjoinr	   r   r)   )r,   r4   r5   r3   r   r   r   r2      s    
r2   c                 C   s   t j| |t d\}}|S )zRun a hook command.

    :param str cmd_name: the user facing name of the hook being run
    :param shell_cmd: shell command to execute
    :type shell_cmd: `list` of `str` or `str`

    :returns: stderr if there was any)env)r   Zexecute_commandr   Zenv_no_snap_for_external_calls)Zcmd_namer   err_r   r   r   r)      s    r)   c                    s.    fddt  D }dd |D }t|S )zList paths to all hooks found in dir_path in sorted order.

    :param str dir_path: directory to search

    :returns: `list` of `str`
    :rtype: sorted list of absolute paths to executables in dir_path

    c                 3   s   | ]}t j |V  qd S )N)r	   r   r8   ).0fdir_pathr   r   	<genexpr>       zlist_hooks.<locals>.<genexpr>c                 S   s$   g | ]}t |r|d s|qS )~)r   Zis_executableendswith)r<   r   r   r   r   
<listcomp>   rA   zlist_hooks.<locals>.<listcomp>)r	   listdirsorted)r?   ZallpathsZhooksr   r>   r   r#      s    	r#   )#__doc__Z
__future__r   ZloggingZacme.magic_typingr   r   Zcertbotr   r   Zcertbot.compatr   r   r	   Zcertbot.pluginsr   Z	getLogger__name__r'   r   r   r   r   r6   r&   r$   r   r/   r.   r1   r   r   r2   r)   r#   r   r   r   r   <module>   s4   
 