diff options
author | Chad Smith <chad.smith@canonical.com> | 2023-02-09 15:50:33 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-09 15:50:33 -0700 |
commit | 55686b977570a6de69bef51c1e1a9d452333995d (patch) | |
tree | 0b36881db29374d18ac7728b348fbb229147455f /cloudinit/safeyaml.py | |
parent | b923a1c4fe740e9142d2c16b269d692a69919c0d (diff) | |
download | cloud-init-git-55686b977570a6de69bef51c1e1a9d452333995d.tar.gz |
cli: schema also validate vendordata*.
cloud-init schema --annotate now walks any valid
user-data, vendor-data and vendor2-data to report
whether any of these cloud-config files provide invalid
or deprecated schema values.
Also, fix a bug in nested mapping annotations to
properly report the full nested indexed schema path.
The following now can be annotated without KeyErrors:
users:
- default
- lock-passwd: false
name: root
Diffstat (limited to 'cloudinit/safeyaml.py')
-rw-r--r-- | cloudinit/safeyaml.py | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/cloudinit/safeyaml.py b/cloudinit/safeyaml.py index 368ac861..4a3b6c84 100644 --- a/cloudinit/safeyaml.py +++ b/cloudinit/safeyaml.py @@ -25,6 +25,27 @@ class _CustomSafeLoader(yaml.SafeLoader): return super().construct_scalar(node) +def _fix_nested_map_index(new_key_path, marks): + new_marks = [] + for mark in marks: + if "." not in mark.path: + new_marks.append(mark) + continue + path_prefix, _path_idx = mark.path.rsplit(".", 1) + if new_key_path not in mark.path and path_prefix in mark.path: + new_marks.append( + SchemaPathMarks( + # Replace only the first match of path_prefix + mark.path.replace(path_prefix, new_key_path, 1), + mark.start_mark, + mark.end_mark, + ) + ) + else: + new_marks.append(mark) + return new_marks + + class _CustomSafeLoaderWithMarks(yaml.SafeLoader): """A loader which provides line and column start and end marks for YAML. @@ -102,7 +123,30 @@ class _CustomSafeLoaderWithMarks(yaml.SafeLoader): if line_num not in self.schemamarks_by_line: self.schemamarks_by_line[line_num] = [marks] else: - self.schemamarks_by_line[line_num].append(marks) + if line_num == sequence_item.end_mark.line: + self.schemamarks_by_line[line_num].append(marks) + else: # Incorrect multi-line mapping or sequence object. + for inner_line in range( + line_num, sequence_item.end_mark.line + ): + if inner_line in self.schemamarks_by_line: + schema_marks = self.schemamarks_by_line[inner_line] + new_marks = _fix_nested_map_index( + node_key_path, schema_marks + ) + if ( + inner_line == line_num + and schema_marks[0].path != node_key_path + ): + new_marks.insert( + 0, + SchemaPathMarks( + node_key_path, + schema_marks[0].start_mark, + schema_marks[-1].end_mark, + ), + ) + self.schemamarks_by_line[inner_line] = new_marks return sequence def get_single_data(self): |