U
    Jh                  
   @   s<  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Zd dlZd dlZd dl	m
Z
mZ d dlmZmZmZmZmZmZmZ d dlZd dlmZ d dlmZmZmZmZmZmZmZ d dlm Z  d dl!m"Z" dZ#d	Z$d
Z%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3dZ4dZ5ej67e dej67e dgej67e dej67e dej67e dej67e d gd!Z8d"d#d$gZ9e: Z;e<e=e>Z?ej@G d%d& d&ejAZBed'd(eCfd)eCfd*eCfgZDd+d, ZEeEeCeCd-d.d/ZFd0d1 ZGeCeeC d2d3d4ZHdeeC eeC eeeCeCf  eCd5d6d7ZIe
dd8deeC eeeCeCf  eCd9d:d;ZJG d<d= d=ZKd>d? ZLd@dA ZMeCeeC dBdCdDZNdeCeOeeC dFdGdHZPdeeeCeCf  eCdIdJdKZQeRejSejTfe9eCdLdMdNZUdeeC eeeC  eeeCeCf  eCdOdPdQZVeCeejW dRdSdTZXeeC eejW dRdUdVZYdejWeeC eejZ dWdXdYZ[eeC eCeOeCeCdZd[d\Z\deeC eCeOeCeCeOeCd]d^d_Z]deCeCeCeeC eCeeC eeO dd`dadbZ^dcdd Z_dedf Z`deCeCeeC eeC ddgdhdiZadjdk Zbdldm Zcdndo Zddpdq ZeeCeOdrdsdtZfeeD dudvdwZgeeC dudxdyZhddeBjifeeC eeC eeB ddzd{d|Zjeek dud}d~Zleek duddZmeej duddZndd ZodduddZpeeC eCdddZqeeC eCdddZreeC dddZsdd Ztdd ZueeC eeCeeCeeC f f dddZveCduddZwdS )    N)	lru_cachewraps)DictIterableList
NamedTupleOptionalSetUnion)AcquireProgress)event_logger
exceptionsgpgmessagessecret_managersystemutil)ESM_APT_ROOTDIR)status_cache_fileg      N@z  # ubuntu-pro-clientzDir::Etc::netrc/zDir::Etc::netrcparts/zDir::State::lists/a  /*
 * Autogenerated by ubuntu-pro-client
 * Do not edit this file directly
 *
 * To change what ubuntu-pro-client sets, use the `pro config set`
 * or the `pro config unset` commands to set/unset either:
 *      global_apt_http_proxy and global_apt_https_proxy
 * for a global apt proxy
 * or
 *      ua_apt_http_proxy and ua_apt_https_proxy
 * for an apt proxy that only applies to Ubuntu Pro related repos.
 */
z$Acquire::http::Proxy "{proxy_url}";
z%Acquire::https::Proxy "{proxy_url}";
z4Acquire::http::Proxy::esm.ubuntu.com "{proxy_url}";
z5Acquire::https::Proxy::esm.ubuntu.com "{proxy_url}";
z/etc/apt/trusted.gpg.d/z/usr/share/keyringsz/usr/lib/apt/methods/httpsz /usr/sbin/update-ca-certificatesz//etc/apt/apt.conf.d/90ubuntu-advantage-aptproxyz*/var/lib/apt/periodic/update-success-stampz/var/lib/dpkg/status)ZxenialZbionicZfocalZjammyz# Written by ubuntu-pro-client
Types: deb{deb_src}
URIs: {url}
Suites: {suites}
Components: main
Signed-By: {keyrings_dir}/{keyring_file}
zetc/apt/sources.listzvar/lib/dpkg/statuszetc/apt/apt.conf.dzetc/apt/preferences.dzvar/cache/apt/archives/partialzvar/lib/apt/lists/partial)filesfoldersg      ?g      @g      $@c                   @   s   e Zd Ze Ze ZdS )AptProxyScopeN)__name__
__module____qualname__objectGLOBALUACLIENT r   r   ./usr/lib/python3/dist-packages/uaclient/apt.pyr   c   s   r   InstalledAptPackagenameversionarchc                    s   t   fdd}|S )z*Decorator ensuring apt_pkg is initialized.c                     s"   t jddkrt    | |S )NDir )apt_pkgconfiggetinit)argskwargsfr   r   new_fq   s    z"ensure_apt_pkg_init.<locals>.new_f)r   )r-   r.   r   r,   r   ensure_apt_pkg_initn   s    r/   abc                 C   s   t | |S N)r&   version_comparer0   r   r   r   r4   |   s    r4   c              
   C   s  |  d\}}tjdsdS zFt 4}tjddd||||tj	|dgt
