diff --git a/CHANGELOG.md b/CHANGELOG.md index e935868ca2..c643d5a823 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * EXOCalendarProcessing * Initial release. +* EXOPlace + * Initial release. * DEPENDENCIES * Updated MSCloudLoginAssistant to version 1.0.121. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.psm1 new file mode 100644 index 0000000000..93d282d5fd --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.psm1 @@ -0,0 +1,645 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $AudioDeviceName, + + [Parameter()] + [System.String] + $Building, + + [Parameter()] + [System.UInt32] + $Capacity, + + [Parameter()] + [System.String] + $City, + + [Parameter()] + [System.String] + $CountryOrRegion, + + [Parameter()] + [System.String[]] + $Desks = @(), + + [Parameter()] + [System.String] + $DisplayDeviceName, + + [Parameter()] + [System.UInt32] + $Floor, + + [Parameter()] + [System.String] + $FloorLabel, + + [Parameter()] + [System.String] + $GeoCoordinates, + + [Parameter()] + [System.Boolean] + $IsWheelChairAccessible, + + [Parameter()] + [System.String] + $Label, + + [Parameter()] + [System.Boolean] + $MTREnabled, + + [Parameter()] + [System.String] + $ParentId, + + [Parameter()] + [ValidateSet("Floor", "Section", "None")] + [System.String] + $ParentType, + + [Parameter()] + [System.String] + $Phone, + + [Parameter()] + [System.String] + $PostalCode, + + [Parameter()] + [System.String] + $State, + + [Parameter()] + [System.String] + $Street, + + [Parameter()] + [System.String[]] + $Tags, + + [Parameter()] + [System.String] + $VideoDeviceName, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + Write-Verbose -Message "Getting configuration for Place for $($Identity)" + + if ($Global:CurrentModeIsExport) + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters ` + -SkipModuleReload $true + } + else + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters + } + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullReturn = $PSBoundParameters + $nullReturn.Ensure = 'Absent' + + try + { + $place = Get-Place -Identity $Identity -ErrorAction Stop + + if ($null -eq $place) + { + Write-Verbose -Message "Place $($Identity) does not exist." + return $nullReturn + } + else + { + $result = @{ + Identity = $place.Identity + AudioDeviceName = $place.AudioDeviceName + Building = $place.Building + Capacity = $place.Capacity + City = $place.City + CountryOrRegion = $place.CountryOrRegion + Desks = [Array] $place.Desks + DisplayDeviceName = $place.DisplayDeviceName + Floor = $place.Floor + FloorLabel = $place.FloorLabel + GeoCoordinates = $place.GeoCoordinates + IsWheelChairAccessible = [Boolean] $place.IsWheelChairAccessible + Label = $place.Label + MTREnabled = [Boolean] $place.MTREnabled + ParentId = $place.ParentId + ParentType = $place.ParentType + Phone = $place.Phone + PostalCode = $place.PostalCode + State = $place.State + Street = $place.Street + Tags = [Array] $place.Tags + VideoDeviceName = $place.VideoDeviceName + Credential = $Credential + Ensure = 'Present' + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId + } + + Write-Verbose -Message "Found Place $($Identity)" + return $result + } + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullReturn + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $AudioDeviceName, + + [Parameter()] + [System.String] + $Building, + + [Parameter()] + [System.UInt32] + $Capacity, + + [Parameter()] + [System.String] + $City, + + [Parameter()] + [System.String] + $CountryOrRegion, + + [Parameter()] + [System.String[]] + $Desks = @(), + + [Parameter()] + [System.String] + $DisplayDeviceName, + + [Parameter()] + [System.UInt32] + $Floor, + + [Parameter()] + [System.String] + $FloorLabel, + + [Parameter()] + [System.String] + $GeoCoordinates, + + [Parameter()] + [System.Boolean] + $IsWheelChairAccessible, + + [Parameter()] + [System.String] + $Label, + + [Parameter()] + [System.Boolean] + $MTREnabled, + + [Parameter()] + [System.String] + $ParentId, + + [Parameter()] + [ValidateSet("Floor", "Section", "None")] + [System.String] + $ParentType, + + [Parameter()] + [System.String] + $Phone, + + [Parameter()] + [System.String] + $PostalCode, + + [Parameter()] + [System.String] + $State, + + [Parameter()] + [System.String] + $Street, + + [Parameter()] + [System.String[]] + $Tags, + + [Parameter()] + [System.String] + $VideoDeviceName, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Setting configuration of Place for $($Identity)" + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters + + $PSBoundParameters.Remove('Ensure') | Out-Null + $PSBoundParameters.Remove('Credential') | Out-Null + $PSBoundParameters.Remove('ApplicationId') | Out-Null + $PSBoundParameters.Remove('TenantId') | Out-Null + $PSBoundParameters.Remove('CertificateThumbprint') | Out-Null + $PSBoundParameters.Remove('CertificatePath') | Out-Null + $PSBoundParameters.Remove('CertificatePassword') | Out-Null + $PSBoundParameters.Remove('ManagedIdentity') | Out-Null + + if ([System.String]::IsNullOrEmpty($ParentId) -and $null -ne $ParentType) + { + Write-Verbose -Message 'ParentId is $null, removing ParentType.' + $PSBoundParameters.Remove('ParentType') | Out-Null + } + Set-Place @PSBoundParameters +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $AudioDeviceName, + + [Parameter()] + [System.String] + $Building, + + [Parameter()] + [System.UInt32] + $Capacity, + + [Parameter()] + [System.String] + $City, + + [Parameter()] + [System.String] + $CountryOrRegion, + + [Parameter()] + [System.String[]] + $Desks = @(), + + [Parameter()] + [System.String] + $DisplayDeviceName, + + [Parameter()] + [System.UInt32] + $Floor, + + [Parameter()] + [System.String] + $FloorLabel, + + [Parameter()] + [System.String] + $GeoCoordinates, + + [Parameter()] + [System.Boolean] + $IsWheelChairAccessible, + + [Parameter()] + [System.String] + $Label, + + [Parameter()] + [System.Boolean] + $MTREnabled, + + [Parameter()] + [System.String] + $ParentId, + + [Parameter()] + [ValidateSet("Floor", "Section", "None")] + [System.String] + $ParentType, + + [Parameter()] + [System.String] + $Phone, + + [Parameter()] + [System.String] + $PostalCode, + + [Parameter()] + [System.String] + $State, + + [Parameter()] + [System.String] + $Street, + + [Parameter()] + [System.String[]] + $Tags, + + [Parameter()] + [System.String] + $VideoDeviceName, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of Place for $($Identity)" + + $CurrentValues = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $ValuesToCheck = $PSBoundParameters + + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $($TestResult)" + + return $TestResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters ` + -SkipModuleReload $true + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + try + { + [array]$places = Get-Place -ErrorAction Stop + $dscContent = '' + + if ($places.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + $i = 1 + foreach ($place in $places) + { + Write-Host " |---[$i/$($places.Length)] $($place.Identity)" -NoNewline + + $Params = @{ + Identity = $place.Identity + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + CertificatePath = $CertificatePath + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + Write-Host $Global:M365DSCEmojiGreenCheckMark + $i++ + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.schema.mof new file mode 100644 index 0000000000..5d63f2ea12 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.schema.mof @@ -0,0 +1,35 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("EXOPlace")] +class MSFT_EXOPlace : OMI_BaseResource +{ + [Key, Description("The Identity parameter specifies the room mailbox that you want to modify. You can use any value that uniquely identifies the room.")] String Identity; + [Write, Description("The AudioDeviceName parameter specifies the name of the audio device in the room. If the value contains spaces, enclose the value in quotation marks.")] String AudioDeviceName; + [Write, Description("The Building parameter specifies the building name or building number that the room is in. If the value contains spaces, enclose the value in quotation marks.")] String Building; + [Write, Description("The Capacity parameter specifies the capacity of the room. A valid value is an integer.")] UInt32 Capacity; + [Write, Description("The City parameter specifies the room's city. If the value contains spaces, enclose the value in quotation marks.")] String City; + [Write, Description("The CountryOrRegion parameter specifies the room's country or region. A valid value is a valid ISO 3166-1 two-letter country code (for example, AU for Australia) or the corresponding friendly name for the country (which might be different from the official ISO 3166 Maintenance Agency short name).")] String CountryOrRegion; + [Write, Description("N/A")] String Desks[]; + [Write, Description("The DisplayDeviceName parameter specifies the name of the display device in the room. If the value contains spaces, enclose the value in quotation marks.")] String DisplayDeviceName; + [Write, Description("The Floor parameter specifies the floor number that the room is on.")] String Floor; + [Write, Description("The FloorLabel parameter specifies a descriptive label for the floor that the room is on. If the value contains spaces, enclose the value in quotation marks.")] String FloorLabel; + [Write, Description("The GeoCoordinates parameter specifies the room's location in latitude, longitude and (optionally) altitude coordinates.")] String GeoCoordinates; + [Write, Description("The IsWheelChairAccessible parameter specifies whether the room is wheelchair accessible.")] Boolean IsWheelChairAccessible; + [Write, Description("The Label parameter specifies a descriptive label for the room (for example, a number or name). If the value contains spaces, enclose the value in quotation marks.")] String Label; + [Write, Description("The MTREnabled parameter identifies the room as configured with a Microsoft Teams room system. You can add Teams room systems as audio sources in Teams meetings that involve the room.")] Boolean MTREnabled; + [Write, Description("The ParentId parameter specifies the ID of a Place in the parent location hierarchy in Microsoft Places.")] String ParentId; + [Write, Description("The ParentType parameter specifies the parent type of the ParentId in Microsoft Places. Valid values are: Floor, Section"), ValueMap{"Floor","Section","None"}, Values{"Floor","Section","None"}] String ParentType; + [Write, Description("The Phone parameter specifies the room's telephone number.")] String Phone; + [Write, Description("The PostalCode parameter specifies the room's postal code.")] String PostalCode; + [Write, Description("The State parameter specifies the room's state or province.")] String State; + [Write, Description("The Street parameter specifies the room's physical address.")] String Street; + [Write, Description("The Tags parameter specifies additional features of the room (for example, details like the type of view or furniture type).")] String Tags[]; + [Write, Description("The VideoDeviceName parameter specifies the name of the video device in the room. If the value contains spaces, enclose the value in quotation marks.")] String VideoDeviceName; + [Write, Description("Specifies if this Outbound connector should exist."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Credentials of the Exchange Global Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Username can be made up to anything but password will be used for CertificatePassword"), EmbeddedInstance("MSFT_Credential")] String CertificatePassword; + [Write, Description("Path to certificate used in service principal usually a PFX file.")] String CertificatePath; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/readme.md new file mode 100644 index 0000000000..f4b35eb960 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/readme.md @@ -0,0 +1,5 @@ +# EXOInboundConnector + +## Description + +This resource configures an Inbound connector in your cloud-based organization. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/settings.json new file mode 100644 index 0000000000..5b2c1575a1 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/settings.json @@ -0,0 +1,31 @@ +{ + "resourceName": "EXOInboundConnector", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Remote and Accepted Domains", + "View-Only Configuration" + ], + "requiredrolegroups": "Organization Management" + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/1-ConfigurePlace.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/1-ConfigurePlace.ps1 new file mode 100644 index 0000000000..6a0952ab08 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/1-ConfigurePlace.ps1 @@ -0,0 +1,36 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param + ( + [Parameter(Mandatory = $true)] + [PSCredential] + $credential + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOPlace 'TestPlace' + { + AudioDeviceName = "MyAudioDevice"; + Capacity = 15; #Drift + City = ""; + Credential = $credential + DisplayDeviceName = "DisplayDeviceName"; + Ensure = 'Present' + Identity = "MyRoom@$contoso.com"; + IsWheelChairAccessible = $True; + MTREnabled = $False; + ParentType = "None"; + Phone = "555-555-5555"; + Tags = @("Tag1", "Tag2"); + VideoDeviceName = "VideoDevice"; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOPlace.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOPlace.Tests.ps1 new file mode 100644 index 0000000000..37cd7891ad --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOPlace.Tests.ps1 @@ -0,0 +1,172 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource 'EXOPlace' -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + + BeforeAll { + $secpasswd = ConvertTo-SecureString 'test@password1' -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Set-Place -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + } + + # Test contexts + Context -Name 'Instance is already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + AudioDeviceName = "MyAudioDevice"; + Capacity = 10; + City = ""; + Credential = $Credential; + DisplayDeviceName = "DisplayDeviceName"; + Ensure = "Present"; + Identity = "MyRoom@$contoso.com"; + IsWheelChairAccessible = $True; + MTREnabled = $False; + ParentType = "None"; + Phone = "555-555-5555"; + Tags = @("Tag1", "Tag2"); + VideoDeviceName = "VideoDevice"; + } + + Mock -CommandName Get-Place -MockWith { + return @{ + AudioDeviceName = "MyAudioDevice"; + Capacity = 10; + City = ""; + DisplayDeviceName = "DisplayDeviceName"; + Identity = "MyRoom@$contoso.com"; + IsWheelChairAccessible = $True; + MTREnabled = $False; + ParentType = "None"; + Phone = "555-555-5555"; + Tags = @("Tag1", "Tag2"); + VideoDeviceName = "VideoDevice"; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + + It 'Should not update anything in the Set Method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + } + + Context -Name 'Instance is NOT already in the desired state' -Fixture { + BeforeAll { + $testParams = @{ + AudioDeviceName = "MyAudioDevice"; + Capacity = 10; + City = ""; + Credential = $Credential; + DisplayDeviceName = "DisplayDeviceName"; + Ensure = "Present"; + Identity = "MyRoom@$contoso.com"; + IsWheelChairAccessible = $True; + MTREnabled = $False; + ParentType = "None"; + Phone = "555-555-5555"; + Tags = @("Tag1", "Tag2"); + VideoDeviceName = "VideoDevice"; + } + + Mock -CommandName Get-Place -MockWith { + return @( + @{ + AudioDeviceName = "MyAudioDevice"; + Capacity = 15; #Drift + City = ""; + DisplayDeviceName = "DisplayDeviceName"; + Identity = "MyRoom@$contoso.com"; + IsWheelChairAccessible = $True; + MTREnabled = $False; + ParentType = "None"; + Phone = "555-555-5555"; + Tags = @("Tag1", "Tag2"); + VideoDeviceName = "VideoDevice"; + } + ) + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should not update anything in the Set Method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should update the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Set-Place -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + Mock -CommandName Get-Place -MockWith { + return @( + @{ + AudioDeviceName = "MyAudioDevice"; + Capacity = 15; #Drift + City = ""; + DisplayDeviceName = "DisplayDeviceName"; + Identity = "MyRoom@$contoso.com"; + IsWheelChairAccessible = $True; + MTREnabled = $False; + ParentType = "None"; + Phone = "555-555-5555"; + Tags = @("Tag1", "Tag2"); + VideoDeviceName = "VideoDevice"; + } + ) + } + } + + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 8a04f97a59..9391c3c24e 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -1119,6 +1119,27 @@ function Get-PerimeterConfig $Identity ) } +function Get-Place +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $Type, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $ResultSize + ) +} function Get-PolicyTipConfig { [CmdletBinding()] @@ -9616,6 +9637,10 @@ function Set-OrganizationConfig [System.Boolean] $MailTipsAllTipsEnabled, + [Parameter()] + [System.Boolean] + $PostponeRoamingSignaturesUntilLater, + [Parameter()] [System.Object] $RemotePublicFolderMailboxes, @@ -10686,6 +10711,103 @@ function Set-PerimeterConfig $GatewayIPAddresses ) } +function Set-Place +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $PostalCode, + + [Parameter()] + [System.String] + $Phone, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $CountryOrRegion, + + [Parameter()] + [System.String] + $ParentId, + + [Parameter()] + [System.String] + $Street, + + [Parameter()] + [System.Boolean] + $IsWheelChairAccessible, + + [Parameter()] + [System.String] + $AudioDeviceName, + + [Parameter()] + [System.String] + $DisplayDeviceName, + + [Parameter()] + [System.Object[]] + $Desks, + + [Parameter()] + [System.String] + $Building, + + [Parameter()] + [System.String] + $State, + + [Parameter()] + [System.String] + $City, + + [Parameter()] + [System.Object] + $Floor, + + [Parameter()] + [System.Object] + $ParentType, + + [Parameter()] + [System.String] + $VideoDeviceName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.String[]] + $Tags, + + [Parameter()] + [System.String] + $FloorLabel, + + [Parameter()] + [System.Object] + $Capacity, + + [Parameter()] + [System.String] + $Label, + + [Parameter()] + [System.Object] + $GeoCoordinates, + + [Parameter()] + [System.Boolean] + $MTREnabled + ) +} function Set-PolicyTipConfig { [CmdletBinding()]