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

Remove-DbaLinkedServer: Add option to drop logins along with the linked server #7952

Merged
merged 2 commits into from Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 10 additions & 1 deletion functions/Remove-DbaLinkedServer.ps1
Expand Up @@ -29,6 +29,9 @@ function Remove-DbaLinkedServer {
.PARAMETER Confirm
Prompts you for confirmation before executing any changing operations within the command.

.PARAMETER Force
Drops the linked server login(s) associated with the linked server and then drops the linked server.

.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.
Expand All @@ -50,6 +53,11 @@ function Remove-DbaLinkedServer {

Removes the linked server "linkedServer1" from the sql01 instance.

.EXAMPLE
PS C:\>Remove-DbaLinkedServer -SqlInstance sql01 -LinkedServer linkedServer1 -Confirm:$false -Force

Removes the linked server "linkedServer1" and the associated linked server logins from the sql01 instance.

.EXAMPLE
PS C:\>$linkedServer1 = Get-DbaLinkedServer -SqlInstance sql01 -LinkedServer linkedServer1
PS C:\>$linkedServer1 | Remove-DbaLinkedServer -Confirm:$false
Expand All @@ -68,6 +76,7 @@ function Remove-DbaLinkedServer {
[string[]]$LinkedServer,
[parameter(ValueFromPipeline)]
[object[]]$InputObject,
[switch]$Force,
[switch]$EnableException
)
begin {
Expand Down Expand Up @@ -107,7 +116,7 @@ function Remove-DbaLinkedServer {

if ($Pscmdlet.ShouldProcess($lsToDrop.Parent.Name, "Removing the linked server $($lsToDrop.Name) on $($lsToDrop.Parent.Name)")) {
try {
$lsToDrop.Drop()
$lsToDrop.Drop([boolean]$Force)
} catch {
Stop-Function -Message "Failure on $($lsToDrop.Parent.Name) to remove the linked server $($lsToDrop.Name)" -ErrorRecord $_ -Continue
}
Expand Down
84 changes: 58 additions & 26 deletions tests/Remove-DbaLinkedServer.Tests.ps1
Expand Up @@ -5,7 +5,7 @@ Write-Host -Object "Running $PSCommandPath" -ForegroundColor Cyan
Describe "$CommandName Unit Tests" -Tag 'UnitTests' {
Context "Validate parameters" {
[object[]]$params = (Get-Command $CommandName).Parameters.Keys | Where-Object { $_ -notin ('whatif', 'confirm') }
[object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'LinkedServer', 'InputObject', 'EnableException'
[object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'LinkedServer', 'InputObject', 'Force', 'EnableException'
$knownParameters += [System.Management.Automation.PSCmdlet]::CommonParameters
It "Should only contain our specific parameters" {
(@(Compare-Object -ReferenceObject ($knownParameters | Where-Object { $_ }) -DifferenceObject $params).Count ) | Should Be 0
Expand All @@ -17,56 +17,88 @@ Describe "$commandname Integration Tests" -Tags "IntegrationTests" {
BeforeAll {
$random = Get-Random
$instance2 = Connect-DbaInstance -SqlInstance $script:instance2
$instance3 = Connect-DbaInstance -SqlInstance $script:instance3

$instance2.Query("EXEC sp_addlinkedserver @server=N'LS1_$random'")
$instance2.Query("EXEC sp_addlinkedserver @server=N'LS2_$random'")
$instance2.Query("EXEC sp_addlinkedserver @server=N'LS3_$random'")
$linkedServerName1 = "dbatoolscli_LS1_$random"
$linkedServerName2 = "dbatoolscli_LS2_$random"
$linkedServerName3 = "dbatoolscli_LS3_$random"
$linkedServerName4 = "dbatoolscli_LS4_$random"

$ls1 = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer "LS1_$random"
$ls2 = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer "LS2_$random"
$ls3 = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer "LS3_$random"
$linkedServer1 = New-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName1
$linkedServer2 = New-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName2
$linkedServer3 = New-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName3
$linkedServer4 = New-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName4

$securePassword = ConvertTo-SecureString -String 's3cur3P4ssw0rd?' -AsPlainText -Force
$loginName = "dbatoolscli_test_$random"
New-DbaLogin -SqlInstance $instance2, $instance3 -Login $loginName -SecurePassword $securePassword

$newLinkedServerLogin = New-Object Microsoft.SqlServer.Management.Smo.LinkedServerLogin
$newLinkedServerLogin.Parent = $linkedServer4
$newLinkedServerLogin.Name = $loginName
$newLinkedServerLogin.RemoteUser = $loginName
$newLinkedServerLogin.SetRemotePassword(($securePassword | ConvertFrom-SecurePass))
$newLinkedServerLogin.Create()
}
AfterAll {
if ($instance2.LinkedServers.Name -contains "LS1_$random") {
$instance2.LinkedServers["LS1_$random"].Drop()
if ($instance2.LinkedServers.Name -contains $linkedServerName1) {
$instance2.LinkedServers[$linkedServerName1].Drop()
}

if ($instance2.LinkedServers.Name -contains $linkedServerName2) {
$instance2.LinkedServers[$linkedServerName2].Drop()
}

if ($instance2.LinkedServers.Name -contains "LS2_$random") {
$instance2.LinkedServers["LS2_$random"].Drop()
if ($instance2.LinkedServers.Name -contains $linkedServerName3) {
$instance2.LinkedServers[$linkedServerName3].Drop()
}

if ($instance2.LinkedServers.Name -contains "LS3_$random") {
$instance2.LinkedServers["LS3_$random"].Drop()
if ($instance2.LinkedServers.Name -contains $linkedServerName4) {
$instance2.LinkedServers[$linkedServerName4].Drop($true)
}

Remove-DbaLogin -SqlInstance $instance2, $instance3 -Login $loginName -Confirm:$false
}

Context "ensure command works" {

It "Removes a linked server" {
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer "LS1_$random"
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName1
$results.Length | Should -Be 1
Remove-DbaLinkedServer -SqlInstance $script:instance2 -LinkedServer "LS1_$random" -Confirm:$false
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer "LS1_$random"
Remove-DbaLinkedServer -SqlInstance $script:instance2 -LinkedServer $linkedServerName1 -Confirm:$false
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName1
$results | Should -BeNullOrEmpty
}

It "Tries to remove a non-existent linked server" {
Remove-DbaLinkedServer -SqlInstance $script:instance2 -LinkedServer "LS1_$random" -Confirm:$false -WarningVariable warnings
$warnings | Should -BeLike "*Linked server LS1_$random does not exist on $($instance2.Name)"
Remove-DbaLinkedServer -SqlInstance $script:instance2 -LinkedServer $linkedServerName1 -Confirm:$false -WarningVariable warnings
$warnings | Should -BeLike "*Linked server $linkedServerName1 does not exist on $($instance2.Name)"
}

It "Removes a linked server using a server from a pipeline and a linked server from a pipeline" {
$results = Get-DbaLinkedServer -SqlInstance $script:instance2 -LinkedServer "LS2_$random"
It "Removes a linked server passed in via pipeline" {
$results = Get-DbaLinkedServer -SqlInstance $script:instance2 -LinkedServer $linkedServerName2
$results.Length | Should -Be 1
Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer "LS2_$random" | Remove-DbaLinkedServer -WarningVariable warn -Confirm:$false
$warn | Should -BeNullOrEmpty
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer "LS2_$random"
Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName2 | Remove-DbaLinkedServer -Confirm:$false
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName2
$results | Should -BeNullOrEmpty
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems a bit excessive to make so many calls in one It block. Is there anything wrong with just having it test the below line. Not sure why we need to perform this test twice either (piping the command or the object via a variable is the same thing).

Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName2 | Remove-DbaLinkedServer -WarningVariable warn -Confirm:$false

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The goal is to test both of the input object types. I split this into two separate tests.

}

$results = Get-DbaLinkedServer -SqlInstance $script:instance2 -LinkedServer "LS3_$random"
It "Removes a linked server using a server passed in via pipeline" {
$results = Get-DbaLinkedServer -SqlInstance $script:instance2 -LinkedServer $linkedServerName3
$results.Length | Should -Be 1
$instance2 | Remove-DbaLinkedServer -LinkedServer "LS3_$random" -Confirm:$false
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer "LS3_$random"
$instance2 | Remove-DbaLinkedServer -LinkedServer $linkedServerName3 -Confirm:$false
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName3
$results | Should -BeNullOrEmpty
}

It "Tries to remove a linked server that still has logins" {
Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName4 | Remove-DbaLinkedServer -Confirm:$false -WarningVariable warnings
$warnings | Should -BeLike "*There are still remote logins or linked logins for the server*"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed, or put it a unique it block for testing the warning message. If this fails it will appear in the results that the use of -Force is broken.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this into its own test.

}

It "Removes a linked server that requires the -Force param" {
Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName4 | Remove-DbaLinkedServer -Confirm:$false -Force
$results = Get-DbaLinkedServer -SqlInstance $instance2 -LinkedServer $linkedServerName4
$results | Should -BeNullOrEmpty
}
}
Expand Down