From 05c4ff05ad0ef7fd0f0ee5ce01f2fb693e5c8a55 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 06:06:39 -0400 Subject: [PATCH 01/25] fixed searchid bug and added unit tests --- pctiler/pctiler/endpoints/pg_mosaic.py | 4 +- pctiler/tests/endpoints/test_pg_mosaic.py | 75 ++++++++++++++++++++--- scripts/test-mosaic | 7 +++ 3 files changed, 75 insertions(+), 11 deletions(-) create mode 100755 scripts/test-mosaic diff --git a/pctiler/pctiler/endpoints/pg_mosaic.py b/pctiler/pctiler/endpoints/pg_mosaic.py index 3dd77839..d7777988 100644 --- a/pctiler/pctiler/endpoints/pg_mosaic.py +++ b/pctiler/pctiler/endpoints/pg_mosaic.py @@ -11,6 +11,7 @@ from titiler.core.resources.enums import ImageType from titiler.pgstac.dependencies import SearchIdParams, TmsTileParams from titiler.pgstac.factory import MosaicTilerFactory +from titiler.pgstac.extensions import searchInfoExtension from pccommon.config import get_collection_config from pccommon.config.collections import MosaicInfo @@ -45,9 +46,10 @@ def __init__(self, request: Request): colormap_dependency=PCColorMapParams, layer_dependency=AssetsBidxExprParams, reader_dependency=ReaderParams, - router_prefix=get_settings().mosaic_endpoint_prefix + "/{search_id}", + router_prefix=get_settings().mosaic_endpoint_prefix + "/{search_id}", # reverts /searches back to /mosaic backend_dependency=BackendParams, add_statistics=False, + extensions=[searchInfoExtension()] ) diff --git a/pctiler/tests/endpoints/test_pg_mosaic.py b/pctiler/tests/endpoints/test_pg_mosaic.py index 508bb5aa..38997694 100644 --- a/pctiler/tests/endpoints/test_pg_mosaic.py +++ b/pctiler/tests/endpoints/test_pg_mosaic.py @@ -10,7 +10,6 @@ @pytest.fixture async def register_search(client: AsyncClient) -> REGISTER_TYPE: - cql = { "filter-lang": "cql2-json", "filter": { @@ -18,13 +17,38 @@ async def register_search(client: AsyncClient) -> REGISTER_TYPE: "args": [{"op": "=", "args": [{"property": "collection"}, "naip"]}], }, } - expected_content_hash = "8b989f86a149628eabfde894fb965982" response = await client.post("/mosaic/register", json=cql) + expected_content_hash = response.json()["searchid"] resp = response.json() - return (expected_content_hash, resp) +async def test_register_search_with_geom(client: AsyncClient) -> None: + geom = { + "type": "Polygon", + "coordinates": [ + [ + [-79.09062791441062, 43.08554661560049], + [-79.0629876337021, 43.08554661560049], + [-79.0629876337021, 43.067969831431895], + [-79.09062791441062, 43.067969831431895], + [-79.09062791441062, 43.08554661560049], + ] + ], + } + cql = { + "filter-lang": "cql2-json", + "filter": { + "op": "and", + "args": [{"op": "=", "args": [{"property": "collection"}, "naip"]}, + {"op": "s_intersects", "args": [{"property": "geometry"}, geom]}], + }, + } + response = await client.post("/mosaic/register", json=cql) + assert response.status_code == 200 + assert response.json()["searchid"] == '2607eab51afd5d626da8d50d9df3bbf0' + + @pytest.mark.asyncio async def test_mosaic_info(client: AsyncClient) -> None: response = await client.get("/mosaic/info?collection=naip") @@ -43,13 +67,10 @@ async def test_register(client: AsyncClient, register_search: REGISTER_TYPE) -> # and that the search hash remains consistent assert register_resp["searchid"] == expected_content_hash # Test that the links have had the {tileMatrixSetId} template string removed - assert len(register_resp["links"]) == 2 - assert register_resp["links"][0]["href"].endswith( - f"/mosaic/{expected_content_hash}/tilejson.json" - ) - assert register_resp["links"][1]["href"].endswith( - f"/mosaic/{expected_content_hash}/WMTSCapabilities.xml" - ) + assert len(register_resp["links"]) == 3 + assert register_resp["links"][0]["href"].endswith(f"/mosaic/{expected_content_hash}/info") # gets added by searchInfoExtension + assert register_resp["links"][1]["href"].endswith(f"/mosaic/{expected_content_hash}/tilejson.json") + assert register_resp["links"][2]["href"].endswith(f"/mosaic/{expected_content_hash}/WMTSCapabilities.xml") @pytest.mark.asyncio @@ -101,6 +122,40 @@ async def test_mosaic_tile_routes( assert response.status_code == 200 +async def test_info_path_with_searchid(client: AsyncClient, register_search: REGISTER_TYPE) -> None: + # route source code is here https://github.com/developmentseed/titiler/blob/main/src/titiler/mosaic/titiler/mosaic/factory.py#L157 + # the searchId functionality is added by titiler-pgstac + route = "mosaic/{searchId}/info" + expected_content_hash, _ = register_search + formatted_route = route.format(searchId=expected_content_hash) + url = (f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip") + response = await client.get(url) + assert response.status_code == 200 + + +async def test_info_path_with_bad_searchid(client: AsyncClient) -> None: + route = "mosaic/{searchId}/info" + expected_content_hash = "9b989f86a149628eabfde894fb965982" # does not match the one we registered in the fixture + formatted_route = route.format(searchId=expected_content_hash) + url = (f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip") + response = await client.get(url) + assert response.status_code == 404 + + +async def test_bad_searchid(client: AsyncClient) -> None: + route = "mosaic/tiles/{searchId}/{z}/{x}/{y}" + expected_content_hash = "9b989f86a149628eabfde894fb965982" # does not match the one we registered in the fixture + formatted_route = route.format( + searchId=expected_content_hash, + z=16, + x=17218, + y=26838 + ) + url = (f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip") + response = await client.get(url) + assert response.status_code == 404 + + @pytest.mark.asyncio @pytest.mark.parametrize( "route", diff --git a/scripts/test-mosaic b/scripts/test-mosaic new file mode 100755 index 00000000..ca28b9a0 --- /dev/null +++ b/scripts/test-mosaic @@ -0,0 +1,7 @@ +#!/bin/bash + +docker compose \ + -f docker-compose.yml \ + -f docker-compose.dev.yml \ + run --rm \ + tiler-dev python3 -m pytest pctiler/tests/endpoints/test_pg_mosaic.py From 49af1867c22fe4c877a85f90df58631aeec8f680 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 06:09:32 -0400 Subject: [PATCH 02/25] readme tweaks --- README.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 30a7bbf3..3a5d8de9 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ This repository contains two components of the Planetary Computer APIs: the STAC The `pcstac` project provides a STAC API which indexes Microsoft's publicly available [geospatial data](https://planetarycomputer.microsoft.com/catalog) and an API for searching through this large collection. The `pctiler` provides visualization and data access capabilities for the data in the Planetary Computer. -## Azure Functions +## Azure Functions (a.k.a. Funcs) -This repository also contains Azure Functions that provide additional endpoints for working with Planetary Computer data and metadata. This includes Function endpoints for generating images and animations based on STAC searches, using the tiler to render mosaiced data from Collections +This repository also contains Azure Functions that provide additional endpoints for working with Planetary Computer data and metadata. This includes Function endpoints for generating images and animations based on STAC searches, using the tiler to render mosaiced data from Collections. ## Collection configuration @@ -61,26 +61,27 @@ This project uses a variation on [scripts to rule them all](https://github.com/g #### Environment setup and building images -Before setting up the local environment, ensure that you have set the AZURITE_ACCOUNT_KEY environment variable. -The account key can be found in the [Azurite GitHub repository](https://github.com/Azure/Azurite?tab=readme-ov-file#usage-with-azure-storage-sdks-or-tools) +Before setting up the local environment, you must set the AZURITE_ACCOUNT_KEY environment variable to the Azurite default +account key, a string that can be [found here](https://github.com/Azure/Azurite?tab=readme-ov-file#usage-with-azure-storage-sdks-or-tools). For example, you can set the environment variable in your terminal with: + ```console -> export AZURITE_ACCOUNT_KEY= +export AZURITE_ACCOUNT_KEY= ``` -To set up a local environment, use +To set up a local environment, use: ```console -> ./scripts/setup +./scripts/setup ``` This will build containers, apply database migrations, and load the development data. -After migrations and development database loading are in place, you can rebuild the docker images with +After migrations and development database loading are in place, you can rebuild the docker images with: ```console -> ./scripts/update +./scripts/update ``` `pip` dependencies in `setup.py` are collected and installed through requirements files. @@ -99,11 +100,13 @@ az login To run the servers, use ```console -> ./scripts/server +./scripts/server ``` This will bring up the development database, STAC API, Tiler, Azure Functions, and other services. +To test the tiler, try going to . + #### Testing and and formatting To run tests, use From 7ebaf67cab72568267ca7eec1c00b8d08cfe7128 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 06:26:10 -0400 Subject: [PATCH 03/25] black line length --- scripts/bin/format-common | 4 ++-- scripts/bin/format-funcs | 2 +- scripts/bin/format-scripts | 2 +- scripts/bin/format-stac | 6 +++--- scripts/bin/format-tiler | 4 ++-- scripts/bin/test-common | 2 +- scripts/bin/test-funcs | 2 +- scripts/bin/test-stac | 2 +- scripts/bin/test-tiler | 2 +- scripts/format-local | 19 +++++++++++++++++++ 10 files changed, 32 insertions(+), 13 deletions(-) create mode 100755 scripts/format-local diff --git a/scripts/bin/format-common b/scripts/bin/format-common index aeea85f8..ad53d5db 100755 --- a/scripts/bin/format-common +++ b/scripts/bin/format-common @@ -20,6 +20,6 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting common..." isort --overwrite-in-place pccommon/pccommon isort --overwrite-in-place pccommon/tests - black pccommon/pccommon - black pccommon/tests + black --line-length 120 pccommon/pccommon + black --line-length 120 pccommon/tests fi diff --git a/scripts/bin/format-funcs b/scripts/bin/format-funcs index 09154164..1ae1a6fd 100755 --- a/scripts/bin/format-funcs +++ b/scripts/bin/format-funcs @@ -18,5 +18,5 @@ This scripts is meant to be run inside the funcs container. if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting funcs..." isort --overwrite-in-place pcfuncs - black pcfuncs + black --line-length 120 pcfuncs fi diff --git a/scripts/bin/format-scripts b/scripts/bin/format-scripts index e270b3ff..7328aca4 100755 --- a/scripts/bin/format-scripts +++ b/scripts/bin/format-scripts @@ -19,5 +19,5 @@ This script is meant to be run inside the stac-dev container. if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting scripts..." isort --overwrite-in-place scripts/bin - black scripts/bin + black --line-length 120 scripts/bin fi diff --git a/scripts/bin/format-stac b/scripts/bin/format-stac index 7d2230b9..feb76a8a 100755 --- a/scripts/bin/format-stac +++ b/scripts/bin/format-stac @@ -20,10 +20,10 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting stac..." isort --overwrite-in-place pcstac/pcstac isort --overwrite-in-place pcstac/tests - black pcstac/pcstac - black pcstac/tests + black --line-length 120 pcstac/pcstac + black --line-length 120 pcstac/tests echo "Formatting common..." isort --overwrite-in-place pccommon - black pccommon + black --line-length 120 pccommon fi diff --git a/scripts/bin/format-tiler b/scripts/bin/format-tiler index 1c898f94..f5c98489 100755 --- a/scripts/bin/format-tiler +++ b/scripts/bin/format-tiler @@ -19,6 +19,6 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting tiler..." isort --overwrite-in-place pctiler/pctiler isort --overwrite-in-place pctiler/tests - black pctiler/pctiler - black pctiler/tests + black --line-length 120 pctiler/pctiler + black --line-length 120 pctiler/tests fi diff --git a/scripts/bin/test-common b/scripts/bin/test-common index d0bb5a1d..f958e755 100755 --- a/scripts/bin/test-common +++ b/scripts/bin/test-common @@ -22,7 +22,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then mypy pccommon echo "Running black for common..." - black --check pccommon + black --line-length 120 --check pccommon echo "Running flake8 for common..." flake8 pccommon/pccommon pccommon/tests diff --git a/scripts/bin/test-funcs b/scripts/bin/test-funcs index 64bb06eb..ffa3ea83 100755 --- a/scripts/bin/test-funcs +++ b/scripts/bin/test-funcs @@ -38,7 +38,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then mypy pcfuncs echo "Running black for funcs..." - black --check pcfuncs + black --line-length 120 --check pcfuncs echo "Running flake8 for funcs..." flake8 pcfuncs diff --git a/scripts/bin/test-stac b/scripts/bin/test-stac index 41982cc3..dcfd1cbc 100755 --- a/scripts/bin/test-stac +++ b/scripts/bin/test-stac @@ -22,7 +22,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then mypy pcstac/pcstac echo "Running black for stac..." - black --check pcstac/pcstac pcstac/tests + black --line-length 120 --check pcstac/pcstac pcstac/tests echo "Running flake8 for stac..." flake8 pcstac/pcstac pcstac/tests diff --git a/scripts/bin/test-tiler b/scripts/bin/test-tiler index c3a6372f..c2d2b25a 100755 --- a/scripts/bin/test-tiler +++ b/scripts/bin/test-tiler @@ -38,7 +38,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then mypy pctiler/pctiler echo "Running black for tiler..." - black --check pctiler/pctiler pctiler/tests + black --line-length 120 --check pctiler/pctiler pctiler/tests echo "Running flake8 for tiler..." flake8 pctiler/pctiler pctiler/tests diff --git a/scripts/format-local b/scripts/format-local new file mode 100755 index 00000000..9737db90 --- /dev/null +++ b/scripts/format-local @@ -0,0 +1,19 @@ +#!/bin/bash +isort --overwrite-in-place pccommon +isort --overwrite-in-place pccommon/pccommon +isort --overwrite-in-place pccommon/tests +isort --overwrite-in-place pcfuncs +isort --overwrite-in-place scripts/bin +isort --overwrite-in-place pctiler/pctiler +isort --overwrite-in-place pctiler/tests +isort --overwrite-in-place pcstac/pcstac +isort --overwrite-in-place pcstac/tests +black --line-length 120 pccommon/pccommon +black --line-length 120 pccommon/tests +black --line-length 120 pcfuncs +black --line-length 120 scripts/bin +black --line-length 120 pcstac/pcstac +black --line-length 120 pcstac/tests +black --line-length 120 pccommon +black --line-length 120 pctiler/pctiler +black --line-length 120 pctiler/tests From c6c6d320291eb8cdeb7f224eb8799e368520be57 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 06:27:58 -0400 Subject: [PATCH 04/25] change line length in flake settings --- .flake8 | 2 +- scripts/bin/format-common | 4 ++-- scripts/bin/format-funcs | 2 +- scripts/bin/format-scripts | 2 +- scripts/bin/format-stac | 6 +++--- scripts/bin/format-tiler | 4 ++-- scripts/bin/test-common | 2 +- scripts/bin/test-funcs | 2 +- scripts/bin/test-stac | 2 +- scripts/bin/test-tiler | 2 +- scripts/format-local | 18 +++++++++--------- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.flake8 b/.flake8 index e034c121..b8453309 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -max-line-length = 88 +max-line-length = 120 extend-ignore = E203, W503 exclude = .git diff --git a/scripts/bin/format-common b/scripts/bin/format-common index ad53d5db..aeea85f8 100755 --- a/scripts/bin/format-common +++ b/scripts/bin/format-common @@ -20,6 +20,6 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting common..." isort --overwrite-in-place pccommon/pccommon isort --overwrite-in-place pccommon/tests - black --line-length 120 pccommon/pccommon - black --line-length 120 pccommon/tests + black pccommon/pccommon + black pccommon/tests fi diff --git a/scripts/bin/format-funcs b/scripts/bin/format-funcs index 1ae1a6fd..09154164 100755 --- a/scripts/bin/format-funcs +++ b/scripts/bin/format-funcs @@ -18,5 +18,5 @@ This scripts is meant to be run inside the funcs container. if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting funcs..." isort --overwrite-in-place pcfuncs - black --line-length 120 pcfuncs + black pcfuncs fi diff --git a/scripts/bin/format-scripts b/scripts/bin/format-scripts index 7328aca4..e270b3ff 100755 --- a/scripts/bin/format-scripts +++ b/scripts/bin/format-scripts @@ -19,5 +19,5 @@ This script is meant to be run inside the stac-dev container. if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting scripts..." isort --overwrite-in-place scripts/bin - black --line-length 120 scripts/bin + black scripts/bin fi diff --git a/scripts/bin/format-stac b/scripts/bin/format-stac index feb76a8a..7d2230b9 100755 --- a/scripts/bin/format-stac +++ b/scripts/bin/format-stac @@ -20,10 +20,10 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting stac..." isort --overwrite-in-place pcstac/pcstac isort --overwrite-in-place pcstac/tests - black --line-length 120 pcstac/pcstac - black --line-length 120 pcstac/tests + black pcstac/pcstac + black pcstac/tests echo "Formatting common..." isort --overwrite-in-place pccommon - black --line-length 120 pccommon + black pccommon fi diff --git a/scripts/bin/format-tiler b/scripts/bin/format-tiler index f5c98489..1c898f94 100755 --- a/scripts/bin/format-tiler +++ b/scripts/bin/format-tiler @@ -19,6 +19,6 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then echo "Formatting tiler..." isort --overwrite-in-place pctiler/pctiler isort --overwrite-in-place pctiler/tests - black --line-length 120 pctiler/pctiler - black --line-length 120 pctiler/tests + black pctiler/pctiler + black pctiler/tests fi diff --git a/scripts/bin/test-common b/scripts/bin/test-common index f958e755..d0bb5a1d 100755 --- a/scripts/bin/test-common +++ b/scripts/bin/test-common @@ -22,7 +22,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then mypy pccommon echo "Running black for common..." - black --line-length 120 --check pccommon + black --check pccommon echo "Running flake8 for common..." flake8 pccommon/pccommon pccommon/tests diff --git a/scripts/bin/test-funcs b/scripts/bin/test-funcs index ffa3ea83..64bb06eb 100755 --- a/scripts/bin/test-funcs +++ b/scripts/bin/test-funcs @@ -38,7 +38,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then mypy pcfuncs echo "Running black for funcs..." - black --line-length 120 --check pcfuncs + black --check pcfuncs echo "Running flake8 for funcs..." flake8 pcfuncs diff --git a/scripts/bin/test-stac b/scripts/bin/test-stac index dcfd1cbc..41982cc3 100755 --- a/scripts/bin/test-stac +++ b/scripts/bin/test-stac @@ -22,7 +22,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then mypy pcstac/pcstac echo "Running black for stac..." - black --line-length 120 --check pcstac/pcstac pcstac/tests + black --check pcstac/pcstac pcstac/tests echo "Running flake8 for stac..." flake8 pcstac/pcstac pcstac/tests diff --git a/scripts/bin/test-tiler b/scripts/bin/test-tiler index c2d2b25a..c3a6372f 100755 --- a/scripts/bin/test-tiler +++ b/scripts/bin/test-tiler @@ -38,7 +38,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then mypy pctiler/pctiler echo "Running black for tiler..." - black --line-length 120 --check pctiler/pctiler pctiler/tests + black --check pctiler/pctiler pctiler/tests echo "Running flake8 for tiler..." flake8 pctiler/pctiler pctiler/tests diff --git a/scripts/format-local b/scripts/format-local index 9737db90..5a80bb3f 100755 --- a/scripts/format-local +++ b/scripts/format-local @@ -8,12 +8,12 @@ isort --overwrite-in-place pctiler/pctiler isort --overwrite-in-place pctiler/tests isort --overwrite-in-place pcstac/pcstac isort --overwrite-in-place pcstac/tests -black --line-length 120 pccommon/pccommon -black --line-length 120 pccommon/tests -black --line-length 120 pcfuncs -black --line-length 120 scripts/bin -black --line-length 120 pcstac/pcstac -black --line-length 120 pcstac/tests -black --line-length 120 pccommon -black --line-length 120 pctiler/pctiler -black --line-length 120 pctiler/tests +black pccommon/pccommon +black pccommon/tests +black pcfuncs +black scripts/bin +black pcstac/pcstac +black pcstac/tests +black pccommon +black pctiler/pctiler +black pctiler/tests From c090186c6bda169931c6f689721df281f9182f9d Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 06:30:20 -0400 Subject: [PATCH 05/25] revert line length change, going to do it in separate PR --- .flake8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.flake8 b/.flake8 index b8453309..e034c121 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -max-line-length = 120 +max-line-length = 88 extend-ignore = E203, W503 exclude = .git From 1cab1ee37ac3bc551506b2e2b6bde375a4750485 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 06:31:06 -0400 Subject: [PATCH 06/25] autoformatter --- pctiler/pctiler/endpoints/pg_mosaic.py | 8 ++-- pctiler/tests/endpoints/test_pg_mosaic.py | 46 ++++++++++++++--------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/pctiler/pctiler/endpoints/pg_mosaic.py b/pctiler/pctiler/endpoints/pg_mosaic.py index d7777988..f8e692fb 100644 --- a/pctiler/pctiler/endpoints/pg_mosaic.py +++ b/pctiler/pctiler/endpoints/pg_mosaic.py @@ -10,8 +10,8 @@ from titiler.core.factory import img_endpoint_params from titiler.core.resources.enums import ImageType from titiler.pgstac.dependencies import SearchIdParams, TmsTileParams -from titiler.pgstac.factory import MosaicTilerFactory from titiler.pgstac.extensions import searchInfoExtension +from titiler.pgstac.factory import MosaicTilerFactory from pccommon.config import get_collection_config from pccommon.config.collections import MosaicInfo @@ -23,7 +23,6 @@ @dataclass class AssetsBidxExprParams(dependencies.AssetsBidxExprParams): - collection: str = Query(None, description="STAC Collection ID") @@ -46,10 +45,11 @@ def __init__(self, request: Request): colormap_dependency=PCColorMapParams, layer_dependency=AssetsBidxExprParams, reader_dependency=ReaderParams, - router_prefix=get_settings().mosaic_endpoint_prefix + "/{search_id}", # reverts /searches back to /mosaic + router_prefix=get_settings().mosaic_endpoint_prefix + + "/{search_id}", # reverts /searches back to /mosaic backend_dependency=BackendParams, add_statistics=False, - extensions=[searchInfoExtension()] + extensions=[searchInfoExtension()], ) diff --git a/pctiler/tests/endpoints/test_pg_mosaic.py b/pctiler/tests/endpoints/test_pg_mosaic.py index 38997694..f0d54992 100644 --- a/pctiler/tests/endpoints/test_pg_mosaic.py +++ b/pctiler/tests/endpoints/test_pg_mosaic.py @@ -40,13 +40,15 @@ async def test_register_search_with_geom(client: AsyncClient) -> None: "filter-lang": "cql2-json", "filter": { "op": "and", - "args": [{"op": "=", "args": [{"property": "collection"}, "naip"]}, - {"op": "s_intersects", "args": [{"property": "geometry"}, geom]}], + "args": [ + {"op": "=", "args": [{"property": "collection"}, "naip"]}, + {"op": "s_intersects", "args": [{"property": "geometry"}, geom]}, + ], }, } response = await client.post("/mosaic/register", json=cql) assert response.status_code == 200 - assert response.json()["searchid"] == '2607eab51afd5d626da8d50d9df3bbf0' + assert response.json()["searchid"] == "2607eab51afd5d626da8d50d9df3bbf0" @pytest.mark.asyncio @@ -60,7 +62,6 @@ async def test_mosaic_info(client: AsyncClient) -> None: @pytest.mark.asyncio async def test_register(client: AsyncClient, register_search: REGISTER_TYPE) -> None: - expected_content_hash, register_resp = register_search # Test that `searchid` which has been removed in titiler remains in pctiler, @@ -68,9 +69,15 @@ async def test_register(client: AsyncClient, register_search: REGISTER_TYPE) -> assert register_resp["searchid"] == expected_content_hash # Test that the links have had the {tileMatrixSetId} template string removed assert len(register_resp["links"]) == 3 - assert register_resp["links"][0]["href"].endswith(f"/mosaic/{expected_content_hash}/info") # gets added by searchInfoExtension - assert register_resp["links"][1]["href"].endswith(f"/mosaic/{expected_content_hash}/tilejson.json") - assert register_resp["links"][2]["href"].endswith(f"/mosaic/{expected_content_hash}/WMTSCapabilities.xml") + assert register_resp["links"][0]["href"].endswith( + f"/mosaic/{expected_content_hash}/info" + ) # gets added by searchInfoExtension + assert register_resp["links"][1]["href"].endswith( + f"/mosaic/{expected_content_hash}/tilejson.json" + ) + assert register_resp["links"][2]["href"].endswith( + f"/mosaic/{expected_content_hash}/WMTSCapabilities.xml" + ) @pytest.mark.asyncio @@ -122,36 +129,41 @@ async def test_mosaic_tile_routes( assert response.status_code == 200 -async def test_info_path_with_searchid(client: AsyncClient, register_search: REGISTER_TYPE) -> None: +async def test_info_path_with_searchid( + client: AsyncClient, register_search: REGISTER_TYPE +) -> None: # route source code is here https://github.com/developmentseed/titiler/blob/main/src/titiler/mosaic/titiler/mosaic/factory.py#L157 # the searchId functionality is added by titiler-pgstac route = "mosaic/{searchId}/info" expected_content_hash, _ = register_search formatted_route = route.format(searchId=expected_content_hash) - url = (f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip") + url = ( + f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip" + ) response = await client.get(url) assert response.status_code == 200 async def test_info_path_with_bad_searchid(client: AsyncClient) -> None: route = "mosaic/{searchId}/info" - expected_content_hash = "9b989f86a149628eabfde894fb965982" # does not match the one we registered in the fixture + expected_content_hash = "9b989f86a149628eabfde894fb965982" # does not match the one we registered in the fixture formatted_route = route.format(searchId=expected_content_hash) - url = (f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip") + url = ( + f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip" + ) response = await client.get(url) assert response.status_code == 404 async def test_bad_searchid(client: AsyncClient) -> None: route = "mosaic/tiles/{searchId}/{z}/{x}/{y}" - expected_content_hash = "9b989f86a149628eabfde894fb965982" # does not match the one we registered in the fixture + expected_content_hash = "9b989f86a149628eabfde894fb965982" # does not match the one we registered in the fixture formatted_route = route.format( - searchId=expected_content_hash, - z=16, - x=17218, - y=26838 + searchId=expected_content_hash, z=16, x=17218, y=26838 + ) + url = ( + f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip" ) - url = (f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip") response = await client.get(url) assert response.status_code == 404 From 55936f140f0cd6b1d2f010e540170e72653054f6 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 06:40:19 -0400 Subject: [PATCH 07/25] retrigger github actions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a5d8de9..4cea8d0b 100644 --- a/README.md +++ b/README.md @@ -151,4 +151,4 @@ See the [Helm chart repository](https://microsoft.github.io/planetary-computer-a ### Functions -See the [Function package repository](https://microsoft.github.io/planetary-computer-apis) published to GitHub pages for the published Azure Functions. +See the [Function package repository](https://microsoft.github.io/planetary-computer-apis) published to GitHub pages for the published Azure Functions. \ No newline at end of file From 4c693d4a58010a63c076c077d1d782ef15281763 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 17:34:05 -0400 Subject: [PATCH 08/25] Delete scripts/test-mosaic --- scripts/test-mosaic | 7 ------- 1 file changed, 7 deletions(-) delete mode 100755 scripts/test-mosaic diff --git a/scripts/test-mosaic b/scripts/test-mosaic deleted file mode 100755 index ca28b9a0..00000000 --- a/scripts/test-mosaic +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -docker compose \ - -f docker-compose.yml \ - -f docker-compose.dev.yml \ - run --rm \ - tiler-dev python3 -m pytest pctiler/tests/endpoints/test_pg_mosaic.py From 29ceab370c7721002b53f26471407043f273b170 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 18:05:32 -0400 Subject: [PATCH 09/25] hack for not needing secrets AZURITE_ACCOUNT_KEY --- .github/workflows/pr.yml | 4 +- ...se-azurite?tabs=visual-studio,blob-storage | 1472 +++++++++++++++++ 2 files changed, 1474 insertions(+), 2 deletions(-) create mode 100644 storage-use-azurite?tabs=visual-studio,blob-storage diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 71480a36..3607aafc 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -13,7 +13,7 @@ jobs: - name: Set Azurite Default Key run: | - echo "AZURITE_ACCOUNT_KEY=${{ secrets.AZURITE_ACCOUNT_KEY }}" >> $GITHUB_ENV + echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage#well-known-storage-account-and-key|grep "Account key:"|cut -b 24-111)" >> $GITHUB_ENV echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" - name: Run cibuild @@ -30,7 +30,7 @@ jobs: - name: Set Azurite Default Key run: | - echo "AZURITE_ACCOUNT_KEY=${{ secrets.AZURITE_ACCOUNT_KEY }}" >> $GITHUB_ENV + echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage#well-known-storage-account-and-key|grep "Account key:"|cut -b 24-111)" >> $GITHUB_ENV echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" - name: Validate diff --git a/storage-use-azurite?tabs=visual-studio,blob-storage b/storage-use-azurite?tabs=visual-studio,blob-storage new file mode 100644 index 00000000..381c5c67 --- /dev/null +++ b/storage-use-azurite?tabs=visual-studio,blob-storage @@ -0,0 +1,1472 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use Azurite emulator for local Azure Storage development | Microsoft Learn + + + + + +
+ Skip to main content + + + + + +
+
+ + +
+
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+
+
+ + + + + +
+ +
+
+ +
+
+ + + +
+ + + + + Edit + +
+

