Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/ms.compute.disks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ jobs:
- name: 'Using test file [${{ matrix.moduleTestFilePaths }}]'
uses: ./.github/actions/templates/validateModuleDeployment
with:
templateFilePath: '${{ env.modulePath }}/deploy.bicep'
parameterFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}'
templateFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}'
location: '${{ env.location }}'
resourceGroupName: '${{ env.resourceGroupName }}'
subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<#
.SYNOPSIS
Copy a VHD baked from a given image template to a given destination storage account blob container

.DESCRIPTION
Copy a VHD baked from a given image template to a given destination storage account blob container

.PARAMETER ImageTemplateName
Mandatory. The name of the image template

.PARAMETER ImageTemplateResourceGroup
Mandatory. The resource group name of the image template

.PARAMETER DestinationStorageAccountName
Mandatory. The name of the destination storage account

.PARAMETER DestinationContainerName
Optional. The name of the existing destination blob container

.PARAMETER VhdName
Optional. Specify a different name for the destination VHD file

.PARAMETER WaitForComplete
Optional. Run the command synchronously. Wait for the completion of the copy.

.EXAMPLE
Copy-VhdToStorageAccount -ImageTemplateName 'vhd-img-template-001-2022-07-29-15-54-01' -ImageTemplateResourceGroup 'validation-rg' -DestinationStorageAccountName 'vhdstorage001'

Copy a VHD created by image template 'vhd-img-template-001-2022-07-29-15-54-01' in resource group 'validation-rg' to destination storage account 'vhdstorage001' in blob container named 'vhds'. Save the VHD file as 'vhd-img-template-001-2022-07-29-15-54-01.vhd'.

.EXAMPLE
Copy-VhdToStorageAccount -ImageTemplateName 'vhd-img-template-001-2022-07-29-15-54-01' -ImageTemplateResourceGroup 'validation-rg' -DestinationStorageAccountName 'vhdstorage001' -VhdName 'vhd-img-template-001' -WaitForComplete

Copy a VHD baked by image template 'vhd-img-template-001-2022-07-29-15-54-01' in resource group 'validation-rg' to destination storage account 'vhdstorage001' in a blob container named 'vhds' and wait for the completion of the copy. Save the VHD file as 'vhd-img-template-001.vhd'.
#>

[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory = $true)]
[string] $ImageTemplateName,

[Parameter(Mandatory = $true)]
[string] $ImageTemplateResourceGroup,

[Parameter(Mandatory = $true)]
[string] $DestinationStorageAccountName,

[Parameter(Mandatory = $false)]
[string] $DestinationContainerName = 'vhds',

[Parameter(Mandatory = $false)]
[string] $VhdName = $ImageTemplateName,

[Parameter(Mandatory = $false)]
[switch] $WaitForComplete
)

begin {
Write-Debug ('{0} entered' -f $MyInvocation.MyCommand)

# Install required modules
$currentVerbosePreference = $VerbosePreference
$VerbosePreference = 'SilentlyContinue'
$requiredModules = @(
'Az.ImageBuilder',
'Az.Storage'
)
foreach ($moduleName in $requiredModules) {
if (-not ($installedModule = Get-Module $moduleName -ListAvailable)) {
Install-Module $moduleName -Repository 'PSGallery' -Force -Scope 'CurrentUser'
if ($installed = Get-Module -Name $moduleName -ListAvailable) {
Write-Verbose ('Installed module [{0}] with version [{1}]' -f $installed.Name, $installed.Version) -Verbose
}
} else {
Write-Verbose ('Module [{0}] already installed in version [{1}]' -f $installedModule[0].Name, $installedModule[0].Version) -Verbose
}
}
$VerbosePreference = $currentVerbosePreference
}

