Skip to content

Commit 3d1a3e7

Browse files
azure-powershell-botazurepowershell
andauthored
Sync tools folder from main branch to generation branch (#21053)
Co-authored-by: azurepowershell <[email protected]>
1 parent 06c712b commit 3d1a3e7

25 files changed

+213
-100
lines changed

src/Az.Shared.props

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,20 @@
88

99
<!-- Build -->
1010
<PropertyGroup>
11-
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
11+
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
12+
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
13+
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
14+
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
15+
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
16+
<GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
17+
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
1218
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
1319
<WarningsAsErrors />
1420
</PropertyGroup>
1521

16-
</Project>
22+
<!-- include shared source code -->
23+
<ItemGroup>
24+
<Compile Include="$(MSBuildThisFileDirectory)shared\*.cs" />
25+
</ItemGroup>
26+
27+
</Project>

src/Az.props

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<SignAssembly>true</SignAssembly>
2525
<DelaySign>true</DelaySign>
2626
<AssemblyOriginatorKeyFile>$(RepoSrc)MSSharedLibKey.snk</AssemblyOriginatorKeyFile>
27-
<DefineConstants>TRACE;RELEASE;NETSTANDARD;SIGN</DefineConstants>
27+
<DefineConstants>TRACE;RELEASE;NETSTANDARD;SIGN;$(TestCoverage)</DefineConstants>
2828
</PropertyGroup>
2929

3030
<!-- Resources -->
@@ -34,8 +34,6 @@
3434
<AutoGen>true</AutoGen>
3535
<DependentUpon>Resources.resx</DependentUpon>
3636
</Compile>
37-
<!-- include shared source code -->
38-
<Compile Include="$(MSBuildThisFileDirectory)shared\*.cs" />
3937
</ItemGroup>
4038

4139
<ItemGroup>
@@ -53,4 +51,4 @@
5351
<None Update="*.ps1xml" CopyToOutputDirectory="PreserveNewest" />
5452
</ItemGroup>
5553

56-
</Project>
54+
</Project>

src/shared/ConfigKeys.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ internal static class ConfigKeys
3131
public const string EnableTestCoverage = "EnableTestCoverage";
3232
public const string EnableLoginByWam = "EnableLoginByWam";
3333
public const string TestCoverageLocation = "TestCoverageLocation";
34+
public const string DisplayRegionIdentified = "DisplayRegionIdentified";
3435
}
3536
}

tools/Az.Tools.Predictor/Az.Tools.Predictor.Test/AzPredictorServiceTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ public void VerifyNoPrediction(string userInput)
229229
Assert.Equal(0, actual.Count);
230230

231231
actual = this._noPredictorService.GetSuggestion(predictionContext, 1, 1, CancellationToken.None);
232-
Assert.Null(actual);
232+
Assert.Empty(actual.PredictiveSuggestions);
233233
}
234234

235235
/// <summary>

tools/Az.Tools.Predictor/Az.Tools.Predictor.Test/AzPredictorTelemetryTests.cs

Lines changed: 67 additions & 28 deletions
Large diffs are not rendered by default.