Share via

+ + + + +
+ +
+
+ +
+
+
+ +
+ +

Use the Azurite emulator for local Azure Storage development

The Azurite open-source emulator provides a free local environment for testing your Azure Blob, Queue Storage, and Table Storage applications. When you're satisfied with how your application is working locally, switch to using an Azure Storage account in the cloud. The emulator provides cross-platform support on Windows, Linux, and macOS.

+

Azurite supersedes the Azure Storage Emulator, and continues to be updated to support the latest versions of Azure Storage APIs.

+

This video shows you how to install and run the Azurite emulator.

+
+

The steps in the video are also described in the following sections. Select any of these tabs.

+

Install Azurite

+
+ +
+ +

Azurite is automatically available with Visual Studio 2022. The Azurite executable is updated as part of Visual Studio new version releases. If you're running an earlier version of Visual Studio, you can install Azurite by using either Node Package Manager (npm), DockerHub, or by cloning the Azurite GitHub repository.

+
+ + + + +
+

Run Azurite

+
+ +
+ +

To use Azurite with most project types in Visual Studio, you first need to run the Azurite executable. Once the executable is running, Azurite listens for connection requests from the application. To learn more, see Running Azurite from the command line.

+

For Azure Functions projects and ASP.NET projects, you can choose to configure the project to start Azurite automatically. This configuration is done during the project setup. While this project configuration starts Azurite automatically, Visual Studio doesn't expose detailed Azurite configuration options. To customize detailed Azurite configuration options, run the Azurite executable before launching Visual Studio.

