U
    Ld "                  
   @   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 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)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,Z/e+e%d*d-d.Z0dS )/z9ansible enables running on first boot either ansible-pull    N)deepcopy)	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:
              package_name: ansible-core
              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__D   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_versionO   s    

zAnsiblePull.get_versionc                 G   s   |  | j|\}}|S N)r'   r   )r!   argsr-   r.   r"   r"   r#   pullX   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 r1   )r   r   r   r'   r!   r8   kwargsr"   r"   r#   r'   `   s    zAnsiblePull.do_asc                 K   s   t |fd| ji|S )Nr   )r   r   r9   r"   r"   r#   r   e   s    zAnsiblePull.subpc                 C   s   d S r1   r"   r6   r"   r"   r#   r4   h   s    zAnsiblePull.is_installedpkg_namec                 C   s   d S r1   r"   r!   r<   r"   r"   r#   installl   s    zAnsiblePull.installN)__name__
__module____qualname__r   r$   r   r   r0   strr3   r7   listr'   r   abcabstractmethodr4   r>   r"   r"   r"   r#   r   C   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   rG   	user_baser.   Zansible_pathZold_path	__class__r"   r#   r$   r   s    

zAnsiblePullPip.__init__r;   c                 C   s|   |   sxzddl}W n$ tk
r8   | j| jj Y nX tjddddg}| jrZ|	d | 
|d	 | 
||f dS )
zishould cloud-init grow an interface for non-distro package
        managers? this seems reusable
        r   N-mpipr>   z--break-system-packagesz--user	--upgrade)rS   rR   )r4   rR   ImportErrorr   install_packagesZpip_package_namerK   rL   r   appendr'   )r!   r<   rR   cmdr"   r"   r#   r>      s    
zAnsiblePullPip.installr%   c                 C   s    |  tjdddg\}}d|kS )NrQ   rR   rC   r   )r'   rK   rL   )r!   r-   r.   r"   r"   r#   r4      s    zAnsiblePullPip.is_installed)r?   r@   rA   r   r   rB   r$   r>   boolr4   __classcell__r"   r"   rO   r#   rF   q   s   rF   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 r1   )r4   r   rU   r=   r"   r"   r#   r>      s    zAnsiblePullDistro.installr%   c                 C   s   t tdS )Nr   )rX   r   r6   r"   r"   r#   r4      s    zAnsiblePullDistro.is_installedN)r?   r@   rA   rB   r>   rX   r4   r"   r"   r"   r#   rZ      s   rZ   )r   cfgcloudr2   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galaxyr3   package_name rR   r   )r    validate_configr   rF   rZ   r>   r7   r   CFG_OVERRIDEansible_galaxyrun_ansible_pullr   ansible_controller)r   r[   r\   r2   Zansible_cfgZansible_userr]   r^   Z
galaxy_cfgZpull_cfgr_   r   r   r   r"   r"   r#   handle   s0    







rf   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]   r_   zMissing required key 'z' from r3   )zpull/urlzpull/playbook_namer^   repositoriesrun_ansiblezMissing required key from r]   )rR   r   z Invalid install method {install})r   r5   r    any)r[   Zrequired_keyskeyZcontroller_cfgr>   r"   r"   r#   ra      s&    



ra   )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.0rk   valuer"   r"   r#   
<dictcomp>   s   
 zfilter_args.<locals>.<dictcomp>)itemsrg   r"   r"   r#   filter_args   s    rs   )r3   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"   rn   r"   r"   r#   
<listcomp>   s   z$run_ansible_pull.<locals>.<listcomp>)r)   r0   LOGwarningr   r    r5   majorminorZpatchr3   rs   rr   rK   r-   write)r3   r[   rt   vr-   r"   r"   r#   rd      s"    


rd   )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   r8   r"   r"   r#   rc     s
    rc   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 )Nrh   ZgitZclonesourcepathri   playbook_dirrt   zansible-playbookc                 S   s    g | ]\}}d | d| qS )rx   ry   r"   rn   r"   r"   r#   rz     s     z&ansible_controller.<locals>.<listcomp>)cwd)r    r'   r)   rs   rr   )r[   r   Z
repositoryr2   r   rt   r8   r"   r"   r#   re     s    

re   )1__doc__rD   r   r*   rK   copyr   Zloggingr   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{   rb   ABCr   rF   rZ   rB   rC   rf   dictra   rs   rd   rc   re   r"   r"   r"   r#   <module>   sX   
+.+	%		