How to filter unique values with jq? - bash

I'm using the gcloud describe command to get metadata information about instances.What's the best way to filter the json response with jq to get the name of the instance - if it contains "kafka" as a key.
.name + " " + .metadata.items[]?.key | select(contains("kafka"))'
Basically if items contains kafka print name.This is just a small excerpt from the json file.
"metadata": {
"fingerprint": "xxxxx=",
"items": [
{
"key": "kafka",
"value": "xxx="
},
{
"key": "some_key",
"value": "vars"
}
],
"kind": "compute#metadata"
},
"name": "instance-name",
"networkInterfaces": [
{
"accessConfigs": [
{
"kind": "compute#accessConfig",
"name": "External NAT",
"natIP": "ip",
"type": "ONE_TO_ONE_NAT"
}
],
"kind": "compute#networkInterface",
"name": "",
"network": xxxxx
}
],

I'm sure this is possible with jq, but in general working with gcloud lists is going to be easier using the built-in formatting and filtering:
$ gcloud compute instances list \
--filter 'metadata.items.key:kafka' \
--format 'value(name)'
--filter tells you which items to pick; in this case, it grabs the instance metadata, looks at the items, and checks the keys for those containing kafka (use = instead to look for keys that are exactly kafka).
--format tells you to grab just one value() (as opposed to a table, JSON, YAML) from each matching item; that item will be the name of the instance.
You can learn more by running gcloud topic filters, gcloud topic formats, and gcloud topic projections.

Here is a simple jq solution using if and any:
if .metadata.items | any(.key == "kafka") then . else empty end
| .name

Related

Bash getting escaped variable key value with script

I want to use jq to get value's out of a the Traefik API service. The output of the service looks like this:
{
"loadBalancer": {
"servers": [
{
"url": "http://172.18.0.19:3000"
},
{
"url": "http://172.18.0.17:3000"
},
{
"url": "http://172.20.0.3:3000"
}
],
"healthCheck": {
"path": "/health",
"interval": "10s",
"timeout": "10s",
"followRedirects": true
},
"passHostHeader": true
},
"status": "enabled",
"serverStatus": {
"http://172.18.0.17:3000": "UP",
"http://172.18.0.19:3000": "UP",
"http://172.20.0.3:3000": "DOWN"
},
"provider": "docker",
"type": "loadbalancer"
}
I want to get the value of the serverStatus dynamically. First assigning a variable with the correct IP address from docker inspect. I'm using curl with jq to check if the container is being serviced.
The problem is when getting it with a variable I cannot seem to escape the special characters in the url key. Nothing is returned.
This is the command I use is:
TRAEFIK_URL="http://someurl.com/"
TRAEFIK_URL="'Authorization: Basic hashkey"
NEW_IPADDRESS=$(docker container inspect some_container_name | jq -r .[].NetworkSettings.Networks.proxy.IPAddress)
NEW_ENV_URL="http://${NEW_IPADDRESS}:3000"
curl --location --request GET "$TRAEFIK_URL" --header "$TRAEFIK_AUTH_HEADER" | jq -r '.serverStatus["${NEW_ENV_URL}"]'
I've tried using this command and some other obvious options but all didn't work.
jq -r .serverStatus[$NEW_ENV_URL]
I do get the correct value when I'm not using a variable to get the status using:
jq -r '.serverStatus["http://172.18.0.17:3000"]'
Any help is welcome.
Use the option --arg to pass arguments to jq.
jq --arg url http://172.18.0.17:3000 -r '.serverStatus[$url]'
Always use this option to avoid security problems by injections.
One of the preferred ways to pass specific environment variables into jq is using the --arg command-line option; in your case:
jq -r --arg url "${NEW_ENV_URL}" '.serverStatus[$url]'

jmeter json path Conditional Extraction at peer level

