o
    i)                  
   @   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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 ddlmZ dd	lmZmZ dd
lmZ ddlmZ deegdgdZeed< eeZ dZ!G dd dej"Z#G dd de#Z$G dd de#Z%de&dedede'ddf
ddZ(de)fddZ*de)de)fd d!Z+d"e#de)fd#d$Z,de)de#fd%d&Z-de)de#fd'd(Z.dS ))z9ansible enables running on first boot either ansible-pull    N)deepcopy)ListOptional)	lifecyclesubp)Cloud)Config)
MetaSchema)ALL_DISTROSDistro)PER_INSTANCE)get_cfg_by_path
cc_ansibleansible)id	frequencydistrosactivate_by_schema_keysmetaansible_configc                   @   s|   e Zd ZdefddZdeej fddZde	fddZ
d	d
 ZdefddZdd Zejdd Zejde	fddZdS )AnsiblePulldistroc                 C   s<   dg| _ ddg| _|| _i | _d | _tjdd| jd< d S )Nzansible-pullz	--versionHOMEz/root)cmd_pullcmd_versionr   envrun_userosenvironget)selfr    r!   =/usr/lib/python3/dist-packages/cloudinit/config/cc_ansible.py__init__    s   
zAnsiblePull.__init__returnc                 C   sH   |  | j\}}| d}td|}|r"|d}tj	|S d S )Nr   z	([\d\.]+))
do_asr   
splitlinespopresearchgroupr   Versionfrom_str)r    stdout_
first_linematchesversionr!   r!   r"   get_version+   s   
zAnsiblePull.get_versionc                 G   s   |  g | j|\}}|S N)r%   r   )r    argsr-   r.   r!   r!   r"   pull4   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_deps8   s   zAnsiblePull.check_depscommandc                 K   s0   | j s| j|fi |S | jj|| j fi |S r3   )r   r   r   r%   r    r:   kwargsr!   r!   r"   r%   <   s   zAnsiblePull.do_asc                 K   s   t j |fd| ji|S )N
update_env)r   r   r;   r!   r!   r"   r   A   s   zAnsiblePull.subpc                 C      d S r3   r!   r8   r!   r!   r"   r6   D      zAnsiblePull.is_installedpkg_namec                 C   r>   r3   r!   r    r@   r!   r!   r"   installH   r?   zAnsiblePull.installN)__name__
__module____qualname__r   r#   r   r   r+   r2   strr5   r9   listr%   r   abcabstractmethodr6   rB   r!   r!   r!   r"   r      s    	
r   c                       sd   e Zd Zdedee f fddZdd Zdd Zd	efd
dZ	de
fddZdefddZ  ZS )AnsiblePullPipr   userc                    s   t  | || _|   d S r3   )superr#   r   add_pip_install_site_to_pathr    r   rK   	__class__r!   r"   r#   N   s   zAnsiblePullPip.__init__c                 C   s`   | j r.| tjddg\}}| d}| jd}|r'd||g| jd< d S || jd< d S d S )Nz-cz&import site; print(site.getuserbase())z/bin/PATH:)r   r%   sys
executabler   r   join)r    	user_baser.   ansible_pathold_pathr!   r!   r"   rM   S   s   
z+AnsiblePullPip.add_pip_install_site_to_pathc                 C   s6   zdd l }W d S  ty   | j| jjg Y d S w )Nr   )pipImportErrorr   install_packagespip_package_name)r    rY   r!   r!   r"   bootstrap_pip_if_requiredd   s
   z(AnsiblePullPip.bootstrap_pip_if_requiredr@   c                 C   s   |    |  sFtjdddg}tjtjt	ddr"|
d | jr*|
d | | td| | g || td	| d
S d
S )zishould cloud-init grow an interface for non-distro package
        managers? this seems reusable
        -mrY   rB   stdlibzEXTERNALLY-MANAGEDz--break-system-packages--userzInstalling the %s packagezInstalled the %s packageN)r]   r6   rS   rT   r   pathexistsrU   	sysconfigget_pathappendr   _AnsiblePullPip__upgrade_pipLOGinfor%   )r    r@   cmdr!   r!   r"   rB   j   s(   



zAnsiblePullPip.installri   c              
   C   sh   t d z| g |dd W n tjy, } zt d| W Y d}~dS d}~ww t d dS )zOTry to upgrade pip then not raise an exception
        if the pip upgrade failszUpgrading pipz	--upgraderY   zZFailed at upgrading pip. This is usually not criticalso the script will skip this step.