process {
# Retrieving and initializing parameters before the blob copy
Write-Verbose 'Initializing source storage account parameters before the blob copy' -Verbose
Write-Verbose ('Retrieving source storage account from image template [{0}] in resource group [{1}]' -f $imageTemplateName, $imageTemplateResourceGroup) -Verbose
Get-InstalledModule
$imgtRunOutput = Get-AzImageBuilderTemplateRunOutput -ImageTemplateName $imageTemplateName -ResourceGroupName $imageTemplateResourceGroup | Where-Object ArtifactUri -NE $null
$sourceUri = $imgtRunOutput.ArtifactUri
$sourceStorageAccountName = $sourceUri.Split('//')[1].Split('.')[0]
$storageAccountList = Get-AzStorageAccount
$sourceStorageAccount = $storageAccountList | Where-Object StorageAccountName -EQ $sourceStorageAccountName
$sourceStorageAccountContext = $sourceStorageAccount.Context
$sourceStorageAccountRGName = $sourceStorageAccount.ResourceGroupName
Write-Verbose ('Retrieving artifact uri [{0}] stored in resource group [{1}]' -f $sourceUri, $sourceStorageAccountRGName) -Verbose

Write-Verbose 'Initializing destination storage account parameters before the blob copy' -Verbose
$destinationStorageAccount = $storageAccountList | Where-Object StorageAccountName -EQ $destinationStorageAccountName
$destinationStorageAccountContext = $destinationStorageAccount.Context
$destinationBlobName = "$vhdName.vhd"
Write-Verbose ('Planning for destination blob name [{0}] in container [{1}] and storage account [{2}]' -f $destinationBlobName, $destinationContainerName, $destinationStorageAccountName) -Verbose

# Copying the VHD to a destination blob container
$resourceActionInputObject = @{
AbsoluteUri = $sourceUri
Context = $sourceStorageAccountContext
DestContext = $destinationStorageAccountContext
DestBlob = $destinationBlobName
DestContainer = $destinationContainerName
Force = $true
}

if ($PSCmdlet.ShouldProcess('Storage blob copy of VHD [{0}]' -f $destinationBlobName, 'Start')) {
$destBlob = Start-AzStorageBlobCopy @resourceActionInputObject
Write-Verbose ('Copied/initialized copy of VHD from URI [{0}] to container [{1}] in storage account [{2}]' -f $sourceUri, $destinationContainerName, $destinationStorageAccountName) -Verbose
}

if ($WaitForComplete) {
$destBlob | Get-AzStorageBlobCopyState -WaitForComplete
}
}

end {
Write-Debug ('{0} exited' -f $MyInvocation.MyCommand)
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<#
.SYNOPSIS
Create image artifacts from a given image template

.DESCRIPTION
Create image artifacts from a given image template

.PARAMETER ImageTemplateName
Mandatory. The name of the image template

.PARAMETER ImageTemplateResourceGroup
Mandatory. The resource group name of the image template

.PARAMETER NoWait
Optional. Run the command asynchronously

.EXAMPLE
Start-AzImageBuilderTemplate -ImageTemplateName 'vhd-img-template-001-2022-07-29-15-54-01' -ImageTemplateResourceGroup 'validation-rg'

Create image artifacts from image template 'vhd-img-template-001-2022-07-29-15-54-01' in resource group 'validation-rg' and wait for their completion

.EXAMPLE
Start-AzImageBuilderTemplate -ImageTemplateName 'vhd-img-template-001-2022-07-29-15-54-01' -ImageTemplateResourceGroup 'validation-rg' -NoWait

Start the creation of artifacts from image template 'vhd-img-template-001-2022-07-29-15-54-01' in resource group 'validation-rg' and do not wait for their completion
#>

[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory = $true)]
[string] $ImageTemplateName,

[Parameter(Mandatory = $true)]
[string] $ImageTemplateResourceGroup,

[Parameter(Mandatory = $false)]
[switch] $NoWait
)

begin {
Write-Debug ('{0} entered' -f $MyInvocation.MyCommand)

# Install required modules
$currentVerbosePreference = $VerbosePreference
$VerbosePreference = 'SilentlyContinue'
$requiredModules = @(
'Az.ImageBuilder'
)
foreach ($moduleName in $requiredModules) {
if (-not ($installedModule = Get-Module $moduleName -ListAvailable)) {
Install-Module $moduleName -Repository 'PSGallery' -Force -Scope 'CurrentUser'
if ($installed = Get-Module -Name $moduleName -ListAvailable) {
Write-Verbose ('Installed module [{0}] with version [{1}]' -f $installed.Name, $installed.Version) -Verbose
}
} else {
Write-Verbose ('Module [{0}] already installed in version [{1}]' -f $installedModule[0].Name, $installedModule[0].Version) -Verbose
}
}
$VerbosePreference = $currentVerbosePreference
}

process {
# Create image artifacts from existing image template
$resourceActionInputObject = @{
ImageTemplateName = $imageTemplateName
ResourceGroupName = $imageTemplateResourceGroup
}
if ($NoWait) {
$resourceActionInputObject['NoWait'] = $true
}
if ($PSCmdlet.ShouldProcess('Image template [{0}]' -f $imageTemplateName, 'Start')) {
$null = Start-AzImageBuilderTemplate @resourceActionInputObject
Write-Verbose ('Created/initialized creation of image artifacts from image template [{0}] in resource group [{1}]' -f $imageTemplateName, $imageTemplateResourceGroup) -Verbose
}
}