tools/Az.Tools.Predictor/Az.Tools.Predictor.Test/CommandLineTests.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,20 @@ public void VerifyUnescapingText(string expected, string input)
5959
[InlineData("Get-AzResourceGroup -Location:*** -Name ***", "Get-AzResourceGroup -Name Test -Location:WestUS2")]
6060
// skip the positional parameter
6161
[InlineData("Get-AzResourceGroup -Location:***", "Get-AzResourceGroup Test -Location:WestUS2")]
62+
[InlineData("Get-AzResourceGroup", "Get-AzResourceGroup Test WestUS2")]
63+
// Take the last command in a pipe
64+
[InlineData("Set-AzContext", "$context | Set-AzContext")]
65+
// Take the command at the right of assignment
66+
[InlineData("Get-AzRoleAssignment -ObjectId ***", "$a=Get-AzRoleAssignment -ObjectId xxx")]
67+
// Take the command inside parentheses
68+
[InlineData("Get-AzRoleAssignment -ObjectId ***", "Remove-AzRoleAssignment -RoleDefinitionId (Get-AzRoleAssignment -ObjectId xxx")]
6269
[InlineData("git", "git status")]
6370
[InlineData("customCommand -Parameter ***", "customCommand -Parameter Value")]
6471
[InlineData("customCommand", "customCommand /Parameter Value")]
6572
[InlineData("customCommand", "customCommand --Parameter Value")]
6673
public void VerifyMaskCommandLine(string expected, string input)
6774
{
68-
var asts = Parser.ParseInput(input, out _, out _);
69-
var allNestedAsts = asts?.FindAll((ast) => ast is CommandAst, true);
70-
var commandAst = allNestedAsts?.LastOrDefault() as CommandAst;
71-
72-
string maskedCommandLine = CommandLineUtilities.MaskCommandLine(commandAst);
75+
string maskedCommandLine = CommandLineUtilities.MaskCommandLine(input);
7376

7477
Assert.Equal(expected, maskedCommandLine);
7578
}
@@ -82,7 +85,7 @@ public void VerifyMaskCommandLine(string expected, string input)
8285
[InlineData("Set-AzContext -Subscription 'xxxx-xxxx-xxxx-xxxx' -Tenant {String}", null)]
8386
[InlineData("Set-AzContext -Subscription $subscription -Tenant [[String]]", null)]
8487
[InlineData("Set-AzContext -Subscription 'xxxx-xxxx-xxxx-xxxx' -Tenant TenantName", null)]
85-
[InlineData("Get-AzContext | Set-AzContext", "Get-AzContext")]
88+
[InlineData("Get-AzContext | Set-AzContext", "Set-AzContext")]
8689
public void VerifyGetCommandAst(string input, string expected)
8790
{
8891
if (expected == null)

tools/Az.Tools.Predictor/Az.Tools.Predictor.Test/Mocks/MockAzPredictorService.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15+
using System;
1516
using System.Collections.Generic;
1617
using System.Management.Automation.Language;
1718
using System.Management.Automation.Subsystem.Prediction;
@@ -71,8 +72,8 @@ public MockAzPredictorService(string history, IList<PredictiveCommand> suggestio
7172
}
7273
}
7374

74-
/// <inheritdoc/>
75-
public override bool IsSupportedCommand(string cmd) => IsRecognizedCommand(cmd);
75+
// <inheritdoc/>
76+
// public override bool IsSupportedCommand(string cmd) => IsRecognizedCommand(cmd) || cmd.IndexOf(AzPredictorConstants.AzCommandMoniker, StringComparison.OrdinalIgnoreCase) > 0;
7677

7778
/// <inheritdoc/>
7879
public override Task<bool?> RequestPredictionsAsync(IEnumerable<string> commands, string requestId, CancellationToken cancellationToken)

tools/Az.Tools.Predictor/Az.Tools.Predictor/AzContext.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public Version ModuleVersion
127127
}
128128

129129
/// <inheritdoc/>
130-
public bool IsInternal { get; internal set; }
130+
public bool IsInternal { get; private set; }
131131

132132
public AzContext(IPowerShellRuntime powerShellRuntime) => _powerShellRuntime
133133
= powerShellRuntime;
@@ -138,11 +138,7 @@ public void UpdateContext()
138138
AzVersion = GetAzVersion();
139139
RawUserId = GetUserAccountId();
140140
HashUserId = GenerateSha256HashString(RawUserId);
141-
142-
if (!IsInternal)
143-
{
144-
IsInternal = RawUserId.EndsWith(AzContext.InternalUserSuffix, StringComparison.OrdinalIgnoreCase);
145-
}
141+
IsInternal = RawUserId.EndsWith(AzContext.InternalUserSuffix, StringComparison.OrdinalIgnoreCase);
146142
}
147143

148144
internal string RawUserId { get; set; }