td W 5 Q R X W n tjk
r } zntdt| |jd	krt|j }td
|rtj| dntd|rtj| dtjt|dW 5 d}~X Y n& tjk
r   tjt
|d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: UbuntuProError for invalid credentials, timeout or unexpected
        errors.
    ://z/usr/lib/apt/apt-helperNzdownload-filez{}://{}:{}@{}/pool/zapt-helper-output)Ztimeoutretry_sleepszError running apt-helper: %sd   z401\s+unauthorized|httperror401)repozconnection timed outZdetail)Zsecondsr8   )splitospathexiststempfileZTemporaryDirectoryr   subpformatjoinAPT_HELPER_TIMEOUTAPT_RETRIESr   ProcessExecutionErrorLOGerrorstrZ	exit_codestderrlowerresearchZAPTInvalidCredentialsZ
APTTimeoutAPTUnexpectedError
subprocessZTimeoutExpiredZAPTCommandTimeout)repo_urlusernamepasswordZprotocol	repo_pathZtmpderH   r   r   r   assert_valid_apt_credentials   sB    

   
  rS   )	apt_errorreturnc                 C   sV   t  }|  dD ]<}|rtd|}|rd| d dd  }|| q|S )aA  Parse apt update errors for invalid apt config in user machine.

    This functions parses apt update errors regarding the presence of
    invalid apt config in the system, for example, a ppa that cannot be
    reached, for example.

    In that scenario, apt will output a message in the following formats:

    The repository 'ppa 404 Release' ...
    Failed to fetch ppa 404 ...

    On some releases, both of these errors will be present in the apt error
    message.

    :param apt_error: The apt error string
    :return: a NamedMessage containing the error message
    
z2(Failed to fetch |The repository .)(?P<url>[^\s]+)z- urlz/distsr   )setstripr:   rJ   rK   	groupdictadd)rT   failed_reposlineZpattern_matchZrepo_url_matchr   r   r   (_parse_apt_update_for_invalid_apt_config   s     r^   )cmd	error_msgoverride_env_varsrU   c              
   C   s   zt j| dt|d\}}W n tjk
r } zrtdt| t| dt|jkr\t	 n$t
|j}|rtjdt|d|r|nt|}tj|dW 5 d}~X Y nX |S )	a  Run an apt command, retrying upon failure APT_RETRIES times.

    :param cmd: List containing the apt command to run, passed to subp.
    :param error_msg: The string to raise as UbuntuProError when all retries
       are exhausted in failure.
    :param override_env_vars: Passed directly as subp's override_env_vars arg

    :return: stdout from successful run of the apt command.
    :raise UbuntuProError: on issues running apt-cache policy.
    T)Zcapturer6   ra   z Error running apt command %s: %sz%Could not get lock /var/lib/dpkg/lockrV   )r\   r9   N)r   r?   rC   r   rD   rE   rF   rG   rH   APTProcessConflictErrorr^   APTInvalidRepoErrorrA   sortedrL   )r_   r`   ra   out_errrR   r\   msgr   r   r   run_apt_command   s&    

rh   )maxsize)r`   ra   rU   c                 C   s   t ddg| |dS )N	apt-cachepolicy)r_   r`   ra   )rh   )r`   ra   r   r   r   get_apt_cache_policy   s
    rl   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )PreserveAptCfgc                 C   s   || _ i | _d S r3   )apt_funccurrent_apt_cfg)selfrn   r   r   r   __init__	  s    zPreserveAptCfg.__init__c                    s&   t j  fdd  D | _|  S )Nc                    s   i | ]}|t  |qS r   )copydeepcopyr(   ).0keycfgr   r   
