diff --git a/README.md b/README.md index 6f7f96b..63c96de 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,14 @@ +Note +============ +See forked project at https://github.com/DexterPOSH/PSRemotely. + Synopsis ============ Executes a script block against a remote runspace. Remotely can be used with Pester for executing script blocks on a remote system. Description ====================== -The contents on the Remotely block are executed on a remote runspace. The connection information of the runspace is supplied in a CSV file of the format: - -``` -ComputerName,Username,Password -ComputerName1,Username1,Password1 -ComputerName2,Username2,Password2 -``` - -The filename must be `machineConfig.csv`. - -The CSV file is expected to be placed next to this file. - -If the CSV file is not found or username is not specified, the machine name is ignored and runspace to localhost -is created for executing the script block. - -If the password has a ',' then it needs to be escaped by using quotes like: - -``` -ComputerName,Username,Password -ComputerName1,Username1,Password1 -ComputerName2,Username2,"Some,other,password" -``` +The contents on the Remotely block are executed on a remote runspace. The connection information of the runspace is supplied using the -Nodes parameter or as the argument to the first positional parameter. By default, this assumes the local credentials have access to the remote session configuration on the target nodes. To get access to the streams, use GetVerbose, GetDebugOutput, GetError, GetProgressOutput, GetWarning on the resultant object. @@ -35,19 +18,28 @@ Example Usage in Pester: ```powershell +$my_creds = Get-Credential +$node1_hash = @{} +$node1_hash.add("authentication","credssp") +$node1_hash.add("credential",$my_creds) + +# All k,v pairs in $node1_hash are passed to New-PSSession for the specific node. +$remotely_nodes = @{} +$remotely_nodes.add("localhost",$node1_hash) + Describe "Add-Numbers" { - It "adds positive numbers" { - Remotely { 2 + 3 } | Should Be 5 + It "adds positive numbers on a remote system" { + Remotely -Nodes $remotely_nodes -ScriptBlock { 2 + 3 } | Should Be 5 } It "gets verbose message" { - $sum = Remotely { Write-Verbose -Verbose "Test Message" } + $sum = Remotely -Nodes $remotely_nodes -ScriptBlock { Write-Verbose -Verbose "Test Message" } $sum.GetVerbose() | Should Be "Test Message" } - It "can pass parameters to remote block" { + It "can pass parameters to remote block with different credentials" { $num = 10 - $process = Remotely { param($number) $number + 1 } -ArgumentList $num + $process = Remotely -Nodes $remotely_nodes -ScriptBlock { Param($number) $number + 1 } -ArgumentList $num $process | Should Be 11 } } @@ -65,5 +57,3 @@ Pester-based tests are located in ```/Remotely.Tests.ps1``` * Ensure Pester is installed on the machine * Run tests: .\Remotely.Tests.ps1 - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/Remotely.Tests.ps1 b/Remotely.Tests.ps1 index d464e3e..80a82a0 100644 --- a/Remotely.Tests.ps1 +++ b/Remotely.Tests.ps1 @@ -1,106 +1,45 @@ -# Function to update the table that defines the machineconfig.csv -# based on test environment variables -Function Update-ConfigContentTable -{ - param( - [parameter(Mandatory=$true)] - [HashTable]$configContentTable - - ) +$VerbosePreference = "continue" - if($global:AppveyorRemotelyUserName -or $global:AppveyorRemotelyPassword) - { - $computername = $configContentTable.ComputerName - if($computername -ieq 'localhost') - { - $computername = '127.0.0.1' - } - elseif ( $computername -ieq '.') - { - $computername = '::1' - } - - $configContentTable.ComputerName = $computername - } - - if($global:AppveyorRemotelyUserName) - { - $configContentTable['Username']=$global:AppveyorRemotelyUserName - } - - if($global:AppveyorRemotelyPassword) - { - $configContentTable['Password']=$global:AppveyorRemotelyPassword - } - - return $configContentTable +$here = Split-Path -Parent $MyInvocation.MyCommand.Path +If((Get-Module | Select-Object Name -ExpandProperty Name) -contains "Remotely") { + Remove-Module "Remotely" } +$mod_path = $here.trimend("\") + "\Remotely.psm1" +Import-Module $mod_path Describe "Add-Numbers" { - BeforeAll { - $configFile = (join-path $PSScriptRoot 'machineConfig.csv') - $configContentTable = @{ComputerName = "localhost" } - Update-ConfigContentTable -configContentTable $configContentTable - $configContent = @([pscustomobject] $configContentTable) | ConvertTo-Csv -NoTypeInformation - $configContent | Out-File -FilePath $configFile -Force - } - $testcases = @( @{NoSessionValue = $true}, @{NoSessionValue = $false}) - It "can execute script with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - - $expectedRemotelyTarget = 'localhost' - if($configContentTable['Computername']) - { - $expectedRemotelyTarget = $configContentTable['Computername'] - } - - $output = Remotely { 1 + 1 } -NoSession:$NoSessionValue - $output | Should Be 2 - - if($NoSessionValue -eq $true) - { - $output.RemotelyTarget | Should BeNullOrEmpty - } - else - { - $output.RemotelyTarget | Should Be $expectedRemotelyTarget - } - } + It "can execute script" { + Remotely { 1 + 1 } | Should Be 2 + } - It "can return an array with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - $returnObjs = Remotely { 1..10 } -NoSession:$NoSessionValue + It "can return an array" { + $returnObjs = Remotely { 1..10 } $returnObjs.count | Should Be 10 } - It "can return a hashtable with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - $returnObjs = Remotely { @{Value = 2} } -NoSession:$NoSessionValue + It "can return a hashtable" { + $returnObjs = Remotely { @{Value = 2} } $returnObjs["Value"] | Should Be 2 } - It "can get verbose message with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - $output = Remotely { Write-Verbose -Verbose "Verbose Message" } -NoSession:$NoSessionValue + It "can get verbose message" { + $output = Remotely { Write-Verbose -Verbose "Verbose Message" } $output.GetVerbose() | Should Be "Verbose Message" } - It "can get error message with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - $output = Remotely { Write-Error "Error Message" } -NoSession:$NoSessionValue + It "can get error message" { + $output = Remotely { Write-Error "Error Message" } $output.GetError() | Should Be "Error Message" } - It "can get warning message with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - $output = Remotely { Write-Warning "Warning Message" } -NoSession:$NoSessionValue + It "can get warning message" { + $output = Remotely { Write-Warning "Warning Message" } $output.GetWarning() | Should Be "Warning Message" } - It "can get debug message with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - $output = Remotely -NoSession:$NoSessionValue { + It "can get debug message" { + $output = Remotely { $originalPreference = $DebugPreference $DebugPreference = "continue" Write-Debug "Debug Message" @@ -109,49 +48,39 @@ Describe "Add-Numbers" { $output.GetDebugOutput() | Should Be "Debug Message" } - It "can get progress message with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - $output = Remotely -NoSession:$NoSessionValue { Write-Progress -Activity "Test" -Status "Testing" -Id 1 -PercentComplete 100 -SecondsRemaining 0 } + It "can get progress message" { + $output = Remotely { Write-Progress -Activity "Test" -Status "Testing" -Id 1 -PercentComplete 100 -SecondsRemaining 0 } $output.GetProgressOutput().Activity | Should Be "Test" $output.GetProgressOutput().StatusDescription | Should Be "Testing" $output.GetProgressOutput().ActivityId | Should Be 1 } - It 'can return $false as a value with NoSessionValue : ' -TestCases $testcases { - param($NoSessionValue) - $output = Remotely { $false } -NoSession:$NoSessionValue + It 'can return $false as a value' { + $output = Remotely { $false } $output | Should Be $false } - It 'can return throw messages with NoSessionValue : ' -TestCases $testcases { - param($NoSessionValue) - $output = Remotely { throw 'bad' } -NoSession:$NoSessionValue + It 'can return throw messages' { + $output = Remotely { throw 'bad' } $output.GetError().FullyQualifiedErrorId | Should Be 'bad' - } - - It "can pass parameters to remote block with NoSessionValue : " -TestCases $testcases { - param($NoSessionValue) - $num = 10 - $process = Remotely { param($number) $number + 1 } -ArgumentList $num -NoSession:$NoSessionValue - $process | Should Be 11 } - - It "can get remote sessions" { + + It "can get remote sessions" { Remotely { 1 + 1 } | Should Be 2 $remoteSessions = Get-RemoteSession - $remoteSessions | % { $remoteSessions.Name -match "Remotely" | Should Be $true} + $remoteSessions | ForEach-Object { $remoteSessions.Name -match "Remotely" | Should Be $true} + } + + It "can pass parameters to remote block" { + $num = 10 + $process = Remotely { param($number) $number + 1 } -ArgumentList $num + $process | Should Be 11 } It "can get target of the remotely block" { - $expectedRemotelyTarget = 'localhost' - if($configContentTable['Computername']) - { - $expectedRemotelyTarget = $configContentTable['Computername'] - } - $output = Remotely { 1 } - $output.RemotelyTarget | Should Be $expectedRemotelyTarget + $output.RemotelyTarget | Should Be "localhost" } It "can handle delete sessions" { @@ -166,91 +95,27 @@ Describe "Add-Numbers" { } It "can execute against more than 1 remote machines" { - # Testing with no configuration name for compatibility - $configFile = (join-path $PSScriptRoot 'machineConfig.csv') - $configContentTable = @{ComputerName = "localhost" } - Update-ConfigContentTable -configContentTable $configContentTable - $configContentTable2 = @{ComputerName = "." } - Update-ConfigContentTable -configContentTable $configContentTable2 - $configContent = @([pscustomobject] $configContentTable, [pscustomobject] $configContentTable2) | ConvertTo-Csv -NoTypeInformation - $configContent | Out-File -FilePath $configFile -Force + $nodes = @{} + $nodes.add('localhost',$null) + $nodes.add([string]$env:computername,$null) - try - { - $results = Remotely { 1 + 1 } + try { + $results = Remotely { 1 + 1 } -Nodes $nodes $results.Count | Should Be 2 - foreach($result in $results) - { + foreach($result in $results) { $result | Should Be 2 } } - catch - { + catch{ $_.FullyQualifiedErrorId | Should Be $null } - finally - { - Remove-Item $configFile -ErrorAction SilentlyContinue -Force - } - } -} - -Describe "ConfigurationName" { - BeforeAll { - $configFile = (join-path $PSScriptRoot 'machineConfig.csv') - } - AfterAll { - Remove-Item $configFile -ErrorAction SilentlyContinue -Force - } - Context "Default configuration name" { - $configContentTable = @{ - ComputerName = "localhost" - Username = $null - Password = $null - ConfigurationName = "Microsoft.PowerShell" - } - Update-ConfigContentTable -configContentTable $configContentTable - $configContent = @([pscustomobject] $configContentTable) | ConvertTo-Csv -NoTypeInformation - $configContent | Out-File -FilePath $configFile -Force - - it "Should connect when a configurationName is specified" { - - $results = Remotely { 1 + 1 } - - $results | Should Be 2 - } - } - - Context "Invalid configuration name" { - - Write-Verbose "Clearing remote session..." -Verbose - Clear-RemoteSession - $configContentTable = @{ - ComputerName = "localhost" - Username = $null - Password = $null - ConfigurationName = "Microsoft.PowerShell2" + finally { } - Update-ConfigContentTable -configContentTable $configContentTable - $configContent = @([pscustomobject] $configContentTable) | ConvertTo-Csv -NoTypeInformation - $configContent | Out-File -FilePath $configFile -Force - - $expectedRemotelyTarget = 'localhost' - if($configContentTable['Computername']) - { - $expectedRemotelyTarget = $configContentTable['Computername'] - } - - - it "Should not connect to an invalid ConfigurationName" { - {$results = Remotely { 1 + 1 }} | should throw "Connecting to remote server $expectedRemotelyTarget failed with the following error message : The WS-Management service cannot process the request. Cannot find the Microsoft.PowerShell2 session configuration in the WSMan: drive on the $expectedRemotelyTarget computer. For more information, see the about_Remote_Troubleshooting Help topic." - } } -} -Describe "Clear-RemoteSession" { + It "can clear remote sessions" { Clear-RemoteSession Get-PSSession -Name Remotely* | Should Be $null } -} \ No newline at end of file +} \ No newline at end of file diff --git a/Remotely.psd1 b/Remotely.psd1 index c5b27b5..87794bb 100644 --- a/Remotely.psd1 +++ b/Remotely.psd1 @@ -4,7 +4,7 @@ ModuleToProcess = 'Remotely.psm1' # Version number of this module. -ModuleVersion = '1.0.0' +ModuleVersion = '1.0.1' # ID used to uniquely identify this module GUID = 'a20c9efd-077e-4c53-a500-f74dec071799' diff --git a/Remotely.psm1 b/Remotely.psm1 index e38de50..37d218f 100644 --- a/Remotely.psm1 +++ b/Remotely.psm1 @@ -1,193 +1,95 @@ -function Remotely { -<# -.SYNOPSIS -Executes a script block against a remote runspace. Remotely can be used with Pester for executing script blocks on remote system. +function Remotely { + param ( + [Parameter(Mandatory = $true, Position = 1)] + [ScriptBlock] $ScriptBlock, -.DESCRIPTION -The contents on the Remotely block are executed on a remote runspace. The connection information of the runspace is supplied in a CSV file of the format: + [Parameter(Mandatory = $false, Position = 2)] + $ArgumentList, -ComputerName,Username,Password -machinename,user,password + [Parameter(Mandatory = $false, Position = 3)] + [HashTable] $Nodes = @{'localhost'= $null}, -The file name must be machineConfig.csv - -The CSV file is expected to be placed next to this file. - -If the CSV file is not found or username is not specified, the machine name is ignored and runspace to localhost -is created for executing the script block. - -If the ConfigurationName is not in the CSV file, Remotely will default to Microsoft.PowerShell. - -If the password has a ',' then it needs to be escaped by using quotes like: -ComputerName,Username,Password,ConfigurationName -machinename,user,"Some,password",Microsoft.Powershell - -To get access to the streams GetVerbose, GetDebugOutput, GetError, GetProgressOutput, GetWarning can be used on the resultant object. - -.PARAMETER Test -The script block that should throw an exception if the expectation of the test is not met. - -.PARAMETER ArgumentList -Arguments that will be passed to the script block. - -.PARAMETER NoSession -The switch opts to use the script block without using any powershell sessions, but local runspace. - -.EXAMPLE - -Describe "Add-Numbers" { - It "adds positive numbers" { - Remotely { 2 + 3 } | Should Be 5 - } + [Parameter(Mandatory = $false, Position = 4)] + [Int32] $Timeout = 300 + ) - It "gets verbose message" { - $sum = Remotely { Write-Verbose -Verbose "Test Message" } - $sum.GetVerbose() | Should Be "Test Message" + if ($null -eq $script:sessionsHashTable) { + $script:sessionsHashTable = @{} } - - It "can pass parameters to remote block" { - $num = 10 - $process = Remotely { param($number) $number + 1 } -ArgumentList $num - $process | Should Be 11 + + Write-Verbose ("Creating sessions for nodes.") + CreateSessions -Nodes $Nodes + + $sessions = @() + foreach($sessionInfo in $script:sessionsHashTable.Values.GetEnumerator()) { + Write-Verbose ("Reconnecting to session: $sessionInfo") + CheckAndReConnect -sessionInfo $sessionInfo + $sessions += $sessionInfo.Session } - It "adds positive numbers with NoSession" { - Remotely { 2 + 3 } -NoSession | Should Be 5 + if($sessions.Count -le 0) { + Throw "No sessions are available" + } else { + $num_sessions = $sessions.count + Write-Verbose ("Created $num_sessions sessions.") } -} - -.LINK -https://github.com/PowerShell/Remotely -https://github.com/pester/Pester -#> - -param( - [Parameter(Mandatory = $true, Position = 0)] - [ScriptBlock] $test = {}, - - [Parameter(Mandatory = $false, Position = 1)] - $ArgumentList, - - [Parameter(Mandatory = $false, Position =2)] - [switch]$NoSession - ) + + Write-Verbose ("Invoking job on nodes.") + $testjob = Invoke-Command -Session $sessions -ScriptBlock $ScriptBlock -AsJob -ArgumentList $ArgumentList | Wait-Job -Timeout $Timeout $results = @() - if(-not $NoSession.IsPresent) - { - if($script:sessionsHashTable -eq $null) - { - $script:sessionsHashTable = @{} - } - - $machineConfigFile = Join-Path $PSScriptRoot "machineConfig.CSV" - - CreateSessions -machineConfigFile $machineConfigFile - - $sessions = @() + foreach($childJob in $testjob.ChildJobs) { - foreach($sessionInfo in $script:sessionsHashTable.Values.GetEnumerator()) - { - CheckAndReConnect -sessionInfo $sessionInfo - $sessions += $sessionInfo.Session - } - - if($sessions.Count -le 0) - { - throw "No sessions are available" + Write-Verbose ("Working on Job: $childJob.") + if($childJob.Output.Count -eq 0) { + [object] $outputStream = New-Object psobject } - - $testjob = Invoke-Command -Session $sessions -ScriptBlock $test -AsJob -ArgumentList $ArgumentList | Wait-Job - - foreach($childJob in $testjob.ChildJobs) - { - $outputStream = ConstructOutputStream -resultObj $childJob.Output -streamSource $childJob - - if($childJob.State -eq 'Failed') - { - $childJob | Receive-Job -ErrorAction SilentlyContinue -ErrorVariable jobError - $outputStream.__Streams.Error = $jobError - } - - $results += ,$outputStream + else { + [object] $outputStream = $childJob.Output | ForEach-Object { $_ } } - $testjob | Remove-Job -Force - } - else - { - $ps = [Powershell]::Create() - $ps.runspace = [runspacefactory]::CreateRunspace() - $ps.runspace.open() - - try - { - $res = $ps.AddScript($test.ToString()).AddArgument($ArgumentList).Invoke() - } - catch - { - $executionError = $_.Exception.InnerException.ErrorRecord + $errorStream = CopyStreams $childJob.Error + $verboseStream = CopyStreams $childJob.Verbose + $debugStream = CopyStreams $childJob.Debug + $warningStream = CopyStreams $childJob.Warning + $progressStream = CopyStreams $childJob.Progress + + $allStreams = @{ + Error = $errorStream + Verbose = $verboseStream + DebugOutput = $debugStream + Warning = $warningStream + ProgressOutput = $progressStream } - - $outputStream = ConstructOutputStream -resultObj $res -streamSource $ps.Streams - - if(($ps.Streams.Error.Count -eq 0) -and ($ps.HadErrors)) - { - $outputStream.__streams.Error = $executionError; + + $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType NoteProperty -Name __Streams -Value $allStreams + $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetError -Value { return $this.__Streams.Error } + $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetVerbose -Value { return $this.__Streams.Verbose } + $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetDebugOutput -Value { return $this.__Streams.DebugOutput } + $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetProgressOutput -Value { return $this.__Streams.ProgressOutput } + $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetWarning -Value { return $this.__Streams.Warning } + $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType NoteProperty -Name RemotelyTarget -Value $childJob.Location + + if($childJob.State -eq 'Failed') { + $childJob | Receive-Job -ErrorAction SilentlyContinue -ErrorVariable jobError + $outputStream.__Streams.Error = $jobError } $results += ,$outputStream - - $ps.Dispose() } + $testjob | Remove-Job -Force $results } -function ConstructOutputStream -{ - param( - $resultObj, - $streamSource - ) - - if($resultObj.Count -eq 0) - { - [object] $outputStream = New-Object psobject - } - else - { - [object] $outputStream = $resultObj | % { $_ } - } - - $errorStream = CopyStreams $streamSource.Error - $verboseStream = CopyStreams $streamSource.Verbose - $debugStream = CopyStreams $streamSource.Debug - $warningStream = CopyStreams $streamSource.Warning - $progressStream = CopyStreams $streamSource.Progress - - $allStreams = @{ - Error = $errorStream - Verbose = $verboseStream - DebugOutput = $debugStream - Warning = $warningStream - ProgressOutput = $progressStream - } - - $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType NoteProperty -Name __Streams -Value $allStreams -Force - $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetError -Value { return $this.__Streams.Error } -Force - $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetVerbose -Value { return $this.__Streams.Verbose } -Force - $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetDebugOutput -Value { return $this.__Streams.DebugOutput } -Force - $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetProgressOutput -Value { return $this.__Streams.ProgressOutput } -Force - $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType ScriptMethod -Name GetWarning -Value { return $this.__Streams.Warning } -Force - $outputStream = Add-Member -InputObject $outputStream -PassThru -MemberType NoteProperty -Name RemotelyTarget -Value $streamSource.Location -Force - return $outputStream -} - function CopyStreams { - param( [Parameter(Position=0, Mandatory=$true)] $inputStream) + param + ( + [Parameter(Position=0, Mandatory=$true)] + $inputStream + ) $outStream = New-Object 'System.Management.Automation.PSDataCollection[PSObject]' @@ -201,96 +103,125 @@ function CopyStreams ,$outStream } -function CreateSessions -{ - param([string] $machineConfigFile) - - if(Test-Path $machineConfigFile) - { - Write-Verbose "Found machine configuration file: $machineConfigFile" - - $machineInfo = Import-Csv $machineConfigFile +function CreateSessions { + param ( + [Parameter( + Mandatory = $true, + Position = 0 + )] + [HashTable] $Nodes = @{'localhost'=$null} + ) - foreach($item in $machineInfo) - { - $configurationName = 'Microsoft.PowerShell' - if($item.ConfigurationName) - { - $configurationName = $item.ConfigurationName + # Note: case sensitive. Keep keys lower case. + $default_node_options = @{} + $default_node_options.Add("sessionoptions",$null) + $default_node_options.Add("credential",$null) + $default_node_options.Add("authentication",$null) + + $Nodes.keys | ForEach-Object { + $node_name = $_ + + Write-Verbose ("Working on node name $node_name .") + # Merge given options with default options. + $node_options = @{} + $node_val = $nodes[$node_name] + If($null -eq $node_val) { + } Else { + # TODO Assert $node_options -is [HashTable] + $default_node_options.keys | ForEach-Object { + $cur_key = $null + $cur_key = $_ + $node_option_val = $null + If($node_val.keys -contains $cur_key.ToLower()) { + $node_option_val = $node_val[$cur_key] + } Else { + $node_option_val = $default_node_options[$cur_key] + } + $node_options.add($cur_key,$node_option_val) } + } + Write-Verbose ("Final node options: " + ($node_options | out-string)) - if([String]::IsNullOrEmpty($item.UserName)) - { - Write-Verbose "No username specified. Creating session to localhost." - CreateLocalSession $item.ComputerName -configurationName $configurationName + If(-not $script:sessionsHashTable.ContainsKey($node_name)) { + + $create_session_info_params = @{} + $new_ps_session_params = @{} + $new_ps_session_params.add("ComputerName",$node_name) + $new_ps_session_params.add("Name",("Remotely-" + $node_name)) + + If ($node_options.credential) { + $create_session_info_params.add("Credential",$node.credential) + $new_ps_session_params.add("Credential",$node.credential) } - else - { - $password = ConvertTo-SecureString -String $item.Password -AsPlainText -Force - $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $item.Username,$password - - if(-not $script:sessionsHashTable.ContainsKey($item.ComputerName)) - { - $sessionName = "Remotely" + (Get-Random).ToString() - - Write-Verbose "Creating new session, computer: $($item.ComputerName); ConfigurationName: $($ConfigurationName) " - $sessionInfo = CreateSessionInfo -Session (New-PSSession -ComputerName $item.ComputerName -Credential $cred -Name $sessionName -configurationname $configurationName -ErrorAction Stop) -Credential $cred - $script:sessionsHashTable.Add($sessionInfo.session.ComputerName, $sessionInfo) - } + + If ($node_options.authentication) { + $new_ps_session_params.add("authentication",$node.authentication) } - } - } - else - { - Write-Verbose "No machine configuration file found. Creating session to localhost." - CreateLocalSession + + Write-Verbose ("Calling new-pssession with the following parameters: " + ($new_ps_session_params | out-string)) + $ps_session = $null + $ps_session = New-PSSession @new_ps_session_params -Verbose + $create_session_info_params.add("Session", $ps_session) + + Write-Verbose ("Calling CreateSessionInfo.") + $sessionInfo = CreateSessionInfo @create_session_info_params + + $script:sessionsHashTable.Add($sessionInfo.session.ComputerName, $sessionInfo) + } } } -function CreateLocalSession -{ - param( - [Parameter(Position=0)] $machineName = 'localhost', - $configurationName = 'Microsoft.PowerShell' - ) - - if(-not $script:sessionsHashTable.ContainsKey($machineName)) - { - $sessionName = "Remotely" + (Get-Random).ToString() - - Write-Verbose "Creating new local session, ConfigurationName: $($ConfigurationName) " - $sessionInfo = CreateSessionInfo -Session (New-PSSession -ComputerName $machineName -Name $sessionName -ConfigurationName $configurationName -ErrorAction Stop) - - $script:sessionsHashTable.Add($machineName, $sessionInfo) - } -} +# function CreateLocalSession +# { +# param( +# [Parameter(Position=0)] $Node = 'localhost' +# ) + +# if(-not $script:sessionsHashTable.ContainsKey($Node)) +# { +# $sessionInfo = CreateSessionInfo -Session (New-PSSession -ComputerName $Node -Name $sessionName) +# $script:sessionsHashTable.Add($Node, $sessionInfo) +# } +# } function CreateSessionInfo { param( - [Parameter(Position=0, Mandatory=$true)] [ValidateNotNullOrEmpty()] [System.Management.Automation.Runspaces.PSSession] $Session, - [System.Management.Automation.PSCredential] $Credential - ) + [Parameter(Position=0, Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [System.Management.Automation.Runspaces.PSSession] $Session, - return [PSCustomObject] @{ Session = $Session; Credential = $Credential; ConfigurationName=$Session.ConfigurationName } + [Parameter(Position=1)] + [pscredential] $Credential + ) + return [PSCustomObject] @{ Session = $Session; Credential = $Credential} } function CheckAndReconnect { - param([Parameter(Position=0, Mandatory=$true)] [ValidateNotNullOrEmpty()] $sessionInfo) + param + ( + [Parameter(Position=0, Mandatory=$true)] + [ValidateNotNullOrEmpty()] $sessionInfo + ) if($sessionInfo.Session.State -ne [System.Management.Automation.Runspaces.RunspaceState]::Opened) { Write-Verbose "Unexpected session state: $sessionInfo.Session.State for machine $($sessionInfo.Session.ComputerName). Re-creating session" - - if($sessionInfo.Session.ComputerName -ne "localhost") + if($sessionInfo.Session.ComputerName -ne 'localhost') { - $sessionInfo.Session = New-PSSession -ComputerName $sessionInfo.Session.ComputerName -Credential $sessionInfo.Credential -configurationname $sessionInfo.ConfigurationName + if ($sessionInfo.Credential) + { + $sessionInfo.Session = New-PSSession -ComputerName $sessionInfo.Session.ComputerName -Credential $sessionInfo.Credential + } + else + { + $sessionInfo.Session = New-PSSession -ComputerName $sessionInfo.Session.ComputerName + } } else { - Write-Verbose "Creating local session with configurationname:$sessionInfo.ConfigurationName" - $sessionInfo.Session = New-PSSession -ComputerName 'localhost' -configurationname $sessionInfo.ConfigurationName + $sessionInfo.Session = New-PSSession -ComputerName 'localhost' } } } @@ -312,6 +243,5 @@ function Get-RemoteSession { $sessions += $sessionInfo.Session } - $sessions -} +} \ No newline at end of file diff --git a/machineConfig.csv b/machineConfig.csv deleted file mode 100644 index 214af59..0000000 --- a/machineConfig.csv +++ /dev/null @@ -1,2 +0,0 @@ -ComputerName,Username,Password,ConfigurationName -localhost \ No newline at end of file