
    fw                        d dl Z d dlZd dlZd dlZd dl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 d dlmZ d dl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ddddZ, ejZ                         Z. ej^                   ej`                  e1            Z2ejf                   G d dejh                               Z5 G d de jl                        Z7de8fdZ9	 d9dedee:ef   dee:ef   d e;d!e;d"dfd#Z<	 	 d:ded$ee:ef   d%ee:ef   d e;d!e;d"e	ee;f   fd&Z=d'ej|                  d"ej~                  fd(Z@d) ZAded"ee   fd*ZBded+e:d"ee:ef   fd,ZCded"e;fd-ZDd.ee:e:f   d/ee:e:f   d"eEfd0ZF	 d;d1ee:ef   d2e:d3e:d4ee:   d"eeEee:ef   f   f
d5ZG	 	 d<d$ee:ef   d6ee:   d4ee:   d"dfd7ZHded"e	e5eEf   fd8ZIy)=    N)AnyDictListOptionalTuple)cloudsevent_logger
exceptionshttpmessagessystemutilversion)_enabled_services)_is_attached)UAConfig)ATTACH_FAIL_DATE_FORMAT!CONTRACT_EXPIRY_GRACE_PERIOD_DAYSCONTRACT_EXPIRY_PENDING_DAYS)attachment_data_file)serviceclientz/v1/context/machines/tokenz3/v1/contracts/{contract}/context/machines/{machine}z/v1/resourcesz3/v1/resources/{resource}/context/machines/{machine}z/v1/clouds/{cloud_type}/tokenz3/v1/contracts/{contract}/machine-activity/{machine}z/v1/contractz/v1/magic-attach            )series_overridesseriescloudvariantc                        e Zd ZdZdZdZdZdZy)ContractExpiryStatusr   r   r   r   r   N)__name__
__module____qualname__NONEACTIVEACTIVE_EXPIRED_SOONEXPIRED_GRACE_PERIODEXPIRED     3/usr/lib/python3/dist-packages/uaclient/contract.pyr!   r!   >   s    DFGr+   r!   c                      e Zd ZdZ ej
                  ej                  g d      	 dd       Zde	e
ef   fdZde
de	e
ef   fd	Z ej
                  ej                  g d      d
ej                  fd       Z	 	 dde
de
dee
   dede	e
ef   f
dZd Zde
de	e
ef   fdZde	e
ef   fdZde
fdZ	 dde
de
dee
   de	e
ef   fdZ	 dde
de
dee
   de	fdZd Zy)UAContractClientcontract_url)r   r   r   )retry_sleepsNc                 N   |st        j                  | j                        }| j                         }|j	                  ddj                  |      i       | j                         }|j                         |d<   ||d}t        |      }| j                  t        ||      }|j                  dk(  rt        j                         |j                  dk(  rt        |       |j                  dk7  r0t        j                  t        |j                  |j                   	      |j"                  S )
a}  Requests machine attach to the provided machine_id.

        @param contract_token: Token string providing authentication to
            ContractBearer service endpoint.
        @param machine_id: Optional unique system machine id. When absent,
            contents of /etc/machine-id will be used.

        @return: Dict of the JSON response containing the machine-token.
        Authorization	Bearer {}lastAttachment	machineIdactivityInfo)dataheaders  i     urlcodebody)r   get_machine_idcfgr9   updateformat_get_activity_info	isoformat_support_old_machine_inforequest_urlAPI_V1_ADD_CONTRACT_MACHINEr>   r
   AttachInvalidTokenError_raise_attach_forbidden_messageContractAPIErrorr?   	json_dict)	selfcontract_tokenattachment_dt
machine_idr9   activity_infor8   backcompat_dataresponses	            r,   add_contract_machinez%UAContractClient.add_contract_machineJ   s    ..txx8J,,.););N)KLM//1*7*A*A*C&''G3D9##'ow $ 
 ==C4466]]c!+H5==C--/]]]]  !!!r+   returnc                    | j                         }| j                  t        |d   |d   |d   |d   d      }|j                  dk7  r0t	        j
                  t        |j                  |j                        |j                  S )	z=Requests list of entitlements available to this machine type.architecturer   kernelvirtrW   r   rX   rY   )query_paramsr;   r<   )rD   rG   API_V1_AVAILABLE_RESOURCESr>   r
   rK   r?   rL   )rM   rQ   rS   s      r,   available_resourcesz$UAContractClient.available_resourcesp   s    //1##& -n ='1'1%f-	 $ 
 ==C--.]]]] 
 !!!r+   rN   c                 *   | j                         }|j                  ddj                  |      i       | j                  t        |      }|j
                  dk7  r0t        j                  t        |j
                  |j                        |j                  S )Nr2   r3   r9   r;   r<   )
r9   rB   rC   rG   API_V1_GET_CONTRACT_USING_TOKENr>   r
   rK   r?   rL   )rM   rN   r9   rS   s       r,   get_contract_using_tokenz)UAContractClient.get_contract_using_token   s    ,,.););N)KLM##+W $ 
 ==C--3]]]] 
 !!!r+   instancec                   | j                  t        j                  |j                        |j                        }|j
                  dk7  ry|j                  j                  dd      }|r+t        j                  |       t        j                  |      t        j                  t        |j
                  |j                        | j                  j                  d|j                         |j                  S )	zRequests contract token for auto-attach images for Pro clouds.

        @param instance: AutoAttachCloudInstance for the cloud.

        @return: Dict of the JSON response containing the contract-token.
        )
cloud_type)r8   r;   message )	error_msgr<   zcontract-token)rG   ,API_V1_GET_CONTRACT_TOKEN_FOR_CLOUD_INSTANCErC   rd   identity_docr>   rL   getLOGdebugr
   InvalidProImagerK   r?   rA   write_cache)rM   rb   rS   msgs       r,   %get_contract_token_for_cloud_instancez6UAContractClient.get_contract_token_for_cloud_instance   s     ##8??#.. @  &&	 $ 
 ==C$$((B7C		# 003??--@]]]]  	-x/A/AB!!!r+   machine_tokenresourcerP   	save_filec                 n   |st        j                  | j                        }| j                         }|j	                  ddj                  |      i       t        j                  ||      }| j                  ||      }|j                  dk7  r0t        j                  t        |j                  |j                        |j                  j                  d      r|j                  d   |j                  d<   |r5| j                  j                  dj                  |      |j                         |j                  S )	a  Requests machine access context for a given resource

        @param machine_token: The authentication token needed to talk to
            this contract service endpoint.
        @param resource: Entitlement name.
        @param machine_id: Optional unique system machine id. When absent,
            contents of /etc/machine-id will be used.
        @save_file: If the machine access should be saved on the user machine

        @return: Dict of the JSON response containing entitlement accessInfo.
        r2   r3   )rr   machiner_   r;   r<   expireszmachine-access-{})r   r@   rA   r9   rB   rC   "API_V1_GET_RESOURCE_MACHINE_ACCESSrG   r>   r
   rK   r?   rj   rL   rn   )rM   rq   rr   rP   rs   r9   r=   rS   s           r,   get_resource_machine_accessz,UAContractClient.get_resource_machine_access   s   $ ..txx8J,,.););M)JKL077z 8 
 ##C#9==C--6]]]] 
 	*,4,<,<Y,GHy)HH  #**84h6H6H !!!r+   c                    | j                   j                  j                  }| j                   j                  j	                  d      }t        j                  | j                         }| j                         }t        j                  ||      }| j                         }|j                  ddj                  |      i       | j                  |||      }|j                  dk7  r,t        j                  ||j                  |j                         |j"                  rK| j                   j                  }|j"                  |d<   | j                   j                  j%                  |       y	y	)
zReport current activity token and enabled services.

        This will report to the contracts backend all the current
        enabled services in the system.
        machineTokencontractru   r2   r3   )r9   r8   r;   r<   r7   N)rA   machine_token_filecontract_idrq   rj   r   r@   rD   API_V1_UPDATE_ACTIVITY_TOKENrC   r9   rB   rG   r>   r
   rK   r?   rL   write)rM   r~   rq   rP   request_datar=   r9   rS   s           r,   update_activity_tokenz&UAContractClient.update_activity_token   s&    hh11==..22>B**4884
..0*11 * 2 
 ,,.););M)JKL##C|#L==C--hmm(--   HH22M -5,>,>M.)HH''--m< r+   magic_tokenc                    | j                         }|j                  ddj                  |      i       | j                  t        |      }|j
                  dk(  rt        j                         |j
                  dk(  rt        j                         |j
                  dk7  r0t        j                  t        |j
                  |j                        |j                  S )zRequest magic attach token info.

        When the magic token is registered, it will contain new fields
        that will allow us to know that the attach process can proceed
        r2   r3   r_   r:     r;   r<   )r9   rB   rC   rG   "API_V1_GET_MAGIC_ATTACH_TOKEN_INFOr>   r
   MagicAttachTokenErrorMagicAttachUnavailablerK   r?   rL   rM   r   r9   rS   s       r,   get_magic_attach_token_infoz,UAContractClient.get_magic_attach_token_info   s     ,,.););K)HIJ##. $ 
 ==C2244==C3355==C--6]]]]  !!!r+   c                 .   | j                         }| j                  t        |d      }|j                  dk(  rt	        j
                         |j                  dk7  r0t	        j                  t        |j                  |j                        |j                  S )z)Create a magic attach token for the user.POSTr9   methodr   r;   r<   )	r9   rG   API_V1_NEW_MAGIC_ATTACHr>   r
   r   rK   r?   rL   )rM   r9   rS   s      r,   new_magic_attach_tokenz'UAContractClient.new_magic_attach_token  s    ,,.### $ 
 ==C3355==C--+]]]]  !!!r+   c                    | j                         }|j                  ddj                  |      i       | j                  t        |d      }|j
                  dk(  rt        j                         |j
                  dk(  rt        j                         |j
                  dk(  rt        j                         |j
                  dk7  r0t        j                  t        |j
                  |j                  	      y
)z)Revoke a magic attach token for the user.r2   r3   DELETEr   i  r:   r   r;   r<   N)r9   rB   rC   rG   API_V1_REVOKE_MAGIC_ATTACHr>   r
    MagicAttachTokenAlreadyActivatedr   r   rK   r?   r   s       r,   revoke_magic_attach_tokenz*UAContractClient.revoke_magic_attach_token+  s    ,,.););K)HIJ##& $ 
 ==C==??==C2244==C3355==C--.]]]]   r+   r~   c           
      >   |st        j                  | j                        }| j                         }|j	                  ddj                  |      i       t        j                  ||      }| j                         }| j                  |d||d   |d   |d   |d   d	
      }|j                  dk7  r,t        j                  ||j                  |j                        |j                  j                  d      r|j                  d   |j                  d<   |j                  S )a|  Get the updated machine token from the contract server.

        @param machine_token: The machine token needed to talk to
            this contract service endpoint.
        @param contract_id: Unique contract id provided by contract service
        @param machine_id: Optional unique system machine id. When absent,
            contents of /etc/machine-id will be used.
        r2   r3   r{   GETrW   r   rX   rY   rZ   )r   r9   r[   r;   r<   rv   )r   r@   rA   r9   rB   rC   API_V1_GET_CONTRACT_MACHINErD   rG   r>   r
   rK   r?   rj   rL   )rM   rq   r~   rP   r9   r=   rQ   rS   s           r,   get_contract_machinez%UAContractClient.get_contract_machineB  s    ..txx8J,,.););M)JKL)00  1 
 //1## -n ='1'1%f-		 $ 

 ==C--hmm(--  	*,4,<,<Y,GHy)!!!r+   c                 8   |st        j                  | j                        }| j                         }|j	                  ddj                  |      i       || j                         d}t        |      }t        j                  ||      }| j                  ||d|      }|j                  dk7  r,t        j                  ||j                  |j                        |j                  j                  d	      r|j                  d	   |j                  d	<   |j                  S )
a  Request machine token refresh from contract server.

        @param machine_token: The machine token needed to talk to
            this contract service endpoint.
        @param contract_id: Unique contract id provided by contract service.
        @param machine_id: Optional unique system machine id. When absent,
            contents of /etc/machine-id will be used.

        @return: Dict of the JSON response containing refreshed machine-token
        r2   r3   r5   r{   r   )r9   r   r8   r;   r<   rv   )r   r@   rA   r9   rB   rC   rD   rF   API_V1_UPDATE_CONTRACT_MACHINErG   r>   r
   rK   r?   rj   rL   )	rM   rq   r~   rP   r9   r8   rR   r=   rS   s	            r,   update_contract_machinez(UAContractClient.update_contract_machinem  s     ..txx8J,,.););M)JKL# 335
 4D9,33 * 4 
 ##o $ 
 ==C--hmm(--  	*,4,<,<Y,GHy)!!!r+   c                    t        j                         j                  t        j                         j                  t        j                         j
                  t        j                         t        j                         t        j                         t        j                         d}t        | j                        j                  rt        | j                        j                  }t!        j"                         }| j                  j$                  j&                  xs t        j(                  | j                        | j                  j$                  j*                  |D cg c]  }|j,                   c}|D ci c]%  }|j.                  r|j,                  |j0                  ' c}|r|j2                  j5                         ndd}ni }i ||S c c}w c c}w )z9Return a dict of activity info data for contract requests)distributionrX   r   rW   desktoprY   clientVersionN)
activityIDactivityToken	resourcesresourceVariantsr4   )r   get_release_infor   get_kernel_infouname_releaser   get_dpkg_arch
is_desktopget_virt_typer   get_versionr   rA   is_attachedr   enabled_servicesr   readr}   activity_idr@   activity_tokennamevariant_enabledvariant_nameattached_atrE   )rM   machine_infor   attachment_dataservicerQ   s         r,   rD   z#UAContractClient._get_activity_info  sv    #335BB,,.<<--/66"002((*((*$002
 !--0:KK2779O"hh99EE 3((2!%!<!<!K!K:JKwgllK $4%.. LL'"6"66% # #2"="="G"G"IM M


 	
 L%s   G
5*G
N)NT)r"   r#   r$   cfg_url_base_attrr   retrysockettimeoutrT   r   strr   r]   ra   r   AutoAttachCloudInstancerp   r   boolrx   r   r   r   r   r   r   rD   r*   r+   r,   r.   r.   G   s   &TZZY78<#" 8#"J"T#s(^ "("s "tCH~ " TZZY7"!99" 8"B %)&"&" &" SM	&"
 &" 
c3h&"P$=L"s "tCH~ "2"S#X "(S 6 %)	)")" )" SM	)"
 
c3h)"^ %)	&"&" &" SM	&"
 
&"P$
r+   r.   request_bodyc           	         | j                  di       }| j                  d      ||j                  d      |j                  d      |j                  d      |j                  d      dt        j                         j                  dd	S )
a?  
    Transforms a request_body that has the new activity_info into a body that
    includes both old and new forms of machineInfo/activityInfo

    This is necessary because there may be old ua-airgapped contract
    servers deployed that we need to support.
    This function is used for attach and refresh calls.
    r7   r6   rW   r   rX   r   Linux)r   rX   r   typerelease)r6   r7   rW   os)rj   r   r   r   )r   rQ   s     r,   rF   rF     s     !$$^R8M "%%k2%%)).9)--n=#''1#''1 ..088
	 r+   rA   past_entitlementsnew_entitlementsallow_enabler   rU   c                 Z   ddl m} d}d}g } ||       D ]I  }		 ||	   }
g }	 t        | |j	                  |	i       |
||      \  }}|s2|s5t
        j                  |	       K t
        j                  |       |r4t        j                  |D 	cg c]  }	|	t         j"                  f c}		      |r4t        j$                  |D 	cg c]  }	|	t         j&                  f c}		      y# t        $ r Y w xY w# t        j                  $ rJ}t        j                  |       d}|j                  |	       t        j                  d|	|
       Y d}~5d}~wt        $ rJ}t        j                  |       d}|j                  |	       t        j                  d|	|
       Y d}~d}~ww xY wc c}	w c c}	w )
a  Iterate over all entitlements in new_entitlement and apply any delta
    found according to past_entitlements.

    :param cfg: UAConfig instance
    :param past_entitlements: dict containing the last valid information
        regarding service entitlements.
    :param new_entitlements: dict containing the current information regarding
        service entitlements.
    :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.
    :param series_overrides: Boolean set True if series overrides should be
        applied to the new_access dict.
    r   )entitlements_enable_orderF)rA   orig_access
new_accessr   r   Tz+Failed to process contract delta for %s: %rNz5Unexpected error processing contract delta for %s: %r)failed_services)uaclient.entitlementsr   KeyErrorprocess_entitlement_deltarj   eventservice_processedr
   UbuntuProErrorrk   	exceptionappenderror	Exceptionservices_failedAttachFailureUnknownErrorr   UNEXPECTED_ERRORAttachFailureDefaultServices!E_ATTACH_FAILURE_DEFAULT_SERVICES)rA   r   r   r   r   r   delta_errorunexpected_errorr   r   new_entitlementdeltasservice_enabledes                 r,   process_entitlements_deltar     s   * @K O)#. %.	.t4O 	.&?-11$;*)!1'#FO8 6''-K%.L 
/*22>M6:x001
 	

 
55 , xAAB
 	
 
U  		 (( 	MM!K""4(II= 
  	MM!#""4(MMG 		"s@   C##C2F#F(#	C/.C/2F ?E

F ?FF r   r   c                 <   ddl m} |rt        |       t        j                  ||      }d}|r|j                  di       j                  d      }|s!|j                  di       j                  d      }|st        j                  ||      |j                  di       j                  di       j                  d	d
      }		  || ||	      }
 |
| |      }|j                  |||      }||fS # t        j                  $ r}t        j                  d|       |d}~ww xY w)a,  Process a entitlement access dictionary deltas if they exist.

    :param cfg: UAConfig instance
    :param orig_access: Dict with original entitlement access details before
        contract refresh deltas
    :param new_access: Dict with updated entitlement access details after
        contract refresh
    :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.
    :param series_overrides: Boolean set True if series overrides should be
        applied to the new_access dict.

    :raise UbuntuProError: on failure to process deltas.
    :return: A tuple containing a dict of processed deltas and a
             boolean indicating if the service was fully processed
    r   )entitlement_factoryFentitlementr   )orignewentitlementsobligationsuse_selectorrf   )rA   r   r   z3Skipping entitlement deltas for "%s". No such classN)rA   
assume_yesr   )r   r   apply_contract_overridesr   get_dict_deltasrj   r
    InvalidContractDeltasServiceTypeEntitlementNotFoundErrorrk   rl   process_contract_deltas)rA   r   r   r   r   r   r   retr   r   ent_clsexcr   s                r,   r   r   *  s&   0 : ,!!+z:F
C}b155f=::mR044V<D== j 
 NN>2.S#S$ 	
	)cgNG #,?11l 2 
 3; 22 	IIEt I		s   >C+ +D>DDrS   c                    | j                   j                  d      }|r|d   }|d   }|dk(  rB|d   j                  t              }t	        j
                  |||d   j                  d            |dk(  rB|d   j                  t              }t	        j                  |||d   j                  d      	      |d
k(  rt	        j                  |      t	        j                         )Ninfo
contractIdreasonzno-longer-effectivetimez%m-%d-%Y)r~   datecontract_expiry_dateznot-effective-yet)r~   r   contract_effective_dateznever-effective)r~   )	rL   rj   strftimer   r
   AttachForbiddenExpiredAttachForbiddenNotYetAttachForbiddenNeverAttachExpiredToken)rS   r   r~   r   r   s        r,   rJ   rJ   f  s     !!&)D<(h**<(()@AD33'%)&\%:%::%F	  **<(()@AD22'(,V(=(=j(I	  ((11kJJ

'
'
))r+   c                    | j                   j                  }| j                  }|d   }|d   d   d   }t        |       }|j	                  ||      }| j                   j                  |       t        j                  j                          |j                  di       j                  dt        j                  |             }| j                  d|       t        | || j                   j                  d	       y
)a  Request contract refresh from ua-contracts service.

    :param cfg: Instance of UAConfig for this machine.

    :raise UbuntuProError: on failure to update contract or error processing
        contract deltas
    :raise ConnectivityError: On failure during a connection
    rz   machineTokenInfocontractInfoid)rq   r~   r6   z
machine-idFr   N)r}   r   rq   r.   r   r   r   r@   cache_clearrj   rn   r   )rA   orig_entitlements
orig_tokenrq   r~   contract_clientresprP   s           r,   refreshr    s     ..;;""J~.M/0@FK&s+O22# 3 D   &
%%',b155V**3/J OOL*-++	r+   c                 \    t        |       }|j                         }|j                  dg       S )zDQuery available resources from the contract server for this machine.r   )r.   r]   rj   )rA   clientr   s      r,   get_available_resourcesr    s+    c"F**,I==b))r+   tokenc                 :    t        |       }|j                  |      S )z/Query contract information for a specific token)r.   ra   )rA   r  r  s      r,   get_contract_informationr    s    c"F**511r+   c                    | j                   }| j                  j                  }|j                  dd      }|j                  di       j                  di       j                  dd       }|syt	        |       }|j                  ||      }|j                  di       j                  di       j                  dd       }|r|n| j                  j                  }| j                  j                  |k7  ry| j                  j                  |      }	t        |	j                               D ]/  \  }
}t        j                  |j                  |
i       |      }|s/ y y)	Nrz   rf   r  r  r  FeffectiveToT)rq   r}   r   rj   r.   r   contract_expiry_datetimeget_entitlements_from_tokensorteditemsr   r   )rA   r	  r  rq   r~   r
  r  resp_expiry
new_expirycurr_entitlementsr   r   r   s                r,   is_contract_changedr    sO   ""J..;;NN>26M)2.	^R	 	T4 
 &s+O//{KD#R(	^R	 	]D	!   	##<< 
 66*D..JJ "((9(?(?(A!B o%%!!$+_
  r+   override_selectorselector_valuesc                 ~    d}| j                         D ]'  \  }}||f|j                         vr y|t        |   z  }) |S )Nr   )r  OVERRIDE_SELECTOR_WEIGHTS)r  r  override_weightselectorvalues        r,   _get_override_weightr$    sV     O,224 ?%eO$9$9$;;4X>>?
 r+   r   series_namerd   r   c                     i }||d}|r||d<   | j                  di       j                  |i       }|r||t        d   <   t        j                  | j	                  dg             }|D ]%  }t        |j                  d      |      }	|	s!|||	<   ' |S )N)r   r   r   r   r   	overridesr"  )popr   copydeepcopyrj   r$  )
r   r%  rd   r   r'  r  r   general_overridesoverrideweights
             r,   _select_overridesr.    s     I!,zBO%,	""x488bI  	%&89	
 kook2&FG% )%LL$o
  (If) r+   r   c                    ddl m} t        t        | t              d| v g      st        dj                  |             |t        j                         j                  n|} |       \  }}| j                  di       }t        ||||      }t        |j                               D ][  \  }	}
|
j                         D ]C  \  }}| d   j                  |      }t        |t              r|j                  |       <|| d   |<   E ] y)a  Apply series-specific overrides to an entitlement dict.

    This function mutates orig_access dict by applying any series-overrides to
    the top-level keys under 'entitlement'. The series-overrides are sparse
    and intended to supplement existing top-level dict values. So, sub-keys
    under the top-level directives, obligations and affordance sub-key values
    will be preserved if unspecified in series-overrides.

    To more clearly indicate that orig_access in memory has already had
    the overrides applied, the 'series' key is also removed from the
    orig_access dict.

    :param orig_access: Dict with original entitlement access details
    r   )get_cloud_typer   z?Expected entitlement access dict. Missing "entitlement" key: {}N)uaclient.clouds.identityr0  all
isinstancedictRuntimeErrorrC   r   r   r   rj   r.  r  r  rB   )r   r   r   r0  r%  rd   _orig_entitlementr'  _weightoverrides_to_applykeyr#  currents                 r,   r   r     s
   & 8
;-}/KLM&%
 	
 -3N!((  #$MJ"}b9!+z7I (.ioo.?'@ 	8##,224 	8JC!-044S9G'4( u% 38M*3/	8	8r+   c                    t        |       j                  st        j                  dfS t        }t
        }| j                  j                  }|(t        j                  d       t        j                  | fS d|cxk  r|k  rn nt        j                  |fS | |cxk  rdk  rn nt        j                  |fS || k  rt        j                  |fS t        j                  |fS )z/Return a tuple [ContractExpiryStatus, num_days]r   z:contract effectiveTo date is null - assuming it is expired)r   r   r!   r%   r   r   r}   contract_remaining_daysrk   warningr)   r'   r(   r&   )rA   grace_periodpending_expiryremaining_dayss       r,   get_contract_expiry_statusrB  2  s     ((#((!++4L1N++CCN H	
 $++l]::N,n,#77GG
.	,1	,#88.HH	<-	'#++^;;&&66r+   )T)FTr   )NN)Jr)  enumloggingr   typingr   r   r   r   r   uaclientr   r	   r
   r   r   r   r   r   -uaclient.api.u.pro.status.enabled_services.v1r   (uaclient.api.u.pro.status.is_attached.v1r   uaclient.configr   uaclient.defaultsr   r   r   uaclient.files.state_filesr   uaclient.httpr   rH   r   r   r\   rw   rh   r   r`   r   r   r   r   get_event_loggerr   	getLoggerreplace_top_level_logger_namer"   rk   uniqueEnumr!   UAServiceClientr.   r4  rF   r   r   r   r   HTTPResponseNamedMessagerJ   r  r  r  r  intr$  r.  r   rB  r*   r+   r,   <module>rV     s8       3 3	 	 	 L A $ 
 < ' ; 9  :  - 9 # 0O ,9  #1 %7 ", /  	  	&%%'g:::8DE 499  r
}44 r
jD @ "P
	P
CH~P
 38nP
 	P

 P
 
P
n !9	9c3h9 S#X9 	9
 9 4:9x***:D* *d4j *2( 23 24S> 2#X #$ #L	CH~	8<S#X		  "	c3h  c]	
 
#tCH~
> !!.8c3h.8SM.8 c].8 
	.8b7	7
$%7r+   