U
    Adx!                  
   @   s  U d Z ddlZddlZddlZddlZddlmZ ddlmZ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mZ dd
lmZmZ ddlmZ ddlmZmZ ddlmZmZ dddeegdgedededgdZ ee!d< ee Z e	e"Z#dZ$G dd dej%Z&G dd de&Z'G dd de&Z(e)eeee*dddd Z+e,d!d"d#Z-e,e,d$d%d&Z.e&e,d'd(d)Z/e,e&d*d+d,Z0e,e&d*d-d.Z1dS )/z9ansible enables running on first boot either ansible-pull    N)deepcopy)Logger	getLogger)dedent)Optional)Cloud)Config)
MetaSchemaget_meta_doc)ALL_DISTROSDistro)PER_INSTANCE)subpwhich)Versionget_cfg_by_pathZ
cc_ansibleZAnsiblezConfigure ansible for instanceansiblea          This module provides ``ansible`` integration for
        augmenting cloud-init's configuration of the local
        node.


        This module installs ansible during boot and
        then uses ``ansible-pull`` to run the playbook
        repository at the remote URL.
        z            ansible:
              install_method: distro
              pull:
                url: "https://github.com/holmanb/vmboot.git"
                playbook_name: ubuntu.yml
            z            ansible:
              package_name: ansible-core
              install_method: pip
              pull:
                url: "https://github.com/holmanb/vmboot.git"
                playbook_name: ubuntu.yml
            )idnametitleZ	frequencyZdistrosZactivate_by_schema_keysZdescriptionZexamplesmetaansible_configc                   @   sz   e Zd ZedddZee dddZedddZ	d	d
 Z
edddZdd Zejdd ZejedddZdS )AnsiblePull)distroc                 C   s>   dg| _ ddg| _|| _tj| _d | _| jdd| jd< d S )Nzansible-pullz	--versionHOMEz/root)cmd_pullcmd_versionr   osenvironenvrun_userget)selfr    r#   =/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py__init__C   s    
zAnsiblePull.__init__returnc                 C   sF   |  | j\}}| d}td|}|rB|d}t|S d S )Nr   z	([\d\.]+))	do_asr   
splitlinespopresearchgroupr   Zfrom_str)r"   stdout_Z
first_lineZmatchesversionr#   r#   r$   get_versionN   s    

zAnsiblePull.get_versionc                 G   s   |  | j|\}}|S N)r(   r   )r"   argsr.   r/   r#   r#   r$   pullW   s    zAnsiblePull.pullc                 C   s   |   stdd S )Nz!command: ansible is not installed)is_installed
ValueErrorr"   r#   r#   r$   
check_deps[   s    zAnsiblePull.check_deps)commandc                 K   s(   | j s| j|f|S | jj|| j f|S r2   )r    r   r   r(   r"   r9   kwargsr#   r#   r$   r(   _   s    zAnsiblePull.do_asc                 K   s   t |fd| ji|S )Nr   )r   r   r:   r#   r#   r$   r   d   s    zAnsiblePull.subpc                 C   s   d S r2   r#   r7   r#   r#   r$   r5   g   s    zAnsiblePull.is_installedpkg_namec                 C   s   d S r2   r#   r"   r=   r#   r#   r$   installk   s    zAnsiblePull.installN)__name__
__module____qualname__r   r%   r   r   r1   strr4   r8   listr(   r   abcabstractmethodr5   r?   r#   r#   r#   r$   r   B   s   	
r   c                       sD   e Zd Zeee d fddZedddZeddd	Z	  Z
S )
AnsiblePullPip)r   userc                    sf   t  | || _| tjddg\}}| d}| jd}|rXd||g| jd< n
|| jd< d S )Nz-cz('import site; print(site.getuserbase())'z/bin/PATH:)	superr%   r    r(   sys
executabler   r!   join)r"   r   rH   	user_baser/   Zansible_pathZold_path	__class__r#   r$   r%   q   s    

zAnsiblePullPip.__init__r<   c                 C   sz   |   svzddl}W n$ tk
r8   | j| jj Y nX tjdddg}| jrX|	d | 
|d | 
||f dS )	zishould cloud-init grow an interface for non-distro package
        managers? this seems reusable
        r   N-mpipr?   z--user	--upgrade)rT   rS   )r5   rS   ImportErrorr   install_packagesZpip_package_namerL   rM   r    appendr(   )r"   r=   rS   cmdr#   r#   r$   r?      s    