+

To learn more about configuring Azure Functions projects and ASP.NET projects to start Azurite automatically, see the following guidance:

+ +

Azurite executable file location

+

The following table shows the location of the Azurite executable for different versions of Visual Studio running on a Windows machine:

+ + + + + + + + + + + + + + + + + + + + + +
Visual Studio versionAzurite executable location
Visual Studio Community 2022C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator
Visual Studio Professional 2022C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator
Visual Studio Enterprise 2022C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator
+

Running Azurite from the command line

+

You can find the Azurite executable file in the extensions folder of your Visual Studio installation, as detailed in the Azurite executable file location table.

+

Navigate to the appropriate location and start azurite.exe. After you run the executable file, Azurite listens for connections.

+
+

Azurite command-line output

+
+

To learn more about available command line options to configure Azurite, see Command line options.

+

Running Azurite from an Azure Functions project

+

In Visual Studio 2022, create an Azure Functions project. While setting the project options, mark the box labeled Use Azurite for runtime storage account.

+

+ +A screenshot showing how to set Azurite to be the runtime storage account for an Azure Functions project. + + +

+

After you create the project, Azurite starts automatically. The location of the Azurite executable file is detailed in the Azurite executable file location table. The output looks similar to the following screenshot:

+

+ +A screenshot showing output after setting Azurite to be the runtime storage account for an Azure Functions project. + + +

