5
  • 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"
  ]
}
koss
  • 107
  • 1
  • 7

3 Answers3

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.

sschmeck
  • 7,233
  • 4
  • 40
  • 67
  • 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/(?.[-,0-9,a-f]*)").id) }] – Peter Nov 30 '21 at 12:12
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
monkut
  • 42,176
  • 24
  • 124
  • 155
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/

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Nancy
  • 26,865
  • 3
  • 18
  • 34
  • 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) . – koss Dec 07 '20 at 19:25
  • 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. – Nancy Dec 08 '20 at 07:16
  • Read [JMESPath Tutorial](https://jmespath.org/tutorial.html#slicing), 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? – Nancy Dec 09 '20 at 05:52
  • 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. – koss Dec 09 '20 at 06:16