I'm using jmeter v2.13 and jp#gc - JSON Path Extractor.
Here is my JSON sample:
{
"views": [{
"id": 9701,
"name": " EBS: EAS: IDC (EAS MBT IDC)",
"canEdit": true,
"sprintSupportEnabled": true,
"filter": {
"id": 55464,
"name": "Filter for EBS: EAS: IDC & oBill Boar",
"query": "project = \"EBS: EAS: IDC\"",
"owner": {},
"canEdit": false,
"isOrderedByRank": true,
"permissionEntries": [{
"values": [{
"type": "Shared with the public",
"name": ""
}]
}]
},
"boardAdmins": {}
},
{}
]
}
Is it possible to extract views[x].id where there exists an entry views[x].filter.permissionEntries[*].values[*].type that equals Shared with the public?
How would I do it?
Thanks
JSON Query would look like this (I admit I didn't try it in JMeter)
$.views[?(#.filter[?(#.permissionEntries[?(#.values[?(#.type == "Shared with the public")])])])].id
Explanation:
We expect under root ($) to have views and for it to have property id. The rest (in []) are conditions to select only views items based on predefined condition. Hence $.views[conditions].id
Conditions in this case are coming one within the other, but main parts are:
We define condition as a filter ?(...)
We ask filter to look under current item (#) for a specific child item (.child), child may have its own conditions ([...]). Hence #.child[conditions]. That way we move through filter, permissionEntries, values
Finally we get to field values and filter it for a child type field with particular value Shared with the public. Hence #.type == "Shared with the public"
As you see it's not very intuitive, and JSON path is a bit limited. If this is a repetitive issue, and your JSON is even more complicated, you ay consider investing into a scriptable pre-processor (similar to the one explained here.

SoftLayer_Virtual_Guest_Block_Device_Template_Group::editObject update datacenters

The createFromExternalSource method does not allow you to specify a list of datacenters to enable the image to be used. I can get the image imported, but then when I then go to edit the image template to augment the datacenters, I always get:
{"error":"Object does not exist to execute method on.
(SoftLayer_Virtual_Guest_Block_Device_Template_Group::editObject)","code":"SoftLayer_Exception"}
Does anyone have a proper example of using editObject for SoftLayer_Virtual_Guest_Block_Device_Template_Group using JSON not XMLRPC like the slcli does?
Preferred if some has a curl example which updates attributes on SoftLayer_Virtual_Guest_Block_Device_Template_Group object would be awesome.
To update the datacenters of an image template you have to use the method “setAvailableLocations” of the service SoftLayer_Virtual_Guest_Block_Device_Template_Group.
The method editObject just edit an image template group's name and note.
You can use this curl example to update the datacenters of an imagen template:
curl -d #post.json -k https://[username]:[apiKey]#api.softlayer.com/rest/v3/SoftLayer_Virtual_Guest_Block_Device_Template_Group/1722867/setAvailableLocations.json | python -mjson.tool
You have to add in this curl example the json file “#post.json”, where is the image template body.
The json file must contain the following data:
{
"parameters": [
[
{
"id": 265592
},
{
"id": 814994
},
{
"id": 138124
},
{
"id": 154820
},
{
"id": 449600
}
]
]
}
To get the datacenters ids you can use this curl command example:
curl -k "https://[username]:[apiKey]#api.softlayer.com/rest/v3/SoftLayer_Location/getDatacenters.json" | python -mjson.tool

How to reference the Amazon Data Pipeline name?

Is it possible to use the name of an Amazon Data Pipeline as a variable inside the Data Pipeline itself? If yes, how can you do that?
Unfortunately, you can't refer to the name. You can refer to the pipeline ID using the expression #pipelineId. For example, you could define a ShellCommandActivity to print the pipeline ID:
{
"id": "ExampleActivity",
"name": "ExampleActivity",
"runsOn": { "ref": "SomeEc2Resource" },
"type": "ShellCommandActivity",
"command": "echo \"Hello from #{#pipelineId}\""
}

Cucumber: read a template with placeholders

I am writing a cucumber framework to test a set of API calls which use long JSON formatted parameters. I would like to hide the JSON in a template file in order to make the scenario easier for my users to read and DRYer, in that the templates may be used by other scenarios and feature files. The templates contain placeholders and I would like to rig the cucumber/ruby code to fill in the values defined in the table of examples. It appears that ERB is the closest thing to doing the replacement. However, I have not found a way to bind the definitions from the table of examples.
It may be that the only way around this is to run the feature file and template through a pre-processor which combines them and manufactures the final feature file. I am looking for a more elegant single step solution, if possible.
Example feature file code:
Feature: Create users
Scenario Outline: Test create a merchant user
Given I am logged in
When I send a :post request to "createUser" using the "Merchant" template:
Then the JSON response should have "$..status" with the text "success"
Examples:
| OrgName | KeyName | KeyValue |
| CClient_RMBP_0_UNIQ_ | paramX | TRUE |
| CClient_RMBP_1_UNIQ_ | paramY | some text |
| CClient_RMBP_2_UNIQ_ | paramZ | 12345 |
Sample Merchant.json File:
{
"Organization": {
"parameters": [
{
"key": "orgName",
"value": {
"value": "<OrgName>"
}
},
{
"key": "<KeyName>",
"value": {
"value": "<KeyValue>"
}
}
]
},
"parentOrganizationId": "1",
"User": {
"firstName": "Mary",
"lastName": "Smith",
"id": "<OrgName>",
"language": "en",
"locale": "US",
"primaryEmail": "primary#mailaddr.com",
"cellPhone": "1-123-456-7890"
},
"active": "true"
}
I prefer to hide any notion of the response format from the cucumber steps.
Instead i'd prefer to have the steps at a higher level and have validate methods within the step definitions.
e.g.
When I attempt to create a user using the <type> template
Then the response is successful and contains the user's details
and in my step definition I would have a validate_response method which grabs the last response and checks the user details against the input.

Resources