How to validate Azure resource moves using PowerShell

How to validate Azure resource moves using PowerShell

How to validate Azure resource moves using PowerShell

The validate move resources API operation in Azure lets you pre-validate a potential move without actually moving any resources. This can be helpful when planning complex move scenarios.

In this tutorial, you’ll learn how to invoke the validate move operation using the Invoke-RestMethod PowerShell command and how to view the validation results.


To follow along with this tutorial, you’ll need the following:

  • A workstation with PowerShell 7.1 and the Az module installed. I’m using a Windows 10 workstation with PowerShell 7.1 and Az 5.8.0.
  • The appropriate permissions in Azure.
  • A source resource group containing at least one resource.
  • A destination resource group.

Gather the required information

The validateMoveResources API endpoint requires the following information:

  • Your Azure access token.
  • The ResourceId of the source resource group: rg-source in this example.
  • The Id of one or more source resources (which must be in the source resource group). I am using a single storage account resource called st-source in this example.
  • The ResourceId of the destination resource group: rg-dest in this example.

The following code connects to Azure using Connect-AzAccount and stores your access token in a variable ($Token).


# Store the access token as a Secure String, as this is required by the
# Invoke-RestMethod command later.
$Token = (Get-AzAccessToken).Token | ConvertTo-SecureString -AsPlainText -Force

The ResourceId of the source and destination resource groups, as well as the source storage account Id, can be stored in variables ($SourceGroupId, $SourceResourceId, and $DestGroupId), as below.

You may need to switch between subscriptions using the Set-AzContext command, depending on your Azure configuration.

$SourceGroupId = (Get-AzResourceGroup -Name "rg-source").ResourceId
$SourceResourceId = (Get-AzStorageAccount -Name "st-source" -ResourceGroupName "rg-source").Id
$DestGroupId = (Get-AzResourceGroup -Name "rg-dest").ResourceId

Send the initial request to the move validation API endpoint

To start the move validation task, you’ll send a POST request to the API endpoint. This request must include a JSON object as the body; for example:

 "resources": ["<resource-id-1>", "<resource-id-2>"],
 "targetResourceGroup": "/subscriptions/<subscription-id>/resourceGroups/<target-group>"

You can create the request body using the variables you stored in the previous step. The code below first creates a PowerShell hashtable ($Body) representing the data, and then converts the hashtable to a JSON object ($JsonBody).

$Body = @{
    resources = @($SourceResourceId)
    targetResourceGroup = $DestGroupId
$JsonBody = $Body | ConvertTo-Json -Depth 5 

With the $JsonBody variable now stored, you can issue the POST request to start the asynchronous validation task. The following command builds the required Uri using the $SourceGroupId variable, specifies the $JsonBody variable as the request body, and uses the $Token variable to include the Azure access key.

This example uses PowerShell parameter splatting. If you’re unfamiliar with this concept, check out my recent post here.

$Params = @{
    Uri = "$SourceGroupId/validateMoveResources?api-version=2019-05-10"
    Body = $JsonBody
    Method = "Post"
    Authentication = "Bearer"
    Token = $Token
    ContentType = "application/json"
    ResponseHeadersVariable = "ResHeaders"
Invoke-RestMethod @Params

If successful, this command won’t produce any output to the console.

Retrieving the results of the validation task

When the previous command completed, it created a variable containing the HTTP headers from the response ($ResHeaders). $ResHeaders contains a Location property, which you can use to retrieve the task results, as follows.

You don’t need to specify the Method parameter when sending a GET request with Invoke-RestMethod, as it’s the default option.

$Params = @{
    Uri = $ResHeaders.Location[0]
    Authentication = "Bearer"
    Token = $Token
    ContentType = "application/json"
    StatusCodeVariable = "StatusCode"
Invoke-RestMethod @Params

If the validation succeeds, the API returns a 204 HTTP response code with no content. You can check the status code by printing the $StatusCode variable to the console. If the validation detects issues, it’ll return an error; for instance:

Invoke-RestMethod: {"error":{"code":"MissingRegistrationsForTypes","message":"The subscription '037d15db-9c32-4493-a4dd-65054fc5a44f' is not registered for resource types 'Microsoft.Storage/storageAccounts (westeurope)'."}}


In this tutorial, you’ve learned how to use the Invoke-RestMethod PowerShell cmdlet to validate potential resource moves in Azure.

I hope this has been informative for you and thank you for reading!