forked from Azure/azure-powershell
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAzureRMCmdlet.cs
300 lines (275 loc) · 13.5 KB
/
AzureRMCmdlet.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------
using Microsoft.Azure.Commands.Common.Authentication;
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
using Microsoft.Azure.Commands.Common.Authentication.Models;
using Microsoft.Azure.Commands.ResourceManager.Common.Properties;
using Microsoft.Azure.Management.Internal.Resources;
using Microsoft.Rest;
using Microsoft.WindowsAzure.Commands.Common;
using Microsoft.WindowsAzure.Commands.Utilities.Common;
using System;
using System.Globalization;
using System.Linq;
using System.Management.Automation;
namespace Microsoft.Azure.Commands.ResourceManager.Common
{
/// <summary>
/// Represents base class for Resource Manager cmdlets
/// </summary>
public abstract class AzureRMCmdlet : AzurePSCmdlet
{
protected ServiceClientTracingInterceptor _serviceClientTracingInterceptor;
IAzureContextContainer _profile;
/// <summary>
/// Creates new instance from AzureRMCmdlet and add the RPRegistration handler.
/// </summary>
public AzureRMCmdlet()
{
}
/// <summary>
/// Gets or sets the global profile for ARM cmdlets.
/// </summary>
[Parameter(Mandatory =false, HelpMessage= "The credentials, account, tenant, and subscription used for communication with Azure.")]
[Alias("AzureRmContext", "AzureCredential")]
public IAzureContextContainer DefaultProfile
{
get
{
if (_profile != null)
{
return _profile;
}
if (AzureRmProfileProvider.Instance == null)
{
throw new InvalidOperationException(Resources.ProfileNotInitialized);
}
return AzureRmProfileProvider.Instance.Profile;
}
set
{
_profile = value;
}
}
protected override string DataCollectionWarning
{
get
{
return Resources.ARMDataCollectionMessage;
}
}
/// <summary>
/// Return a default context safely if it is available, without throwing if it is not setup
/// </summary>
/// <param name="context">The default context</param>
/// <returns>True if there is a valid default context, false otherwise</returns>
public virtual bool TryGetDefaultContext(out IAzureContext context)
{
bool result = false;
context = null;
if (DefaultProfile != null && DefaultProfile.DefaultContext != null && DefaultProfile.DefaultContext.Account != null)
{
context = DefaultProfile.DefaultContext;
result = true;
}
return result;
}
/// <summary>
/// Gets the current default context.
/// </summary>
protected override IAzureContext DefaultContext
{
get
{
if (DefaultProfile == null || DefaultProfile.DefaultContext == null || DefaultProfile.DefaultContext.Account == null)
{
throw new PSInvalidOperationException(Resources.RunConnectAccount);
}
return DefaultProfile.DefaultContext;
}
}
/// <summary>
/// Guards execution of the given action using ShouldProcess and ShouldContinue. The optional
/// useSHouldContinue predicate determines whether SHouldContinue should be called for this
/// particular action (e.g. a resource is being overwritten). By default, both
/// ShouldProcess and ShouldContinue will be executed. Cmdlets that use this method overload
/// must have a force parameter.
/// </summary>
/// <param name="force">Do not ask for confirmation</param>
/// <param name="continueMessage">Message to describe the action</param>
/// <param name="processMessage">Message to prompt after the active is performed.</param>
/// <param name="target">The target name.</param>
/// <param name="action">The action code</param>
protected override void ConfirmAction(bool force, string continueMessage, string processMessage, string target,
Action action)
{
ConfirmAction(force, continueMessage, processMessage, target, action, () => true);
}
/// <summary>
/// Prompt for confirmation for the specified change to the specified ARM resource
/// </summary>
/// <param name="resourceType">The resource type</param>
/// <param name="resourceName">The resource name for the changed reource</param>
/// <param name="resourceGroupName">The resource group containign the changed resource</param>
/// <param name="processMessage">A description of the change to the resource</param>
/// <param name="action">The code action to perform if confirmation is successful</param>
protected void ConfirmResourceAction(string resourceType, string resourceName, string resourceGroupName,
string processMessage, Action action)
{
ConfirmAction(processMessage, string.Format(Resources.ResourceConfirmTarget,
resourceType, resourceName, resourceGroupName), action);
}
/// <summary>
/// Prompt for confirmation for the specified change to the specified ARM resource
/// </summary>
/// <param name="resourceType">The resource type</param>
/// <param name="resourceName">The resource name for the changed reource</param>
/// <param name="resourceGroupName">The resource group containign the changed resource</param>
/// <param name="force">True if Force parameter was passed</param>
/// <param name="continueMessage">The message to display in a ShouldContinue prompt, if offered</param>
/// <param name="processMessage">A description of the change to the resource</param>
/// <param name="action">The code action to perform if confirmation is successful</param>
/// <param name="promptForContinuation">Predicate to determine whether a ShouldContinue prompt is necessary</param>
protected void ConfirmResourceAction(string resourceType, string resourceName, string resourceGroupName,
bool force, string continueMessage, string processMessage, Action action, Func<bool> promptForContinuation = null )
{
ConfirmAction(force, continueMessage, processMessage, string.Format(Resources.ResourceConfirmTarget,
resourceType, resourceName, resourceGroupName), action, promptForContinuation);
}
/// <summary>
/// Prompt for confirmation for the specified change to the specified ARM resource
/// </summary>
/// <param name="resourceId">The identity of the resource to be changed</param>
/// <param name="actionName">A description of the change to the resource</param>
/// <param name="action">The code action to perform if confirmation is successful</param>
protected void ConfirmResourceAction(string resourceId, string actionName, Action action)
{
ConfirmAction(actionName, string.Format(Resources.ResourceIdConfirmTarget,
resourceId), action);
}
/// <summary>
/// Prompt for confirmation for the specified change to the specified ARM resource
/// </summary>
/// <param name="resourceId">The identity of the resource to be changed</param>
/// <param name="force">True if Force parameter was passed</param>
/// <param name="continueMessage">The message to display in a ShouldContinue prompt, if offered</param>
/// <param name="actionName">A description of the change to the resource</param>
/// <param name="action">The code action to perform if confirmation is successful</param>
/// <param name="promptForContinuation">Predicate to determine whether a ShouldContinue prompt is necessary</param>
protected void ConfirmResourceAction(string resourceId, bool force, string continueMessage, string actionName,
Action action, Func<bool> promptForContinuation = null)
{
ConfirmAction(force, continueMessage, actionName, string.Format(Resources.ResourceIdConfirmTarget,
resourceId), action, promptForContinuation);
}
protected override void InitializeQosEvent()
{
var commandAlias = this.GetType().Name;
if (this.MyInvocation != null && this.MyInvocation.MyCommand != null)
{
commandAlias = this.MyInvocation.MyCommand.Name;
}
_qosEvent = new AzurePSQoSEvent()
{
CommandName = commandAlias,
ModuleName = this.GetType().Assembly.GetName().Name,
ModuleVersion = this.GetType().Assembly.GetName().Version.ToString(),
ClientRequestId = this._clientRequestId,
SessionId = _sessionId,
IsSuccess = true,
};
if (this.MyInvocation != null && this.MyInvocation.BoundParameters != null
&& this.MyInvocation.BoundParameters.Keys != null)
{
_qosEvent.Parameters = string.Join(" ",
this.MyInvocation.BoundParameters.Keys.Select(
s => string.Format(CultureInfo.InvariantCulture, "-{0} ***", s)));
}
IAzureContext context;
if (TryGetDefaultContext(out context)
&& context.Account != null
&& !string.IsNullOrWhiteSpace(context.Account.Id))
{
_qosEvent.Uid = MetricHelper.GenerateSha256HashString(context.Account.Id.ToString());
}
else
{
_qosEvent.Uid = "defaultid";
}
}
protected override void LogCmdletStartInvocationInfo()
{
base.LogCmdletStartInvocationInfo();
IAzureContext context;
if (TryGetDefaultContext(out context)
&& context.Account != null
&& context.Account.Id != null)
{
WriteDebugWithTimestamp(string.Format("using account id '{0}'...",
context.Account.Id));
}
}
protected override void LogCmdletEndInvocationInfo()
{
base.LogCmdletEndInvocationInfo();
string message = string.Format("{0} end processing.", this.GetType().Name);
WriteDebugWithTimestamp(message);
}
protected override void SetupDebuggingTraces()
{
ServiceClientTracing.IsEnabled = true;
base.SetupDebuggingTraces();
_serviceClientTracingInterceptor = _serviceClientTracingInterceptor
?? new ServiceClientTracingInterceptor(DebugMessages);
ServiceClientTracing.AddTracingInterceptor(_serviceClientTracingInterceptor);
}
protected override void TearDownDebuggingTraces()
{
ServiceClientTracingInterceptor.RemoveTracingInterceptor(_serviceClientTracingInterceptor);
_serviceClientTracingInterceptor = null;
base.TearDownDebuggingTraces();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing && _serviceClientTracingInterceptor != null)
{
ServiceClientTracingInterceptor.RemoveTracingInterceptor(_serviceClientTracingInterceptor);
_serviceClientTracingInterceptor = null;
AzureSession.Instance.ClientFactory.RemoveHandler(typeof(RPRegistrationDelegatingHandler));
}
}
protected override void BeginProcessing()
{
AzureSession.Instance.ClientFactory.RemoveHandler(typeof(RPRegistrationDelegatingHandler));
IAzureContext context;
if (TryGetDefaultContext(out context)
&& context.Account != null
&& context.Subscription != null)
{
AzureSession.Instance.ClientFactory.AddHandler(new RPRegistrationDelegatingHandler(
() =>
{
var client = new ResourceManagementClient(
context.Environment.GetEndpointAsUri(AzureEnvironment.Endpoint.ResourceManager),
AzureSession.Instance.AuthenticationFactory.GetServiceClientCredentials(context, AzureEnvironment.Endpoint.ResourceManager));
client.SubscriptionId = context.Subscription.Id;
return client;
},
s => DebugMessages.Enqueue(s)));
}
base.BeginProcessing();
}
}
}