zAnsiblePullPip.installr&   c                 C   s    |  tjdddg\}}d|kS )NrR   rS   rD   r   )r(   rL   rM   )r"   r.   r/   r#   r#   r$   r5      s    zAnsiblePullPip.is_installed)r@   rA   rB   r   r   rC   r%   r?   boolr5   __classcell__r#   r#   rP   r$   rG   p   s   rG   c                   @   s(   e Zd ZedddZedddZdS )AnsiblePullDistror<   c                 C   s   |   s| j| d S r2   )r5   r   rV   r>   r#   r#   r$   r?      s    zAnsiblePullDistro.installr&   c                 C   s   t tdS )Nr   )rY   r   r7   r#   r#   r$   r5      s    zAnsiblePullDistro.is_installedN)r@   rA   rB   rC   r?   rY   r5   r#   r#   r#   r$   r[      s   r[   )r   cfgcloudlogr3   r'   c                 C   s   | di }| d}| d}| d}| d}	| d}
| dd}|rt| |j}|d	krpt||}nt|}|| |  | d
d}|r||jt< |	rt	|	| |
rt
|t|
 |rt|| d S )Nr   r    install_methodsetup_controllerZgalaxyr4   package_name rS   r   )r!   validate_configr   rG   r[   r?   r8   r   CFG_OVERRIDEansible_galaxyrun_ansible_pullr   ansible_controller)r   r\   r]   r^   r3   Zansible_cfgZansible_userr_   r`   Z
galaxy_cfgZpull_cfgra   r   r   r   r#   r#   r$   handle   s0    







rh   r\   c                 C   s   d}|D ]"}t | |std| d|  q| dr^dD ]"}t | |s:td| d|  q:| d}|rt|d|dgstd	| | d
 }|dkrtdd S )N)r_   ra   zMissing required key 'z' from r4   )zpull/urlzpull/playbook_namer`   repositoriesrun_ansiblezMissing required key from r_   )rS   r   z Invalid install method {install})r   r6   r!   any)r\   Zrequired_keyskeyZcontroller_cfgr?   r#   r#   r$   rc      s&    



rc   )r\   r'   c                 C   s   dd |   D S )zremove boolean false valuesc                 S   s&   i | ]\}}|d k	r| dd|qS )Fr/   -)replace.0rm   valuer#   r#   r$   
<dictcomp>   s   
 zfilter_args.<locals>.<dictcomp>)itemsri   r#   r#   r$   filter_args   s    ru   )r4   r\   c                 C   s   | d}|  }|s"td n<|tdddk r^|dr^td|j d|j d|j	 d	| j
d
d t| D |f }|rtj|  d S )Nplaybook_namezCannot parse ansible version      r   ZdiffzAnsible version .z%doesn't support --diff flag, exiting.c                 S   s2   g | ]*\}}|d k	r$d| d| nd| qS )T--=r#   rp   r#   r#   r$   
<listcomp>   s   z$run_ansible_pull.<locals>.<listcomp>)r*   r1   LOGwarningr   r!   r6   majorminorZpatchr4   ru   rt   rL   r.   write)r4   r\   rv   vr.   r#   r#   r$   rf      s"    


rf   )r\   r   c                 C   s4   |  dg }|std|  |D ]}|| q d S )NactionszInvalid config: %s)r!   r}   r~   r(   )r\   r   r   r9   r#   r#   r$   re     s
    re   c                 C   s   |  dg D ]}|dd|d |d g q|  dg D ]D}|d}|d}d	|fd
d t| D }|j||d q8d S )Nrj   ZgitZclonesourcepathrk   playbook_dirrv   zansible-playbookc                 S   s    g | ]\}}d | d| qS )rz   r{   r#   rp   r#   r#   r$   r|     s     z&ansible_controller.<locals>.<listcomp>)cwd)r!   r(   r*   ru   rt   )r\   r   Z
repositoryr3   r   rv   r9   r#   r#   r$   rg     s    

rg   )2__doc__rE   r   r+   rL   copyr   Zloggingr   r   textwrapr   typingr   Zcloudinit.cloudr   Zcloudinit.configr   Zcloudinit.config.schemar	   r
   Zcloudinit.distrosr   r   Zcloudinit.settingsr   Zcloudinit.subpr   r   Zcloudinit.utilr   r   r   __annotations__r@   r}   rd   ABCr   rG   r[   rC   rD   rh   dictrc   ru   rf   re   rg   r#   r#   r#   r$   <module>   sd   	*.%
    '		