a '¡Dgk,ã@sÜdZddlZddlZddlZddlZddlmZddlmZm Z ddl m Z ddl m Z mZmZddlmZddlmZd Ze e¡Zdd d „Zd d „Zedœdd„Zeeeedœdd„Zdd„Zdd„Z edkrØe ƒ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_helperÚutil)Úread_cfg_paths)Úconvert_jinja_instance_dataÚget_jinja_variable_aliasÚrender_jinja_payload)ÚREDACT_SENSITIVE_VALUE)ÚJinjaSyntaxParsingExceptionÚquerycCs¾|stjttd�}|jdddddd�|jdd td tƒ d ¡›�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)ÚactionÚdefaultÚhelpz-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.txtÚvarnameú?zÇA 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:". )rÚnargsrz-az--allÚdump_allz Dump all available instance-data)rrÚdestrz-fz--formatÚformatzŸOptionally specify a custom output format string. Any instance-data variable can be specified between double-curly braces. For example -f "{{ v2.cloud_name }}")rrr)ÚargparseÚArgumentParserÚNAMEÚ__doc__Ú add_argumentÚstrrÚ get_runpath©Úparser©r#ú7/usr/lib/python3.9/site-packages/cloudinit/cmd/query.pyÚ get_parser&st û ÿû ú û û û úú r%cCsBtj|dd�}z | d¡WSty<tj|ddd�YS0dS)züAttempt 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 Cs–t ¡}tƒ}|r|}nF| d¡}|dkrZ| d¡}tj |¡rF|}q^t d||¡|}n|}|rh|}ntj |j d¡}|r‚|} ntj |j d¡} | d¡} zt   |¡} WnNt t fyø} z2| jtkrÖt d|¡n t d |¡‚WYd } ~ n d } ~ 00t  | ¡}zt  t   | ¡¡} Wnt t f�y4d } Yn0|dk�rrd t|f|d <d t| f|d <d t| f|d<n t|ƒ|d <t| ƒ|d <| |d<|S)ašReturn 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.txtÚcombined_cloud_configz$No read permission on '%s'. Try sudozMissing instance-data file: %sNz <%s> file:%sZuserdataZ vendordata)ÚosÚgetuidrr ÚpathÚexistsÚLOGZwarningÚjoinZ instance_linkrZload_text_fileÚIOErrorÚOSErrorÚerrnorÚerrorZ load_jsonr r))rÚ user_dataÚ vendor_dataÚuidÚpathsZinstance_data_fnZredacted_data_fnZsensitive_data_fnZ user_data_fnZvendor_data_fnZcombined_cloud_config_fnZ instance_jsonÚer+r#r#r$Ú_read_instance_data�sl    ý    ÿ  þ þ þ   r;©Újinja_vars_without_aliasesÚjinja_vars_with_aliasesrÚ list_keysc Cs¾d}|}| d¡D]¦}z ||}WnLtyn}z4|rFdj||d�}n d |¡}t|ƒ|‚WYd}~n d}~00||vr‚||}n"|D]} t| ƒ|kr†|| }q¤q†|r°|d7}||7}q|S)a³Return 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)ÚsplitÚKeyErrorrÚ ValueErrorr) r=r>rr?Zwalked_key_pathÚresponseZ key_path_partr:ÚmsgÚkeyr#r#r$Ú(_find_instance_data_leaf_by_varname_pathÝs, ÿ     rHc Cs¤t|j|j|j|jgƒs0t d¡tƒ ¡dSzt |j |j |j ƒ}Wnt tfy^YdS0|jrÞdj|jd�}zt|d||jrˆdndd�}Wn6tyÈ}zt d t|ƒ¡WYd }~dSd }~00|rÚt|ƒd SdSt|ƒ}|j�rJt|dd �}zt|||j|jd �}Wn6ttf�yH}zt |¡WYd }~dSd }~00|j�r‚t|tƒ�spt d|j¡dSd t| ¡ƒ¡}t|tƒ�s˜t |¡}t|ƒd S)z3Handle calls to 'cloud-init query' as a subcommand.zDExpected one of the options: --all, --format, --list-keys or varnameéz## template: jinja {fmt})Úfmtzquery command lineTF)ÚpayloadZ payload_fnrÚdebugz#Failed to render templated data. %sNr)Zinclude_key_aliasesr<z+--list-keys provided but '%s' is not a dictÚ )Úanyr?rrrr0r5r%Ú print_helpr;rr6r7r2r3rrLr rÚprintrrHrCrDÚ isinstanceÚdictr1ÚsortedÚkeysrZ json_dumps)ÚnameÚargsrrKZrendered_payloadr:rEr>r#r#r$Ú handle_argssrÿ  ÿ ü þÿü   ÿ  rWcCstƒ}t tt| ¡ƒ¡dS)z,Tool to query specific instance-data values.N)r%ÚsysÚexitrWrÚ 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;rÚboolrHrWr[r#r#r#r$Ús0       XQü +C