U
    w7e"                  
   @   s  U d Z ddl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,Z0e,e&d*d-d.Z1d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__E   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_versionP   s    

zAnsiblePull.get_versionc                 G   s   |  | j|\}}|S N)r'   r   )r!   argsr-   r.   r"   r"   r#   pullY   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'   a   s    zAnsiblePull.do_asc                 K   s   t |fd| ji|S )Nr   )r   r   r9   r"   r"   r#   r   f   s    zAnsiblePull.subpc                 C   s   d S r1   r"   r6   r"   r"   r#   r4   i   s    zAnsiblePull.is_installedpkg_namec                 C   s   d S r1   r"   r!   r<   r"   r"   r#   installm   s    zAnsiblePull.installN)__name__
__module____qualname__r   r$   r   r   r0   strr3   r7   listr'   r   abcabstractmethodr4   r>   r"   r"   r"   r#   r   D   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$   s   s    

zAnsiblePullPip.__init__r;   c                 C   s   |   szddl}W n$ tk
r8   | j| jj Y nX tjdddg}tj	
tj	tddrn|d | jr~|d	 | |d | ||f dS )zishould cloud-init grow an interface for non-distro package
        managers? this seems reusable
        r   N-mpipr>   ZstdlibzEXTERNALLY-MANAGEDz--break-system-packagesz--user	--upgrade)rS   rR   )r4   rR   ImportErrorr   install_packagesZpip_package_namerK   rL   r   pathexistsrM   	sysconfigZget_pathappendr   r'   )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   r   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   )r[   r   r6   r"   r"   r#   r4      s    zAnsiblePullDistro.is_installedN)r?   r@   rA   rB   r>   r[   r4   r"   r"   r"   r#   r]      s   r]   )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   r]   r>   r7   r   CFG_OVERRIDEansible_galaxyrun_ansible_pullr   ansible_controller)r   r^   r_   r2   Zansible_cfgZansible_userr`   ra   Z
galaxy_cfgZpull_cfgrb   r   r   r   r"   r"   r#   handle   s0    







ri   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`   rb   zMissing required key 'z' from r3   )zpull/urlzpull/playbook_namera   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#   rd      s&    



rd   )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.0rn   valuer"   r"   r#   
<dictcomp>   s   
 zfilter_args.<locals>.<dictcomp>)itemsrj   r"   r"   r#   filter_args   s    rv   )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"   rq   r"   r"   r#   
<listcomp>  s   z$run_ansible_pull.<locals>.<listcomp>)r)   r0   LOGwarningr   r    r5   majorminorZpatchr3   rv   ru   rK   r-   write)r3   r^   rw   vr-   r"   r"   r#   rg      s"    


rg   )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#   rf     s
    rf   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 )Nrk   ZgitZclonesourcerV   rl   playbook_dirrw   zansible-playbookc                 S   s    g | ]\}}d | d| qS )r{   r|   r"   rq   r"   r"   r#   r}   !  s     z&ansible_controller.<locals>.<listcomp>)cwd)r    r'   r)   rv   ru   )r^   r   Z
repositoryr2   r   rw   r8   r"   r"   r#   rh     s    

rh   )2__doc__rD   r   r*   rK   rX   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~   re   ABCr   rF   r]   rB   rC   ri   dictrd   rv   rg   rf   rh   r"   r"   r"   r#   <module>   sZ   
+.0	%		