
    f=                        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	 d dl
mZmZmZmZmZ d dlmZmZ d dlmZ d dlmZ  e       Zdedefd	Z ej6                   ee            Z G d
 dej<                        Z G d dej@                        Z!d Z"	 d8deeef   deeef   dedeeef   fdZ#dg fdedee   defdZ$	 d9dede%de%de%fdZ&deeef   dede%fdZ'g dZ(e(fdee   defdZ)d ee   de%fd!Z*d"ede j                   fd#Z+d$edefd%Z,d& Z-d' Z.d(d)d*d+d,d-Z/d.edefd/Z0d0ee   dee   fd1Z1de%fd2Z2d3ed4edefd5Z3d6ee   fd7Z4y):    Nwraps)AnyDictListOptionalUnion)
exceptionsmessages)CONFIG_FIELD_ENVVAR_ALLOWLIST)MessagingOperationsnamereturnc                 \    | dk(  ry| j                  d      }d|d<   dj                  |      S )z1Replace the name of the root logger from __name__ .	ubuntupror   )splitjoin)r   namess     //usr/lib/python3/dist-packages/uaclient/util.pyreplace_top_level_logger_namer      s0    rzJJsOEE!H88E?    c                   "     e Zd ZdZ fdZ xZS )DatetimeAwareJSONEncoderzBA json.JSONEncoder subclass that writes out isoformat'd datetimes.c                 v    t        |t        j                        r|j                         S t        |   |      S N)
isinstancedatetime	isoformatsuperdefault)selfo	__class__s     r   r"   z DatetimeAwareJSONEncoder.default"   s.    a**+;;= wq!!r   )__name__
__module____qualname____doc__r"   __classcell__r%   s   @r   r   r      s    L" "r   r   c                   2     e Zd ZdZ fdZed        Z xZS )DatetimeAwareJSONDecodera,  
    A JSONDecoder that parses some ISO datetime strings to datetime objects.

    Important note: the "some" is because we seem to only be able extend
    Python's json library in a way that lets us convert string values within
    JSON objects (e.g. '{"lastModified": "2019-07-25T14:35:51"}'). Strings
    outside of JSON objects (e.g. '"2019-07-25T14:35:51"') will not be passed
    through our decoder.

    (N.B. This will override any object_hook specified using arguments to it,
    or used in load or loads calls that specify this as the cls.)
    c                 f    d|v r|j                  d       t        |   |d| j                  i| y )Nobject_hook)popr!   __init__r/   )r#   argskwargsr%   s      r   r1   z!DatetimeAwareJSONDecoder.__init__6   s4    F"JJ}%$GD,<,<GGr   c                     | j                         D ]'  \  }}t        |t              s	 t        |      }|| |<   ) | S # t        $ r |}Y w xY wr   )itemsr   strparse_rfc3339_date
