xref: /spdk/test/json_config/config_filter.py (revision b69e3ff279affbf4cbc4a09fa1f9c6c2b72397ff)
1#!/usr/bin/env python3
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2018 Intel Corporation
4#  All rights reserved.
5#
6
7import sys
8import json
9import argparse
10from collections import OrderedDict
11
12
13def sort_json_object(o):
14    if isinstance(o, dict):
15        sorted_o = OrderedDict()
16        """ Order of keys in JSON object is irrelevant but we need to pick one
17        to be able to compare JSONS. """
18        for key in sorted(o.keys()):
19            sorted_o[key] = sort_json_object(o[key])
20        return sorted_o
21    if isinstance(o, list):
22        """ Keep list in the same order but sort each item """
23        return [sort_json_object(item) for item in o]
24    else:
25        return o
26
27
28def filter_methods(do_remove_global_rpcs):
29    global_rpcs = [
30        'dsa_scan_accel_module',
31        'iscsi_set_options',
32        'nvmf_set_config',
33        'nvmf_set_max_subsystems',
34        'nvmf_create_transport',
35        'nvmf_set_crdt',
36        'bdev_set_options',
37        'bdev_wait_for_examine',
38        'bdev_iscsi_set_options',
39        'bdev_nvme_set_options',
40        'bdev_nvme_set_hotplug',
41        'sock_impl_set_options',
42        'sock_set_default_impl',
43        'framework_set_scheduler',
44        'accel_crypto_key_create',
45        'accel_assign_opc',
46        'accel_set_options',
47        'dpdk_cryptodev_scan_accel_module',
48        'dpdk_cryptodev_set_driver',
49        'virtio_blk_create_transport',
50        'iobuf_set_options',
51        'bdev_raid_set_options',
52        'fsdev_set_opts',
53    ]
54
55    data = json.loads(sys.stdin.read())
56    out = {'subsystems': []}
57    for s in data['subsystems']:
58        if s['config']:
59            s_config = []
60            for config in s['config']:
61                m_name = config['method']
62                is_global_rpc = m_name in global_rpcs
63                if do_remove_global_rpcs != is_global_rpc:
64                    s_config.append(config)
65        else:
66            s_config = None
67        out['subsystems'].append({
68            'subsystem': s['subsystem'],
69            'config': s_config,
70        })
71
72    print(json.dumps(out, indent=2))
73
74
75def check_empty():
76    data = json.loads(sys.stdin.read())
77    if not data:
78        raise EOFError("Can't read config!")
79
80    for s in data['subsystems']:
81        if s['config']:
82            print("Config not empty")
83            print(s['config'])
84            sys.exit(1)
85
86
87if __name__ == "__main__":
88    parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
89    parser.add_argument('-method', dest='method', default=None,
90                        help="""One of the methods:
91check_empty
92    check if provided configuration is logically empty
93delete_global_parameters
94    remove pre-init configuration (pre framework_start_init RPC methods)
95delete_configs
96    remove post-init configuration (post framework_start_init RPC methods)
97sort
98    remove nothing - just sort JSON objects (and subobjects but not arrays)
99    in lexicographical order. This can be used to do plain text diff.""")
100
101    args = parser.parse_args()
102    if args.method == "delete_global_parameters":
103        filter_methods(True)
104    elif args.method == "delete_configs":
105        filter_methods(False)
106    elif args.method == "check_empty":
107        check_empty()
108    elif args.method == "sort":
109        """ Wrap input into JSON object so any input is possible here
110        like output from bdev_get_bdevs RPC method"""
111        o = json.loads('{ "the_object": ' + sys.stdin.read() + ' }')
112        print(json.dumps(sort_json_object(o)['the_object'], indent=2))
113    else:
114        raise ValueError("Invalid method '{}'\n\n{}".format(args.method, parser.format_help()))
115