Skip to content

Commit fdafbff

Browse files
authored
Merge pull request #7423 from vinisoto/windows_containers_pssession
New cmdlets to create/enter PSSession in remote container app
2 parents 2bb79e0 + f931c2e commit fdafbff

File tree

18 files changed

+6920
-3
lines changed

18 files changed

+6920
-3
lines changed

src/ResourceManager/Profile/Commands.Profile/AzureRmAlias/Mappings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2395,6 +2395,8 @@
23952395
"Get-AzDeletedWebApp": "Get-AzureRmDeletedWebApp",
23962396
"Restore-AzDeletedWebApp": "Restore-AzureRmDeletedWebApp",
23972397
"Get-AzWebAppContainerContinuousDeploymentUrl": "Get-AzureRmWebAppContainerContinuousDeploymentUrl",
2398-
"Swap-AzWebAppSlot": "Swap-AzureRmWebAppSlot"
2398+
"Swap-AzWebAppSlot": "Swap-AzureRmWebAppSlot",
2399+
"Enter-AzWebAppContainerPSSession" : "Enter-AzureRmWebAppContainerPSSession",
2400+
"New-AzWebAppContainerPSSession" : "New-AzureRmWebAppContainerPSSession"
23992401
}
24002402
}

src/ResourceManager/Websites/Commands.Websites.Test/Commands.Websites.Test.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@
212212
<None Include="SessionRecords\Microsoft.Azure.Commands.Websites.Test.ScenarioTests.WebAppBackupRestoreTests\TestRestoreDeletedWebAppToNew.json">
213213
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
214214
</None>
215+
<None Include="SessionRecords\Microsoft.Azure.Commands.Websites.Test.ScenarioTests.WebAppTests\TestWindowsContainerWebAppCanIssuePSSession.json">
216+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
217+
</None>
218+
<None Include="SessionRecords\Microsoft.Azure.Commands.Websites.Test.ScenarioTests.WebAppTests\TestWindowsContainerWebAppPSSessionOpened.json">
219+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
220+
</None>
215221
</ItemGroup>
216222
<ItemGroup>
217223
<ProjectReference Include="..\..\..\Storage\Commands.Storage\Commands.Storage.csproj">

src/ResourceManager/Websites/Commands.Websites.Test/ScenarioTests/WebAppTests.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,5 +129,19 @@ public void TestRemoveWebApp()
129129
{
130130
WebsitesController.NewInstance.RunPsTest(_logger, "Test-RemoveWebApp");
131131
}
132+
133+
[Fact(Skip = "Skipping while investigation regarding PowerShell version in Travis continues")]
134+
[Trait(Category.AcceptanceType, Category.CheckIn)]
135+
public void TestWindowsContainerWebAppCanIssuePSSession()
136+
{
137+
WebsitesController.NewInstance.RunPsTest(_logger, "Test-WindowsContainerCanIssueWebAppPSSession");
138+
}
139+
140+
[Fact(Skip = "Expected to fail during playback because it validates that a PsSession into a real container web app can be established")]
141+
[Trait(Category.AcceptanceType, Category.CheckIn)]
142+
public void TestWindowsContainerWebAppPSSessionOpened()
143+
{
144+
WebsitesController.NewInstance.RunPsTest(_logger, "Test-WindowsContainerWebAppPSSessionOpened");
145+
}
132146
}
133147
}

src/ResourceManager/Websites/Commands.Websites.Test/ScenarioTests/WebAppTests.ps1

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,276 @@ function Test-EnableContainerContinuousDeploymentAndGetUrl
663663
}
664664
}
665665

