summaryrefslogtreecommitdiff
path: root/cloudinit/safeyaml.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/safeyaml.py')
-rw-r--r--cloudinit/safeyaml.py46
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):