Optimizing Windows Terminal for Sovereign Clouds

I work with Azure sovereign clouds (specifically Azure Government) every day, and I spend a lot of time using the Azure CLI inside of Windows Terminal. I was recently on an episode of Azure Friday talking about Azure Government with Scott Hanselman, which included a demo using the Azure CLI with Azure Government. After the recording was over, Scott and I were chatting and he mentioned a couple of suggestions to me that might enhance my (already heavily customized) Windows Terminal experience when working with sovereign clouds. Specifically his ideas were:

  • Leverage the Oh My Post Azure segment to show my current Azure CLI session
  • Dynamically change my terminal background image to make it more obvious which cloud I was currently connected to (i.e., Azure public vs. Azure Gov)

While those two things sounded great, neither was precisely supported "out of the box". (Side note: before I start diving into Oh My Posh in this post, I highly recommend checking out their docs for those who are not familiar).

Oh My Posh Azure Segment

The Oh My Posh Azure Segment will contextually display information about your current Azure CLI session like this:

Azure Segment default

This segment (in light blue above) shows me the currently logged in user and the name of my Azure subscription. However, it doesn't tell me which Azure cloud I'm logged into. Yes, it's pretty easy to know which usernames I use for Azure public vs. Azure Gov, but it's not obvious. Switching between Azure and Azure Government using the Azure CLI is done simply using these CLI commands:

az cloud set --name AzureCloud         # sets to Azure
az cloud set --name AzureUSGovernment  # sets to Azure Gov

The first challenge is that the environment name wasn't supported by the Oh My Posh Az segment. After a couple of emails with Jan De Dobbeleer (of Oh My Posh fame), and a blazingly fast turn-around on Jan's part for a new release, the Az segment was updated to use templating so that any property in the az account show command could be used. With this ability, my Az segment configuration now looks like this:

{
  "type": "az",
  "style": "powerline",
  "powerline_symbol": "\uE0B0",
  "foreground": "#000000",
  "background": "#9ec3f0",
  "properties": {
    "template": "{{.EnvironmentName}} | {{.Name}}",
    "prefix": " \uFD03 ",
    "include_folders": [
      "*\\\\az"
    ]
  }
},

Which results in a terminal prompt that looks like this:

Azure Segment with env

Now I can configure this to show whatever I want - which in this case is to show the environment name (AzureUSGovernment or AzureCloud) followed by the current subscription name.

One other thing to note is that I'm using the include_folders property in my configuration above. This is because segments like this can cause a little bit of a delay since they're invoking an az cli command every time it renders a prompt. So I wanted a quick way to turn the segment on/off on demand without having to mess with my oh-my-posh configuration. This enables me to just cd ~/az anytime I want to turn this segment on.

Dynamically Change Terminal Background

The oh-my-posh Azure segment now does exactly what I want, but wouldn't it be great to have an even more obvious way to see which cloud I was logged into? And be able to see it all the time rather than only when I'm in the ~/az directory? For example, notice in the screenshot below, I'm logged into regular Azure public ("AzureCloud" is showing as my environment in the Az segment) and the normal Azure icon is shown in the bottom right as my terminal background.

Azure Terminal public

I switch back and forth between Azure and Azure Gov frequently. Scott suggested that it would be cool to dynamically change that icon in the lower right to show that as well. However, integration between oh-my-posh and Windows Terminal isn't natively supported. But what about a more "brute force" approach? I could create a couple of functions in my PowerShell profile ($profile) that:

  1. Set the Azure cloud via the az cloud set command (the oh-my-posh Az segment will change accordingly)
  2. Set the Windows Terminal background image to change depending on cloud

The Windows Terminal doesn't have any magical API that you can programmatically manipulate. However, it does have a settings.json file that it watches for changes. So I can just change the backgroundImage property of the correct profile and that should do the trick. Here are the functions I added to my $profile:

function Set-AzureCloud() {
  param([string]$cloud, [string]$img)

  az cloud set --name $cloud

  # Set background for Windows Terminal
  $settingsPath = "$env:LocalAppData\Packages\Microsoft.WindowsTerminalPreview_*\LocalState\settings.json"
  $json = (Get-Content $settingsPath -Raw) | ConvertFrom-Json -Depth 32
  $psProfile = $json.profiles.list.Where({$_.name -eq 'PowerShell'})
  $($psProfile).backgroundImage = "$home\Dropbox\utils\terminal\$img"
  $json | ConvertTo-Json -Depth 32 | Set-Content (Get-Item $settingsPath).FullName
}

function Set-AzPublic {
  Set-AzureCloud 'AzureCloud' 'azure-tr-236x225.png'
}

function Set-AzGov {
  Set-AzureCloud 'AzureUSGovernment' 'ages-tr-236x225.png'
}

With that in place, it enables me to have nice PowerShell commands (with auto-completion) on my command line - Set-AzPublic and Set-AzGov - that enable me to do this:

Dynamic Terminal

(Note: the red-white-blue Azure logo is completely non-official and just something our team uses internally.)

For those looking to customize their own terminal, I recommend starting with Scott Hanselman's Ultimate PowerShell prompt. Additionally, I keep my terminal customizations (including all the code I showed in this post, and more) on my GitHub here.

Tweet Post Share Update Email RSS