666+
<#
667+
.SYNOPSIS
668+
Tests issuing an EnterPsSession command to a Windows container web app.
669+
.DESCRIPTION
670+
SmokeTest
671+
#>
672+
function Test-WindowsContainerCanIssueWebAppPSSession
673+
{
674+
# Setup
675+
$rgname = Get-ResourceGroupName
676+
$wname = Get-WebsiteName
677+
$location = Get-WebLocation
678+
$whpName = Get-WebHostPlanName
679+
$tier = "PremiumContainer"
680+
$apiversion = "2015-08-01"
681+
$resourceType = "Microsoft.Web/sites"
682+
$containerImageName = "mcr.microsoft.com/azure-app-service/samples/aspnethelloworld:latest"
683+
$containerRegistryUrl = "https://mcr.microsoft.com"
684+
$containerRegistryUser = "testregistry"
685+
$pass = "7Dxo9p79Ins2K3ZU"
686+
$containerRegistryPassword = ConvertTo-SecureString -String $pass -AsPlainText -Force
687+
$dockerPrefix = "DOCKER|"
688+
689+
try
690+
{
691+
692+
Write-Debug "Creating app service plan..."
693+
694+
#Setup
695+
New-AzureRmResourceGroup -Name $rgname -Location $location
696+
$serverFarm = New-AzureRmAppServicePlan -ResourceGroupName $rgname -Name $whpName -Location $location -Tier $tier -WorkerSize Large -HyperV
697+
698+
Write-Debug "App service plan created"
699+
700+
Write-Debug "Creating web app plan..."
701+
702+
# Create new web app
703+
$job = New-AzureRmWebApp -ResourceGroupName $rgname -Name $wname -Location $location -AppServicePlan $whpName -ContainerImageName $containerImageName -ContainerRegistryUrl $containerRegistryUrl -ContainerRegistryUser $containerRegistryUser -ContainerRegistryPassword $containerRegistryPassword -AsJob
704+
$job | Wait-Job
705+
$actual = $job | Receive-Job
706+
707+
Write-Debug "Webapp created"
708+
709+
# Assert
710+
Assert-AreEqual $wname $actual.Name
711+
Assert-AreEqual $serverFarm.Id $actual.ServerFarmId
712+
# Get new web app
713+
$result = Get-AzureRmWebApp -ResourceGroupName $rgname -Name $wname
714+
715+
Write-Debug "Webapp retrieved"
716+
717+
Write-Debug "Validating web app properties..."
718+
719+
# Assert
720+
Assert-AreEqual $wname $result.Name
721+
Assert-AreEqual $serverFarm.Id $result.ServerFarmId
722+
Assert-AreEqual $true $result.IsXenon
723+
Assert-AreEqual ($dockerPrefix + $containerImageName) $result.SiteConfig.WindowsFxVersion
724+
725+
$actualAppSettings = @{}
726+
727+
foreach ($kvp in $result.SiteConfig.AppSettings)
728+
{
729+
$actualAppSettings[$kvp.Name] = $kvp.Value
730+
}
731+
732+
# Validate Appsettings
733+
734+
$expectedAppSettings = @{}
735+
$expectedAppSettings["DOCKER_REGISTRY_SERVER_URL"] = $containerRegistryUrl;
736+
$expectedAppSettings["DOCKER_REGISTRY_SERVER_USERNAME"] = $containerRegistryUser;
737+
$expectedAppSettings["DOCKER_REGISTRY_SERVER_PASSWORD"] = $pass;
738+
739+
foreach ($key in $expectedAppSettings.Keys)
740+
{
741+
Assert-True {$actualAppSettings.Keys -contains $key}
742+
Assert-AreEqual $actualAppSettings[$key] $expectedAppSettings[$key]
743+
}
744+
745+
Write-Debug "Enabling Win-RM..."
746+
747+
# Adding Appsetting: enabling WinRM
748+
$actualAppSettings["CONTAINER_WINRM_ENABLED"] = "1"
749+
$webApp = Set-AzureRmWebApp -ResourceGroupName $rgname -Name $wName -AppSettings $actualAppSettings
750+
751+
# Validating that the client can at least issue the EnterPsSession command.
752+
# This will validate that this cmdlet will run succesfully in Cloud Shell.
753+
# If the current PsVersion is 5.1 or less (Windows PowerShell) and the current WSMAN settings will not allow the user
754+
# to connect (for example: invalid Trusted Hosts, Basic Auth not enabled) this command will issue a Warning instructing the user
755+
# to fix WSMAN settings. It will not attempt to run EnterPsSession.
756+
#
757+
# If the current version is 6.0 (PowerShell Core) this command will not attempt to validate WSMAN settings and
758+
# just try to run EnterPsSession. EnterPsSession is available in Cloud Shell
759+
#
760+
# We need an real Windows Container app running to fully validate the returned PsSession object, which is not
761+
# possible in 'Playback' mode.
762+
#
763+
# This assert at least verifies that the EnterPsSession command is attempted and that the behavior is the expected in
764+
# Windows PowerShell and PowerShell Core.
765+
New-AzureRmWebAppContainerPSSession -ResourceGroupName $rgname -Name $wname -WarningVariable wv -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -Force
766+
767+
768+
if ((Get-WebsitesTestMode) -ne 'Playback')
769+
{
770+
# Message for Recording mode
771+
$message = "Connecting to remote server $wname.azurewebsites.net failed with the following error message : The connection to the specified remote host was refused."
772+
$resultError = $Error[0] -like "*$($message)*"
773+
Write-Debug "Expected Message: $message"
774+
}
775+
else
776+
{
777+
# Two possible messages in Playback mode since the site will not exist.
778+
$messageDNS = "Connecting to remote server $wname.azurewebsites.net failed with the following error message : The WinRM client cannot process the request because the server name cannot be resolved"
779+
$messageUnavailable = "Connecting to remote server $wname.azurewebsites.net failed with the following error message : The WinRM client sent a request to an HTTP server and got a response saying the requested HTTP URL was not available."
780+
$resultError = ($Error[0] -like "*$($messageDNS)*") -or ($Error[0] -like "*$($messageUnavailable)*")
781+
Write-Debug "Expected Message 1: $messageDNS"
782+
Write-Debug "Expected Message 2: $messageUnavailable"
783+
}
784+
785+
Write-Debug "Error: $Error[0]"
786+
Write-Debug "Warnings: $wv"
787+
788+
Write-Debug "Printing PsVersion"
789+
foreach ($key in $PsVersionTable.Keys)
790+
{
791+
Write-Debug "$key"
792+
foreach($v in $PsVersionTable[$key])
793+
{
794+
Write-Debug " $v"
795+
}
796+
}
797+
798+
799+
If(!$resultError)
800+
{
801+
Write-Output "expected error $($message), actual error $($Error[0])"
802+
Write-Output "Warnings: $wv"
803+
}
804+
Assert-True {$resultError}
805+
}
806+
finally
807+
{
808+
# Cleanup
809+
Remove-AzureRmWebApp -ResourceGroupName $rgname -Name $wname -Force
810+
Remove-AzureRmAppServicePlan -ResourceGroupName $rgname -Name $whpName -Force
811+
Remove-AzureRmResourceGroup -Name $rgname -Force
812+
}
813+
}
814+
815+
<#
816+
.SYNOPSIS
817+
Tests that a PsSession can be established to a Windows Container App. It is expected to fail in Playback mode
818+
.DESCRIPTION
819+
SmokeTest
820+
#>
821+
function Test-WindowsContainerWebAppPSSessionOpened
822+
{
823+
# Setup
824+
$rgname = Get-ResourceGroupName
825+
$wname = Get-WebsiteName
826+
$location = Get-WebLocation
827+
$whpName = Get-WebHostPlanName
828+
$tier = "PremiumContainer"
829+
$apiversion = "2015-08-01"
830+
$resourceType = "Microsoft.Web/sites"
831+
$containerImageName = "mcr.microsoft.com/azure-app-service/samples/aspnethelloworld:latest"
832+
$containerRegistryUrl = "https://mcr.microsoft.com"
833+
$containerRegistryUser = "testregistry"
834+
$pass = "7Dxo9p79Ins2K3ZU"
835+
$containerRegistryPassword = ConvertTo-SecureString -String $pass -AsPlainText -Force
836+
$dockerPrefix = "DOCKER|"
837+
838+
try
839+
{
840+
841+
Write-Debug "Creating app service plan..."
842+
843+
#Setup
844+
New-AzureRmResourceGroup -Name $rgname -Location $location
845+
$serverFarm = New-AzureRmAppServicePlan -ResourceGroupName $rgname -Name $whpName -Location $location -Tier $tier -WorkerSize Large -HyperV
846+
847+
Write-Debug "App service plan created"
848+
849+
Write-Debug "Creating web app plan..."
850+
851+
# Create new web app
852+
$job = New-AzureRmWebApp -ResourceGroupName $rgname -Name $wname -Location $location -AppServicePlan $whpName -ContainerImageName $containerImageName -ContainerRegistryUrl $containerRegistryUrl -ContainerRegistryUser $containerRegistryUser -ContainerRegistryPassword $containerRegistryPassword -AsJob
853+
$job | Wait-Job
854+
$actual = $job | Receive-Job
855+
856+
Write-Debug "Webapp created"
857+
858+
# Assert
859+
Assert-AreEqual $wname $actual.Name
860+
Assert-AreEqual $serverFarm.Id $actual.ServerFarmId
861+
# Get new web app
862+
$result = Get-AzureRmWebApp -ResourceGroupName $rgname -Name $wname
863+
864+
Write-Debug "Webapp retrieved"
865+
866+
Write-Debug "Validating web app properties..."
867+
868+
# Assert
869+
Assert-AreEqual $wname $result.Name
870+
Assert-AreEqual $serverFarm.Id $result.ServerFarmId
871+
Assert-AreEqual $true $result.IsXenon
872+
Assert-AreEqual ($dockerPrefix + $containerImageName) $result.SiteConfig.WindowsFxVersion
873+
874+
$actualAppSettings = @{}
875+
876+
foreach ($kvp in $result.SiteConfig.AppSettings)
877+
{
878+
$actualAppSettings[$kvp.Name] = $kvp.Value
879+
}
880+
881+
# Validate Appsettings
882+
883+
$expectedAppSettings = @{}
884+
$expectedAppSettings["DOCKER_REGISTRY_SERVER_URL"] = $containerRegistryUrl;
885+
$expectedAppSettings["DOCKER_REGISTRY_SERVER_USERNAME"] = $containerRegistryUser;
886+
$expectedAppSettings["DOCKER_REGISTRY_SERVER_PASSWORD"] = $pass;
887+
888+
foreach ($key in $expectedAppSettings.Keys)
889+
{
890+
Assert-True {$actualAppSettings.Keys -contains $key}
891+
Assert-AreEqual $actualAppSettings[$key] $expectedAppSettings[$key]
892+
}
893+
894+
Write-Debug "Enabling Win-RM..."
895+
896+
# Adding Appsetting: enabling WinRM
897+
$actualAppSettings["CONTAINER_WINRM_ENABLED"] = "1"
898+
$webApp = Set-AzureRmWebApp -ResourceGroupName $rgname -Name $wName -AppSettings $actualAppSettings
899+
900+
$status = PingWebApp($webApp)
901+
Write-Debug "Just pinged the web app"
902+
Write-Debug "Status: $status"
903+
904+
# Wait for the container app to return 200.
905+
# Windows Container apps return 503 when starting up. Usualy takes 8-9 minutes.
906+
# Timing out at 15 minutes
907+
908+
$count=0
909+
while (($status -like "ServiceUnavailable") -and $count -le 15)
910+
{
911+
Wait-Seconds 60
912+
$status = PingWebApp($webApp)
913+
Write-Debug $count
914+
$count++
915+
}
916+
917+
# Asserting status of the last ping to the web app
918+
Assert-AreEqual $status "200"
919+
920+
$ps_session = New-AzureRmWebAppContainerPSSession -ResourceGroupName $rgname -Name $wname -Force
921+
922+
Write-Debug "After PSSession"
923+
924+
Assert-AreEqual $ps_session.ComputerName $wname".azurewebsites.net"
925+
Assert-AreEqual $ps_session.State "Opened"
926+
}
927+
finally
928+
{
929+
# Cleanup
930+
Remove-AzureRmWebApp -ResourceGroupName $rgname -Name $wname -Force
931+
Remove-AzureRmAppServicePlan -ResourceGroupName $rgname -Name $whpName -Force
932+
Remove-AzureRmResourceGroup -Name $rgname -Force
933+
}
934+
}
935+
666936
<#
667937
.SYNOPSIS
668938
Tests creating a new website on an ase