+

This configuration option can be changed later by modifying the project's Connected Services dependencies.

+

Running Azurite from an ASP.NET project

+

In Visual Studio 2022, create an ASP.NET Core Web App project. Then, open the Connected Services dialog box, select Add a service dependency, and then select Storage Azurite emulator.

+

+ +A screenshot showing how to add Azurite as a dependency to an ASP.NET project. + + +

+

In the Configure Storage Azurite emulator dialog box, set the Connection string name field to StorageConnectionString, and then select Finish.

+

+ +A screenshot showing how to configure a connection string to use Azurite with an ASP.NET project. + + +

+

When the configuration completes, select Close, and the Azurite emulator starts automatically. The location of the Azurite executable file is detailed in the Azurite executable file location table. The output looks similar to the following screenshot:

+

+ +A screenshot showing output after connecting an ASP.NET project to the Azurite emulator. + + +

+

This configuration option can be changed later by modifying the project's Connected Services dependencies.

+
+ + + + +
+

Command line options

+

This section details the command line switches available when launching Azurite.

+

Help

+

Optional - Get command-line help by using the -h or --help switch.

+
azurite -h
+azurite --help
+
+

Listening host

+
+ +
+ +

Optional - By default, Azurite listens to 127.0.0.1 as the local server. Use the --blobHost switch to set the address to your requirements.

+

Accept requests on the local machine only:

+
azurite --blobHost 127.0.0.1
+
+

Allow remote requests:

+
azurite --blobHost 0.0.0.0
+
+
+

Caution

+

Allowing remote requests may make your system vulnerable to external attacks.

+
+
+ + +
+

Listening port configuration

+
+ +
+ +

Optional - By default, Azurite listens for the Blob service on port 10000. Use the --blobPort switch to specify the listening port that you require.

+
+

Note

+

After using a customized port, you need to update the connection string or corresponding configuration in your Azure Storage tools or SDKs.

+
+

Customize the Blob service listening port:

+
azurite --blobPort 8888
+
+

Let the system auto select an available port:

+
azurite --blobPort 0
+
+

The port in use is displayed during Azurite startup.

+
+ + +
+

Workspace path

+

Optional - Azurite stores data to the local disk during execution. Use the -l or --location switch to specify a path as the workspace location. By default, the current process working directory is used. Note the lowercase 'l'.

+
azurite -l c:\azurite
+azurite --location c:\azurite
+
+

Access log

+

Optional - By default, the access log is displayed in the console window. Disable the display of the access log by using the -s or --silent switch.

+
azurite -s
+azurite --silent
+
+

Debug log

+

Optional - The debug log includes detailed information on every request and exception stack trace. Enable the debug log by providing a valid local file path to the -d or --debug switch.

+
azurite -d path/debug.log
+azurite --debug path/debug.log
+
+

Loose mode

+

Optional - By default, Azurite applies strict mode to block unsupported request headers and parameters. Disable strict mode by using the -L or --loose switch. Note the capital 'L'.

+
azurite -L
+azurite --loose
+
+

Version

+

Optional - Display the installed Azurite version number by using the -v or --version switch.

+
azurite -v
+azurite --version
+
+

Certificate configuration (HTTPS)

+

Optional - By default, Azurite uses the HTTP protocol. You can enable HTTPS mode by providing a path to a Privacy Enhanced Mail (.pem) or Personal Information Exchange (.pfx) certificate file to the --cert switch. HTTPS is required to connect to Azurite using OAuth authentication.

+

When --cert is provided for a PEM file, you must provide a corresponding --key switch.

+
azurite --cert path/server.pem --key path/key.pem
+
+

When --cert is provided for a PFX file, you must provide a corresponding --pwd switch.

+
azurite --cert path/server.pfx --pwd pfxpassword
+
+
HTTPS setup
+

For detailed information on generating PEM and PFX files, see HTTPS Setup.

+

OAuth configuration

+

Optional - Enable OAuth authentication for Azurite by using the --oauth switch.

+
azurite --oauth basic --cert path/server.pem --key path/key.pem
+
+
+

Note

+

OAuth requires an HTTPS endpoint. Make sure HTTPS is enabled by providing --cert switch along with the --oauth switch.

+
+

Azurite supports basic authentication by specifying the basic parameter to the --oauth switch. Azurite performs basic authentication, like validating the incoming bearer token, checking the issuer, audience, and expiry. Azurite doesn't check the token signature or permissions. To learn more about authorization, see Authorization for tools and SDKs.

+

Skip API version check

+

Optional - When starting up, Azurite checks that the requested API version is valid. The following command skips the API version check:

+
azurite --skipApiVersionCheck
+
+

Disable production-style URL

+

Optional. When using the fully qualified domain name instead of the IP in request Uri host, by default Azurite parses the storage account name from request URI host. You can force the parsing of the storage account name from request URI path by using --disableProductStyleUrl:

+
azurite --disableProductStyleUrl
+
+

In-memory persistence

+

Optional. By default, blob and queue metadata is persisted to disk and content is persisted to extent files. Table storage persists all data to disk. You can disable persisting any data to disk and only store data in-memory. In the in-memory persistence scenario, if the Azurite process is terminated, all data is lost. The default persistence behavior can be overridden using the following option:

+
azurite --inMemoryPersistence
+
+

This setting is rejected when the SQL-based metadata implementation is enabled (via AZURITE_DB), or when the --location option is specified.

+

Extent memory limit

+

Optional. By default, the in-memory extent store (for blob and queue content) is limited to 50% of the total memory on the host machine. The total is evaluated using os.totalmem(). This limit can be overridden using the following option:

+
azurite --extentMemoryLimit <megabytes>
+
+

There's no restriction on the value specified for this option, but virtual memory might be used if the limit exceeds the amount of available physical memory as provided by the operating system. A high limit might eventually lead to out of memory errors or reduced performance. This option is rejected when --inMemoryPersistence isn't specified.

+

To learn more, see Use in-memory storage.

+

Connect to Azurite with SDKs and tools

+

You can connect to Azurite from Azure Storage SDKs, or tools like Azure Storage Explorer. Authentication is required, and Azurite supports authorization with OAuth, Shared Key, and shared access signatures (SAS). Azurite also supports anonymous access to public containers.

+

To learn more about using Azurite with the Azure SDKs, see Azure SDKs.

+

Well-known storage account and key

+

Azurite accepts the same well-known account and key used by the legacy Azure Storage Emulator.

+
    +
  • Account name: devstoreaccount1
  • +
  • Account key: Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==
  • +
+

Custom storage accounts and keys

+

Azurite supports custom storage account names and keys by setting the AZURITE_ACCOUNTS environment variable in the following format: account1:key1[:key2];account2:key1[:key2];....

+

For example, use a custom storage account that has one key:

+
set AZURITE_ACCOUNTS="account1:key1"
+
+
export AZURITE_ACCOUNTS="account1:key1"
+
+
+

Note

+

The account keys must be a base64 encoded string.

+
+

Or use multiple storage accounts with two keys each:

+
set AZURITE_ACCOUNTS="account1:key1:key2;account2:key1:key2"
+
+
export AZURITE_ACCOUNTS="account1:key1:key2;account2:key1:key2"
+
+

Azurite refreshes custom account names and keys from the environment variable every minute by default. With this feature, you can dynamically rotate the account key, or add new storage accounts without restarting Azurite.

+
+

Note

+

The default devstoreaccount1 storage account is disabled when you set custom storage accounts. If you want to continue using devstoreaccount1 after enabling custom storage accounts, you need to add it to the list of custom accounts and keys in the AZURITE_ACCOUNTS environment variable.

+
+

The account keys must be a base64 encoded string.

+

Connection strings

+

The easiest way to connect to Azurite from your application is to configure a connection string in your application's configuration file that references the shortcut UseDevelopmentStorage=true. Here's an example of a connection string in an app.config file:

