File: netplan_schema_check.py

package info (click to toggle)
cloud-init 25.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 12,412 kB
  • sloc: python: 135,894; sh: 3,883; makefile: 141; javascript: 30; xml: 22
file content (91 lines) | stat: -rw-r--r-- 3,458 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import argparse
import os
import yaml

from jsonschema import Draft4Validator


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="""
This script validates netplan example files against the cloud-init networkv2
schema.  The goal is to provide an easy way to track drift between networkv2
and netplan.

Netplan does not provide a centralized schema file to compare against directly,
but does maintain a reasonably comprehensive examples directory.  This script
relies on that directory to glean the netplan schema.
            """,
        formatter_class=argparse.RawTextHelpFormatter,
    )
    parser.add_argument(
        "--schema-file",
        required=True,
        help="""
The cloud-init networkv2 schema file found in
cloudinit/config/schemas/schema-network-config-v2.json
in this repository.
        """,
    )
    parser.add_argument(
        "--netplan-examples",
        required=True,
        help="""
The examples/ directory in the netplan repo.  The most
recent netplan repo can be cloned from
https://github.com/canonical/netplan.
        """,
    )
    return parser.parse_args()


def validate_netplan_against_networkv2(schema_file, netplan_examples):
    """
    This script validates netplan example files against the cloud-init
    networkv2 schema.  The goal is to provide an easy way to track drift
    between networkv2 and netplan.

    Netplan does not provide a centralized schema file to compare against
    directly, but does maintain a reasonably comprehensive examples directory.
    This script relies on that directory to glean the netplan schema.

    There are two arguments required for this script.  The first is schema_file
    which should point to the cloud-init networkv2 schema file found in
    cloudinit/config/schemas/schema-network-config-v2.json in this repository.
    The second is netplan_examples which should point to the examples/
    directory in the netplan repo.  The most recent netplan repo can be cloned
    from https://github.com/canonical/netplan.
    """
    networkv2_schema = None
    with open(schema_file) as f:
        networkv2_schema = yaml.safe_load(f)
    validator = Draft4Validator(networkv2_schema)

    error_obj = {}
    for walk_tuple in os.walk(netplan_examples):
        filenames = walk_tuple[2]
        for fname in filenames:
            if fname.endswith(".yaml"):
                with open(netplan_examples + fname) as netplan_f:
                    netplan_example = yaml.safe_load(netplan_f)
                    errors = validator.iter_errors(netplan_example)
                    for e in errors:
                        schema_path_str = "-".join(map(str, e.schema_path))
                        if schema_path_str not in error_obj:
                            error_obj[schema_path_str] = {}
                        if e.message not in error_obj[schema_path_str]:
                            error_obj[schema_path_str][e.message] = set()
                        error_obj[schema_path_str][e.message].add(fname)

    # clean up error_obj for human readability
    for schema_path in error_obj:
        for message in error_obj[schema_path]:
            error_obj[schema_path][message] = list(
                error_obj[schema_path][message]
            )
    print(yaml.dump(error_obj))


if __name__ == "__main__":
    args = parse_args()
    validate_netplan_against_networkv2(args.schema_file, args.netplan_examples)