Skip to content

Commit 2ba5db3

Browse files
authored
Throw RequestFailedException for failed backup/restore (#41919)
* Throw RequestFailedException for failed backup/restore Fixes #41855 * Update release dates
1 parent 162774f commit 2ba5db3

File tree

7 files changed

+94
-7
lines changed

7 files changed

+94
-7
lines changed

sdk/keyvault/Azure.Security.KeyVault.Administration/CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Release History
22

3-
## 4.4.0 (2024-02-13)
3+
## 4.4.0 (2024-02-14)
44

55
Changes from both the last release and the last beta include:
66

@@ -10,6 +10,10 @@ Changes from both the last release and the last beta include:
1010
- The `sasToken` parameter is now optional in `KeyVaultBackupClient.StartRestore` and `StartRestoreAsync`. Managed Identity will be used instead if `sasToken` is null.
1111
- The `sasToken` parameter is now optional in `KeyVaultBackupClient.StartSelectiveKeyRestore` and `StartSelectiveKeyRestoreAsync`. Managed Identity will be used instead if `sasToken` is null.
1212

13+
### Breaking Changes
14+
15+
- `KeyVaultBackupOperation`, `KeyVaultRestoreOperation`, and `KeyVaultSelectiveKeyRestoreOperation` now throw a `RequestFailedException` with a different error message - but a raw `Response` with more details - when the service returns an error response. ([#41855](https://github.com/Azure/azure-sdk-for-net/issues/41855))
16+
1317
### Bugs Fixed
1418

1519
- When a Key Vault is moved to another tenant, the client is reauthenticated.

sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupOperation.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,12 @@ await _client.GetBackupDetailsAsync(Id, cancellationToken).ConfigureAwait(false)
151151
_requestFailedException = new RequestFailedException("Unexpected failure", ex);
152152
throw _requestFailedException;
153153
}
154+
154155
if (_value != null && _value.EndTime.HasValue && _value.Error != null)
155156
{
156-
_requestFailedException = new RequestFailedException($"{_value.Error.Message}\nInnerError: {_value.Error.InnerError}\nCode: {_value.Error.Code}");
157+
_requestFailedException = _response != null ?
158+
new RequestFailedException(_response)
159+
: new RequestFailedException($"{_value.Error.Message}\nInnerError: {_value.Error.InnerError}\nCode: {_value.Error.Code}");
157160
throw _requestFailedException;
158161
}
159162
}

sdk/keyvault/Azure.Security.KeyVault.Administration/src/RestoreOperationInternal.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ internal RestoreOperationInternal(TResponseType value, Response response, KeyVau
119119
};
120120

121121
/// <summary>
122-
/// The error value resturned by the service call.
122+
/// The error value returned by the service call.
123123
/// </summary>
124124
internal KeyVaultServiceError Error => _value switch
125125
{
@@ -215,9 +215,12 @@ await _client.GetSelectiveKeyRestoreDetailsAsync(Id, cancellationToken).Configur
215215
_requestFailedException = new RequestFailedException("Unexpected Failure.", ex);
216216
throw _requestFailedException;
217217
}
218+
218219
if (_value != null && EndTime.HasValue && Error?.Code != null)
219220
{
220-
_requestFailedException = new RequestFailedException($"{Error.Message}\nInnerError: {Error.InnerError}\nCode: {Error.Code}");
221+
_requestFailedException = _response != null ?
222+
new RequestFailedException(_response)
223+
: new RequestFailedException($"{Error.Message}\nInnerError: {Error.InnerError}\nCode: {Error.Code}");
221224
throw _requestFailedException;
222225
}
223226
}

sdk/keyvault/Azure.Security.KeyVault.Administration/tests/BackupOperationTests.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
// Licensed under the MIT License.
33

44
using System;
5+
using System.Text.Json;
56
using System.Threading;
7+
using Azure.Core.Serialization;
8+
using Azure.Core.TestFramework;
69
using Azure.Security.KeyVault.Administration.Models;
710
using Moq;
811
using NUnit.Framework;
@@ -120,5 +123,79 @@ public void ValueThrowsWhenOperationIsNotComplete()
120123
Assert.That(operation.StartTime, Is.EqualTo(incompleteBackup.StartTime));
121124
Assert.That(operation.EndTime, Is.EqualTo(incompleteBackup.EndTime));
122125
}
126+
127+
[Test(Description = "https://github.com/Azure/azure-sdk-for-net/issues/41855")]
128+
public void BackupOperationThrowsOnBadRequest()
129+
{
130+
const string jobId = "c79735efd41d4b8a8ef23634b7f3dd0d";
131+
var response = new MockResponse(200, "OK").WithJson($$"""
132+
{
133+
"endTime": 1704409031,
134+
"error": {
135+
"code": "BadRequest",
136+
"innererror": null,
137+
"message": "Invalid backup: Reason: Cannot read backup status document"
138+
},
139+
"jobId": "c79735efd41d4b8a8ef23634b7f3dd0d",
140+
"startTime": 1704409030,
141+
"status": "Failed",
142+
"statusDetails": "Invalid backup: Reason: Cannot read backup status document"
143+
}
144+
""");
145+
146+
using var doc = JsonDocument.Parse(response.Content.ToStream());
147+
var detail = FullBackupDetailsInternal.DeserializeFullBackupDetailsInternal(doc.RootElement);
148+
149+
var mockClient = new Mock<KeyVaultBackupClient>();
150+
mockClient
151+
.Setup(m => m.GetBackupDetails(It.IsAny<string>(), It.IsAny<CancellationToken>()))
152+
.Returns(Response.FromValue(detail, response));
153+
154+
var operation = new KeyVaultBackupOperation(mockClient.Object, jobId);
155+
var ex = Assert.Throws<RequestFailedException>(() => operation.WaitForCompletion());
156+
Assert.AreEqual(ex.Status, 200);
157+
158+
dynamic error = ex.GetRawResponse()?.Content.ToDynamicFromJson(JsonPropertyNames.UseExact).error;
159+
Assert.NotNull(error);
160+
Assert.AreEqual("BadRequest", (string)error.code);
161+
Assert.AreEqual("Invalid backup: Reason: Cannot read backup status document", (string)error.message);
162+
}
163+
164+
[Test(Description = "https://github.com/Azure/azure-sdk-for-net/issues/41855")]
165+
public void RestoreOperationThrowsOnBadRequest()
166+
{
167+
const string jobId = "c79735efd41d4b8a8ef23634b7f3dd0d";
168+
var response = new MockResponse(200, "OK").WithJson($$"""
169+
{
170+
"endTime": 1704409031,
171+
"error": {
172+
"code": "BadRequest",
173+
"innererror": null,
174+
"message": "Invalid backup: Reason: Cannot read backup status document"
175+
},
176+
"jobId": "c79735efd41d4b8a8ef23634b7f3dd0d",
177+
"startTime": 1704409030,
178+
"status": "Failed",
179+
"statusDetails": "Invalid backup: Reason: Cannot read backup status document"
180+
}
181+
""");
182+
183+
using var doc = JsonDocument.Parse(response.Content.ToStream());
184+
var detail = RestoreDetailsInternal.DeserializeRestoreDetailsInternal(doc.RootElement);
185+
186+
var mockClient = new Mock<KeyVaultBackupClient>();
187+
mockClient
188+
.Setup(m => m.GetRestoreDetails(It.IsAny<string>(), It.IsAny<CancellationToken>()))
189+
.Returns(Response.FromValue(detail, response));
190+
191+
var operation = new KeyVaultRestoreOperation(mockClient.Object, jobId);
192+
var ex = Assert.Throws<RequestFailedException>(() => operation.WaitForCompletion());
193+
Assert.AreEqual(ex.Status, 200);
194+
195+
dynamic error = ex.GetRawResponse()?.Content.ToDynamicFromJson(JsonPropertyNames.UseExact).error;
196+
Assert.NotNull(error);
197+
Assert.AreEqual("BadRequest", (string)error.code);
198+
Assert.AreEqual("Invalid backup: Reason: Cannot read backup status document", (string)error.message);
199+
}
123200
}
124201
}

sdk/keyvault/Azure.Security.KeyVault.Certificates/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Release History
22

3-
## 4.6.0 (2024-02-13)
3+
## 4.6.0 (2024-02-14)
44

55
Changes from both the last release and the last beta include:
66

sdk/keyvault/Azure.Security.KeyVault.Keys/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Release History
22

3-
## 4.6.0 (2024-02-13)
3+
## 4.6.0 (2024-02-14)
44

55
Changes from both the last release and the last beta include:
66

sdk/keyvault/Azure.Security.KeyVault.Secrets/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Release History
22

3-
## 4.6.0 (2024-02-13)
3+
## 4.6.0 (2024-02-14)
44

55
Changes from both the last release and the last beta include:
66

0 commit comments

Comments
 (0)