Skip to content

Commit 1e6b56c

Browse files
author
Sean Oh
committed
Added autoregister functionality for Reservations
1 parent 11c84ee commit 1e6b56c

File tree

5 files changed

+158
-4
lines changed

5 files changed

+158
-4
lines changed

src/ResourceManager/Reservations/Commands.Reservations/Cmdlets/PatchReservation.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
namespace Microsoft.Azure.Commands.Reservations.Cmdlets
1111
{
1212
[Cmdlet(VerbsData.Update, "AzureRmReservation", DefaultParameterSetName = Constants.ParameterSetNames.CommandParameterSet, SupportsShouldProcess = true), OutputType(typeof(PSReservation))]
13-
public class PatchReservation : AzureReservationsCmdletBase
13+
public class PatchReservation : AzureReservationsAutoRegisterCmdletBase
1414
{
1515
[Parameter(ParameterSetName = Constants.ParameterSetNames.CommandParameterSet,
1616
Mandatory = true)]
@@ -37,6 +37,8 @@ public class PatchReservation : AzureReservationsCmdletBase
3737
[ValidateNotNull]
3838
public PSReservation Reservation { get; set; }
3939

40+
protected override bool ShouldRegister => AppliedScope != null;
41+
4042
public override void ExecuteCmdlet()
4143
{
4244
if (ParameterSetName.Equals(Constants.ParameterSetNames.ObjectParameterSet))

src/ResourceManager/Reservations/Commands.Reservations/Commands.Reservations.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@
6262
<Compile Include="Cmdlets\MergeReservation.cs" />
6363
<Compile Include="Cmdlets\PatchReservation.cs" />
6464
<Compile Include="Cmdlets\SplitReservation.cs" />
65+
<Compile Include="Common\AzureReservationsAutoRegisterCmdletBase.cs" />
6566
<Compile Include="Common\AzureReservationsCmdletBase.cs" />
67+
<Compile Include="Common\AzureReservationsAutoRegisterDelegatingHandler.cs" />
6668
<Compile Include="Common\Constants.cs" />
6769
<Compile Include="Custom\PSCatalog.cs" />
6870
<Compile Include="Custom\PSAppliedReservationOrderId.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
using Microsoft.Azure.Commands.Common.Authentication;
8+
using Microsoft.Azure.Commands.Common.Authentication.Models;
9+
using Microsoft.Azure.Commands.ResourceManager.Common;
10+
using Microsoft.Azure.Management.Reservations;
11+
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
12+
using Microsoft.Azure.Management.Internal.Resources;
13+
14+
namespace Microsoft.Azure.Commands.Reservations.Common
15+
{
16+
/// <summary>
17+
/// Base class of Azure Reservations Auto Register Cmdlet.
18+
/// </summary>
19+
public abstract class AzureReservationsAutoRegisterCmdletBase : AzureReservationsCmdletBase
20+
{
21+
//Register for compute is required for Reservations commands inheriting this class
22+
private string ComputeProviderNamespace = "Microsoft.Compute";
23+
24+
protected abstract bool ShouldRegister { get; }
25+
26+
protected override void BeginProcessing()
27+
{
28+
AzureSession.Instance.ClientFactory.RemoveHandler(typeof(AzureReservationsAutoRegisterDelegatingHandler));
29+
IAzureContext context;
30+
if (TryGetDefaultContext(out context)
31+
&& context.Account != null
32+
&& context.Subscription != null)
33+
{
34+
AzureSession.Instance.ClientFactory.AddHandler(new AzureReservationsAutoRegisterDelegatingHandler(
35+
ComputeProviderNamespace,
36+
ShouldRegister,
37+
() =>
38+
{
39+
var client = new ResourceManagementClient(
40+
context.Environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager),
41+
AzureSession.Instance.AuthenticationFactory.GetServiceClientCredentials(context, AzureEnvironment.Endpoint.ResourceManager));
42+
client.SubscriptionId = context.Subscription.Id;
43+
return client;
44+
},
45+
s => DebugMessages.Enqueue(s)));
46+
}
47+
48+
base.BeginProcessing();
49+
}
50+
}
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Net.Http;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Microsoft.Azure.Commands.ResourceManager.Common.Properties;
7+
using Microsoft.Azure.Management.Internal.Resources;
8+
using Microsoft.Azure.Management.Internal.Resources.Models;
9+
using Microsoft.Rest.Azure;
10+
using Microsoft.WindowsAzure.Commands.Utilities.Common;
11+
12+
namespace Microsoft.Azure.Commands.Reservations.Common
13+
{
14+
class AzureReservationsAutoRegisterDelegatingHandler : DelegatingHandler, ICloneable
15+
{
16+
private const short RetryCount = 10;
17+
18+
private Func<ResourceManagementClient> createClient;
19+
20+
private Action<string> writeDebug;
21+
22+
private string providerName;
23+
24+
private bool shouldRegister;
25+
26+
public ResourceManagementClient ResourceManagementClient { get; set; }
27+
28+
public AzureReservationsAutoRegisterDelegatingHandler(string providerName, bool shouldRegister,
29+
Func<ResourceManagementClient> createClient, Action<string> writeDebug)
30+
{
31+
this.providerName = providerName;
32+
this.createClient = createClient;
33+
this.writeDebug = writeDebug;
34+
this.shouldRegister = shouldRegister;
35+
}
36+
37+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
38+
{
39+
try
40+
{
41+
if (shouldRegister)
42+
{
43+
ResourceManagementClient = createClient();
44+
writeDebug($"Attempting to check if Subscription is registered with {providerName}");
45+
var provider = ResourceManagementClient.Providers.Get(providerName);
46+
if (provider.RegistrationState != RegistrationState.Registered)
47+
{
48+
writeDebug(string.Format(Resources.ResourceProviderRegisterAttempt, providerName));
49+
short retryCount = 0;
50+
do
51+
{
52+
if (retryCount++ > RetryCount)
53+
{
54+
throw new TimeoutException();
55+
}
56+
provider = ResourceManagementClient.Providers.Register(providerName);
57+
TestMockSupport.Delay(2000);
58+
} while (provider.RegistrationState != RegistrationState.Registered);
59+
writeDebug(string.Format(Resources.ResourceProviderRegisterSuccessful, providerName));
60+
}
61+
else
62+
{
63+
writeDebug($"Subscription is already registered with {providerName}");
64+
}
65+
}
66+
}
67+
catch (Exception e)
68+
{
69+
writeDebug(string.Format(Resources.ResourceProviderRegisterFailure, providerName, e.Message));
70+
71+
if (e.Message?.IndexOf("does not have authorization") >= 0 && e.Message?.IndexOf("register/action",
72+
StringComparison.InvariantCultureIgnoreCase) >= 0)
73+
{
74+
throw new CloudException(e.Message);
75+
}
76+
}
77+
78+
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
79+
}
80+
81+
public object Clone()
82+
{
83+
return new AzureReservationsAutoRegisterDelegatingHandler(providerName, shouldRegister, createClient, writeDebug);
84+
}
85+
}
86+
}

src/ResourceManager/Reservations/Commands.Reservations/help/Update-AzureRmReservation.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ Update a `Reservation`.
1515
### CommandLine (Default)
1616
```
1717
Update-AzureRmReservation -ReservationOrderId <String> -ReservationId <String> -AppliedScopeType <String>
18-
[-AppliedScope <String>] [-WhatIf] [-Confirm] [<CommonParameters>]
18+
[-AppliedScope <String>] [-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm] [<CommonParameters>]
1919
```
2020

2121
### PipeObject
2222
```
2323
Update-AzureRmReservation -AppliedScopeType <String> [-AppliedScope <String>] -Reservation <PSReservation>
24-
[-WhatIf] [-Confirm] [<CommonParameters>]
24+
[-DefaultProfile <IAzureContextContainer>] [-WhatIf] [-Confirm] [<CommonParameters>]
2525
```
2626

2727
## DESCRIPTION
@@ -31,7 +31,7 @@ Updates the applied scopes of the `Reservation`.
3131

3232
### Example 1
3333
```
34-
PS C:\> Update-AzureRmReservation -ReservationOrderId "11111111-1111-1111-1111-1111111111" -ReservationId "00000000-1111-1111-1111-0000000000" -appliedScopeType "Single" -appliedscope "1111aaaa-b1b2-c0c2-d0d2-00000fffff"
34+
PS C:\> Update-AzureRmReservation -ReservationOrderId "11111111-1111-1111-1111-1111111111" -ReservationId "00000000-1111-1111-1111-0000000000" -appliedScopeType "Single" -appliedscope "/subscriptions/1111aaaa-b1b2-c0c2-d0d2-00000fffff"
3535
```
3636

3737
Updates the AppliedScopeType of the specified reservation to Single
@@ -76,6 +76,19 @@ Accept pipeline input: False
7676
Accept wildcard characters: False
7777
```
7878

79+
### -DefaultProfile
80+
The credentials, account, tenant, and subscription used for communication with Azure.```yaml
81+
Type: IAzureContextContainer
82+
Parameter Sets: (All)
83+
Aliases: AzureRmContext, AzureCredential
84+
85+
Required: False
86+
Position: Named
87+
Default value: None
88+
Accept pipeline input: False
89+
Accept wildcard characters: False
90+
```
91+
7992
### -Reservation
8093
Pipe object parameter for `Reservation`
8194

0 commit comments

Comments
 (0)