U
    2d>                     @   s   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m	Z	m
Z
mZmZ d dlmZmZmZmZmZmZmZmZ d dlmZ d dlmZ e ZeeeZG dd dej Z!dS )	    N)exists)AnyDictListOptionalTupleUnion)aptcontractevent_logger
exceptionshttpmessagessystemutil)base)ApplicationStatusc                       s,  e Zd ZdZdZdZdZdZdZe	e
eedf dddZe	ee dd	d
ZedddZe	ejedddZd$eedddZd%ddZeeeej f dddZdd Zd&eeef eeef eed fddZ d'eee  eeddddZ!d(edddd Z"d)eed!d"d#Z#  Z$S )*RepoEntitlementz*/etc/apt/sources.list.d/ubuntu-{name}.listz$/etc/apt/preferences.d/ubuntu-{name}z	{}/ubuntuNF)returnc                 C   s   d S N selfr   r   </usr/lib/python3/dist-packages/uaclient/entitlements/repo.pyrepo_pin_priority)   s    z!RepoEntitlement.repo_pin_priorityc                 C   s<   g }| j di }|r8|di }t|dg }|}|S )zdebs to install on enablemententitlement
directivesadditionalPackages)entitlement_cfggetcopy)r   packagesr   r   Zadditional_packagesr   r   r   r!   -   s    
zRepoEntitlement.packagesc                 C   s    t jt| jd}t| |S )z%Check if system needs to be rebooted.)Zinstalled_pkgs)r   Zshould_rebootsetr!   eventZneeds_reboot)r   Zreboot_requiredr   r   r   _check_for_reboot>   s
    
z!RepoEntitlement._check_for_rebootc                 C   s   d S r   r   r   r   r   r   repo_key_fileF   s    zRepoEntitlement.repo_key_file)silentr   c                 C   s   | j |d | jrb| jrbt| jdkr6dd| j nd}td| tt	j
j| jd n*|   tt	jj| jd | jdd	 d
S )zEnable specific entitlement.

        @return: True on success, False otherwise.
        @raises: UserFacingError on failure to install suggested packages
        r&   r   z:   zSkipping installing packages{}titleinstall)Z	operationT)setup_apt_configZsupports_access_onlyZaccess_onlylenr!   joinr#   infoformatr   ZACCESS_ENABLED_TMPLr+   install_packagesZENABLED_TMPLZ_check_for_reboot_msg)r   r&   Zpackages_strr   r   r   _perform_enableK   s    zRepoEntitlement._perform_enablec                 C   s"   t | dr|   | j|d dS )Nremove_packagesr'   T)hasattrr4   remove_apt_config)r   r&   r   r   r   _perform_disablea   s    
z RepoEntitlement._perform_disablec                 C   s   t jtjj| jdf}| j}|di di }|d}|sTt jtjj| jdfS t	j
tjjd}t| j||}|rt jtjj| jdf}| jr| jD ]*}t	|st jtjj| j|df  S q|S )Nr*   r   r   aptURL)	error_msg)servicepackage)r   DISABLEDr   ZSERVICE_NOT_CONFIGUREDr1   r+   r   r   ZNO_APT_URL_FOR_SERVICEr	   Zget_apt_cache_policyZAPT_POLICY_FAILEDmsgresearchrepo_url_tmplZENABLEDZSERVICE_IS_ACTIVEcheck_packages_are_installedr!   Zis_installedZ SERVICE_DISABLED_MISSING_PACKAGEname)r   Zcurrent_statusr   r   repo_urlZpolicymatchr;   r   r   r   application_statusg   s>     


 
z"RepoEntitlement.application_statusc                 C   sP   | j j| jd}tdd t| dD r6dS |s>dS t|t|kS )zCheck if apt url delta should be applied.

        :param apt_url: string containing the apt url to be used.

        :return: False if apt url is already found on the source file.
                 True otherwise.
        rB   c                 s   s   | ]}| d V  qdS )#N)
startswith).0liner   r   r   	<genexpr>   s   z<RepoEntitlement._check_apt_url_is_applied.<locals>.<genexpr>
FT)	repo_list_file_tmplr1   rB   allr   Z	load_filestripsplitbool)r   Zapt_urlZapt_filer   r   r   _check_apt_url_is_applied   s    z)RepoEntitlement._check_apt_url_is_applied)orig_accessdeltasallow_enabler   c                    s
  t  |||rdS |di }|di }|d}|d}| jd}|r^|r^|  }	n|  \}	}
|	tjkrxdS | 	|st
d| j |di }|di d}|r| jj| jd	}t|| |   |   |rt
d
d| | j|d dS )a1  Process any contract access deltas for this entitlement.

        :param orig_access: Dictionary containing the original
            resourceEntitlement access details.
        :param deltas: Dictionary which contains only the changed access keys
        and values.
        :param allow_enable: Boolean set True if allowed to perform the enable
            operation. When False, a message will be logged to inform the user
            about the recommended enabled service.

        :return: True when delta operations are processed; False when noop.
        Tr   r   r8   r   zstatus-cacheFz5Updating '%s' apt sources list on changed directives.rF   z-Installing packages on changed directives: {}, )package_list)superprocess_contract_deltasr   cfgZ
read_cacheZ"_check_application_status_on_cacherE   r   r<   rR   LOGr0   rB   rM   r1   r	   remove_auth_apt_repor6   r-   r/   r2   )r   rS   rT   rU   Zdelta_entitlementZdelta_directivesZdelta_apt_urlZdelta_packagesZstatus_cacherE   _Zorig_entitlementZold_urlrepo_filename	__class__r   r   rY      s@    




