Skip to content

Commit cf9eb4f

Browse files
author
Nicholas King
committed
Add interactive parameter set for Restore-AzureRmDeletedWebApp. Add asserts to tests. Fix az mapping.
1 parent 97bea41 commit cf9eb4f

File tree

9 files changed

+1421
-490
lines changed

9 files changed

+1421
-490
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ----------------------------------------------------------------------------------
1+
// ----------------------------------------------------------------------------------
22
//
33
// Copyright Microsoft Corporation
44
// Licensed under the Apache License, Version 2.0 (the 'License');
@@ -768,7 +768,9 @@ public static Dictionary<string, object> GetCaseInsensitiveMapping()
768768
'New-AzWebAppDatabaseBackupSetting': 'New-AzureRmWebAppDatabaseBackupSetting',
769769
'Get-AzWebAppSSLBinding': 'Get-AzureRmWebAppSSLBinding',
770770
'Get-AzWebAppSlot': 'Get-AzureRmWebAppSlot',
771-
'New-AzWebApp': 'New-AzureRmWebApp'
771+
'New-AzWebApp': 'New-AzureRmWebApp',
772+
'Restore-AzDeletedWebApp': 'Restore-AzureRmDeletedWebApp',
773+
'Get-AzDeletedWebApp': 'Get-AzureRmDeletedWebApp'
772774
},
773775
'Az.Maps': {
774776
'Get-AzMapsAccountKey': 'Get-AzureRmMapsAccountKey',
@@ -2383,6 +2385,7 @@ public static Dictionary<string, object> GetCaseInsensitiveMapping()
23832385
'Remove-AzNotificationHubsNamespace': 'Remove-AzureRmNotificationHubsNamespace'
23842386
}
23852387
}
2388+
23862389
";
23872390
}
23882391
}

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

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -431,21 +431,31 @@ function Test-RestoreDeletedWebAppToExisting
431431
$rgname = Get-ResourceGroupName
432432
$wname = Get-WebsiteName
433433
$slotName = "staging"
434+
$appWithSlotName = "$wname/$slotName"
434435
$location = Get-WebLocation
435436
$whpName = Get-WebHostPlanName
436437
$tier = "Standard"
437438

