Skip to content

Commit d56e2a6

Browse files
Merge pull request #2573 from pamelafox/azureupgrade
Upgrade Azure Blob Storage SDK to v12
2 parents 5f9a24c + 8926695 commit d56e2a6

File tree

17 files changed

+321
-136
lines changed

17 files changed

+321
-136
lines changed

.devcontainer/devcontainer.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// For format details, see https://aka.ms/devcontainer.json
2+
{
3+
"name": "flask-admin (Python 3.12)",
4+
"image": "mcr.microsoft.com/devcontainers/python:3.12-bullseye",
5+
6+
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
7+
"remoteUser": "vscode"
8+
}

.devcontainer/tests/Dockerfile

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
ARG IMAGE=bullseye
2+
FROM mcr.microsoft.com/devcontainers/${IMAGE}
3+
4+
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
5+
&& apt-get -y install --no-install-recommends postgresql-client \
6+
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*

.devcontainer/tests/devcontainer.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// For format details, see https://aka.ms/devcontainer.json.
2+
{
3+
"name": "flask-admin tests (Postgres + Azurite + Mongo)",
4+
"dockerComposeFile": "docker-compose.yaml",
5+
"service": "app",
6+
"workspaceFolder": "/workspace",
7+
"forwardPorts": [10000, 10001, 5432, 27017],
8+
"portsAttributes": {
9+
"10000": {"label": "Azurite Blob Storage Emulator", "onAutoForward": "silent"},
10+
"10001": {"label": "Azurite Blob Storage Emulator HTTPS", "onAutoForward": "silent"},
11+
"5432": {"label": "PostgreSQL port", "onAutoForward": "silent"},
12+
"27017": {"label": "MongoDB port", "onAutoForward": "silent"},
13+
},
14+
"features": {
15+
// For authenticating to a production Azure account
16+
"ghcr.io/devcontainers/features/azure-cli:1": {}
17+
},
18+
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
19+
"remoteUser": "vscode",
20+
"postAttachCommand": "pip install -e \".[all]\" && pip install --use-pep517 -r requirements/dev.txt && psql -U postgres -h localhost -c 'CREATE EXTENSION IF NOT EXISTS hstore;' flask_admin_test"
21+
}
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
version: '3'
2+
3+
services:
4+
app:
5+
build:
6+
context: .
7+
dockerfile: Dockerfile
8+
args:
9+
IMAGE: python:3.12
10+
11+
volumes:
12+
- ../..:/workspace:cached
13+
14+
# Overrides default command so things don't shut down after the process ends.
15+
command: sleep infinity
16+
environment:
17+
AZURE_STORAGE_CONNECTION_STRING: DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;
18+
19+
postgres:
20+
image: postgis/postgis:16-3.4
21+
restart: unless-stopped
22+
environment:
23+
POSTGRES_PASSWORD: postgres
24+
POSTGRES_DB: flask_admin_test
25+
volumes:
26+
- postgres-data:/var/lib/postgresql/data
27+
network_mode: service:app
28+
29+
azurite:
30+
container_name: azurite
31+
image: mcr.microsoft.com/azure-storage/azurite:latest
32+
restart: unless-stopped
33+
volumes:
34+
- azurite-data:/data
35+
network_mode: service:app
36+
37+
mongo:
38+
image: mongo:5.0.14-focal
39+
restart: unless-stopped
40+
network_mode: service:app
41+
42+
volumes:
43+
postgres-data:
44+
azurite-data:

.github/workflows/tests.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
ports:
5656
- 27017:27017
5757
azurite:
58-
image: arafato/azurite:2.6.5
58+
image: mcr.microsoft.com/azure-storage/azurite:latest
5959
env:
6060
executable: blob
6161
ports:

README.md

+17-4
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,13 @@ You should see output similar to:
131131

132132
OK
133133

134-
**NOTE!** For all the tests to pass successfully, you\'ll need Postgres (with
135-
the postgis and hstore extension) & MongoDB to be running locally. You'll
136-
also need *libgeos* available.
134+
**NOTE!** For all the tests to pass successfully, you'll need several services running locally:
135+
Postgres (with the postgis and hstore extension), MongoDB, and Azurite.
136+
You'll also need *libgeos* available.
137+
See tests.yaml for Docker configuration and follow service-specific setup below.
138+
139+
## Setting up local Postgres for tests
137140

