
Eventhouse Authoring Cli
- 118 installs
- 934 repo stars
- Updated July 30, 2026
- microsoft/skills-for-fabric
How to create/alter KQL tables, ingest data, configure policies, and manage materialized views in Fabric Eventhouse using CLI commands.
About
The eventhouse-authoring-cli skill enables developers to programmatically manage Fabric Eventhouse and KQL Database schemas, data ingestion, and policies through CLI-based KQL management commands. It supports table creation and alteration, bulk and streaming ingestion from storage and OneLake, retention/caching/partitioning policies, materialized views, stored functions, and update policies for automated ETL. Uses az rest with Kusto REST API and requires Admin or Ingestor role access. Ideal for schema deployment scripts, data pipeline automation, and infrastructure-as-code workflows in data engineering contexts.
- Execute KQL management commands (create-merge, alter, drop, ingestion) via az rest pattern
- Support for inline, blob storage, OneLake, and streaming ingestion with data mappings
- Configure retention, caching, partitioning, and streaming ingestion policies
- Create and manage materialized views with backfill and health monitoring
- Schema evolution and export with safe idempotent commands for CI/CD deployment
Eventhouse Authoring Cli by the numbers
- 118 all-time installs (skills.sh)
- +7 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #2,862 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/microsoft/skills-for-fabric --skill eventhouse-authoring-cliAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 118 |
|---|---|
| repo stars | ★ 934 |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 30, 2026 |
| Repository | microsoft/skills-for-fabric ↗ |
What it does
Execute KQL management commands (table creation, ingestion, policies, functions, materialized views) against Fabric Eventhouse via CLI.
Who is it for?
Data engineers and backend developers automating Eventhouse schema deployment, ingestion workflows, ETL pipelines, and policy management in production environments.
Skip if: Read-only data exploration (use eventhouse-consumption-cli); teams requiring UI-only workflows; non-KQL databases.
When should I use this skill?
User requests create KQL table, kql ingestion, ingest into eventhouse, kql function, materialized view, kql retention policy, eventhouse schema, kql authoring, create eventhouse table, kql mapping.
What you get
Schema and ingestion pipelines deployed via idempotent KQL commands; tables, functions, views, and policies provisioned consistently across environments.
Files
Update Check — ONCE PER SESSION (mandatory)
The first time this skill is used in a session, run the check-updates skill before proceeding.
- GitHub Copilot CLI / VS Code: invoke the check-updates skill.- Claude Code / Cowork / Cursor / Windsurf / Codex: compare local vs remote package.json version.
- Skip if the check was already performed earlier in this session.
CRITICAL NOTES
1. To find the workspace details (including its ID) from workspace name: list all workspaces and, then, use JMESPath filtering
2. To find the item details (including its ID) from workspace ID, item type, and item name: list all items of that type in that workspace and, then, use JMESPath filtering
eventhouse-authoring-cli — Eventhouse Authoring and Management via CLI
Table of Contents
| Task | Reference | Notes |
|---|---|---|
| Finding Workspaces and Items in Fabric | COMMON-CLI.md § Finding Workspaces and Items in Fabric | Mandatory — READ link first [needed for workspace/item ID resolution] |
| Fabric Topology & Key Concepts | COMMON-CORE.md § Fabric Topology & Key Concepts | Hierarchy, Finding Things in Fabric |
| Environment URLs | COMMON-CORE.md § Environment URLs | KQL Cluster URI, KQL Ingestion URI |
| Authentication & Token Acquisition | COMMON-CORE.md § Authentication & Token Acquisition | Wrong audience = 401; KQL audience: kusto.kusto.windows.net |
| Core Control-Plane REST APIs | COMMON-CORE.md § Core Control-Plane REST APIs | List Workspaces, List Items, Item Creation |
| Pagination | COMMON-CORE.md § Pagination | |
| Long-Running Operations (LRO) | COMMON-CORE.md § Long-Running Operations (LRO) | |
| Rate Limiting & Throttling | COMMON-CORE.md § Rate Limiting & Throttling | |
| OneLake Data Access | COMMON-CORE.md § OneLake Data Access | Requires storage.azure.com token, not Fabric token |
| Job Execution | COMMON-CORE.md § Job Execution | |
| Capacity Management | COMMON-CORE.md § Capacity Management | |
| Gotchas & Troubleshooting | COMMON-CORE.md § Gotchas & Troubleshooting | |
| Best Practices | COMMON-CORE.md § Best Practices | |
| Tool Selection Rationale | COMMON-CLI.md § Tool Selection Rationale | |
| Authentication Recipes | COMMON-CLI.md § Authentication Recipes | az login flows and token acquisition |
Fabric Control-Plane API via az rest | COMMON-CLI.md § Fabric Control-Plane API via az rest | Always pass `--resource https://api.fabric.microsoft.com` or az rest fails |
| Pagination Pattern | COMMON-CLI.md § Pagination Pattern | |
| Long-Running Operations (LRO) Pattern | COMMON-CLI.md § Long-Running Operations (LRO) Pattern | |
OneLake Data Access via curl | COMMON-CLI.md § OneLake Data Access via curl | Use curl not az rest (different token audience) |
| SQL / TDS Data-Plane Access | COMMON-CLI.md § SQL / TDS Data-Plane Access | sqlcmd (Go) — not for KQL, but useful for cross-workload |
| Job Execution (CLI) | COMMON-CLI.md § Job Execution | |
| OneLake Shortcuts | COMMON-CLI.md § OneLake Shortcuts | |
| Capacity Management (CLI) | COMMON-CLI.md § Capacity Management | |
| Composite Recipes | COMMON-CLI.md § Composite Recipes | |
| Gotchas & Troubleshooting (CLI-Specific) | COMMON-CLI.md § Gotchas & Troubleshooting (CLI-Specific) | az rest audience, shell escaping, token expiry |
Quick Reference: az rest Template | COMMON-CLI.md § Quick Reference: az rest Template | |
| Quick Reference: Token Audience / CLI Tool Matrix | COMMON-CLI.md § Quick Reference: Token Audience ↔ CLI Tool Matrix | Which --resource + tool for each service |
| Authoring Capability Matrix | EVENTHOUSE-AUTHORING-CORE.md § Authoring Capability Matrix | Read first — KQL Database vs Shortcut (read-only); connection requires Admin/Ingestor role |
| Table Management and Schema Evolution | EVENTHOUSE-AUTHORING-CORE.md § Table Management and Schema Evolution | Create Table, Create-Merge (idempotent), Alter / Rename / Drop, Schema Evolution (Rename, Swap/Blue-Green) |
| Ingestion and Data Mappings | EVENTHOUSE-AUTHORING-CORE.md § Ingestion and Data Mappings | Inline, Set-or-Append/Replace, From Storage, Streaming, Data Mappings (CSV, JSON) |
| Policies | EVENTHOUSE-AUTHORING-CORE.md § Policies | Retention, Caching, Partitioning, Merge |
| Materialized Views | EVENTHOUSE-AUTHORING-CORE.md § Materialized Views | Create, Alter, Lifecycle, Supported aggregations |
| Stored Functions and Update Policies | EVENTHOUSE-AUTHORING-CORE.md § Stored Functions and Update Policies | Stored Functions, Update Policies (auto-transform on ingestion) |
| External Tables | EVENTHOUSE-AUTHORING-CORE.md § External Tables | OneLake / ADLS External Table, Query External Table |
| Permission Model | EVENTHOUSE-AUTHORING-CORE.md § Permission Model | Database Roles, Grant Permissions |
| Authoring Gotchas and Troubleshooting | EVENTHOUSE-AUTHORING-CORE.md § Authoring Gotchas and Troubleshooting Reference | 10 numbered issues with cause + fix |
| Bash Templates | authoring-script-templates.md § Bash Templates | Create Table + Ingest, Schema Deployment, Export Schema, Set Retention/Caching |
| PowerShell Templates | authoring-script-templates.md § PowerShell Templates | Create Table + Ingest, Schema Deployment |
| Tool Stack | SKILL.md § Tool Stack | |
| Connection | SKILL.md § Connection | |
| Authoring Scope | SKILL.md § Authoring Scope | |
| Execute KQL Command | SKILL.md § Execute KQL Command | `az rest` pattern — write JSON body, then execute |
| Table Management via CLI | SKILL.md § Table Management via CLI | Create Table, Add Column, Drop Table |
| Data Ingestion via CLI | SKILL.md § Data Ingestion via CLI | Inline, From Storage, From OneLake, Set-or-Append |
| Policies via CLI | SKILL.md § Policies via CLI | Retention, Caching, Streaming Ingestion |
| Materialized Views via CLI | SKILL.md § Materialized Views via CLI | |
| Functions and Update Policies via CLI | SKILL.md § Functions and Update Policies via CLI | Create Function, Create Update Policy |
| Schema Evolution via CLI | SKILL.md § Schema Evolution via CLI | Safe Schema Deployment Script, Export Current Schema |
| Monitoring Authoring Operations | SKILL.md § Monitoring Authoring Operations | |
| Must / Prefer / Avoid / Troubleshooting | SKILL.md § Must / Prefer / Avoid / Troubleshooting | MUST DO / AVOID / PREFER checklists |
| Agentic Workflows | SKILL.md § Agentic Workflows | Exploration Before Authoring, Script Generation Workflow |
| Examples | SKILL.md § Examples | |
| Agent Integration Notes | SKILL.md § Agent Integration Notes |
---
Tool Stack
| Tool | Purpose | Install |
|---|---|---|
| az cli | KQL management commands via Kusto REST API; Fabric control-plane discovery | winget install Microsoft.AzureCLI |
| jq | JSON processing and output formatting | winget install jqlang.jq |
---
Connection
Same as eventhouse-consumption-cli. Authoring requires elevated roles:
# Discover KQL Database query URI
WS_ID="<workspace-id>"
az rest --method GET \
--url "https://api.fabric.microsoft.com/v1/workspaces/${WS_ID}/kqlDatabases" \
--resource "https://api.fabric.microsoft.com" \
| jq '.value[] | {name: .displayName, queryUri: .properties.queryServiceUri}'
# Set connection variables
CLUSTER_URI="https://<cluster>.kusto.fabric.microsoft.com"
DB_NAME="MyDatabase"
# Verify admin access
cat > /tmp/kql_body.json << EOF
{"db":"${DB_NAME}","csl":".show database ${DB_NAME} principals | where Role == 'Admin'"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/mgmt" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'---
Authoring Scope
| Operation | Command Pattern |
|---|---|
| Create table | .create-merge table T (cols) |
| Add column | .alter-merge table T (NewCol: type) |
| Drop table | .drop table T ifexists |
| Ingest data | .ingest into table T (...) |
| Set retention | .alter table T policy retention ... |
| Set caching | .alter table T policy caching hot = Nd |
| Create function | .create-or-alter function F() { ... } |
| Create materialized view | .create materialized-view MV on table T { ... } |
| Create update policy | .alter table T policy update ... |
| Create data mapping | .create table T ingestion csv mapping ... |
---
Execute KQL Command
All KQL management commands in this skill follow the same az rest pattern. After setting CLUSTER_URI and DB, write the JSON body to /tmp/kql_body.json and execute:
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":"<KQL management command>"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/mgmt" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'Nested JSON — For commands whose KQL contains embedded JSON (policies, mappings), use<< 'EOF'(single-quoted) to prevent shell expansion of backslash-escaped quotes, and replace${DB}with the literal database name.
PowerShell equivalent —@{db=$Database;csl=$Command} | ConvertTo-Json -Compress | Out-File $env:TEMP\kql_body.json -Encoding utf8NoBOMthen--body "@$env:TEMP\kql_body.json". See PowerShell Templates.
---
Table Management via CLI
Create Table (Idempotent)
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".create-merge table Events (Timestamp: datetime, EventType: string, UserId: string, Properties: dynamic, Duration: real)"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandAdd Column
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".alter-merge table Events (Region: string)"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandDrop Table
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".drop table Events ifexists"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command---
Data Ingestion via CLI
Inline Ingestion (Testing)
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".ingest inline into table Events <| 2025-01-15T10:00:00Z,Login,user1,{},0.5\n2025-01-15T10:01:00Z,Click,user2,{},0.2"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandIngest from Storage
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".ingest into table Events (h'https://mystorage.blob.core.windows.net/data/events.csv.gz;impersonate') with (format='csv', ingestionMappingReference='EventsCsvMapping', ignoreFirstRecord=true)"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandIngest from OneLake
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".ingest into table Events (h'abfss://workspace@onelake.dfs.fabric.microsoft.com/lakehouse.Lakehouse/Files/events.parquet;impersonate') with (format='parquet')"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandSet-or-Append from Query
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".set-or-append CleanEvents <| RawEvents | where IsValid == true | project Timestamp, EventType, UserId"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command---
Policies via CLI
Retention
# Set 365-day retention
cat > /tmp/kql_body.json << 'EOF'
{"db":"MyDB","csl":".alter table Events policy retention '{\"SoftDeletePeriod\":\"365.00:00:00\",\"Recoverability\":\"Enabled\"}'"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandCaching (Hot Cache)
# Keep last 30 days in hot cache
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".alter table Events policy caching hot = 30d"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandStreaming Ingestion
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".alter table Events policy streamingingestion enable"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command---
Materialized Views via CLI
# Create materialized view with backfill
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".create materialized-view with (backfill=true) HourlyEventCounts on table Events { Events | summarize Count = count(), LastSeen = max(Timestamp) by EventType, bin(Timestamp, 1h) }"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command# Check health
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".show materialized-view HourlyEventCounts statistics"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command---
Functions and Update Policies via CLI
Create Function
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".create-or-alter function with (docstring='Parse raw events', folder='ETL') ParseRawEvents() { RawEvents | extend Parsed = parse_json(RawData) | project Timestamp = todatetime(Parsed.timestamp), EventType = tostring(Parsed.eventType), UserId = tostring(Parsed.userId) }"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandCreate Update Policy
cat > /tmp/kql_body.json << 'EOF'
{"db":"MyDB","csl":".alter table ParsedEvents policy update @'[{\"IsEnabled\":true,\"Source\":\"RawEvents\",\"Query\":\"ParseRawEvents()\",\"IsTransactional\":true}]'"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command---
Schema Evolution via CLI
Safe Schema Deployment Script
Save management commands in a .kql file (one per line), then execute each command via az rest:
# deploy_schema.kql contains one command per line:
# .create-merge table Events (Timestamp: datetime, EventType: string, UserId: string, Properties: dynamic)
# .create-merge table ParsedEvents (Timestamp: datetime, EventType: string, UserId: string, PageName: string)
# .alter table Events policy retention '{\"SoftDeletePeriod\":\"365.00:00:00\",\"Recoverability\":\"Enabled\"}'
# .alter table Events policy caching hot = 30d
# Execute each command from the file (see "Execute KQL Command" section)
while IFS= read -r cmd; do
[[ "$cmd" =~ ^// ]] && continue # skip comment lines
[[ -z "$cmd" ]] && continue # skip blank lines
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":"${cmd}"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/mgmt" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
done < deploy_schema.kqlExport Current Schema
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".show database ${DB} schema as csl script"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/mgmt" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq -r '.Tables[0].Rows[][0]' > current_schema.kql---
Monitoring Authoring Operations
// Recent management commands
.show commands
| where StartedOn > ago(1h)
| project StartedOn, CommandType, Text = substring(Text, 0, 100), State, Duration
| order by StartedOn desc
// Ingestion failures
.show ingestion failures
| where FailedOn > ago(24h)
| summarize FailureCount = count() by ErrorCode, Table
| order by FailureCount desc
// Materialized view health
.show materialized-views
| project Name, IsEnabled, IsHealthy, MaterializedTo---
Must / Prefer / Avoid / Troubleshooting
Must
- Clarify before acting on ambiguous prompts — if the request does not specify a target table, operation type, or schema (e.g. "set up my Eventhouse", "configure my database"), ask the user what they want to do. Never infer intent and apply management commands autonomously. Irreversible side-effects (policy changes, schema mutations, data ingestion) require explicit user intent.
- Use idempotent commands —
.create-merge table,.create-or-alter function,.create table ifnotexists. - Verify permissions before authoring — must have
AdminorIngestorrole. - Test update policies by running the function independently before attaching.
- Include `impersonate` in storage URIs when ingesting from OneLake or Blob Storage.
Prefer
- `az rest` with loop for deploying multi-command schema files.
- Fabric KQL MCP server for agent-integrated ingestion and management workflows.
- `.create-merge table` over
.create tablefor safe schema evolution. - Materialized views over repeated expensive aggregation queries.
- Script-based CI/CD — export schema with
.show database DB schema as csl script, store in git.
Avoid
- `.drop table` without
ifexists— fails on missing tables. - `.alter table` to add columns — use
.alter-merge tableinstead (additive only). - Ingestion without mappings for CSV/JSON — column order or field names may not match.
- Hardcoded storage URIs — parameterise in scripts.
- Disabling materialized views without understanding the re-backfill cost.
Troubleshooting
| Symptom | Fix |
|---|---|
.create table fails "already exists" | Use .create-merge table or .create table ifnotexists |
| Ingestion succeeds but table empty | Check data mappings: .show table T ingestion csv mappings |
| Update policy not firing | Verify function runs standalone; check .show table T policy update |
Forbidden (403) on management commands | Request admin or ingestor database role |
| Materialized view stuck | Check .show materialized-view MV statistics; may need .disable/.enable |
| OneLake ingest auth error | Add ;impersonate to abfss:// URI |
---
Agentic Workflows
Exploration Before Authoring
Always check for explicit intent before doing anything:
Step 0 → Is the request specific? Does it name a table, operation, and/or schema?
→ NO → Ask: "What would you like to set up? Options: create tables,
configure policies, set up ingestion mappings, create materialized views."
STOP — do not proceed until user specifies.
→ YES → Continue to Step 1.
Step 1 → .show tables details // what exists?
Step 2 → .show table <TABLE> schema as json // current columns
Step 3 → .show table <TABLE> policy retention // current policies
Step 4 → Plan changes (create-merge, alter, etc.)
Step 5 → Execute changes
Step 6 → Verify: .show table <TABLE> schema as json // confirm changesScript Generation Workflow
Step 1 → Understand requirements from user
Step 2 → Generate KQL management commands
Step 3 → Save to .kql file
Step 4 → Deploy via az rest (one command at a time)
Step 5 → Verify deployed state matches intent---
Examples
Example 1: Create Table with Policies and Mapping
# Create table
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".create-merge table SensorData (Timestamp: datetime, DeviceId: string, Temperature: real, Humidity: real, Location: dynamic)"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command# Set retention
cat > /tmp/kql_body.json << 'EOF'
{"db":"MyDB","csl":".alter table SensorData policy retention '{\"SoftDeletePeriod\":\"90.00:00:00\",\"Recoverability\":\"Enabled\"}'"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command# Set caching
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".alter table SensorData policy caching hot = 7d"}
EOFExecute /tmp/kql_body.json — see Execute KQL Command# Create JSON mapping
cat > /tmp/kql_body.json << 'EOF'
{"db":"MyDB","csl":".create table SensorData ingestion json mapping 'SensorJsonMapping' '[{\"column\":\"Timestamp\",\"path\":\"$.ts\",\"datatype\":\"datetime\"},{\"column\":\"DeviceId\",\"path\":\"$.deviceId\",\"datatype\":\"string\"},{\"column\":\"Temperature\",\"path\":\"$.temp\",\"datatype\":\"real\"},{\"column\":\"Humidity\",\"path\":\"$.humidity\",\"datatype\":\"real\"},{\"column\":\"Location\",\"path\":\"$.location\",\"datatype\":\"dynamic\"}]'"}
EOFExecute /tmp/kql_body.json — see Execute KQL CommandExample 2: ETL with Update Policy
// 1. Target table
.create-merge table ParsedLogs (Timestamp: datetime, Level: string, Message: string, Source: string)
// 2. Transform function
.create-or-alter function ParseRawLogs() {
RawLogs
| extend J = parse_json(RawMessage)
| project
Timestamp = todatetime(J.timestamp),
Level = tostring(J.level),
Message = tostring(J.message),
Source = tostring(J.source)
}
// 3. Attach update policy
.alter table ParsedLogs policy update
@'[{"IsEnabled":true,"Source":"RawLogs","Query":"ParseRawLogs()","IsTransactional":true}]'---
Agent Integration Notes
- This skill covers authoring operations — creating/altering database objects and ingesting data.
- For read-only queries and data exploration, delegate to eventhouse-consumption-cli.
- For cross-workload orchestration, delegate to the FabricDataEngineer agent.
- All management commands require elevated database roles (
AdminorIngestor).
Eventhouse Authoring Script Templates
Reusable Bash and PowerShell templates for common Eventhouse authoring operations via az rest.
---
Bash Templates
Create Table and Ingest from Blob
#!/bin/bash
set -euo pipefail
CLUSTER_URI="${1:?Usage: $0 <cluster_uri> <database>}"
DB="${2:?Usage: $0 <cluster_uri> <database>}"
run_mgmt() {
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":"$1"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/mgmt" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
}
echo "=== Creating table ==="
run_mgmt ".create-merge table Events (Timestamp: datetime, EventType: string, UserId: string, Properties: dynamic, Duration: real)"
echo "=== Creating CSV mapping ==="
run_mgmt ".create-or-alter table Events ingestion csv mapping 'EventsCsvMapping' '[{\"column\":\"Timestamp\",\"datatype\":\"datetime\",\"ordinal\":0},{\"column\":\"EventType\",\"datatype\":\"string\",\"ordinal\":1},{\"column\":\"UserId\",\"datatype\":\"string\",\"ordinal\":2},{\"column\":\"Properties\",\"datatype\":\"dynamic\",\"ordinal\":3},{\"column\":\"Duration\",\"datatype\":\"real\",\"ordinal\":4}]'"
echo "=== Ingesting data ==="
BLOB_URI="${3:-}"
if [ -n "${BLOB_URI}" ]; then
run_mgmt ".ingest into table Events (h'${BLOB_URI};impersonate') with (format='csv', ingestionMappingReference='EventsCsvMapping', ignoreFirstRecord=true)"
echo "Ingestion command submitted."
else
echo "No blob URI provided — skipping ingestion."
fi
echo "=== Verifying ==="
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":"Events | count"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/query" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
echo "Done."---
Schema Deployment (Idempotent)
#!/bin/bash
set -euo pipefail
CLUSTER_URI="${1:?Usage: $0 <cluster_uri> <database> <schema_file>}"
DB="${2:?}"
SCHEMA_FILE="${3:?}"
echo "=== Deploying schema from ${SCHEMA_FILE} ==="
while IFS= read -r cmd; do
[[ "$cmd" =~ ^// ]] && continue # skip comment lines
[[ -z "$cmd" ]] && continue # skip blank lines
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":"${cmd}"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/mgmt" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
done < "${SCHEMA_FILE}"
echo "=== Verifying deployment ==="
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".show tables details | project TableName, TotalRowCount"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/query" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".show functions | project Name, Folder"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/query" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".show materialized-views | project Name, IsEnabled, IsHealthy"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/query" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
echo "Schema deployment complete."---
Export Schema to File
#!/bin/bash
set -euo pipefail
CLUSTER_URI="${1:?Usage: $0 <cluster_uri> <database> [output_file]}"
DB="${2:?}"
OUTPUT="${3:-schema_export_$(date +%Y%m%d).kql}"
echo "=== Exporting schema for ${DB} ==="
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".show database ${DB} schema as csl script"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/mgmt" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq -r '.Tables[0].Rows[][0]' > "${OUTPUT}"
echo "Schema exported to ${OUTPUT}"---
Set Retention and Caching Policies
#!/bin/bash
set -euo pipefail
CLUSTER_URI="${1:?Usage: $0 <cluster_uri> <database> <table> <retention_days> <cache_days>}"
DB="${2:?}"
TABLE="${3:?}"
RETENTION_DAYS="${4:?}"
CACHE_DAYS="${5:?}"
run_mgmt() {
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":"$1"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/mgmt" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
}
echo "=== Setting retention to ${RETENTION_DAYS}d for ${TABLE} ==="
run_mgmt ".alter table ${TABLE} policy retention '{\"SoftDeletePeriod\":\"${RETENTION_DAYS}.00:00:00\",\"Recoverability\":\"Enabled\"}'"
echo "=== Setting hot cache to ${CACHE_DAYS}d for ${TABLE} ==="
run_mgmt ".alter table ${TABLE} policy caching hot = ${CACHE_DAYS}d"
echo "=== Verifying ==="
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".show table ${TABLE} policy retention"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/query" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
cat > /tmp/kql_body.json << EOF
{"db":"${DB}","csl":".show table ${TABLE} policy caching"}
EOF
az rest --method POST \
--url "${CLUSTER_URI}/v1/rest/query" \
--resource "https://kusto.kusto.windows.net" \
--headers "Content-Type=application/json" \
--body @/tmp/kql_body.json \
| jq '.Tables[0].Rows'
echo "Done."---
PowerShell Templates
Create Table and Ingest
param(
[Parameter(Mandatory)][string]$ClusterUri,
[Parameter(Mandatory)][string]$Database,
[string]$BlobUri
)
function Invoke-KustoMgmt {
param([string]$Command)
@{ db = $Database; csl = $Command } | ConvertTo-Json -Compress | Out-File $env:TEMP\kql_body.json -Encoding utf8NoBOM
az rest --method POST `
--url "$ClusterUri/v1/rest/mgmt" `
--resource "https://kusto.kusto.windows.net" `
--headers "Content-Type=application/json" `
--body "@$env:TEMP\kql_body.json" 2>$null | ConvertFrom-Json | ForEach-Object { $_.Tables[0].Rows }
}
Write-Host "=== Creating table ===" -ForegroundColor Cyan
Invoke-KustoMgmt ".create-merge table Events (Timestamp: datetime, EventType: string, UserId: string, Properties: dynamic, Duration: real)"
Write-Host "=== Creating CSV mapping ===" -ForegroundColor Cyan
Invoke-KustoMgmt ".create-or-alter table Events ingestion csv mapping 'EventsCsvMapping' '[{`"column`":`"Timestamp`",`"datatype`":`"datetime`",`"ordinal`":0},{`"column`":`"EventType`",`"datatype`":`"string`",`"ordinal`":1},{`"column`":`"UserId`",`"datatype`":`"string`",`"ordinal`":2},{`"column`":`"Properties`",`"datatype`":`"dynamic`",`"ordinal`":3},{`"column`":`"Duration`",`"datatype`":`"real`",`"ordinal`":4}]'"
if ($BlobUri) {
Write-Host "=== Ingesting from $BlobUri ===" -ForegroundColor Cyan
Invoke-KustoMgmt ".ingest into table Events (h'${BlobUri};impersonate') with (format='csv', ingestionMappingReference='EventsCsvMapping', ignoreFirstRecord=true)"
}
Write-Host "=== Verifying ===" -ForegroundColor Cyan
@{ db = $Database; csl = "Events | count" } | ConvertTo-Json -Compress | Out-File $env:TEMP\kql_body.json -Encoding utf8NoBOM
az rest --method POST `
--url "$ClusterUri/v1/rest/query" `
--resource "https://kusto.kusto.windows.net" `
--headers "Content-Type=application/json" `
--body "@$env:TEMP\kql_body.json" 2>$null | ConvertFrom-Json | ForEach-Object { $_.Tables[0].Rows }
Write-Host "Done." -ForegroundColor Green---
Schema Deployment
param(
[Parameter(Mandatory)][string]$ClusterUri,
[Parameter(Mandatory)][string]$Database,
[Parameter(Mandatory)][string]$SchemaFile
)
Write-Host "=== Deploying schema from $SchemaFile ===" -ForegroundColor Cyan
Get-Content $SchemaFile | Where-Object { $_ -and $_ -notmatch '^\s*//' } | ForEach-Object {
@{ db = $Database; csl = $_ } | ConvertTo-Json -Compress | Out-File $env:TEMP\kql_body.json -Encoding utf8NoBOM
az rest --method POST `
--url "$ClusterUri/v1/rest/mgmt" `
--resource "https://kusto.kusto.windows.net" `
--headers "Content-Type=application/json" `
--body "@$env:TEMP\kql_body.json" 2>$null | ConvertFrom-Json | ForEach-Object { $_.Tables[0].Rows }
}
Write-Host "=== Verification ===" -ForegroundColor Cyan
foreach ($cmd in @(
".show tables details | project TableName, TotalRowCount",
".show functions | project Name, Folder",
".show materialized-views | project Name, IsEnabled, IsHealthy"
)) {
@{ db = $Database; csl = $cmd } | ConvertTo-Json -Compress | Out-File $env:TEMP\kql_body.json -Encoding utf8NoBOM
az rest --method POST `
--url "$ClusterUri/v1/rest/query" `
--resource "https://kusto.kusto.windows.net" `
--headers "Content-Type=application/json" `
--body "@$env:TEMP\kql_body.json" 2>$null | ConvertFrom-Json | ForEach-Object { $_.Tables[0].Rows }
}
Write-Host "Schema deployment complete." -ForegroundColor GreenRelated skills
FAQ
Is Eventhouse Authoring Cli safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.