%sNzUpgraded pip)rg   rh   r%   r   ProcessExecutionErrorwarning)r    ri   er!   r!   r"   __upgrade_pip   s   
	zAnsiblePullPip.__upgrade_pipr$   c                 C   s4   t jdddg}| jr|d | |\}}d|v S )Nr^   rY   rG   r`   r   )rS   rT   r   re   r%   )r    ri   r-   r.   r!   r!   r"   r6      s
   
zAnsiblePullPip.is_installed)rC   rD   rE   r   r   rF   r#   rM   r]   rB   rG   rf   boolr6   __classcell__r!   r!   rO   r"   rJ   M   s    rJ   c                       sF   e Zd Zdedee f fddZdefddZdefd	d
Z	  Z
S )AnsiblePullDistror   rK   c                    s   t  | || _d S r3   )rL   r#   r   rN   rO   r!   r"   r#      s   
zAnsiblePullDistro.__init__r@   c                 C   s   |   s| j|g d S d S r3   )r6   r   r[   rA   r!   r!   r"   rB      s   zAnsiblePullDistro.installr$   c                 C   s   t tdS )Nr   )rn   r   whichr8   r!   r!   r"   r6      s   zAnsiblePullDistro.is_installed)rC   rD   rE   r   r   rF   r#   rB   rn   r6   ro   r!   r!   rO   r"   rp      s    rp   namecfgcloudr4   r$   c                 C   s   | di }| d}| d}| d}| d}| d}	| dd}
|ryt| |j}|d	kr8t||}nt||}||
 |  | d
d}|rS||jt< |rZt	|| |	rpt
|	trd|	g}	|	D ]	}t|t| qf|r{t|| d S d S d S )Nr   r   install_methodsetup_controllergalaxyr5   package_name rY   r   )r   validate_configr   rJ   rp   rB   r9   r   CFG_OVERRIDEansible_galaxy
isinstancedictrun_ansible_pullr   ansible_controller)rr   rs   rt   r4   ansible_cfgansible_userru   rv   
galaxy_cfgpull_cfgrx   r   r   r   r!   r!   r"   handle   s:   









r   c           	      C   s6  d}|D ]}t | |std| d|  q| d}|rst|tr&|g}nt|ts2td| |D ]>}t|tsBtd| t |dsNtd| t |d	}t |d
}t||gsetd| t||grrtd| q4| d}|rt|d|dgstd| | d }|dvrtdd S )N)ru   rx   zMissing required key 'z' from r5   zLInvalid value ansible.pull. Expected either dict of list of dicts but found z7Invalid value of ansible.pull. Expected dict but found urlz Missing required key 'url' from playbook_nameplaybook_namesz+Missing required key 'playbook_names' from zzKey 'ansible.pull.playbook_name' and 'ansible.pull.playbook_names' are mutually exclusive. Please use 'playbook_names' in rv   repositoriesrun_ansiblezMissing required key from ru   )rY   r   z Invalid install method {install})r   r7   r   r}   r~   rG   anyall)	rs   required_keyskeyr   p_cfghas_playbookhas_playbookscontroller_cfgrB   r!   r!   r"   rz      sb   








rz   c                 C   s   dd |   D S )zremove boolean false valuesc                 S   s&   i | ]\}}|d ur| dd|qS )Fr.   -)replace.0r   valuer!   r!   r"   
<dictcomp>  s
    zfilter_args.<locals>.<dictcomp>)items)rs   r!   r!   r"   filter_args  s   r   r5   c                 C   s  | dd }| dd }|r|g}|  }|std n|tdddk r<|dr<td|j d	|j	 d	|j
 d
dd t| D }|ri|tdddkri| jg ||R  }|rgtj|  d S d S |D ]}| jg ||R  }|rtj|  qkd S )Nr   r   zCannot parse ansible version      r   diffzAnsible version .z%doesn't support --diff flag, exiting.c                 S   s2   g | ]\}}|d urd| d| nd| qS )T--=r!   r   r!   r!   r"   
<listcomp>#  s     z$run_ansible_pull.<locals>.<listcomp>   )r'   r2   rg   rk   r   r+   r   r7   majorminorpatchr   r   r5   rS   r-   write)r5   rs   r   r   v	pull_argsr-   playbookr!   r!   r"   r     s4   

r   c                 C   s4   |  dg }|std|  |D ]}|| qd S )NactionszInvalid config: %s)r   rg   rk   r%   )rs   r   r   r:   r!   r!   r"   r|   5  s   r|   c                 C   s   |  dg D ]}|dd|d |d g q|  dg D ]"}|d}|d}d	|gd
d t| D }|j||d qd S )Nr   gitclonesourcera   r   playbook_dirr   zansible-playbookc                 S   s    g | ]\}}d | d| qS )r   r   r!   r   r!   r!   r"   r   I  s     z&ansible_controller.<locals>.<listcomp>)cwd)r   r%   r'   r   r   )rs   r   
repositoryr4   r   r   r:   r!   r!   r"   r   >  s   

r   )/__doc__rH   loggingr   r(   rS   rc   copyr   typingr   r   	cloudinitr   r   cloudinit.cloudr   cloudinit.configr   cloudinit.config.schemar	   cloudinit.distrosr
   r   cloudinit.settingsr   cloudinit.utilr   r   __annotations__	getLoggerrC   rg   r{   ABCr   rJ   rp   rF   rG   r   r~   rz   r   r   r|   r   r!   r!   r!   r"   <module>   s@    
.T(5	!	