ValueError)r$   keyvalue	new_values       r   r/   z$DatetimeAwareJSONDecoder.object_hook;   s_    '') 		#JC%%& 2!I ##		# 	 " & %I&s   =A
A)r&   r'   r(   r)   r1   staticmethodr/   r*   r+   s   @r   r-   r-   (   s"    H
  r   r-   c                       fd}|S )a  Decorator to retry on exception for retry_sleeps.

    @param retry_sleeps: List of sleep lengths to apply between
       retries. Specifying a list of [0.5, 1] tells subp to retry twice
       on failure; sleeping half a second before the first retry and 1 second
       before the second retry.
    @param exception: The exception class to catch and retry for the provided
       retry_sleeps. Any other exception types will not be caught by the
       decorator.
    c                 4     t                fd       }|S )Nc                      j                         }	 	  | i |S # $ r[}|s|t        j                  dt        |      t	        |             t        j                  |j                  d             Y d }~nd }~ww xY wm)Nz%s: Retrying %d more times.r   )copyLOGdebugr6   lentimesleepr0   )r2   r3   sleepse	exceptionfretry_sleepss       r   	decoratorz)retry.<locals>.wrapper.<locals>.decoratorW   sz    !&&(F.d-f--  .!II5s1vs6{ JJvzz!}--. s    A<AA77A<r   )rI   rK   rH   rJ   s   ` r   wrapperzretry.<locals>.wrapperV   s!    	q	. 
	. r    )rH   rJ   rL   s   `` r   retryrN   J   s    " Nr   r   	orig_dictnew_dictpathc                    i }| j                         D ]  \  }}|j                  |t              }|s|n|dz   |z   }t        |t              r(||v rt        |||   |      }|sP|||<   Vt        ||<   `||k7  sft        j                  d|t        |             |||<    |j                         D ]  \  }}|| vs|||<    |S )z<Return a dictionary of delta between orig_dict and new_dict.r   )rQ   z'Contract value for '%s' changed to '%s')	r5   getDROPPED_KEYr   dictget_dict_deltasrA   rB   r6   )	rO   rP   rQ   deltasr9   r:   r;   key_path	sub_deltas	            r   rV   rV   j   s     Foo' $
ULLk2	"3s
S(8eT"h+8C=x	 "+F3K)siII9I
 $F3K%$& nn&  
UiF3K  Mr   msgvalid_choicesc           
      >   ddl m} |j                         }d}dj                  |dj	                  |D cg c]  }|j                          c}            }	 |j                  |        t        d      j                         }||v r	 |S |j                  |       Cc c}w )aG  Interactive prompt message, returning a valid choice from msg.

    Expects a structured msg which designates choices with square brackets []
    around the characters which indicate a valid choice.

    Uppercase and lowercase responses are allowed. Loop on invalid choices.

    :return: Valid response character chosen.
    r   event_loggerr   z{} is not one of: {}z, z> )	uaclientr^   get_event_loggerformatr   upperinfoinputlower)rZ   r[   r^   eventr:   choice	error_msgs          r   prompt_choicesri      s     &))+EE&--tyy}EV&,,.EFI 

3d!!#M!L 	

9  Fs   B
assume_yesr"   c                     |ry| st         j                  } t        |       j                         j	                         }|dk(  r|S |dv ryy)a  
    Display a confirmation prompt, returning a bool indicating the response

    :param msg: String custom prompt text to emit from input call.
    :param assume_yes: Boolean set True to skip confirmation input and return
        True.
    :param default: Boolean to return when user doesn't enter any text

    This function will only prompt a single time, and defaults to "no" (i.e. it
    returns False).
    Tr   )yyesF)r   PROMPT_YES_NOrd   re   strip)rZ   rj   r"   r:   s       r   prompt_for_confirmationrp      sM     $$#J$$&E{r   configpath_to_valuec                 0   | }i }|j                  d      }|d   }|D ]-  }||k(  rd}t        |t              r|j                  ||      }- y t	        |      }|j                         dk(  ry|j                         dk(  ryt        j                  |d|      )	aJ  Check if value parameter can be translated into a boolean 'True' value.

    @param config: A config dict representing
                   /etc/ubuntu-advantange/uaclient.conf
    @param path_to_value: The path from where the value parameter was
                          extracted.
    @return: A boolean value indicating if the value paramater corresponds
             to a 'True' boolean value.
    @raises exceptions.UbuntuProError when the value provide by the
            path_to_value parameter can not be translated into either
            a 'False' or 'True' boolean value.
    r   falseFtrueTzboolean string: true or false)rr   expected_valuer:   )r   r   rU   rS   r6   re   r
   InvalidBooleanConfigValue)rq   rr   r:   default_valuepaths
leaf_valuer9   	value_strs           r   is_config_value_truer}      s     EM$ErJ *#MeT"IIc=1E E
IF"		g	%22':
 	