src/ResourceManager/Websites/Commands.Websites.Test/SessionRecords/Microsoft.Azure.Commands.Websites.Test.ScenarioTests.WebAppTests/TestWindowsContainerWebAppCanIssuePSSession.json

Lines changed: 3011 additions & 0 deletions
Large diffs are not rendered by default.

src/ResourceManager/Websites/Commands.Websites.Test/SessionRecords/Microsoft.Azure.Commands.Websites.Test.ScenarioTests.WebAppTests/TestWindowsContainerWebAppPSSessionOpened.json

Lines changed: 3011 additions & 0 deletions
Large diffs are not rendered by default.

src/ResourceManager/Websites/Commands.Websites/Az.Websites.psd1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ CmdletsToExport = 'Get-AzAppServicePlan', 'Set-AzAppServicePlan',
9797
'Set-AzWebApp', 'Start-AzWebApp', 'Stop-AzWebApp',
9898
'Get-AzWebAppSnapshot', 'Restore-AzWebAppSnapshot',
9999
'Get-AzDeletedWebApp', 'Restore-AzDeletedWebApp',
100-
'Get-AzWebAppContainerContinuousDeploymentUrl'
100+
'Get-AzWebAppContainerContinuousDeploymentUrl',
101+
'Enter-AzWebAppContainerPSSession', 'New-AzWebAppContainerPSSession'
101102

