How to perform substring like function in jmespath on a string
Asked Answered
B

3

7
  • I would like to know if there is substring function one can leverage in JMESPATH (supported by az cli).
  • I have the below az cli request and I want to just extract the name of the linked subnet with a security group, but unlike other cloud providers azure doesn't store associated resources names the same way.

The name can be extracted in the subnet.id node which looks like below

$ az network nsg show -g my_group -n My_NSG --query "subnets[].id" -o json
[
  "/subscriptions/xxxxxx2/resourceGroups/my_group/providers/Microsoft.Network/virtualNetworks/MY-VNET/subnets/My_SUBNET"
]
  • I want to only extract "MY_SUBNET" from the the result.

I know there is something called search that is supposed to mimic substring (explained here https://github.com/jmespath/jmespath.jep/issues/5) but it didn't work for me .

$ az network nsg show -g my_group -n My_NSG  --query "subnets[].search(id,'@[120:-1]')" -o json
InvalidArgumentValueError: argument --query: invalid jmespath_type value: "subnets[].search(id,'@[120:-1]')"

CLIInternalError: The command failed with an unexpected error. Here is the traceback:
Unknown function: search()

Thank you


Edit :

I actually run the request including other elements that's why using substring with bash in a new line is not what I want . here's an example of the full query :

az network nsg show -g "$rg_name" -n "$sg_name" --query "{Name:name,Combo_rule_Ports:to_string(securityRules[?direction==\`Inbound\`].destinationPortRanges[]),single_rule_Ports:to_string(securityRules[?direction==\`Inbound\`].destinationPortRange),sub:subnets[].id,resourceGroup:resourceGroup}" -o json        

output

{
  "Combo_rule_Ports": "[]",
  "Name": "sg_Sub_demo_SSH",
  "resourceGroup": "brokedba",
  "single_rule_Ports": "[\"22\",\"80\",\"443\"]",
  "sub": [
    "/subscriptions/xxxxxxx/resourceGroups/brokedba/providers/Microsoft.Network/virtualNetworks/CLI-VNET/subnets/Sub_demo"
  ]
}
Breazeale answered 4/12, 2020 at 17:32 Comment(2)
I suspect this is because, unlike in python, a string is not a list of characters in JMESPath, so you cannot use the slicing technique on one string.Lamarckian
well that sucks!Breazeale
A
2

I had a similar problem with EventGrid subscriptions and used jq to transform JSON returned by the az command. As a result, you get an JSON array.

az eventgrid event-subscription list -l $location -g $resourceGroup --query "[].{
     Name:name,
     Container:deadLetterDestination.blobContainerName,
     Account:deadLetterDestination.resourceId
  }" \
  | jq '[.[] | { Name, Container, Account: (.Account | capture("storageAccounts/(?<name>.+)").name) }]'

The expression Account: (.Account | capture("storageAccounts/(?<name>.+)").name) transforms the original resourceId from the Azure CLI.

# From Azure resourceId...
"Account": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/my-resource-group/providers/Microsoft.Storage/storageAccounts/mystorageaccount"
# .. to Azure Storage Account name
"Account": "mystorageaccount"

I've adapted the approach from How to extract a json value substring with jq.

Anjaanjali answered 27/5, 2021 at 6:55 Comment(1)
Thanks for this, I needed to pull the subcription guid from the resource's Id, and so I setup 'SubId' from 'Id' as follows : [.[] | { Name, Rgrp, InstKey, SubId: (.Id | capture("/subscriptions/(?<id>.[-,0-9,a-f]*)").id) }]Miracidium
K
2

cut can be used to extract desired values:

az network nsg show -g my_group -n My_NSG --query "subnets[].id|[0]" -o json | cut -d"/" -f11
Kennith answered 8/10, 2021 at 2:28 Comment(0)
M
1

If you run Azure CLI in bash, here are string manipulation operations you can do:

Following syntax deletes the longest match of $substring from the front of $string

${string##substring}

In this case, you can retrieve the subnet like this.

var=$(az network nsg show -g nsg-rg -n nsg-name --query "subnets[].id"  -o tsv)
echo ${var##*/}

enter image description here

For more information, you could refer to https://www.thegeekstuff.com/2010/07/bash-string-manipulation/

Miriam answered 7/12, 2020 at 2:17 Comment(4)
Hi @nancy-xiong , thanks for the suggestion . the command does display the subnet indeed however I asked for a jmespath option because I have other columns to display display from the query along with the subnet as my output is table (all in one line) .Breazeale
Just like the feature request you linked, I haven't know other jmespath option yet. Based on my experience, this is a simple way to extract the substring in a string result, and don't need to write a complicated logic expression, then you can pass the result into a variable and reference it in your CLI scripts anywhere.Miriam
Read JMESPath Tutorial, it seems that we can extract and transform elements from a JSON document but it's not possible to modify or extract the substring in the value of key or value in a JSON output, we only could catch the full value of the key or value. So, for this issue, do you still have any questions?Miriam
Nancy, in my specific case and I can update my OP. I needed to have them all in one line (that's why I specified jmespath way not shell). the subnet can be extracted through the name element on the subnet resource but I wanted to show in my bash that the nsg I created has been associated to the right subnet . so far I have the output in json but it's ugly like all other ids on azure by the way . - My goal was to display in table mode and get rid of all non relevant sections so the could be clean as the full id will have the row exceed the screen width.Breazeale

© 2022 - 2024 — McMap. All rights reserved.