Job definitions whose runs cannot be traced to a team or cost center
What does ZopNight detect here?
Jobs spend in bursts: each run spins up a job cluster, bills DBUs plus VMs, and vanishes minutes later. Tags on the job definition are what stitch those ephemeral runs back to an owner, so ZopNight checks every job for the 3 keys: team, environment, and cost-center.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-2322 · RC-2422 · RC-2222 |
| Category | governance |
| Severity | low |
| Metric | none — pure configuration read |
| Source | missing_tags.go |
Where it applies
Attribution per run, not per machine
A job’s cost profile is the inverse of a cluster’s. There is no long-lived machine to point at. Each scheduled run provisions a job cluster, burns DBUs and VM-hours for its duration, and tears itself down. By the time anyone reviews the bill, the compute that generated it no longer exists. The only durable object in that lifecycle is the job definition itself, which is why the definition is where the cost-allocation keys have to live: tags set there ride along to every run.
Definitions never sleep, so the check never gates
ZopNight’s cluster and warehouse tag rules skip stopped resources because stopped
compute is not current spend. Jobs get no such gate, deliberately. A job definition
has no power state, and a job that is untagged today will produce untagged spend at
its next scheduled fire whether that is in an hour or a month. Every job is checked,
every time, for the same 3 keys the rest of the platform uses: team, environment,
and cost-center. Any one of them missing produces the finding, naming exactly which
keys are absent. A tag blob that fails to parse yields no finding rather than a
guessed one.
Dump job tags across the workspace
databricks api get '/api/2.1/jobs/list?limit=25&expand_tasks=false' | jq ' .jobs[] | {job_id, name: .settings.name, missing: (["team", "environment", "cost-center"] - ((.settings.tags // {}) | keys))} | select(.missing | length > 0)'Page through with the returned next_page_token on workspaces with more than 25 jobs.
Where the tags travel
Tags on a job propagate to the job clusters launched for its runs, and from there to the underlying cloud VMs, so a correctly tagged job produces per-run spend that both Databricks system tables and the cloud provider’s cost tools can group by team. That chain is what makes the job key set worth enforcing: one field on the definition labels every future run’s infrastructure.
Closing the gap for good
Backfill the missing keys on the jobs this finding lists, then make tagging part of how jobs are born: deployment pipelines that create jobs via the API should refuse specs without the 3 keys, and job clusters can additionally be bound to policies that require them. Definitions created by hand in the UI are the leak to watch.