U
    M[‚^›-  ã                   @   sX  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 d dlm	Z	 d dlm
Z
 zd dlmZ W n ek
r„   Y nX dZdZd	Zd
ZdZdZdZdZdZdddgZdd„ Zedœdd„Zeeededdœdd„Zdd„ Zdd„ Zd3eeedd œd!d"„Zedd#œd$d%„Zd&d'„ Z d(d)„ Z!d*d+„ Z"d,d-„ Z#dd.œd/d0„Z$ddœd1d2„Z%dS )4é    N)Ú
exceptions)Úgpg)Ústatus)Úutil)ÚListg      4@z  # ubuntu-advantage-toolszDir::Etc::netrc/zDir::Etc::netrcparts/zDir::State::lists/z/etc/apt/trusted.gpg.dz/usr/share/keyringsz/usr/lib/apt/methods/httpsz /usr/sbin/update-ca-certificatesg      ð?g      @g      $@c              
   C   s  |   d¡\}}tj d¡sdS zDt ¡ 2}tjddd ||||¡tj 	|d¡gt
d W 5 Q R X W n¨ tjk
râ } z`|jdkrÈt|jƒ ¡ }t d	|¡r¬t d
 | ¡¡‚nt d|¡rÈt d | ¡¡‚t d¡‚W 5 d}~X Y n* tjk
r
   t d t
|¡¡‚Y nX dS )a  Validate apt credentials for a PPA.

    @param repo_url: private-ppa url path
    @param username: PPA login username.
    @param password: PPA login password or resource token.

    @raises: UserFacingError for invalid credentials, timeout or unexpected
        errors.
    ú://z/usr/lib/apt/apt-helperNzdownload-filez{}://{}:{}@{}/ubuntu/pool/zapt-helper-output)Ztimeoutéd   z401\s+unauthorized|httperror401z'Invalid APT credentials provided for {}zconnection timed outz-Timeout trying to access APT repository at {}z7Unexpected APT error. See /var/log/ubuntu-advantage.logzVCannot validate credentials for APT repo. Timeout after {} seconds trying to reach {}.)ÚsplitÚosÚpathÚexistsÚtempfileZTemporaryDirectoryr   ÚsubpÚformatÚjoinÚAPT_HELPER_TIMEOUTÚProcessExecutionErrorZ	exit_codeÚstrÚstderrÚlowerÚreÚsearchr   ÚUserFacingErrorÚ
subprocessZTimeoutExpired)Úrepo_urlÚusernameÚpasswordZprotocolÚ	repo_pathZtmpdÚer   © r   ú./usr/lib/python3/dist-packages/uaclient/apt.pyÚassert_valid_apt_credentials$   sR    

   ÿú÷
ÿÿÿÿ þÿr!   )Úreturnc              
   C   sb   zt j| dtd\}}W nD t jk
r\ } z$dt|jƒkrB|d7 }t |¡‚W 5 d}~X Y nX |S )z¾Run an apt command, retrying upon failure APT_RETRIES times.

    :return: stdout from successful run of the apt command.
    :raise UserFacingError: on issues running apt-cache policy.
    T)ZcaptureZretry_sleepsz%Could not get lock /var/lib/dpkg/lockz  Another process is running APT.N)r   r   ÚAPT_RETRIESr   r   r   r   r   )ÚcmdZ	error_msgÚoutÚ_errr   r   r   r    Úrun_apt_commandW   s    r'   z	List[str])Úrepo_filenamer   ÚcredentialsÚsuitesÚkeyring_filer"   c                 C   s4  z|  d¡\}}W n tk
r.   d}|}Y nX t ¡ d }| d¡rR|dd… }t|||ƒ d}tdd	gtjƒ}	|	 	¡ D ]&}
d
 
|¡|
krŽqzd|
kr˜qzd} q¢qzd}|D ]D}||kr¸qªd}d|krÚ|sÚt d||¡ d}|dj
|||d7 }qªt | |¡ t|||ƒ tj t|¡}tj t|¡}t ||¡ dS )z¥Add an authenticated apt repo and credentials to the system.

    @raises: InvalidAPTCredentialsError when the token provided can't access
        the repo PPA.
    ú:ZbearerÚseriesú/NéÿÿÿÿFz	apt-cacheÚpolicyza={}-updatesz	o=Ubuntu,TÚ z-updatesz?Not enabling apt suite "%s" because "%s-updates" is not enabledz# zQ{maybe_comment}deb {url}/ubuntu {suite} main
# deb-src {url}/ubuntu {suite} main
)Úmaybe_commentZurlÚsuite)r	   Ú
ValueErrorr   Úget_platform_infoÚendswithr!   r'   r   ZMESSAGE_APT_POLICY_FAILEDÚ
splitlinesr   ÚloggingÚdebugÚ
write_fileÚadd_apt_auth_conf_entryr
   r   r   ÚKEYRINGS_DIRÚAPT_KEYS_DIRr   Zexport_gpg_key)r(   r   r)   r*   r+   r   r   r-   Zupdates_enabledr0   ÚlineÚcontentr3   r2   Zsource_keyring_fileZdestination_keyring_filer   r   r    Úadd_auth_apt_repof   sZ    

 ÿü  þÿr@   c                 C   sò   t ƒ }|  d¡\}}| d¡r*|dd… }tj |¡rBt |¡}nd}dj|||t	d}d}g }	| 
¡ D ]V}
t d	|
¡}|r´| d
¡}||krž|	 |¡ d}qh||kr´|	 |¡ d}|	 |
¡ qh|sÎ|	 |¡ |	 d¡ tj|d |	¡dd dS )zBAdd or replace an apt auth line in apt's auth.conf file or conf.d.r   r.   Nr/   r1   z;machine {repo_path}/ login {login} password {password}{cmt})r   Úloginr   ZcmtFz$machine\s+(?P<repo_url>[.\-\w]+)/?.*r   TÚ
é€  ©Úmode)Ú!get_apt_auth_file_from_apt_configr	   r6   r
   r   r   r   Ú	load_filer   ÚAPT_AUTH_COMMENTr7   r   ÚmatchÚgroupÚappendr:   r   )r   rA   r   Úapt_auth_fileÚ	_protocolr   Zorig_contentZrepo_auth_lineZadded_new_authZ	new_linesr>   Zmachine_matchZmatched_repor   r   r    r;   ¥   s@    
ûÿ	




r;   c                    sŒ   |   d¡\}}| d¡r$|dd… }tƒ }tj |¡rˆt |¡}dj|d‰ d 	‡ fdd	„| 
¡ D ƒ¡}|sxt |¡ ntj||d
d dS )z+Remove a repo from the shared apt auth filer   r.   Nr/   zmachine {repo_path}/ login)r   rB   c                    s   g | ]}ˆ |kr|‘qS r   r   )Ú.0r>   ©Zauth_prefixr   r    Ú
<listcomp>Ø   s      z2remove_repo_from_apt_auth_file.<locals>.<listcomp>rC   rD   )r	   r6   rF   r
   r   r   r   rG   r   r   r7   Úunlinkr:   )r   rM   r   rL   Zapt_authr?   r   rO   r    Úremove_repo_from_apt_auth_fileÎ   s    

ÿrR   )r(   r   r+   r"   c                 C   s2   t  | ¡ |r&tj t|¡}t  |¡ t|ƒ dS )z>Remove an authenticated apt repo and credentials to the systemN)r   Zdel_filer
   r   r   r=   rR   )r(   r   r+   r   r   r    Úremove_auth_apt_repoà   s
    

rS   )Úfilenamer"   c                 C   s&   t  | ¡}| dd¡}t  | |¡ dS )z0Uncomment commented deb lines in the given file.z# deb zdeb N)r   rG   Úreplacer:   )rT   Zfile_contentr   r   r    Úrestore_commented_apt_list_fileë   s    
rV   c                 C   sP   t  ¡ d }| d¡\}}| d¡r0|dd… }dj|||d}t  | |¡ dS )z.Add an apt preferences file and pin for a PPA.r-   r   r.   Nr/   zHPackage: *
Pin: release o={origin}, n={series}
Pin-Priority: {priority}
)ÚoriginÚpriorityr-   )r   r5   r	   r6   r   r:   )Zapt_preference_filer   rW   rX   r-   rM   r   r?   r   r   r    Úadd_ppa_pinningò   s    
  ýÿrY   c                  C   sZ   t  dddtg¡\} }| r,|  d¡d d S t  dddtg¡\} }|  d¡d  d¡S dS )	z7Return to patch to the system configured APT auth file.ú
apt-configÚshellÚkeyú'é   z90ubuntu-advantager.   N)r   r   ÚAPT_CONFIG_AUTH_PARTS_DIRr	   ÚAPT_CONFIG_AUTH_FILEÚrstrip)r%   r&   r   r   r    rF     s    
ÿ
ÿrF   c              
   C   s~   |   d¡\}}| d¡r$|dd… }d}t dddtg¡\}}|rP|  d	¡d
 }| dd¡}tt tj	 
||d |¡ ¡¡ƒS )zEList any apt files in APT_CONFIG_LISTS_DIR given repo_url and series.r   r.   Nr/   z/var/lib/apt/listsrZ   r[   r\   r]   r^   Ú_z
_dists_{}*)r	   r6   r   r   ÚAPT_CONFIG_LISTS_DIRrU   ÚsortedÚglobr
   r   r   r   )r   r-   rM   r   Z	lists_dirr%   r&   Zaptlist_filenamer   r   r    Úfind_apt_list_files  s     
 ÿÿÿrf   c                 C   s*   t | |ƒD ]}tj |¡r
t |¡ q
dS )z?Remove any apt list files present for this repo_url and series.N)rf   r
   r   r   rQ   )r   r-   r   r   r   r    Úremove_apt_list_files$  s    rg   )Ú_entitlementsc                 C   sh   | dkrddl m}  | jD ]H}t|dƒs*q|jj|jdd}t |¡D ]}t 	d|¡ t
 |¡ qFqdS )a'  
    Clean apt sources list files written by uaclient

    :param _entitlements:
        The uaclient.entitlements module to use, defaults to
        uaclient.entitlements. (This is only present for testing, because the
        import happens within the function to avoid circular imports.)
    Nr   )Úentitlementsr   Ú*)Únamer-   zRemoving apt source file: %s)Úuaclientri   ZENTITLEMENT_CLASSESÚhasattrZrepo_list_file_tmplr   rk   re   r8   Úinfor
   rQ   )rh   Zent_clsZrepo_list_globr   r   r   r    Úclean_apt_sources+  s    	

 ÿro   c                  C   s   t  dddg¡\} }|  ¡ S )Nz
dpkg-queryz-Wz--showformat=${Package}\n)r   r   r7   )r%   rb   r   r   r    Úget_installed_packagesD  s    rp   )N)&re   r8   r
   r   r   r   rl   r   r   r   r   Útypingr   ÚImportErrorr   rH   r`   r_   rc   r=   r<   ZAPT_METHOD_HTTPS_FILEZCA_CERTIFICATES_FILEr#   r!   r   r'   r@   r;   rR   rS   rV   rY   rF   rf   rg   ro   rp   r   r   r   r    Ú<module>   s`   
3ú?) ÿ  þ