Overview
The Azure Blob Storage data source template turns a blob container (optionally scoped to a prefix) into a Validatar data source. It lists blobs with azure-storage-blob, catalogs every blob as a table, reads and profiles the common data formats (CSV, Excel, Parquet, Avro, JSON, XML, GeoJSON), and captures statistics for non-tabular blobs (PDF, Markdown, images, plain text). Blob prefixes become schemas, blobs become tables, and columns are inferred from each blob's contents.
This is a Python (Script) template that uses the same shared file-reading library as the Windows Directory and AWS S3 templates. The macros, profiling, and custom fields are identical — only the storage layer (azure-storage-blob) and the connection parameters differ.
Platform: Azure Blob Storage / ADLS Gen2
Connection Category: Script (PythonScript)
Runs on: any runtime that has azure-storage-blob and network reachability to the storage account — typically the Data Agent
Template version: 1.0.0
How It Works
- Prefixes are schemas, blobs are tables. The template lists the container under the configured prefix. Each virtual directory becomes a schema (
.-rooted, e.g..\csv\customer_1001); each blob becomes a table. - Columns are inferred on read. Blobs are read into data frames and columns/types inferred (Parquet and Avro carry explicit types; CSV and Excel are inferred).
- One ingestion pass catalogs the whole scope at the data-source level.
- Scope with
container+prefixand control depth withinclude_sub_folders.
Authentication
The template supports three authentication styles from a single template. Which one is used is determined by which credential parameters you fill in.
| Method | Parameters to fill | When to use |
|---|---|---|
| Connection string | Connection String | Simplest setup; the connection string embeds the account and its key |
| SAS token | Account URL + SAS Token | Least-privilege, time-bounded access scoped to a container or prefix — the recommended production pattern |
| Account key | Account URL + Account Key | Full-account access via the storage account key, without embedding it in a connection string |
The adapter picks the method by inspecting which parameters are present: a connection string is used directly; otherwise it builds a client from the Account URL plus whichever credential (SAS token or account key) you supplied.
Tip: Prefer a SAS token in production. Scope it to read + list on just the container (or a specific prefix) and give it an expiry, so Validatar's access is bounded in both scope and time. A SAS with only read/list permission is all this template needs.
Warning: Connection strings and account keys grant broad access to the storage account. Treat them as high-value secrets, and rotate them on the account's key-rotation schedule.
Connection Parameters
| Parameter | Reference key | Type | Required | Description |
|---|---|---|---|---|
| Container | container |
String | Yes | Blob container name. |
| Prefix | prefix |
String | No | Blob-name prefix to scope the catalog. |
| Account URL | account_url |
String | No | https://<account>.blob.core.windows.net (for SAS or account-key auth). |
| SAS Token | sas_token |
Secret | No | SAS token (used with Account URL). |
| Connection String | connection_string |
Secret | No | Full connection string (alternative to Account URL + credential). |
| Account Key | account_key |
Secret | No | Storage account key (used with Account URL). |
| Include Sub Folders | include_sub_folders |
Boolean | Yes | Descend into nested blob prefixes. Default: true. |
Required Python Packages
These must be present on the runtime that executes the source (the Data Agent, or a cloud runtime that carries the SDK).
Required
azure-storage-blob— the Azure Blob client (required for this template)pandas,numpy— the core data-frame and numeric layerpyarrow— Parquet / ORC / Featherfastavro— Avroopenpyxl— Excel (.xlsx/.xlsm)
Optional (features degrade gracefully if absent)
fitz(PyMuPDF) — PDF statisticsPillow(PIL) — image statisticscharset_normalizer— text-encoding detectionlxml— XML reading
Note: The library degrades per blob, not per run — a missing optional package only affects the blobs that need it; the rest of the catalog continues.
Capabilities
Supported File Types
| Catalog file type | Extensions | Read as |
|---|---|---|
| Delimited | .csv, .tsv, .tab |
Tabular (delimiter sniffed) |
| Fixed Width / Text | .txt, .flat, .dat |
Tabular |
| Excel | .xlsx, .xlsm, .xls |
Tabular |
| Columnar | .parquet, .orc, .feather |
Tabular (explicit types) |
| Row Binary | .avro |
Tabular (explicit types) |
| Semi-Structured | .json, .jsonl, .ndjson, .xml, .geojson |
Tabular (flattened / normalized) |
| Document | .pdf, .md, .markdown, .rst |
Content statistics |
| Image | .png, .jpg, .jpeg, .gif, .bmp, .tif, .tiff, .webp |
Content statistics |
Note: Line-delimited JSON is detected even when a blob has a
.jsonextension, and flattened into columns.
Macros
The template ships with 21 generic macros. Because every macro goes through the shared reader, the same test works against any blob and any supported format. Parameters are metadata-linked (Folder → Schema, File → Table, Column) so they render as catalog-driven dropdowns.
A. Single-blob data
| Macro | Returns |
|---|---|
| File - Read Data (any type) | The whole blob as a dataset |
| File - First N Rows | The first N rows (default 100) |
| File - Row Count | Row count as a single value |
| File - Schema (columns + inferred types) | Column list with inferred type and null % |
| File - Profile One Column | Profile statistics for one column |
| File - Row Count Grouped by Column | Group-by counts |
| File - Aggregate a Column | sum / min / max / mean / count / nunique |
B. Pattern & union (multi-blob)
| Macro | Returns |
|---|---|
| Folder - Files Matching a Pattern | Blobs whose name matches a glob (e.g. account_*.avro) |
| Folder - Union Files Matching a Pattern | Every matching blob read and unioned (schema-aligned, source-tagged) |
| Folder - Row Count Across Matching Files | Per-blob and total row counts |
| Folder - Schema Consistency Across Files | Each blob's columns and whether they match the first (partitioned extracts) |
C. Prefix & blob information
| Macro | Returns |
|---|---|
| Folder - File Inventory | Every blob with size, detected type, and modified date |
| Folder - Summary | One-row rollup: blob count, total size, distinct types, date range |
| File - Full Metadata | One blob's size, modified date, MD5, and (if tabular) row/column counts |
D. Content statistics (including non-tabular)
| Macro | Returns |
|---|---|
| File - Content Stats (any type) | Type-aware stats for any blob |
| PDF - Statistics | Pages, words, embedded images, title/author, encryption flag |
| Markdown - Statistics | Headings, links, images, code blocks, table rows |
| Text - Statistics | Lines, words, encoding, blank lines, longest line |
| Image - Statistics | Width/height, megapixels, format, mode, alpha |
| JSON - Statistics | Record count, nesting depth, top-level keys |
| XML - Statistics | Root tag, element count, distinct tags, depth |
Tip: Folder - Union Files Matching a Pattern unifies partitioned blob layouts — point it at a prefix of
*.avroor*.parquetblobs and it returns one dataset with a_source_filecolumn, so you can validate the combined set and still trace any row to its blob.
See Macros for how macros are used when building tests.
Metadata Ingestion
Ingestion runs once at the data-source level. It lists the container under the prefix, registers each blob prefix as a schema and each blob as a table, and populates the File Info catalog custom fields — including per-prefix rollups (blob count, total size, distinct file types, newest/oldest modified). Column-level metadata is discovered on demand by the profile set.
See Metadata Ingestion Scripts — Python Templates.
Profiling
The template ships one profile: File Profile (columns + table metrics, any file type) — the same type-safe profiler as the Windows Directory template. Run it as a profile set against a prefix to profile every blob in it. Following the principle that numeric/statistical values are profiles and descriptors are custom fields, it produces:
- Column-level profiles: null/blank/distinct counts and percentages, length statistics, most-common value, numeric statistics (min/max/mean/median/standard deviation, zero/negative counts), and date range.
- Table-level file metrics: file size (bytes), file age (days), row count, column count, and type-specific metrics (PDF page count, content word/line/record count, image width/height).
See Profiling Configuration — Python Templates.
Catalog Custom Fields (required dependency)
The ingestion script emits File Info catalog custom fields to describe blobs and prefixes — the text/tag/date descriptors and prefix rollups that don't fit the numeric profile model. Import the File Info - Catalog Custom Fields set before running ingestion; Validatar silently drops custom-field columns with no matching definition.
Schema level (prefix rollups): Contains Files, Schema Object Represents, Full Path, File Count, Total Size (bytes), Distinct File Types, Readable File Count, Newest Modified, Oldest Modified
Table level (per blob): File Type, File Name, Sheet Name, File Size, File Total Bytes, File Extension, Date Modified, File Logical Table
Warning: Catalog custom fields import through the UI only (Settings > Catalog Custom Fields > Import) and require the GlobalCustomMetadataAdmin role.
Installation
- Import the custom fields first — the File Info - Catalog Custom Fields set (Settings > Catalog Custom Fields > Import).
- Import the template — Settings > Data Source Templates > Import, select the Azure Blob Storage template file.
- Create a data source and set Container and Prefix, then supply credentials for one auth method (connection string; or Account URL + SAS token; or Account URL + account key).
- Assign a runtime with
azure-storage-bloband network access to the storage account. - Run metadata ingestion, then run the File Profile profile set.
What You Still Need to Configure
- Auth method — connection string, SAS token, or account key. Prefer a scoped, time-bounded SAS token in production.
- Container access — read + list on the container (or a prefix, for a scoped SAS).
- Runtime placement — a Data Agent or cloud runtime that carries
azure-storage-blob. - Scope — set
prefixto avoid cataloging an entire large container, andinclude_sub_foldersto control depth.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Authentication / authorization error | Wrong or expired credential; SAS lacks read/list | Re-issue the SAS with read + list; verify the connection string or account key |
| Empty catalog | Wrong container/prefix | Verify the container name and prefix |
| No auth method resolves | None of the credential combinations are complete | Provide a connection string, or Account URL + SAS token, or Account URL + account key |
| A single blob errors | Missing optional package for that format | Install the package (fastavro, openpyxl, pyarrow, fitz, Pillow) |
| Custom-field values missing | File Info custom fields not imported before ingestion | Import the File Info set, then re-run ingestion |