<dictcomp>  s     z,PreserveAptCfg.__enter__.<locals>.<dictcomp>)r&   r'   keysro   rn   )rp   r   rv   r   	__enter__  s
    
zPreserveAptCfg.__enter__c                 C   s4   t j}| j D ]}||| j|  qt   d S r3   )r&   r'   ro   ry   rX   Zinit_system)rp   typevalue	tracebackrw   ru   r   r   r   __exit__  s    zPreserveAptCfg.__exit__N)r   r   r   rq   rz   r~   r   r   r   r   rm     s   rm   c                  C   s.   t j D ]} t j|  q
t   t d S r3   )r&   r'   ry   clearr)   Cacheru   r   r   r   get_apt_pkg_cache  s    r   c                  C   sn   zPt   tj D ]} td| stj|  qtjdt t	  t
d W S  tk
rh   i  Y S X d S )Nz^Acquirer$   )_ensure_esm_cache_structurer&   r'   ry   rJ   rK   r   rX   r   r)   r   	Exceptionr   r   r   r   get_esm_apt_pkg_cache&  s    r   )pkg_namerU   c              	   C   sT   t t4}z||  }W n  tk
r6   Y W 5 Q R  d S X W 5 Q R X |jrP|jjS d S r3   )rm   r   KeyErrorcurrent_verver_str)r   cachepackager   r   r   get_pkg_version>  s    
r   F)r   check_esm_cacherU   c              
   C   s  t t`}z||  }W n  tk
r6   Y W 5 Q R  d S X t|}||}|s^W 5 Q R  d S |j}W 5 Q R X |sv|S t t}|rz||  }W n$ tk
r   | Y W  5 Q R  S X t|}	|	|}
|
s|W  5 Q R  S |
j}t||dkr|W  5 Q R  S W 5 Q R X |S )Nr   )	rm   r   r   r&   DepCacheget_candidate_verr   r   r4   )r   r   r   r   	dep_cache	candidateZcandidate_versionZ	esm_cacheZesm_packageZesm_dep_cacheZesm_candidateZesm_candidate_versionr   r   r   get_pkg_candidate_versionK  s@    





 r   )ra   rU   c              
   C   s   zztddg| d}W n tjk
rR } ztdt| t W 5 d }~X Y nb tj	k
r } ztj
|jdW 5 d }~X Y n2 tjk
r } ztj|jdW 5 d }~X Y nX W 5 t   X |S )Napt-getupdater_   ra   z Error running apt-get update: %sZrepo_msgr9   )rl   cache_clearrh   r   rb   rE   rF   rG   ZAPTUpdateProcessConflictErrorrc   ZAPTUpdateInvalidRepoErrorrg   ZUbuntuProErrorAPTUpdateFailed)ra   re   rR   r   r   r   run_apt_update_commandw  s     
$
r   )sources_list_pathc                 C   s*  t t}tjdtj|  tjdd tjdd t }|	  t
 }tjtjdd}t|}zz"| |||d W 5 Q R X W nt ttd	d
k
r } ztdt| t W 5 d }~X Y n4 tk
r } ztjt|dW 5 d }~X Y nX W 5 t  X W 5 Q R X d S )NzDir::Etc::sourcelistzDir::Etc::sourcepartszN.O.F.O.L.D.E.RzAPT::List-Cleanup0zDir::State::Listslockr   Errorr   zError updating apt cache: %sr9   )rm   r   r&   r'   rX   r;   r<   abspath
SourceListread_main_listr   rA   Zfind_dirZFileLockrl   r   r   getattrrE   rF   rG   r   rb   SystemErrorr   )r   r   sources_listfetch_progressZ	lock_filer   rR   r   r   r   update_sources_list  s0     

 
&r   )packagesapt_optionsra   rU   c              
   C   s   |d krg }zt dddg| |  |d}W nZ tjk
rT   td|  t Y n2 tjk
r } ztj|jdW 5 d }~X Y nX |S )Nr   install--assume-yesr   z)Error running apt install for packages %sr   )	rh   r   rb   rE   rF   ZAPTInstallProcessConflictErrorrc   ZAPTInstallInvalidRepoErrorrg   )r   r   ra   re   rR   r   r   r   run_apt_install_command  s"    
 r   )originrU   c              	   C   s\   t  }tt@}|jD ]2}|j}|r|jD ]\}}|j| kr*|| q*qW 5 Q R X t|S r3   )	rX   rm   r   r   r   	file_listr   r[   list)r   resultr   r   installed_versionfile_r   r   r    get_installed_packages_by_origin  s    


r   c           	   	   C   s   | d krg S t  }tt`}t|}|jD ]H}|j}|r,||}|r,||kr,|jD ]\}}|j	| krV|
| qVq,W 5 Q R X t|S r3   )rX   rm   r   r&   r   r   r   r   r   r   r[   r   )	r   r   r   r   r   r   r   r   r   r   r   r   ;get_installed_packages_with_uninstalled_candidate_in_origin  s    




