{Core} Pass JSON output between commands #6
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Pass JSON output between commands
Goal
The goal is to facilitate the interaction between commands, like how PowerShell uses variables to store objects.
For example, PowerShell CmdLet Add-AzVirtualNetworkSubnetConfig takes
-VirtualNetwork <PSVirtualNetwork>
. See Create a virtual network using PowerShell.Current status
Currently, with Azure CLI users need to append
--query id --output tsv
to a command to extract the information from the output JSON and pass it to the next command, as documented in Tips for using Azure CLI effectively.For example, we want to add a newly created subnet to a storage account's network rule. See Configure Azure Storage firewalls and virtual networks.
With CLI in Bash:
With Azure PowerShell:
We want to eliminate the usage of
--query id --output tsv
and achieve the same effect.Changes
In this PR, a new factory
get_json_query_type(query='id')
is added for command arguments. It has one parameter as the JMESPath query string, which is used to query the input JSON string. If the input is not a valid JSON, the original value is used.Then we can pipe the output JSON to the next command with either variable style or pipeline style.
Variable style
Bash
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameters.html
PowerShell
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_variables
Variable style doesn't work well with PowerShell due to a bug in PowerShell. See appendix for more information.
Pipeline style
Bash
https://www.gnu.org/software/bash/manual/html_node/Pipelines.html
az network vnet subnet show -g rg1 --vnet-name vnet1 -n subnet1 | az storage account network-rule add -g rg1 --account-name st0507 --subnet @-
PowerShell
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pipelines
As symbol
@
is interpreted by PowerShell as splatting symbol, so quote it or escape it.More information about quoting can be found at https://github.com/Azure/azure-cli/blob/dev/doc/use_cli_effectively.md#quoting-issues
Problems
Some problems can emerge with this approach:
The JSON can't be used to populate multiple parameters. For example, populating
--resource-group
and--vnet-name
when a vnet JSON is provided:az network vnet subnet create --resource-group rg1 --vnet-name $vnet -n subnet1
Possible solutions:
--vnet
which takes a resource ID by itself, likeThis can conflict with the newly introduced local context which may automatically populate
--resource-group
and--vnet-name
Appendix
Quoting issue with PowerShell
Due to issue PowerShell/PowerShell#1995, double quotes within the JSON string are lost when calling a native
.exe
file.As you can see, the workaround makes the command awkward. Of course we can do some replacement to the JSON string to workaround the PowerShell issue but it takes more efforts, thus counteracting the benefit we gain from variable style.