I have a json file pulled from an HPE iLO interface with the snmp configuration. It looks like:
[
{
"Comments": {
"BIOSDate": "01/23/2021",
"BIOSFamily": "U30",
"Manufacturer": "HPE",
"Model": "ProLiant DL380 Gen10",
"SerialNumber": "5UNESX378",
"iLOVersion": "iLO 5 v2.65"
}
},
{
"#HpeiLOSnmpService.v2_3_0.HpeiLOSnmpService": {
"/redfish/v1/Managers/1/SnmpService/": {
"#odata.context": "/redfish/v1/$metadata#HpeiLOSnmpService.HpeIloSnmpService",
"#odata.id": "/redfish/v1/Managers/1/SnmpService",
"Actions": {
"#HpeIloSnmpService.SendSNMPTestAlert": {
"target": "/redfish/v1/Managers/1/SnmpService/Actions/HpeILOSnmpService.SendSNMPTestAlert/"
}
},
"AlertDestinationAssociations": [
{
"SNMPAlertProtocol": "SNMPv3Trap",
"SecurityName": null
}
],
"AlertDestinations": [
"1.2.3.4",
"5.6.7.8",
null,
null
],
"AlertsEnabled": true,
"Name": "SnmpService"
},
"PeriodicHSATrapConfig": "Disabled",
"ReadCommunities": [
"",
"",
""
],
"Role": "",
"RoleDetail": "",
"SNMPAlertDestinations": {
"#odata.id": "/redfish/v1/Managers/1/SnmpService/SNMPAlertDestinations/"
},
"SNMPUsers": {
"#odata.id": "/redfish/v1/Managers/1/SnmpService/SNMPUsers/"
},
"SNMPv1Enabled": false,
"SNMPv3EngineID": "0x8920000000E3028329E002033",
"SNMPv3InformRetryAttempt": 2,
"SNMPv3InformRetryIntervalSeconds": 15,
"Status": {
"State": "Enabled"
},
"TrapCommunities": [
"",
"",
"",
"",
"",
"",
""
],
"TrapSourceHostname": "Manager",
"Users": [
{
"AuthProtocol": "MD5",
"PrivacyProtocol": "DES",
"SecurityName": "",
"UserEngineID": null
},
{
"AuthProtocol": "MD5",
"PrivacyProtocol": "DES",
"SecurityName": "",
"UserEngineID": null
},
{
"AuthProtocol": "SHA",
"PrivacyProtocol": "AES",
"SecurityName": "oneview_4849283d97929392",
"UserEngineID": null
},
{
"AuthProtocol": "MD5",
"PrivacyProtocol": "DES",
"SecurityName": "",
"UserEngineID": null
}
]
}
}
]
I want to select an element in the Users array that has SecurityName set to "" and change that element. I don't need the Comments portion. So, I try to select the section starting with #HpeiLOSnmpService.v2_3_0.HpeiLOSnmpService with:
jq -r '.[] | .#HpeiLOSnmpService.v2_3_0.HpeiLOSnmpService' snmp.json
but it gives me everything without the enclosing array. Anyone have a suggestion?
Thanks!
# starts a comment and your jq program degenerates to .[]|. which is identical to the program .[] (|. is a no-op/the identity filter). This program will simply select all values from the input.
You must quote certain characters, such as #, when they are part of propery names. The following will work with your JSON file:
jq -r '.[] | ."#HpeiLOSnmpService".v2_3_0.HpeiLOSnmpService'
Thanks. Using the quotes around the key with a '#' works. Ultimately, selecting the SecurityName that was unset was done with:
jq -r '.Users[] | select (.SecurityName == "") | {"AuthProtocol":.AuthProtocol,"PrivacyProtocol":.PrivacyProtocol,"SecurityName":.SecurityName,"UserEngineID":.UserEngineID}'
Related
I have a file like below (excerpt)
cat input.json
{
"Metrics": [
{
"Namespace": "CWAgent",
"MetricName": "disk_used_percent",
"Dimensions": [
{
"Name": "path",
"Value": "/aem"
},
{
"Name": "host",
"Value": "uat2-author01.uat.cloud.abc.com.au"
},
{
"Name": "device",
"Value": "mapper/aem-aem"
},
{
"Name": "fstype",
"Value": "ext4"
}
]
},
{
"Namespace": "CWAgent",
"MetricName": "mem_used_percent",
"Dimensions": [
{
"Name": "host",
"Value": "uat2-dispatch02.uat.cloud.abc.com.au"
}
]
}
]
}
As you can see the "Dimensions" is a list of json objects of varying length. I am required to print each objects under "Metrics" in a single line like below -
CWAgent|disk_used_percent|path:/aem|host:uat2-author01.uat.cloud.abc.com.au|device:mapper/aem-aem|fstype:ext4
CWAgent|mem_used_percent|host:uat2-dispatch02.uat.cloud.abc.com.au
I used this -
cat input.json | jq -r ".Metrics[] | .Namespace + \"|\" + .MetricName + \"|\" + (.Dimensions[] | .Name + \":\" + .Value + \"|\")"
And the output is like below:
CWAgent|disk_used_percent|path:/aem|
CWAgent|disk_used_percent|host:uat2-author01.uat.cloud.abc.com.au|
CWAgent|disk_used_percent|device:mapper/aem-aem|
CWAgent|disk_used_percent|fstype:ext4|
CWAgent|mem_used_percent|host:uat2-dispatch02.uat.cloud.abc.com.au|
As you can see, we are getting 4 lines for first object each having different object under Dimensions. Can anyone please suggest what will be the jq command to get desired output. I am novice in jq and wasted too much time on this experimenting.
Thanks,
Bijitesh
You're looking for this:
jq -r '.Metrics[] | [.Namespace, .MetricName] + (.Dimensions | map("\(.Name):\(.Value)")) | join("|")' input.json
I am trying to add a new user in below json which matches group NP01-RW. i am able to do without NP01-RW but not able to select users under NP01-RW and return updated json.
{
"id": 181,
"guid": "c9b7dbde-63de-42cc-9840-1b4a06e13364",
"isEnabled": true,
"version": 17,
"service": "Np-Hue",
"name": "DATASCIENCE-CUROPT-RO",
"policyType": 0,
"policyPriority": 0,
"isAuditEnabled": true,
"resources": {
"database": {
"values": [
"hive_cur_acct_1dev",
"hive_cur_acct_1eng",
"hive_cur_acct_1rwy",
"hive_cur_acct_1stg",
"hive_opt_acct_1dev",
"hive_opt_acct_1eng",
"hive_opt_acct_1stg",
"hive_opt_acct_1rwy"
],
"isExcludes": false,
"isRecursive": false
},
"column": {
"values": [
"*"
],
"isExcludes": false,
"isRecursive": false
},
"table": {
"values": [
"*"
],
"isExcludes": false,
"isRecursive": false
}
},
"policyItems": [
{
"accesses": [
{
"type": "select",
"isAllowed": true
},
{
"type": "update",
"isAllowed": true
},
{
"type": "create",
"isAllowed": true
},
{
"type": "drop",
"isAllowed": true
},
{
"type": "alter",
"isAllowed": true
},
{
"type": "index",
"isAllowed": true
},
{
"type": "lock",
"isAllowed": true
},
{
"type": "all",
"isAllowed": true
},
{
"type": "read",
"isAllowed": true
},
{
"type": "write",
"isAllowed": true
}
],
"users": [
"user1",
"user2",
"user3"
],
"groups": [
"NP01-RW"
],
"conditions": [],
"delegateAdmin": false
},
{
"accesses": [
{
"type": "select",
"isAllowed": true
}
],
"users": [
"user1"
],
"groups": [
"NP01-RO"
],
"conditions": [],
"delegateAdmin": false
}
],
"denyPolicyItems": [],
"allowExceptions": [],
"denyExceptions": [],
"dataMaskPolicyItems": [],
"rowFilterPolicyItems": [],
"options": {},
"validitySchedules": [],
"policyLabels": [
"DATASCIENCE-CurOpt-RO_NP01"
]
}
below is what i have tried but it returns part of the JSON matching NP01-RW and not full JSON
jq --arg username "$sync_userName" '.policyItems[] | select(.groups[] | IN("NP01-RO")).users += [$username]' > ${sync_policyName}.json
Operator precedence in jq is not always intuitive. Your program is parsed as:
.policyItems[] | (select(.groups[] | IN("NP01-RO")).users += [$username])
Which first streams all policyItems and only then changes them, leaving you with policyItems only in the output.
You need to make sure that the stream selects the correct values, which you can then assign:
(.policyItems[] | select(.groups[] | IN("NP01-RO")).users) += [$username]
This will do the assignment, but still return the full input (.).
Here is the jq I have, it just wants to build a new element and then append it to an array,
[.[] | . as { foo: $foo1, bar: $bar1} |
{
names: ([
$foo1 | range(0;length) as $i |
{ key: ($foo1[$i]) }
] + [{ key: $bar1 }])
} |
{
values: .names,
}
]
And suppose I have a json like this,
{
"foo":[
"key1",
"key2"
],
"bar": "key3"
}
This will generate a json file like this,
[
{
"values": [
{
"key": "key1"
},
{
"key": "key2"
},
{
"key": "key3"
}
]
}
]
But the element should be only appended when the $bar is not an empty string, can I do something like this?
[.[] | . as { foo1: $foo1, bar1: $bar1 if $bar != ""}
...
or do it when is appended,
names: ([
$foo1 | range(0;length) as $i |
{ key: ($foo1[$i]) }
] + [{ key: $bar1 }] | if $bar != "")
thanks in advance for any help!
You could just use select to filter out that case
jq '[{values: (.foo + [.bar | select(. != "")]) | map({key:.})}]'
If .bar == "key3", it prints
[
{
"values": [
{
"key": "key1"
},
{
"key": "key2"
},
{
"key": "key3"
}
]
}
]
If .bar == "", it prints
[
{
"values": [
{
"key": "key1"
},
{
"key": "key2"
}
]
}
]
If .bar does not exist, it will print
[
{
"values": [
{
"key": "key1"
},
{
"key": "key2"
},
{
"key": null
}
]
}
]
If in this last case you want to have the same result as with .bar == "", then change . != "" to values != "" in the filter to consider only values that are not null (or to strings != "" to only consider (non-empty) strings and disregard any other type).
I have the following data
Command output:
| jq '.rrsets[]'
{
"comments": [],
"name": "name1.",
"records": [
{
"content": "10.10.10.10",
"disabled": false
}
],
"ttl": 60,
"type": "A"
}
{
"comments": [],
"name": "name2.",
"records": [
{
"content": "20.20.20.20",
"disabled": false
}
],
"ttl": 60,
"type": "CNAME"
}
I want to get names where type is A.
Help, tell me how to do this?
| jq '.rrsets[] | with_entries(select(.key== "name", .value == "A"))'
{
"name": "name1."
}
{
"name": "name2.",
"type": "A"
}
Displays all the lines, but I only need where type = A
I'm not sure if this is what you are looking for, but wouldn't simply ... | select(.type == "A") do the trick?
... | jq '.rrsets[] | select(.type == "A")'
{
"comments": [],
"name": "name1.",
"records": [
{
"content": "10.10.10.10",
"disabled": false
}
],
"ttl": 60,
"type": "A"
}
Demo
And then just get the .name if you want only that (using -r to get rid of the JSON formatting):
... | jq -r '.rrsets[] | select(.type == "A").name'
name1.
Demo
I want to parse terraform.tfstate (where openstack provider is used), to return instance name and it's internal + floating IP (if assigned).
First select what we are interested in:
jq -r '.modules?[]|.resources[]?|select(.type == "openstack_compute_floatingip_v2", .type == "openstack_compute_instance_v2")' < terraform.tfstate
For simplicity, pre-parsed example with the above part (one FIP and one instance):
{
"type": "openstack_compute_floatingip_v2",
"depends_on": [
"openstack_networking_router_interface_v2.management"
],
"primary": {
"id": "48b039fc-a9fa-4672-934a-32d6d267f280",
"attributes": {
"address": "209.66.89.143",
"fixed_ip": "10.10.10.5",
"id": "48b039fc-a9fa-4672-934a-32d6d267f280",
"instance_id": "597e75e8-834d-4f05-8408-e2e6e733577e",
"pool": "public",
"region": "RegionOne"
},
"meta": {},
"tainted": false
},
"deposed": [],
"provider": "provider.openstack"
}
{
"type": "openstack_compute_instance_v2",
"depends_on": [
"openstack_compute_floatingip_v2.management",
"openstack_compute_secgroup_v2.ssh_only",
"openstack_networking_network_v2.management"
],
"primary": {
"id": "597e75e8-834d-4f05-8408-e2e6e733577e",
"attributes": {
"access_ip_v4": "10.10.10.5",
"access_ip_v6": "",
"all_metadata.%": "1",
"all_metadata.habitat": "sup",
"availability_zone": "nova",
"flavor_id": "eb36e84e-17c1-42ab-b359-4380f6f524ae",
"flavor_name": "m1.large",
"force_delete": "false",
"id": "597e75e8-834d-4f05-8408-e2e6e733577e",
"image_id": "c574aeed-e47c-4fb7-9da0-75550b76ee56",
"image_name": "ubuntu-16.04",
"key_pair": "vault-etcd_test_tf",
"metadata.%": "1",
"metadata.habitat": "sup",
"name": "ctl01",
"network.#": "1",
"network.0.access_network": "false",
"network.0.fixed_ip_v4": "10.10.10.5",
"network.0.fixed_ip_v6": "",
"network.0.floating_ip": "",
"network.0.mac": "02:c6:61:f9:ee:7e",
"network.0.name": "management",
"network.0.port": "",
"network.0.uuid": "f2468669-e321-4eb4-9ede-003e362a8988",
"region": "RegionOne",
"security_groups.#": "1",
"security_groups.1845949017": "vault-etcd_test_ssh_only",
"stop_before_destroy": "false"
},
"meta": {
"e2bfb730-ecaa-11e6-8f88-34363bc7c4c0": {
"create": 1800000000000,
"delete": 1800000000000,
"update": 1800000000000
}
},
"tainted": false
},
"deposed": [],
"provider": "provider.openstack"
}
Required is to take from "type": "openstack_compute_floatingip_v2" replace .primary.attributes.address and .fixed_ip and from corresponding .instance_id the .name.
So, sth like:
{"address": "209.66.89.143",
"fixed_ip": "10.10.10.5",
"name": "ctl01"}
Well, I came with an idea while using walk, but miss how to actually assign the proper value from corresponding instance id:
jq -r "$(cat floating.jq)" terraform.tfstate
floating.jq:
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
.modules?[]|.resources[]?|select(.type ==
"openstack_compute_floatingip_v2", .type ==
"openstack_compute_instance_v2")|
.primary|walk( if type == "object" and .attributes.address then
.attributes.instance_id |= "REFERRED VALUE HERE") else . end)
Let's assume the two related objects are in a file named two.json. Then one way to merge the information from both objects is using the -s command-line option, e.g.
jq -s '
(.[0].primary.attributes | {address, fixed_ip})
+ {name: .[1].primary.attributes.name}' two.json
Output
With your example input, the output would be:
{
"address": "209.66.89.143",
"fixed_ip": "10.10.10.5",
"name": "ctl01"
}