Skip to content

Commit

Permalink
[COST-5820] Return Azure errors to UI (#5474)
Browse files Browse the repository at this point in the history
* [COST-5820] Azure - return raw error messages to UI where necessary

* clean up

* remove parsed Azure user facing error messages

* clean up unittest
  • Loading branch information
djnakabaale authored Feb 4, 2025
1 parent 6a609de commit 2018b47
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 91 deletions.
31 changes: 0 additions & 31 deletions koku/providers/provider_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,37 +99,6 @@ class ProviderErrors:
" and subscription ID or scope with export name. "
"Edit your Azure source to include these details."
)
AZURE_EXPIRED_CLIENT_SECRET_KEYS_MESSAGE = (
"The provided client secret keys for this source are expired. "
"In Azure, refresh your client secret and try again."
)
AZURE_CLIENT_SECRET_INCORRECT_MESSAGE = (
"A problem has been detected with the Azure client secret for this source. "
"Refer to the Microsoft Azure troubleshooting guide in the cost management documentation for details."
)
AZURE_INCORRECT_CLIENT_ID_MESSAGE = (
"The client ID was entered incorrectly for this source. Edit your Azure source and verify the client ID."
)
AZURE_INCORRECT_TENANT_ID_MESSAGE = (
"The tenant ID was entered incorrectly for this source. Edit your Azure source and verify the tenant ID."
)
AZURE_INCORRECT_RESOURCE_GROUP_MESSAGE = (
"The resource group was entered incorrectly for this source. "
"Edit your Azure source and verify the resource group."
)
AZURE_INCORRECT_STORAGE_ACCOUNT_MESSAGE = (
"The storage account was entered incorrectly for this source. "
"Edit your Azure source and verify the storage account."
)
AZURE_INCORRECT_SUBSCRIPTION_ID_MESSAGE = (
"The subscription ID was entered incorrectly for this source. "
"Edit your Azure source and verify the subscription ID."
)
AZURE_UNAUTHORIZED_MESSAGE = (
"Azure reported an authorization error. "
"In Azure, check the resource group, storage account, cost export scope, and service principal."
)
AZURE_GENERAL_CLIENT_ERROR_MESSAGE = "Azure client configuration error."
OCI_BUCKET_MISSING_MESSAGE = (
"Cost management requires an OCI bucket to store cost and usage reports. "
"Edit your OCI source to include the name of your OCI bucket."
Expand Down
22 changes: 0 additions & 22 deletions koku/sources/sources_error_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,6 @@ def __init__(self, error):
"""Initialize the message generator."""
self._error = error

def azure_client_errors(self, message):
"""Azure client error messages."""
scrubbed_message = ProviderErrors.AZURE_GENERAL_CLIENT_ERROR_MESSAGE
if any(test in message for test in ["http error: 401", "Authentication failed", "(401) Unauthorized"]):
scrubbed_message = ProviderErrors.AZURE_CLIENT_SECRET_INCORRECT_MESSAGE
if "AADSTS700016" in message:
scrubbed_message = ProviderErrors.AZURE_INCORRECT_CLIENT_ID_MESSAGE
if "AADSTS90002" in message:
scrubbed_message = ProviderErrors.AZURE_INCORRECT_TENANT_ID_MESSAGE
if "AADSTS7000222" in message:
scrubbed_message = ProviderErrors.AZURE_EXPIRED_CLIENT_SECRET_KEYS_MESSAGE
if "ResourceGroupNotFound" in message:
scrubbed_message = ProviderErrors.AZURE_INCORRECT_RESOURCE_GROUP_MESSAGE
if "ResourceNotFound" in message:
scrubbed_message = ProviderErrors.AZURE_INCORRECT_STORAGE_ACCOUNT_MESSAGE
if any(test in message for test in ["SubscriptionNotFound", "InvalidSubscriptionId"]):
scrubbed_message = ProviderErrors.AZURE_INCORRECT_SUBSCRIPTION_ID_MESSAGE
if any(test in message for test in ["RBACAccessDenied", "does not have authorization", "scope is invalid"]):
scrubbed_message = ProviderErrors.AZURE_UNAUTHORIZED_MESSAGE
return scrubbed_message

def aws_client_errors(self, message):
"""AWS client error messages."""
return ProviderErrors.AWS_ROLE_ARN_UNREACHABLE_MESSAGE
Expand All @@ -62,7 +41,6 @@ def general_errors(self, message):
def _display_string_function(self, key):
"""Return function to get user facing string."""
ui_function_map = {
ProviderErrors.AZURE_CLIENT_ERROR: self.azure_client_errors,
ProviderErrors.AWS_ROLE_ARN_UNREACHABLE: self.aws_client_errors,
ProviderErrors.AWS_BILLING_SOURCE_NOT_FOUND: self.aws_no_billing_source,
ProviderErrors.AWS_COMPRESSION_REPORT_CONFIG: self.aws_invalid_report_compression,
Expand Down
8 changes: 3 additions & 5 deletions koku/sources/test/api/test_source_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,11 +538,9 @@ def test_azure_unavailable(self, mock_client_credential):
)
response = client.get(url + "?source_id=1", **self.headers)
actual_source_status = response.data
expected = {
"availability_status": "unavailable",
"availability_status_error": ProviderErrors.AZURE_INCORRECT_SUBSCRIPTION_ID_MESSAGE,
}
self.assertEqual(actual_source_status, expected)

self.assertEqual(actual_source_status.get("availability_status"), "unavailable")
self.assertIn("SubscriptionNotFound", actual_source_status.get("availability_status_error"))

def test_ocp_unavailable(self):
"""Test that the API returns status when a source is configured correctly."""
Expand Down
46 changes: 13 additions & 33 deletions koku/sources/test/test_sources_error_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,51 +52,53 @@ def test_azure_errors(self):
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": ", AdalError: Get Token request returned http error: 401 and server response:",
"expected_message": ProviderErrors.AZURE_CLIENT_SECRET_INCORRECT_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": "Authentication failed",
"expected_message": ProviderErrors.AZURE_CLIENT_SECRET_INCORRECT_MESSAGE,
"internal_message": (
"(401) Unauthorized. Request ID: cca1a5a4-4107-4e7a-b3b4-b88f31e6a674\n"
"Code: 401\nMessage: Unauthorized. Request ID: cca1a5a4-4107-4e7a-b3b4-b88f31e6a674"
),
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": (
"(401) Unauthorized. Request ID: cca1a5a4-4107-4e7a-b3b4-b88f31e6a674\n"
"Code: 401\nMessage: Unauthorized. Request ID: cca1a5a4-4107-4e7a-b3b4-b88f31e6a674"
"The client 'xxxxx' with object id 'xxxxx' does not have authorization to perform action "
"'Microsoft.Storage/storageAccounts/listKeys/action' over scope "
"'/subscriptions/xxxxx/resourceGroups/xxxxx/providers/Microsoft.Storage/storageAccounts/xxxxx' "
"or the scope is invalid. If access was recently granted, please refresh your credentials."
),
"expected_message": ProviderErrors.AZURE_CLIENT_SECRET_INCORRECT_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": "'(RBACAccessDenied) The client does not have authorization to perform action.",
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": (
", AdalError: Get Token request returned http error: 400 and server response:"
' {"error":"invalid_request","error_description":"AADSTS90002: Tenant'
),
"expected_message": ProviderErrors.AZURE_INCORRECT_TENANT_ID_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": (
", AdalError: Get Token request returned http error: 400 and server response:"
' {"error":"unauthorized_client","error_description":"AADSTS700016:'
),
"expected_message": ProviderErrors.AZURE_INCORRECT_CLIENT_ID_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": (
"Authentication failed: AADSTS7000222: The provided client secret keys for app"
" '84ed5026-61c8-42a3-9511-74735a5c6be2' are expired."
),
"expected_message": ProviderErrors.AZURE_EXPIRED_CLIENT_SECRET_KEYS_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": (
"Azure Error: ResourceGroupNotFound\nMessage: Resource group" "'RG2' could not be found."
),
"expected_message": ProviderErrors.AZURE_INCORRECT_RESOURCE_GROUP_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
Expand All @@ -105,7 +107,6 @@ def test_azure_errors(self):
"Resource 'Microsoft.Storage/storageAccounts/mysa5' under "
"resource group 'RG1' was not found"
),
"expected_message": ProviderErrors.AZURE_INCORRECT_STORAGE_ACCOUNT_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
Expand All @@ -114,27 +115,6 @@ def test_azure_errors(self):
"subscription '2639de71-ca37-4a17-a104-17665a50e7fd'"
" could not be found."
),
"expected_message": ProviderErrors.AZURE_INCORRECT_SUBSCRIPTION_ID_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": "Random azure error",
"expected_message": ProviderErrors.AZURE_GENERAL_CLIENT_ERROR_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": (
"The client 'xxxxx' with object id 'xxxxx' does not have authorization to perform action "
"'Microsoft.Storage/storageAccounts/listKeys/action' over scope "
"'/subscriptions/xxxxx/resourceGroups/xxxxx/providers/Microsoft.Storage/storageAccounts/xxxxx' "
"or the scope is invalid. If access was recently granted, please refresh your credentials."
),
"expected_message": ProviderErrors.AZURE_UNAUTHORIZED_MESSAGE,
},
{
"key": ProviderErrors.AZURE_CLIENT_ERROR,
"internal_message": "'(RBACAccessDenied) The client does not have authorization to perform action.",
"expected_message": ProviderErrors.AZURE_UNAUTHORIZED_MESSAGE,
},
]
for test in test_matrix:
Expand All @@ -143,7 +123,7 @@ def test_azure_errors(self):
message = test.get("internal_message")
error = ValidationError(error_obj(key, message))
message_obj = SourcesErrorMessage(error)
self.assertEqual(message_obj.display(source_id=1), test.get("expected_message"))
self.assertEqual(message_obj.display(source_id=1), message)

def test_general_string_error(self):
"""Test general string error fallback."""
Expand Down

0 comments on commit 2018b47

Please sign in to comment.