Do you have any tips on reversing a json dictionary?
I have a map of IPv4 addresses to environments and I would like to have a map of
environments to IPv4s.
1
2
3
4
5
6
7
|
{
"192.0.2.131" : "TEST-NET-1",
"198.51.100.151" : "TEST-NET-2",
"198.51.100.146" : "TEST-NET-2",
"203.0.113.146" : "TEST-NET-3",
"203.0.113.21" : "TEST-NET-3"
}
|
Would become:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
{
"TEST-NET-1": [
"192.0.2.131"
],
"TEST-NET-2": [
"198.51.100.146",
"198.51.100.151"
],
"TEST-NET-3": [
"203.0.113.146",
"203.0.113.21"
]
}
|
I think that is too complex to do naively in policy. jq
is really good for
working with JSON and I found an answer of how to swap key and value of an
object using jq stackoverflow.
We can use mapdata()
to do that same conversion from within policy.
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
|
bundle agent example_mapdata_jq_reverse_key_values
{
vars:
"policy_hub_zone_data" data => '{
"192.0.2.131" : "TEST-NET-1",
"198.51.100.151" : "TEST-NET-2",
"198.51.100.146" : "TEST-NET-2",
"203.0.113.146" : "TEST-NET-3",
"203.0.113.21" : "TEST-NET-3"
}';
"jq" string => "/usr/bin/jq 'to_entries \
| map( {(.value) : {(.key):null} }) \
| reduce .[] as $item ({}; . * $item) \
| to_entries \
| map({key:.key, value:(.value|keys)}) \
| from_entries '";
"rev"
data => mapdata( "json_pipe",
'$(jq)',
policy_hub_zone_data );
# Since mapdata returns an array, you need to pick out the first element
"picked" data => mergedata( "rev[0]" );
reports:
"$(with)" with => string_mustache( "{{ %-top- }}", "picked");
}
bundle agent __main__
{
methods:
"example_mapdata_jq_reverse_key_values";
}
|
Running that policy produces the reversed map:
R: {
"TEST-NET-1": [
"192.0.2.131"
],
"TEST-NET-2": [
"198.51.100.146",
"198.51.100.151"
],
"TEST-NET-3": [
"203.0.113.146",
"203.0.113.21"
]
}