diff --git a/CHANGELOG.md b/CHANGELOG.md index a63685e8..14f598fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## Unreleased +## 4.5.0.0 + +- Opt-in to Example publishing to PowerShell Gallery - fixes [Issue #186](https://github.com/PowerShell/StorageDsc/issues/186). +- DiskAccessPath: + - Updated the resource to not assign a drive letter by default when adding + a disk access path. Adding a Set-Partition -NoDefaultDriveLetter + $NoDefaultDriveLetter block defaulting to true. + When adding access paths the disks will no longer have + drive letters automatically assigned on next reboot which is the desired + behavior - Fixes [Issue #145](https://github.com/PowerShell/StorageDsc/issues/145). + ## 4.4.0.0 - Refactored module folder structure to move resource to root folder of diff --git a/DSCResources/MSFT_DiskAccessPath/MSFT_DiskAccessPath.psm1 b/DSCResources/MSFT_DiskAccessPath/MSFT_DiskAccessPath.psm1 index 724dd417..f963dd73 100644 --- a/DSCResources/MSFT_DiskAccessPath/MSFT_DiskAccessPath.psm1 +++ b/DSCResources/MSFT_DiskAccessPath/MSFT_DiskAccessPath.psm1 @@ -27,6 +27,9 @@ $localizedData = Get-LocalizedData ` .PARAMETER AccessPath Specifies the access path folder to the assign the disk volume to + .PARAMETER NoDefaultDriveLetter + Prevents a default drive letter from being assigned to a newly created partition. Defaults to True. + .PARAMETER DiskId Specifies the disk identifier for the disk to modify. @@ -55,6 +58,10 @@ function Get-TargetResource [System.String] $AccessPath, + [Parameter()] + [System.Boolean] + $NoDefaultDriveLetter = $true, + [Parameter(Mandatory = $true)] [System.String] $DiskId, @@ -115,13 +122,14 @@ function Get-TargetResource -ErrorAction SilentlyContinue).BlockSize $returnValue = @{ - DiskId = $DiskId - DiskIdType = $DiskIdType - AccessPath = $AccessPath - Size = $assignedPartition.Size - FSLabel = $FSLabel - AllocationUnitSize = $blockSize - FSFormat = $fileSystem + DiskId = $DiskId + DiskIdType = $DiskIdType + AccessPath = $AccessPath + NoDefaultDriveLetter = $assignedPartition.NoDefaultDriveLetter + Size = $assignedPartition.Size + FSLabel = $FSLabel + AllocationUnitSize = $blockSize + FSFormat = $fileSystem } $returnValue } # Get-TargetResource @@ -133,6 +141,9 @@ function Get-TargetResource .PARAMETER AccessPath Specifies the access path folder to the assign the disk volume to + .PARAMETER NoDefaultDriveLetter + Prevents a default drive letter from being assigned to a newly created partition. Defaults to True. + .PARAMETER DiskId Specifies the disk identifier for the disk to modify. @@ -162,6 +173,10 @@ function Set-TargetResource [System.String] $AccessPath, + [Parameter()] + [System.Boolean] + $NoDefaultDriveLetter = $true, + [Parameter(Mandatory = $true)] [System.String] $DiskId, @@ -409,7 +424,7 @@ function Set-TargetResource Write-Verbose -Message ( @( "$($MyInvocation.MyCommand): " $($localizedData.PartitionAlreadyAssignedMessage -f ` - $AccessPath, $partition.PartitionNumber) + $AccessPath, $assignedPartition.PartitionNumber) ) -join '' ) $assignAccessPath = $false @@ -502,6 +517,23 @@ function Set-TargetResource $($localizedData.SuccessfullyInitializedMessage -f $AccessPath) ) -join '' ) } # if + + # Get the current partition state for NoDefaultDriveLetter + $assignedPartition = $partition | + Where-Object -Property AccessPaths -Contains -Value $AccessPath + + if ($assignedPartition.NoDefaultDriveLetter -ne $NoDefaultDriveLetter) + { + Write-Verbose -Message ( @( + "$($MyInvocation.MyCommand): " + "$($localizedData.NoDefaultDriveLetterMismatchMessage -f $assignedPartition.NoDefaultDriveLetter, $NoDefaultDriveLetter)" + ) -join '' ) + + # Setting the partition property NoDefaultDriveLetter to True to prevent adding drive letter on reboot + Set-Partition -PartitionNumber $assignedPartition.PartitionNumber ` + -DiskNumber $disk.Number ` + -NoDefaultDriveLetter $NoDefaultDriveLetter + } # if } # Set-TargetResource <# @@ -511,6 +543,9 @@ function Set-TargetResource .PARAMETER AccessPath Specifies the access path folder to the assign the disk volume to + .PARAMETER NoDefaultDriveLetter + Prevents a default drive letter from being assigned to a newly created partition. Defaults to True. + .PARAMETER DiskId Specifies the disk identifier for the disk to modify. @@ -539,6 +574,10 @@ function Test-TargetResource [System.String] $AccessPath, + [Parameter()] + [System.Boolean] + $NoDefaultDriveLetter = $true, + [Parameter(Mandatory = $true)] [System.String] $DiskId, @@ -636,6 +675,16 @@ function Test-TargetResource return $false } # if + # Check if the partition NoDefaultDriveLetter parameter is correct + if ($assignedPartition.NoDefaultDriveLetter -ne $NoDefaultDriveLetter) + { + Write-Verbose -Message ( @( + "$($MyInvocation.MyCommand): " + $($localizedData.NoDefaultDriveLetterMismatchMessage -f $assignedPartition.NoDefaultDriveLetter, $NoDefaultDriveLetter) + ) -join '' ) + return $false + } # if + # Partition size was passed so check it if ($Size) { diff --git a/DSCResources/MSFT_DiskAccessPath/MSFT_DiskAccessPath.schema.mof b/DSCResources/MSFT_DiskAccessPath/MSFT_DiskAccessPath.schema.mof index 3e49fd07..9c05ebe1 100644 --- a/DSCResources/MSFT_DiskAccessPath/MSFT_DiskAccessPath.schema.mof +++ b/DSCResources/MSFT_DiskAccessPath/MSFT_DiskAccessPath.schema.mof @@ -3,6 +3,7 @@ class MSFT_DiskAccessPath : OMI_BaseResource { [Key, Description("Specifies the access path folder to the assign the disk volume to.")] String AccessPath; + [Write, Description("Specifies no automatic drive letter assignment to the partition: Defaults to True")] Boolean NoDefaultDriveLetter; [Required, Description("Specifies the disk identifier for the disk to modify.")] String DiskId; [Write, Description("Specifies the identifier type the DiskId contains. Defaults to Number."), ValueMap{"Number","UniqueId","Guid"}, Values{"Number","UniqueId","Guid"}] String DiskIdType; [Write, Description("Specifies the size of new volume.")] Uint64 Size; diff --git a/DSCResources/MSFT_DiskAccessPath/en-us/MSFT_DiskAccessPath.strings.psd1 b/DSCResources/MSFT_DiskAccessPath/en-us/MSFT_DiskAccessPath.strings.psd1 index 775fcc85..80f68c89 100644 --- a/DSCResources/MSFT_DiskAccessPath/en-us/MSFT_DiskAccessPath.strings.psd1 +++ b/DSCResources/MSFT_DiskAccessPath/en-us/MSFT_DiskAccessPath.strings.psd1 @@ -20,6 +20,7 @@ DiskReadOnlyMessage = Disk with {0} '{1}'is readonly. DiskNotGPTMessage = Disk with {0} '{1}' is initialised with '{2}' partition style. GPT required. AccessPathNotFoundMessage = A volume assigned to access path '{0}' was not found. + NoDefaultDriveLetterMismatchMessage = Partition default drive letter assigmemt parameter '{0}' does not match '{1}'. SizeMismatchMessage = Partition assigned to access path '{0}' has size {1}, which does not match expected size {2}. AllocationUnitSizeMismatchMessage = Volume assigned to access path '{0}' has allocation unit size {1} KB does not match expected allocation unit size {2} KB. FileSystemFormatMismatch = Volume assigned to access path '{0}' filesystem format '{1}' does not match expected format '{2}'. diff --git a/StorageDsc.psd1 b/StorageDsc.psd1 index 3f613390..abb096a0 100644 --- a/StorageDsc.psd1 +++ b/StorageDsc.psd1 @@ -10,7 +10,7 @@ # RootModule = '' # Version number of this module. -moduleVersion = '4.4.0.0' +moduleVersion = '4.5.0.0' # ID used to uniquely identify this module GUID = '00d73ca1-58b5-46b7-ac1a-5bfcf5814faf' @@ -102,13 +102,14 @@ PrivateData = @{ # IconUri = '' # ReleaseNotes of this module - ReleaseNotes = '- Refactored module folder structure to move resource to root folder of - repository and remove test harness - fixes [Issue 169](https://github.com/PowerShell/StorageDsc/issues/169). -- Updated Examples to support deployment to PowerShell Gallery scripts. -- Removed limitation on using Pester 4.0.8 during AppVeyor CI. -- Moved the Code of Conduct text out of the README.md and into a - CODE\_OF\_CONDUCT.md file. -- Explicitly removed extra hidden files from release package + ReleaseNotes = '- Opt-in to Example publishing to PowerShell Gallery - fixes [Issue 186](https://github.com/PowerShell/StorageDsc/issues/186). +- DiskAccessPath: + - Updated the resource to not assign a drive letter by default when adding + a disk access path. Adding a Set-Partition -NoDefaultDriveLetter + $NoDefaultDriveLetter block defaulting to true. + When adding access paths the disks will no longer have + drive letters automatically assigned on next reboot which is the desired + behavior - Fixes [Issue 145](https://github.com/PowerShell/StorageDsc/issues/145). ' @@ -137,3 +138,4 @@ PrivateData = @{ + diff --git a/Tests/Unit/MSFT_DiskAccessPath.Tests.ps1 b/Tests/Unit/MSFT_DiskAccessPath.Tests.ps1 index c9e0edac..247ab8f7 100644 --- a/Tests/Unit/MSFT_DiskAccessPath.Tests.ps1 +++ b/Tests/Unit/MSFT_DiskAccessPath.Tests.ps1 @@ -33,6 +33,7 @@ try $script:testDiskUniqueId = 'TESTDISKUNIQUEID' $script:testDiskGptGuid = [guid]::NewGuid() $script:testDiskMbrGuid = '123456' + $script:NoDefaultDriveLetter = $true $script:mockedDisk0 = [pscustomobject] @{ Number = $script:testDiskNumber @@ -97,11 +98,22 @@ try '\\?\Volume{2d313fdd-e4a4-4f31-9784-dad758e0030f}\' $script:testAccessPath ) - Size = $script:mockedPartitionSize - PartitionNumber = 1 - Type = 'Basic' + Size = $script:mockedPartitionSize + PartitionNumber = 1 + Type = 'Basic' + NoDefaultDriveLetter = $true } + $script:mockedPartitionNoDefaultDriveLetter = [pscustomobject] @{ + AccessPaths = @( + '\\?\Volume{2d313fdd-e4a4-4f31-9784-dad758e0030f}\' + $script:testAccessPath + ) + Size = $script:mockedPartitionSize + PartitionNumber = 1 + Type = 'Basic' + NoDefaultDriveLetter = $false + } $script:mockedPartitionNoAccess = [pscustomobject] @{ AccessPaths = @( '\\?\Volume{2d313fdd-e4a4-4f31-9784-dad758e0030f}\' @@ -109,6 +121,7 @@ try Size = $script:mockedPartitionSize PartitionNumber = 1 Type = 'Basic' + NoDefaultDriveLetter = $false } $script:mockedVolume = [pscustomobject] @{ @@ -519,7 +532,7 @@ try #region Function Set-TargetResource Describe 'MSFT_DiskAccessPath\Set-TargetResource' { - Context 'Offline GPT disk using Disk Number' { + Context 'Offline GPT disk using Disk Number with NoDefaultDriveLetter set to False' { # verifiable (should be called) mocks Mock ` -CommandName Assert-AccessPathValid ` @@ -558,6 +571,10 @@ try -CommandName Add-PartitionAccessPath ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + # mocks that should not be called Mock -CommandName Initialize-Disk @@ -582,10 +599,11 @@ try Assert-MockCalled -CommandName New-Partition -Times 1 Assert-MockCalled -CommandName Format-Volume -Times 1 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 } } - Context 'Offline GPT disk using Disk Unique Id' { + Context 'Offline GPT disk using Disk Unique Id with NoDefaultDriveLetter set to False' { # verifiable (should be called) mocks Mock ` -CommandName Assert-AccessPathValid ` @@ -624,6 +642,10 @@ try -CommandName Add-PartitionAccessPath ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + # mocks that should not be called Mock -CommandName Initialize-Disk @@ -633,6 +655,7 @@ try -DiskId $script:mockedDisk0Offline.UniqueId ` -DiskIdType 'UniqueId' ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -Verbose } | Should -Not -Throw } @@ -649,6 +672,7 @@ try Assert-MockCalled -CommandName New-Partition -Times 1 Assert-MockCalled -CommandName Format-Volume -Times 1 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 } } @@ -691,6 +715,11 @@ try -CommandName Add-PartitionAccessPath ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + + # mocks that should not be called Mock -CommandName Initialize-Disk @@ -716,6 +745,8 @@ try Assert-MockCalled -CommandName New-Partition -Times 1 Assert-MockCalled -CommandName Format-Volume -Times 1 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 + } } @@ -745,6 +776,10 @@ try -MockWith { $script:mockedPartitionNoAccess } ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + Mock ` -CommandName Get-Volume ` -MockWith { $script:mockedVolumeUnformatted } ` @@ -782,6 +817,7 @@ try Assert-MockCalled -CommandName New-Partition -Times 1 Assert-MockCalled -CommandName Format-Volume -Times 1 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 } } @@ -828,6 +864,10 @@ try -CommandName Add-PartitionAccessPath ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + # mocks that should not be called It 'Should not throw an exception' { @@ -851,6 +891,7 @@ try Assert-MockCalled -CommandName New-Partition -Times 1 Assert-MockCalled -CommandName Format-Volume -Times 1 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 } } @@ -893,6 +934,10 @@ try -CommandName Add-PartitionAccessPath ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + # mocks that should not be called Mock -CommandName Set-Disk @@ -917,6 +962,7 @@ try Assert-MockCalled -CommandName New-Partition -Times 1 Assert-MockCalled -CommandName Format-Volume -Times 1 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 } } @@ -939,7 +985,7 @@ try Mock ` -CommandName New-Partition ` - -MockWith { $script:mockedPartition } ` + -MockWith { $script:mockedPartitionNoDefaultDriveLetter } ` -Verifiable Mock ` @@ -955,6 +1001,10 @@ try -CommandName Add-PartitionAccessPath ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + # mocks that should not be called Mock -CommandName Set-Disk Mock -CommandName Initialize-Disk @@ -964,6 +1014,7 @@ try Set-targetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -Verbose } | Should -Not -Throw } @@ -980,6 +1031,7 @@ try Assert-MockCalled -CommandName New-Partition -Times 1 Assert-MockCalled -CommandName Format-Volume -Times 1 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 } } @@ -1135,7 +1187,7 @@ try } } - Context 'Online GPT disk with partition/volume already assigned using Disk Number' { + Context 'Online GPT disk with partition/volume already assigned using Disk Number with NoDefaultDriveLetter set to False' { # verifiable (should be called) mocks Mock ` -CommandName Assert-AccessPathValid ` @@ -1170,6 +1222,7 @@ try Set-targetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -Verbose } | Should -Not -Throw } @@ -1216,6 +1269,10 @@ try -CommandName Add-PartitionAccessPath ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + # mocks that should not be called Mock -CommandName Set-Disk Mock -CommandName Initialize-Disk @@ -1227,6 +1284,7 @@ try Set-targetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -Size $script:mockedPartitionSize ` -Verbose } | Should -Not -Throw @@ -1244,10 +1302,11 @@ try Assert-MockCalled -CommandName New-Partition -Times 0 Assert-MockCalled -CommandName Format-Volume -Times 0 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 } } - Context 'Online GPT disk containing matching partition but not assigned using Disk Number with no size parameter specified' { + Context 'Online GPT disk containing matching partition but not assigned using Disk Number with no size parameter specified with NoDefaultDriveLetter set to False' { # verifiable (should be called) mocks Mock ` -CommandName Assert-AccessPathValid ` @@ -1274,6 +1333,10 @@ try -CommandName Add-PartitionAccessPath ` -Verifiable + Mock ` + -CommandName Set-Partition ` + -Verifiable + # mocks that should not be called Mock -CommandName Set-Disk Mock -CommandName Initialize-Disk @@ -1285,6 +1348,7 @@ try Set-targetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -Verbose } | Should -Not -Throw } @@ -1301,6 +1365,7 @@ try Assert-MockCalled -CommandName New-Partition -Times 0 Assert-MockCalled -CommandName Format-Volume -Times 0 Assert-MockCalled -CommandName Add-PartitionAccessPath -Times 1 + Assert-MockCalled -CommandName Set-Partition -Times 1 } } @@ -1343,6 +1408,7 @@ try Set-targetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -FSLabel 'NewLabel' ` -Verbose } | Should -Not -Throw @@ -1634,6 +1700,7 @@ try $script:result = Test-TargetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -AllocationUnitSize 4096 ` -Size 124 ` -Verbose @@ -1688,6 +1755,7 @@ try $script:result = Test-TargetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -AllocationUnitSize 4097 ` -Verbose } | Should -Not -Throw @@ -1744,6 +1812,7 @@ try $script:result = Test-TargetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -FSFormat 'ReFS' ` -Verbose } | Should -Not -Throw @@ -1799,6 +1868,7 @@ try $script:result = Test-TargetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -FSLabel 'NewLabel' ` -Verbose } | Should -Not -Throw @@ -1819,6 +1889,50 @@ try } } + Context 'Test mismatching NoDefaultDriveLetter using Disk Number' { + # verifiable (should be called) mocks + Mock ` + -CommandName Assert-AccessPathValid ` + -MockWith { $script:testAccessPath } ` + -Verifiable + + Mock ` + -CommandName Get-DiskByIdentifier ` + -ParameterFilter { $DiskId -eq $script:mockedDisk0.Number -and $DiskIdType -eq 'Number' } ` + -MockWith { $script:mockedDisk0 } ` + -Verifiable + + Mock ` + -CommandName Get-Partition ` + -MockWith { $script:mockedPartitionNoDefaultDriveLetter } ` + -Verifiable + + $script:result = $null + + It 'Should not throw an exception' { + { + $script:result = Test-TargetResource ` + -DiskId $script:mockedDisk0.Number ` + -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` + -FSLabel 'myLabel' ` + -Verbose + } | Should -Not -Throw + } + + It 'Should return false' { + $script:result | Should -Be $false + } + + It 'Should call the correct mocks' { + Assert-VerifiableMock + Assert-MockCalled -CommandName Assert-AccessPathValid -Times 1 + Assert-MockCalled -CommandName Get-DiskByIdentifier -Times 1 ` + -ParameterFilter { $DiskId -eq $script:mockedDisk0.Number -and $DiskIdType -eq 'Number' } + Assert-MockCalled -CommandName Get-Partition -Times 1 + } + } + Context 'Test all disk properties matching using Disk Number' { # verifiable (should be called) mocks Mock ` @@ -1854,6 +1968,7 @@ try $script:result = Test-TargetResource ` -DiskId $script:mockedDisk0.Number ` -AccessPath $script:testAccessPath ` + -NoDefaultDriveLetter $script:NoDefaultDriveLetter ` -AllocationUnitSize 4096 ` -Size $script:mockedPartition.Size ` -FSFormat $script:mockedVolume.FileSystem ` diff --git a/appveyor.yml b/appveyor.yml index 146e15ea..00806ad7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -38,5 +38,4 @@ deploy_script: -Type 'Wiki' ` -ResourceModuleName $moduleName - Invoke-AppVeyorDeployTask ` - -OptIn @() + Invoke-AppVeyorDeployTask