Skip to content

Image Version Clarification and potential cloning/copying opportunity.#430

Open
mbiver wants to merge 1 commit intoMicrosoftDocs:mainfrom
mbiver:patch-13
Open

Image Version Clarification and potential cloning/copying opportunity.#430
mbiver wants to merge 1 commit intoMicrosoftDocs:mainfrom
mbiver:patch-13

Conversation

@mbiver
Copy link
Contributor

@mbiver mbiver commented Mar 5, 2026

The original article talks about "Create an image in one tenant using the source image in another tenant", but that's not really accurate. the guide is showing how to create an image version and doesn't even address the part about creating the image definition. I think we need to add some clarity to this section calling out the differences between image definitions and image versions. Also, is there an opportunity to provide some additional scripting/guidance around "cloning" either a complete gallery, or just specific image definitions/version in the gallery, etc. something like the scripting below might be able to be used, but of course would need to be checked.


# Variables (update as needed)
$SrcSub      = "SOURCE_SUBSCRIPTION_ID"
$SrcRG       = "SOURCE_RG_NAME"
$SrcGallery  = "SOURCE_GALLERY_NAME"
$DstSub      = "DEST_SUB_ID"
$DstRG       = "DEST_RG_NAME"
$DstGallery  = "DEST_GALLERY_NAME"
$DstLocation = "DEST_LOCATION"

# Sign in (if not already) and set destination subscription
az login
az account set --subscription $DstSub

# 1. Create target gallery if it doesn't exist
if (az sig show --resource-group $DstRG --gallery-name $DstGallery --query name -o tsv 2>$null) {
   Write-Output "Target gallery '$DstGallery' already exists in '$DstRG'."
} else {
   Write-Output "Creating target gallery '$DstGallery' in '$DstRG' ($DstLocation)..."
   az sig create --resource-group $DstRG --gallery-name $DstGallery --location $DstLocation --description "Cloned from $SrcGallery"
   Write-Output "Target gallery created."
}

# 2. Switch to source subscription and list image definitions
az account set --subscription $SrcSub
$defs = az sig image-definition list --resource-group $SrcRG --gallery-name $SrcGallery --query "[].name" -o tsv | Where-Object { $_ }

# 3. Loop through each image definition
foreach ($def in $defs) {
   Write-Output "`n*** Cloning Image Definition '$def' ***"

   # Read source properties

   $pub     = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "identifier.publisher" -o tsv)
   $offer   = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "identifier.offer"     -o tsv)
   $sku     = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "identifier.sku"       -o tsv)
   $osType  = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "osType"               -o tsv)
   $osState = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "osState"              -o tsv)
   $hv      = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "hyperVGeneration"     -o tsv)

   # Retrieve all features and format as "Name=Value" pairs
   $featureJson = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "features" -o json)
   $featureJson
   $features    = ($featureJson | ConvertFrom-Json | ForEach-Object { "$($_.name)=$($_.value)" }) -join " "
$features


# Join the array of lines into one JSON string
$json = ($featureJson -join "`n")

# Parse the JSON into objects
$features = ConvertFrom-Json -InputObject $json

# Build "Name=value Name=value" with booleans normalized to lowercase
$featuresString = ($features | ForEach-Object { $sv = [string]$_.value; if ($_.value -is [bool]) { $val = ($_.value).ToString().ToLower() } elseif ($sv -match '^(?i:true|false)$') { $val = $sv.ToLower() } else { $val = $sv }; "$($_.name)=$val" }) -join ' '