end {
Write-Debug ('{0} exited' -f $MyInvocation.MyCommand)
}
13 changes: 13 additions & 0 deletions modules/Microsoft.Compute/disks/.test/common/dependencies.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@description('Optional. The location to deploy resources to.')
param location string = resourceGroup().location

@description('Required. The name of the Managed Identity to create.')
param managedIdentityName string

resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
name: managedIdentityName
location: location
}

@description('The principal ID of the created managed identity')
output managedIdentityPrincipalId string = managedIdentity.properties.principalId
61 changes: 61 additions & 0 deletions modules/Microsoft.Compute/disks/.test/common/deploy.test.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
targetScope = 'subscription'

// ========== //
// Parameters //
// ========== //

@description('Optional. The name of the resource group to deploy for a testing purposes')
@maxLength(90)
param resourceGroupName string = 'ms.compute.images-${serviceShort}-rg'

@description('Optional. The location to deploy resources to')
param location string = deployment().location

@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints')
param serviceShort string = 'cdcom'

// =========== //
// Deployments //
// =========== //

// General resources
// =================
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: resourceGroupName
location: location
}

module resourceGroupResources 'dependencies.bicep' = {
scope: resourceGroup
name: '${uniqueString(deployment().name, location)}-paramNested'
params: {
managedIdentityName: 'dep-<<namePrefix>>-msi-${serviceShort}'
}
}

// ============== //
// Test Execution //
// ============== //
module testDeployment '../../deploy.bicep' = {
scope: resourceGroup
name: '${uniqueString(deployment().name, location)}-test-${serviceShort}'
params: {
name: '<<namePrefix>>-${serviceShort}001'
sku: 'UltraSSD_LRS'
diskIOPSReadWrite: 500
diskMBpsReadWrite: 60
diskSizeGB: 128
lock: 'CanNotDelete'
logicalSectorSize: 512
osType: 'Windows'
publicNetworkAccess: 'Enabled'
roleAssignments: [
{
roleDefinitionIdOrName: 'Reader'
principalIds: [
resourceGroupResources.outputs.managedIdentityPrincipalId
]
}
]
}
}
28 changes: 0 additions & 28 deletions modules/Microsoft.Compute/disks/.test/image.parameters.json

This file was deleted.

13 changes: 13 additions & 0 deletions modules/Microsoft.Compute/disks/.test/image/dependencies.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@description('Optional. The location to deploy resources to.')
param location string = resourceGroup().location

@description('Required. The name of the Managed Identity to create.')
param managedIdentityName string

resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
name: managedIdentityName
location: location
}

@description('The principal ID of the created managed identity')
output managedIdentityPrincipalId string = managedIdentity.properties.principalId
56 changes: 56 additions & 0 deletions modules/Microsoft.Compute/disks/.test/image/deploy.test.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
targetScope = 'subscription'

// ========== //
// Parameters //
// ========== //

@description('Optional. The name of the resource group to deploy for a testing purposes')
@maxLength(90)
param resourceGroupName string = 'ms.compute.images-${serviceShort}-rg'

@description('Optional. The location to deploy resources to')
param location string = deployment().location

@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints')
param serviceShort string = 'cdimg'

// =========== //
// Deployments //
// =========== //

// General resources
// =================
resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
name: resourceGroupName
location: location
}

module resourceGroupResources 'dependencies.bicep' = {
scope: resourceGroup
name: '${uniqueString(deployment().name, location)}-paramNested'
params: {
managedIdentityName: 'dep-<<namePrefix>>-msi-${serviceShort}'
}
}

// ============== //
// Test Execution //
// ============== //
module testDeployment '../../deploy.bicep' = {
scope: resourceGroup
name: '${uniqueString(deployment().name, location)}-test-${serviceShort}'
params: {
name: '<<namePrefix>>-${serviceShort}001'
sku: 'Standard_LRS'
createOption: 'FromImage'
imageReferenceId: '${subscription().id}/Providers/Microsoft.Compute/Locations/westeurope/Publishers/MicrosoftWindowsServer/ArtifactTypes/VMImage/Offers/WindowsServer/Skus/2016-Datacenter/Versions/14393.4906.2112080838'
roleAssignments: [
{
roleDefinitionIdOrName: 'Reader'
principalIds: [
resourceGroupResources.outputs.managedIdentityPrincipalId
]
}
]
}
}
Loading