3 \mee@sdZddlZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m Z ddlmZddlmZddlmZdd lmZmZmZmZmZmZmZmZddlZdd lmZm Z dd l!m"Z"dd l#m$Z$m%Z%dd l&m'Z'ddl(m)Z)m*Z*m+Z+yddl,m-Z.e.Z-Wne/k r.e0Z-YnXej1e2Z3dZ4dZ5dZ6de5ide6idZ7ddddZ8dZ9dZ:dZ;dZdZ?dZ@eAd d!e$jBDZCerddlZdd"lDmEZEmFZFGd#d$d$eFZGneHZGGd%d&d&e-ZIGd'd(d(eZJeeJZKGd)d*d*eZLdd+d,eKeeMeMeMd-d.d/ZNGd0d1d1eOZPd2d3ZQdeHeMd5d6d7ZRee-d8d9d:ZSeIfeTeHeMee0d;dZVeeUd?d>ZWeIfee0d@dAdBZXeIfee0d@dCdDZYdEdFZZdeHdHdIdJZ[deHeeHeMeTeTeTeTdLdMdNZ\GdOdPdPZ]dddQeHeMeHeeKeeKeeMe^fdRdSdTZ_eMeeJdUdVdWZ`deMeMeMeLdXdYdZZadeMeHeMeTeMeTd[d\d]Zbd^d_Zcd`daZdeHeMeeMdbdcddZeeHeHeMdedfdgZfeMd8dhdiZgeHeHdjdkdlZheHdmdndoZieHeMdpdqdrZjdeHeHeMdtdudvZkeGeMdwdxdyZleGeMdwdzd{ZmdeGeeHeMd|d}d~ZneHd8ddZoepeMdddZqeMd8ddZrdeMeHdddZsdddZtddZuddZve2dkrejwevdS)zFschema.py: Set of module functions for processing cloud-config schema.N) defaultdict)Iterable)deepcopy)EACCES)partial)chain) TYPE_CHECKING DefaultDictList NamedTupleOptionalTypeUnioncast)importersafeyaml)read_cfg_paths)INCLUSION_TYPES_MAPtype_from_starts_with)DataSourceNotFoundException)errorget_modules_from_dir load_file)ValidationErrorz!versions.schema.cloud-config.jsonzschema-cloud-config-v1.jsonzschema-network-config-v1.jsonlatest)z cloud-configznetwork-configtrueZfalseZnull)TFNap {name} {title_underbar} {title} .. tab-set:: {prefix3}.. tab-item:: Summary {description} {prefix6}**Internal name:** ``{id}`` {prefix6}**Module frequency:** {frequency} {prefix6}**Supported distros:** {distros} {prefix6}{activate_by_schema_keys} {prefix3}.. tab-item:: Config schema {property_doc} {prefix3}.. tab-item:: Examples {prefix6}:: {examples} z5{prefix}* **{prop_name}:** ({prop_type}){description}zJ{prefix}* Each object in **{prop_name}** list supports the following keys:z& # --- Example{example_count} --- deprecatedz DEPRECATED: cCsg|]}|ddkr|qS)r#).0trr/usr/lib/python3.6/schema.py psr#) NotRequired TypedDictc@sBeZdZUeeeeej e ej e e e e edS) MetaSchemaN)__name__ __module__ __qualname__strnameidtitle descriptiontypingr distrosexamples frequencyr$activate_by_schema_keysrrrr"r&zs   r&c@s eZdZdS)SchemaDeprecationErrorN)r'r(r)rrrr"r4sr4c@s$eZdZUeeedddZdS) SchemaProblem)returncCs|jd|jS)Nz: )pathmessage)selfrrr"formatszSchemaProblem.formatN)r'r(r)r*r7r8r:rrrr"r5s r5c@seZdZUeedS)UserDataTypeAndDecodedContentN)r'r(r)r* userdata_typecontentrrrr"r;s r;z, )prefix separator)schema_problemsr>r?r6cCs(|jtdd|}|r$||}|S)NcSs|jS)N)r:)prrr"sz)_format_schema_problems..)joinmap)r@r>r?Z formattedrrr"_format_schema_problemss rEcs@eZdZdZd eeeedfdd ZedddZZ S) SchemaValidationErrorz)sortedlistsetrE)problemsr>)r8rr"handle_problemssz7SchemaValidationError.__init__..handle_problemszCloud config schema errors: )r>z"Cloud config schema deprecations: N)rGrHsuper__init__)r9rGrHrM) __class__)r8r"rOs    zSchemaValidationError.__init__)r6cCs t|jS)N)boolrG)r9rrr" has_errorssz SchemaValidationError.has_errors)NN) r'r(r)__doc__r SchemaProblemsrOrQrR __classcell__rr)rPr"rFsrFc Cs@yddlm}Wntk r$dSX|jj|dp>t|tfS)zWTYPE_CHECKER override allowing bytes for string type For jsonschema v. 3.0.0+ r)Draft4ValidatorFstring) jsonschemarV ImportError TYPE_CHECKERis_type isinstancebytes)ZcheckerinstancerVrrr"is_schema_byte_stringsr_F)configr6csRtdfdd }|r|ndddg}djt||}jdd}||jS) zcombine description with new/changed/deprecated message deprecated/changed/new keys require a _version key (this is verified in a unittest), a _description key is optional )keycsrj|sdSj|dd}j|dd|d}|jd|d|}rbd|Sd |jd S) NrZ _descriptionZ_versionz z in version z.  z **)get capitalizestrip)raZkey_descriptionvmsg)annotater`rr"format_messages  z:_add_deprecated_changed_or_new_msg..format_messagerchangednewrr.)r*rCrDrdrstrip)r`ri filter_keyrjZ filter_keysZchanged_new_deprecatedr.r)rir`r""_add_deprecated_changed_or_new_msgs  ro)r6cCsg}d}t|tod|k}x|D]}|r|d|jjdijdijdgkrT|gSt|dr||jdddkr|j|q|jr|jddkr|j|q t|j|kr|j|q t|j|kr t|j}|g}q W|S) zReturn the best_match errors based on the deepest match in the json_path This is useful for anyOf and oneOf subschemas where the most-specific error tends to be the most appropriate. rtype propertiesenum json_pathN) r\dictschemardhasattrrsappendr7len)errorsr^Z best_matchesZ path_depthr[errrrr"cloud_init_deepest_matchess(        r})rrwrn error_typeccs"|rt|d|gd}||VdS)zJsonschema validator for `deprecated` items. It raises a instance of `error_type` if deprecated that must be handled, otherwise the instance is consider faulty. T)rirnN)ro) _validatorrZ _instancerwrnr~rhrrr"r#s r)rnrk)r~c#sddlm}g}g}d}xt|D]\} } t|j|| | d} ttfdd| } ttfdd| } | sz|j| Pt|trd|krd | j d d krd |d| d krd }| EdH|j| q"W|s||Vt d|f|dV|EdHdS)aJsonschema validator for `anyOf`. It treats occurrences of `error_type` as non-errors, but yield them for external processing. Useful to process schema annotations, as `deprecated`. Cloud-init's network schema under the `config` key has a complexity of allowing each list dict item to declare it's type with a `type` key which can contain the values: bond, bridge, nameserver, physical, route, vlan. This schema 'flexibility' makes it hard for the default jsonschema.exceptions.best_match function to find the correct schema failure because it typically returns the failing schema error based on the schema of greatest match depth. Since each anyOf dict matches the same depth into the network schema path, `best_match` just returns the first set of schema errors, which is almost always incorrect. To find a better schema match when encountering schema validation errors, cloud-init network schema introduced schema $defs with the prefix `anyOf_type_`. If the object we are validating contains a 'type' key, and one of the failing schema objects in an anyOf clause has a name of the format anyOf_type_XXX, raise those schema errors instead of calling best_match. r) best_matchF) schema_pathcs t| S)N)r\)e)r~rr"rBbsz_anyOf..cs t|S)N)r\)r)r~rr"rBdsrpZ anyOf_typez$refrZ anyOf_type_TNz.%r is not valid under any of the given schemas)context) jsonschema.exceptionsr enumeraterJdescendfilterextendr\rvrdr) validatoranyOfr^_schemar~r all_errorsall_deprecationsZskip_best_matchindex subschemaall_errserrs deprecationsr)r~r"_anyOf;s4      rc#st|}g}g}x~|D]f\}} tj| |d} ttfdd| } ttfdd| } | sr| } |j| P|j| qWt|EdHfdd|D}|r|j| djd d |D}td |fVn |EdHdS) zJsonschema validator for `oneOf`. It treats occurrences of `error_type` as non-errors, but yield them for external processing. Useful to process schema annotations, as `deprecated`. )rcs t| S)N)r\)r)r~rr"rBsz_oneOf..cs t|S)N)r\)r)r~rr"rBsNcs g|]\}}j|r|qSr)is_valid)r is)r^rrr"r#sz_oneOf..z, css|]}t|VqdS)N)repr)r rwrrr" sz_oneOf..z%r is valid under each of %s) rrJrrrr}ryrCr)roneOfr^rr~Z subschemasrrrrrrrZ first_validZ more_validZreprsr)r~r^rr"_oneOf~s,   rc Csddlm}m}ddlm}t|j}ddi|dd<i}t|drdd |d <|jj dt }d |i}n|j }t t f|d<d |i}t|j}t|t<t|d <t|d<t|d<|f||dd|}ddd} | |_||fS)zGet metaschema validator and format checker Older versions of jsonschema require some compatibility changes. @returns: Tuple: (jsonschema.Validator, FormatChecker) @raises: ImportError when jsonschema is not present r)rV FormatChecker)createrprWrqlabelrZFadditionalProperties type_checkerZ default_typesrkrrZdraft4) meta_schema validatorsversionNc[s$tdd|j||}t|ddkS)zgOverride version of `is_valid`. It does ignore instances of `SchemaDeprecationError`. cSs t|t S)N)r\r4)rrrr"rBsz.is_valid..N)r iter_errorsnext)r9r^r__r{rrr"rsz*get_jsonschema_validator..is_valid)N)rXrVrZjsonschema.validatorsrrZ META_SCHEMArxrZZredefiner_Z DEFAULT_TYPESr*r]rvZ VALIDATORS_validator_deprecatedDEPRECATED_KEY_validator_changedrrr) rVrrrZvalidator_kwargsrtypesrcloudinitValidatorrrrr"get_jsonschema_validators4       rT)rwcCszddlm}y|j|WnZ|k rt}z>|rXttdjdd|jD|jgd|tj d|WYdd}~XnXdS) a Validate provided schema meets the metaschema definition. Return strict Validator and FormatChecker for use in validation @param validator: Draft4Validator instance used to validate the schema @param schema: schema to validate @param throw: Sometimes the validator and checker are required, even if the schema is invalid. Toggle for whether to raise SchemaValidationError or log warnings. @raises: ImportError when jsonschema is not present @raises: SchemaValidationError when the schema is invalid r) SchemaError.cSsg|] }t|qSr)r*)r rArrr"r# sz3validate_cloudconfig_metaschema..)rGzGMeta-schema validation failed, attempting to validate config anyway: %sN) rrZ check_schemarFr5rCr7r8LOGwarning)rrwthrowrr|rrr"validate_cloudconfig_metaschemas  r cloud-config)r`rw schema_typestrictstrict_metaschema log_detailslog_deprecationsc Csx|dkrt|}y t\}}|r.t||ddWntk rNtjddSX|||d} g} g} xt| j|dddD]x} d jd d | j D} | r| j d kr| j |krt j d | j}|r|d} t| | jf}t| tr| |7} q~| |7} q~W|r| rt| ddd}tj||r:| s0| r:t| | | rt|r^t| d|ddd}n d|d}tj|dS)aValidate provided config meets the schema definition. @param config: Dict of cloud configuration settings validated against schema. Ignored if strict_metaschema=True @param schema: jsonschema dict describing the supported schema definition for the cloud config module (config.cc_*). If None, validate against global schema. @param schema_type: Optional string. One of: cloud-config, network-config Default: cloud-config. @param strict: Boolean, when True raise SchemaValidationErrors instead of logging warnings. @param strict_metaschema: Boolean, when True validates schema using strict metaschema definition at runtime (currently unused) @param log_details: Boolean, when True logs details of validation errors. If there are concerns about logging sensitive userdata, this should be set to False. @param log_deprecations: Controls whether to log deprecations or not. @raises: SchemaValidationError when provided config does not validate against the provided schema. @raises: RuntimeError when provided config sourced from YAML is not a dict. @raises: ValueError on invalid schema_type not in cloud-config or network_config NF)rz5Ignoring schema validation. jsonschema is not present)Zformat_checkercSs|jS)N)r7)rrrr"rBIsz-validate_cloudconfig_schema..)rarcSsg|] }t|qSr)r*)r rArrr"r#Ksz/validate_cloudconfig_schema..rz#.*\('(?P.*)' was unexpected\)r+z"Deprecated cloud-config provided:  )r>r?zInvalid z provided: zQ provided: Please run 'sudo cloud-init schema --system' to see the schema errors.T) get_schemarrrYrdebugrIrrCr7rrwrematchr8r5r\r4rErrFr)r`rwrrrrrrrrr{r schema_errorr7Z prop_matchproblemr8Zdetailsrrr"validate_cloudconfig_schemasZ!              rc @seZdZeeedddZeeeeedddZe ddd Z edeeeeeee ee d d d Z eeeeeedddZ e e edddZdS) _Annotator) cloudconfigoriginal_content schemamarkscCs||_||_||_dS)N) _cloudconfig_original_content _schemamarks)r9rrrrrr"rO|sz_Annotator.__init__)r-r=r6cCsdj|}d|d|dS)Nrz# z: ------------- z )rC)r-r=Zbodyrrr" _build_footers z_Annotator._build_footer)r@cCs~tt}xp|D]h\}}tjd|}|rF|j\}}|t|j|nd}||j|j||dk rdj|||d}qW|S)Nz&format-l(?P\d+)\.c(?P\d+).*zLine {line} column {col}: {msg})linecolrh) rrJrrgroupsintryrr:)r9r@errors_by_liner7rhrrrrrr"_build_errors_by_lines  z _Annotator._build_errors_by_liner)rLlabelsfooterr label_prefixr6cCsFx@|D]8}||}|j||jd|d||d7}qW|S)Nz# z: )ry)rLrrrrrrrrr" _add_problemss     z_Annotator._add_problems)linesrdeprecations_by_liner6csg}g}g}d}d}x~t|dD]p\} } || } || } | s@| rg} j| | ||dd}j| | ||dd}|j| ddj| q |j| q W|jtfddtd dd |fd |ff|S) NrE)rDz # ,cs j|S)N)r)seq)r9rr"rBsz._Annotator._annotate_content..cSs t|dS)Nr)rQ)rrrr"rBsErrorsZ Deprecations)rrryrCrrDr)r9rrrannotated_contentZ error_footerZdeprecation_footerZ error_indexZdeprecation_indexZ line_numberrr{rrr)r9r"_annotate_contents8 z_Annotator._annotate_content)rGrHr6cCsp| r| r|jS|jjd}t|jtsDdj||jddggS|j|}|j|}|j|||}dj|S)Nrrz&# E1: Cloud-config is not a YAML dict.) rsplitr\rrvrCrrr)r9rGrHrrrrrrr"ris      z_Annotator.annotateN)r)r'r(r)rvr*rO staticmethodr rrTrrrrrirrrr"r{s  )r)rGrH)rrrrGrHr6cCst|||j|pg|pgS)aReturn contents of the cloud-config file annotated with schema errors. @param cloudconfig: YAML-loaded dict from the original_content or empty dict if unparseable. @param original_content: The contents of a cloud-config file @param schemamarks: Dict with schema marks. @param schema_errors: Instance of `SchemaProblems`. @param schema_deprecations: Instance of `SchemaProblems`. @return Annotated schema )rri)rrrrGrHrrr"annotated_cloudconfig_files r)r=r6cCsfddlm}||krgSg}xDt|jdD]2\}}|j|r,|jtd|d|j|dq,W|S)aAnnotate and return schema validation errors in merged cloud-config.txt When merging multiple cloud-config parts cloud-init logs an error and ignores any user-data parts which are declared as #cloud-config but cannot be processed. the hanlder.cloud_config module also leaves comments in the final merged config for every invalid part file which begin with MERGED_CONFIG_SCHEMA_ERROR_PREFIX to aid in triage. r)MERGED_PART_SCHEMA_ERROR_PREFIXrzformat-lz.c1zIgnored invalid user-data: )Zcloudinit.handlers.cloud_configrr splitlines startswithryr5replace)r=rr{Zline_numrrrr")process_merged_cloud_config_part_problemss   r) config_pathr=instance_data_pathr6c Cs ddlm}m}m}t|}d}|dkry||||}Wnd|k rl}ztt|dg|WYdd}~Xn2|k r}ztt|ddWYdd}~XnXd }t|}|s|j d \} } } tt|d |d | d dj t gn|dkrt d|dt ||S)a Return tuple of user-data-type and rendered content. When encountering jinja user-data, render said content. :return: UserDataTypeAndDecodedContent :raises: SchemaValidationError when non-jinja content found but header declared ## template: jinja. r)JinjaLoadError NotJinjaErrorrender_jinja_payload_from_filez format-l1.c1z text/jinja2zRDetected type '{user_data_type}' from header. But, content is not a jinja templateNT)sys_exitz format-l2.c1rz!Unrecognized user-data header in z: "z%". Expected first line to be one of: z, ztext/cloud-configzUser-data type 'z.' not currently evaluated by cloud-init schema)Z!cloudinit.handlers.jinja_templaterrrrrFr5rr* partitionrCUSERDATA_VALID_HEADERSprintr;) rr=rrrrZuser_data_typeZschema_positionrZ header_line_rrr"&_get_config_type_and_rendered_userdata&s6"$ r)rrwrrirr6c"Cst|dd}|s$td||fdS|dkr8t||}n t|||}|jdkrRdS|j}t|}y&|rvtj|\} } ntj |} i} Wnt j k r`} zd} } d}t | d rt | d rt | d }nt | d rt | d rt | d }|r|jd} |jd} |jtd j| | d d j|t| t|}|rJtti|i|jd|| WYdd} ~ XnXt| ts|st|d|d|dkr| jd| }|stddS|jddkrtd|jddSy*t| |dddstd|ddSWntk r} zl| jr*|| j7}|rJtt| || || jdn | jrjt| jddd}t||r|t|d| WYdd} ~ XnXdS)aValidate cloudconfig file adheres to a specific jsonschema. @param config_path: Path to the yaml cloud-config file to parse, or None to default to system userdata from Paths object. @param schema: Dict describing a valid jsonschema to validate against. @param schema_type: One of network-config or cloud-config. @param annotate: Boolean set True to print original config file with error annotations on the offending lines. @param instance_data_path: Path to instance_data JSON, used for text/jinja rendering. :return: True when validation was performed successfully :raises SchemaValidationError containing any of schema_errors encountered. :raises RuntimeError when config_path does not exist. T)decodez,Empty '%s' found at %s. Nothing to validate.Fnetwork-configtext/cloud-configrNZ context_markZ problem_markzformat-l{line}.c{col})rrzFile {0} is not valid YAML. {1})rGrbz is not a YAML dict.Znetworkz:Skipping network-config schema validation on empty config.rzJSkipping network-config schema validation. No network schema for version: )rrz Skipping z2 schema validation. Jsonschema dependency missing.)rGrHz"Cloud config schema deprecations: z, )r>r?)r)rr)rrr;rr<r=rrZload_with_marksloadyamlZ YAMLErrorrxgetattrrcolumnryr5r:r*rFrrGr\rv RuntimeErrorrdrrRrHrE)rrwrrirZdecoded_contentZdecoded_configr=r{rZmarksrrrZmarkrZnetcfgr8rrr"validate_cloudconfig_filecs               rcCs|dkr dS|dkrdSdS)zProvide a sorting weight for documentation of property types. Weight values ensure 'array' sorted after 'object' which is sorted after anything else which remains unsorted. Zarrayobjectrrr)valuerrr"_sort_property_orders rccsBx<|D]4}t|tr4t|ttf r4t|EdHq|VqWdS)N)r\rr*r]_flatten)Zxsxrrr"rs r) property_dict multi_keyr6cCsrg}x`|j|iD]P}|jtr"q|jdrJ|jdd|jdgDq|jdr|j|dqWtt|S)NrrcSs g|]}dtj||dqS)z``) _YAML_MAPrd)r Z enum_valuerrr"r#sz,_collect_subschema_types..rp)rdrrryrJr)rrproperty_typesrrrr"_collect_subschema_typess   r)rdefsr6c Cs|t|||jdg}t|ts&|g}|jdrDdd|dD}n6|jdr`|jt|dn|jdrz|jt|dt|dkr|d}n|jtd d j |}|jd i}|jdg}t|ts|g}t |}xHt |jdi|jdiD]*}t ||}|r|d krq|j |qW|rrt|dkrF|d |dS|jtd dd j |d} |d | S|pzd S)zNReturn a string representing a property type from a given jsonschema. rprrcSs g|]}dtj||dqS)z``)rrd)r krrr"r#sz&_get_property_type..rrrr)ra/itemsZ UNDEFINEDz of ())_flatten_schema_refsrdr\rJrrrzsortrrCrQr_get_property_typery) rrrZ property_typerZsub_property_typesZprune_undefinedsub_itemZsub_typeZsub_property_docrrr"r  s>                r cCs>|}tjdd|}tjddj||}tjddj||}|S)aParse description from the meta in a format that we can better display in our docs. This parser does three things: - Guarantee that a paragraph will be in a single line - Guarantee that each new paragraph will be aligned with the first paragraph - Proper align lists of items @param description: The original description in the meta. @param prefix: The number of spaces used to align the current description z (\S)\n(\S)z\1 \2z\n\nz\n\n{}z\n( +)-z\n{}-)rsubr:)r.r>Zlist_paragraphrrr"_parse_description5s r)src_cfgrcCsd|kr(|jdjdd}|j||d|krd|dkrd|djdjdd}|dj||d|dkrx<|ddD],}d|kr~|jdjdd}|j||q~WxTt|jdg|jdg|jdgD],}d|kr|jdjdd}|j||qWdS) zEFlatten schema: replace $refs in src_cfg with definitions from $defs.z$refz#/$defs/rrrrallOfN)poprupdaterrd)rrZ reference sub_schemarrr"r Ks&    r )rcCs0|jdd}|sdSx|D]}|j|qWdS)zFlatten schema: Merge allOf. If a schema as allOf, then all of the sub-schemas must hold. Therefore it is safe to merge them. rN)rr)rZ sub_schemasrrrr"_flatten_schema_all_ofes   r) prop_configr6cCstttddd}|jdi}|jdi}g}g}||||xt||D]}||||qJWdjt||}|r|d|}|S)aGReturn accumulated property description. Account for the following keys: - top-level description key - any description key present in each subitem under anyOf or allOf Order and deprecated property description after active descriptions. Add a trailing stop "." to any description not ending with ":". )r` descriptionsdeprecated_descriptionscSs<tt|jdr |jt|n|jdr8|jt|dS)Ndeprecated_versionchanged_version new_versionr.)rrr)anyrDrdryro)r`rrrrr"assign_descriptions}s  z6_get_property_description..assign_descriptionsrrz. rb)rvrJrdrrC)rrrrrrr r.rrr"_get_property_descriptionrs     r )rwrr6c s|d}g}jddkrdSfdddD}fd d|D}x\|D]R}xJ|jD]<\}} t| |t| | jddkrq\t| } | jd |} |jtj|| t| |dt | |d | jd } | rtt| || jds| jdr|jt j|| d |jt | ||dxV| jdgD]F} | jdsF| jdr*|jt j|| d |jt | ||dq*Wd| ksd| kr\|jt | ||dq\WqJWdj |S)zDReturn restructured text describing the supported schema properties.z hiddenTrcs$g|]}dks|dkr|qS)rr)r ra)rwrr"r#sz%_get_property_doc..rqpatternPropertiescsg|]}j|iqSr)rd)r ra)rwrr"r#sr)r> prop_namer.Z prop_typer)r>r!)rr>rz )rqr ) rdrr rrrySCHEMA_PROPERTY_TMPLr:rr SCHEMA_LIST_ITEM_TMPL_get_property_docrC)rwrr>Z new_prefixrqZ property_keysZproperty_schemasZ prop_schemaZprop_keyrr.rrZ alt_schemar)rwr"r$sZ         r$)metar6cCsb|jd}|sdSt}xFt|dD]8\}}|tj|d7}tj|djd}|dj|7}q"W|S)zAReturn restructured text describing the meta examples if present.r1rr)Z example_countz r) rdSCHEMA_EXAMPLES_HEADERrSCHEMA_EXAMPLES_SPACER_TEMPLATEr:textwrapindentrrC)r%r1Z rst_contentcountZexampleZindented_linesrrr" _get_exampless  r+cCs2|jdsdSdjdd|dD}d|dS)Nr3rz, css|]}d|dVqdS)z``Nr)r rrrr"rsz3_get_activate_by_schema_keys_doc..z**Activate only on keys:** z )rdrC)r%Z schema_keysrrr" _get_activate_by_schema_keys_docs  r,)r%rwr6c Cs|dkrtdd}| s| r&tdt|j}ddddd d d h}d h}d }||rfdj||}n|||rdj||}|rt|tt|}d |d<d|d<d|d<tj t t |d d|d <|j di}|j |dr|j |di}t t|}t |djrPyt||dd|d<Wn(tk rNtjdd |d<YnX|j dd sfd|d<tj t|d|d<|dsd|d<dj|d |d <tjdd|d |d<t||d <tjf|}|S) zReturn reStructured text rendering the provided metadata. @param meta: Dict of metadata to render. @param schema: Optional module schema, if absent, read global schema. @raise KeyError: If metadata lacks an expected key. Nz cloud-config)rz"Expected non-empty meta and schemar,r-r1r2r0r.r+r3rz(Missing required keys in module meta: {}z3Additional unexpected keys found in module meta: {}Zproperty_headerz Zprefix6z Zprefix3z$defsrq)rr>Z property_docz3Unable to render property_doc due to invalid schemaz+ No schema definitions for this modulez$ No examples for this modulez, r-Ztitle_underbar)r ValueErrorrKkeysr:KeyErrorrvrr(r)rr*rdrvaluesr$AttributeErrorrrr+rCrr r,SCHEMA_DOC_TMPL) r%rwr/Z required_keysZ optional_keysZ error_messageZ meta_copyrtemplaterrr" get_meta_docsd             r5cCstjjtjjt}t|S)N)osr7dirnameabspath__file__r)Z configs_dirrrr" get_modulesDsr:)requested_modulesr6cCsd}ttjdg}t|jt|}|rLtdjt|dj|ddxR|D]J}d|ksf||krRtj |dgdg\}}|rRtj |d }||j pd7}qRW|S) zaLoad module docstrings Docstrings are generated on module load. Reduce, reuse, recycle. rallz+Invalid --docs value {}. Must be one of: {}z, T)rzcloudinit.configr%r) rJr:r1rK differencerr:rCr find_module import_modulerS)r;docsZ all_modulesZ invalid_docsZmod_nameZmod_locsrmodrrr"load_docIs"  rBcCstjjtjjtjjtdS)NZschemas)r6r7rCr7r8r9rrrr"get_schema_dirdsrC)rr6c CsZtjjtt|d}d}ytjt|}Wn&tt fk rTt j d||iSX|S)ziReturn jsonschema for a specific type. Return empty schema when no specific schema file exists. rNz;Skipping %s schema valiation. No JSON schema file found %s.) r6r7rCrCSCHEMA_FILES_BY_TYPEjsonloadsrIOErrorOSErrorrr)rZ schema_file full_schemarrr"rhsrcCs|stjddd}|jdddd|jdd td d gd d |jddtdtjdd|jddddd|jddddd|jddddd|S)z0Return a parser for supported cmdline arguments.zcloudconfig-schemazSchema validation and documentation of instance-data configuration provided to cloud-init. This includes: user-data, vendor-data and network-config)progr.z-cz --config-filez@Path of the cloud-config or network-config YAML file to validate)helpz-tz --schema-typez cloud-configznetwork-configz_When providing --config-file, the schema type to validate config against. Default: cloud-config)rpchoicesrKz-iz--instance-datazbPath to instance-data.json file for variable expansion of '##template: jinja' user-data. Default: instance_data)rprKz--system store_trueFzVValidate the system instance-data provided as vendor-data user-data and network-config)actiondefaultrKz-dz--docs+zCPrint schema module docs. Choices: all or space-delimited cc_names.)nargsrKz --annotatez;Annotate existing instance-data files any discovered errors)argparseArgumentParser add_argumentr*r get_runpath)parserrrr" get_parser}sFrXc)CsJ|j|j|jg}tdd|Ddkr2tdddt|j|jgrP|jrPtd|jrh|jrhtdddt d d }|jrtt |jd Syt d d }Wnft t fk r}z$|jtkrtjdt }nWYd d }~Xn$tk rt }tjdYnX|jr|j}n$tjdkr*|jd}n |jd}|jrL|j|jff}ntjdkrftddd|jd}|stdddd Sy2tj|jdkr|jd} tj| jr| }Wntk rYnXd|ff}d|jdfd|jdfd|jdff} x4| D],\} } | rtjj| r|| | ff7}qWtjj|ddsltd|dddd dd!d"} tt|dk}|rtd#d$jd%d&|Dd'} g}xtt |dD]d\}\} } d(}|rtd)|d*| d+| d,| dkrt | }| }n|}| d krdn| } d }yt!| |||j|}Wnt"k r}zN| sRd-} |jst| d.| d/| tt#|| d0d1|j$| WYd d }~Xn|t%k r}z6t| d.| tt#|| d0d1|j$| WYd d }~Xn*X|r|jr| n| }t| d2|qW|rFtd$jd3d&|Dd4dd!d S)5z@Handle provided schema args and perform the appropriate actions.cSsg|] }|r|qSrr)r argrrr"r#sz&handle_schema_args..rz;Expected one of --config-file, --system or --docs argumentsT)rz[WARNING: The --schema-type parameter is inapplicable when either --system or --docs presentz;Invalid flag combination. Cannot use --annotate with --docsz cloud-config)rNZtrust)Zfetch_existing_datasourcez=Using default instance-data/user-data paths for non-root userzEdatasource not detected, using default instance-data/user-data paths.rrMZinstance_data_sensitivezNUnable to read system userdata or vendordata as non-root user. Try using sudo.Z cloud_configz;Unable to obtain user data file. No instance data availableZ userdata_rawz user-dataz vendor-dataZvendor_cloud_configz vendor2-dataZvendor2_cloud_configznetwork-configZnetwork_configz Config file z does not existz Error: {})fmtrrz!Found cloud-config data types: %sz, css|]\}}|VqdS)Nr)r cfg_typerrrr"rsz%handle_schema_args..z Frz. z at :ZUNKNOWN_CONFIG_HEADERzInvalid rbz Error: {} )rZz Valid schema css|] }|VqdS)Nr)r r~rrr"rHszError: Invalid schema: {} )&Z config_filer@systemrzrrrrrirrBrrGrHerrnorrrrrrMr6getuidrVZ get_ipathstatst_sizeFileNotFoundErrorr7existsrQrCrrrFr*ryr)r+argsZexclusive_argsrIpathsrrZ config_filesZ userdata_fileZraw_userdata_fileZsupplemental_config_filesr[Zcfg_fileZnested_output_prefixZmulti_config_outputZ error_typesidxZperformed_schema_validationZ cfg_schemarZcfgrrr"handle_schema_argss              rgcCst}td|jdS)zDTool to validate schema of a cloud-config file or print schema docs.zcloudconfig-schemar)rXrg parse_args)rWrrr"mainNsri__main__)FN)T)NrFFTF)N)rFN)r)N)r)N)xrSrSrEZloggingr6rsysr( collectionsrcollections.abcrcopyrr^r functoolsr itertoolsrr/rr r r r r rrrZ cloudinitrrZcloudinit.cmd.develrZcloudinit.handlersrrZcloudinit.sourcesrZcloudinit.utilrrrrXrZ_ValidationErrorrY ExceptionZ getLoggerr'rZVERSIONED_USERDATA_SCHEMA_FILEZUSERDATA_SCHEMA_FILEZNETWORK_CONFIG_V1_SCHEMA_FILErDrr3ZSCHEMA_PROPERTY_HEADERr"r#r&r'rZDEPRECATED_PREFIXrIr/rZtyping_extensionsr$r%r&rvr4r5rTr;r*rEr.rFr_ror}rQrrrrrrrrrr]rrrrrrrr rr rrr$r+r,r5r:rJrBrCrrXrgriexitrrrr"s      (         )!'  C%L% ]z< z , *F J A