blob: 6d224ddffe461072ad0b42777433b3dd3467a5a4 [file] [log] [blame]
Ole Troan6a3064f2019-05-14 13:24:10 +02001#!/usr/bin/env python3
2
3import sys
4import os
5import ipaddress
6import yaml
7from pprint import pprint
8import re
9from jsonschema import validate
10import argparse
11from subprocess import run, PIPE
12
13# VPP feature JSON schema
14schema = {
15 "$schema": "http://json-schema.org/schema#",
16 "type": "object",
17 "properties": {
18 "name": {"type": "string"},
19 "description": { "type": "string" },
20 "maintainer": { "type": "string" },
21 "state": {"type": "string",
22 "enum": ["production", "experimental"]},
23 "features": { "$ref": "#/definitions/features" },
24 "missing": { "$ref": "#/definitions/features" },
25 "properties": { "type": "array",
26 "items": { "type": "string",
27 "enum": ["API", "CLI", "STATS", "MULTITHREAD"] },
28 },
29 },
30 "additionalProperties": False,
31 "definitions": {
32 "featureobject": {
33 "type": "object",
34 "patternProperties": {
35 "^.*$": { "$ref": "#/definitions/features" },
36 },
37 },
38 "features": {
39 "type": "array",
40 "items": {"anyOf": [{ "$ref": "#/definitions/featureobject" },
41 { "type": "string" },
42 ]},
43 "minItems": 1,
44 },
45 },
46}
47
48
49
50def filelist_from_git_status():
51 filelist = []
52 git_status = 'git status --porcelain */FEATURE.yaml'
53 rv = run(git_status.split(), stdout=PIPE, stderr=PIPE)
54 if rv.returncode != 0:
55 sys.exit(rv.returncode)
56
57 for l in rv.stdout.decode('ascii').split('\n'):
58 if len(l):
59 filelist.append(l.split()[1])
60 return filelist
61
62def filelist_from_git_ls():
63 filelist = []
64 git_ls = 'git ls-files :(top)*/FEATURE.yaml'
65 rv = run(git_ls.split(), stdout=PIPE, stderr=PIPE)
66 if rv.returncode != 0:
67 sys.exit(rv.returncode)
68
69 for l in rv.stdout.decode('ascii').split('\n'):
70 if len(l):
71 filelist.append(l)
72 return filelist
73
74def output_features(indent, fl):
75 for f in fl:
76 if type(f) is dict:
77 for k,v in f.items():
78 print('{}- {}'.format(' ' * indent, k))
79 output_features(indent + 2, v)
80 else:
81 print('{}- {}'.format(' ' * indent, f))
82
83def output_markdown(features):
84 for k,v in features.items():
85 print('# {}'.format(v['name']))
86 print('Maintainer: {} '.format(v['maintainer']))
87 print('State: {}\n'.format(v['state']))
88 print('{}\n'.format(v['description']))
89 output_features(0, v['features'])
90 if 'missing' in v:
91 print('\n## Missing')
92 output_features(0, v['missing'])
93 print()
94
95def main():
96 parser = argparse.ArgumentParser(description='VPP Feature List.')
97 parser.add_argument('--validate', dest='validate', action='store_true',
98 help='validate the FEATURE.yaml file')
99 parser.add_argument('--git-status', dest='git_status', action='store_true',
100 help='Get filelist from git status')
101 parser.add_argument('--all', dest='all', action='store_true',
102 help='Validate all files in repository')
103 parser.add_argument('--markdown', dest='markdown', action='store_true',
104 help='Output feature table in markdown')
105 parser.add_argument('infile', nargs='?', type=argparse.FileType('r'),
106 default=sys.stdin)
107 args = parser.parse_args()
108
109 features = {}
110
111 if args.git_status:
112 filelist = filelist_from_git_status()
113 elif args.all:
114 filelist = filelist_from_git_ls()
115 else:
116 filelist = args.infile
117
118 for featurefile in filelist:
119 featurefile = featurefile.rstrip()
120
121 # Load configuration file
122 with open(featurefile) as f:
123 cfg = yaml.load(f)
124 validate(instance=cfg, schema=schema)
125 features[featurefile] = cfg
126
127 if args.markdown:
128 output_markdown(features)
129
130if __name__ == '__main__':
131 main()