r   )z(Bearer )[^\']+z(\'attach\', \')[^\']+z(\'machineToken\': \')[^\']+(\'token\': \')[^\']+z((\'X-aws-ec2-metadata-token\': \')[^\']+z*(.*\[PUT\] response.*api/token,.*data: ).*z(https://bearer:)[^\@]+z1(/snap/bin/canonical-livepatch\s+enable\s+)[^\s]+z>(Contract\s+value\s+for\s+'resourceToken'\s+changed\s+to\s+).*z(\'resourceToken\': \')[^\']+z(\'contractToken\': \')[^\']+zF(https://contracts.canonical.com/v1/resources/livepatch\?token=)[^\s]+z(\"identityToken\": \")[^\"]+zT(response:\s+http://metadata/computeMetadata/v1/instance/service-accounts.*data: ).*r~   z(\'userCode\': \')[^\']+z(\'magic_token=)[^\']+z(--registration-key=\")[^\"]+z(--registration-key=\')[^\']+z(--registration-key=)[^ ]+z(--registration-key \")[^\"]+z(--registration-key \')[^\']+z(--registration-key )[^\s]+z(-p \")[^\"]+z(-p \')[^\']+z(-p )[^\s]+redact_regexsc                 F    | }|D ]  }t        j                  |d|      } |S )z4Redact known sensitive information from log content.z\g<1><REDACTED>)resub)logr   redacted_logredact_regexs       r   redact_sensitive_logsr     s3     L% Nvvl,>MNr   msg_opsc                     ddl m} |j                         }| sy| D ]3  }t        |t              r|j                  |       %|\  }} |di |r3 y y)ah  Emit messages to the console for user interaction

    :param msg_op: A list of strings or tuples. Any string items are printed.
        Any tuples will contain a callable and a dict of args to pass to the
        callable. Callables are expected to return True on success and
        False upon failure.

    :return: True upon success, False on failure.
    r   r]   TFrM   )r_   r^   r`   r   r6   rc   )r   r^   rf   msg_opfunctorr2   s         r   handle_message_operationsr     sZ     &))+E fc"JJv"MGT?T? r   dt_strc                     t        j                  dd|       }t        j                  dd|      }|j                  dd      }t        j                  dd|      }t        j                  j	                  |d	      S )
aT  
    Parse a datestring in rfc3339 format. Originally written for compatibility
    with golang's time.MarshalJSON function. Also handles output of pythons
    isoformat datetime method.

    This drops subseconds.

    :param dt_str: a date string in rfc3339 format

    :return: datetime.datetime object of time represented by dt_str
    z(\d{2}:\d{2}:\d{2})\.\d+z\g<1>z(\d{2}:\d{2}:\d{2})$z\g<1>ZZz+00:00z(-|\+)(\d{2}):(\d{2})$z\g<1>\g<2>\g<3>z%Y-%m-%dT%H:%M:%S%z)r   r   replacer   strptime)r   dt_str_without_subsecondsdt_str_with_zdt_str_without_zdt_str_with_pythonish_tzs        r   r7   r7   (  s    ( !##Xv! FF,EM %,,S(;  "vv!#57G  %% "7 r   messagec                 ~   t         j                  j                  *dt         j                  j                  j                         vrx| j	                  dd      } | j	                  t
        j                  dz   d      } | j	                  t
        j                  dz   d      } | j                  dd      j                         } | S )z}
    Verify if the system can output unicode characters and if not,
    remove those characters from the message string.
    zUTF-8u   —- r   asciiignore)
sysstdoutencodingrb   r   r   OKGREEN_CHECKFAIL_Xencodedecode)r   s    r   handle_unicode_charactersr   _  s     	

##**--3355
 //(C0
 //("8"83">C//(//C"7< ..(3::<Nr   c                      t         j                  j                         D  ci c]4  \  } }| j                         t        v s| j                  d      s| dk(  r| |6 c}} S c c}} w )NUA_FEATURESUA_CONFIG_FILE)osenvironr5   re   r   
startswith)kvs     r   get_pro_environmentr   y  s]     JJ$$&Aq77955<<&  	 	
1  s   9Ac                 n   d }|j                         D ]  \  }}| j                  |      }t        |t              r t        |t              rt	        | |   |       Gt        |t
              rDt        |t
              r4t        |      r"t        |d   t              r || |   ||       	 || |<   || |<    y)a  Merge the contents of overlay dict into base_dict not only on top-level
    keys, but on all on the depths of the overlay_dict object. For example,
    using these values as entries for the function:

    base_dict = {"a": 1, "b": {"c": 2, "d": 3}}
    overlay_dict = {"b": {"c": 10}}

    Should update base_dict into:

    {"a": 1, "b": {"c": 10, "d": 3}}

    @param base_dict: The dict to be updated
    @param overlay_dict: The dict with information to be added into base_dict
    c                    dddd}g }|j                  |      }|D ]]  }d}t        |       D ]7  \  }}	|	j                  |      |j                  |      k(  s*t        |	|       d}9 |rM|j                  |       _ | j	                  |       y )Nr   typeselector)availableResourcesresourceEntitlements	overridesFT)rS   	enumeratedepth_first_merge_overlay_dictappendextend)
base_valuesoverlay_valuesr9   merge_id_key_mapvalues_to_appendid_keyoverlay_valuewas_replacedbase_value_idx
base_values
             r   update_dict_listz8depth_first_merge_overlay_dict.<locals>.update_dict_list  s    "($*#

 !%%c*+ 	7M L.7.D (*
>>&)]->->v-FF2:}M#'L(
   ''6	7 	+,r   r   )r9   N)r5   rS   r   rU   r   listrC   )	base_dictoverlay_dictr   r9   r:   r   s         r   r   r     s     -( #((* #
U]]3'
j$'Jud,C*9S>5A
D)j.E::jmT#B 3C@E "'	#"IcN#r   amd64i386ppc64elarm64armhf)x86_64i686ppc64leaarch64armv7larchc                 N    | j                         }t        j                  ||      S r   )re   ARCH_ALIASESrS   )r   
arch_lowers     r   standardize_arch_namer     s     JJ
33r   archesc                     t               }| D ]  }|j                  t        |              t        t	        |            S r   )setaddr   sortedr   )r   deduplicated_archesr   s      r   deduplicate_archesr     s>    % = 5d ;<=$*+,,r   c                  0    t        j                         dk(  S )Nr   )r   getuidrM   r   r   we_are_currently_rootr     s    99;!r   filenamenew_extensionc                 V    t         j                  j                  |       \  }}|dz   |z   S )Nr   )r   rQ   splitext)r   r   r   
_extensions       r   set_filename_extensionr     s*    ww''1D*#:%%r   package_listc                     t        dj                  t        j                  dj                  |       ddddd                   t        d       y )N
r   P   Fz  )widthbreak_long_wordsbreak_on_hyphensinitial_indentsubsequent_indentr   )printr   textwrapwrap)r   s    r   print_package_listr     sH     
		MM&!&!&#"&		
 
"Ir   )r   )r   FF)5r   jsonloggingr   r   r   r   rD   	functoolsr   typingr   r   r   r   r	   r_   r
   r   uaclient.defaultsr   uaclient.typesr   objectrT   r6   r   	getLoggerr&   rA   JSONEncoderr   JSONDecoderr-   rN   rV   ri   boolrp   r}   REDACT_SENSITIVE_LOGSr   r   r7   r   r   r   r   r   r   r   r   r   rM   r   r   <module>r      s<      	 	 
    3 3 ) ; .h   g5h?@"t// "t// DB FHCH~)-c3h?B	#s(^< !R  c C 6 >C	#6:	4$
c3h $
 $
 $
N @ %:S	)*	84s 4x'8'8 4ns s 41#j 4 4 4
-tCy -T#Y -t &S & & &
s)r   