Browse code

Use JSON returns values to create RETURN docs

After running hacking/test-module to generate some output,
the JSON output can be fed into the return skeletion generator
to create an excellent starting point for RETURN docs

(cherry picked from commit 5e978b0f2b1008b6fefbe3da7df3192a49acc4ad)

Will Thames authored on 2017/09/11 14:19:50
Showing 1 changed files
1 1
new file mode 100755
... ...
@@ -0,0 +1,96 @@
0
+#!/usr/bin/env python
1
+
2
+# (c) 2017, Will Thames <will@thames.id.au>
3
+#
4
+# This file is part of Ansible
5
+#
6
+# Ansible is free software: you can redistribute it and/or modify
7
+# it under the terms of the GNU General Public License as published by
8
+# the Free Software Foundation, either version 3 of the License, or
9
+# (at your option) any later version.
10
+#
11
+# Ansible is distributed in the hope that it will be useful,
12
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+# GNU General Public License for more details.
15
+#
16
+# You should have received a copy of the GNU General Public License
17
+# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
18
+
19
+# return_skeleton_generator.py takes JSON output from a module and
20
+# and creates a starting point for the RETURNS section of a module.
21
+# This can be provided as stdin or a file argument
22
+#
23
+# The easiest way to obtain the JSON output is to use hacking/test-module
24
+#
25
+# You will likely want to adjust this to remove sensitive data or
26
+# ensure the `returns` value is correct, and to write a useful description
27
+
28
+from __future__ import print_function
29
+from collections import OrderedDict
30
+import json
31
+import sys
32
+import yaml
33
+
34
+
35
+# Allow OrderedDicts to be used when dumping YAML
36
+# https://stackoverflow.com/a/16782282/3538079
37
+def represent_ordereddict(dumper, data):
38
+    value = []
39
+
40
+    for item_key, item_value in data.items():
41
+        node_key = dumper.represent_data(item_key)
42
+        node_value = dumper.represent_data(item_value)
43
+
44
+        value.append((node_key, node_value))
45
+
46
+    return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', value)
47
+
48
+
49
+def get_return_data(key, value):
50
+    # The OrderedDict here is so that, for complex objects, the
51
+    # summary data is at the top before the contains information
52
+    returns_info = {key: OrderedDict()}
53
+    returns_info[key]['description'] = "FIXME *** add description for %s" % key
54
+    returns_info[key]['returned'] = "always"
55
+    if isinstance(value, dict):
56
+        returns_info[key]['type'] = 'complex'
57
+        returns_info[key]['contains'] = get_all_items(value)
58
+    elif isinstance(value, list) and value and isinstance(value[0], dict):
59
+        returns_info[key]['type'] = 'complex'
60
+        returns_info[key]['contains'] = get_all_items(value[0])
61
+    else:
62
+        returns_info[key]['type'] = type(value).__name__
63
+        returns_info[key]['sample'] = value
64
+        # override python unicode type to set to string for docs
65
+        if returns_info[key]['type'] == 'unicode':
66
+            returns_info[key]['type'] = 'string'
67
+    return returns_info
68
+
69
+
70
+def get_all_items(data):
71
+    items = sorted([get_return_data(key, value) for key, value in data.items()])
72
+    result = OrderedDict()
73
+    for item in items:
74
+        key, value = item.items()[0]
75
+        result[key] = value
76
+    return result
77
+
78
+
79
+def main(args):
80
+    yaml.representer.SafeRepresenter.add_representer(OrderedDict, represent_ordereddict)
81
+
82
+    if args:
83
+        src = open(args[0])
84
+    else:
85
+        src = sys.stdin
86
+
87
+    data = json.load(src, strict=False)
88
+    docs = get_all_items(data)
89
+    if 'invocation' in docs:
90
+        del(docs['invocation'])
91
+    print(yaml.safe_dump(docs, default_flow_style=False))
92
+
93
+
94
+if __name__ == '__main__':
95
+    main(sys.argv[1:])