r   )r   exclude_originrU   c                    s6   g }| j D ]&} fdd|jD }|r
|| q
|S )Nc                    s(   g | ] \}}|j d kr|j kr|qS )Znow)Z	componentr   )rt   r   r   r   r   r   
<listcomp>  s   
 
z3get_remote_versions_for_package.<locals>.<listcomp>)Zversion_listr   append)r   r   Zvalid_versionsr"   Zvalid_originsr   r   r   get_remote_versions_for_package  s    

r   )suitesseriesupdates_enabledrN   rU   c                 C   sR   d}| D ]D}||krqd}d|kr8|s8t d|| d}|dj|||d7 }q|S )Nr%   -updatesz?Not enabling apt suite "%s" because "%s-updates" is not enabledz# zC{maybe_comment}deb {url} {suite} main
# deb-src {url} {suite} main
)maybe_commentrW   suite)rE   warningr@   )r   r   r   rN   contentr   r   r   r   r   _get_list_file_content	  s(      r   )r   r   r   rN   keyring_fileinclude_deb_srcrU   c           	         sZ    fdd| D }|s0t d  dd |D }|r8dnd}tj|d|t||d}|S )	Nc                    s   g | ]} |kr|qS r   r   rt   r   r   r   r   r   +  s      z-_get_sources_file_content.<locals>.<listcomp>zPNot enabling service-related -updates suites because "%s-updates" is not enabledc                 S   s   g | ]}d |kr|qS )r   r   r   r   r   r   r   2  s     z deb-srcr%    )rW   r   Zkeyrings_dirr   deb_src)rE   r   DEB822_REPO_FILE_CONTENTr@   rA   KEYRINGS_DIR)	r   r   r   rN   r   r   Zappliable_suitesr   r   r   r   r   _get_sources_file_content#  s$    r   )repo_filenamerN   credentialsr   r   snapshot_urlscheck_updates_pocketrU   c                 C   s2  z| d\}}W n tk
r.   d}|}Y nX tj| t j}	|dr\|dd }t	||| d}
|rd}
t
dd	gtj}| D ]&}d
|	|krqd|krqd}
 qq|g| D ]}t||| q|	tkrtjt|}tjt|}t|| t||	|
|}nt||	|
||}t| | dS )zAdd an authenticated apt repo and credentials to the system.

    @raises: InvalidAPTCredentialsError when the token provided can't access
        the repo PPA.
    :Zbearer/NTFrj   rk   za={}-updatesz	o=Ubuntu,)r:   
ValueErrorr   ZsecretsZ
add_secretr   Zget_release_infor   endswithrS   rh   r   ZAPT_POLICY_FAILED
splitlinesr@   add_apt_auth_conf_entrySERIES_NOT_USING_DEB822r;   r<   rA   r   APT_KEYS_DIRr   Zexport_gpg_keyr   r   
write_file)r   rN   r   r   r   r   r   rO   rP   r   r   rk   r]   rW   Zsource_keyring_fileZdestination_keyring_filer   r   r   r   add_auth_apt_repoC  sX    


 
       r   c                 C   s  t  }d| kr| d\}}n| }|ds4|d7 }tj|rLt|}nd}dj|||t	d}d}g }	|
 D ]\}
