Skip to content

Commit 10d1fad

Browse files
thomhurstclaude
andauthored
fix: use specific exception types in ArmClientExtensions (#1578) (#1689)
Replace generic Exception throws with specific, descriptive exceptions: - AzureResourceNotFoundException: Thrown when a resource cannot be found in the resource group. Inherits from InvalidOperationException and includes the ResourceIdentifier for debugging. - UnsupportedAzureScopeException: Thrown when an unsupported scope type is encountered. Inherits from NotSupportedException and includes the Scope object for debugging. Added XML documentation for GetResourceIdentifierAsync explaining when each exception is thrown. Note: Issue #1574 (SuccessHttpHandler) was already fixed in commit 828c5b5 which removed the SuccessHttpHandler class entirely. Fixes #1578 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 1072365 commit 10d1fad

3 files changed

Lines changed: 89 additions & 3 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using ModularPipelines.Azure.Scopes;
2+
3+
namespace ModularPipelines.Azure.Exceptions;
4+
5+
/// <summary>
6+
/// Exception thrown when an Azure resource cannot be found.
7+
/// </summary>
8+
public class AzureResourceNotFoundException : InvalidOperationException
9+
{
10+
/// <summary>
11+
/// Gets the Azure resource identifier that was not found.
12+
/// </summary>
13+
public AzureResourceIdentifier ResourceIdentifier { get; }
14+
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="AzureResourceNotFoundException"/> class.
17+
/// </summary>
18+
/// <param name="resourceIdentifier">The Azure resource identifier that was not found.</param>
19+
public AzureResourceNotFoundException(AzureResourceIdentifier resourceIdentifier)
20+
: base($"Azure resource not found: {resourceIdentifier}")
21+
{
22+
ResourceIdentifier = resourceIdentifier;
23+
}
24+
25+
/// <summary>
26+
/// Initializes a new instance of the <see cref="AzureResourceNotFoundException"/> class.
27+
/// </summary>
28+
/// <param name="resourceIdentifier">The Azure resource identifier that was not found.</param>
29+
/// <param name="innerException">The inner exception that caused this exception.</param>
30+
public AzureResourceNotFoundException(AzureResourceIdentifier resourceIdentifier, Exception? innerException)
31+
: base($"Azure resource not found: {resourceIdentifier}", innerException)
32+
{
33+
ResourceIdentifier = resourceIdentifier;
34+
}
35+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using ModularPipelines.Azure.Scopes;
2+
3+
namespace ModularPipelines.Azure.Exceptions;
4+
5+
/// <summary>
6+
/// Exception thrown when an unsupported Azure scope type is encountered.
7+
/// </summary>
8+
public class UnsupportedAzureScopeException : NotSupportedException
9+
{
10+
/// <summary>
11+
/// Gets the Azure scope that is not supported.
12+
/// </summary>
13+
public AzureScope Scope { get; }
14+
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="UnsupportedAzureScopeException"/> class.
17+
/// </summary>
18+
/// <param name="scope">The Azure scope that is not supported.</param>
19+
public UnsupportedAzureScopeException(AzureScope scope)
20+
: base($"Unsupported Azure scope type: {scope.GetType().Name}. Scope value: {scope}")
21+
{
22+
Scope = scope;
23+
}
24+
25+
/// <summary>
26+
/// Initializes a new instance of the <see cref="UnsupportedAzureScopeException"/> class.
27+
/// </summary>
28+
/// <param name="scope">The Azure scope that is not supported.</param>
29+
/// <param name="innerException">The inner exception that caused this exception.</param>
30+
public UnsupportedAzureScopeException(AzureScope scope, Exception? innerException)
31+
: base($"Unsupported Azure scope type: {scope.GetType().Name}. Scope value: {scope}", innerException)
32+
{
33+
Scope = scope;
34+
}
35+
}

src/ModularPipelines.Azure/Extensions/ArmClientExtensions.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
using Azure.Core;
22
using Azure.ResourceManager;
3+
using ModularPipelines.Azure.Exceptions;
34
using ModularPipelines.Azure.Scopes;
45

56
namespace ModularPipelines.Azure.Extensions;
67

8+
/// <summary>
9+
/// Extension methods for <see cref="ArmClient"/>.
10+
/// </summary>
711
public static class ArmClientExtensions
812
{
13+
/// <summary>
14+
/// Gets the <see cref="ResourceIdentifier"/> for the specified Azure scope.
15+
/// </summary>
16+
/// <param name="armClient">The ARM client.</param>
17+
/// <param name="azureScope">The Azure scope to resolve.</param>
18+
/// <returns>The resolved <see cref="ResourceIdentifier"/>.</returns>
19+
/// <exception cref="AzureResourceNotFoundException">
20+
/// Thrown when the specified <see cref="AzureResourceIdentifier"/> cannot be found in the resource group.
21+
/// </exception>
22+
/// <exception cref="UnsupportedAzureScopeException">
23+
/// Thrown when the <paramref name="azureScope"/> is of an unsupported type.
24+
/// </exception>
925
public static async Task<ResourceIdentifier> GetResourceIdentifierAsync(this ArmClient armClient, AzureScope azureScope)
1026
{
1127
switch (azureScope)
@@ -26,7 +42,7 @@ public static async Task<ResourceIdentifier> GetResourceIdentifierAsync(this Arm
2642
}
2743
}
2844

29-
throw new Exception($"Unknown Resource: {azureResourceIdentifier}");
45+
throw new AzureResourceNotFoundException(azureResourceIdentifier);
3046
}
3147

3248
case AzureResourceGroupIdentifier azureResourceGroupIdentifier:
@@ -37,8 +53,8 @@ public static async Task<ResourceIdentifier> GetResourceIdentifierAsync(this Arm
3753
return azureManagementGroupIdentifier.ToManagementGroupIdentifier();
3854
default:
3955
{
40-
throw new Exception($"Unknown Resource: {azureScope}");
56+
throw new UnsupportedAzureScopeException(azureScope);
4157
}
4258
}
4359
}
44-
}
60+
}

0 commit comments

Comments
 (0)