+
<appSettings>
+  <add key="StorageConnectionString" value="UseDevelopmentStorage=true" />
+</appSettings>
+
+
HTTP connection strings
+

You can pass the following connection strings to the Azure SDKs or tools, like Azure CLI 2.0 or Storage Explorer.

+

The full connection string is:

+

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;

+

To connect to a specific service, you can use the following connection strings:

+
+ +
+ +

To connect to Blob Storage only, the connection string is:

+

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;

+
+ + +
+
HTTPS connection strings
+

The full HTTPS connection string is:

+

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=https://127.0.0.1:10001/devstoreaccount1;TableEndpoint=https://127.0.0.1:10002/devstoreaccount1;

+

To connect to a specific service, you can use the following connection strings:

+
+ +
+ +

To use the blob service only, the HTTPS connection string is:

+

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;

+
+ + +
+ +

If you used dotnet dev-certs to generate your self-signed certificate, use the following connection string.

+

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://localhost:10000/devstoreaccount1;QueueEndpoint=https://localhost:10001/devstoreaccount1;TableEndpoint=https://localhost:10002/devstoreaccount1;

+

Update the connection string when using custom storage accounts and keys.

+

For more information, see Configure Azure Storage connection strings.

+

Azure SDKs

+

To connect to Azurite with the Azure SDKs, follow these steps:

+ +

Once the certificates are in place, start Azurite with the following command line options:

+
azurite --oauth basic --cert cert-name.pem --key cert-name-key.pem
+
+

Replace cert-name.pem and certname-key.pem with the names of your certificate and key files. If you're using a PFX certificate, use the --pwd option instead of the --key option.

+
+ +
+ +

To interact with Blob Storage resources, you can instantiate a BlobContainerClient, BlobServiceClient, or BlobClient.

+

The following examples show how to authorize a BlobContainerClient object using three different authorization mechanisms: DefaultAzureCredential, connection string, and shared key. DefaultAzureCredential provides a Bearer token-based authentication mechanism, and uses a chain of credential types used for authentication. Once authenticated, this credential provides the OAuth token as part of client instantiation. To learn more, see the DefaultAzureCredential class reference.

