U
    M[^e4                     @   s   d dl Z d dlmZ d dlZd dlZz6d dlmZmZmZmZm	Z	 e	e
eg ef ef ZW n ek
rn   Y nX 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mZ d	ZG d
d de jdZdS )    N)datetime)AnyCallableDictOptionalTuple)config)contract)status)util)ApplicabilityStatusContractStatusUserFacingStatuszZ(?P<major>[\d]+)[.-](?P<minor>[\d]+)[.-](?P<patch>[\d]+\-[\d]+)-(?P<flavor>[A-Za-z0-9_-]+)c                   @   s(  e Zd ZdZeejedddZeejedddZ	eejedddZ
d	Zd+d
ddddZejddeedddZd,eedddZd-eedddZddddZejd.eedddZedddZeddd Zd/d!d!eed"d#d$Zd%dd&d'Zejd(dd)d*ZdS )0UAEntitlementN)returnc                 C   s   dS )z&The lowercase name of this entitlementN selfr   r   </usr/lib/python3/dist-packages/uaclient/entitlements/base.pyname#   s    zUAEntitlement.namec                 C   s   dS )z,The human readable title of this entitlementNr   r   r   r   r   title)   s    zUAEntitlement.titlec                 C   s   dS )z&A sentence describing this entitlementNr   r   r   r   r   description/   s    zUAEntitlement.descriptionr   zOptional[config.UAConfig])cfgr   c                 C   s   |st  }|| _dS )z]Setup UAEntitlement instance

        @param config: Parsed configuration dictionary
        N)r   ZUAConfigr   )r   r   r   r   r   __init__:   s    zUAEntitlement.__init__F)silent_if_inapplicable)r   r   c                C   s   dS )a  Enable specific entitlement.

        :param silent_if_inapplicable:
            Don't emit any messages until after it has been determined that
            this entitlement is applicable to the current machine.

        @return: True on success, False otherwise.
        Nr   )r   r   r   r   r   enableC   s    
zUAEntitlement.enable)silentr   c                 C   s8   |   \}}|tjjkr4|s0ttjj| jd dS dS )zReport whether or not disabling is possible for the entitlement.

        @param silent: Boolean set True to silence printed messages/warnings.
        r   FT)application_statusr
   ApplicationStatusDISABLEDprintZMESSAGE_ALREADY_DISABLED_TMPLformatr   )r   r   r   _r   r   r   can_disableO   s    zUAEntitlement.can_disablec                 C   s   |   r"td| j t| j |  tj	ksL|sHt
tjj| jd dS |  \}}|tjjkr|s|t
tjj| jd dS |  \}}|tjjkr|st
| dS dS )z
        Report whether or not enabling is possible for the entitlement.

        :param silent: if True, suppress output
        z(Updating contract on service '%s' expiryr   FT)is_access_expiredloggingdebugr   r	   Zrequest_updated_contractr   contract_statusr   ENTITLEDr!   r
   ZMESSAGE_UNENTITLED_TMPLr"   r   r   r   r    ZMESSAGE_ALREADY_ENABLED_TMPLapplicability_statusr   INAPPLICABLE)r   r   r   r#   r*   detailsr   r   r   
