From b4807ab1a20219eb2df460ac08d523207f0161fa Mon Sep 17 00:00:00 2001 From: tonysathre Date: Wed, 27 Nov 2024 12:06:26 -0600 Subject: [PATCH 01/24] add Get-PathType function --- .../functions/private/Get-PathType.ps1 | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 module/CitrixAutodeploy/functions/private/Get-PathType.ps1 diff --git a/module/CitrixAutodeploy/functions/private/Get-PathType.ps1 b/module/CitrixAutodeploy/functions/private/Get-PathType.ps1 new file mode 100644 index 0000000..80979eb --- /dev/null +++ b/module/CitrixAutodeploy/functions/private/Get-PathType.ps1 @@ -0,0 +1,25 @@ +function Get-PathType { + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string]$Path + ) + + if ($Path -match '^https?://') { + return 'Uri' + } + + $InvalidPathChars = [System.IO.Path]::GetInvalidPathChars() + $Pattern = [regex]::Escape(($InvalidPathChars -join '')) + + if ($Path -match "[$Pattern]") { + return 'Unknown' + } + + if (Test-Path -Path $Path -PathType Leaf) { + return 'LocalFile' + } + + return 'Unknown' +} From 73fc35b65a3f6f6f7649f343b4e45fce317c4baf Mon Sep 17 00:00:00 2001 From: tonysathre Date: Wed, 27 Nov 2024 12:06:43 -0600 Subject: [PATCH 02/24] add tests for Get-PathType.Tests --- tests/Get-PathType.Tests.ps1 | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 tests/Get-PathType.Tests.ps1 diff --git a/tests/Get-PathType.Tests.ps1 b/tests/Get-PathType.Tests.ps1 new file mode 100644 index 0000000..4e1fa4f --- /dev/null +++ b/tests/Get-PathType.Tests.ps1 @@ -0,0 +1,89 @@ +Describe 'Get-PathType Function' { + BeforeAll { + . "${PSScriptRoot}\..\module\CitrixAutodeploy\functions\private\Get-PathType.ps1" + } + + Context 'Valid HTTP/S URLs' { + It "Should return 'Uri' for an HTTP URL" { + $Result = Get-PathType -Path 'http://example.com' + $Result | Should -Be 'Uri' + } + + It "Should return 'Uri' for an HTTPS URL" { + $Result = Get-PathType -Path 'https://example.com' + $Result | Should -Be 'Uri' + } + + It "Should return 'Uri' for an HTTPS URL with query parameters" { + $Result = Get-PathType -Path 'https://example.com?param=value' + $Result | Should -Be 'Uri' + } + + It "Should return 'Uri' for an HTTPS URL with port number" { + $Result = Get-PathType -Path 'https://example.com:8080' + $Result | Should -Be 'Uri' + } + } + + Context 'Valid Local File Paths' { + BeforeAll { + # Create temporary files for testing + New-Item -Path "$PSScriptRoot\TestFile1.txt" -ItemType File -Force | Out-Null + New-Item -Path "$PSScriptRoot\TestFile2.json" -ItemType File -Force | Out-Null + } + + AfterAll { + # Clean up temporary files + Remove-Item -Path "$PSScriptRoot\TestFile1.txt", "$PSScriptRoot\TestFile2.json" -Force + } + + It "Should return 'LocalFile' for a valid local file path" { + $Result = Get-PathType -Path "$PSScriptRoot\TestFile1.txt" + $Result | Should -Be 'LocalFile' + } + + It "Should return 'LocalFile' for another valid local file path" { + $Result = Get-PathType -Path "$PSScriptRoot\TestFile2.json" + $Result | Should -Be 'LocalFile' + } + } + + Context 'Invalid Paths' { + It "Should return 'Unknown' for a non-existent file path" { + $Result = Get-PathType -Path "$PSScriptRoot\NonExistentFile.txt" + $Result | Should -Be 'Unknown' + } + + It "Should return 'Unknown' for a random string" { + $Result = Get-PathType -Path 'randomstring' + $Result | Should -Be 'Unknown' + } + + It "Should return 'Unknown' for a malformed URL" { + $Result = Get-PathType -Path 'htp:/malformed-url' + $Result | Should -Be 'Unknown' + } + + It 'Should throw an [ParameterArgumentValidationError] exception for an empty string' { + { Get-PathType -Path '' } | Should -Throw -ErrorId 'ParameterArgumentValidationError,Get-PathType' -ExceptionType ([System.Exception]) -ExpectedMessage "*The argument is null or empty*" + } + } + + Context 'Edge Cases' { + It "Should return 'Uri' for a URL with a long query string" { + $LongUrl = 'https://example.com?' + ('param=value&' * 100) + $Result = Get-PathType -Path $LongUrl + $Result | Should -Be 'Uri' + } + + It "Should return 'Unknown' for a directory path" { + $Result = Get-PathType -Path "$PSScriptRoot" + $Result | Should -Be 'Unknown' + } + + It "Should return 'Unknown' for a path with invalid characters" { + $Result = Get-PathType -Path 'C:\Invalid|Path.txt' + $Result | Should -Be 'Unknown' + } + } +} From 56f7021e4e4cf846fb1c6da8fa51cc3d6bfc3296 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Mon, 2 Dec 2024 15:01:29 -0600 Subject: [PATCH 03/24] update module manifest --- build.ps1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index 57c13c5..abffae5 100644 --- a/build.ps1 +++ b/build.ps1 @@ -3,16 +3,18 @@ Import-Module Microsoft.PowerShell.PSResourceGet -ErrorAction Stop $Author = 'Tony Sathre' $CompanyName = 'Tony Sathre' -$Description = 'This module is used to automate the deployment of Citrix virtual desktops in a Citrix Virtual Apps & Desktops environment.' +$Description = 'This module is used to automate the creation of Citrix virtual desktops in a Citrix Virtual Apps & Desktops environment.' $ModuleVersion = '2.0.0.0' $Copyright = "(c) {0} ${Author}. All rights reserved." -f (Get-Date -Format 'yyyy') $ProjectUri = 'https://github.com/tonysathre/CitrixAutodeploy' $BasePath = "${PSScriptRoot}\module\CitrixAutodeploy" +$Path = "${BasePath}\CitrixAutodeploy.psd1" +$RootModule = "${PSScriptRoot}\module\CitrixAutodeploy\CitrixAutodeploy.psm1" $NestedModules = Get-ChildItem -Recurse ${BasePath}\functions\*.ps1 | ForEach-Object { ".\functions\$(Split-Path -Leaf $_.Directory)\$($_.Name)" } $FunctionsToExport = (Get-ChildItem ${BasePath}\functions\public\*.ps1).Name -replace '\.ps1$' $RequiredModules = @('PoShLog') -$ScriptsToProcess = @('.\functions\private\Initialize-InternalLogger.ps1') +#$ScriptsToProcess = @('.\functions\private\Initialize-InternalLogger.ps1') $VariablesToExport = @('InternalLogger') From 4e21c48351e99afeb899cb8bab315295108109cf Mon Sep 17 00:00:00 2001 From: tonysathre Date: Mon, 2 Dec 2024 15:06:30 -0600 Subject: [PATCH 04/24] implement config over http/s --- tests/Get-CtxAutodeployConfig.Tests.ps1 | 122 ++++++++++++------ tests/Get-PathType.Tests.ps1 | 24 ++-- tests/Pester.Helper.psm1 | 10 +- tests/Test-DdcConnection.Tests.ps1 | 2 +- tests/Test-MachineCountExceedsLimit.Tests.ps1 | 2 +- 5 files changed, 104 insertions(+), 56 deletions(-) diff --git a/tests/Get-CtxAutodeployConfig.Tests.ps1 b/tests/Get-CtxAutodeployConfig.Tests.ps1 index 68d382e..73ca86e 100644 --- a/tests/Get-CtxAutodeployConfig.Tests.ps1 +++ b/tests/Get-CtxAutodeployConfig.Tests.ps1 @@ -3,62 +3,106 @@ param () Describe 'Get-CtxAutodeployConfig' { BeforeAll { - Import-Module ${PSScriptRoot}\Pester.Helper.psm1 -Force -ErrorAction Stop 3> $null 4> $null - . "${PSScriptRoot}\..\module\CitrixAutodeploy\functions\public\Get-CtxAutodeployConfig.ps1" + Import-Module "${PSScriptRoot}\Pester.Helper.psm1" -Force -ErrorAction Stop 3> $null 4> $null + Import-CitrixAutodeployModule 3> $null 4> $null } - Context 'When the configuration file exists' { - It 'Should return a configuration object' { - $FilePath = "${PSScriptRoot}\test_config.json" - $Config = Get-CtxAutodeployConfig -FilePath $FilePath - $Config | Should -Not -BeNullOrEmpty - $Config.AutodeployMonitors.AutodeployMonitor[0].AdminAddress | Should -Be 'test-admin-address' + BeforeEach { + $script:FilePath = "${PSScriptRoot}\temp_config.json" + @' +{ + "AutodeployMonitors": { + "AutodeployMonitor": [ + { + "AdminAddress": "test-admin-address", + "BrokerCatalog": "TestCatalog1", + "DesktopGroupName": "TestGroup1", + "MinAvailableMachines": 2, + "PreTask": "", + "PostTask": "" + } + ] + } +} +'@ | Set-Content -Path $FilePath + } + + AfterAll { + if (Test-Path -Path $FilePath) { + Remove-Item -Path $FilePath -Force } } - Context 'When the configuration file does not exist' { - It 'Should throw an error' { - $FilePath = "${PSScriptRoot}\non_existent_config.json" - { Get-CtxAutodeployConfig -FilePath $FilePath } | Should -Throw + Context 'Config File Set via $env:CITRIX_AUTODEPLOY_CONFIG' { + It 'Should return expected configuration object when a valid file path is set via environment variable' { + $env:CITRIX_AUTODEPLOY_CONFIG = $FilePath + + $Result = Get-CtxAutodeployConfig + $Result | Should -BeOfType [PSCustomObject] + $Result.AutodeployMonitors.AutodeployMonitor[0].AdminAddress | Should -Be 'test-admin-address' } } - Context 'When the configuration file is invalid JSON' { - It 'Should throw an error' { - $InvalidJson = @' -{ - "AutodeployMonitors": { - "AutodeployMonitor": [ - { - "AdminAddress": "test-admin-address", - "BrokerCatalog": "test-broker-catalog", - "DesktopGroupName": "test-desktop-group-name", + Context 'Valid Config File' { + It 'Should return expected configuration object when a valid file is provided' { + $Result = Get-CtxAutodeployConfig -Path $FilePath + $Result | Should -BeOfType [PSCustomObject] + $Result.AutodeployMonitors.AutodeployMonitor[0].AdminAddress | Should -Be 'test-admin-address' } } -} -'@ | Set-Content -Path "${PSScriptRoot}\invalid_config.json" - $FilePath = "${PSScriptRoot}\invalid_config.json" - { Get-CtxAutodeployConfig -FilePath $FilePath } | Should -Throw + + Context 'Invalid File Path' { + It 'Should throw an [PathNotFound] exception when file does not exist' { + { Get-CtxAutodeployConfig -Path "${PSScriptRoot}\non_existent_config.json" } | Should -Throw -ErrorId 'PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand' -ExpectedMessage 'Cannot find path*' } + } + + Context 'Unsupported File Format' { + It 'Should throw an error when an unsupported file format is used' { + Set-Content -Path $FilePath -Value 'Invalid Content' + + { Get-CtxAutodeployConfig -Path $FilePath } | Should -Throw -ErrorId 'System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand' -ExpectedMessage 'Invalid JSON primitive: Invalid.' - AfterAll { - Remove-Item "${PSScriptRoot}\invalid_config.json" + Remove-Item -Path $FilePath -Force } } - Context 'When no FilePath is provided and environment variable is set' { - It 'Should use the environment variable for the file path' { - $env:CITRIX_AUTODEPLOY_CONFIG = "${PSScriptRoot}\test_config.json" - $Config = Get-CtxAutodeployConfig - $Config | Should -Not -BeNullOrEmpty - $Config.AutodeployMonitors.AutodeployMonitor[0].AdminAddress | Should -Be 'test-admin-address' + Context 'Download Config Over <_>' -ForEach 'HTTP', 'HTTPS' { + It 'Should successfully download and parse a valid JSON config from an <_> URL' { + $Uri = "{0}://example.com/config.json" -f $_ + + Mock Invoke-WebRequest { + return [PSCustomObject]@{ + StatusCode = 200 + StatusCodeDescription = 'OK' + Content = '{ "Key": "Value" }' + } + } -ModuleName CitrixAutodeploy + + $Result = Get-CtxAutodeployConfig -Path $Uri + + $Result | Should -BeOfType [PSCustomObject] + $Result.Key | Should -Be 'Value' } } - Context 'When no FilePath is provided and environment variable is not set' { - It 'Should throw an error' { - $env:CITRIX_AUTODEPLOY_CONFIG = $null - { Get-CtxAutodeployConfig } | Should -Throw + Context 'Invalid JSON Format' { + It 'Should throw an [System.ArgumentException] exception for invalid JSON format' { + Set-Content -Path $FilePath -Value '{Invalid:Json}' + + { Get-CtxAutodeployConfig -Path $FilePath } | Should -Throw -ErrorId 'System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand' -ExpectedMessage 'Invalid JSON primitive: Json.' + + Remove-Item -Path $FilePath -Force } } -} \ No newline at end of file + + Context 'Empty Config File' { + It 'Should throw an error when the file is empty' { + Set-Content -Path $FilePath -Value $null + + { Get-CtxAutodeployConfig -Path $FilePath } | Should -Throw -ExpectedMessage 'The configuration file is empty*' + + Remove-Item -Path $FilePath -Force + } + } +} diff --git a/tests/Get-PathType.Tests.ps1 b/tests/Get-PathType.Tests.ps1 index 4e1fa4f..40df8c1 100644 --- a/tests/Get-PathType.Tests.ps1 +++ b/tests/Get-PathType.Tests.ps1 @@ -1,4 +1,7 @@ -Describe 'Get-PathType Function' { +[CmdletBinding()] +param () + +Describe 'Get-PathType' { BeforeAll { . "${PSScriptRoot}\..\module\CitrixAutodeploy\functions\private\Get-PathType.ps1" } @@ -27,13 +30,11 @@ Describe 'Get-PathType Function' { Context 'Valid Local File Paths' { BeforeAll { - # Create temporary files for testing New-Item -Path "$PSScriptRoot\TestFile1.txt" -ItemType File -Force | Out-Null New-Item -Path "$PSScriptRoot\TestFile2.json" -ItemType File -Force | Out-Null } AfterAll { - # Clean up temporary files Remove-Item -Path "$PSScriptRoot\TestFile1.txt", "$PSScriptRoot\TestFile2.json" -Force } @@ -46,14 +47,14 @@ Describe 'Get-PathType Function' { $Result = Get-PathType -Path "$PSScriptRoot\TestFile2.json" $Result | Should -Be 'LocalFile' } - } - Context 'Invalid Paths' { - It "Should return 'Unknown' for a non-existent file path" { + It "Should return 'LocalFile' for a non-existent file path" { $Result = Get-PathType -Path "$PSScriptRoot\NonExistentFile.txt" - $Result | Should -Be 'Unknown' + $Result | Should -Be 'LocalFile' } + } + Context 'Invalid Paths' { It "Should return 'Unknown' for a random string" { $Result = Get-PathType -Path 'randomstring' $Result | Should -Be 'Unknown' @@ -67,6 +68,10 @@ Describe 'Get-PathType Function' { It 'Should throw an [ParameterArgumentValidationError] exception for an empty string' { { Get-PathType -Path '' } | Should -Throw -ErrorId 'ParameterArgumentValidationError,Get-PathType' -ExceptionType ([System.Exception]) -ExpectedMessage "*The argument is null or empty*" } + + It 'Should throw an exception for a file path with invalid characters' { + { Get-PathType -Path 'C:\Invalid|Path.txt' } | Should -Throw -ExpectedMessage "The provided file path contains invalid characters*" + } } Context 'Edge Cases' { @@ -80,10 +85,5 @@ Describe 'Get-PathType Function' { $Result = Get-PathType -Path "$PSScriptRoot" $Result | Should -Be 'Unknown' } - - It "Should return 'Unknown' for a path with invalid characters" { - $Result = Get-PathType -Path 'C:\Invalid|Path.txt' - $Result | Should -Be 'Unknown' - } } } diff --git a/tests/Pester.Helper.psm1 b/tests/Pester.Helper.psm1 index ef71d88..e309db0 100644 --- a/tests/Pester.Helper.psm1 +++ b/tests/Pester.Helper.psm1 @@ -7,7 +7,7 @@ function Import-CitrixPowerShellModules { 'Citrix.Broker.Commands', 'Citrix.ConfigurationLogging.Commands', 'Citrix.MachineCreation.Commands' - ) | Import-Module -Force -ErrorAction Stop 3> $null 4> $null + ) | Import-Module -Force -ErrorAction Stop } function Remove-CitrixPowerShellModules { @@ -24,9 +24,13 @@ function Remove-CitrixPowerShellModules { function Import-CitrixAutodeployModule { [CmdletBinding()] - param () + param ( + [Parameter()] + [ValidateSet('Global', 'Local')] + [string]$Scope = 'Global' + ) - Import-Module "${PSScriptRoot}\..\module\CitrixAutodeploy" -Force -ErrorAction Stop + Import-Module "${PSScriptRoot}\..\module\CitrixAutodeploy" -Scope $Scope -Force -ErrorAction Stop } function Remove-CitrixAutodeployModule { diff --git a/tests/Test-DdcConnection.Tests.ps1 b/tests/Test-DdcConnection.Tests.ps1 index d08c5f0..8002c3d 100644 --- a/tests/Test-DdcConnection.Tests.ps1 +++ b/tests/Test-DdcConnection.Tests.ps1 @@ -14,7 +14,7 @@ Describe 'Test-DdcConnection' { } Context 'When connection fails' { - It 'Should return $false using protocol <_>' -ForEach $Protocols { + It "Should return $false using protocol <_>" -ForEach $Protocols { Mock Invoke-RestMethod { return $false } $Result = Test-DdcConnection -AdminAddress 'test-admin-address' -Protocol 'https' diff --git a/tests/Test-MachineCountExceedsLimit.Tests.ps1 b/tests/Test-MachineCountExceedsLimit.Tests.ps1 index 309a6d4..4842bd8 100644 --- a/tests/Test-MachineCountExceedsLimit.Tests.ps1 +++ b/tests/Test-MachineCountExceedsLimit.Tests.ps1 @@ -4,7 +4,7 @@ param () Describe 'Test-MachineCountExceedsLimit' { BeforeDiscovery { Import-Module ${PSScriptRoot}\Pester.Helper.psm1 -Force -ErrorAction Stop 3> $null 4> $null - Import-CitrixPowerShellModules + Import-CitrixPowerShellModules 3> $null 4> $null } BeforeAll { From 32fae84dd3e0fedb6d019cb3a1396c8b75987543 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Mon, 2 Dec 2024 15:07:31 -0600 Subject: [PATCH 05/24] trim trailing whitespace in module manifest --- build.ps1 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build.ps1 b/build.ps1 index abffae5..c575cbb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -25,12 +25,16 @@ $ModuleManifest = @{ Copyright = $Copyright ProjectUri = $ProjectUri ModuleVersion = $ModuleVersion - Path = "${BasePath}\CitrixAutodeploy.psd1" + RootModule = $RootModule + Path = $Path FunctionsToExport = $FunctionsToExport NestedModules = $NestedModules RequiredModules = $RequiredModules - ScriptsToProcess = $ScriptsToProcess + #ScriptsToProcess = $ScriptsToProcess VariablesToExport = $VariablesToExport } Update-PSModuleManifest @ModuleManifest + +# Trim trailing whitespace added by Update-PSModuleManifest +(Get-Content $Path).Trim() | Set-Content $Path From 6e1642920a7bafc7d004c81e4a6442b3c4f0e0f6 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Mon, 2 Dec 2024 15:52:27 -0600 Subject: [PATCH 06/24] handle directories --- .../functions/private/Get-PathType.ps1 | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/module/CitrixAutodeploy/functions/private/Get-PathType.ps1 b/module/CitrixAutodeploy/functions/private/Get-PathType.ps1 index 80979eb..74a865e 100644 --- a/module/CitrixAutodeploy/functions/private/Get-PathType.ps1 +++ b/module/CitrixAutodeploy/functions/private/Get-PathType.ps1 @@ -6,20 +6,29 @@ function Get-PathType { [string]$Path ) + Write-VerboseLog -Message 'Function {MyCommand} called with parameters: {PSBoundParameters}' -PropertyValues $MyInvocation.MyCommand, ($PSBoundParameters | Out-String) + if ($Path -match '^https?://') { return 'Uri' } - $InvalidPathChars = [System.IO.Path]::GetInvalidPathChars() + # PowerShell 5.1 uses .NET 4.0.30319.42000 + # [System.IO.Path]::GetInvalidPathChars() contains these printable characters: "<>\|☺☻♥♦♣\t\n\f\r►◄↕‼¶§▬↨↑↓→∟↔▲▼ + # There are also several non-printable characters in the array. + $InvalidPathChars = [System.IO.Path]::InvalidPathChars $Pattern = [regex]::Escape(($InvalidPathChars -join '')) if ($Path -match "[$Pattern]") { - return 'Unknown' + throw [System.IO.IOException]::new('The provided file path contains invalid characters: {0}' -f $Path) } - if (Test-Path -Path $Path -PathType Leaf) { + if ([System.IO.Path]::GetExtension($Path)) { return 'LocalFile' } + if (Test-Path $Path -PathType Container) { + return 'Directory' + } + return 'Unknown' } From f0bb2a708e04b390a2dda8ddae0ae61244e64368 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Mon, 2 Dec 2024 15:56:37 -0600 Subject: [PATCH 07/24] improve tests --- test.ps1 | 20 +++++++------- tests/Get-CtxAutodeployConfig.Tests.ps1 | 18 ++++++------- tests/Get-PathType.Tests.ps1 | 36 +++++++++++++------------ 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/test.ps1 b/test.ps1 index 4404d1e..53f9e44 100644 --- a/test.ps1 +++ b/test.ps1 @@ -28,30 +28,32 @@ param ( try { if ($PSBoundParameters['Verbose']) { . ${PSScriptRoot}\module\CitrixAutodeploy\functions\public\Initialize-CtxAutodeployLogger.ps1 4> $null - $VerbosePreference -eq 'Continue' $Logger = Initialize-CtxAutodeployLogger -LogLevel Verbose -AddEnrichWithExceptionDetails } if ($PSBoundParameters['Debug']) { . ${PSScriptRoot}\module\CitrixAutodeploy\functions\public\Initialize-CtxAutodeployLogger.ps1 4> $null - $DebugPreference -eq 'Continue' $Logger = Initialize-CtxAutodeployLogger -LogLevel Debug -AddEnrichWithExceptionDetails } $PesterConfiguration = New-PesterConfiguration - $PesterConfiguration.Output.Verbosity = $Output - $PesterConfiguration.Run.Path = $Tests - $PesterConfiguration.Output.StackTraceVerbosity = $StackTraceVerbosity - $PesterConfiguration.CodeCoverage.Enabled = $CodeCoverageEnabled - $PesterConfiguration.CodeCoverage.Path = $Tests + $PesterConfiguration.Output.Verbosity = $Output + $PesterConfiguration.Run.Path = $Tests + $PesterConfiguration.Output.StackTraceVerbosity = $StackTraceVerbosity + $PesterConfiguration.CodeCoverage.Enabled = $CodeCoverageEnabled + $PesterConfiguration.CodeCoverage.Path = $Tests $PesterConfiguration.CodeCoverage.CoveragePercentTarget = 75 Invoke-Pester -Configuration $PesterConfiguration } -catch {} +catch { + throw $_ +} finally { Close-Logger -} + $global:VerbosePreference = 'SilentlyContinue' + $global:DebugPreference = 'SilentlyContinue' +} diff --git a/tests/Get-CtxAutodeployConfig.Tests.ps1 b/tests/Get-CtxAutodeployConfig.Tests.ps1 index 73ca86e..ddcd164 100644 --- a/tests/Get-CtxAutodeployConfig.Tests.ps1 +++ b/tests/Get-CtxAutodeployConfig.Tests.ps1 @@ -33,19 +33,19 @@ Describe 'Get-CtxAutodeployConfig' { } } - Context 'Config File Set via $env:CITRIX_AUTODEPLOY_CONFIG' { - It 'Should return expected configuration object when a valid file path is set via environment variable' { - $env:CITRIX_AUTODEPLOY_CONFIG = $FilePath - - $Result = Get-CtxAutodeployConfig + Context 'Valid Config File' { + It 'Should return expected configuration object when a valid file is provided' { + $Result = Get-CtxAutodeployConfig -Path $FilePath $Result | Should -BeOfType [PSCustomObject] $Result.AutodeployMonitors.AutodeployMonitor[0].AdminAddress | Should -Be 'test-admin-address' } } - Context 'Valid Config File' { - It 'Should return expected configuration object when a valid file is provided' { - $Result = Get-CtxAutodeployConfig -Path $FilePath + Context 'Config File Set via $env:CITRIX_AUTODEPLOY_CONFIG' { + It 'Should return expected configuration object when a valid file path is set via environment variable' { + $env:CITRIX_AUTODEPLOY_CONFIG = $FilePath + + $Result = Get-CtxAutodeployConfig $Result | Should -BeOfType [PSCustomObject] $Result.AutodeployMonitors.AutodeployMonitor[0].AdminAddress | Should -Be 'test-admin-address' } @@ -97,7 +97,7 @@ Describe 'Get-CtxAutodeployConfig' { } Context 'Empty Config File' { - It 'Should throw an error when the file is empty' { + It 'Should throw an error when the file is exists, but is empty' { Set-Content -Path $FilePath -Value $null { Get-CtxAutodeployConfig -Path $FilePath } | Should -Throw -ExpectedMessage 'The configuration file is empty*' diff --git a/tests/Get-PathType.Tests.ps1 b/tests/Get-PathType.Tests.ps1 index 40df8c1..3202c16 100644 --- a/tests/Get-PathType.Tests.ps1 +++ b/tests/Get-PathType.Tests.ps1 @@ -6,24 +6,19 @@ Describe 'Get-PathType' { . "${PSScriptRoot}\..\module\CitrixAutodeploy\functions\private\Get-PathType.ps1" } - Context 'Valid HTTP/S URLs' { - It "Should return 'Uri' for an HTTP URL" { - $Result = Get-PathType -Path 'http://example.com' + Context 'Valid <_> URLs' -ForEach 'HTTP', 'HTTPS' { + It "Should return 'Uri' for an <_> URL" { + $Result = Get-PathType -Path ('{0}://example.com' -f $_) $Result | Should -Be 'Uri' } - It "Should return 'Uri' for an HTTPS URL" { - $Result = Get-PathType -Path 'https://example.com' + It "Should return 'Uri' for an <_> URL with query parameters" { + $Result = Get-PathType -Path ('{0}://example.com?param=value' -f $_) $Result | Should -Be 'Uri' } - It "Should return 'Uri' for an HTTPS URL with query parameters" { - $Result = Get-PathType -Path 'https://example.com?param=value' - $Result | Should -Be 'Uri' - } - - It "Should return 'Uri' for an HTTPS URL with port number" { - $Result = Get-PathType -Path 'https://example.com:8080' + It "Should return 'Uri' for an <_> URL with port number" { + $Result = Get-PathType -Path ('{0}://example.com:8080' -f $_) $Result | Should -Be 'Uri' } } @@ -54,6 +49,18 @@ Describe 'Get-PathType' { } } + Context 'Valid Directory Paths' { + It "Should return 'Directory' for a valid directory path" { + $Result = Get-PathType -Path "$PSScriptRoot" + $Result | Should -Be 'Directory' + } + + It "Should return 'Directory' for another valid directory path" { + $Result = Get-PathType -Path "$env:TEMP" + $Result | Should -Be 'Directory' + } + } + Context 'Invalid Paths' { It "Should return 'Unknown' for a random string" { $Result = Get-PathType -Path 'randomstring' @@ -80,10 +87,5 @@ Describe 'Get-PathType' { $Result = Get-PathType -Path $LongUrl $Result | Should -Be 'Uri' } - - It "Should return 'Unknown' for a directory path" { - $Result = Get-PathType -Path "$PSScriptRoot" - $Result | Should -Be 'Unknown' - } } } From 391f2a594819b2581b1da0409d6b6d9480b52c1f Mon Sep 17 00:00:00 2001 From: tonysathre Date: Mon, 2 Dec 2024 15:57:03 -0600 Subject: [PATCH 08/24] add stuff --- module/CitrixAutodeploy/CitrixAutodeploy.psd1 | 71 ++++++++++--------- module/CitrixAutodeploy/CitrixAutodeploy.psm1 | 10 ++- .../public/Get-CtxAutodeployConfig.ps1 | 57 ++++++++++++--- 3 files changed, 93 insertions(+), 45 deletions(-) diff --git a/module/CitrixAutodeploy/CitrixAutodeploy.psd1 b/module/CitrixAutodeploy/CitrixAutodeploy.psd1 index 5b81baf..bddc554 100644 --- a/module/CitrixAutodeploy/CitrixAutodeploy.psd1 +++ b/module/CitrixAutodeploy/CitrixAutodeploy.psd1 @@ -3,13 +3,13 @@ # # Generated by: Tony Sathre # -# Generated on: 11/25/2024 +# Generated on: 12/2/2024 # @{ # Script module or binary module file associated with this manifest. -# RootModule = '' +RootModule = 'C:\Users\m89944\git\tonysathre\CitrixAutoDeploy\module\CitrixAutodeploy\CitrixAutodeploy.psm1' # Version number of this module. ModuleVersion = '2.0.0.0' @@ -30,7 +30,7 @@ CompanyName = 'Tony Sathre' Copyright = '(c) 2024 Tony Sathre. All rights reserved.' # Description of the functionality provided by this module -Description = 'This module is used to automate the deployment of Citrix virtual desktops in a Citrix Virtual Apps & Desktops environment.' +Description = 'This module is used to automate the creation of Citrix virtual desktops in a Citrix Virtual Apps & Desktops environment.' # Minimum version of the Windows PowerShell engine required by this module # PowerShellVersion = '' @@ -66,24 +66,25 @@ ScriptsToProcess = '.\functions\private\Initialize-InternalLogger.ps1' # FormatsToProcess = @() # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -NestedModules = @('.\functions\private\Initialize-InternalLogger.ps1', - '.\functions\public\Get-CtxAutodeployConfig.ps1', - '.\functions\public\Initialize-CtxAutodeployEnv.ps1', - '.\functions\public\Initialize-CtxAutodeployLogger.ps1', - '.\functions\public\Invoke-CtxAutodeployTask.ps1', - '.\functions\public\New-CtxAutodeployVM.ps1', - '.\functions\public\Start-CtxHighLevelLogger.ps1', - '.\functions\public\Stop-CtxHighLevelLogger.ps1', - '.\functions\public\Test-DdcConnection.ps1', - '.\functions\public\Test-MachineCountExceedsLimit.ps1', - '.\functions\public\Wait-ForIdentityPoolUnlock.ps1') +NestedModules = @('.\functions\private\Get-PathType.ps1', +'.\functions\private\Initialize-InternalLogger.ps1', +'.\functions\public\Get-CtxAutodeployConfig.ps1', +'.\functions\public\Initialize-CtxAutodeployEnv.ps1', +'.\functions\public\Initialize-CtxAutodeployLogger.ps1', +'.\functions\public\Invoke-CtxAutodeployTask.ps1', +'.\functions\public\New-CtxAutodeployVM.ps1', +'.\functions\public\Start-CtxHighLevelLogger.ps1', +'.\functions\public\Stop-CtxHighLevelLogger.ps1', +'.\functions\public\Test-DdcConnection.ps1', +'.\functions\public\Test-MachineCountExceedsLimit.ps1', +'.\functions\public\Wait-ForIdentityPoolUnlock.ps1') # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = 'Get-CtxAutodeployConfig', 'Initialize-CtxAutodeployEnv', - 'Initialize-CtxAutodeployLogger', 'Invoke-CtxAutodeployTask', - 'New-CtxAutodeployVM', 'Start-CtxHighLevelLogger', - 'Stop-CtxHighLevelLogger', 'Test-DdcConnection', - 'Test-MachineCountExceedsLimit', 'Wait-ForIdentityPoolUnlock' +FunctionsToExport = 'Get-CtxAutodeployConfig', 'Initialize-CtxAutodeployEnv', +'Initialize-CtxAutodeployLogger', 'Invoke-CtxAutodeployTask', +'New-CtxAutodeployVM', 'Start-CtxHighLevelLogger', +'Stop-CtxHighLevelLogger', 'Test-DdcConnection', +'Test-MachineCountExceedsLimit', 'Wait-ForIdentityPoolUnlock' # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() @@ -107,29 +108,29 @@ AliasesToExport = @() PrivateData = @{ PSData = @{ - # Tags applied to this module. These help with module discovery in online galleries. - # Tags = @() +# Tags applied to this module. These help with module discovery in online galleries. +# Tags = @() - # A URL to the license for this module. - # LicenseUri = '' +# A URL to the license for this module. +# LicenseUri = '' - # A URL to the main website for this project. - ProjectUri = 'https://github.com/tonysathre/CitrixAutodeploy' +# A URL to the main website for this project. +ProjectUri = 'https://github.com/tonysathre/CitrixAutodeploy' - # A URL to an icon representing this module. - # IconUri = '' +# A URL to an icon representing this module. +# IconUri = '' - # ReleaseNotes of this module - # ReleaseNotes = '' +# ReleaseNotes of this module +# ReleaseNotes = '' - # Prerelease string of this module - # Prerelease = '' +# Prerelease string of this module +# Prerelease = '' - # Flag to indicate whether the module requires explicit user acceptance for install/update/save - # RequireLicenseAcceptance = $false +# Flag to indicate whether the module requires explicit user acceptance for install/update/save +# RequireLicenseAcceptance = $false - # External dependent modules of this module - # ExternalModuleDependencies = @() +# External dependent modules of this module +# ExternalModuleDependencies = @() } # End of PSData hashtable } # End of PrivateData hashtable diff --git a/module/CitrixAutodeploy/CitrixAutodeploy.psm1 b/module/CitrixAutodeploy/CitrixAutodeploy.psm1 index eed3f31..e99a956 100644 --- a/module/CitrixAutodeploy/CitrixAutodeploy.psm1 +++ b/module/CitrixAutodeploy/CitrixAutodeploy.psm1 @@ -1 +1,9 @@ -# TODO: may not even need this \ No newline at end of file +# dot-source private functions +foreach ($Folder in @('private')) { + $Root = Join-Path -Path $PSScriptRoot -ChildPath $Folder + if (Test-Path -Path $Root) { + Write-Verbose "processing folder $Root" + $Files = Get-ChildItem -Path $Root -Filter *.ps1 -Recurse + $Files | ForEach-Object { Write-Verbose $_.basename; . $PSItem.FullName } + } +} diff --git a/module/CitrixAutodeploy/functions/public/Get-CtxAutodeployConfig.ps1 b/module/CitrixAutodeploy/functions/public/Get-CtxAutodeployConfig.ps1 index 19ebf24..ce4ed38 100644 --- a/module/CitrixAutodeploy/functions/public/Get-CtxAutodeployConfig.ps1 +++ b/module/CitrixAutodeploy/functions/public/Get-CtxAutodeployConfig.ps1 @@ -1,21 +1,60 @@ function Get-CtxAutodeployConfig { [CmdletBinding()] - [OutputType([PSCustomObject])] - param( + param ( [Parameter()] - [System.IO.FileInfo]$FilePath = $env:CITRIX_AUTODEPLOY_CONFIG + [ValidateNotNullOrEmpty()] + [string]$Path = $env:CITRIX_AUTODEPLOY_CONFIG ) - Write-VerboseLog -Message "Function {MyCommand} called with parameters: {PSBoundParameters}" -PropertyValues $MyInvocation.MyCommand, ($PSBoundParameters | Out-String) - Write-InfoLog -Message "Loading configuration from file: {FilePath}" -PropertyValues $FilePath + Write-VerboseLog -Message 'Function {MyCommand} called with parameters: {PSBoundParameters}' -PropertyValues $MyInvocation.MyCommand, ($PSBoundParameters | Out-String) + + $PathType = Get-PathType -Path $Path + Write-DebugLog -Message 'PathType: {PathType}' -PropertyValues $PathType + + switch ($PathType) { + 'Uri' { + try { + Write-VerboseLog -Message 'Downloading configuration from URL: {Path}' -PropertyValues $Path + $Response = Invoke-WebRequest -Uri $Path -UseBasicParsing + $ConfigContent = $Response.Content + } + catch { + Write-ErrorLog -Message 'Failed to download the configuration file from URL: {Path}' -Exception $_.Exception -ErrorRecord $_ -PropertyValues $Path + throw + } + } + 'LocalFile' { + try { + Write-VerboseLog -Message 'Reading configuration from local file: {Path}' -PropertyValues $Path + $ConfigContent = Get-Content -Path $Path -Raw -ErrorAction Stop + + if ($ConfigContent.Length -eq 0) { + Write-ErrorLog -Message 'The configuration file is empty: {Path}' -PropertyValues $Path + throw [System.IO.IOException]::new('The configuration file is empty: {0}' -f $Path) + } + } + catch { + Write-FatalLog -Message 'Failed to read the configuration file from local path: {Path}' -Exception $_.Exception -ErrorRecord $_ -PropertyValues $Path + throw + } + } + 'Directory' { + Write-FatalLog -Message 'The provided path is a directory: {Path}' -Exception ([System.Management.Automation.ItemNotFoundException]::new('Directory path')) -PropertyValues $Path + throw + } + default { + Write-FatalLog -Message 'The provided path is neither a valid URL nor a local file path: {Path}' -Exception ([System.Management.Automation.ItemNotFoundException]::new('Invalid path or URL')) -PropertyValues $Path + throw + } + } try { - $Config = Get-Content -Path $FilePath -Raw -ErrorAction Stop | ConvertFrom-Json + $Config = ConvertFrom-Json -InputObject $ConfigContent + + return $Config } catch { - Write-FatalLog -Message "Failed to load configuration from file {FilePath}" -Exception $_.Exception -ErrorRecord $_ -PropertyValues $FilePath + Write-ErrorLog -Message 'Failed to parse the configuration content as JSON: {ConfigContent}' -Exception $_.Exception -ErrorRecord $_ -PropertyValues $ConfigContent throw } - - return $Config } From 0a4b86148c5b16c8ca392b177e4431b7a8f95d9d Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 09:46:39 -0600 Subject: [PATCH 09/24] replace Trim() -> TrimEnd() --- build.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.ps1 b/build.ps1 index c575cbb..9bbeef4 100644 --- a/build.ps1 +++ b/build.ps1 @@ -37,4 +37,4 @@ $ModuleManifest = @{ Update-PSModuleManifest @ModuleManifest # Trim trailing whitespace added by Update-PSModuleManifest -(Get-Content $Path).Trim() | Set-Content $Path +(Get-Content $Path).TrimEnd() | Set-Content $Path From 7acd9d063238aacdc501e512e10d6297ea3c346a Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 10:44:26 -0600 Subject: [PATCH 10/24] update manifest --- module/CitrixAutodeploy/CitrixAutodeploy.psd1 | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/module/CitrixAutodeploy/CitrixAutodeploy.psd1 b/module/CitrixAutodeploy/CitrixAutodeploy.psd1 index bddc554..2b36d3c 100644 --- a/module/CitrixAutodeploy/CitrixAutodeploy.psd1 +++ b/module/CitrixAutodeploy/CitrixAutodeploy.psd1 @@ -3,7 +3,7 @@ # # Generated by: Tony Sathre # -# Generated on: 12/2/2024 +# Generated on: 12/3/2024 # @{ @@ -67,24 +67,24 @@ ScriptsToProcess = '.\functions\private\Initialize-InternalLogger.ps1' # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess NestedModules = @('.\functions\private\Get-PathType.ps1', -'.\functions\private\Initialize-InternalLogger.ps1', -'.\functions\public\Get-CtxAutodeployConfig.ps1', -'.\functions\public\Initialize-CtxAutodeployEnv.ps1', -'.\functions\public\Initialize-CtxAutodeployLogger.ps1', -'.\functions\public\Invoke-CtxAutodeployTask.ps1', -'.\functions\public\New-CtxAutodeployVM.ps1', -'.\functions\public\Start-CtxHighLevelLogger.ps1', -'.\functions\public\Stop-CtxHighLevelLogger.ps1', -'.\functions\public\Test-DdcConnection.ps1', -'.\functions\public\Test-MachineCountExceedsLimit.ps1', -'.\functions\public\Wait-ForIdentityPoolUnlock.ps1') + '.\functions\private\Initialize-InternalLogger.ps1', + '.\functions\public\Get-CtxAutodeployConfig.ps1', + '.\functions\public\Initialize-CtxAutodeployEnv.ps1', + '.\functions\public\Initialize-CtxAutodeployLogger.ps1', + '.\functions\public\Invoke-CtxAutodeployTask.ps1', + '.\functions\public\New-CtxAutodeployVM.ps1', + '.\functions\public\Start-CtxHighLevelLogger.ps1', + '.\functions\public\Stop-CtxHighLevelLogger.ps1', + '.\functions\public\Test-DdcConnection.ps1', + '.\functions\public\Test-MachineCountExceedsLimit.ps1', + '.\functions\public\Wait-ForIdentityPoolUnlock.ps1') # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = 'Get-CtxAutodeployConfig', 'Initialize-CtxAutodeployEnv', -'Initialize-CtxAutodeployLogger', 'Invoke-CtxAutodeployTask', -'New-CtxAutodeployVM', 'Start-CtxHighLevelLogger', -'Stop-CtxHighLevelLogger', 'Test-DdcConnection', -'Test-MachineCountExceedsLimit', 'Wait-ForIdentityPoolUnlock' + 'Initialize-CtxAutodeployLogger', 'Invoke-CtxAutodeployTask', + 'New-CtxAutodeployVM', 'Start-CtxHighLevelLogger', + 'Stop-CtxHighLevelLogger', 'Test-DdcConnection', + 'Test-MachineCountExceedsLimit', 'Wait-ForIdentityPoolUnlock' # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() @@ -108,29 +108,29 @@ AliasesToExport = @() PrivateData = @{ PSData = @{ -# Tags applied to this module. These help with module discovery in online galleries. -# Tags = @() + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() -# A URL to the license for this module. -# LicenseUri = '' + # A URL to the license for this module. + # LicenseUri = '' -# A URL to the main website for this project. -ProjectUri = 'https://github.com/tonysathre/CitrixAutodeploy' + # A URL to the main website for this project. + ProjectUri = 'https://github.com/tonysathre/CitrixAutodeploy' -# A URL to an icon representing this module. -# IconUri = '' + # A URL to an icon representing this module. + # IconUri = '' -# ReleaseNotes of this module -# ReleaseNotes = '' + # ReleaseNotes of this module + # ReleaseNotes = '' -# Prerelease string of this module -# Prerelease = '' + # Prerelease string of this module + # Prerelease = '' -# Flag to indicate whether the module requires explicit user acceptance for install/update/save -# RequireLicenseAcceptance = $false + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false -# External dependent modules of this module -# ExternalModuleDependencies = @() + # External dependent modules of this module + # ExternalModuleDependencies = @() } # End of PSData hashtable } # End of PrivateData hashtable From 565253b6e3663a28cdf84fe64cc8c26bc00d0b7e Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 11:42:24 -0600 Subject: [PATCH 11/24] wip --- tests/Get-CtxAutodeployConfig.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Get-CtxAutodeployConfig.Tests.ps1 b/tests/Get-CtxAutodeployConfig.Tests.ps1 index ddcd164..3a8c8fb 100644 --- a/tests/Get-CtxAutodeployConfig.Tests.ps1 +++ b/tests/Get-CtxAutodeployConfig.Tests.ps1 @@ -28,7 +28,7 @@ Describe 'Get-CtxAutodeployConfig' { } AfterAll { - if (Test-Path -Path $FilePath) { + if (Test-Path -Path $script:FilePath) { Remove-Item -Path $FilePath -Force } } From 014694278e665d308ecd870de94650e7d491016a Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 11:58:38 -0600 Subject: [PATCH 12/24] add tmate for debugging --- .github/workflows/ci.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d63f86..0cde440 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,9 @@ name: CI on: pull_request: +env: + DEBUG: true + jobs: test: runs-on: windows-latest @@ -15,4 +18,8 @@ jobs: - run: | $env:PSModulePath += ";C:\Program Files\Citrix\PowerShellModules" .\test - shell: powershell \ No newline at end of file + shell: powershell + + - name: Setup tmate session + if: ${{ env.DEBUG }} == true + uses: mxschmitt/action-tmate@v3 From 1e1a58adafaecb221501b9cc90da2597a8cb0362 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 11:59:01 -0600 Subject: [PATCH 13/24] wip --- tests/Get-CtxAutodeployConfig.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Get-CtxAutodeployConfig.Tests.ps1 b/tests/Get-CtxAutodeployConfig.Tests.ps1 index 3a8c8fb..8bb9335 100644 --- a/tests/Get-CtxAutodeployConfig.Tests.ps1 +++ b/tests/Get-CtxAutodeployConfig.Tests.ps1 @@ -4,7 +4,7 @@ param () Describe 'Get-CtxAutodeployConfig' { BeforeAll { Import-Module "${PSScriptRoot}\Pester.Helper.psm1" -Force -ErrorAction Stop 3> $null 4> $null - Import-CitrixAutodeployModule 3> $null 4> $null + Import-CitrixAutodeployModule } BeforeEach { @@ -28,7 +28,7 @@ Describe 'Get-CtxAutodeployConfig' { } AfterAll { - if (Test-Path -Path $script:FilePath) { + if (Test-Path -Path $FilePath) { Remove-Item -Path $FilePath -Force } } From 024e5f908b9681933324e352dcfcd7016437ed04 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 12:02:08 -0600 Subject: [PATCH 14/24] true -> 'true' --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cde440..29453e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,5 +21,5 @@ jobs: shell: powershell - name: Setup tmate session - if: ${{ env.DEBUG }} == true + if: ${{ env.DEBUG }} == 'true' uses: mxschmitt/action-tmate@v3 From 48ca4f95ef167e0e7cd905753cb044b09a457289 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 12:05:25 -0600 Subject: [PATCH 15/24] wip --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 29453e8..ce63eaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: pull_request: env: - DEBUG: true + DEBUG: 'true' jobs: test: From 2a7ce5179ad1fc3ce52d28c04c241192f75d25a2 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 12:08:30 -0600 Subject: [PATCH 16/24] wip --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce63eaa..bbdc969 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: pull_request: env: - DEBUG: 'true' + DEBUG: true jobs: test: @@ -21,5 +21,5 @@ jobs: shell: powershell - name: Setup tmate session - if: ${{ env.DEBUG }} == 'true' + if: ${{ env.DEBUG == true }} uses: mxschmitt/action-tmate@v3 From 7e9d6230b50635e2d453852e77704f83bbd5e5ff Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 15:38:12 -0600 Subject: [PATCH 17/24] wip --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbdc969..098c986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: pull_request: env: - DEBUG: true + DEBUG: 'true' jobs: test: @@ -21,5 +21,5 @@ jobs: shell: powershell - name: Setup tmate session - if: ${{ env.DEBUG == true }} + if: ${{ env.DEBUG == 'true' }} uses: mxschmitt/action-tmate@v3 From 5a9165119c680e4cb9732470d1d716cb51e2a77a Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 15:46:25 -0600 Subject: [PATCH 18/24] remove imports --- tests/Initialize-CtxAutodeployLogger.Tests.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/Initialize-CtxAutodeployLogger.Tests.ps1 b/tests/Initialize-CtxAutodeployLogger.Tests.ps1 index ae43e00..5f58fc8 100644 --- a/tests/Initialize-CtxAutodeployLogger.Tests.ps1 +++ b/tests/Initialize-CtxAutodeployLogger.Tests.ps1 @@ -4,8 +4,6 @@ param () Describe 'Initialize-CtxAutodeployLogger' { BeforeAll { . "${PSScriptRoot}\..\module\CitrixAutodeploy\functions\public\Initialize-CtxAutodeployLogger.ps1" - Import-Module ${PSScriptRoot}\Pester.Helper.psm1 -Force -ErrorAction Stop 3> $null 4> $null - Import-CitrixAutodeployModule 3> $null 4> $null } AfterAll { From d2ecd1b4bf7574c1a9d575ba0814b073a316b83a Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 15:47:44 -0600 Subject: [PATCH 19/24] wip --- tests/Get-CtxAutodeployConfig.Tests.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Get-CtxAutodeployConfig.Tests.ps1 b/tests/Get-CtxAutodeployConfig.Tests.ps1 index 8bb9335..aaed7f3 100644 --- a/tests/Get-CtxAutodeployConfig.Tests.ps1 +++ b/tests/Get-CtxAutodeployConfig.Tests.ps1 @@ -4,7 +4,6 @@ param () Describe 'Get-CtxAutodeployConfig' { BeforeAll { Import-Module "${PSScriptRoot}\Pester.Helper.psm1" -Force -ErrorAction Stop 3> $null 4> $null - Import-CitrixAutodeployModule } BeforeEach { @@ -29,7 +28,7 @@ Describe 'Get-CtxAutodeployConfig' { AfterAll { if (Test-Path -Path $FilePath) { - Remove-Item -Path $FilePath -Force + Remove-Item -Path $FilePath -Force -ErrorAction SilentlyContinue } } From 1f48caf123db0b8a01588d1b9de056fc393b4660 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 15:50:51 -0600 Subject: [PATCH 20/24] wip --- tests/Get-CtxAutodeployConfig.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Get-CtxAutodeployConfig.Tests.ps1 b/tests/Get-CtxAutodeployConfig.Tests.ps1 index aaed7f3..d3a1c84 100644 --- a/tests/Get-CtxAutodeployConfig.Tests.ps1 +++ b/tests/Get-CtxAutodeployConfig.Tests.ps1 @@ -4,6 +4,7 @@ param () Describe 'Get-CtxAutodeployConfig' { BeforeAll { Import-Module "${PSScriptRoot}\Pester.Helper.psm1" -Force -ErrorAction Stop 3> $null 4> $null + Import-CitrixAutodeployModule } BeforeEach { From e8ab86f3a09cddceff503d27e0e7e2bffd55713e Mon Sep 17 00:00:00 2001 From: tonysathre Date: Tue, 3 Dec 2024 15:55:56 -0600 Subject: [PATCH 21/24] wip --- tests/Wait-ForIdentityPoolUnlock.Tests.ps1 | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/Wait-ForIdentityPoolUnlock.Tests.ps1 b/tests/Wait-ForIdentityPoolUnlock.Tests.ps1 index eb81045..a7797ca 100644 --- a/tests/Wait-ForIdentityPoolUnlock.Tests.ps1 +++ b/tests/Wait-ForIdentityPoolUnlock.Tests.ps1 @@ -46,12 +46,11 @@ Describe 'Wait-ForIdentityPoolUnlock' { # A bit janky but it works for now $Buffer = .5 $global:CallCount = 0 - $Timeout = 2 $Params = @{ AdminAddress = New-MockAdminAddress IdentityPool = Get-AcctIdentityPoolMock -Lock $true - Timeout = $Timeout + Timeout = 2 } $StartTime = Get-Date @@ -60,14 +59,14 @@ Describe 'Wait-ForIdentityPoolUnlock' { $ExecutionTime = $EndTime - $StartTime $ExecutionTime.TotalSeconds | Should -BeGreaterThan 1 - $ExecutionTime.TotalSeconds | Should -BeLessOrEqual ($Timeout + $Buffer) + $ExecutionTime.TotalSeconds | Should -BeLessOrEqual ($Params.Timeout + $Buffer) } } Context 'When the identity pool remains locked beyond the timeout period' { It 'Should exit after the specified timeout period' { Mock Get-AcctIdentityPool { return Get-AcctIdentityPoolMock -Lock $true } - + $Buffer = 2 $Params = @{ AdminAddress = New-MockAdminAddress IdentityPool = Get-AcctIdentityPoolMock -Lock $true @@ -79,7 +78,7 @@ Describe 'Wait-ForIdentityPoolUnlock' { } $ExecutionTime.TotalSeconds | Should -BeGreaterOrEqual 2 - $ExecutionTime.TotalSeconds | Should -BeLessThan 3 + $ExecutionTime.TotalSeconds | Should -BeLessThan ($Params.Timeout + $Buffer) # 2 second buffer to account for execution overhead Should -Invoke Get-AcctIdentityPool -Times 2 -Scope It } From 6c02cebf5df971e5a1d07ec9ac6671f368953d01 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Wed, 4 Dec 2024 10:03:54 -0600 Subject: [PATCH 22/24] wip --- .github/workflows/ci.yml | 4 ++-- tests/Get-CtxAutodeployConfig.Tests.ps1 | 6 ++++-- tests/Initialize-CtxAutodeployLogger.Tests.ps1 | 2 -- tests/Wait-ForIdentityPoolUnlock.Tests.ps1 | 9 ++++----- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cde440..098c986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: pull_request: env: - DEBUG: true + DEBUG: 'true' jobs: test: @@ -21,5 +21,5 @@ jobs: shell: powershell - name: Setup tmate session - if: ${{ env.DEBUG }} == true + if: ${{ env.DEBUG == 'true' }} uses: mxschmitt/action-tmate@v3 diff --git a/tests/Get-CtxAutodeployConfig.Tests.ps1 b/tests/Get-CtxAutodeployConfig.Tests.ps1 index 3a8c8fb..50f10c0 100644 --- a/tests/Get-CtxAutodeployConfig.Tests.ps1 +++ b/tests/Get-CtxAutodeployConfig.Tests.ps1 @@ -4,7 +4,7 @@ param () Describe 'Get-CtxAutodeployConfig' { BeforeAll { Import-Module "${PSScriptRoot}\Pester.Helper.psm1" -Force -ErrorAction Stop 3> $null 4> $null - Import-CitrixAutodeployModule 3> $null 4> $null + Import-CitrixAutodeployModule } BeforeEach { @@ -29,8 +29,10 @@ Describe 'Get-CtxAutodeployConfig' { AfterAll { if (Test-Path -Path $script:FilePath) { - Remove-Item -Path $FilePath -Force + Remove-Item -Path $script:FilePath -Force -ErrorAction SilentlyContinue } + + Remove-CitrixAutodeployModule } Context 'Valid Config File' { diff --git a/tests/Initialize-CtxAutodeployLogger.Tests.ps1 b/tests/Initialize-CtxAutodeployLogger.Tests.ps1 index ae43e00..5f58fc8 100644 --- a/tests/Initialize-CtxAutodeployLogger.Tests.ps1 +++ b/tests/Initialize-CtxAutodeployLogger.Tests.ps1 @@ -4,8 +4,6 @@ param () Describe 'Initialize-CtxAutodeployLogger' { BeforeAll { . "${PSScriptRoot}\..\module\CitrixAutodeploy\functions\public\Initialize-CtxAutodeployLogger.ps1" - Import-Module ${PSScriptRoot}\Pester.Helper.psm1 -Force -ErrorAction Stop 3> $null 4> $null - Import-CitrixAutodeployModule 3> $null 4> $null } AfterAll { diff --git a/tests/Wait-ForIdentityPoolUnlock.Tests.ps1 b/tests/Wait-ForIdentityPoolUnlock.Tests.ps1 index eb81045..a7797ca 100644 --- a/tests/Wait-ForIdentityPoolUnlock.Tests.ps1 +++ b/tests/Wait-ForIdentityPoolUnlock.Tests.ps1 @@ -46,12 +46,11 @@ Describe 'Wait-ForIdentityPoolUnlock' { # A bit janky but it works for now $Buffer = .5 $global:CallCount = 0 - $Timeout = 2 $Params = @{ AdminAddress = New-MockAdminAddress IdentityPool = Get-AcctIdentityPoolMock -Lock $true - Timeout = $Timeout + Timeout = 2 } $StartTime = Get-Date @@ -60,14 +59,14 @@ Describe 'Wait-ForIdentityPoolUnlock' { $ExecutionTime = $EndTime - $StartTime $ExecutionTime.TotalSeconds | Should -BeGreaterThan 1 - $ExecutionTime.TotalSeconds | Should -BeLessOrEqual ($Timeout + $Buffer) + $ExecutionTime.TotalSeconds | Should -BeLessOrEqual ($Params.Timeout + $Buffer) } } Context 'When the identity pool remains locked beyond the timeout period' { It 'Should exit after the specified timeout period' { Mock Get-AcctIdentityPool { return Get-AcctIdentityPoolMock -Lock $true } - + $Buffer = 2 $Params = @{ AdminAddress = New-MockAdminAddress IdentityPool = Get-AcctIdentityPoolMock -Lock $true @@ -79,7 +78,7 @@ Describe 'Wait-ForIdentityPoolUnlock' { } $ExecutionTime.TotalSeconds | Should -BeGreaterOrEqual 2 - $ExecutionTime.TotalSeconds | Should -BeLessThan 3 + $ExecutionTime.TotalSeconds | Should -BeLessThan ($Params.Timeout + $Buffer) # 2 second buffer to account for execution overhead Should -Invoke Get-AcctIdentityPool -Times 2 -Scope It } From e78ecc0c5eb5771685dd7175084eee6f135ffad8 Mon Sep 17 00:00:00 2001 From: tonysathre Date: Wed, 4 Dec 2024 10:11:08 -0600 Subject: [PATCH 23/24] wip --- tests/Get-CtxAutodeployConfig.Tests.ps1 | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/Get-CtxAutodeployConfig.Tests.ps1 b/tests/Get-CtxAutodeployConfig.Tests.ps1 index 50f10c0..8bac14a 100644 --- a/tests/Get-CtxAutodeployConfig.Tests.ps1 +++ b/tests/Get-CtxAutodeployConfig.Tests.ps1 @@ -4,7 +4,8 @@ param () Describe 'Get-CtxAutodeployConfig' { BeforeAll { Import-Module "${PSScriptRoot}\Pester.Helper.psm1" -Force -ErrorAction Stop 3> $null 4> $null - Import-CitrixAutodeployModule + Import-CitrixAutodeployModule -Scope Global + . "${PSScriptRoot}\..\module\CitrixAutodeploy\functions\public\Get-CtxAutodeployConfig.ps1" } BeforeEach { @@ -27,14 +28,6 @@ Describe 'Get-CtxAutodeployConfig' { '@ | Set-Content -Path $FilePath } - AfterAll { - if (Test-Path -Path $script:FilePath) { - Remove-Item -Path $script:FilePath -Force -ErrorAction SilentlyContinue - } - - Remove-CitrixAutodeployModule - } - Context 'Valid Config File' { It 'Should return expected configuration object when a valid file is provided' { $Result = Get-CtxAutodeployConfig -Path $FilePath From 008a27bb3a2215a6d2aba228b679df673c9420db Mon Sep 17 00:00:00 2001 From: tonysathre Date: Wed, 4 Dec 2024 10:20:40 -0600 Subject: [PATCH 24/24] wip --- tests/Initialize-CtxAutodeployLogger.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Initialize-CtxAutodeployLogger.Tests.ps1 b/tests/Initialize-CtxAutodeployLogger.Tests.ps1 index 5f58fc8..d624ac3 100644 --- a/tests/Initialize-CtxAutodeployLogger.Tests.ps1 +++ b/tests/Initialize-CtxAutodeployLogger.Tests.ps1 @@ -4,6 +4,7 @@ param () Describe 'Initialize-CtxAutodeployLogger' { BeforeAll { . "${PSScriptRoot}\..\module\CitrixAutodeploy\functions\public\Initialize-CtxAutodeployLogger.ps1" + Import-CitrixAutodeployModule -Scope Global } AfterAll {