|s|
 }t|dkr|d }||kr|	| d	}qr||kr|	| d	}|	|
 qr|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.r5   r   r%   z:machine {repo_path} login {login} password {password}{cmt})rQ   loginrP   ZcmtF      TrV     modeN)!get_apt_auth_file_from_apt_configr:   r   r;   r<   r=   r   	load_filer@   APT_AUTH_COMMENTr   lenr   r   rA   )rN   r   rP   apt_auth_file	_protocolrQ   Zorig_contentZrepo_auth_lineZadded_new_authZ	new_linesr]   Z
split_lineZcurr_line_repor   r   r   r     sF    
	



r   c                    s   d| kr|  d\}}n| }|dr2|dd }t }tj|rt|}dj|d d	 fdd	|
 D }|st| ntj||d
d dS )z+Remove a repo from the shared apt auth filer5   r   Nr   zmachine {repo_path}/ login)rQ   rV   c                    s   g | ]} |kr|qS r   r   )rt   r]   Zauth_prefixr   r   r     s      z2remove_repo_from_apt_auth_file.<locals>.<listcomp>r   r   )r:   r   r   r;   r<   r=   r   r   r@   rA   r   ensure_file_absentr   )rN   r   rQ   r   Zapt_authr   r   r   r   remove_repo_from_apt_auth_file  s    

r   )r   rN   r   r   rU   c                 C   s^   t |  | dr&t t| d |rBtjt|}t | |g| D ]}t	| qLdS )z>Remove an authenticated apt repo and credentials to the systemz.sourcesr   N)
r   r   r   r   Zset_filename_extensionr;   r<   rA   r   r   )r   rN   r   r   rW   r   r   r   remove_auth_apt_repo  s    



r   c                 C   sB   | d\}}|dr$|dd }dj||d}t| | dS )z.Add an apt preferences file and pin for a PPA.r5   r   Nr   z<Package: *
Pin: release o={origin}
Pin-Priority: {priority}
)r   priority)r:   r   r@   r   r   )Zapt_preference_filerN   r   r   r   rQ   r   r   r   r   add_ppa_pinning  s    
 r   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shellru   'r   z90ubuntu-advantager   N)r   r?   APT_CONFIG_AUTH_PARTS_DIRr:   APT_CONFIG_AUTH_FILErstrip)re   rf   r   r   r   r     s    

r   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.r5   r   Nr   z/var/lib/apt/listsr   r   ru   r   r   r   z
_dists_{}*)r:   r   r   r?   APT_CONFIG_LISTS_DIRreplacerd   globr;   r<   rA   r@   )rN   r   r   rQ   Z	lists_dirre   rf   Zaptlist_filenamer   r   r   find_apt_list_files  s$    

 r   c                 C   s   t | |D ]}t| q
dS )z?Remove any apt list files present for this repo_url and series.N)r   r   r   )rN   r   r<   r   r   r   remove_apt_list_files  s    r   )pkgrU   c                 C   s
   | t  kS r3   )get_installed_packages_names)r   r   r   r   is_installed  s    r   )rU   c               	   C   sL   g } t t6}|jD ](}|j}|r| t|j|j|jd qW 5 Q R X | S )N)r!   r"   r#   )	rm   r   r   r   r   r    r!   r   r#   )Z	installedr   r   r   r   r   r   get_installed_packages  s    