438439
try
439440
{
440-
#Setup
441441
New-AzureRmResourceGroup -Name $rgname -Location $location
442442
New-AzureRmAppServicePlan -ResourceGroupName $rgname -Name $whpName -Location $location -Tier $tier
443443
New-AzureRmWebApp -ResourceGroupName $rgname -Name $wname -Location $location -AppServicePlan $whpName
444444
New-AzureRmWebAppSlot -ResourceGroupName $rgname -Name $wname -Slot $slotName -AppServicePlan $planName
445+
445446
$deletedApp = Get-AzureRmDeletedWebApp -ResourceGroupName $undeleteRgName -Name $undeleteAppName -Slot "Production"
446-
$deletedSlot = Get-AzureRmDeletedWebApp -ResourceGroupName $undeleteRgName -Name $undeleteAppName -Slot $undeleteSlot
447-
Restore-AzureRmDeletedWebApp $deletedApp -TargetResourceGroupName $rgname -TargetName $wname -Force
448-
Restore-AzureRmDeletedWebApp $deletedSlot -TargetResourceGroupName $rgname -TargetName $wname -TargetSlot $slotName -Force
447+
# Test the InputObject parameter set
448+
$restoredApp = Restore-AzureRmDeletedWebApp $deletedApp -TargetResourceGroupName $rgname -TargetName $wname -Force
449+
# Test the FromDeletedResourceName parameter set
450+
$restoredSlot = Restore-AzureRmDeletedWebApp -ResourceGroupName $undeleteRgName -Name $undeleteAppName -Slot $undeleteSlot -TargetResourceGroupName $rgname -TargetName $wname -TargetSlot $slotName -Force
451+
452+
Assert-NotNull $restoredApp
453+
Assert-AreEqual $rgname $restoredApp.ResourceGroup
454+
Assert-AreEqual $wname $restoredApp.Name
455+
456+
Assert-NotNull $restoredSlot
457+
Assert-AreEqual $rgname $restoredSlot.ResourceGroup
458+
Assert-AreEqual $appWithSlotName $restoredSlot.Name
449459
}
450460
finally
451461
{
@@ -471,8 +481,15 @@ function Test-RestoreDeletedWebAppToNew
471481
New-AzureRmResourceGroup -Name $rgname -Location $location
472482
New-AzureRmAppServicePlan -ResourceGroupName $rgname -Name $whpName -Location $location -Tier $tier
473483
$deletedApp = Get-AzureRmDeletedWebApp -ResourceGroupName $undeleteRgName -Name $undeleteAppName -Slot "Production"
484+
# Test piping the deleted app
474485
$job = $deletedApp | Restore-AzureRmDeletedWebApp -TargetResourceGroupName $rgname -TargetAppServicePlanName $whpName -Force -AsJob
475-
$job | Wait-Job
486+
$result = $job | Wait-Job
487+
Assert-AreEqual "Completed" $result.State;
488+
489+
$restoredApp = $job | Receive-Job
490+
Assert-NotNull $restoredApp
491+
Assert-AreEqual $rgname $restoredApp.ResourceGroup
492+
Assert-AreEqual $undeleteAppName $restoredApp.Name
476493
}
477494
finally
478495
{

src/ResourceManager/Websites/Commands.Websites.Test/SessionRecords/Microsoft.Azure.Commands.Websites.Test.ScenarioTests.WebAppBackupRestoreTests/TestRestoreDeletedWebAppToExisting.json

Lines changed: 861 additions & 303 deletions
Large diffs are not rendered by default.

src/ResourceManager/Websites/Commands.Websites.Test/SessionRecords/Microsoft.Azure.Commands.Websites.Test.ScenarioTests.WebAppBackupRestoreTests/TestRestoreDeletedWebAppToNew.json

Lines changed: 434 additions & 155 deletions
Large diffs are not rendered by default.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ CmdletsToExport = 'Get-AzAppServicePlan', 'Set-AzAppServicePlan',
9696
'Reset-AzWebAppPublishingProfile', 'Restart-AzWebApp',
9797
'Set-AzWebApp', 'Start-AzWebApp', 'Stop-AzWebApp',
9898
'Get-AzWebAppSnapshot', 'Restore-AzWebAppSnapshot',
99-
'Get-AzDeletedWebApp'
99+
'Get-AzDeletedWebApp', 'Restore-AzDeletedWebApp'
100100

101101
# Variables to export from this module
102102
# VariablesToExport = @()

src/ResourceManager/Websites/Commands.Websites/Cmdlets/BackupRestore/GetAzureDeletedWebApp.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace Microsoft.Azure.Commands.WebApps.Cmdlets.WebApps
2626
/// <summary>
2727
/// Gets the deleted Azure Web Apps in a subscription
2828
/// </summary>
29-
[Cmdlet("Get", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeletedWebApp"), OutputType(typeof(AzureDeletedWebApp))]
29+
[Cmdlet("Get", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeletedWebApp"), OutputType(typeof(PSAzureDeletedWebApp))]
3030
public class GetAzureDeletedWebApp : WebAppBaseClientCmdLet
3131
{
3232
[Parameter(Position = 0, Mandatory = false, HelpMessage = "The name of the resource group.")]
@@ -45,10 +45,10 @@ public class GetAzureDeletedWebApp : WebAppBaseClientCmdLet
4545
public override void ExecuteCmdlet()
4646
{
4747
base.ExecuteCmdlet();
48-
IEnumerable<AzureDeletedWebApp> deletedSites = WebsitesClient.GetDeletedSites()
48+
IEnumerable<PSAzureDeletedWebApp> deletedSites = WebsitesClient.GetDeletedSites()
4949
.Where(ds => ds.DeletedSiteId.HasValue)
5050
.Select(ds =>
51-
new AzureDeletedWebApp()
51+
new PSAzureDeletedWebApp()
5252
{
5353
DeletedSiteId = ds.DeletedSiteId.Value,
5454
DeletionTime = DateTime.Parse(ds.DeletedTimestamp),

src/ResourceManager/Websites/Commands.Websites/Cmdlets/BackupRestore/AzureDeletedWebApp.cs renamed to src/ResourceManager/Websites/Commands.Websites/Cmdlets/BackupRestore/PSAzureDeletedWebApp.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
namespace Microsoft.Azure.Commands.WebApps.Cmdlets.WebApps
1818
{
19-
public class AzureDeletedWebApp
19+
public class PSAzureDeletedWebApp
2020
{
2121
public int DeletedSiteId { get; set; }
2222

src/ResourceManager/Websites/Commands.Websites/Cmdlets/BackupRestore/RestoreAzureDeletedWebApp.cs

Lines changed: 93 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,49 @@
1616
using Microsoft.Azure.Commands.WebApps.Models;
1717
using Microsoft.Azure.Management.WebSites.Models;
1818
using System;
19+
using System.Linq;
1920
using System.Management.Automation;
2021

2122
namespace Microsoft.Azure.Commands.WebApps.Cmdlets.BackupRestore
2223
{
2324
/// <summary>
2425
/// Restores a deleted Azure Web App's contents and settings to an existing web app
2526
/// </summary>
26-
[Cmdlet("Restore", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeletedWebApp"), OutputType(typeof(void))]
27+
[Cmdlet("Restore", ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "DeletedWebApp"), OutputType(typeof(PSSite))]
2728
public class RestoreAzureDeletedWebApp : WebAppBaseClientCmdLet
2829
{
30+
private const string FromDeletedAppParameterSet = "FromDeletedApp";
31+
private const string FromDeletedResourceNameParameterSet = "FromDeletedResourceName";
32+
2933
// Note, there can be multiple deleted web apps with the same name and resource group. Internally each deleted app has a unique ID.
30-
[Parameter(Position = 0, Mandatory = true, HelpMessage = "The deleted Azure Web App.", ValueFromPipeline = true)]
31-
public AzureDeletedWebApp InputObject;
34+
[Parameter(Position = 0, ParameterSetName = FromDeletedAppParameterSet, Mandatory = true, HelpMessage = "The deleted Azure Web App.", ValueFromPipeline = true)]
35+
public PSAzureDeletedWebApp InputObject;
36+
37+
[Parameter(Position = 0, ParameterSetName = FromDeletedResourceNameParameterSet, Mandatory = true, HelpMessage = "The resource group of the deleted Azure Web App.")]
38+
public string ResourceGroupName { get; set; }
39+
40+
[Parameter(Position = 1, ParameterSetName = FromDeletedResourceNameParameterSet, Mandatory = true, HelpMessage = "The name of the deleted Azure Web App.")]
41+
public string Name { get; set; }
42+
43+
[Parameter(Position = 2, ParameterSetName = FromDeletedResourceNameParameterSet, Mandatory = false, HelpMessage = "The deleted Azure Web App slot.")]
44+
public string Slot { get; set; }
3245

33-
[Parameter(Position = 1, Mandatory = true, HelpMessage = "The resource group containing the new Azure Web App.", ValueFromPipelineByPropertyName = true)]
46+
[Parameter(Mandatory = false, HelpMessage = "The resource group containing the new Azure Web App.")]
3447
public string TargetResourceGroupName { get; set; }
3548

36-
[Parameter(Position = 2, Mandatory = false, HelpMessage = "The name of the new Azure Web App.", ValueFromPipelineByPropertyName = true)]
49+
[Parameter(Mandatory = false, HelpMessage = "The name of the new Azure Web App.")]
3750
public string TargetName { get; set; }
3851

39-
[Parameter(Position = 3, Mandatory = false, HelpMessage = "The name of the new Azure Web App slot.", ValueFromPipelineByPropertyName = true)]
52+
[Parameter(Mandatory = false, HelpMessage = "The name of the new Azure Web App slot.")]
4053
public string TargetSlot { get; set; }
4154

42-
[Parameter(Mandatory = false, HelpMessage = "The App Service Plan for the new Azure Web App.", ValueFromPipelineByPropertyName = true)]
55+
[Parameter(Mandatory = false, HelpMessage = "The App Service Plan for the new Azure Web App.")]
4356
public string TargetAppServicePlanName { get; set; }
4457

45-
[Parameter(Mandatory = false, HelpMessage = "Restore the web app's files, but do not restore the settings.", ValueFromPipelineByPropertyName = true)]
58+
[Parameter(Mandatory = false, HelpMessage = "Restore the web app's files, but do not restore the settings.")]
4659
public SwitchParameter RestoreContentOnly { get; set; }
4760

48-
[Parameter(Mandatory = false, HelpMessage = "Do the restore without prompting for confirmation.", ValueFromPipelineByPropertyName = true)]
61+
[Parameter(Mandatory = false, HelpMessage = "Do the restore without prompting for confirmation.")]
4962
public SwitchParameter Force { get; set; }
5063

5164
[Parameter(Mandatory = false, HelpMessage = "Run cmdlet in the background")]
@@ -54,21 +67,16 @@ public class RestoreAzureDeletedWebApp : WebAppBaseClientCmdLet
5467
public override void ExecuteCmdlet()
5568
{
5669
base.ExecuteCmdlet();
70+
71+
string deletedSiteId = GetDeletedSiteResourceId();
72+
ResolveTargetParameters();
73+
5774
DeletedAppRestoreRequest restoreReq = new DeletedAppRestoreRequest()
5875
{
59-
DeletedSiteId = "/subscriptions/" + InputObject.SubscriptionId + "/providers/Microsoft.Web/deletedSites/" + InputObject.DeletedSiteId,
76+
DeletedSiteId = deletedSiteId,
6077
RecoverConfiguration = !this.RestoreContentOnly
6178
};
6279

63-
if (string.IsNullOrEmpty(TargetName))
64-
{
65-
TargetName = InputObject.Name;
66-
}
67-
if (string.IsNullOrEmpty(TargetSlot))
68-
{
69-
TargetSlot = string.Empty;
70-
}
71-
7280
Action restoreAction = () => WebsitesClient.RestoreDeletedWebApp(TargetResourceGroupName, TargetName, TargetSlot, restoreReq);
7381

7482
if (WebsitesClient.WebAppExists(TargetResourceGroupName, TargetName, TargetSlot))
@@ -100,6 +108,72 @@ public override void ExecuteCmdlet()
100108
}
101109
ConfirmAction(this.Force.IsPresent, confirmMsg, "The deleted app has been restored.", TargetName, createRestoreAction);
102110
}
111+
112+
PSSite restoredApp = new PSSite(WebsitesClient.GetWebApp(TargetResourceGroupName, TargetName, TargetSlot));
113+
WriteObject(restoredApp);
114+
}
115+
116+
private string GetDeletedSiteResourceId()
117+
{
118+
switch (ParameterSetName)
119+
{
120+
case FromDeletedResourceNameParameterSet:
121+
var deletedSites = WebsitesClient.GetDeletedSites().Where(ds =>
122+
{
123+
bool match = string.Equals(ds.ResourceGroup, ResourceGroupName, StringComparison.InvariantCultureIgnoreCase) &&
124+
string.Equals(ds.Name, Name, StringComparison.InvariantCultureIgnoreCase);
125+
if (!string.IsNullOrEmpty(Slot))
126+
{
127+
match = match && string.Equals(ds.Slot, Slot, StringComparison.InvariantCultureIgnoreCase);
128+
}
129+
return match;
130+
});
131+
if (!deletedSites.Any())
132+
{
133+
throw new Exception("Deleted app not found");
134+
}
135+
DeletedSite lastDeleted = deletedSites.OrderBy(ds => DateTime.Parse(ds.DeletedTimestamp)).Last();
136+
if (deletedSites.Count() > 1)
137+
{
138+
WriteWarning("Found multiple matching deleted apps. Restoring the most recently deleted app, deleted at " + lastDeleted.DeletedTimestamp);
139+
}
140+
return "/subscriptions/" + DefaultContext.Subscription.Id + "/providers/Microsoft.Web/deletedSites/" + lastDeleted.DeletedSiteId;
141+
case FromDeletedAppParameterSet:
142+
return "/subscriptions/" + InputObject.SubscriptionId + "/providers/Microsoft.Web/deletedSites/" + InputObject.DeletedSiteId;
143+
default:
144+
throw new Exception("Parameter set error");
145+
}
146+
}
147+
148+
private void ResolveTargetParameters()
149+
{
150+
switch (ParameterSetName)
151+
{
152+
case FromDeletedResourceNameParameterSet:
153+
if (string.IsNullOrEmpty(TargetResourceGroupName))
154+
{
155+
TargetResourceGroupName = ResourceGroupName;
156+
}
157+
if (string.IsNullOrEmpty(TargetName))
158+
{
159+
TargetName = Name;
160+
}
161+
break;
162+
case FromDeletedAppParameterSet:
163+
if (string.IsNullOrEmpty(TargetResourceGroupName))
164+
{
165+
TargetResourceGroupName = InputObject.ResourceGroupName;
166+
}
167+
if (string.IsNullOrEmpty(TargetName))
168+
{
169+
TargetName = InputObject.Name;
170+
}
171+
break;
172+
}
173+
if (string.IsNullOrEmpty(TargetSlot))
174+
{
175+
TargetSlot = string.Empty;
176+
}
103177
}
104178
}
105179
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
</PropertyGroup>
5151
<ItemGroup>
5252
<Compile Include="Cmdlets\AppServicePlans\GetAzureAppServicePlanMetrics.cs" />
53-
<Compile Include="Cmdlets\BackupRestore\AzureDeletedWebApp.cs" />
53+
<Compile Include="Cmdlets\BackupRestore\PSAzureDeletedWebApp.cs" />
5454
<Compile Include="Cmdlets\BackupRestore\AzureWebAppBackup.cs" />
5555
<Compile Include="Cmdlets\BackupRestore\AzureWebAppBackupConfiguration.cs" />
5656
<Compile Include="Cmdlets\BackupRestore\AzureWebAppSnapshot.cs" />

0 commit comments

Comments
 (0)