As a software engineer, I’m working with Azure on a daily basis. Like most things in my daily computing life, I choose the terminal (and keyboard) over a GUI (and mouse). My development and interaction with Azure is no different. One of the tools that I use the most is the Azure CLI. As a Linux user, this is the best way for me to quickly and efficiently work with Azure resources.
I’ve been using the Azure CLI for years, and over this time I’ve picked up a few things that I think could be helpful for other Azure CLI users.
Discovery with tab completion
My shell of choice is bash, and with bash I’m able to have full tab completion. Being able to <Tab> <Tab>
for completion is a huge time-saver.
For instance, if I want to list VM image SKUs but I don’t know exactly the command groups I need, here’s how I’d figure it out:
1
$ az <Tab><Tab>
I see that vm
is probably the command group I want. So then I just continue the exercise:
1
$ az vm <Tab><Tab>
I continue until I get to the command that I want:
1
$ az vm image <Tab><Tab>
And in that output I see list-skus
, which is exactly what I need.
Discovery with find
Something that I think a lot of people don’t know about is the command find
. It searches through all examples for your keyword. This is helpful if you want to use examples for quick command discovery:
1
2
3
4
5
6
7
8
9
10
11
12
13
$ az find certificate
Finding examples...
Here are the most common ways to use [certificate]:
List certificates in a specified key vault. (autogenerated)
az keyvault certificate list --vault-name myvault
Manage Batch certificates.
az batch certificate
Gets information about a certificate. (autogenerated)
az keyvault certificate show --name mycertificate --vault-name myvault
Here I did a find on “certificate”, and it showed me a few Key Vault examples that probably point me in the right direction with the right command groups.
--help
Finding the command(s) you need is only half the battle. The other half is knowing what to do with them. This might seem obvious, but the --help
switch shows you all of the parameters that you could use (and what are required).
What I wanted to highlight here is my terminal workflow for this. In the top window I’ll page through the help with az vm create --help | less
and in the bottom window I’ll type my desired command:
This is the easiest way I’ve found to ad hoc command construction.
--output table
JSON is great for passing around data between software, but it’s not fun to view with human eyes. When visually parsing data output, I find that it’s easiest to use --output table
for comfortable consumption:
1
2
3
4
5
$ az group list -o table
Name Location Status
------------- ---------- ---------
thstringtest1 eastus Succeeded
thstringtest2 eastus Succeeded
Verify your subscription!
This only applies if you deal with multiple subscriptions (which is fairly common). Check to make sure you’re in the right subscription with az account show
! Or even better, dump the current subscription in your PS1
so it’s always in front of your eyes.
Querying and grep’ing
I’m a big fan of getting what I want the quickest possible way. For me, native tools like grep
will always be my go-to:
1
$ az group list -o table | grep -E '^thstring' | awk '{print $1}'
That gives me the resource group names that start with “thstring”. This can also be achieved with the built-in querying of the Azure CLI:
1
$ az group list --query "[?starts_with(name, 'thstring')].{Name:name}" -o tsv
I’ve found that grep
is great for simple applications (like filtering resource group names), but for more complex querying then using --query
with the CLI is more flexible.
List all resources in a resource group (the “portal” experience)
One of the nice things about the portal is you can click on a resource group and see a list of all resources. That’s possible with the Azure CLI as well, and a really great way to find out what exactly lives in that resource group you’re wondering about:
1
2
3
4
5
6
7
8
9
10
$ az resource list -g rg1 -o table
Name ResourceGroup Location Type Status
--------------- -------------- ---------- --------------------------------------- --------
disk1 rg1 eastus Microsoft.Compute/disks
vm1 rg1 eastus Microsoft.Compute/virtualMachines
adapter1 rg1 eastus Microsoft.Network/networkInterfaces
nsg1 rg1 eastus Microsoft.Network/networkSecurityGroups
pip1 rg1 eastus Microsoft.Network/publicIPAddresses
vnet1 rg1 eastus Microsoft.Network/virtualNetworks
storageaccount1 rg1 eastus Microsoft.Storage/storageAccounts
Now at a quick glance I can see all of the resources in this resource group!
Create wrapper functions
I saved this one for the last one, but it is something that has allowed me to maximize my efficiency. The Azure CLI is great, but a lot of my daily tasks are very repetitive (get all resource groups that belong to me, create VMs in a very specific way, install deb packages on my VMs, etc.). If I was to type out these individual Azure CLI commands all day every day, that would be a lot.
The solution I have created for myself is the az-cli-helpers. This is nothing more than (a lot of) functions that wrap the behavior of the Azure CLI and are designed for me to work as efficiently as possible.
A good example of this is when I need to create another VM from a current VM that I’ve been working on.
Manual steps with the Azure CLI
- Deprovision VM
- Generalize VM
- Create image from source VM
- Create new VM from image
Manual steps with my az-cli-helpers functions
az_vm_create_from_vm
This small example alone shows you how much time I save daily.
I’m not telling you that you should use my bash functions. In fact, the opposite. My az-cli-helpers
repo is worthless to you. My daily workflow as an Azure Linux provisioning engineer is extremely unlikely to be similar to yours (unless you’re my teammate). The time investment in creating wrapper workflow shell functions has a big return on it.
Summary
Hopefully in this article you were able to learn a thing or two that might help you save some time with the Azure CLI or make it a better experience. Sometimes the point-and-click GUI might seem easier, but taking the time to familiarize (and customize) your terminal experience I think you’ll find that is where the true efficiency is.