tools/Az.Tools.Predictor/Az.Tools.Predictor/AzPredictor.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,7 @@ public AzPredictor()
9393
Task.Run(() =>
9494
{
9595
_settings = Settings.GetSettings();
96-
_azContext = new AzContext(_powerShellRuntime)
97-
{
98-
IsInternal = (_settings.SetAsInternal == true) ? true : false,
99-
};
96+
_azContext = new AzContext(_powerShellRuntime);
10097

10198
_azContext.UpdateContext();
10299
// This will run the script in the right context.
@@ -279,7 +276,13 @@ public void OnCommandLineExecuted(PredictionClient client, string commandLine, b
279276
parsedResult = GetAstAndMaskedCommandLine(commandLine);
280277
}
281278

282-
_telemetryClient.OnHistory(new HistoryTelemetryData(client, parsedResult.MaskedCommandLine ?? AzPredictorConstants.CommandPlaceholder, success));
279+
// We only collect the masked command line when the command is supported.
280+
// This is to avoid the case when the user copies and pasted some sensitive data into the command line.
281+
282+
var collectedCommandLine = parsedResult.IsSupported ?
283+
parsedResult.MaskedCommandLine ?? AzPredictorConstants.CommandPlaceholder :
284+
AzPredictorConstants.CommandPlaceholder;
285+
_telemetryClient.OnHistory(new HistoryTelemetryData(client, collectedCommandLine, success));
283286
_commandLineExecutedCompletion?.SetResult();
284287
});
285288

@@ -315,7 +318,10 @@ public SuggestionPackage GetSuggestion(PredictionClient client, PredictionContex
315318
}
316319
finally
317320
{
318-
_telemetryClient.OnGetSuggestion(new GetSuggestionTelemetryData(client, localSuggestionSessionId, context.InputAst,
321+
_telemetryClient.OnGetSuggestion(new GetSuggestionTelemetryData(client,
322+
localSuggestionSessionId,
323+
suggestions?.CommandAst,
324+
_service.IsSupportedCommand(suggestions?.CommandAst?.GetCommandName()),
319325
suggestions,
320326
cancellationToken.IsCancellationRequested,
321327
exception));

tools/Az.Tools.Predictor/Az.Tools.Predictor/AzPredictorService.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,16 +160,21 @@ public virtual CommandLineSuggestion GetSuggestion(PredictionContext context, in
160160
}
161161
}
162162

163+
CommandLineSuggestion earlyReturnResult = new()
164+
{
165+
CommandAst = commandAst
166+
};
167+
163168
if (commandAst == null)
164169
{
165-
return null;
170+
return earlyReturnResult;
166171
}
167172

168173
var commandName = commandAst.GetCommandName();
169174

170175
if (string.IsNullOrWhiteSpace(commandName))
171176
{
172-
return null;
177+
return earlyReturnResult;
173178
}
174179

175180
ParameterSet inputParameterSet = null;
@@ -182,7 +187,7 @@ public virtual CommandLineSuggestion GetSuggestion(PredictionContext context, in
182187
{
183188
// We only ignore the exception when the command name is not supported.
184189
// We want to collect the telemetry about the exception how common it is for the format we don't support.
185-
return null;
190+
return earlyReturnResult;
186191
}
187192

188193
cancellationToken.ThrowIfCancellationRequested();
@@ -250,6 +255,13 @@ public virtual CommandLineSuggestion GetSuggestion(PredictionContext context, in
250255
}
251256
}
252257

258+
if (result is null)
259+
{
260+
result = new CommandLineSuggestion();
261+
}
262+
263+
result.CommandAst = commandAst;
264+
253265
return result;
254266
}
255267

@@ -324,8 +336,10 @@ public virtual void RecordHistory(CommandAst history) =>
324336

325337
/// <inheritdoc/>
326338
public virtual bool IsSupportedCommand(string cmd) => IsRecognizedCommand(cmd)
327-
&& !_surveyCmdlets.Any(cmdlet => cmdlet.Command.StartsWith(cmd, StringComparison.OrdinalIgnoreCase)) // the survey cmdlets aren't in the normal az command flow, so mark them as unsupported.
328-
&& cmd.IndexOf(AzPredictorConstants.AzCommandMoniker) > 0; // This is the Az cmdlet.
339+
|| (!string.IsNullOrWhiteSpace(cmd)
340+
&& !_surveyCmdlets.Any(cmdlet => cmdlet.Command.StartsWith(cmd, StringComparison.OrdinalIgnoreCase)) // the survey cmdlets aren't in the normal az command flow, so mark them as unsupported.
341+
&& cmd.IndexOf(AzPredictorConstants.AzCommandMoniker, StringComparison.OrdinalIgnoreCase) > 0 // This is the Az cmdlet.
342+
);
329343

330344
/// <summary>
331345
/// Checks whether the given <paramref name="cmd" /> is in the command list.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"maxAllowedCommandDuplicate": 1,
33
"serviceUri": "https://app.aladdin.microsoft.com/api/v2.0",
4-
"setAsInternal": false,
54
"suggestionCount": 7
65
}

