def test_get_meta_doc_properly_parse_description(self): """get_meta_doc description properly formatted""" schema = { "properties": { "p1": { "type": "string", "description": dedent("""\ This item has the following options: - option1 - option2 - option3 The default value is option1"""), } } } assert (dedent(""" **Config schema**: **p1:** (string) This item has the following options: - option1 - option2 - option3 The default value is option1 """) in get_meta_doc(self.meta, schema))
def test_get_meta_doc_hidden_hides_specific_properties_from_docs( self, schema, expected): """Docs are hidden for any property in the hidden list. Useful for hiding deprecated key schema. """ assert expected in get_meta_doc(self.meta, schema)
def test_get_meta_doc_handles_string_examples(self): """get_meta_doc properly indented examples as a list of strings.""" full_schema = copy(self.required_schema) full_schema.update({ "examples": [ 'ex1:\n [don\'t, expand, "this"]', "ex2: true", ], "properties": { "prop1": { "type": "array", "description": "prop-description", "items": { "type": "integer" }, } }, }) assert (dedent(""" **Config schema**: **prop1:** (array of integer) prop-description **Examples**:: ex1: [don't, expand, "this"] # --- Example2 --- ex2: true """) in get_meta_doc(self.meta, full_schema))
def test_references_are_flattened_in_schema_docs(self): """get_meta_doc flattens and renders full schema definitions.""" schema = { "$defs": { "flattenit": { "type": ["object", "string"], "description": "Objects support the following keys:", "patternProperties": { "^.+$": { "label": "<opaque_label>", "description": "List of cool strings", "type": "array", "items": { "type": "string" }, "minItems": 1, } }, } }, "properties": { "prop1": { "$ref": "#/$defs/flattenit" } }, } assert (dedent("""\ **prop1:** (string/object) Objects support the following keys: **<opaque_label>:** (array of string) List of cool strings """) in get_meta_doc(self.meta, schema))
def test_get_meta_doc_raises_key_errors(self): """get_meta_doc raises KeyErrors on missing keys.""" schema = { "properties": { "prop1": { "type": "array", "items": { "oneOf": [{"type": "string"}, {"type": "integer"}] }, } } } for key in self.meta: invalid_meta = copy(self.meta) invalid_meta.pop(key) with self.assertRaises(KeyError) as context_mgr: get_meta_doc(invalid_meta, schema) self.assertIn(key, str(context_mgr.exception))
def test_get_meta_doc_handles_nested_oneof_property_types(self): """get_meta_doc describes array items oneOf declarations in type.""" schema = { "properties": { "prop1": { "type": "array", "items": { "oneOf": [{"type": "string"}, {"type": "integer"}] }, } } } self.assertIn( "**prop1:** (array of (string)/(integer))", get_meta_doc(self.meta, schema), )
def test_get_meta_doc_handles_types_as_list(self): """get_meta_doc renders types which have a list value.""" schema = { "properties": { "prop1": { "type": ["boolean", "array"], "items": { "oneOf": [{ "type": "string" }, { "type": "integer" }] }, } } } assert ("**prop1:** (boolean/array of (string/integer))" in get_meta_doc(self.meta, schema))
def test_get_meta_doc_returns_restructured_text(self): """get_meta_doc returns restructured text for a cloudinit schema.""" full_schema = copy(self.required_schema) full_schema.update( { "properties": { "prop1": { "type": "array", "description": "prop-description", "items": {"type": "integer"}, } } } ) doc = get_meta_doc(self.meta, full_schema) self.assertEqual( dedent( """ name ---- **Summary:** title description **Internal name:** ``id`` **Module frequency:** frequency **Supported distros:** debian, rhel **Config schema**: **prop1:** (array of integer) prop-description **Examples**:: ex1: [don't, expand, "this"] # --- Example2 --- ex2: true """ ), doc, )
def test_get_meta_doc_handles_flattening_defs(self): """get_meta_doc renders $defs.""" schema = { "$defs": { "prop1object": { "type": "object", "properties": { "subprop": { "type": "string" } }, } }, "properties": { "prop1": { "$ref": "#/$defs/prop1object" } }, } assert ("**prop1:** (object)\n\n **subprop:** (string)\n" in get_meta_doc(self.meta, schema))
def test_label_overrides_property_name(self): """get_meta_doc overrides property name with label.""" schema = { "properties": { "prop1": { "type": "string", "label": "label1", }, "prop_no_label": { "type": "string", }, "prop_array": { "label": "array_label", "type": "array", "items": { "type": "object", "properties": { "some_prop": { "type": "number" }, }, }, }, }, "patternProperties": { "^.*$": { "type": "string", "label": "label2", } }, } meta_doc = get_meta_doc(self.meta, schema) assert "**label1:** (string)" in meta_doc assert "**label2:** (string" in meta_doc assert "**prop_no_label:** (string)" in meta_doc assert "Each item in **array_label** list" in meta_doc assert "prop1" not in meta_doc assert ".*" not in meta_doc
def test_get_meta_doc_handles_enum_types(self): """get_meta_doc converts enum types to yaml and delimits with '/'.""" schema = {"properties": {"prop1": {"enum": [True, False, "stuff"]}}} self.assertIn("**prop1:** (true/false/stuff)", get_meta_doc(self.meta, schema))
def test_get_meta_doc_handles_multiple_types(self): """get_meta_doc delimits multiple property types with a '/'.""" schema = {"properties": {"prop1": {"type": ["string", "integer"]}}} self.assertIn("**prop1:** (string/integer)", get_meta_doc(self.meta, schema))
MODULE_DESCRIPTION, "distros": distros, "frequency": PER_INSTANCE, "examples": [ dedent("""\ ssh_import_id: - user - gh:user - lp:user """) ], } __doc__ = get_meta_doc(meta) def handle(_name, cfg, cloud, log, args): if not is_key_in_nested_dict(cfg, "ssh_import_id"): log.debug("Skipping module named ssh-import-id, no 'ssh_import_id'" " directives found.") return elif not subp.which(SSH_IMPORT_ID_BINARY): log.warning( "ssh-import-id is not installed, but module ssh_import_id is " "configured. Skipping module.") return # import for "user: XXXXX"
"config": { "type": "object", "description": dedent( """\ Any supported zypo.conf key is written to /etc/zypp/zypp.conf'""" ), }, }, "minProperties": 1, # Either config or repo must be provided "additionalProperties": False, # only repos and config allowed } }, } __doc__ = get_meta_doc(meta, schema) # Supplement python help() LOG = logging.getLogger(__name__) def _canonicalize_id(repo_id): repo_id = repo_id.replace(" ", "_") return repo_id def _format_repo_value(val): if isinstance(val, bool): # zypp prefers 1/0 return 1 if val else 0 if isinstance(val, (list, tuple)): return "\n ".join([_format_repo_value(v) for v in val])
def test_get_meta_doc_handles_enum_types(self, sub_schema, expected): """get_meta_doc converts enum types to yaml and delimits with '/'.""" schema = {"properties": {"prop1": sub_schema}} assert expected in get_meta_doc(self.meta, schema)
"enum": [ "boot-new-instance", "boot-legacy", "boot", "hotplug", ], }, } }, } }, } }, } __doc__ = get_meta_doc(meta, schema) HOTPLUG_UDEV_PATH = "/etc/udev/rules.d/10-cloud-init-hook-hotplug.rules" HOTPLUG_UDEV_RULES_TEMPLATE = """\ # Installed by cloud-init due to network hotplug userdata ACTION!="add|remove", GOTO="cloudinit_end" LABEL="cloudinit_hook" SUBSYSTEM=="net", RUN+="{libexecdir}/hook-hotplug" LABEL="cloudinit_end" """ def handle(_name, cfg, cloud, log, _args): validate_cloudconfig_schema(cfg, schema) network_hotplug_enabled = (