
¡\\Ç!  ã               @   sT  d  Z  d d l m Z d d l Z d d l Z d d l m Z m Z d d l m	 Z	 m
 Z
 d d l m Z d d l m Z d d l m Z e j 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" d# „  Z# d S)$z;Facilities for implementing hooks that call shell commands.é    )Úprint_functionN)ÚPopenÚPIPE)ÚSetÚList)Úerrors)Úutilc             C   sD   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   ú//usr/lib/python3/dist-packages/certbot/hooks.pyÚvalidate_hooks   s    r   c             C   s?   t  j |  ƒ s/ t j |  ƒ t  j |  ƒ s/ d St j j |  ƒ S)zÁExtract 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_surgeryÚosÚpathÚbasename)Ú	shell_cmdr   r   r   Ú_prog   s
    	r   c             C   s„   |  r€ |  j  d d ƒ d } t | ƒ s€ t j d } t j j | ƒ r\ d j | | ƒ } n d j | | | ƒ } t j | ƒ ‚ d S)z‹Check 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   sY   |  j  d k r< |  j r< x! t |  j ƒ D] } t | ƒ q( W|  j } | rU 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   sJ   |  t  k r t j d |  ƒ n' t j d |  ƒ t |  ƒ t  j |  ƒ d S)zÑRun 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Running pre-hook command: %sN)Úexecuted_pre_hooksÚloggerÚinfoÚ	_run_hookÚadd)Úcommandr   r   r   r$   T   s
    	
r$   c             C   s|   |  j  } |  j d k rX |  j rE x! t |  j ƒ D] } t | ƒ q1 W| rx t | ƒ n  | rx t j d | ƒ t | ƒ 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	   zRunning post-hook command: %sN)	r   r!   r"   r#   Zrenewal_post_hooks_dirÚ_run_eventuallyr'   r(   r)   )r   r   r%   r   r   r   r   e   s    		r   c             C   s   |  t  k r t  j |  ƒ d S)zúRegisters 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Úappend)r+   r   r   r   r,   ˆ   s    	r,   c              C   s/   x( t  D]  }  t j d |  ƒ t |  ƒ q Wd S)zGRun any post hooks that were saved up in the course of the 'renew' verbzRunning post-hook command: %sN)r-   r'   r(   r)   )r   r   r   r   Úrun_saved_post_hooks•   s    r/   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   sš   t  ƒ  } |  j rO x: t |  j ƒ D]) } t | | | |  j ƒ | j | ƒ q" W|  j r– |  j | k r} t j	 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_dirr0   r1   r*   r   r'   r(   )r   r2   r3   Zexecuted_dir_hooksr%   r   r   r   r   ª   s    				r   c             C   s[   | r t  j d |  ƒ d Sd j | ƒ t j d <| t j d <t  j d |  ƒ t |  ƒ 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Running deploy-hook command: %s)r'   ZwarningÚjoinr   r   r(   r)   )r+   r2   r3   r1   r   r   r   r0   Ê   s    	r0   c             C   s   t  |  ƒ \ } } | S)z:Run a hook command.

    :returns: stderr if there was any)Úexecute)r   ÚerrÚ_r   r   r   r)   ã   s    r)   c          
   C   s¹   t  |  d d d t d t d d ƒ} | j ƒ  \ } } t j j |  j d d ƒ d ƒ } | rq t j d	 | | ƒ | j	 d k r– t j
 d
 |  | j	 ƒ | r¯ t j
 d | | ƒ | | f S)zBRun a command.

    :returns: `tuple` (`str` stderr, `str` stdout)ÚshellTÚstdoutÚstderrZuniversal_newlinesNr   r   zOutput from %s:
%sz(Hook command "%s" returned error code %dzError output from %s:
%s)r   r   Zcommunicater   r   r   r   r'   r(   Ú
returncodeÚerror)r   r   Úoutr8   Zbase_cmdr   r   r   r7   ì   s    "	r7   c                s9   ‡  f d d †  t  j ˆ  ƒ Dƒ } t d d „  | Dƒ ƒ S)zÒList 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 j ˆ  | ƒ Vq d  S)N)r   r   r6   )Ú.0Úf)Údir_pathr   r   ú	<genexpr>
  s    zlist_hooks.<locals>.<genexpr>c             s   s$   |  ] } t  j | ƒ r | Vq d  S)N)r   Zis_exe)r@   r   r   r   r   rC     s    )r   ÚlistdirÚsorted)rB   Úpathsr   )rB   r   r#     s    	"r#   )$Ú__doc__Z
__future__r   Zloggingr   Ú
subprocessr   r   Zacme.magic_typingr   r   Zcertbotr   r   Zcertbot.pluginsr   Z	getLoggerÚ__name__r'   r   r   r
   r   r4   r&   r$   r   r-   r,   r/   r   r   r0   r)   r7   r#   r   r   r   r   Ú<module>   s2   	  	