forked from jsonnet-libs/xtd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
inspect.libsonnet
209 lines (194 loc) · 5.04 KB
/
inspect.libsonnet
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
local d = import 'doc-util/main.libsonnet';
{
local this = self,
'#': d.pkg(
name='inspect',
url='github.com/jsonnet-libs/xtd/inspect.libsonnet',
help='`inspect` implements helper functions for inspecting Jsonnet',
),
'#inspect':: d.fn(
|||
`inspect` reports the structure of a Jsonnet object with a recursion depth of
`maxDepth` (default maxDepth=10).
|||,
[
d.arg('object', d.T.object),
d.arg('maxDepth', d.T.number),
//d.arg('depth', d.T.number), // used for recursion, not exposing in docs
]
),
inspect(object, maxDepth=10, depth=0):
std.foldl(
function(acc, p)
acc + (
if std.isObject(object[p])
&& depth != maxDepth
then { [p]+:
this.inspect(
object[p],
maxDepth,
depth + 1
) }
else {
[
(if !std.objectHas(object, p)
then 'hidden_'
else '')
+ (if std.isFunction(object[p])
then 'functions'
else 'fields')
]+: [p],
}
),
std.objectFieldsAll(object),
{}
),
'#diff':: d.fn(
|||
`diff` returns a JSON object describing the differences between two inputs. It
attemps to show diffs in nested objects and arrays too.
Simple example:
```jsonnet
local input1 = {
same: 'same',
change: 'this',
remove: 'removed',
};
local input2 = {
same: 'same',
change: 'changed',
add: 'added',
};
diff(input1, input2),
```
Output:
```json
{
"add +": "added",
"change ~": "~[ this , changed ]",
"remove -": "removed"
}
```
|||,
[
d.arg('input1', d.T.any),
d.arg('input2', d.T.any),
]
),
diff(input1, input2)::
if input1 == input2
then ''
else if std.isArray(input1) && std.isArray(input2)
then
[
if input1[i] != input2[i]
then
this.diff(
input1[i],
input2[i]
)
else input2[i]
for i in std.range(0, std.length(input2) - 1)
if std.length(input1) > i
]
+ (if std.length(input1) < std.length(input2)
then [
'+ ' + input2[i]
for i in std.range(std.length(input1), std.length(input2) - 1)
]
else [])
+ (if std.length(input1) > std.length(input2)
then [
'- ' + input1[i]
for i in std.range(std.length(input2), std.length(input1) - 1)
]
else [])
else if std.isObject(input1) && std.isObject(input2)
then std.foldl(
function(acc, k)
acc + (
if k in input1 && input1[k] != input2[k]
then {
[k + ' ~']:
this.diff(
input1[k],
input2[k]
),
}
else if !(k in input1)
then {
[k + ' +']: input2[k],
}
else {}
),
std.objectFields(input2),
{},
)
+ {
[l + ' -']: input1[l]
for l in std.objectFields(input1)
if !(l in input2)
}
else '~[ %s ]' % std.join(' , ', [std.toString(input1), std.toString(input2)]),
'#filterObjects':: d.fn(
|||
`filterObjects` walks a JSON tree returning all matching objects in an array.
The `x` argument can either be an object or an array, other types will be
ignored.
|||,
args=[
d.arg('filter_func', d.T.func),
d.arg('x', d.T.any),
]
),
filterObjects(filter_func, x):
if std.isObject(x)
then
if filter_func(x)
then [x]
else
std.foldl(
function(acc, o)
acc + self.filterObjects(filter_func, x[o]),
std.objectFields(x),
[]
)
else if std.isArray(x)
then
std.flattenArrays(
std.map(
function(obj)
self.filterObjects(filter_func, obj),
x
)
)
else [],
'#filterKubernetesObjects':: d.fn(
|||
`filterKubernetesObjects` implements `filterObjects` to return all Kubernetes objects in
an array, assuming that Kubernetes object are characterized by having an
`apiVersion` and `kind` field.
The `object` argument can either be an object or an array, other types will be
ignored. The `kind` allows to filter out a specific kind, if unset all kinds will
be returned.
|||,
args=[
d.arg('object', d.T.any),
d.arg('kind', d.T.string, default=''),
]
),
filterKubernetesObjects(object, kind=''):
local objects = self.filterObjects(
function(object)
std.objectHas(object, 'apiVersion')
&& std.objectHas(object, 'kind'),
object,
);
if kind == ''
then objects
else
std.filter(
function(o) o.kind == kind,
objects
),
}