102103
# Variables to export from this module
103104
# VariablesToExport = @()

src/ResourceManager/Websites/Commands.Websites/AzureRM.Websites.psd1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ CmdletsToExport = 'Get-AzureRmAppServicePlan', 'Set-AzureRmAppServicePlan',
9797
'Set-AzureRmWebApp', 'Start-AzureRmWebApp', 'Stop-AzureRmWebApp',
9898
'Get-AzureRmWebAppSnapshot', 'Restore-AzureRmWebAppSnapshot',
9999
'Get-AzureRmDeletedWebApp', 'Restore-AzureRmDeletedWebApp',
100-
'Get-AzureRmWebAppContainerContinuousDeploymentUrl'
100+
'Get-AzureRmWebAppContainerContinuousDeploymentUrl',
101+
'Enter-AzureRmWebAppContainerPSSession', 'New-AzureRmWebAppContainerPSSession'
101102

102103
# Variables to export from this module
103104
# VariablesToExport = @()

src/ResourceManager/Websites/Commands.Websites/ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
-->
2020
## Current Release
2121
* New Cmdlet Get-AzureRMWebAppContainerContinuousDeploymentUrl - Gets the Container Continuous Deployment Webhook URL
22+
* New Cmdlets New-AzureRMWebAppContainerPSSession and Enter-WebAppContainerPSSession - Initiates a PowerShell remote session into a windows container app
2223

2324
## Version 5.1.0
2425
* Updating to use the latest .NET SDK version (2.0.0)

0 commit comments

Comments
 (0)