Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[COST-5627] Fix Azure default extension issue #5394

Merged
merged 20 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
cd4d6e0
Making extension parameter optional.
bacciotti Nov 21, 2024
e8c6faf
Revert "Making extension parameter optional."
bacciotti Nov 21, 2024
2919b5a
Making extension parameter optional.
bacciotti Nov 21, 2024
9555319
Fixing unit tests.
bacciotti Nov 22, 2024
455da35
Merge branch 'main' into cost-5627-azure-does-not-change-default-exte…
bacciotti Nov 22, 2024
4c51cff
Creation of a unit tests.
bacciotti Nov 22, 2024
9954d47
Addressing comments.
bacciotti Nov 22, 2024
375c406
Merge branch 'main' into cost-5627-azure-does-not-change-default-exte…
bacciotti Nov 22, 2024
06edd15
Merge branch 'main' into cost-5627-azure-does-not-change-default-exte…
bacciotti Nov 25, 2024
0a297cd
Addressing comments.
bacciotti Nov 25, 2024
d50c602
Addressing comments.
bacciotti Nov 25, 2024
3ea5dff
Merge branch 'main' into cost-5627-azure-does-not-change-default-exte…
bacciotti Nov 26, 2024
4e76245
Merge branch 'main' into cost-5627-azure-does-not-change-default-exte…
bacciotti Nov 26, 2024
b4e28ac
Merge branch 'main' into cost-5627-azure-does-not-change-default-exte…
bacciotti Nov 27, 2024
318a1cb
switch debug log to info
lcouzens Nov 27, 2024
147ea9b
Merge branch 'main' into cost-5627-azure-does-not-change-default-exte…
bacciotti Nov 28, 2024
dac6cb8
Changing var name.
bacciotti Nov 28, 2024
ddcac24
Filters and extension checks removed.
bacciotti Nov 28, 2024
36b34f7
Quick fix.
bacciotti Nov 28, 2024
a689750
Merge branch 'main' into cost-5627-azure-does-not-change-default-exte…
lcouzens Nov 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,7 @@ def _get_manifest(self, date_time): # noqa: C901
manifest["reportKeys"] = [blob["blobName"] for blob in manifest_json["blobs"]]
else:
try:
blob = self._azure_client.get_latest_cost_export_for_path(
report_path, self.container_name, compression_mode
)
blob = self._azure_client.get_latest_cost_export_for_path(report_path, self.container_name)
except AzureCostReportNotFound as ex:
msg = f"Unable to find manifest. Error: {ex}"
LOG.info(log_json(self.tracing_id, msg=msg, context=self.context))
Expand Down
38 changes: 21 additions & 17 deletions koku/masu/external/downloader/azure/azure_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,35 @@ def __init__(
raise AzureServiceError("Azure Service credentials are not configured.")

def _get_latest_blob(
self, report_path: str, blobs: list[BlobProperties], extension: str
self, report_path: str, blobs: list[BlobProperties], extension: t.Optional[str] = None
lcouzens marked this conversation as resolved.
Show resolved Hide resolved
) -> t.Optional[BlobProperties]:
valid_extensions = [
AzureBlobExtension.csv.value,
AzureBlobExtension.gzip.value,
AzureBlobExtension.manifest.value,
]
if extension and extension not in valid_extensions:
raise ValueError(f"Invalid compression type: {extension}")
bacciotti marked this conversation as resolved.
Show resolved Hide resolved

latest_blob = None
for blob in blobs:
if not blob.name.endswith(extension):
continue
if extension:
if not blob.name.endswith(extension):
continue
else:
if not any(blob.name.endswith(ext) for ext in valid_extensions):
continue
bacciotti marked this conversation as resolved.
Show resolved Hide resolved

if report_path in blob.name and not latest_blob:
latest_blob = blob
elif report_path in blob.name and blob.last_modified > latest_blob.last_modified:
latest_blob = blob
if report_path in blob.name:
if not latest_blob or blob.last_modified > latest_blob.last_modified:
latest_blob = blob
return latest_blob

def _get_latest_blob_for_path(
self,
report_path: str,
container_name: str,
extension: str,
extension: t.Optional[str] = None,
) -> BlobProperties:
"""Get the latest file with the specified extension from given storage account container."""

Expand Down Expand Up @@ -120,10 +131,7 @@ def _get_latest_blob_for_path(

latest_report = self._get_latest_blob(report_path, blobs, extension)
if not latest_report:
bacciotti marked this conversation as resolved.
Show resolved Hide resolved
message = (
f"No file with extension '{extension}' found in container "
f"'{container_name}' for path '{report_path}'."
)
message = f"No file found in container " f"'{container_name}' for path '{report_path}'."
raise AzureCostReportNotFound(message)

return latest_report
Expand Down Expand Up @@ -159,7 +167,7 @@ def get_file_for_key(self, key: str, container_name: str) -> BlobProperties:
return report

def get_latest_cost_export_for_path(
self, report_path: str, container_name: str, compression: str
self, report_path: str, container_name: str, compression: t.Optional[str] = None
bacciotti marked this conversation as resolved.
Show resolved Hide resolved
) -> BlobProperties:
"""
Get the latest cost export for a given path and container based on the compression type.
Expand All @@ -176,10 +184,6 @@ def get_latest_cost_export_for_path(
ValueError: If the compression type is not 'gzip' or 'csv'.
AzureCostReportNotFound: If no blob is found for the given path and container.
"""
valid_compressions = [AzureBlobExtension.gzip.value, AzureBlobExtension.csv.value]
if compression not in valid_compressions:
raise ValueError(f"Invalid compression type: {compression}. Expected one of: {valid_compressions}.")

return self._get_latest_blob_for_path(report_path, container_name, compression)

def get_latest_manifest_for_path(self, report_path: str, container_name: str) -> BlobProperties:
Expand Down
19 changes: 16 additions & 3 deletions koku/masu/test/external/downloader/azure/test_azure_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,10 +508,8 @@ def test_azure_service_missing_credentials(self, mock_factory):
self.assertIn("Azure Service credentials are not configured.", str(context.exception))

@patch("masu.external.downloader.azure.azure_service.AzureClientFactory")
@patch.object(AzureService, "_get_latest_blob_for_path")
def test_get_latest_cost_export_for_path_invalid_compression(self, mock_get_latest_blob, mock_factory):
def test_get_latest_cost_export_for_path_invalid_compression(self, mock_factory):
"""Test when an invalid compression type is provided and ValueError is raised."""
mock_get_latest_blob.return_value = None
mock_factory.return_value.credentials = Mock()

service = AzureService(
Expand Down Expand Up @@ -677,3 +675,18 @@ def test_download_file_with_compression(self, mock_tempfile, mock_client_factory
self.assertTrue(result.endswith(".gz"))
mock_cloud_storage_account.get_blob_client.assert_called_with("fake_container", "fake_key.csv.gz")
mock_blob_client.download_blob.assert_called_once()

def test_get_latest_blob_no_extension_invalid_files(self):
"""Test that blobs with invalid extensions are ignored when no extension is specified."""
report_path = "/container/report/path"
blobs = (
FakeBlob(f"{report_path}/file01.csv", datetime(2022, 12, 16)),
FakeBlob(f"{report_path}/file02.txt", datetime(2022, 12, 17)), # Invalid extension
FakeBlob(f"{report_path}/file03.log", datetime(2022, 12, 18)), # Invalid extension
FakeBlob(f"{report_path}/file04.csv.gz", datetime(2022, 12, 19)), # Valid extension
)
azure_service = self.get_mock_client()
latest_blob = azure_service._get_latest_blob(f"{report_path}", blobs, None)

# The latest valid blob is file04.csv.gz
self.assertEqual(latest_blob.name, f"{report_path}/file04.csv.gz")