Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get-DbaConnectedInstance / Disconnect-DbaInstance #7650

Merged
merged 16 commits into from
Jul 30, 2021
5 changes: 4 additions & 1 deletion dbatools.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -1084,4 +1084,7 @@ $onRemoveScript = {
Get-Runspace | Where-Object Name -like dbatools* | ForEach-Object -Process { $_.Dispose() }
}
$ExecutionContext.SessionState.Module.OnRemove += $onRemoveScript
Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $onRemoveScript
Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $onRemoveScript

# Create collection for servers
$script:connectionhash = @{ }
11 changes: 10 additions & 1 deletion functions/Connect-DbaInstance.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ function Connect-DbaInstance {
PS C:\> $server = Connect-DbaInstance -SqlInstance srv1 -DedicatedAdminConnection
PS C:\> $dbaProcess = Get-DbaProcess -SqlInstance $server -ExcludeSystemSpids
PS C:\> $killedProcess = $dbaProcess | Out-GridView -OutputMode Multiple | Stop-DbaProcess
PS C:\> $server.ConnectionContext.Disconnect()
PS C:\> $server | Disconnect-DbaInstance

Creates a dedicated admin connection (DAC) to the default instance on server srv1.
Receives all non-system processes from the instance using the DAC.
Expand Down Expand Up @@ -963,6 +963,7 @@ function Connect-DbaInstance {
}

if ($SqlConnectionOnly) {
$null = Add-ConnectionHashValue -Key $server.ConnectionContext.ConnectionString -Value $server.ConnectionContext.SqlConnectionObject
Write-Message -Level Debug -Message "We return only SqlConnection in server.ConnectionContext.SqlConnectionObject"
$server.ConnectionContext.SqlConnectionObject
continue
Expand Down Expand Up @@ -1066,6 +1067,7 @@ function Connect-DbaInstance {
}
}

$null = Add-ConnectionHashValue -Key $server.ConnectionContext.ConnectionString -Value $server
Write-Message -Level Debug -Message "We are finished with this instance"
continue
}
Expand Down Expand Up @@ -1236,6 +1238,7 @@ function Connect-DbaInstance {
if ($currentdb) {
Add-Member -InputObject $server -NotePropertyName Databases -NotePropertyValue @{ $currentdb.Name = $currentdb } -Force
}#>
$null = Add-ConnectionHashValue -Key $server.ConnectionContext.ConnectionString -Value $server
$server
continue
} catch {
Expand All @@ -1251,6 +1254,7 @@ function Connect-DbaInstance {
$instance.InputObject.ConnectionContext.Connect()
}
if ($SqlConnectionOnly) {
$null = Add-ConnectionHashValue -Key $instance.InputObject.ConnectionContext.ConnectionString -Value $instance.InputObject.ConnectionContext.SqlConnectionObject
$instance.InputObject.ConnectionContext.SqlConnectionObject
continue
} else {
Expand Down Expand Up @@ -1292,6 +1296,8 @@ function Connect-DbaInstance {
if ($AzureUnsupported -and $server.DatabaseEngineType -eq "SqlAzureDatabase") {
Stop-Function -Target $instance -Message "Azure SQL Database not supported" -Continue
}
$null = Add-ConnectionHashValue -Key $server.ConnectionContext.ConnectionString -Value $server.ConnectionContext.SqlConnectionObject

Write-Message -Level Debug -Message "We return server.ConnectionContext.SqlConnectionObject"
$server.ConnectionContext.SqlConnectionObject
continue
Expand Down Expand Up @@ -1321,6 +1327,7 @@ function Connect-DbaInstance {
if ([Sqlcollaborative.Dbatools.TabExpansion.TabExpansionHost]::Cache["sqlinstance"] -notcontains $instance.FullSmoName.ToLowerInvariant()) {
[Sqlcollaborative.Dbatools.TabExpansion.TabExpansionHost]::Cache["sqlinstance"] += $instance.FullSmoName.ToLowerInvariant()
}
$null = Add-ConnectionHashValue -Key $server.ConnectionContext.ConnectionString -Value $server
Write-Message -Level Debug -Message "We return server with server.Name = '$($server.Name)'"
$server
continue
Expand Down Expand Up @@ -1544,6 +1551,7 @@ function Connect-DbaInstance {
}

if ($SqlConnectionOnly) {
$null = Add-ConnectionHashValue -Key $server.ConnectionContext.ConnectionString -Value $server.ConnectionContext.SqlConnectionObject
Write-Message -Level Debug -Message "SqlConnectionOnly, so returning server.ConnectionContext.SqlConnectionObject"
$server.ConnectionContext.SqlConnectionObject
continue
Expand Down Expand Up @@ -1588,6 +1596,7 @@ function Connect-DbaInstance {
Stop-Function -Target $instance -Message "Azure SQL Database not supported" -Continue
}

$null = Add-ConnectionHashValue -Key $server.ConnectionContext.ConnectionString -Value $server
Write-Message -Level Debug -Message "We return server with server.Name = '$($server.Name)'"
$server
continue
Expand Down
111 changes: 111 additions & 0 deletions functions/Disconnect-DbaInstance.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
function Disconnect-DbaInstance {
<#
.SYNOPSIS
Disconnects or closes a connection to a SQL Server instance

.DESCRIPTION
Disconnects or closes a connection to a SQL Server instance

To clear all of your connection pools, use Clear-DbaConnectionPool

.PARAMETER InputObject
The server object to disconnect from, usually piped in from Get-DbaConnectedInstance

.PARAMETER WhatIf
Shows what would happen if the command were to run. No actions are actually performed.

.PARAMETER Confirm
Prompts you for confirmation before executing any changing operations within the command.

.PARAMETER EnableException
By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting.
Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch.

.NOTES
Tags: Connection
Author: Chrissy LeMaire (@cl), netnerds.net

Website: https://dbatools.io
Copyright: (c) 2021 by dbatools, licensed under MIT
License: MIT https://opensource.org/licenses/MIT

.LINK
https://dbatools.io/Disconnect-DbaInstance

.EXAMPLE
PS C:\> Get-DbaConnectedInstance | Disconnect-DbaInstance

Disconnects all connected instances

.EXAMPLE
PS C:\> Get-DbaConnectedInstance | Out-GridView -Passthru | Disconnect-DbaInstance

Disconnects selected SQL Server instances

.EXAMPLE
PS C:\> $server = Connect-DbaInstance -SqlInstance sql01
PS C:\> $server | Disconnect-DbaInstance

Disconnects the $server connection
#>
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Low")]
param (
[parameter(ValueFromPipeline)]
[psobject[]]$InputObject,
[switch]$EnableException
)
process {
# to avoid enumeration problems when piped
$objects += $InputObject
}
end {
foreach ($object in $objects) {
if ($object.ConnectionObject) {
$servers = $object.ConnectionObject
} else {
$servers = $object
}
foreach ($server in $servers) {
try {
if ($server.ConnectionContext) {
if ($Pscmdlet.ShouldProcess($server.Name, "Disconnecting SQL Connection")) {
$null = $server.ConnectionContext.Disconnect()
if ($script:connectionhash[$server.ConnectionContext.ConnectionString]) {
Write-Message -Level Verbose -Message "removing from connection hash"
$null = $script:connectionhash.Remove($server.ConnectionContext.ConnectionString)
}
[pscustomobject]@{
SqlInstance = $server.Name
ConnectionString = (Hide-ConnectionString -ConnectionString $server.ConnectionContext.ConnectionString)
ConnectionType = $server.GetType().FullName
State = "Disconnected"
} | Select-DefaultView -Property SqlInstance, ConnectionType, State
}
}
if ($server.GetType().Name -eq "SqlConnection") {
if ($Pscmdlet.ShouldProcess($server.DataSource, "Closing SQL Connection")) {
if ($server.State -eq "Open") {
$null = $server.Close()
}

if ($script:connectionhash[$server.ConnectionString]) {
Write-Message -Level Verbose -Message "removing from connection hash"
$null = $script:connectionhash.Remove($server.ConnectionString)
}

[pscustomobject]@{
SqlInstance = $server.DataSource
ConnectionString = (Hide-ConnectionString -ConnectionString $server.ConnectionString)
ConnectionType = $server.GetType().FullName
State = $server.State
} | Select-DefaultView -Property SqlInstance, ConnectionType, State
}
}
} catch {
Stop-Function -Message "Failed to disconnect $object" -ErrorRecord $PSItem -Continue
}
}
}
}
}
55 changes: 55 additions & 0 deletions functions/Get-DbaConnectedInstance.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
function Get-DbaConnectedInstance {
<#
.SYNOPSIS
Get a list of all connected instances

.DESCRIPTION
Get a list of all connected instances

.NOTES
Tags: Connection
Author: Chrissy LeMaire (@cl), netnerds.net

Website: https://dbatools.io
Copyright: (c) 2021 by dbatools, licensed under MIT
License: MIT https://opensource.org/licenses/MIT

.LINK
https://dbatools.io/Get-DbaConnectedInstance

.EXAMPLE
PS C:\> Get-DbaConnectedInstance

Gets all connected SQL Server instances

.EXAMPLE
PS C:\> Get-DbaConnectedInstance | Select *

Gets all connected SQL Server instances and shows the associated connectionstrings as well

#>
[CmdletBinding()]
param ()
process {
foreach ($key in $script:connectionhash.Keys) {
if ($script:connectionhash[$key].DataSource) {
$instance = $script:connectionhash[$key] | Select-Object -First 1 -ExpandProperty DataSource
} else {
$instance = $script:connectionhash[$key] | Select-Object -First 1 -ExpandProperty Name
}
$value = $script:connectionhash[$key] | Select-Object -First 1
if ($value.ConnectionContext.NonPooledConnection -or $value.NonPooledConnection) {
$pooling = $false
} else {
$pooling = $true
}
[pscustomobject]@{
SqlInstance = $instance
ConnectionObject = $script:connectionhash[$key]
ConnectionType = $value.GetType().FullName
Pooled = $pooling
ConnectionString = (Hide-ConnectionString -ConnectionString $key)
} | Select-DefaultView -Property SqlInstance, ConnectionType, ConnectionObject, Pooled
}
}
}
18 changes: 18 additions & 0 deletions internal/functions/Add-ConnectionHashValue.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
function Add-ConnectionHashValue {
param(
[Parameter(Mandatory)]
$Key,
[Parameter(Mandatory)]
$Value
)
Write-Message -Level Debug -Message "Adding to connection hash"

if ($Value.ConnectionContext.NonPooledConnection -or $Value.NonPooledConnection) {
if (-not $script:connectionhash[$Key]) {
$script:connectionhash[$Key] = @( )
}
$script:connectionhash[$Key] += $Value
} else {
$script:connectionhash[$Key] = $Value
}
}
27 changes: 27 additions & 0 deletions tests/Disconnect-DbaInstance.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
$CommandName = $MyInvocation.MyCommand.Name.Replace(".Tests.ps1", "")
Write-Host -Object "Running $PSCommandpath" -ForegroundColor Cyan
. "$PSScriptRoot\constants.ps1"

Describe "$CommandName Unit Tests" -Tag "UnitTests" {
Context "Validate parameters" {
[array]$params = ([Management.Automation.CommandMetaData]$ExecutionContext.SessionState.InvokeCommand.GetCommand($CommandName, 'Function')).Parameters.Keys
[object[]]$knownParameters = 'InputObject', 'EnableException'

It "Should only contain our specific parameters" {
Compare-Object -ReferenceObject $knownParameters -DifferenceObject $params | Should -BeNullOrEmpty
}
}
}

Describe "$commandname Integration Tests" -Tag "IntegrationTests" {
BeforeAll {
$null = Get-DbaDatabase -SqlInstance $script:instance1
$null = Connect-DbaInstance -SqlInstance $env:COMPUTERNAME -SqlConnectionOnly
}
Context "disconnets a server" {
It "disconnects and returns some results" {
$results = Get-DbaConnectedInstance | Disconnect-DbaInstance
$results.Count | Should -BeGreaterThan 1
}
}
}
24 changes: 24 additions & 0 deletions tests/Get-DbaConnectedInstance.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
$CommandName = $MyInvocation.MyCommand.Name.Replace(".Tests.ps1", "")
Write-Host -Object "Running $PSCommandpath" -ForegroundColor Cyan
. "$PSScriptRoot\constants.ps1"

Describe "$CommandName Unit Tests" -Tag "UnitTests" {
Context "Validate parameters" {
# fake tests, no parameters to validate
It "Should only contain our specific parameters" {
$null | Should -BeNullOrEmpty
}
}
}

Describe "$commandname Integration Tests" -Tag "IntegrationTests" {
BeforeAll {
$null = Get-DbaDatabase -SqlInstance $script:instance1
}
Context "gets connected objects" {
It "returns some results" {
$results = Get-DbaConnectedInstance
$results.Count | Should -BeGreaterThan 0
}
}
}