# Show the result (e.g., SecurityType=TrustedLaunch DiskControllerTypes=SCSI IsAcceleratedNetworkSupported=true)
$featuresString


   # Create definition in destination with all features
   az account set --subscription $DstSub
   az sig image-definition create --resource-group $DstRG --gallery-name $DstGallery --gallery-image-definition $def --publisher $pub --offer $offer --sku $sku --os-type $osType --os-state $osState --hyper-v-generation $hv --features $featuresString --location $DstLocation
   Write-Output "Created image definition '$def' in target gallery."

   # 4. Loop through versions
   az account set --subscription $SrcSub
   $vers = az sig image-version list --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "[].name" -o tsv | Where-Object { $_ }

   foreach ($ver in $vers) {
       Write-Output " -> Copying version '$ver'..."

       $id        = (az sig image-version show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --gallery-image-version $ver --query "id"                         -o tsv)
       $loc       = (az sig image-version show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --gallery-image-version $ver --query "location"                   -o tsv)
       $saType    = (az sig image-version show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --gallery-image-version $ver --query "publishingProfile.storageAccountType" -o tsv)
       $replicas  = (az sig image-version show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --gallery-image-version $ver --query "publishingProfile.replicaCount"      -o tsv)
       if (-not $saType)   { $saType   = "Standard_LRS" }
       if (-not $replicas) { $replicas = 1 }

       # Create version in destination
       az account set --subscription $DstSub
       az sig image-version create --resource-group $DstRG --gallery-name $DstGallery --gallery-image-definition $def --gallery-image-version $ver --location $loc --image-version $id --storage-account-type $saType --replica-count $replicas
       Write-Output "    Successfully created version '$ver'."
   }
}

The original article talks about "Create an image in one tenant using the source image in another tenant", but that's not really accurate.  the guide is showing how to create an image version and doesn't even address the part about creating the image definition.  I think we need to add some clarity to this section calling out the differences between image definitions and image versions.  Also, is there an opportunity to provide some additional scripting/guidance around "cloning" either a complete gallery, or just specific image definitions/version in the gallery, etc.  something like the scripting below might be able to be used, but of course would need to be checked.

```

# Variables (update as needed)
$SrcSub      = "SOURCE_SUBSCRIPTION_ID"
$SrcRG       = "SOURCE_RG_NAME"
$SrcGallery  = "SOURCE_GALLERY_NAME"
$DstSub      = "DEST_SUB_ID"
$DstRG       = "DEST_RG_NAME"
$DstGallery  = "DEST_GALLERY_NAME"
$DstLocation = "DEST_LOCATION"

# Sign in (if not already) and set destination subscription
az login
az account set --subscription $DstSub

# 1. Create target gallery if it doesn't exist
if (az sig show --resource-group $DstRG --gallery-name $DstGallery --query name -o tsv 2>$null) {
   Write-Output "Target gallery '$DstGallery' already exists in '$DstRG'."
} else {
   Write-Output "Creating target gallery '$DstGallery' in '$DstRG' ($DstLocation)..."
   az sig create --resource-group $DstRG --gallery-name $DstGallery --location $DstLocation --description "Cloned from $SrcGallery"
   Write-Output "Target gallery created."
}

# 2. Switch to source subscription and list image definitions
az account set --subscription $SrcSub
$defs = az sig image-definition list --resource-group $SrcRG --gallery-name $SrcGallery --query "[].name" -o tsv | Where-Object { $_ }

# 3. Loop through each image definition
foreach ($def in $defs) {
   Write-Output "`n*** Cloning Image Definition '$def' ***"

   # Read source properties

   $pub     = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "identifier.publisher" -o tsv)
   $offer   = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "identifier.offer"     -o tsv)
   $sku     = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "identifier.sku"       -o tsv)
   $osType  = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "osType"               -o tsv)
   $osState = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "osState"              -o tsv)
   $hv      = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "hyperVGeneration"     -o tsv)

   # Retrieve all features and format as "Name=Value" pairs
   $featureJson = (az sig image-definition show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "features" -o json)
   $featureJson
   $features    = ($featureJson | ConvertFrom-Json | ForEach-Object { "$($_.name)=$($_.value)" }) -join " "
$features


# Join the array of lines into one JSON string
$json = ($featureJson -join "`n")

# Parse the JSON into objects
$features = ConvertFrom-Json -InputObject $json