r   c                  C   s   t  } dd | D }|S )Nc                 S   s   g | ]
}|j qS r   )r!   )rt   r   r   r   r   r   *  s     z0get_installed_packages_names.<locals>.<listcomp>)r   )Zpackage_listZ	pkg_namesr   r   r   r   (  s    r   )
http_proxyhttps_proxyproxy_scoperU   c                 C   s   | s|rB|rBd}|t jkr d}n|t jkr.d}ttjj|d d}| r|t jkrf|tj| d7 }n|t jkr|t	j| d7 }|r|t jkr|t
j|d7 }n|t jkr|tj|d7 }|dkrt| }|dkrtt ntt| dS )a  
    Writes an apt conf file that configures apt to use the proxies provided as
    args.
    If both args are None, then no apt conf file is written. If this function
    previously wrote a conf file, and was run again with both args as None,
    the existing file is removed.

    :param http_proxy: the url of the http proxy apt should use, or None
    :param https_proxy: the url of the https proxy apt should use, or None
    :return: None
    r%   z	UA-scopedglobal)Zscope)Z	proxy_urlN)r   r   r   eventinfor   ZSETTING_SERVICE_PROXY_SCOPEr@   APT_CONFIG_UA_PROXY_HTTPAPT_CONFIG_GLOBAL_PROXY_HTTPAPT_CONFIG_UA_PROXY_HTTPSAPT_CONFIG_GLOBAL_PROXY_HTTPSAPT_PROXY_CONFIG_HEADERr   r   APT_PROXY_CONF_FILEr   )r   r   r   messageZapt_proxy_configr   r   r   setup_apt_proxy.  sD    







r  c                  C   s    d } t jtrt tj} | S r3   )r;   r<   r=   APT_UPDATE_SUCCESS_STAMP_PATHstatst_mtimeZ
cache_timer   r   r   get_apt_cache_timef  s    r  c                  C   s    d } t jtrt tj} | S r3   )r;   r<   r=   DPKG_STATUS_PATHr
  r  )Zstatus_timer   r   r   get_dpkg_status_timem  s    r  c                  C   s$   t  } | d krd S tj| tjjS r3   )r  datetimeZfromtimestamptimezoneZutcr  r   r   r   get_apt_cache_datetimet  s    r  c                     s   t j tjtddd td td  } t fdd| D rBd S tt td D ]}t	| qTtd D ]}tj