138-
For Postgres:
139141
```bash
140142
psql postgres
141143
> CREATE DATABASE flask_admin_test;
@@ -144,6 +146,7 @@ psql postgres
144146
> CREATE EXTENSION postgis;
145147
> CREATE EXTENSION hstore;
146148
```
149+
147150
If you\'re using Homebrew on MacOS, you might need this:
148151

149152
```bash
@@ -156,6 +159,16 @@ createuser -s postgresql
156159
brew services restart postgresql
157160
```
158161

162+
## Setting up Azure Blob Storage emulator for tests
163+
164+
1. Run the [Azurite emulator](https://learn.microsoft.com/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage)
165+
166+
2. Set the connection string for the emulator:
167+
168+
```bash
169+
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
170+
```
171+
159172
You can also run the tests on multiple environments using *tox*.
160173

161174
## 3rd Party Stuff

doc/changelog.rst

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Changelog
44
2.0.0a3
55
-------
66

7+
Breaking changes:
8+
9+
* Azure Blob Storage SDK has been upgraded from the legacy version (v2) to the latest version (v12). AzureFileAdmin now accept `blob_service_client` rather than `connection_string` to give more flexibility with connection types.
10+
711
Fixes:
812

913
* Jinja templates can now be loaded in StrictUndefined mode.

examples/azure-blob-storage/README.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Azure Blob Storage Example
2+
3+
Flask-Admin example for an Azure Blob Storage account.
4+
5+
If you opened this repository in GitHub Codespaces or a Dev Container with the ["flask-admin tests" configuration](/.devcontainer/tests/devcontainer.json), you can jump straight to step 4.
6+
7+
To run this example:
8+
9+
1. Clone the repository and navigate to this example::
10+
11+
git clone https://github.com/pallets-eco/flask-admin.git
12+
cd flask-admin/examples/azure-blob-storage
13+
14+
2. Create and activate a virtual environment::
15+
16+
python -m venv venv
17+
source venv/bin/activate
18+
19+
3. Configure a connection to an Azure Blob storage account or local emulator.
20+
21+
To connect to the Azurite Blob Storage Emulator, install Azurite and set the following environment variable:
22+
23+
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
24+
25+
To connect to an Azure Blob Storage account, set the `AZURE_STORAGE_ACCOUNT_URL`. If you set that, the example assumes you are using keyless authentication, so you will need to be logged in via the Azure CLI.
26+
27+
4. Install requirements::
28+
29+
pip install -r requirements.txt
30+
31+
5. Run the application::
32+
33+
python app.py

examples/azure-blob-storage/__init__.py

Whitespace-only changes.

examples/azure-blob-storage/app.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import logging
2+
import os
3+
4+
from azure.identity import DefaultAzureCredential
5+
from azure.storage.blob import BlobServiceClient
6+
from flask import Flask
7+
from flask_admin import Admin
8+
from flask_admin.contrib.fileadmin.azure import AzureFileAdmin
9+
from flask_babel import Babel
10+
11+
logging.basicConfig(level=logging.INFO)
12+
app = Flask(__name__)
13+
app.config["SECRET_KEY"] = "secret"
14+
15+
16+
@app.route("/")
17+
def index():
18+
return '<a href="/admin/">Click me to get to Admin!</a>'
19+
20+
21+
admin = Admin(app)
22+
babel = Babel(app)
23+
24+
if account_url := os.getenv("AZURE_STORAGE_ACCOUNT_URL"):
25+
# https://learn.microsoft.com/azure/storage/blobs/storage-blob-python-get-started?tabs=azure-ad#authorize-access-and-connect-to-blob-storage
26+
logging.info("Connecting to Azure Blob storage with keyless auth")
27+
client = BlobServiceClient(account_url, credential=DefaultAzureCredential())
28+
elif conn_str := os.getenv("AZURE_STORAGE_CONNECTION_STRING"):
29+
logging.info("Connecting to Azure Blob storage with connection string.")
30+
client = BlobServiceClient.from_connection_string(conn_str)
31+
32+
file_admin = AzureFileAdmin(
33+
blob_service_client=client,
34+
container_name="fileadmin-tests",
35+
)
36+
admin.add_view(file_admin)
37+
38+
if __name__ == "__main__":
39+
app.run(debug=True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
../..[azure-blob-storage]
2+
azure-identity

0 commit comments

Comments
 (0)