z'RepoEntitlement.process_contract_deltasT)rW   cleanup_on_failureverboser   c                 C   s   |s
| j }|sdS | jdg }t|s.dS |rFtdj| jd | j	r`ddi}ddd	g}nd}g }z(t
jj| jd}tj|||j|d
 W n$ tjk
r   |r|    Y nX dS )a)  Install contract recommended packages for the entitlement.

        :param package_list: Optional package list to use instead of
            self.packages.
        :param cleanup_on_failure: Cleanup apt files if apt install fails.
        :param verbose: If true, print messages to stdout
        NZpre_installzInstalling {title} packagesr*   ZDEBIAN_FRONTENDZnoninteractivez--allow-downgradesz$-o Dpkg::Options::="--force-confdef"z$-o Dpkg::Options::="--force-confold")r!   apt_optionsr9   override_env_vars)r!   Z	messagingr   r   Zhandle_message_operationsr#   r0   r1   r+   apt_noninteractiver   ENABLED_FAILEDr	   run_apt_install_commandr=   r   UserFacingErrorr6   )r   rW   ra   rb   Zmsg_opsrd   rc   r=   r   r   r   r2      s:    

z RepoEntitlement.install_packagesc                 C   s  d}d}d}| j js| j jrNtd| j jtj}td| j jtj}tjj	}n@| j j
s^| j jrtd| j j
tj}td| j jtj}tjj}tj|||d | jj| jd}| j}|d di }|d di }|d	}	|	s>| j jd
 }
|ds&t| j }||
| j}|r&|d	}	|	s>|
}	td| j |d}|s`td| j|d}|s|t| j|d}|std| j| j j| jr| jstd| jt j!j| jdj"| j#j| jd}t$||| j| j g }t%tj&s|'d t%tj(s*|'d |r|sLt)*dd+| ztj,|d W n" tjk
r~   | -   Y nX t.|| j/||	|| j0 |st)*t j1 zt2  W n& tjk
r   | j-dd  Y nX dS )zSetup apt config based on the resourceToken and directives.
        Also sets up apt proxy if necessary.

        :raise UserFacingError: on failure to setup any aspect of this apt
           configuration
        Nr   Zhttps)
http_proxyhttps_proxyZproxy_scoperF   r   r   obligationsZresourceTokenZmachineTokenZenableByDefaultzWNo resourceToken present in contract for service %s. Using machine token as credentialsaptKeyz6Ubuntu Pro server provided no aptKey directive for {}.r8   Zsuitesz%Empty {} apt suites directive from {}z:Cannot setup apt pin. Empty apt repo origin value '{}'.
{}r*   zapt-transport-httpszca-certificateszInstalling prerequisites: {}rV   )r!   F)run_apt_update)3rZ   Zglobal_apt_http_proxyZglobal_apt_https_proxyr   Zvalidate_proxyZPROXY_VALIDATION_APT_HTTP_URLZPROXY_VALIDATION_APT_HTTPS_URLr	   ZAptProxyScopeZGLOBALZua_apt_http_proxyZua_apt_https_proxyZUACLIENTZsetup_apt_proxyrM   r1   rB   r   r   machine_tokenr
   ZUAContractClientZget_resource_machine_accessr[   Zwarningr+   r   rh   MissingAptURLDirectiveZcontract_urlr   originr   rf   r=   repo_pref_file_tmplZadd_ppa_pinningr   ZAPT_METHOD_HTTPS_FILEappendZCA_CERTIFICATES_FILEr#   r0   r/   rg   r6   Zadd_auth_apt_repor@   r%   APT_UPDATING_LISTSrun_apt_update_command)r   r&   ri   rj   Zscoper^   Zresource_cfgr   rk   tokenrn   ZclientZmachine_accessrl   rC   Zrepo_suitesrepo_pref_fileZprerequisite_pkgsr   r   r   r-     s    
  
 



 


z RepoEntitlement.setup_apt_config)rm   r&   c           	      C   s   t  j}| jj| jd}| jjj| j 	di }|	di }|	d}|sXt
| jt||| j t|| | jr| jj| jd}t | |r|sttj t  dS )zRemove any repository apt configuration files.

        :param run_apt_update: If after removing the apt update
            command after removing the apt files.
        rF   r   r   r8   N)r   Zget_release_infoseriesrM   r1   rB   rZ   Zmachine_token_fileZentitlementsr   r   ro   r	   r\   r%   Zremove_apt_list_filesr   rq   Zensure_file_absentr#   r0   r   rs   rt   )	r   rm   r&   rw   r^   r   Zaccess_directivesrC   rv   r   r   r   r6     s&    
 

z!RepoEntitlement.remove_apt_config)F)F)F)NTT)F)TF)%__name__
__module____qualname__rM   rq   r@   rp   re   rA   propertyr   intstrr   r   r!   rQ   r$   abcabstractmethodr%   r3   r7   r   r   r   r   ZNamedMessagerE   rR   r   r   rY   r2   r-   r6   __classcell__r   r   r_   r   r      sV   
( 

?   
3     r   )"r~   r    Zloggingr>   os.pathr   typingr   r   r   r   r   r   Zuaclientr	   r
   r   r   r   r   r   r   Zuaclient.entitlementsr   Z(uaclient.entitlements.entitlement_statusr   Zget_event_loggerr#   Z	getLoggerZreplace_top_level_logger_namerx   r[   ZUAEntitlementr   r   r   r   r   <module>   s    (
