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

Adds Azure Blob Storage media backend #303

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

terricain
Copy link

Adds a MediaStorage plugin for Azure Blob Storage

@terricain terricain force-pushed the add_azure_blob_storage branch from e51a538 to 34921d2 Compare November 9, 2024 16:54
@dantownsend
Copy link
Member

@terricain Thanks for this!

@terricain terricain force-pushed the add_azure_blob_storage branch from 34921d2 to 3565b00 Compare November 10, 2024 19:53
@codecov-commenter
Copy link

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 93.98496% with 8 lines in your changes missing coverage. Please review.

Project coverage is 90.36%. Comparing base (9cc0966) to head (3565b00).
Report is 17 commits behind head on master.

Files with missing lines Patch % Lines
piccolo_api/media/azure.py 93.98% 8 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #303      +/-   ##
==========================================
- Coverage   92.69%   90.36%   -2.33%     
==========================================
  Files          34       43       +9     
  Lines        2053     2596     +543     
==========================================
+ Hits         1903     2346     +443     
- Misses        150      250     +100     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@dantownsend dantownsend left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this - sorry it took me a while to get around to reviewing it.

I think it looks great, just left some minor comments 👍

piccolo_api/media/azure.py Outdated Show resolved Hide resolved
piccolo_api/media/azure.py Outdated Show resolved Hide resolved
storage_account_name: str,
container_name: str,
folder_name: t.Optional[str] = None,
connection_kwargs: t.Optional[t.Dict[str, t.Any]] = None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't really use connection_kwargs for much at the moment - it is just being used as a way of passing a connection string.

Should we pass the connection_kwargs to DefaultAzureCredential? I know the user can set most of the options via environment variables, but it might be convenient to pass them in directly.

https://learn.microsoft.com/en-us/python/api/azure-identity/azure.identity.defaultazurecredential?view=azure-python#constructor

In which case, connection string, could be a separate argument, or:

connection_kwargs: t.Optional[t.Dict[str, t.Any]] | str = None

If it's a string, we treat it as a connection string.

What do you think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it, I think instead of having a union of an optional dictionary or string, leave it as an optional dictionary and if 'connection_string' is not present, pass the kwargs to DefaultCredential

Comment on lines 150 to 157
if "connection_string" in self.connection_kwargs:
self.connection_string = self.connection_kwargs[
"connection_string"
]
elif "AZURE_STORAGE_CONNECTION_STRING" in os.environ:
self.connection_string = os.environ[
"AZURE_STORAGE_CONNECTION_STRING"
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really a big deal, but we can use the walrus operator to simplify this a little bit.

if connection_string := (
    self.connection_kwargs.get("connection_string")
    or os.environ.get("AZURE_STORAGE_CONNECTION_STRING")
):
    self.connection_string = connection_string

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Managed to simplify this somewhat taking into account the previous message.

piccolo_api/media/azure.py Outdated Show resolved Hide resolved
self.container_name
)

return container_client, blob_service_client
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know a huge amount about Azure, and the differences between the two clients. We could split this into two separate methods ... one for each client type ... not sure. We can leave it as is for now.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just return the blob_service_client (which we have to instantiate differently based on how you're authing) and then call something like self.get_client().get_container_client(self.container_name) if needed but we need the container client 90% of the time, so I figured what we have now is slightly simpler. Up to you.

@terricain
Copy link
Author

Sorry for the wait, been a bit busy, have addressed the comments, let me know what you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants