Azure Blob Storage

Fetch a config or secret blob from Azure Blob Storage.

Schemeazblob://
Modulegithub.com/xavidop/mamori/providers/azblob
Sensitiveno (opt-in with WithSensitive)
Watchpoll (ETag)
AuthDefaultAzureCredential (+ account URL)

Install

go get github.com/xavidop/mamori/providers/azblob
import _ "github.com/xavidop/mamori/providers/azblob"

Using the ref

An azblob:// ref points at one blob in a container. The storage account is provider configuration, not part of the ref.

azblob://<container>/<blob>[#json-key]
PartRequiredWhat it means
<container>yesThe blob container name.
<blob>yesThe blob name. It may contain slashes (a virtual-directory path), e.g. config/app.json.
#json-keynoTreat the blob as a JSON object and return one field of it.

Examples

  • azblob://config/app.json fetches the whole blob from the config container - decode it with flatten:"json".
  • azblob://config/app.json#database returns just the database field of that JSON object.
  • azblob://secrets/tls/app.pem fetches a nested blob (the blob name carries slashes).
type Config struct {
	AppConfig AppConfig `source:"azblob://config/app.json" flatten:"json"`
}

mamori.WithProvider(azblobprov.New(
	azblobprov.WithAccountURL("https://myaccount.blob.core.windows.net"),
))

The storage account is provider-level configuration (set it with WithAccountURL / WithServiceURL, or the AZURE_STORAGE_ACCOUNT environment variable), so the same ref can resolve against different accounts across environments. The blob name may contain slashes, so config/app.json is a single name. Value.Version is the blob ETag (or version id when versioning is enabled), so change detection is cheap. Blobs are not marked sensitive by default; pass WithSensitive(true) for accounts that hold secrets.

Watch

mamori polls (WithPollInterval + jitter) using the ETag. For push, Azure Event Grid blob events can trigger an on-demand reload.

Configuration

Authentication uses DefaultAzureCredential (environment, managed identity, Azure CLI). Verified with an in-memory fake; live behavior is covered by //go:build integration tests.

Error classification

HTTP statusmamori kind
404not_found
403permission_denied
401unauthenticated
429rate_limited
5xxunavailable
400invalid
anything elseunknown

A transport failure (no HTTP response at all) stays unknown, since it could be a bug in this provider rather than a genuine backend outage. *azcore.ResponseError stays reachable with errors.As, both through the not-found path (typed bloberror codes and a raw 404) and the classified fallback path.

Verified by unit tests and the conformance kit against an in-memory fake; live Azure behavior is covered by //go:build integration tests.