Skip to content

Commit 6c87ccf

Browse files
authored
Improve error handling and bug fix (#14033)
* Improve error handling and bug fix * Change literal string to constant per change in Common assembly * Fix build error * Code refactoring
1 parent 7cbd0d2 commit 6c87ccf

25 files changed

+481
-219
lines changed

src/Aks/Aks.sln

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
21
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 15
4-
VisualStudioVersion = 15.0.27703.2035
2+
# Visual Studio Version 16
3+
VisualStudioVersion = 16.0.30804.86
54
MinimumVisualStudioVersion = 10.0.40219.1
65
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aks", "Aks\Aks.csproj", "{8058D403-06E3-4BED-8924-D166CE303961}"
76
EndProject
@@ -39,6 +38,10 @@ Global
3938
{142D7B0B-388A-4CEB-A228-7F6D423C5C2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
4039
{142D7B0B-388A-4CEB-A228-7F6D423C5C2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
4140
{142D7B0B-388A-4CEB-A228-7F6D423C5C2E}.Release|Any CPU.Build.0 = Release|Any CPU
41+
{6BD6B80A-06AF-4B5B-9230-69CCFC6C8D64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42+
{6BD6B80A-06AF-4B5B-9230-69CCFC6C8D64}.Debug|Any CPU.Build.0 = Debug|Any CPU
43+
{6BD6B80A-06AF-4B5B-9230-69CCFC6C8D64}.Release|Any CPU.ActiveCfg = Release|Any CPU
44+
{6BD6B80A-06AF-4B5B-9230-69CCFC6C8D64}.Release|Any CPU.Build.0 = Release|Any CPU
4245
{FF81DC73-B8EC-4082-8841-4FBF2B16E7CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
4346
{FF81DC73-B8EC-4082-8841-4FBF2B16E7CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
4447
{FF81DC73-B8EC-4082-8841-4FBF2B16E7CE}.Release|Any CPU.ActiveCfg = Release|Any CPU

src/Aks/Aks/ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
- Additional information about change #1
1919
-->
2020
## Upcoming Release
21+
* Refined error messages of cmdlet failure.
22+
* Upgraded exception handling to use Azure PowerShell related exceptions.
23+
* Fixed the issue that user could not use provided service principal to create Kubernetes cluster. [#13938]
2124

2225
## Version 2.0.1
2326
* Fixed the issue that user cannot use service principal to create a new Kubernetes cluster. [#13012]

src/Aks/Aks/Commands/Constants.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,9 @@ public static class Constants
4141
};
4242
public const string AddOnNameMonitoring = "Monitoring";
4343
public const string AddOnNameVirtualNode = "VirtualNode";
44+
45+
internal const string DotNetApiParameterResourceGroupName = "resourceGroupName";
46+
internal const string DotNetApiParameterResourceName = "resourceName";
47+
internal const string DotNetApiParameterAgentPoolName = "agentPoolName";
4448
}
4549
}

src/Aks/Aks/Commands/CreateOrUpdateKubeBase.cs

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
using Microsoft.Rest.Azure.OData;
3939
using Microsoft.Azure.Management.Internal.Resources.Models;
4040
using Microsoft.WindowsAzure.Commands.Common.CustomAttributes;
41+
using Microsoft.Azure.Commands.Common.Exceptions;
42+
using Microsoft.WindowsAzure.Commands.Common;
4143

4244
namespace Microsoft.Azure.Commands.Aks
4345
{
@@ -150,7 +152,7 @@ protected virtual ManagedCluster BuildNewCluster()
150152
new ContainerServiceLinuxProfile(LinuxProfileAdminUserName,
151153
new ContainerServiceSshConfiguration(pubKey));
152154

153-
var acsServicePrincipal = EnsureServicePrincipal(ServicePrincipalIdAndSecret?.UserName, ServicePrincipalIdAndSecret?.Password?.ToString());
155+
var acsServicePrincipal = EnsureServicePrincipal(ServicePrincipalIdAndSecret?.UserName, ServicePrincipalIdAndSecret?.Password?.ConvertToString());
154156

155157
var spProfile = new ManagedClusterServicePrincipalProfile(
156158
acsServicePrincipal.SpId,
@@ -218,8 +220,6 @@ protected void BeforeBuildNewCluster()
218220
/// <exception cref="ArgumentException">The SSH key or file argument was null and there was no default pub key in path.</exception>
219221
protected string GetSshKey(string sshKeyOrFile)
220222
{
221-
const string helpLink = "https://docs.microsoft.com/en-us/azure/virtual-machines/linux/mac-create-ssh-keys";
222-
223223
// SSH key was specified as either a file or as key data
224224
if (!string.IsNullOrEmpty(SshKeyValue))
225225
{
@@ -237,7 +237,8 @@ protected string GetSshKey(string sshKeyOrFile)
237237
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".ssh", "id_rsa.pub");
238238
if (!AzureSession.Instance.DataStore.FileExists(path))
239239
{
240-
throw new ArgumentException(string.Format(Resources.CouldNotFindSshPublicKeyInError, path, helpLink));
240+
var errorMessage = string.Format(Resources.CouldNotFindSshPublicKeyInError, path);
241+
throw new AzPSArgumentException(errorMessage, nameof(SshKeyValue));
241242
}
242243

243244
WriteVerbose(string.Format(Resources.FetchSshPublicKeyFromFile, path));
@@ -248,12 +249,22 @@ protected string GetSshKey(string sshKeyOrFile)
248249

249250
protected AcsServicePrincipal EnsureServicePrincipal(string spId = null, string clientSecret = null)
250251
{
252+
//If user specifies service principal, just use it directly and no need to save to disk
253+
if(!string.IsNullOrEmpty(spId) && !string.IsNullOrEmpty(clientSecret))
254+
{
255+
return new AcsServicePrincipal()
256+
{
257+
SpId = spId,
258+
ClientSecret = clientSecret
259+
};
260+
}
261+
251262
var acsServicePrincipal = LoadServicePrincipal();
252263
if (acsServicePrincipal == null)
253264
{
254-
WriteVerbose(string.Format(
265+
WriteWarning(string.Format(
255266
Resources.NoServicePrincipalFoundCreatingANewServicePrincipal,
256-
AcsSpFilePath));
267+
AcsSpFilePath, DefaultContext.Subscription.Id));
257268

258269
// if nothing to load, make one
259270
if (clientSecret == null)
@@ -296,14 +307,16 @@ private AcsServicePrincipal BuildServicePrincipal(string name, string url, strin
296307

297308
if (!success)
298309
{
299-
throw new CmdletInvocationException(Resources.CouldNotCreateAServicePrincipalWithTheRightPermissionsAreYouAnOwner);
310+
throw new AzPSInvalidOperationException(
311+
Resources.CouldNotCreateAServicePrincipalWithTheRightPermissionsAreYouAnOwner,
312+
desensitizedMessage: Resources.CouldNotCreateAServicePrincipalWithTheRightPermissionsAreYouAnOwner);
300313
}
301314

302315
AddSubscriptionRoleAssignment("Contributor", sp.ObjectId);
303316
return new AcsServicePrincipal { SpId = app.AppId, ClientSecret = clientSecret, ObjectId = app.ObjectId };
304317
}
305318

306-
protected void AddAcrRoleAssignment(string acrName, AcsServicePrincipal acsServicePrincipal)
319+
protected void AddAcrRoleAssignment(string acrName, string acrParameterName, AcsServicePrincipal acsServicePrincipal)
307320
{
308321
string acrResourceId = null;
309322
try
@@ -313,9 +326,12 @@ protected void AddAcrRoleAssignment(string acrName, AcsServicePrincipal acsServi
313326
var acrObjects = RmClient.Resources.List(acrQuery);
314327
acrResourceId = acrObjects.First().Id;
315328
}
316-
catch(Exception ex)
329+
catch(Exception)
317330
{
318-
throw new CmdletInvocationException(string.Format(Resources.CouldNotFindSpecifiedAcr, acrName), ex);
331+
throw new AzPSArgumentException(
332+
string.Format(Resources.CouldNotFindSpecifiedAcr, acrName),
333+
acrParameterName,
334+
string.Format(Resources.CouldNotFindSpecifiedAcr, "*"));
319335
}
320336

321337
var roleId = GetRoleId("acrpull", acrResourceId);
@@ -331,7 +347,10 @@ protected void AddAcrRoleAssignment(string acrName, AcsServicePrincipal acsServi
331347
}
332348
catch(Exception ex)
333349
{
334-
throw new CmdletInvocationException(string.Format(Resources.CouldNotFindObjectIdForServicePrincipal, acsServicePrincipal.SpId), ex);
350+
throw new AzPSInvalidOperationException(
351+
string.Format(Resources.CouldNotFindObjectIdForServicePrincipal, acsServicePrincipal.SpId),
352+
ex,
353+
string.Format(Resources.CouldNotFindObjectIdForServicePrincipal,"*"));
335354
}
336355
}
337356
var success = RetryAction(() =>
@@ -342,8 +361,9 @@ protected void AddAcrRoleAssignment(string acrName, AcsServicePrincipal acsServi
342361

343362
if (!success)
344363
{
345-
throw new CmdletInvocationException(
346-
Resources.CouldNotAddAcrRoleAssignment);
364+
throw new AzPSInvalidOperationException(
365+
Resources.CouldNotAddAcrRoleAssignment,
366+
desensitizedMessage: Resources.CouldNotAddAcrRoleAssignment);
347367
}
348368
}
349369

@@ -374,8 +394,9 @@ protected void AddSubscriptionRoleAssignment(string role, string appId)
374394

375395
if (!success)
376396
{
377-
throw new CmdletInvocationException(
378-
Resources.CouldNotCreateAServicePrincipalWithTheRightPermissionsAreYouAnOwner);
397+
throw new AzPSInvalidOperationException(
398+
Resources.CouldNotAssignServicePrincipalWithSubsContributorPermission,
399+
desensitizedMessage: Resources.CouldNotAssignServicePrincipalWithSubsContributorPermission);
379400
}
380401
}
381402

@@ -407,7 +428,11 @@ protected bool RetryAction(Action action, string actionName = null)
407428
protected AcsServicePrincipal LoadServicePrincipal()
408429
{
409430
var config = LoadServicePrincipals();
410-
return config?[DefaultContext.Subscription.Id];
431+
if(config?.ContainsKey(DefaultContext.Subscription.Id) == true)
432+
{
433+
return config[DefaultContext.Subscription.Id];
434+
}
435+
return null;
411436
}
412437

413438
protected Dictionary<string, AcsServicePrincipal> LoadServicePrincipals()

src/Aks/Aks/Commands/DisableAzureRmAddons.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,15 @@
1313
// ----------------------------------------------------------------------------------
1414

1515

16+
using System.Collections.Generic;
17+
using System.Management.Automation;
18+
1619
using Microsoft.Azure.Commands.Aks.Models;
1720
using Microsoft.Azure.Commands.Aks.Properties;
18-
using Microsoft.Azure.Commands.Aks.Utils;
21+
using Microsoft.Azure.Commands.Common.Exceptions;
1922
using Microsoft.Azure.Management.ContainerService.Models;
2023
using Microsoft.WindowsAzure.Commands.Utilities.Common;
2124

22-
using System;
23-
using System.Collections.Generic;
24-
using System.Management.Automation;
25-
using System.Runtime.ExceptionServices;
26-
using System.Text;
27-
2825
namespace Microsoft.Azure.Commands.Aks.Commands
2926
{
3027
[Cmdlet(VerbsLifecycle.Disable, ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "AksAddOn", DefaultParameterSetName = DefaultParamSet, SupportsShouldProcess = true)]
@@ -38,11 +35,13 @@ protected override IDictionary<string, ManagedClusterAddonProfile> UpdateAddonsP
3835
string addonServiceName = Constants.AddOnUserReadNameToServiceNameMapper.GetValueOrDefault(addOn, null);
3936
if (addonServiceName == null)
4037
{
41-
throw new ArgumentException(string.Format(Resources.AddonNotDefined, addOn));
38+
var errorMessage = string.Format(Resources.AddonNotDefined, addOn, string.Join(",", Constants.AddOnUserReadNameToServiceNameMapper.Keys));
39+
throw new AzPSArgumentException(errorMessage, nameof(Name), desensitizedMessage: errorMessage);
4240
}
4341
if (!addonProfiles.ContainsKey(addonServiceName))
4442
{
45-
throw new ArgumentException(string.Format(Resources.AddonIsNotInstalled, addOn));
43+
var errorMessage = string.Format(Resources.AddonIsNotInstalled, addOn);
44+
throw new AzPSArgumentException(errorMessage, nameof(Name), desensitizedMessage: errorMessage);
4645
}
4746
ManagedClusterAddonProfile addonProfile = addonProfiles[addonServiceName];
4847
addonProfile.Config = null;

src/Aks/Aks/Commands/EnableAzureRmAddons.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,12 @@
1313
// ----------------------------------------------------------------------------------
1414

1515

16+
using System.Collections.Generic;
17+
using System.Management.Automation;
18+
1619
using Microsoft.Azure.Commands.Aks.Models;
17-
using Microsoft.Azure.Commands.Aks.Properties;
1820
using Microsoft.Azure.Commands.Aks.Utils;
1921
using Microsoft.Azure.Management.ContainerService.Models;
20-
using Microsoft.WindowsAzure.Commands.Utilities.Common;
21-
22-
using System;
23-
using System.Collections.Generic;
24-
using System.Management.Automation;
25-
using System.Text;
2622

2723
namespace Microsoft.Azure.Commands.Aks.Commands
2824
{
@@ -44,7 +40,7 @@ public class EnableAzureRmAddons : UpdateAddonsBase
4440

4541
protected override IDictionary<string, ManagedClusterAddonProfile> UpdateAddonsProfile(IDictionary<string, ManagedClusterAddonProfile> addonProfiles)
4642
{
47-
return AddonUtils.EnableAddonsProfile(addonProfiles, Name, WorkspaceResourceId, SubnetName);
43+
return AddonUtils.EnableAddonsProfile(addonProfiles, Name, nameof(Name), WorkspaceResourceId, nameof(WorkspaceResourceId), SubnetName, nameof(SubnetName));
4844
}
4945
}
5046
}

src/Aks/Aks/Commands/GetAzureRmAks.cs

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,17 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15-
using System;
15+
using System.Collections.Generic;
1616
using System.Linq;
1717
using System.Management.Automation;
1818

1919
using Microsoft.Azure.Commands.Aks.Models;
2020
using Microsoft.Azure.Commands.Aks.Properties;
21+
using Microsoft.Azure.Commands.Common.Exceptions;
2122
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
2223
using Microsoft.Azure.Management.ContainerService;
2324
using Microsoft.Azure.Management.Internal.Resources.Utilities.Models;
25+
using Microsoft.Rest;
2426
using Microsoft.WindowsAzure.Commands.Common.CustomAttributes;
2527

2628
namespace Microsoft.Azure.Commands.Aks
@@ -77,28 +79,42 @@ public override void ExecuteCmdlet()
7779

7880
RunCmdLet(() =>
7981
{
80-
switch (ParameterSetName)
82+
try
8183
{
82-
case NameParameterSet:
83-
var kubeCluster = Client.ManagedClusters.Get(ResourceGroupName, Name);
84-
WriteObject(PSMapper.Instance.Map<PSKubernetesCluster>(kubeCluster), true);
85-
break;
86-
case IdParameterSet:
87-
var resource = new ResourceIdentifier(Id);
88-
var idCluster = Client.ManagedClusters.Get(resource.ResourceGroupName, resource.ResourceName);
89-
WriteObject(PSMapper.Instance.Map<PSKubernetesCluster>(idCluster), true);
90-
break;
91-
case ResourceGroupParameterSet:
92-
var kubeClusterList = string.IsNullOrEmpty(ResourceGroupName)
93-
? ListPaged(() => Client.ManagedClusters.List(),
94-
nextPageLink => Client.ManagedClusters.ListNext(nextPageLink))
95-
: ListPaged(() => Client.ManagedClusters.ListByResourceGroup(ResourceGroupName),
96-
nextPageLink => Client.ManagedClusters.ListNext(nextPageLink));
84+
switch (ParameterSetName)
85+
{
86+
case NameParameterSet:
87+
var kubeCluster = Client.ManagedClusters.Get(ResourceGroupName, Name);
88+
WriteObject(PSMapper.Instance.Map<PSKubernetesCluster>(kubeCluster), true);
89+
break;
90+
case IdParameterSet:
91+
var resource = new ResourceIdentifier(Id);
92+
var idCluster = Client.ManagedClusters.Get(resource.ResourceGroupName, resource.ResourceName);
93+
WriteObject(PSMapper.Instance.Map<PSKubernetesCluster>(idCluster), true);
94+
break;
95+
case ResourceGroupParameterSet:
96+
var kubeClusterList = string.IsNullOrEmpty(ResourceGroupName)
97+
? ListPaged(() => Client.ManagedClusters.List(),
98+
nextPageLink => Client.ManagedClusters.ListNext(nextPageLink))
99+
: ListPaged(() => Client.ManagedClusters.ListByResourceGroup(ResourceGroupName),
100+
nextPageLink => Client.ManagedClusters.ListNext(nextPageLink));
97101

98-
WriteObject(kubeClusterList.Select(PSMapper.Instance.Map<PSKubernetesCluster>), true);
99-
break;
100-
default:
101-
throw new ArgumentException(Resources.ParameterSetError);
102+
WriteObject(kubeClusterList.Select(PSMapper.Instance.Map<PSKubernetesCluster>), true);
103+
break;
104+
default:
105+
throw new AzPSArgumentException(Resources.ParameterSetError, "InvalidParameterSet", null, Resources.ParameterSetError);
106+
}
107+
}
108+
catch (ValidationException e)
109+
{
110+
var sdkApiParameterMap = new Dictionary<string, CmdletParameterNameValuePair>()
111+
{
112+
{ Constants.DotNetApiParameterResourceGroupName, new CmdletParameterNameValuePair(nameof(ResourceGroupName), ResourceGroupName) },
113+
{ Constants.DotNetApiParameterResourceName, new CmdletParameterNameValuePair(nameof(Name), Name) },
114+
};
115+
116+
if (!HandleValidationException(e, sdkApiParameterMap))
117+
throw;
102118
}
103119
});
104120
}

0 commit comments

Comments
 (0)