tools/Az.Tools.Predictor/Az.Tools.Predictor/CommandLineSuggestion.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using Microsoft.Azure.PowerShell.Tools.AzPredictor.Utilities;
1616
using System;
1717
using System.Collections.Generic;
18+
using System.Management.Automation.Language;
1819
using System.Management.Automation.Subsystem.Prediction;
1920

2021
namespace Microsoft.Azure.PowerShell.Tools.AzPredictor
@@ -25,7 +26,7 @@ namespace Microsoft.Azure.PowerShell.Tools.AzPredictor
2526
/// <remarks>
2627
/// Because the performance requirement in <see cref="AzPredictor.GetSuggestion"/>,
2728
/// it contains lists of each piece of information, for example, a collection of predictive suggestion and a list of
28-
/// suggestion sources. Note that the count of each list should be the same. And each element in the list corresonds to
29+
/// suggestion sources. Note that the count of each list should be the same. And each element in the list corresponds to
2930
/// the element in other list at the same index.
3031
/// </remarks>
3132
public sealed class CommandLineSuggestion
@@ -38,6 +39,11 @@ public sealed class CommandLineSuggestion
3839

3940
private readonly List<PredictiveSuggestion> _predictiveSuggestions = new List<PredictiveSuggestion>(CommandLineSuggestion.CollectionDefaultCapacity);
4041

42+
/// <summary>
43+
/// Gets or sets the AST the suggestions are provided for. Note this is not always the same as the whole user input.
44+
/// </summary>
45+
public CommandAst CommandAst { get; set; }
46+
4147
/// <summary>
4248
/// Gets the suggestions returned to show to the user. This can be adjusted from <see cref="SourceTexts"/> based on
4349
/// the user input.

tools/Az.Tools.Predictor/Az.Tools.Predictor/Commands/BasePSCmdlet.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,7 @@ protected override void EndProcessing()
3737
TelemetryClient telemetryClient = TelemetryUtilities.CreateApplicationInsightTelemetryClient();
3838
var settings = Settings.GetSettings();
3939
var nestedPowerShellRuntime = new PowerShellRuntime();
40-
var azContext = new AzContext(nestedPowerShellRuntime)
41-
{
42-
IsInternal = (settings.SetAsInternal == true) ? true : false,
43-
};
40+
var azContext = new AzContext(nestedPowerShellRuntime);
4441

4542
var invocation = MyInvocation;
4643
var command = invocation.MyCommand;

tools/Az.Tools.Predictor/Az.Tools.Predictor/Commands/OpenAzPredictorSurvey.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ protected override void ProcessRecord()
4545
int minIdNumber = 0;
4646
int maxIdNumber = 1000000;
4747
// Format the integer into a 6-digit string, adding 0 to the left if needed, e.g. 123 -> "000123", 123456 -> "123456".
48-
// See https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings
48+
// See https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings
4949
var surveyId = random.Next(minIdNumber, maxIdNumber).ToString("D6", CultureInfo.InvariantCulture);
5050

5151
var link = string.Format(OpenAzPredictorSurvey._SurveyLinkFormat, surveyId, CultureInfo.InvariantCulture);

tools/Az.Tools.Predictor/Az.Tools.Predictor/IAzPredictorService.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public interface IAzPredictorService
3232
/// <param name="suggestionCount">The number of suggestion to return.</param>
3333
/// <param name="cancellationToken">The cancellation token.</param>
3434
/// <param name="maxAllowedCommandDuplicate">The maximum amount of the same commnds in the list of predictions.</param>
35-
/// <returns>The suggestions for <paramref name="context"/>. The maximum number of suggestions is <paramref name="suggestionCount"/>. A null will be returned if there the user input context isn't valid/supported at all.</returns>
35+
/// <returns>The suggestions for <paramref name="context"/>. The maximum number of suggestions is <paramref name="suggestionCount"/>.</returns>
3636
public CommandLineSuggestion GetSuggestion(PredictionContext context, int suggestionCount, int maxAllowedCommandDuplicate, CancellationToken cancellationToken);
3737