|ddd	 qld S )
Nz**/*T)	recursiver   r   c                 3   s   | ]}| kV  qd S r3   r   )rt   r   Zexisting_filesr   r   	<genexpr>  s     z._ensure_esm_cache_structure.<locals>.<genexpr>i  )exist_okr   )r   r;   r<   rA   r   ESM_BASIC_FILE_STRUCTUREallr   Zensure_folder_absentZcreate_filemakedirs)Zdesired_filesr   Zfolderr   r  r   r   {  s     
r   c                 C   s  t  sd S t  ddlm} ddlm} ddlm}m	} d}d}t
 }|d kr^|| d }|dg D ]D}|ddd	kr|d
ddk}|dddkrj|d
ddk}qj|| }	|r|	 d |jkr|	  n|	  t  r|| }
|r|
 d |jkr|
  n|
  ttx}t }|  G dd dt}| }z|||d W n8 tk
r } ztdt| W 5 d }~X Y nX W 5 Q R X d S )Nr   )status)ApplicationStatus)ESMAppsEntitlementESMInfraEntitlementFservicesr!   r%   zesm-appsZ	availableZnoZyesz	esm-infrac                   @   s,   e Zd ZejdddZejdddZdS )z-update_esm_caches.<locals>.EsmAcquireProgress)itemc                 S   s   t d|j d S )NzFetched ESM Apt Cache item: {})rE   debugr@   urirp   r  r   r   r   done  s    z2update_esm_caches.<locals>.EsmAcquireProgress.donec                 S   s   t d|j d S )Nz&Failed to fetch ESM Apt Cache item: {})rE   r   r@   r!  r"  r   r   r   fail  s    
z2update_esm_caches.<locals>.EsmAcquireProgress.failN)r   r   r   r&   ZAcquireItemDescr#  r$  r   r   r   r   EsmAcquireProgress  s   r%  z%Failed to fetch the ESM Apt Cache: {})r   Zis_current_series_ltsr   Zuaclient.actionsr  Z(uaclient.entitlements.entitlement_statusr  Zuaclient.entitlements.esmr  r  r   readr(   Zapplication_statusZDISABLEDZsetup_local_esm_repoZdisable_local_esm_repoZis_current_series_active_esmrm   r   r&   r   r   r   r   r   rE   r   r@   rG   )rw   r  r  r  r  Zapps_availableZinfra_availableZcurrent_statusserviceZappsZinfrar   r   r%  r   rR   r   r   r   update_esm_caches  sP    



	r(  package_namesZerror_messagec                 C   s(   t dddddgt|  |ddid d	S )
a  
    Remove APT packages from the system.

    Setting DEBIAN_FRONTEND to noninteractive makes sure no prompts will
    appear during the operation. In this case, --force-confdef will
    automatically pick the default option when some debconf should appear.
    In the absence of a default option, --force-confold will automatically
    choose to keep the old configuration file.
    r   remover   $-o Dpkg::Options::="--force-confdef"$-o Dpkg::Options::="--force-confold"DEBIAN_FRONTENDnoninteractivera   Nrh   r   r)  r   r   r   remove_packages  s    
r2  c                 C   s(   t dddddgt|  |ddid d	S )
a  
    Purge APT packages from the system - remove everything.

    Setting DEBIAN_FRONTEND to noninteractive makes sure no prompts will
    appear during the operation. In this case, --force-confdef will
    automatically pick the default option when some debconf should appear.
    In the absence of a default option, --force-confold will automatically
    choose to keep the old configuration file.
    r   purger   r,  r-  r.  r/  r0  Nr1  r)  r   r   r   purge_packages  s    
r4  r*  c                 C   s   t | dddgddid dS )a6  
    Install packages, allowing downgrades.

    The --allow downgrades flag is needed because sometimes we need to
    reinstall the packages to a lower version (passed in the package_name
    string, as package=version).

    Setting DEBIAN_FRONTEND to noninteractive makes sure no prompts will
    appear during the operation. In this case, --force-confdef will
    automatically pick the default option when some debconf should appear.
    In the absence of a default option, --force-confold will automatically
    choose to keep the old configuration file.
    z--allow-downgradesr,  r-  r.  r/  )r   ra   N)r   r5  r   r   r   reinstall_packages  s    r6  c                  C   s*   t j D ]} t j|  q
t   t jS r3   )r&   r'   ry   r   Zinit_configr   r   r   r   _get_apt_config  s    r7  c              	   C   s"   t t}|| }W 5 Q R X |S r3   )rm   r7  r   )Zbase_keyapt_cfgZapt_cfg_keysr   r   r   get_apt_config_keys(  s    
r9  )	cfg_namesrU   c              	   C   sN   i }t t8}| D ],}||}t|s6||p4d}|||< qW 5 Q R X |S )z
    Get all APT configuration values for the given config names. If
    one of the config names is not present on the APT config, that
    config name will have a value of None
    N)rm   r7  r(   rG   Z
value_list)r:  Zapt_cfg_dictr8  Zcfg_nameZ	cfg_valuer   r   r   get_apt_config_values/  s    

r;  c                  C   s   d} d}t j|r|S | S )Nz/etc/apt/sources.listz&/etc/apt/sources.list.d/ubuntu.sources)r;   r<   r=   )Zold_sources_pathZnew_sources_pathr   r   r   get_system_sources_fileE  s    
r<  )NN)NN)F)N)NN)N)F)F)N)xrr   r  enumr   Zloggingr;   rJ   rM   r>   	functoolsr   r   typingr   r   r   r   r   r	   r
   r&   Zapt.progress.baser   Zuaclientr   r   r   r   r   r   r   Zuaclient.defaultsr   Zuaclient.files.state_filesr   rB   r   r   r   r   r  r  r  r  r  r   r   ZAPT_METHOD_HTTPS_FILEZCA_CERTIFICATES_FILEr  r	  r  r   r   r<   rA   r  rC   Zget_event_loggerr   Z	getLoggerZreplace_top_level_logger_namer   rE   uniqueEnumr   rG   r    r/   r4   rS   r^   rh   rl   rm   r   r   r   boolr   r   Zretryrb   r   r   r   ZPackager   r   ZVersionr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  floatr  r  r  r   r(  r2  r4  r6  r7  r9  r;  r<  r   r   r   r   <module>   sl  $$	
 +(  +    - 
(  
       ' A/ 8E