can_enable`   s2     zUAEntitlement.can_enablezTuple[ApplicabilityStatus, str]c                 C   s  | j j| j}|stjdfS | jD ]"\}}}| |kr$tj|f  S q$|d di }t	 }|dg }|r|d |krtjt
jj| j|d d|dfS |dg }|r|d |krtjt
jj| j|d	 d
fS |d }	|dg }
|d}tt|	}|
r>|r|d|
kr>tjt
jj| j|	d|
dfS |rt
jj| j|	|d}z"|d\}}t|}t|}W n, tk
r   td| tj|f Y S X |stj|fS t|d}t|d}||k rtj|fS ||kr||k rtj|fS tjdfS )a  Check all contract affordances to vet current platform

        Affordances are a list of support constraints for the entitlement.
        Examples include a list of supported series, architectures for kernel
        revisions.

        :return:
            tuple of (ApplicabilityStatus, detailed_message). APPLICABLE if
            platform passes all defined affordances, INAPPLICABLE if it doesn't
            meet all of the provided constraints.
        z"no entitlement affordances checkedentitlementaffordancesZarchitecturesarchz, )r   r0   Zsupported_archesseriesversion)r   r1   kernelZkernelFlavorsZminKernelVersionZflavor)r   r3   Zsupported_kernels)r   r3   Z
min_kernel.z$Could not parse minKernelVersion: %smajorminor )r   entitlementsgetr   r   
APPLICABLEstatic_affordancesr+   r   Zget_platform_infor
   ZMESSAGE_INAPPLICABLE_ARCH_TMPLr"   r   joinZ MESSAGE_INAPPLICABLE_SERIES_TMPLrematchRE_KERNEL_UNAMEgroupZ MESSAGE_INAPPLICABLE_KERNEL_TMPLZ$MESSAGE_INAPPLICABLE_KERNEL_VER_TMPLsplitint
ValueErrorr&   warning)r   entitlement_cfgZerror_messageZfunctorZexpected_resultr/   platformZaffordance_archesZaffordance_seriesr3   Zaffordance_kernelsZaffordance_min_kernelr>   Zinvalid_msgZkernel_majorZkernel_minorZmin_kern_majorZmin_kern_minorr   r   r   r*      s    
 




z"UAEntitlement.applicability_statusc                 C   s   dS )zDisable specific entitlement

        @param silent: Boolean set True to silence print/log of messages

        @return: True on success, False otherwise.
        Nr   )r   r   r   r   r   disable   s    zUAEntitlement.disablec                 C   s>   | j jstjS | j j| ji }|r8|d dr8tjS tjS )z=Return whether the user is entitled to the entitlement or notr.   entitled)r   Zis_attachedr   Z
UNENTITLEDr8   r9   r   r)   )r   rE   r   r   r   r(      s    zUAEntitlement.contract_statusc                 C   sD   | j j| ji }|d}|s$dS t|d}|t kr@dS dS )z<Return entitlement access info as stale and needing refresh.ZexpiresFz%Y-%m-%dT%H:%M:%S.%fZT)r   r8   r9   r   r   strptimeZutcnow)r   Zentitlement_contractZ
expire_strZexpiryr   r   r   r%      s    
zUAEntitlement.is_access_expiredzDict[str, Any])orig_accessdeltasallow_enabler   c                 C   sF  |sdS | di }t|tjk}|sZ|r<t| |d }|rZd|krZ|d dtjfk}|r|  \}}|tjjkr| j	ddr| 
  td| j ntd| j dS | d}|s| d}| d	i }	| jdd}
t|	 d
o|}|
rB|rB|r$tjj| jd}t| |   ntjj| jd}t| dS dS )av  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.
        :raise: UserFacingError when auto-enable fails unexpectedly.
        Tr.   rH   F)r   z.Due to contract refresh, '%s' is now disabled.zgUnable to disable '%s' as recommended during contract refresh. Service is still active. See `ua status`resourceTokenZobligationsenableByDefault)r   )r9   boolr   ZDROPPED_KEYZapply_series_overridesr   r
   r   r    r$   rG   r&   infor   rD   r-   ZMESSAGE_ENABLE_BY_DEFAULT_TMPLr"   r   Z%MESSAGE_ENABLE_BY_DEFAULT_MANUAL_TMPL)r   rJ   rK   rL   Zdelta_entitlementZtransition_to_unentitledr   r#   rM   Zdelta_obligationsr-   rN   msgr   r   r   process_contract_deltas   s`    





z%UAEntitlement.process_contract_deltaszTuple[UserFacingStatus, str]c                 C   s   |   \}}|tjkr tj|fS | jj| j}|sFtj	d
| jfS |d dddkrltj	d
| jfS |  \}}tjjtjtjjtji| }||fS )z4Return (user-facing status, details) for entitlementz{} is not entitledr.   rH   F)r*   r   r:   r   r+   r   r8   r9   r   ZUNAVAILABLEr"   r   r   r
   r   ZENABLEDZACTIVEr    ZINACTIVE)r   Zapplicabilityr,   rE   r   Zexplanationuser_facing_statusr   r   r   rS   >  s*    



  z UAEntitlement.user_facing_statusz$Tuple[status.ApplicationStatus, str]c                 C   s   dS )z
        The current status of application of this entitlement

        :return:
            A tuple of (ApplicationStatus, human-friendly reason)
        Nr   r   r   r   r   r   V  s    z UAEntitlement.application_status)N)F)F)F)F)__name__
__module____qualname__Zhelp_doc_urlpropertyabcabstractmethodstrr   r   r   r;   r   rO   r   r$   r-   r*   rG   r   r(   r%   rR   rS   r   r   r   r   r   r      s>   	U		 Kr   )	metaclass)rX   r   r&   r=   typingr   r   r   r   r   rZ   rO   ZStaticAffordanceImportErrorZuaclientr   r	   r
   r   Zuaclient.statusr   r   r   r?   ABCMetar   r   r   r   r   <module>   s    