3838
/// <summary>
@@ -51,8 +51,8 @@ public interface IAzPredictorService
5151
public void RecordHistory(CommandAst history);
5252

5353
/// <summary>
54-
/// Return true if command is part of known set of Az cmdlets, false otherwise.
54+
/// Return true if command of the name is part of known set of Az cmdlets, false otherwise.
5555
/// </summary>
56-
public bool IsSupportedCommand(string cmd);
56+
public bool IsSupportedCommand(string commandName);
5757
}
5858
}

tools/Az.Tools.Predictor/Az.Tools.Predictor/Telemetry/AzPredictorTelemetryClient.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,14 +303,14 @@ protected void SendAggregatedTelemetryData()
303303

304304
if (suggestions.Count > 0)
305305
{
306-
properties.Add("Suggestion", JsonSerializer.Serialize(suggestions, JsonUtilities.TelemetrySerializerOptions));
306+
properties.Add(GetSuggestionTelemetryData.PropertyNamePrediction, JsonSerializer.Serialize(suggestions, JsonUtilities.TelemetrySerializerOptions));
307307
}
308308

309309
if (aggregatedData.CommandLine != null)
310310
{
311311
// Add the command history data.
312312
properties.Add(HistoryTelemetryData.PropertyNameSuccess, aggregatedData.IsCommandSuccess.ToString(CultureInfo.InvariantCulture));
313-
properties.Add(HistoryTelemetryData.PropertyNameHistory, aggregatedData.CommandLine);
313+
properties.Add(HistoryTelemetryData.PropertyNameCommand, aggregatedData.CommandLine);
314314
}
315315

316316
SendTelemetry($"{TelemetryUtilities.TelemetryEventPrefix}/Aggregation", properties);
@@ -321,6 +321,12 @@ protected void SendAggregatedTelemetryData()
321321
/// </summary>
322322
protected virtual void SendTelemetry(string eventName, IDictionary<string, string> properties)
323323
{
324+
if (this._azContext.IsInternal)
325+
{
326+
// To better filter internal telemetry, we append "_INTERNAL" to the event name.
327+
eventName = eventName + "_INTERNAL";
328+
}
329+
324330
_telemetryClient.TrackEvent(eventName, properties);
325331
}
326332

@@ -442,7 +448,9 @@ private void ProcessTelemetryData(GetSuggestionTelemetryData telemetryData)
442448
}
443449
}
444450

445-
var maskedUserInput = CommandLineUtilities.MaskCommandLine(telemetryData.UserInput.FindAll((ast) => ast is CommandAst, true).LastOrDefault() as CommandAst);
451+
var maskedUserInput = telemetryData.IsSupported ?
452+
CommandLineUtilities.MaskCommandLine(CommandLineUtilities.GetCommandAst(telemetryData.UserInput)) :
453+
AzPredictorConstants.CommandPlaceholder;
446454

447455
var suggestionSession = new SuggestionSession()
448456
{
@@ -500,7 +508,7 @@ private void ProcessTelemetryData(SuggestionDisplayedTelemetryData telemetryData
500508
if (CachedAggregatedTelemetryData.EstimateSuggestionSessionSize >= AzPredictorTelemetryClient.MaxPropertyValueSizeWithBuffer)
501509
{
502510
suggestionSession = SendAggregateTelemetryDataDuringSuggestionCycle(telemetryData, telemetryData.SuggestionSessionId);
503-
suggestionSession.IsSuggestionComplete = false; // This continue from the previous suggestionsession. So mark it as incomplete.
511+
suggestionSession.IsSuggestionComplete = false; // This continue from the previous suggestion session. So mark it as incomplete.
504512
}
505513

506514
suggestionSession.DisplayMode = telemetryData.DisplayMode;

0 commit comments

Comments
 (0)