+
// With container URL and DefaultAzureCredential
+var client = new BlobContainerClient(
+    new Uri("https://127.0.0.1:10000/devstoreaccount1/container-name"), new DefaultAzureCredential()
+  );
+
+// With connection string
+var client = new BlobContainerClient(
+    "DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;", "container-name"
+  );
+
+// With account name and key
+var client = new BlobContainerClient(
+    new Uri("https://127.0.0.1:10000/devstoreaccount1/container-name"),
+    new StorageSharedKeyCredential("devstoreaccount1", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")
+  );
+
+
+ + +
+

Microsoft Azure Storage Explorer

+

You can use Storage Explorer to view the data stored in Azurite.

+
Connect to Azurite using HTTP
+

In Storage Explorer, connect to Azurite by following these steps:

+
    +
  1. Select the Manage Accounts icon
  2. +
  3. Select Add an account
  4. +
  5. Select Attach to a local emulator
  6. +
  7. Select Next
  8. +
  9. Edit the Display name field to a name of your choice
  10. +
  11. Select Next again
  12. +
  13. Select Connect
  14. +
+
Connect to Azurite using HTTPS
+

By default, Storage Explorer doesn't open an HTTPS endpoint that uses a self-signed certificate. If you're running Azurite with HTTPS, you're likely using a self-signed certificate. In Storage Explorer, import SSL certificates via the Edit -> SSL Certificates -> Import Certificates dialog.

+
Import Certificate to Storage Explorer
+
    +
  1. Find the certificate on your local machine.
  2. +
  3. In Storage Explorer, go to Edit -> SSL Certificates -> Import Certificates and import your certificate.
  4. +
+

If you don't import a certificate, you get an error:

+

unable to verify the first certificate or self signed certificate in chain

+
Add Azurite via HTTPS connection string
+

Follow these steps to add Azurite HTTPS to Storage Explorer:

+
    +
  1. Select Toggle Explorer
  2. +
  3. Select Local & Attached
  4. +
  5. Right-click on Storage Accounts and select Connect to Azure Storage.
  6. +
  7. Select Use a connection string
  8. +
  9. Select Next.
  10. +
  11. Enter a value in the Display name field.
  12. +
  13. Enter the HTTPS connection string from the previous section of this document
  14. +
  15. Select Next
  16. +
  17. Select Connect
  18. +
+

Workspace structure

+

The following files and folders might be created in the workspace location when initializing Azurite.

+
    +
  • __blobstorage__ - Directory containing Azurite blob service persisted binary data
  • +
  • __queuestorage__ - Directory containing Azurite queue service persisted binary data
  • +
  • __tablestorage__ - Directory containing Azurite table service persisted binary data
  • +
  • __azurite_db_blob__.json - Azurite blob service metadata file
  • +
  • __azurite_db_blob_extent__.json - Azurite blob service extent metadata file
  • +
  • __azurite_db_queue__.json - Azurite queue service metadata file
  • +
  • __azurite_db_queue_extent__.json - Azurite queue service extent metadata file
  • +
  • __azurite_db_table__.json - Azurite table service metadata file
  • +
  • __azurite_db_table_extent__.json - Azurite table service extent metadata file
  • +
+

To clean up Azurite, delete above files and folders and restart the emulator.

+

Differences between Azurite and Azure Storage

+

There are functional differences between a local instance of Azurite and an Azure Storage account in the cloud.

+

Endpoint and connection URL

+

The service endpoints for Azurite are different from the endpoints of an Azure Storage account. The local computer doesn't do domain name resolution, requiring Azurite endpoints to be local addresses.

+

When you address a resource in an Azure Storage account, the account name is part of the URI host name. The resource being addressed is part of the URI path:

+

<http|https>://<account-name>.<service-name>.core.windows.net/<resource-path>

+

The following URI is a valid address for a blob in an Azure Storage account:

+

https://myaccount.blob.core.windows.net/mycontainer/myblob.txt

+
IP-style URL
+

Since the local computer doesn't resolve domain names, the account name is part of the URI path instead of the host name. Use the following URI format for a resource in Azurite:

+

http://<local-machine-address>:<port>/<account-name>/<resource-path>

+

The following address might be used for accessing a blob in Azurite:

+

http://127.0.0.1:10000/myaccount/mycontainer/myblob.txt

+
Production-style URL
+

Optionally, you could modify your hosts file to access an account with production-style URL.

+

First, add one or more lines to your hosts file. For example:

+
127.0.0.1 account1.blob.localhost
+127.0.0.1 account1.queue.localhost
+127.0.0.1 account1.table.localhost
+
+

Next, set environment variables to enable customized storage accounts and keys:

+
set AZURITE_ACCOUNTS="account1:key1:key2"
+
+

You could add more accounts. See the Custom storage accounts and keys section of this article.

+

Start Azurite and use a customized connection string to access your account. In the following example, the connection string assumes that the default ports are used.

+
DefaultEndpointsProtocol=http;AccountName=account1;AccountKey=key1;BlobEndpoint=http://account1.blob.localhost:10000;QueueEndpoint=http://account1.queue.localhost:10001;TableEndpoint=http://account1.table.localhost:10002;
+
+

Don't access default account in this way with Azure Storage Explorer. There's a bug that Storage Explorer is always adding account name in URL path, causing failures.

+

By default, when using Azurite with a production-style URL, the account name should be the host name in fully qualified domain name such as http://devstoreaccount1.blob.localhost:10000/container. To use production-style URL with account name in the URL path such as http://foo.bar.com:10000/devstoreaccount1/container, make sure to use the --disableProductStyleUrl parameter when you start Azurite.

+

If you use host.docker.internal as request Uri host (For example: http://host.docker.internal:10000/devstoreaccount1/container), Azurite gets the account name from the request Uri path. This behavior is true regardless of whether you use the --disableProductStyleUrl parameter when you start Azurite.

+

Scaling and performance

+

Azurite doesn't support large numbers of connected clients. There's no performance guarantee. Azurite is intended for development and testing purposes.

+

Error handling

+

Azurite is aligned with Azure Storage error handling logic, but there are differences. For example, error messages might be different, while error status codes align.

+

RA-GRS

+

Azurite supports read-access geo-redundant replication (RA-GRS). For storage resources, access the secondary location by appending -secondary to the account name. For example, the following address might be used for accessing a blob using the read-only secondary in Azurite:

+

http://127.0.0.1:10000/devstoreaccount1-secondary/mycontainer/myblob.txt

+

Table support

+

Support for tables in Azurite is currently in preview. For more information, see the Azurite V3 Table project.

+

Support for durable functions requires tables.

+
+

Important

+

Azurite support for Table Storage is currently in PREVIEW. See the Supplemental Terms of Use for Microsoft Azure Previews for legal terms that apply to Azure features that are in beta, preview, or otherwise not yet released into general availability.

+
+

Azurite is open-source

+

Contributions and suggestions for Azurite are welcome. Go to the Azurite GitHub project page or GitHub issues for milestones and work items we're tracking for upcoming features and bug fixes. Detailed work items are also tracked in GitHub.

+

Next steps

+ +
+
+ + +
+ + + +
+ + +
+ + + + + +
+ +
+ + +
+ +
+ + \ No newline at end of file From 8739b7b50d28ec5424f9c6a52a048aa7523ae296 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 18:07:03 -0400 Subject: [PATCH 10/25] shorten command --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 3607aafc..7c1e41ba 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -30,7 +30,7 @@ jobs: - name: Set Azurite Default Key run: | - echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage#well-known-storage-account-and-key|grep "Account key:"|cut -b 24-111)" >> $GITHUB_ENV + echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" - name: Validate From 2235be9a82d8c39b9eb3de8ef74f5a13a1d135c9 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 18:10:49 -0400 Subject: [PATCH 11/25] testing output --- .github/workflows/pr.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7c1e41ba..ef4f73b6 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -13,7 +13,8 @@ jobs: - name: Set Azurite Default Key run: | - echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage#well-known-storage-account-and-key|grep "Account key:"|cut -b 24-111)" >> $GITHUB_ENV + echo curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111 + echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" - name: Run cibuild From 2e4de7fac12979c1901427220a827d2786e99cdc Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 18:13:04 -0400 Subject: [PATCH 12/25] remove grep --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index ef4f73b6..ae45bf92 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -13,7 +13,7 @@ jobs: - name: Set Azurite Default Key run: | - echo curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111 + echo curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" From a1a341c8b92fc623cbf2019c612ae99acb35653b Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 18:15:47 -0400 Subject: [PATCH 13/25] quotes --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index ae45bf92..27beea63 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -13,7 +13,7 @@ jobs: - name: Set Azurite Default Key run: | - echo curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite + echo "curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite" echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" From 3297f7c014d3120ec555ee1be00e5bd587185d57 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 18:23:07 -0400 Subject: [PATCH 14/25] trying another method --- .github/workflows/pr.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 27beea63..deac0235 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -13,8 +13,8 @@ jobs: - name: Set Azurite Default Key run: | - echo "curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite" - echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV + response = $(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111) + echo "AZURITE_ACCOUNT_KEY=$response" echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" - name: Run cibuild From 24b51b0e8245541a69bb030086975e5e1a2b7cff Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 21:56:32 -0400 Subject: [PATCH 15/25] trying another method --- .github/workflows/pr.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index deac0235..73095292 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -12,10 +12,10 @@ jobs: - uses: actions/checkout@v3 - name: Set Azurite Default Key - run: | - response = $(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111) - echo "AZURITE_ACCOUNT_KEY=$response" - echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" + run: echo "AZURITE_ACCOUNT_KEY=$(echo curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV + + - name: Test + run: echo $AZURITE_ACCOUNT_KEY - name: Run cibuild run: ./scripts/cibuild From 2d1b474d93bf09f7e36894be740113d3bc8fa3d8 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 22:00:44 -0400 Subject: [PATCH 16/25] remove extra echo --- .github/workflows/pr.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 73095292..944325ff 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v3 - name: Set Azurite Default Key - run: echo "AZURITE_ACCOUNT_KEY=$(echo curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV + run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - name: Test run: echo $AZURITE_ACCOUNT_KEY @@ -30,9 +30,7 @@ jobs: cache: "pip" - name: Set Azurite Default Key - run: | - echo "AZURITE_ACCOUNT_KEY="$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - echo "Using Azurite default key: $AZURITE_ACCOUNT_KEY" + run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - name: Validate run: ./scripts/validate From d70a127d3745f8100ca6a4f27123621c61c7ca78 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Thu, 29 Aug 2024 22:08:49 -0400 Subject: [PATCH 17/25] tweaks --- .github/workflows/pr.yml | 5 +++-- pctiler/tests/endpoints/test_pg_mosaic.py | 12 +++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 944325ff..e5530ab2 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -14,8 +14,9 @@ jobs: - name: Set Azurite Default Key run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - - name: Test - run: echo $AZURITE_ACCOUNT_KEY + - name: Verify Azurite Key was retrieved correctly + if: (echo $AZURITE_ACCOUNT_KEY | cut -b 1-4) == 'Eby8' + run: echo GOT HERE - name: Run cibuild run: ./scripts/cibuild diff --git a/pctiler/tests/endpoints/test_pg_mosaic.py b/pctiler/tests/endpoints/test_pg_mosaic.py index f0d54992..52ffa105 100644 --- a/pctiler/tests/endpoints/test_pg_mosaic.py +++ b/pctiler/tests/endpoints/test_pg_mosaic.py @@ -132,7 +132,7 @@ async def test_mosaic_tile_routes( async def test_info_path_with_searchid( client: AsyncClient, register_search: REGISTER_TYPE ) -> None: - # route source code is here https://github.com/developmentseed/titiler/blob/main/src/titiler/mosaic/titiler/mosaic/factory.py#L157 + # route source code is in titiler/mosaic/titiler/mosaic/factory.py#L157 # the searchId functionality is added by titiler-pgstac route = "mosaic/{searchId}/info" expected_content_hash, _ = register_search @@ -146,7 +146,10 @@ async def test_info_path_with_searchid( async def test_info_path_with_bad_searchid(client: AsyncClient) -> None: route = "mosaic/{searchId}/info" - expected_content_hash = "9b989f86a149628eabfde894fb965982" # does not match the one we registered in the fixture + + # does not match the one we registered in the fixture + expected_content_hash = "9b989f86a149628eabfde894fb965982" + formatted_route = route.format(searchId=expected_content_hash) url = ( f"/{formatted_route}?asset_bidx=image%7C1%2C2%2C3&assets=image&collection=naip" @@ -157,7 +160,10 @@ async def test_info_path_with_bad_searchid(client: AsyncClient) -> None: async def test_bad_searchid(client: AsyncClient) -> None: route = "mosaic/tiles/{searchId}/{z}/{x}/{y}" - expected_content_hash = "9b989f86a149628eabfde894fb965982" # does not match the one we registered in the fixture + + # does not match the one we registered in the fixture + expected_content_hash = "9b989f86a149628eabfde894fb965982" + formatted_route = route.format( searchId=expected_content_hash, z=16, x=17218, y=26838 ) From e9a94aebd807dfdccb408f0755dfc0d67eeaa5fa Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Fri, 30 Aug 2024 09:28:51 -0400 Subject: [PATCH 18/25] remove echo --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e5530ab2..3966bf0e 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -15,7 +15,7 @@ jobs: run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - name: Verify Azurite Key was retrieved correctly - if: (echo $AZURITE_ACCOUNT_KEY | cut -b 1-4) == 'Eby8' + if: ($AZURITE_ACCOUNT_KEY | cut -b 1-4) == 'Eby8' run: echo GOT HERE - name: Run cibuild From 09ef95080ddc61251f55140de287589700e87e2b Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Fri, 30 Aug 2024 09:32:34 -0400 Subject: [PATCH 19/25] use env --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 3966bf0e..14527f11 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -15,7 +15,7 @@ jobs: run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - name: Verify Azurite Key was retrieved correctly - if: ($AZURITE_ACCOUNT_KEY | cut -b 1-4) == 'Eby8' + if: contains(env.AZURITE_ACCOUNT_KEY, 'Eby8') run: echo GOT HERE - name: Run cibuild From f06975a2f469db8cf94bc101096beaf8c966b619 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Fri, 30 Aug 2024 09:33:16 -0400 Subject: [PATCH 20/25] test failure --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 14527f11..98fcd78e 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -15,7 +15,7 @@ jobs: run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - name: Verify Azurite Key was retrieved correctly - if: contains(env.AZURITE_ACCOUNT_KEY, 'Eby8') + if: contains(env.AZURITE_ACCOUNT_KEY, 'Aby8') run: echo GOT HERE - name: Run cibuild From 0cbff10bad679b1865ca07cb7f9e737765b65ceb Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Fri, 30 Aug 2024 09:38:07 -0400 Subject: [PATCH 21/25] fail step --- .github/workflows/pr.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 98fcd78e..53647d38 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -15,8 +15,8 @@ jobs: run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - name: Verify Azurite Key was retrieved correctly - if: contains(env.AZURITE_ACCOUNT_KEY, 'Aby8') - run: echo GOT HERE + if: "!startsWith(env.AZURITE_ACCOUNT_KEY, 'Aby8')" + run: echo Failed to find key at learn.microsoft.com && exit 1 - name: Run cibuild run: ./scripts/cibuild From e6f11e9cf32ef96a756e8a41fa741b9d58c20894 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Fri, 30 Aug 2024 09:39:54 -0400 Subject: [PATCH 22/25] try removing azurite from api validator --- .github/workflows/pr.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 53647d38..f844f1a7 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -15,7 +15,7 @@ jobs: run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - name: Verify Azurite Key was retrieved correctly - if: "!startsWith(env.AZURITE_ACCOUNT_KEY, 'Aby8')" + if: "!startsWith(env.AZURITE_ACCOUNT_KEY, 'Eby8')" run: echo Failed to find key at learn.microsoft.com && exit 1 - name: Run cibuild @@ -30,8 +30,5 @@ jobs: python-version: "3.10" # stac-api-validator requires >= 3.10 cache: "pip" - - name: Set Azurite Default Key - run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV - - - name: Validate + - name: API Validator run: ./scripts/validate From 2620b5408c5be19e320fece081631d0c54aeb23f Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Fri, 30 Aug 2024 09:46:04 -0400 Subject: [PATCH 23/25] autoformatter --- pctiler/tests/endpoints/test_pg_mosaic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pctiler/tests/endpoints/test_pg_mosaic.py b/pctiler/tests/endpoints/test_pg_mosaic.py index 52ffa105..a17e7150 100644 --- a/pctiler/tests/endpoints/test_pg_mosaic.py +++ b/pctiler/tests/endpoints/test_pg_mosaic.py @@ -163,7 +163,7 @@ async def test_bad_searchid(client: AsyncClient) -> None: # does not match the one we registered in the fixture expected_content_hash = "9b989f86a149628eabfde894fb965982" - + formatted_route = route.format( searchId=expected_content_hash, z=16, x=17218, y=26838 ) From fb0fe863de515854f09244ef6be9cc1bb82f8bcc Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Fri, 30 Aug 2024 09:47:33 -0400 Subject: [PATCH 24/25] pipeline tweak --- .github/workflows/pr.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f844f1a7..e31975b8 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -30,5 +30,8 @@ jobs: python-version: "3.10" # stac-api-validator requires >= 3.10 cache: "pip" + - name: Set Azurite Default Key + run: echo "AZURITE_ACCOUNT_KEY=$(curl https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite | grep "Account key:" | cut -b 24-111)" >> $GITHUB_ENV + - name: API Validator run: ./scripts/validate From ef1a9abfc53b44740129cd4294dce9067f5f2eb2 Mon Sep 17 00:00:00 2001 From: Marc Lichtman Date: Fri, 30 Aug 2024 11:57:26 -0400 Subject: [PATCH 25/25] Delete storage-use-azurite?tabs=visual-studio,blob-storage --- ...se-azurite?tabs=visual-studio,blob-storage | 1472 ----------------- 1 file changed, 1472 deletions(-) delete mode 100644 storage-use-azurite?tabs=visual-studio,blob-storage diff --git a/storage-use-azurite?tabs=visual-studio,blob-storage b/storage-use-azurite?tabs=visual-studio,blob-storage deleted file mode 100644 index 381c5c67..00000000 --- a/storage-use-azurite?tabs=visual-studio,blob-storage +++ /dev/null @@ -1,1472 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Use Azurite emulator for local Azure Storage development | Microsoft Learn - - - - - -
- Skip to main content - - - - - -
-
- - -
-
- -
-
- -
- -
- -
-
- -
- -
-
-
- - - - - -
- -
-
- -
-
- - - -
- - - - - Edit - -
-

Share via

- - - - -
- -
-
- -
-
-
- -
- -

Use the Azurite emulator for local Azure Storage development

The Azurite open-source emulator provides a free local environment for testing your Azure Blob, Queue Storage, and Table Storage applications. When you're satisfied with how your application is working locally, switch to using an Azure Storage account in the cloud. The emulator provides cross-platform support on Windows, Linux, and macOS.

-

Azurite supersedes the Azure Storage Emulator, and continues to be updated to support the latest versions of Azure Storage APIs.

-

This video shows you how to install and run the Azurite emulator.

-
-

The steps in the video are also described in the following sections. Select any of these tabs.

-

Install Azurite

-
- -
- -

Azurite is automatically available with Visual Studio 2022. The Azurite executable is updated as part of Visual Studio new version releases. If you're running an earlier version of Visual Studio, you can install Azurite by using either Node Package Manager (npm), DockerHub, or by cloning the Azurite GitHub repository.

-
- - - - -
-

Run Azurite

-
- -
- -

To use Azurite with most project types in Visual Studio, you first need to run the Azurite executable. Once the executable is running, Azurite listens for connection requests from the application. To learn more, see Running Azurite from the command line.

-

For Azure Functions projects and ASP.NET projects, you can choose to configure the project to start Azurite automatically. This configuration is done during the project setup. While this project configuration starts Azurite automatically, Visual Studio doesn't expose detailed Azurite configuration options. To customize detailed Azurite configuration options, run the Azurite executable before launching Visual Studio.

-

To learn more about configuring Azure Functions projects and ASP.NET projects to start Azurite automatically, see the following guidance:

- -

Azurite executable file location

-

The following table shows the location of the Azurite executable for different versions of Visual Studio running on a Windows machine:

- - - - - - - - - - - - - - - - - - - - - -
Visual Studio versionAzurite executable location
Visual Studio Community 2022C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator
Visual Studio Professional 2022C:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator
Visual Studio Enterprise 2022C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator
-

Running Azurite from the command line

-

You can find the Azurite executable file in the extensions folder of your Visual Studio installation, as detailed in the Azurite executable file location table.

-

Navigate to the appropriate location and start azurite.exe. After you run the executable file, Azurite listens for connections.

-
-

Azurite command-line output

-
-

To learn more about available command line options to configure Azurite, see Command line options.

-

Running Azurite from an Azure Functions project

-

In Visual Studio 2022, create an Azure Functions project. While setting the project options, mark the box labeled Use Azurite for runtime storage account.

-

- -A screenshot showing how to set Azurite to be the runtime storage account for an Azure Functions project. - - -

-

After you create the project, Azurite starts automatically. The location of the Azurite executable file is detailed in the Azurite executable file location table. The output looks similar to the following screenshot:

-

- -A screenshot showing output after setting Azurite to be the runtime storage account for an Azure Functions project. - - -

-

This configuration option can be changed later by modifying the project's Connected Services dependencies.

-

Running Azurite from an ASP.NET project

-

In Visual Studio 2022, create an ASP.NET Core Web App project. Then, open the Connected Services dialog box, select Add a service dependency, and then select Storage Azurite emulator.

-

- -A screenshot showing how to add Azurite as a dependency to an ASP.NET project. - - -

-

In the Configure Storage Azurite emulator dialog box, set the Connection string name field to StorageConnectionString, and then select Finish.

-

- -A screenshot showing how to configure a connection string to use Azurite with an ASP.NET project. - - -

-

When the configuration completes, select Close, and the Azurite emulator starts automatically. The location of the Azurite executable file is detailed in the Azurite executable file location table. The output looks similar to the following screenshot:

-

- -A screenshot showing output after connecting an ASP.NET project to the Azurite emulator. - - -

-

This configuration option can be changed later by modifying the project's Connected Services dependencies.

-
- - - - -
-

Command line options

-

This section details the command line switches available when launching Azurite.

-

Help

-

Optional - Get command-line help by using the -h or --help switch.

-
azurite -h
-azurite --help
-
-

Listening host

-
- -
- -

Optional - By default, Azurite listens to 127.0.0.1 as the local server. Use the --blobHost switch to set the address to your requirements.

-

Accept requests on the local machine only:

-
azurite --blobHost 127.0.0.1
-
-

Allow remote requests:

-
azurite --blobHost 0.0.0.0
-
-
-

Caution

-

Allowing remote requests may make your system vulnerable to external attacks.

-
-
- - -
-

Listening port configuration

-
- -
- -

Optional - By default, Azurite listens for the Blob service on port 10000. Use the --blobPort switch to specify the listening port that you require.

-
-

Note

-

After using a customized port, you need to update the connection string or corresponding configuration in your Azure Storage tools or SDKs.

-
-

Customize the Blob service listening port:

-
azurite --blobPort 8888
-
-

Let the system auto select an available port:

-
azurite --blobPort 0
-
-

The port in use is displayed during Azurite startup.

-
- - -
-

Workspace path

-

Optional - Azurite stores data to the local disk during execution. Use the -l or --location switch to specify a path as the workspace location. By default, the current process working directory is used. Note the lowercase 'l'.

-
azurite -l c:\azurite
-azurite --location c:\azurite
-
-

Access log

-

Optional - By default, the access log is displayed in the console window. Disable the display of the access log by using the -s or --silent switch.

-
azurite -s
-azurite --silent
-
-

Debug log

-

Optional - The debug log includes detailed information on every request and exception stack trace. Enable the debug log by providing a valid local file path to the -d or --debug switch.

-
azurite -d path/debug.log
-azurite --debug path/debug.log
-
-

Loose mode

-

Optional - By default, Azurite applies strict mode to block unsupported request headers and parameters. Disable strict mode by using the -L or --loose switch. Note the capital 'L'.

-
azurite -L
-azurite --loose
-
-

Version

-

Optional - Display the installed Azurite version number by using the -v or --version switch.

-
azurite -v
-azurite --version
-
-

Certificate configuration (HTTPS)

-

Optional - By default, Azurite uses the HTTP protocol. You can enable HTTPS mode by providing a path to a Privacy Enhanced Mail (.pem) or Personal Information Exchange (.pfx) certificate file to the --cert switch. HTTPS is required to connect to Azurite using OAuth authentication.

-

When --cert is provided for a PEM file, you must provide a corresponding --key switch.

-
azurite --cert path/server.pem --key path/key.pem
-
-

When --cert is provided for a PFX file, you must provide a corresponding --pwd switch.

-
azurite --cert path/server.pfx --pwd pfxpassword
-
-
HTTPS setup
-

For detailed information on generating PEM and PFX files, see HTTPS Setup.

-

OAuth configuration

-

Optional - Enable OAuth authentication for Azurite by using the --oauth switch.

-
azurite --oauth basic --cert path/server.pem --key path/key.pem
-
-
-

Note

-

OAuth requires an HTTPS endpoint. Make sure HTTPS is enabled by providing --cert switch along with the --oauth switch.

-
-

Azurite supports basic authentication by specifying the basic parameter to the --oauth switch. Azurite performs basic authentication, like validating the incoming bearer token, checking the issuer, audience, and expiry. Azurite doesn't check the token signature or permissions. To learn more about authorization, see Authorization for tools and SDKs.

-

Skip API version check

-

Optional - When starting up, Azurite checks that the requested API version is valid. The following command skips the API version check:

-
azurite --skipApiVersionCheck
-
-

Disable production-style URL

-

Optional. When using the fully qualified domain name instead of the IP in request Uri host, by default Azurite parses the storage account name from request URI host. You can force the parsing of the storage account name from request URI path by using --disableProductStyleUrl:

-
azurite --disableProductStyleUrl
-
-

In-memory persistence

-

Optional. By default, blob and queue metadata is persisted to disk and content is persisted to extent files. Table storage persists all data to disk. You can disable persisting any data to disk and only store data in-memory. In the in-memory persistence scenario, if the Azurite process is terminated, all data is lost. The default persistence behavior can be overridden using the following option:

-
azurite --inMemoryPersistence
-
-

This setting is rejected when the SQL-based metadata implementation is enabled (via AZURITE_DB), or when the --location option is specified.

-

Extent memory limit

-

Optional. By default, the in-memory extent store (for blob and queue content) is limited to 50% of the total memory on the host machine. The total is evaluated using os.totalmem(). This limit can be overridden using the following option:

-
azurite --extentMemoryLimit <megabytes>
-
-

There's no restriction on the value specified for this option, but virtual memory might be used if the limit exceeds the amount of available physical memory as provided by the operating system. A high limit might eventually lead to out of memory errors or reduced performance. This option is rejected when --inMemoryPersistence isn't specified.

-

To learn more, see Use in-memory storage.

-

Connect to Azurite with SDKs and tools

-

You can connect to Azurite from Azure Storage SDKs, or tools like Azure Storage Explorer. Authentication is required, and Azurite supports authorization with OAuth, Shared Key, and shared access signatures (SAS). Azurite also supports anonymous access to public containers.

-

To learn more about using Azurite with the Azure SDKs, see Azure SDKs.

-

Well-known storage account and key

-

Azurite accepts the same well-known account and key used by the legacy Azure Storage Emulator.

-
    -
  • Account name: devstoreaccount1
  • -
  • Account key: Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==
  • -
-

Custom storage accounts and keys

-

Azurite supports custom storage account names and keys by setting the AZURITE_ACCOUNTS environment variable in the following format: account1:key1[:key2];account2:key1[:key2];....

-

For example, use a custom storage account that has one key:

-
set AZURITE_ACCOUNTS="account1:key1"
-
-
export AZURITE_ACCOUNTS="account1:key1"
-
-
-

Note

-

The account keys must be a base64 encoded string.

-
-

Or use multiple storage accounts with two keys each:

-
set AZURITE_ACCOUNTS="account1:key1:key2;account2:key1:key2"
-
-
export AZURITE_ACCOUNTS="account1:key1:key2;account2:key1:key2"
-
-

Azurite refreshes custom account names and keys from the environment variable every minute by default. With this feature, you can dynamically rotate the account key, or add new storage accounts without restarting Azurite.

-
-

Note

-

The default devstoreaccount1 storage account is disabled when you set custom storage accounts. If you want to continue using devstoreaccount1 after enabling custom storage accounts, you need to add it to the list of custom accounts and keys in the AZURITE_ACCOUNTS environment variable.

-
-

The account keys must be a base64 encoded string.

-

Connection strings

-

The easiest way to connect to Azurite from your application is to configure a connection string in your application's configuration file that references the shortcut UseDevelopmentStorage=true. Here's an example of a connection string in an app.config file:

-
<appSettings>
-  <add key="StorageConnectionString" value="UseDevelopmentStorage=true" />
-</appSettings>
-
-
HTTP connection strings
-

You can pass the following connection strings to the Azure SDKs or tools, like Azure CLI 2.0 or Storage Explorer.

-

The full connection string is:

-

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=http://127.0.0.1:10001/devstoreaccount1;TableEndpoint=http://127.0.0.1:10002/devstoreaccount1;

-

To connect to a specific service, you can use the following connection strings:

-
- -
- -

To connect to Blob Storage only, the connection string is:

-

DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;

-
- - -
-
HTTPS connection strings
-

The full HTTPS connection string is:

-

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;QueueEndpoint=https://127.0.0.1:10001/devstoreaccount1;TableEndpoint=https://127.0.0.1:10002/devstoreaccount1;

-

To connect to a specific service, you can use the following connection strings:

-
- -
- -

To use the blob service only, the HTTPS connection string is:

-

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;

-
- - -
- -

If you used dotnet dev-certs to generate your self-signed certificate, use the following connection string.

-

DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://localhost:10000/devstoreaccount1;QueueEndpoint=https://localhost:10001/devstoreaccount1;TableEndpoint=https://localhost:10002/devstoreaccount1;

-

Update the connection string when using custom storage accounts and keys.

-

For more information, see Configure Azure Storage connection strings.

-

Azure SDKs

-

To connect to Azurite with the Azure SDKs, follow these steps:

- -

Once the certificates are in place, start Azurite with the following command line options:

-
azurite --oauth basic --cert cert-name.pem --key cert-name-key.pem
-
-

Replace cert-name.pem and certname-key.pem with the names of your certificate and key files. If you're using a PFX certificate, use the --pwd option instead of the --key option.

-
- -
- -

To interact with Blob Storage resources, you can instantiate a BlobContainerClient, BlobServiceClient, or BlobClient.

-

The following examples show how to authorize a BlobContainerClient object using three different authorization mechanisms: DefaultAzureCredential, connection string, and shared key. DefaultAzureCredential provides a Bearer token-based authentication mechanism, and uses a chain of credential types used for authentication. Once authenticated, this credential provides the OAuth token as part of client instantiation. To learn more, see the DefaultAzureCredential class reference.

-
// With container URL and DefaultAzureCredential
-var client = new BlobContainerClient(
-    new Uri("https://127.0.0.1:10000/devstoreaccount1/container-name"), new DefaultAzureCredential()
-  );
-
-// With connection string
-var client = new BlobContainerClient(
-    "DefaultEndpointsProtocol=https;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=https://127.0.0.1:10000/devstoreaccount1;", "container-name"
-  );
-
-// With account name and key
-var client = new BlobContainerClient(
-    new Uri("https://127.0.0.1:10000/devstoreaccount1/container-name"),
-    new StorageSharedKeyCredential("devstoreaccount1", "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")
-  );
-
-
- - -
-

Microsoft Azure Storage Explorer

-

You can use Storage Explorer to view the data stored in Azurite.

-
Connect to Azurite using HTTP
-

In Storage Explorer, connect to Azurite by following these steps:

-
    -
  1. Select the Manage Accounts icon
  2. -
  3. Select Add an account
  4. -
  5. Select Attach to a local emulator
  6. -
  7. Select Next
  8. -
  9. Edit the Display name field to a name of your choice
  10. -
  11. Select Next again
  12. -
  13. Select Connect
  14. -
-
Connect to Azurite using HTTPS
-

By default, Storage Explorer doesn't open an HTTPS endpoint that uses a self-signed certificate. If you're running Azurite with HTTPS, you're likely using a self-signed certificate. In Storage Explorer, import SSL certificates via the Edit -> SSL Certificates -> Import Certificates dialog.

-
Import Certificate to Storage Explorer
-
    -
  1. Find the certificate on your local machine.
  2. -
  3. In Storage Explorer, go to Edit -> SSL Certificates -> Import Certificates and import your certificate.
  4. -
-

If you don't import a certificate, you get an error:

-

unable to verify the first certificate or self signed certificate in chain

-
Add Azurite via HTTPS connection string
-

Follow these steps to add Azurite HTTPS to Storage Explorer:

-
    -
  1. Select Toggle Explorer
  2. -
  3. Select Local & Attached
  4. -
  5. Right-click on Storage Accounts and select Connect to Azure Storage.
  6. -
  7. Select Use a connection string
  8. -
  9. Select Next.
  10. -
  11. Enter a value in the Display name field.
  12. -
  13. Enter the HTTPS connection string from the previous section of this document
  14. -
  15. Select Next
  16. -
  17. Select Connect
  18. -
-

Workspace structure

-

The following files and folders might be created in the workspace location when initializing Azurite.

-
    -
  • __blobstorage__ - Directory containing Azurite blob service persisted binary data
  • -
  • __queuestorage__ - Directory containing Azurite queue service persisted binary data
  • -
  • __tablestorage__ - Directory containing Azurite table service persisted binary data
  • -
  • __azurite_db_blob__.json - Azurite blob service metadata file
  • -
  • __azurite_db_blob_extent__.json - Azurite blob service extent metadata file
  • -
  • __azurite_db_queue__.json - Azurite queue service metadata file
  • -
  • __azurite_db_queue_extent__.json - Azurite queue service extent metadata file
  • -
  • __azurite_db_table__.json - Azurite table service metadata file
  • -
  • __azurite_db_table_extent__.json - Azurite table service extent metadata file
  • -
-

To clean up Azurite, delete above files and folders and restart the emulator.

-

Differences between Azurite and Azure Storage

-

There are functional differences between a local instance of Azurite and an Azure Storage account in the cloud.

-

Endpoint and connection URL

-

The service endpoints for Azurite are different from the endpoints of an Azure Storage account. The local computer doesn't do domain name resolution, requiring Azurite endpoints to be local addresses.

-

When you address a resource in an Azure Storage account, the account name is part of the URI host name. The resource being addressed is part of the URI path:

-

<http|https>://<account-name>.<service-name>.core.windows.net/<resource-path>

-

The following URI is a valid address for a blob in an Azure Storage account:

-

https://myaccount.blob.core.windows.net/mycontainer/myblob.txt

-
IP-style URL
-

Since the local computer doesn't resolve domain names, the account name is part of the URI path instead of the host name. Use the following URI format for a resource in Azurite:

-

http://<local-machine-address>:<port>/<account-name>/<resource-path>

-

The following address might be used for accessing a blob in Azurite:

-

http://127.0.0.1:10000/myaccount/mycontainer/myblob.txt

-
Production-style URL
-

Optionally, you could modify your hosts file to access an account with production-style URL.

-

First, add one or more lines to your hosts file. For example:

-
127.0.0.1 account1.blob.localhost
-127.0.0.1 account1.queue.localhost
-127.0.0.1 account1.table.localhost
-
-

Next, set environment variables to enable customized storage accounts and keys:

-
set AZURITE_ACCOUNTS="account1:key1:key2"
-
-

You could add more accounts. See the Custom storage accounts and keys section of this article.

-

Start Azurite and use a customized connection string to access your account. In the following example, the connection string assumes that the default ports are used.

-
DefaultEndpointsProtocol=http;AccountName=account1;AccountKey=key1;BlobEndpoint=http://account1.blob.localhost:10000;QueueEndpoint=http://account1.queue.localhost:10001;TableEndpoint=http://account1.table.localhost:10002;
-
-

Don't access default account in this way with Azure Storage Explorer. There's a bug that Storage Explorer is always adding account name in URL path, causing failures.

-

By default, when using Azurite with a production-style URL, the account name should be the host name in fully qualified domain name such as http://devstoreaccount1.blob.localhost:10000/container. To use production-style URL with account name in the URL path such as http://foo.bar.com:10000/devstoreaccount1/container, make sure to use the --disableProductStyleUrl parameter when you start Azurite.

-

If you use host.docker.internal as request Uri host (For example: http://host.docker.internal:10000/devstoreaccount1/container), Azurite gets the account name from the request Uri path. This behavior is true regardless of whether you use the --disableProductStyleUrl parameter when you start Azurite.

-

Scaling and performance

-

Azurite doesn't support large numbers of connected clients. There's no performance guarantee. Azurite is intended for development and testing purposes.

-

Error handling

-

Azurite is aligned with Azure Storage error handling logic, but there are differences. For example, error messages might be different, while error status codes align.

-

RA-GRS

-

Azurite supports read-access geo-redundant replication (RA-GRS). For storage resources, access the secondary location by appending -secondary to the account name. For example, the following address might be used for accessing a blob using the read-only secondary in Azurite:

-

http://127.0.0.1:10000/devstoreaccount1-secondary/mycontainer/myblob.txt

-

Table support

-

Support for tables in Azurite is currently in preview. For more information, see the Azurite V3 Table project.

-

Support for durable functions requires tables.

-
-

Important

-

Azurite support for Table Storage is currently in PREVIEW. See the Supplemental Terms of Use for Microsoft Azure Previews for legal terms that apply to Azure features that are in beta, preview, or otherwise not yet released into general availability.

-
-

Azurite is open-source

-

Contributions and suggestions for Azurite are welcome. Go to the Azurite GitHub project page or GitHub issues for milestones and work items we're tracking for upcoming features and bug fixes. Detailed work items are also tracked in GitHub.

-

Next steps

- -
-
- - -
- - - -
- - -
- - - - - -
- -
- - -
- -
- - \ No newline at end of file