o Hcf= @sjddlZddlZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z m Z m Z mZmZmZddlmZmZddlmZddlmZeZdedefd d ZeeeZGd d d ejZ Gd ddej!Z"ddZ# dKde ee fde ee fdede ee ffddZ$dgfdedeedefddZ% dLdede&de&de&fddZ'd e ee fd!ede&fd"d#Z(gd$Z)e)fd%eedefd&d'Z*d(eed)e egdfde&fd*d+Z+d,edejfd-d.Z,d/edefd0d1Z-d2d3Z.d4d5Z/d6d7d8d9d:d;Z0dZ1d?eedeefd@dAZ2de&fdBdCZ3dDedEedefdFdGZ4dHeefdIdJZ5dS)MNwraps)AnyCallableDictListOptionalUnion) exceptionsmessages)CONFIG_FIELD_ENVVAR_ALLOWLIST)MessagingOperationsnamereturncCs(|dkrdS|d}d|d<d|S)z1Replace the name of the root logger from __name__. ubuntupror)splitjoin)rnamesr//usr/lib/python3/dist-packages/uaclient/util.pyreplace_top_level_logger_names   rcs eZdZdZfddZZS)DatetimeAwareJSONEncoderzBA json.JSONEncoder subclass that writes out isoformat'd datetimes.cs t|tjr |St|SN) isinstancedatetime isoformatsuperdefault)selfo __class__rrr"s  z DatetimeAwareJSONEncoder.default)__name__ __module__ __qualname____doc__r __classcell__rrr"rrsrcs,eZdZdZfddZeddZZS)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.) cs.d|vr |dtj|d|ji|dS)N object_hook)popr__init__r*)r argskwargsr"rrr,6s z!DatetimeAwareJSONDecoder.__init__c CsL|D]\}}t|tr#zt|}Wn ty|}Ynw|||<q|Sr)itemsrstrparse_rfc3339_date ValueError)r!keyvalue new_valuerrrr*;s  z$DatetimeAwareJSONDecoder.object_hook)r$r%r&r'r, staticmethodr*r(rrr"rr)(s  r)csfdd}|S)aDecorator 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. cstfdd}|S)Nc sp} z|i|WSy6}z|s|tdt|t|t|dWYd}~nd}~wwq)NTz%s: Retrying %d more times.r)copyLOGdebugr0lentimesleepr+)r-r.sleepse) exceptionf retry_sleepsrr decoratorWsz)retry..wrapper..decoratorr)r@rBr?rA)r@rwrapperVs zretry..wrapperr)r?rArDrrCrretryJs rEr orig_dictnew_dictpathc Csi}|D]C\}}||t}|s|n|d|}t|tr8||vr3t||||d}|r2|||<qt||<q||krItd|t||||<q|D] \}}||vrZ|||<qN|S)zsz"prompt_choices..Tz> )uaclientrRget_event_loggerformatrinfoinputlower)rPrQrReventr4 error_msgrrrprompt_choicess    r_F assume_yesrcCs>|rdS|s tj}t|}|dkr|S|dvrdSdS)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)yyesF)r PROMPT_YES_NOr[r\strip)rPr`rr4rrrprompt_for_confirmationsreconfig path_to_valuecCs|}i}|d}|d}|D]}||krd}t|tr#|||}qdSt|}|dkr2dS|dkr:dStj|d|d) aJCheck 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. rfalseFtrueTzboolean string: true or false)rgexpected_valuer4)rrrKrIr0r\r InvalidBooleanConfigValue)rfrgr4 default_valuepaths leaf_valuer3 value_strrrris_config_value_trues(     rq)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: ).*rrz(\'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_regexscCs |}|D] }t|d|}q|S)z4Redact known sensitive information from log content.z\g<1>)resub)logrs redacted_log redact_regexrrrredact_sensitive_logssrymsg_opsprint_fncCsF|sdS|D]}t|tr||q|\}}|di|s dSqdS)ahEmit 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. TFNr)rr0)rzr{msg_opfunctorr-rrrhandle_message_operations s   r~dt_strcCsDtdd|}tdd|}|dd}tdd|}tj|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>ZZz+00:00z(-|\+)(\d{2}):(\d{2})$z\g<1>\g<2>\g<3>z%Y-%m-%dT%H:%M:%S%z)rtrureplacerstrptime)rdt_str_without_subseconds dt_str_with_zdt_str_without_zdt_str_with_pythonish_tzrrrr1&s  r1messagecCs`tjjdusdtjjvr.|dd}|tjdd}|tjdd}|dd }|S) z} Verify if the system can output unicode characters and if not, remove those characters from the message string. NzUTF-8u—- rasciiignore) sysstdoutencodingrSrr OKGREEN_CHECKFAIL_Xencodedecode)rrrrhandle_unicode_characters]s  rcCsddtjDS)NcSs4i|]\}}|tvs|ds|dkr||qS) UA_FEATURESUA_CONFIG_FILE)r\r startswith)rTkvrrr xs z'get_pro_environment..)osenvironr/rrrrget_pro_environmentwsrcCsdd}|D]D\}}||}t|tr#t|tr#t|||qt|trHt|trHt|rBt|dtrB|||||dq |||<q|||<qdS)aMerge 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 Ssxdddd}g}||}|D]%}d}t|D]\}} | |||kr,t| |d}q|s4||q||dS)Nrtypeselector)availableResourcesresourceEntitlements overridesFT)rI enumeratedepth_first_merge_overlay_dictappendextend) base_valuesoverlay_valuesr3merge_id_key_mapvalues_to_appendid_key overlay_value was_replacedbase_value_idx base_valuerrrupdate_dict_lists"   z8depth_first_merge_overlay_dict..update_dict_listr)r3N)r/rIrrKrlistr:) base_dict overlay_dictrr3r4rrrrrs   ramd64i386ppc64elarm64armhf)x86_64i686ppc64leaarch64armv7larchcCs|}t||Sr)r\ ARCH_ALIASESrI)r arch_lowerrrrstandardize_arch_names rarchescCs*t}|D] }|t|qtt|Sr)setaddrsortedr)rdeduplicated_archesrrrrdeduplicate_archess rcCs tdkS)Nr)rgetuidrrrrwe_are_currently_roots rfilename new_extensioncCstj|\}}|d|S)Nr)rrHsplitext)rrr _extensionrrrset_filename_extensions r package_listc Cs&dtjd|dddddddS)N rPFz )widthbreak_long_wordsbreak_on_hyphensinitial_indentsubsequent_indent)rtextwrapwrap)rrrrcreate_package_list_strs r)r)rFF)6rjsonloggingrrtrrr; functoolsrtypingrrrrrr rWr r uaclient.defaultsr uaclient.typesr objectrJr0r getLoggerr$r8 JSONEncoderr JSONDecoderr)rErLr_boolrerqREDACT_SENSITIVE_LOGSryr~r1rrrrrrrrrrrrrs      "!     '     7 5