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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Public command:
- `Get-FileProductVersion` - Get the product version of a file.
- `Test-PendingRestart` - Test if a pending restart is required.
- Private command
- `Clear-ZeroedEnumPropertyValue` from `DscResource.Base`.
- `Get-DscProperty`
- Add optional parameter `IgnoreZeroEnumValue`.

### Fixed

Expand Down
47 changes: 47 additions & 0 deletions source/Private/Clear-ZeroedEnumPropertyValue.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<#
.SYNOPSIS
Removes any properties from a hashable which have values that are
type [System.Enum] and have an [System.Int32] value of 0.

.DESCRIPTION
Removes any properties from a hashable which have values that are
type [System.Enum] and have an [System.Int32] value of 0.

.PARAMETER InputObject
The hashtable to be checked.

.EXAMPLE
Clear-ZeroedEnumPropertyValue -InputObject $ht

.OUTPUTS
[System.Collections.Hashtable]
#>

function Clear-ZeroedEnumPropertyValue
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[System.Collections.Hashtable]
$InputObject
)

process
{
$result = @{}

foreach ($property in $InputObject.Keys)
{
$value = $InputObject.$property
if ($value -is [System.Enum] -and [System.Int32]$value.value__ -eq 0)
{
continue
}

$result.$property = $value
}

return $result
}
}
36 changes: 29 additions & 7 deletions source/Public/Get-DscProperty.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
If left out all properties are returned regardless if there is a value
assigned or not.

.PARAMETER IgnoreZeroEnumValue
Specifies to return only Enum properties that has been assigned a non zero value.

.OUTPUTS
System.Collections.Hashtable

Expand Down Expand Up @@ -55,6 +58,12 @@
Returns the DSC resource properties that has the specified attributes and
has a non-null value assigned.

.EXAMPLE
Get-DscProperty -InputObject $this -Attribute @('Optional') -HasValue -IgnoreZeroEnumValue

Returns the DSC resource properties that has the specified attributes and
has a non-null value assigned, and any Enum properties that has a non-zero value.

.OUTPUTS
[System.Collections.Hashtable]

Expand All @@ -64,31 +73,39 @@
#>
function Get-DscProperty
{
[CmdletBinding()]
[CmdletBinding(DefaultParameterSetName = 'Default')]
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Default')]
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'HasValue')]
[PSObject]
$InputObject,

[Parameter()]
[Parameter(ParameterSetName = 'Default')]
[Parameter(ParameterSetName = 'HasValue')]
[System.String[]]
$Name,

[Parameter()]
[Parameter(ParameterSetName = 'Default')]
[Parameter(ParameterSetName = 'HasValue')]
[System.String[]]
$ExcludeName,

[Parameter()]
[Parameter(ParameterSetName = 'Default')]
[Parameter(ParameterSetName = 'HasValue')]
[ValidateSet('Key', 'Mandatory', 'NotConfigurable', 'Optional')]
[Alias('Type')]
[System.String[]]
$Attribute,

[Parameter()]
[Parameter(ParameterSetName = 'HasValue', Mandatory = $true)]
[System.Management.Automation.SwitchParameter]
$HasValue
$HasValue,

[Parameter(ParameterSetName = 'HasValue')]
[System.Management.Automation.SwitchParameter]
$IgnoreZeroEnumValue
)

process
Expand Down Expand Up @@ -167,6 +184,11 @@ function Get-DscProperty
$getPropertyResult.$currentProperty = $InputObject.$currentProperty
}

if ($IgnoreZeroEnumValue.IsPresent)
{
$getPropertyResult = $getPropertyResult | Clear-ZeroedEnumPropertyValue
}

return $getPropertyResult
}
}
154 changes: 154 additions & 0 deletions tests/Unit/Private/Clear-ZeroedEnumPropertyValue.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
param ()

BeforeDiscovery {
try
{
if (-not (Get-Module -Name 'DscResource.Test'))
{
# Assumes dependencies has been resolved, so if this module is not available, run 'noop' task.
if (-not (Get-Module -Name 'DscResource.Test' -ListAvailable))
{
# Redirect all streams to $null, except the error stream (stream 2)
& "$PSScriptRoot/../../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
}

# If the dependencies has not been resolved, this will throw an error.
Import-Module -Name 'DscResource.Test' -Force -ErrorAction 'Stop'
}
}
catch [System.IO.FileNotFoundException]
{
throw 'DscResource.Test module dependency not found. Please run ".\build.ps1 -ResolveDependency -Tasks build" first.'
}
}

BeforeAll {
$script:moduleName = 'DscResource.Common'

# Make sure there are not other modules imported that will conflict with mocks.
Get-Module -Name $script:moduleName -All | Remove-Module -Force

Import-Module -Name $script:moduleName

$PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName
$PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName
$PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName
}

AfterAll {
$PSDefaultParameterValues.Remove('InModuleScope:ModuleName')
$PSDefaultParameterValues.Remove('Mock:ModuleName')
$PSDefaultParameterValues.Remove('Should:ModuleName')

# Unload the module being tested so that it doesn't impact any other tests.
Get-Module -Name $script:moduleName -All | Remove-Module -Force
}

Describe 'Clear-ZeroedEnumPropertyValue' -Tag 'Private' {
Context 'When the hashtable does not contain zeroed Enum properties' {
Context 'When input is passed as a named variable' {
It 'Should return the same amount of values' {
InModuleScope -ScriptBlock {
Set-StrictMode -Version 1.0

$testParams = @{
Variable1 = 'SomeString'
Variable2 = [System.Int32] 10
Variable3 = $true
Variable4 = New-TimeSpan -Days 8
}

$result = Clear-ZeroedEnumPropertyValue -InputObject $testParams

$result.Count | Should -Be $testParams.Count
}
}
}

Context 'When input is passed via pipeline' {
It 'Should return the same amount of values' {
InModuleScope -ScriptBlock {
Set-StrictMode -Version 1.0

$testParams = @{
Variable1 = 'SomeString'
Variable2 = [System.Int32] 10
Variable3 = $true
Variable4 = New-TimeSpan -Days 8
}

$result = $testParams | Clear-ZeroedEnumPropertyValue

$result.Count | Should -Be $testParams.Count
}
}
}
}

Context 'When the hashtable does contain zeroed Enum properties' {
Context 'When input is passed as a named variable' {
It 'Should return the same amount of values' {
InModuleScope -ScriptBlock {
Set-StrictMode -Version 1.0

enum MyMockEnum
{
Value1 = 1
Value2
Value3
Value4
Value5
}

$testParams = @{
Variable1 = 'SomeString'
Variable2 = [System.Int32] 10
Variable3 = $true
Variable4 = New-TimeSpan -Days 8
Variable5 = [MyMockEnum]::Value1
Variable6 = [MyMockEnum]::new()
Variable7 = [MyMockEnum]::Value3
Variable8 = [MyMockEnum]::new()
}

$result = Clear-ZeroedEnumPropertyValue -InputObject $testParams

$result.Count | Should -Be ($testParams.Count - 2)
}
}
}

Context 'When input is passed via pipeline' {
It 'Should return the same amount of values' {
InModuleScope -ScriptBlock {
Set-StrictMode -Version 1.0

enum MyMockEnum
{
Value1 = 1
Value2
Value3
Value4
Value5
}

$testParams = @{
Variable1 = 'SomeString'
Variable2 = [System.Int32] 10
Variable3 = $true
Variable4 = New-TimeSpan -Days 8
Variable5 = [MyMockEnum]::Value1
Variable6 = [MyMockEnum]::new()
Variable7 = [MyMockEnum]::Value3
Variable8 = [MyMockEnum]::new()
}

$result = $testParams | Clear-ZeroedEnumPropertyValue

$result.Count | Should -Be ($testParams.Count - 2)
}
}
}
}
}
63 changes: 63 additions & 0 deletions tests/Unit/Public/Get-DscProperty.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,69 @@ Describe 'Get-DscProperty' -Tag 'Public' {
}
}

Context 'When using parameter IgnoreZeroEnumValue' {
Context 'When getting all optional properties' {
BeforeAll {
enum MyEnum
{
MyValue1 = 1
MyValue2
MyValue3
}

class MyMockResource
{
[DscProperty(Key)]
[System.String]
$MyResourceKeyProperty1

[DscProperty(Key)]
[System.String]
$MyResourceKeyProperty2

[DscProperty(Mandatory)]
[System.String]
$MyResourceMandatoryProperty

[DscProperty()]
[MyEnum]
$MyResourceProperty1

[DscProperty()]
[MyEnum]
$MyResourceProperty2

[DscProperty(NotConfigurable)]
[System.String]
$MyResourceReadProperty
}

$script:mockResourceBaseInstance = [MyMockResource]::new()
$script:mockResourceBaseInstance.MyResourceKeyProperty1 = 'MockValue1'
$script:mockResourceBaseInstance.MyResourceKeyProperty2 = 'MockValue2'
$script:mockResourceBaseInstance.MyResourceMandatoryProperty = 'MockValue3'
$script:mockResourceBaseInstance.MyResourceProperty1 = [MyEnum]::new()
$script:mockResourceBaseInstance.MyResourceProperty2 = [MyEnum]::MyValue3
}

It 'Should return the correct value' {
$result = Get-DscProperty -Attribute 'Optional' -HasValue -InputObject $script:mockResourceBaseInstance -IgnoreZeroEnumValue

$result | Should -BeOfType [System.Collections.Hashtable]

$result.Keys | Should -Not -Contain 'MyResourceMandatoryProperty' -Because 'mandatory properties should not be part of the collection'
$result.Keys | Should -Not -Contain 'MyResourceKeyProperty1' -Because 'key properties should not be part of the collection'
$result.Keys | Should -Not -Contain 'MyResourceKeyProperty2' -Because 'key properties should not be part of the collection'
$result.Keys | Should -Not -Contain 'MyResourceReadProperty' -Because 'read properties should not be part of the collection'

$result.Keys | Should -Not -Contain 'MyResourceProperty1' -Because 'the enum property has a zero value'

$result.Keys | Should -Contain 'MyResourceProperty2' -Because 'the enum property has a non zero value'
$result.MyResourceProperty2 | Should -Be MyValue3
}
}
}

Context 'When getting specific named properties' {
BeforeAll {
class MyMockResource
Expand Down