a 'Dgk,@sdZddlZddlZddlZddlZddlmZddlmZm Z ddl m Z ddl m Z mZmZddlmZddlmZd ZeeZdd d Zd d ZedddZeeeedddZddZddZ edkre dS)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) atomic_helperutil)read_cfg_paths)convert_jinja_instance_dataget_jinja_variable_aliasrender_jinja_payload)REDACT_SENSITIVE_VALUE)JinjaSyntaxParsingExceptionquerycCs|stjttd}|jdddddd|jdd td td d |jd ddddd|jddtdd |jddtdd |jdtddd|jddddddd|jdd td!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_runpathparserr#7/usr/lib/python3.9/site-packages/cloudinit/cmd/query.py get_parser&st        r%cCsBtj|dd}z |dWSty<tj|dddYS0dS)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. T)quietzutf-8F)r&decodeN)rZload_binary_filer'UnicodeDecodeErrorZ decomp_gzip)Z ud_file_pathZbdatar#r#r$ load_userdata~s   r))returnc Cst}t}|r|}nF|d}|dkrZ|d}tj|rF|}q^td|||}n|}|rh|}ntj|j d}|r|} ntj|j d} |d} zt |} WnNt t fy} z2| jtkrtd|n td |WYd } ~ n d } ~ 00t | }zt t | } Wnt t fy4d } Yn0|dkrrd t|f|d <d t| f|d <d t| f|d<n t||d <t| |d <| |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. rrZinstance_data_sensitivez4Missing root-readable %s. Using redacted %s instead.z user-data.txtzvendor-data.txtcombined_cloud_configz$No read permission on '%s'. Try sudozMissing instance-data file: %sNz <%s> file:%sZuserdataZ vendordata)osgetuidrr pathexistsLOGZwarningjoinZ instance_linkrZload_text_fileIOErrorOSErrorerrnorerrorZ load_jsonr r))r user_data vendor_datauidpathsZinstance_data_fnZredacted_data_fnZsensitive_data_fnZ user_data_fnZvendor_data_fnZcombined_cloud_config_fnZ instance_jsoner+r#r#r$_read_instance_datasl               r;jinja_vars_without_aliasesjinja_vars_with_aliasesr list_keysc Csd}|}|dD]}z ||}WnLtyn}z4|rFdj||d}n d|}t||WYd}~n d}~00||vr||}n"|D]} t| |kr|| }qq|r|d7}||7}q|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}')ZleafZkey_pathz Undefined instance-data key '{}'N)splitKeyErrorr ValueErrorr) r=r>rr?Zwalked_key_pathresponseZ key_path_partr:msgkeyr#r#r$(_find_instance_data_leaf_by_varname_paths,      rHc Cst|j|j|j|jgs0tdtdSzt |j |j |j }Wnt tfy^YdS0|jrdj|jd}zt|d||jrdndd}Wn6ty}ztd t|WYd }~dSd }~00|rt|d SdSt|}|jrJt|dd }zt|||j|jd }Wn6ttfyH}zt|WYd }~dSd }~00|jrt|tsptd|jdSdt|}t|tst|}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 command lineTF)payloadZ payload_fnrdebugz#Failed to render templated data. %sNr)Zinclude_key_aliasesr<z+--list-keys provided but '%s' is not a dict )anyr?rrrr0r5r% print_helpr;rr6r7r2r3rrLr rprintrrHrCrD isinstancedictr1sortedkeysrZ json_dumps)nameargsrrKZrendered_payloadr:rEr>r#r#r$ handle_argssr        rWcCst}ttt|dS)z,Tool to query specific instance-data values.N)r%sysexitrWr parse_argsr!r#r#r$mainKsr[__main__)N)!rrZloggingr,rXr4rZ cloudinitrrZcloudinit.cmd.develrZ!cloudinit.handlers.jinja_templaterrrZcloudinit.sourcesr Zcloudinit.templaterr rZ getLogger__name__r0r%r)rRr;rboolrHrWr[r#r#r#r$s0       XQ +C