Skip to content

Commit

Permalink
Merge pull request #4322 from ykuijs/Dev
Browse files Browse the repository at this point in the history
New unit test and fixed issue with invalid value in parameter set
  • Loading branch information
NikCharlebois authored Feb 14, 2024
2 parents 6db4774 + 32fa1cc commit 2403334
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 77 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

# UNRELEASED

* AADConditionalAccessPolicy
* Removed invalid empty string value that was added to the validate set
of two parameters.
* AADRoleEligibilityScheduleRequest
* Fixed an issue where an error was thrown if no requests were found instead
of simply returning the Null object.
Expand Down Expand Up @@ -34,6 +37,7 @@
* Fix nested change detection for CIMInstances
* Fix IntuneDeviceEnrolllmentPlatformRestriction comparison in report
FIXES [#4291](https://github.com/microsoft/Microsoft365DSC/issues/4291)
* Added new QA test to check for missing description in resource schema

# 1.24.207.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function Get-TargetResource

[Parameter()]
[System.String]
[ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')]
[ValidateSet('all', 'enumerated', 'unknownFutureValue')]
$IncludeExternalTenantsMembershipKind,

[Parameter()]
Expand All @@ -85,7 +85,7 @@ function Get-TargetResource

[Parameter()]
[System.String]
[ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')]
[ValidateSet('all', 'enumerated', 'unknownFutureValue')]
$ExcludeExternalTenantsMembershipKind,

[Parameter()]
Expand Down Expand Up @@ -755,7 +755,7 @@ function Set-TargetResource

[Parameter()]
[System.String]
[ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')]
[ValidateSet('all', 'enumerated', 'unknownFutureValue')]
$IncludeExternalTenantsMembershipKind,

[Parameter()]
Expand All @@ -769,7 +769,7 @@ function Set-TargetResource

[Parameter()]
[System.String]
[ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')]
[ValidateSet('all', 'enumerated', 'unknownFutureValue')]
$ExcludeExternalTenantsMembershipKind,

[Parameter()]
Expand Down Expand Up @@ -1738,7 +1738,7 @@ function Test-TargetResource

[Parameter()]
[System.String]
[ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')]
[ValidateSet('all', 'enumerated', 'unknownFutureValue')]
$IncludeExternalTenantsMembershipKind,

[Parameter()]
Expand All @@ -1752,7 +1752,7 @@ function Test-TargetResource

[Parameter()]
[System.String]
[ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')]
[ValidateSet('all', 'enumerated', 'unknownFutureValue')]
$ExcludeExternalTenantsMembershipKind,

[Parameter()]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ class MSFT_AADConditionalAccessPolicy : OMI_BaseResource
[Write, Description("AAD Admin Roles in scope of the Policy.")] String IncludeRoles[];
[Write, Description("AAD Admin Roles out of scope of the Policy.")] String ExcludeRoles[];
[Write, Description("Represents the Included internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue."), ValueMap{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}, Values{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}] String IncludeGuestOrExternalUserTypes[];
[Write, Description("Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"","all","enumerated","unknownFutureValue"}, Values{"","all","enumerated","unknownFutureValue"}] String IncludeExternalTenantsMembershipKind;
[Write, Description("Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"all","enumerated","unknownFutureValue"}, Values{"all","enumerated","unknownFutureValue"}] String IncludeExternalTenantsMembershipKind;
[Write, Description("Represents the Included collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting.")] String IncludeExternalTenantsMembers[];
[Write, Description("Represents the Excluded internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue."), ValueMap{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}, Values{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}] String ExcludeGuestOrExternalUserTypes[];
[Write, Description("Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"","all","enumerated","unknownFutureValue"}, Values{"","all","enumerated","unknownFutureValue"}] String ExcludeExternalTenantsMembershipKind;
[Write, Description("Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"all","enumerated","unknownFutureValue"}, Values{"all","enumerated","unknownFutureValue"}] String ExcludeExternalTenantsMembershipKind;
[Write, Description("Represents the Excluded collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting.")] String ExcludeExternalTenantsMembers[];
[Write, Description("Client Device Platforms in scope of the Policy.")] String IncludePlatforms[];
[Write, Description("Client Device Platforms out of scope of the Policy.")] String ExcludePlatforms[];
Expand Down
207 changes: 138 additions & 69 deletions Tests/QA/Microsoft365DSC.Resources.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,107 @@
}
}

Describe -Name "Check schema for resource '<ResourceName>'" -ForEach $schemaFiles{
BeforeAll {
function Get-MofSchemaObject
BeforeAll {
function Get-MofSchemaObject
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter(Mandatory = $true)]
[System.String]
$FileName
)

$temporaryPath = (Get-Item -Path env:TEMP).Value

#region Workaround for OMI_BaseResource inheritance not resolving.

$filePath = (Resolve-Path -Path $FileName).Path
$tempFilePath = Join-Path -Path $temporaryPath -ChildPath "DscMofHelper_$((New-Guid).Guid).tmp"
$rawContent = (Get-Content -Path $filePath -Raw) -replace '\s*:\s*OMI_BaseResource'

Set-Content -LiteralPath $tempFilePath -Value $rawContent -ErrorAction 'Stop'

# .NET methods don't like PowerShell drives
$tempFilePath = Convert-Path -Path $tempFilePath

#endregion

try
{
$exceptionCollection = [System.Collections.ObjectModel.Collection[System.Exception]]::new()
$moduleInfo = [System.Tuple]::Create('Module', [System.Version] '1.0.0')

$class = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportClasses(
$tempFilePath, $moduleInfo, $exceptionCollection
)

if ($null -eq $class)
{
throw "No classes found in the schema file"
}
}
catch
{
throw "Failed to import classes from file $FileName. Error $_"
}
finally
{
Remove-Item -LiteralPath $tempFilePath -Force
}

foreach ($currentCimClass in $class)
{
$attributes = foreach ($property in $currentCimClass.CimClassProperties)
{
$state = switch ($property.flags)
{
{ $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Key }
{
'Key'
}
{ $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Required }
{
'Required'
}
{ $_ -band [Microsoft.Management.Infrastructure.CimFlags]::ReadOnly }
{
'Read'
}
default
{
'Write'
}
}

@{
Name = $property.Name
State = $state
DataType = $property.CimType
ValueMap = $property.Qualifiers.Where( { $_.Name -eq 'ValueMap' }).Value
IsArray = $property.CimType -gt 16
Description = $property.Qualifiers.Where( { $_.Name -eq 'Description' }).Value
EmbeddedInstance = $property.Qualifiers.Where( { $_.Name -eq 'EmbeddedInstance' }).Value
}
}

@{
ClassName = $currentCimClass.CimClassName
Attributes = $attributes
ClassVersion = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'ClassVersion' }).Value
FriendlyName = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'FriendlyName' }).Value
}
}
}
}

Describe -Name "Check schema for resource '<ResourceName>'" -ForEach $schemaFiles {
BeforeDiscovery {
function Confirm-MofSchema
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
[OutputType([System.Boolean])]
param
(
[Parameter(Mandatory = $true)]
Expand Down Expand Up @@ -44,95 +139,69 @@ Describe -Name "Check schema for resource '<ResourceName>'" -ForEach $schemaFile
$class = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportClasses(
$tempFilePath, $moduleInfo, $exceptionCollection
)

if ($null -eq $class)
{
return $false
}
else
{
return $true
}
}
catch
{
throw "Failed to import classes from file $FileName. Error $_"
return $false
}
finally
{
Remove-Item -LiteralPath $tempFilePath -Force
}

foreach ($currentCimClass in $class)
{
$attributes = foreach ($property in $currentCimClass.CimClassProperties)
{
$state = switch ($property.flags)
{
{ $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Key }
{
'Key'
}
{ $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Required }
{
'Required'
}
{ $_ -band [Microsoft.Management.Infrastructure.CimFlags]::ReadOnly }
{
'Read'
}
default
{
'Write'
}
}

@{
Name = $property.Name
State = $state
DataType = $property.CimType
ValueMap = $property.Qualifiers.Where( { $_.Name -eq 'ValueMap' }).Value
IsArray = $property.CimType -gt 16
Description = $property.Qualifiers.Where( { $_.Name -eq 'Description' }).Value
EmbeddedInstance = $property.Qualifiers.Where( { $_.Name -eq 'EmbeddedInstance' }).Value
}
}

@{
ClassName = $currentCimClass.CimClassName
Attributes = $attributes
ClassVersion = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'ClassVersion' }).Value
FriendlyName = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'FriendlyName' }).Value
}
}
}
}

It 'Schema should be read successfully' {
{ Get-MofSchemaObject -FileName $FullName } | Should -Not -Throw
$skipTest = -not (Confirm-MofSchema -FileName $FullName)
}

It 'Schema should have a Key parameter' {
$mofSchemas = Get-MofSchemaObject -FileName $FullName
$attributes = ($mofSchemas | Where-Object { [String]::IsNullOrEmpty($_.FriendlyName) -eq $false }).Attributes
$keyCount = ($attributes | Where-Object { $_.State -eq 'Key' }).Count
$keyCount | Should -BeGreaterThan 1
Context 'Validate if the schema is correct' {
It 'Schema should be read successfully' {
{ $mofSchemas = Get-MofSchemaObject -FileName $FullName } | Should -Not -Throw
}
}

It 'Schema should contain an instance of all used subclasses' {
$mofSchemas = Get-MofSchemaObject -FileName $FullName
Context 'Run all schema checks' -Skip:$skipTest {
BeforeAll {
$mofSchemas = Get-MofSchemaObject -FileName $FullName
}

$errors = 0
It 'Schema should have a Key parameter' {
$attributes = ($mofSchemas | Where-Object { [String]::IsNullOrEmpty($_.FriendlyName) -eq $false }).Attributes
$keyCount = ($attributes | Where-Object { $_.State -eq 'Key' }).Count
$keyCount | Should -BeGreaterThan 1
}

$availableClasses = $mofSchemas.ClassName | Where-Object -FilterScript { $_ -ne $ResourceName }
It 'Schema should contain an instance of all used subclasses' {
$availableClasses = $mofSchemas.ClassName | Where-Object -FilterScript { $_ -ne $ResourceName }

foreach ($mofSchema in $mofSchemas)
{
foreach ($attribute in $mofSchema.Attributes)
foreach ($mofSchema in $mofSchemas)
{
if ([String]::IsNullOrEmpty($attribute.EmbeddedInstance) -eq $false -and $attribute.EmbeddedInstance -ne "MSFT_Credential")
foreach ($attribute in $mofSchema.Attributes)
{
if ($attribute.EmbeddedInstance -notin $availableClasses)
if ([String]::IsNullOrEmpty($attribute.EmbeddedInstance) -eq $false -and $attribute.EmbeddedInstance -ne 'MSFT_Credential')
{
Write-Host "[ERROR] Property $($attribute.Name) in class $($mofSchema.ClassName) / Specified EmbeddedInstance: $($attribute.EmbeddedInstance) not found!" -ForegroundColor Red
$errors++
$attribute.EmbeddedInstance | Should -BeIn $availableClasses
}
}
}
}

$errors | Should -Be 0
It 'Schema should have a description for all properties' {
foreach ($mofSchema in $mofSchemas)
{
foreach ($attribute in $mofSchema.Attributes)
{
$attribute.Description | Should -Not -BeNullOrEmpty
}
}
}
}

}

0 comments on commit 2403334

Please sign in to comment.