# Build "Name=value Name=value" with booleans normalized to lowercase
$featuresString = ($features | ForEach-Object { $sv = [string]$_.value; if ($_.value -is [bool]) { $val = ($_.value).ToString().ToLower() } elseif ($sv -match '^(?i:true|false)$') { $val = $sv.ToLower() } else { $val = $sv }; "$($_.name)=$val" }) -join ' '

# Show the result (e.g., SecurityType=TrustedLaunch DiskControllerTypes=SCSI IsAcceleratedNetworkSupported=true)
$featuresString


   # Create definition in destination with all features
   az account set --subscription $DstSub
   az sig image-definition create --resource-group $DstRG --gallery-name $DstGallery --gallery-image-definition $def --publisher $pub --offer $offer --sku $sku --os-type $osType --os-state $osState --hyper-v-generation $hv --features $featuresString --location $DstLocation
   Write-Output "Created image definition '$def' in target gallery."

   # 4. Loop through versions
   az account set --subscription $SrcSub
   $vers = az sig image-version list --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --query "[].name" -o tsv | Where-Object { $_ }

   foreach ($ver in $vers) {
       Write-Output " -> Copying version '$ver'..."

       $id        = (az sig image-version show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --gallery-image-version $ver --query "id"                         -o tsv)
       $loc       = (az sig image-version show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --gallery-image-version $ver --query "location"                   -o tsv)
       $saType    = (az sig image-version show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --gallery-image-version $ver --query "publishingProfile.storageAccountType" -o tsv)
       $replicas  = (az sig image-version show --resource-group $SrcRG --gallery-name $SrcGallery --gallery-image-definition $def --gallery-image-version $ver --query "publishingProfile.replicaCount"      -o tsv)
       if (-not $saType)   { $saType   = "Standard_LRS" }
       if (-not $replicas) { $replicas = 1 }

       # Create version in destination
       az account set --subscription $DstSub
       az sig image-version create --resource-group $DstRG --gallery-name $DstGallery --gallery-image-definition $def --gallery-image-version $ver --location $loc --image-version $id --storage-account-type $saType --replica-count $replicas
       Write-Output "    Successfully created version '$ver'."
   }
}
```
@mbiver
Copy link
Contributor Author

mbiver commented Mar 5, 2026

@microsoft-github-policy-service agree

@prmerger-automator
Copy link
Contributor

@mbiver : Thanks for your contribution! The author(s) and reviewer(s) have been notified to review your proposed change.

@mbiver
Copy link
Contributor Author

mbiver commented Mar 5, 2026

@microsoft-github-policy-service agree company="Microsoft"

@learn-build-service-prod
Copy link
Contributor

Learn Build status updates of commit 14e2dbc:

✅ Validation status: passed

File Status Preview URL Details
articles/virtual-machines/image-version.md ✅Succeeded

For more details, please refer to the build report.

@ttorble ttorble requested a review from Copilot March 5, 2026 16:52
@ttorble
Copy link
Contributor

ttorble commented Mar 5, 2026

@sandeepraichura

Can you review the proposed changes?

IMPORTANT: When the changes are ready for publication, adding a #sign-off comment is the best way to signal that the PR is ready for the review team to merge.

#label:"aq-pr-triaged"
@MicrosoftDocs/public-repo-pr-review-team

@prmerger-automator prmerger-automator bot added the aq-pr-triaged C+L Pull Request Review Team label label Mar 5, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions
Copy link

This pull request has been inactive for at least 14 days. If you are finished with your changes, don't forget to sign off. See the contributor guide for instructions.
Get Help
Docs Support Teams Channel
Resolve Merge Conflict

@github-actions github-actions bot added the inactive This PR is inactive for more than 14 days label Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

aq-pr-triaged C+L Pull Request Review Team label azure-virtual-machines/svc Change sent to author do-not-merge gallery/subsvc inactive This PR is inactive for more than 14 days

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants