From 525b3ea2c0e615d16ca955e1730971825f45d605 Mon Sep 17 00:00:00 2001 From: Alex Urbina <42731074+urbinaalex17@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:52:15 -0600 Subject: [PATCH] BRE-342 Implement retry mechanism with error handling to get secrets from KV (#329) * BRE-342 DEBUG: Print error message for debuging purposes * BRE-342 REFACTOR: Error message while downloading secret * BRE-342 ADD: retry mechanism with error handling for null/undefined responses in getSecretValue to prevent failures and retry up to 3 times with a delay * BRE-342 REFACTOR: Increase RETRY_DELAY * BRE-342 REFACTOR: Added retry logic to getSecretValue to handle both response and apiResult errors * BRE-342 REFACTOR: retry logic in getSecretValue by extracting repetitive code into a helper function for cleaner retries --- get-keyvault-secrets/lib/KeyVaultClient.js | 49 +++++++++++++++++----- get-keyvault-secrets/lib/KeyVaultHelper.js | 1 + 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/get-keyvault-secrets/lib/KeyVaultClient.js b/get-keyvault-secrets/lib/KeyVaultClient.js index 7128f6b4..8417d4ff 100644 --- a/get-keyvault-secrets/lib/KeyVaultClient.js +++ b/get-keyvault-secrets/lib/KeyVaultClient.js @@ -122,11 +122,25 @@ class KeyVaultClient extends AzureRestClient_1.ServiceClient { } })).then((apiResult) => callback(apiResult.error, apiResult.result), (error) => callback(error)); } - getSecretValue(secretName, callback) { + getSecretValue(secretName, callback, attempt = 1) { + const MAX_RETRY_ATTEMPTS = 3; // Define the maximum number of retry attempts + const RETRY_DELAY = 3000; // Define the delay between retries in milliseconds if (!callback) { core.debug("Callback Cannot Be Null"); throw new Error("Callback Cannot Be Null"); } + // Helper function to handle retries + const retryRequest = (reason) => { + if (attempt < MAX_RETRY_ATTEMPTS) { + core.debug(`Retrying... Attempt ${attempt + 1} due to: ${reason}`); + setTimeout(() => { + this.getSecretValue(secretName, callback, attempt + 1); // Retry the request + }, RETRY_DELAY); + } else { + callback(new Error(`${reason} after max retries`), null); // If max retries reached, pass the error + } + }; + // Create HTTP transport objects var httpRequest = { method: 'GET', @@ -136,17 +150,32 @@ class KeyVaultClient extends AzureRestClient_1.ServiceClient { }, [], this.apiVersion) }; this.invokeRequest(httpRequest).then((response) => __awaiter(this, void 0, void 0, function* () { - if (response.statusCode == 200) { - var result = response.body.value; - return new AzureRestClient_1.ApiResult(null, result); - } - else if (response.statusCode == 400) { - return new AzureRestClient_1.ApiResult('Get Secret Failed Because Of Invalid Characters', secretName); + try { + if (!response || response.statusCode == null) { + throw new Error("Response or statusCode is null"); + } + if (response.statusCode == 200) { + var result = response.body.value; + return new AzureRestClient_1.ApiResult(null, result); + } else if (response.statusCode == 400) { + return new AzureRestClient_1.ApiResult('Get Secret Failed Because Of Invalid Characters', secretName); + } else { + return new AzureRestClient_1.ApiResult((0, AzureRestClient_1.ToError)(response)); + } + } catch (error) { + retryRequest(error.message); // Retry on error } - else { - return new AzureRestClient_1.ApiResult((0, AzureRestClient_1.ToError)(response)); + })).then((apiResult) => { + if (apiResult && apiResult.error) { + retryRequest(apiResult.error.message); // Retry on apiResult error + } else if (apiResult && typeof apiResult.result !== 'undefined') { + callback(null, apiResult.result); // No error, pass the result + } else { + retryRequest("Unexpected result format"); // Retry on unexpected result format } - })).then((apiResult) => callback(apiResult.error, apiResult.result), (error) => callback(error)); + }, (error) => { + retryRequest(error.message); // Retry on promise rejection + }); } convertToAzureKeyVaults(result) { var listOfSecrets = []; diff --git a/get-keyvault-secrets/lib/KeyVaultHelper.js b/get-keyvault-secrets/lib/KeyVaultHelper.js index bb859098..95dbb051 100644 --- a/get-keyvault-secrets/lib/KeyVaultHelper.js +++ b/get-keyvault-secrets/lib/KeyVaultHelper.js @@ -106,6 +106,7 @@ class KeyVaultHelper { return new Promise((resolve, reject) => { this.keyVaultClient.getSecretValue(secretName, (error, secretValue) => { if (error) { + console.log(util.format("Error: %s", this.getError(error))); core.setFailed(util.format("Could not download the secret %s", secretName)); } else {