Simple task, simple solution. One of our Remote Desktop Services Hosts was no longer needed. It was running Windows 2012R2
and the team finally decided to move to 2016. Anyway - the time for decomission has come.
I’ve decided to use this as an introduction lesson to Pester for our junior admin. I just using Pester in infra checks This is an overkill for such a simple task, but remember - intro lesson.
Let’s create a simple checklist for tasks to be done:
Connection Broker
RDS Deployment
Server
Now let’s prepare a simple Pester checklist BEFORE
we do anything (in pseudo-code)
Describe "Verify current state of RDS server" {
IT "Collection name {$RDSCollectionName} on connectionBroker {$RDSConnectionBroker} exists" {
Get-Current-State-of-Collection |
Should -BeTrue -Because "We need to make sure collection exists"
}
IT "Server {$RDSServer} in connectionBroker {$RDSConnectionBroker} has RDS Role" {
Get-Current-State-of-RDS-Server |
Should -BeTrue -Because "Server should be in RDS Deployment"
}
IT "Server {$RDSServer} should have RDS roles installed" {
Get-Current-State-of-RDS-Server-Role |
Should -BeTrue -Because "Server should have all roles installed"
}
}
I didn’t use Context
block by purpose here not to overcomplicate it. As you can see there is no ‘actual’ code in here - just knowledge WHAT is needed. Now, let’s go on a hunt HOW to Get-Current-State-of...
This won’t be hard as RDS module have all necessary cmdlets. How do I know it? by running Get-Command -Module RemoteDesktop
. There are 79 total cmdlets. Because I need to Get-
some information, let’s narrow it down:
PS C:\AdminTools> Get-Command -Module RemoteDesktop -Name Get-*
CommandType Name Version Source
----------- ---- ------- ------
Function Get-RDAvailableApp 2.0.0.0 RemoteDesktop
Function Get-RDCertificate 2.0.0.0 RemoteDesktop
Function Get-RDConnectionBrokerHighAvailability 2.0.0.0 RemoteDesktop
Function Get-RDDeploymentGatewayConfiguration 2.0.0.0 RemoteDesktop
Function Get-RDFileTypeAssociation 2.0.0.0 RemoteDesktop
Function Get-RDLicenseConfiguration 2.0.0.0 RemoteDesktop
Function Get-RDPersonalSessionDesktopAssignment 2.0.0.0 RemoteDesktop
Function Get-RDPersonalVirtualDesktopAssignment 2.0.0.0 RemoteDesktop
Function Get-RDPersonalVirtualDesktopPatchSchedule 2.0.0.0 RemoteDesktop
Function Get-RDRemoteApp 2.0.0.0 RemoteDesktop
Function Get-RDRemoteDesktop 2.0.0.0 RemoteDesktop
Function Get-RDServer 2.0.0.0 RemoteDesktop
Function Get-RDSessionCollection 2.0.0.0 RemoteDesktop
Function Get-RDSessionCollectionConfiguration 2.0.0.0 RemoteDesktop
Function Get-RDSessionHost 2.0.0.0 RemoteDesktop
Function Get-RDUserSession 2.0.0.0 RemoteDesktop
Function Get-RDVirtualDesktop 2.0.0.0 RemoteDesktop
Function Get-RDVirtualDesktopCollection 2.0.0.0 RemoteDesktop
Function Get-RDVirtualDesktopCollectionConfiguration 2.0.0.0 RemoteDesktop
Function Get-RDVirtualDesktopCollectionJobStatus 2.0.0.0 RemoteDesktop
Function Get-RDVirtualDesktopConcurrency 2.0.0.0 RemoteDesktop
Function Get-RDVirtualDesktopIdleCount 2.0.0.0 RemoteDesktop
Function Get-RDVirtualDesktopTemplateExportPath 2.0.0.0 RemoteDesktop
Function Get-RDWorkspace 2.0.0.0 RemoteDesktop
Ok, Seems I will need:
Get-RDSessionCollection
Get-RDServer
Get-WindowsFeature
Let’s code a bit:
$RDSCollectionName = 'CollectionName'
$RDSConnectionBroker = 'ConnectionBroker.contoso.com'
$RDSServer = 'RDSServer'
$RDServerRole = 'RDS-RD-SERVER'
Describe "Verify current state of RDS server" {
IT "Collection name {$RDSCollectionName} on connectionBroker {$RDSConnectionBroker} exists" {
Get-RDSessionCollection -ConnectionBroker $RDSConnectionBroker | Where-Object {$PSItem.CollectionName -eq $RDSCollectionName} |
Should -BeTrue -Because "We need to make sure collection exists"
}
IT "Server {$RDSServer} in connectionBroker {$RDSConnectionBroker} has RDS Role" {
Get-RDServer -ConnectionBroker $RDSConnectionBroker -Role $RDServerRole |
Should -BeTrue -Because "Server should be in RDS Deployment"
}
IT "Server {$RDSServer} should have RDS roles installed" {
Get-WindowsFeature -ComputerName $RDSServer | Where-Object {$PSItem.Name -eq $RDServerRole} | Where-Object {$PSItem.Installed -eq $True} |
Should -BeTrue -Because "Server should have all roles installed"
}
}
Which will generate following output:
Describing Verify current state of RDS server
[+] Collection name {CollectionName} on connectionBroker {ConnectionBroker.contoso.com} exists 5.8s
[+] Server {RDSServer} in connectionBroker {ConnectionBroker.contoso.com} has RDS Role 3.96s
[+] Server {RDSServer} should have RDS roles installed 936ms
Hey, this can be my checklist IF server is properly configured, right?
Ok, let’s get back to our task - removing server:
Remove-RDSessionCollection -CollectionName $RDSCollectionName -ConnectionBroker $RDSConnectionBroker
Remove-RDServer -ConnectionBroker $RDSConnectionBroker -Server $RDSServer -Role $RDServerRole
$status = Invoke-Command -ComputerName $RDSServer -ScriptBlock {
$status = Get-WindowsFeature -ComputerName $RDSServer | Where-Object {$PSItem.Name -eq $USING:RDServerRole}
if ($status.Installed) {
$status | Remove-WindowsFeature
}
Get-WindowsFeature | Where-Object {$PSItem.Name -eq $USING:RDServerRole}
}
if($status.ExitCode -eq 'SuccessRestartRequired') {
Restart-Computer -ComputerName $RDSServer -Protocol WSMan -Wait -Force
}
This will perform all three steps we require.
Let’s assume test if everything is ok now, that we have pester base:
Describe "Verify current state of RDS server" {
IT "Collection name {$RDSCollectionName} on connectionBroker {$RDSConnectionBroker} is removed" {
Get-RDSessionCollection -ConnectionBroker $RDSConnectionBroker | Where-Object {$PSItem.CollectionName -eq $RDSCollectionName} |
Should -BeNullOrEmpty -Because "Collection should be removed before removing server role"
}
IT "Server {$RDSServer} removed from connectionBroker {$RDSConnectionBroker}" {
Get-RDServer -ConnectionBroker $RDSConnectionBroker -Role $RDServerRole | Where-Object {$PSitem.Server -eq $RDSServer} |
Should -BeNullOrEmpty -Because "Server should be removed from connection broker"
}
IT "Server {$RDSServer} should have RDS roles uninstalled" {
Get-WindowsFeature -ComputerName $RDSServer | Where-Object {$PSItem.Name -eq $RDServerRole} | Where-Object {$PSItem.Installed -ne $False} |
Should -BeNullOrEmpty -Because "Server should be removed from connection broker"
}
}
Describing Verify current state of RDS server
[+] Collection name {CollectionName} on connectionBroker {ConnectionBroker.contoso.com} is removed 2.61s
[+] Server {RDSServer} removed from connectionBroker {ConnectionBroker.contoso.com} 3.59s
[+] Server {RDSServer} should have RDS roles uninstalled 170ms