܍~c(dZddlZddlZddlZddlmZddlmZmZddl m Z m Z ddl m Z mZmZddlmZdZejeZdd Zd Zd efd Zd edededefdZdZdZedkr edSdS)aTQuery standardized instance metadata provided to machine, returning a JSON structure. Some instance-data values may be binary on some platforms, such as userdata and vendordata. Attempt to decompress and decode UTF-8 any binary values. Any binary values in the instance metadata will be base64-encoded and prefixed with "ci-b64:" in the output. userdata and, where applicable, vendordata may be provided to the machine gzip-compressed (and therefore as binary data). query will attempt to decompress these to a string before emitting the JSON output; if this fails, they are treated as binary. N)EACCES)logutil)addLogHandlerCLIread_cfg_paths)convert_jinja_instance_dataget_jinja_variable_aliasrender_jinja_payload)REDACT_SENSITIVE_VALUEqueryc Z|s tjtt}|ddddd|dd t d t d  |d dddd|ddt d |ddt d |dt dd|dddddd|dd t d!d"#|S)$a#Build or extend an arg parser for query utility. @param parser: Optional existing ArgumentParser instance representing the query subcommand which will be extended to support the args of this utility. @returns: ArgumentParser with proper argument configuration. )prog descriptionz-dz--debug store_trueFz+Add verbose messages during template render)actiondefaulthelpz-iz--instance-dataz,Path to instance-data.json file. Default is instance_data)typerz-lz --list-keyszBList query keys available at the provided instance-data .z-uz --user-datazHPath to user-data file. Default is /var/lib/cloud/instance/user-data.txtz-vz --vendor-datazLPath to vendor-data file. Default is /var/lib/cloud/instance/vendor-data.txtvarname?zA dot-delimited specific variable to query from instance-data. For example: v1.local_hostname. If the value is not JSON serializable, it will be base64-encoded and will contain the prefix "ci-b64:". )rnargsrz-az--alldump_allz Dump all available instance-data)rrdestrz-fz--formatformatzOptionally specify a custom output format string. Any instance-data variable can be specified between double-curly braces. For example -f "{{ v2.cloud_name }}")rrr)argparseArgumentParserNAME__doc__ add_argumentstrr get_runpathparsers 5/usr/lib/python3/dist-packages/cloudinit/cmd/query.py get_parserr&$s I(dHHH   :     ?++O<< ? ?            5     7    3        /      <     Mctj|d} |dS#t$rtj|ddcYSwxYw)zAttempt to return a string of user-data from ud_file_path Attempt to decode or decompress if needed. If unable to decode the content, raw bytes will be returned. @returns: String of uncompressed userdata if possible, otherwise bytes. F)decodezutf-8T)quietr))r load_filer)UnicodeDecodeError decomp_gzip) ud_file_pathbdatas r% load_userdatar0|sm N< 6 6 6EA||G$$$ AAAU4@@@@@@As-!AAreturnctj}t}|r|}ns|d}|dkrV|d}tj|r|}n!t d|||}n|}|r|}n%tj|j d}|r|} n%tj|j d} tj |} na#ttf$rM} | jtkrt d|nt d|d } ~ wwxYwtj| }|dkr!d t$d ||d <d t$d | |d <n$t'||d <t'| |d <|S)aReturn a dict of merged instance-data, vendordata and userdata. The dict will contain supplemental userdata and vendordata keys sourced from default user-data and vendor-data files. Non-root users will have redacted INSTANCE_JSON_FILE content and redacted vendordata and userdata values. :raise: IOError/OSError on absence of instance-data.json file or invalid access perms. rrinstance_data_sensitivez4Missing root-readable %s. Using redacted %s instead.z user-data.txtzvendor-data.txtz$No read permission on '%s'. Try sudozMissing instance-data file: %sN file:userdata vendordata)osgetuidrr"pathexistsLOGwarningjoin instance_linkrr+IOErrorOSErrorerrnorerror load_jsonr r0) r user_data vendor_datauidpathsinstance_data_fnredacted_data_fnsensitive_data_fn user_data_fnvendor_data_fn instance_jsones r%_read_instance_datarOs )++C   E0( ,,_== !88 % 1 12K L L w~~/00 4#4   J%$ $4  / J w||E$7II N$e&9;LMM'788 W  7f   II<>N O O O O II68H I I I N=11M axxx " " " L% j!! # " " N' l## %2,$?$? j!&3N&C&C l# s/DE"AEE"jinja_vars_without_aliasesjinja_vars_with_aliasesr list_keyscjd}|}|dD]} ||}nQ#t$rD}|rd||}nd|}t||d}~wwxYw||vr ||}n"|D]} t | |kr || }n |r|dz }||z }|S)aReturn the value of the dot-delimited varname path in instance-data Split a dot-delimited jinja variable name path into components, walk the path components into the instance_data and look up a matching jinja variable name or cloud-init's underscore-delimited key aliases. :raises: ValueError when varname represents an invalid key name or path or if list-keys is provided by varname isn't a dict object. .z*instance-data '{key_path}' has no '{leaf}')leafkey_pathz Undefined instance-data key '{}'N)splitKeyErrorr ValueErrorr ) rPrQrrRwalked_key_pathresponse key_path_partrNmsgkeys r%(_find_instance_data_leaf_by_varname_pathr`sO)H s++))  )'>m&L # # ) ) ) IBII&J9??HHS//q ( ) H $ $ .HH  +C00MAA'}HEB  # s "O=( Os& A4?A//A4ctt|jr tjn tjt |j|j|j |j gsstAj!|}t+|d S)z3Handle calls to 'cloud-init query' as a subcommand.zDExpected one of the options: --all, --format, --list-keys or varnamez## template: jinja {fmt})fmtzquery commandlineTF)payload payload_fnrdebugr)include_key_aliases)rPrQrrRNz+--list-keys provided but '%s' is not a dict )"rr;rfrDEBUGWARNINGanyrRrrrrBr& print_helprOrrDrEr?r@r printrr`rYrZ isinstancedictr=sortedkeysr!r json_dumps)nameargsrrdrendered_payloadr\rQrNs r% handle_argsrvsmStzB#))s{CCC  dk4=I J J  &     !!!q+  0@   W qq { -444EE/*'*/$$%       " # # #1q +=99H | "= t# # #  ?+3(? . HH *%    IIaLLL11111  ~6(D))  II=t|   199VHMMOO4455 h $ $-?8,, (OOO 1s* B88C  C  E))F:FFct}tjtt|dS)z,Tool to query specific instance-data values.N)r&sysexitrvr parse_argsr#s r%mainr{4s7 \\FH[v0022 3 344444r'__main__)N)rrr7rxrAr cloudinitrrcloudinit.cmd.develrr!cloudinit.handlers.jinja_templaterr r cloudinit.sourcesr r getLoggerr;r&r0rorOr!boolr`rvr{__name__r'r%rs   @@@@@@@@ 544444cmDUUUUp A A A>$>>>>B( $(!(( ((((V: : : z555  zDFFFFFr'