Skip to main content

Views

Views are dynamic, data-driven dashboards in Mission Control that aggregate and visualize data from multiple sources. They collect data from multiple sources into an in-memory SQLite database, enabling you to run any SQL query for filtering, joining, and aggregating your observability data.

Views Concept

Views serve as a powerful data aggregation and visualization layer in Mission Control. They:

  • Aggregate data from multiple sources including configuration items, changes, and Prometheus metrics
  • Display data as interactive tables and visualization panels (gauges, pie charts, ...)
  • Support templating with variables that users can adjust to dynamically filter and update the view
  • Cache results intelligently to balance data freshness with performance
  • Transform data using expressions to map raw query results to meaningful display columns
  • Embed views inside config item pages or assemble multiple views on one page with sections

Key Features

Data Sources

Views can query data from multiple sources:

  • Config Items: Infrastructure components and configurations via the configs selector
  • Changes: Configuration change tracking and audit data via the changes selector
  • Metrics: Time-series data from Prometheus using PromQL queries
  • SQL: Direct SQL queries via stored connections (PostgreSQL, MySQL, SQL Server)
  • Other Views: Reuse cached tables from existing views with viewTableSelector

Output Types

Views can generate:

  • One Table: Structured data with typed columns for detailed data presentation
  • Multiple Panels: Interactive visualizations including pie charts, gauges, numbers, and summary tables

How Views Work

Views transform your data into an in-memory SQL database, giving you the full power of SQL to slice, dice, and analyze your infrastructure:

1. Named Queries (Required)

Every view must define queries with unique names:

queries:
deployments: # Table name in SQL
configs:
types: ['Kubernetes::Deployment']
pipelines: # Another table name
changes:
search: change_type=GitHubActionRun

2. In-Memory SQL Database

Views execute your named queries and create an SQLite database in memory:

  • Each query becomes a table with the query's name
  • Table schema gets generated dynamically from the query results
  • Example: queries named deployments, pipelines, metrics create 3 SQL tables

3. SQL-Powered Data Processing

Once you load data, you can run any SQL query against it to combine data from multiple sources:

# View table data (optional)
merge: |
SELECT d.name, d.status, p.duration
FROM deployments d
LEFT JOIN pipelines p ON d.name = p.app

# Panel queries (required for panels)
panels:
- name: 'Status Distribution'
type: piechart
query: 'SELECT COUNT(*) AS count, status FROM deployments GROUP BY status'

This SQL-first approach gives you unlimited flexibility to slice, filter, and aggregate your data.

Compose Pages with Sections

Use spec.sections to render multiple views together. Mission Control aggregates their variables and shows a single filter bar for all sections.

workload-overview.yaml
apiVersion: mission-control.flanksource.com/v1
kind: View
metadata:
name: workload-overview
namespace: mc
spec:
description: Overview page that stitches together multiple workload views.
display:
title: Workload Overview
icon: view-details
sidebar: true
sections:
- title: Deployments
icon: kubernetes::deployment
viewRef:
namespace: mc
name: deployments
- title: Pods
icon: kubernetes::pod
viewRef:
namespace: mc
name: pods
- title: Pipelines
icon: github
viewRef:
namespace: mc
name: pipelines

Attach Views to Config Tabs

display.plugins lets you place a view as a tab on matching config items. Variables can be templated from the config to scope the view automatically.

namespace.yaml
apiVersion: mission-control.flanksource.com/v1
kind: View
metadata:
name: namespace
namespace: mc
spec:
columns:
- cardPosition: title
name: name
primaryKey: true
type: config_item
url:
config: row.id
- cardPosition: deck
filter:
type: multiselect
icon: row.health
name: status
type: status
- filter:
type: multiselect
hidden: true
name: health
type: health
- cardPosition: deck
description: Memory usage
gauge:
max: row.memory_limit
thresholds:
- color: green
percent: 0
- color: orange
percent: 75
- color: red
percent: 90
name: memory
type: gauge
unit: bytes
- cardPosition: deck
gauge:
max: row.cpu_limit
thresholds:
- color: "#8BC34A"
percent: 0
- color: "#F4B23C"
percent: 70
- color: "#F25C54"
percent: 85
name: cpu
type: gauge
unit: millicore
- cardPosition: footer
name: updated
type: datetime
- cardPosition: footer
name: created
type: datetime
- cardPosition: body
hidden: true
name: image
type: string
- cardPosition: body
hidden: true
name: node
type: string
description: View for inspecting a Kubernetes Namespace
display:
icon: namespace
plugins:
- configTab:
types:
- Kubernetes::Namespace
variables:
cluster: $(.config.tags.cluster)
namespace: $(.config.name)
sidebar: true
title: Namespace
mapping:
created: row.created_at
image: |
has(row.config) ? row.config.JSON().spec.containers[0].image : "N/A"
node: |
has(row.config) ? (has(row.config.JSON().spec.nodeName) ? row.config.JSON().spec.nodeName : "N/A"): "N/A"
updated: row.updated_at
merge: |
"SELECT
pod.id,
pod.name,
json_extract(pod.tags, '$.namespace')
AS namespace,
pod.status,
pod.health,
pod.config,
pod.created_at,
pod.updated_at,
memory.value as memory,
to_bytes(COALESCE(
json_extract(pod.config,
'$.spec.containers[0].resources.limits.memory'),
''
)) AS memory_limit,
cpu.value as cpu,
to_millicores(COALESCE(
json_extract(pod.config, '$.spec.containers[0].resources.limits.cpu'),

''
)) AS cpu_limit\nFROM pod\nLEFT JOIN memory
ON pod.name = memory.pod

AND json_extract(pod.tags, '$.namespace') = memory.namespace\nLEFT JOIN cpu
ON pod.name = cpu.pod
AND json_extract(pod.tags, '$.namespace') = cpu.namespace\nORDER
BY namespace, name
"
panels:
- description: Total Pods in the namespace
name: Total Pods
query: SELECT COUNT(*) AS value FROM pod
type: number
queries:
cpu:
columns:
namespace: string
pod: string
value: decimal
prometheus:
bearer: {}
connection: connection://mc/prometheus
oauth:
clientID: {}
clientSecret: {}
password: {}
query: |
sum by (namespace, pod) (
irate(container_cpu_usage_seconds_total{
container!="POD", # Skip The pause/infra container
image!="" # Skip dead containers
}[30s])
) * 1000
tls:
ca: {}
cert: {}
key: {}
username: {}
memory:
columns:
namespace: string
pod: string
value: decimal
prometheus:
bearer: {}
connection: connection://mc/prometheus
oauth:
clientID: {}
clientSecret: {}
password: {}
query: |
sum by (namespace, pod) (
container_memory_working_set_bytes{
container!="POD", # Skip The pause/infra container
image!="" # Skip dead containers
}
)
tls:
ca: {}
cert: {}
key: {}
username: {}
memory_usage:
columns:
namespace: string
pod: string
value: decimal
prometheus:
bearer: {}
connection: connection://mc/prometheus
oauth:
clientID: {}
clientSecret: {}
password: {}
query: |
sum(rate(container_memory_working_set_bytes{namespace=~"$(.var.namespace)", image!=""}[5m])) / sum(machine_memory_bytes{})
tls:
ca: {}
cert: {}
key: {}
username: {}
pod:
configs:
agent: all
tagSelector: cluster=$(.var.cluster),namespace=$(.var.namespace)
types:
- Kubernetes::Pod
templating:
- key: cluster
label: Cluster
valueFrom:
config:
types:
- Kubernetes::Cluster
- dependsOn:
- cluster
key: namespace
label: Namespace
valueFrom:
config:
tagSelector: cluster=$(.var.cluster)
types:
- Kubernetes::Namespace
status: {}

API Reference

FieldDescriptionScheme
queries*

Named queries that populate the view data sources

map[string]Query

cache.maxAge

Maximum age of cache before it's deemed stale (default: 15m)

Duration

cache.minAge

Minimum age of cache a user can request (default: 10s)

Duration

cache.refreshTimeout

Duration to wait for a view to process before returning stale data (default: 5s)

Duration

columns

Define the structure and data types of the view table

[]ViewColumnDef

description

Short explanation of what the view shows

string

display.card

Default card layout for the view (body column count and whether cards are the default mode)

DisplayCard

display.icon

Icon identifier for navigation and visual identification

Icon

display.ordinal

Sort order for navigation, lower numbers appear first (default: 0)

integer

display.plugins[]

Attach the view as a tab on matching config items with templated variables extracted from the config

ViewConfigUIPlugin

display.sidebar

Whether the view appears in sidebar navigation (default: false)

boolean

display.title

Human-readable title displayed in the UI (defaults to view name)

string

mapping

CEL expressions to map query results to view columns. If not specified, columns are automatically populated from query results.

map[string]CELExpression

merge

SQL query to merge/join data from multiple named queries. Required when using multiple queries with table output (columns only).

string

panels

Interactive visualizations for aggregated data

[]PanelDef

sections

List of other views to render on the same page

[]ViewSection

templating

Variable definitions that can be substituted into queries and mappings

[]ViewVariable

Validation Requirements
  • At least one query: Views must define at least one named query (unless the view only renders sections)
  • Output definition: Views must have either panels or columns (or both)
  • Merge requirement: When using multiple queries with table output (columns only), you must provide a merge SQL query

Query

Query definition for data sources.

FieldDescriptionScheme
changes

Query configuration changes and audit data

ResourceSelector

configs

Query config items from the catalog

ResourceSelector

prometheus

Query time-series data from Prometheus

Prometheus Query

sql

Run a SQL query against a configured connection (PostgreSQL, MySQL, SQL Server)

SQL query

viewTableSelector

Read cached rows from another view table

View Table Selector

Prometheus Query

Query configuration for Prometheus metrics.

FieldDescriptionScheme
query*

PromQL query string

string

bearer

Bearer token for authentication

EnvVar

connection

Reference to a connection for authentication

string

password

Basic auth password

EnvVar

url

Prometheus server URL

string

username

Basic auth username

EnvVar

View Column Definition

Column definition for view tables with data types and visualization properties.

FieldDescriptionScheme
name*

Column name (must be a valid SQL identifier)

string

type*

Data type that determines formatting and visualization

string, number, boolean, datetime, duration, health, status, gauge, bytes, decimal, millicore, url, badge, config_item, labels

card

Card layout configuration for this column (position and accent highlighting)

CardConfig

configItem

Options for config_item columns (choose which field to treat as the config ID)

ConfigItemColumnType

description

Human-readable description of the column

string

filter

Enable column filtering in the UI. Options are populated from the cached table per request fingerprint (type: multiselect; labels columns support key/value include-exclude filters)

object

for

Reference to another column this column provides data for (helper columns). Only applicable for type=url.

string

gauge

Configuration for gauge visualization (required when type=gauge)

GaugeConfig

hidden

Whether to hide the column from the UI (default: false)

boolean

icon

CEL expression that selects an icon per row (for tables and cards)

string

primaryKey

Whether this column is part of the primary key (default: false). At least one column must be marked as primary key.

boolean

unit

Unit string appended to values (e.g., %, bytes, millicore)

string

url

Link to configs, other views, or custom URLs using CEL/Go templates

ColumnURL

Primary Key Requirement

If columns are defined, at least one must be marked as primaryKey: true.

Panel Definition

Panel definition for interactive visualizations.

FieldDescriptionScheme
name*

Name of the panel

string

query*

SQL query to aggregate data from the view's named queries

string

type*

Type of panel visualization

piechart, table, text, number, duration, gauge, bargauge, timeseries

bargauge

Configuration for bar gauge panels

Bar Gauge Configuration

description

Description of the panel

string

gauge

Configuration for gauge panels

Gauge Configuration

number

Configuration for number panels

Panel Number Configuration

piechart

Configuration for pie chart panels

Pie Chart Configuration

timeseries

Configuration for timeseries panels

Timeseries Configuration

Pie Chart Configuration

Configuration for pie chart panels.

FieldDescriptionScheme
colors

Custom color mapping for categories

[map[string]string]

showLabels

Display labels on pie slices

boolean

Gauge Configuration

Configuration for gauge visualizations with thresholds and color coding.

FieldDescriptionScheme
max

Maximum value for the gauge (number or CEL expression)

string

min

Minimum value for the gauge (number or CEL expression)

string

thresholds[].color

Color for this threshold

string

thresholds[].value

Threshold value (deprecated; use percent)

integer

Panel Number Configuration

Configuration for number panels.

FieldDescriptionScheme
precision

Number of decimal places

integer

unit

Display unit (e.g., 'seconds', 'MB', '%')

string

Bar Gauge Configuration

Configuration for bar gauge panels.

FieldDescriptionScheme
format

Display format (percentage or multiplier)

string

group

Optional group name to merge multiple bar gauges

string

max

Maximum value (number or CEL expression)

string

min

Minimum value (number or CEL expression)

string

precision

Number of decimal places

integer

thresholds[].color

Color for this threshold

string

thresholds[].value

Threshold value (deprecated; use percent)

integer

unit

Unit label appended to values

string

Timeseries Configuration

Configuration for timeseries panels (API-level; UI rendering in progress).

FieldDescriptionScheme
style

Visualization style: lines, area, or points

string

timeKey

Field name for the timestamp column (default: timestamp)

string

valueKey

Field name for the numeric value column (default: value)

string

View Card Layout

display.card controls the default card layout for tables with card positioning. Cards become the default view when default: true and at least one column defines card.position (or legacy cardPosition). Use columns[].card.useForAccent to color the card accent based on a column's value (status/health heuristics in the UI):

FieldDescriptionScheme
columns*

Number of columns in the card body

integer

default

Whether the Cards tab should be the default display mode

boolean

Config Tabs

Use display.plugins to attach a view as a tab on config detail pages. The configTab selector chooses matching configs, and variables templating pulls values from the config into the view request.

namespace.yaml
apiVersion: mission-control.flanksource.com/v1
kind: View
metadata:
name: namespace
namespace: mc
spec:
columns:
- cardPosition: title
name: name
primaryKey: true
type: config_item
url:
config: row.id
- cardPosition: deck
filter:
type: multiselect
icon: row.health
name: status
type: status
- filter:
type: multiselect
hidden: true
name: health
type: health
- cardPosition: deck
description: Memory usage
gauge:
max: row.memory_limit
thresholds:
- color: green
percent: 0
- color: orange
percent: 75
- color: red
percent: 90
name: memory
type: gauge
unit: bytes
- cardPosition: deck
gauge:
max: row.cpu_limit
thresholds:
- color: "#8BC34A"
percent: 0
- color: "#F4B23C"
percent: 70
- color: "#F25C54"
percent: 85
name: cpu
type: gauge
unit: millicore
- cardPosition: footer
name: updated
type: datetime
- cardPosition: footer
name: created
type: datetime
- cardPosition: body
hidden: true
name: image
type: string
- cardPosition: body
hidden: true
name: node
type: string
description: View for inspecting a Kubernetes Namespace
display:
icon: namespace
plugins:
- configTab:
types:
- Kubernetes::Namespace
variables:
cluster: $(.config.tags.cluster)
namespace: $(.config.name)
sidebar: true
title: Namespace
mapping:
created: row.created_at
image: |
has(row.config) ? row.config.JSON().spec.containers[0].image : "N/A"
node: |
has(row.config) ? (has(row.config.JSON().spec.nodeName) ? row.config.JSON().spec.nodeName : "N/A"): "N/A"
updated: row.updated_at
merge: |
"SELECT
pod.id,
pod.name,
json_extract(pod.tags, '$.namespace')
AS namespace,
pod.status,
pod.health,
pod.config,
pod.created_at,
pod.updated_at,
memory.value as memory,
to_bytes(COALESCE(
json_extract(pod.config,
'$.spec.containers[0].resources.limits.memory'),
''
)) AS memory_limit,
cpu.value as cpu,
to_millicores(COALESCE(
json_extract(pod.config, '$.spec.containers[0].resources.limits.cpu'),

''
)) AS cpu_limit\nFROM pod\nLEFT JOIN memory
ON pod.name = memory.pod

AND json_extract(pod.tags, '$.namespace') = memory.namespace\nLEFT JOIN cpu
ON pod.name = cpu.pod
AND json_extract(pod.tags, '$.namespace') = cpu.namespace\nORDER
BY namespace, name
"
panels:
- description: Total Pods in the namespace
name: Total Pods
query: SELECT COUNT(*) AS value FROM pod
type: number
queries:
cpu:
columns:
namespace: string
pod: string
value: decimal
prometheus:
bearer: {}
connection: connection://mc/prometheus
oauth:
clientID: {}
clientSecret: {}
password: {}
query: |
sum by (namespace, pod) (
irate(container_cpu_usage_seconds_total{
container!="POD", # Skip The pause/infra container
image!="" # Skip dead containers
}[30s])
) * 1000
tls:
ca: {}
cert: {}
key: {}
username: {}
memory:
columns:
namespace: string
pod: string
value: decimal
prometheus:
bearer: {}
connection: connection://mc/prometheus
oauth:
clientID: {}
clientSecret: {}
password: {}
query: |
sum by (namespace, pod) (
container_memory_working_set_bytes{
container!="POD", # Skip The pause/infra container
image!="" # Skip dead containers
}
)
tls:
ca: {}
cert: {}
key: {}
username: {}
memory_usage:
columns:
namespace: string
pod: string
value: decimal
prometheus:
bearer: {}
connection: connection://mc/prometheus
oauth:
clientID: {}
clientSecret: {}
password: {}
query: |
sum(rate(container_memory_working_set_bytes{namespace=~"$(.var.namespace)", image!=""}[5m])) / sum(machine_memory_bytes{})
tls:
ca: {}
cert: {}
key: {}
username: {}
pod:
configs:
agent: all
tagSelector: cluster=$(.var.cluster),namespace=$(.var.namespace)
types:
- Kubernetes::Pod
templating:
- key: cluster
label: Cluster
valueFrom:
config:
types:
- Kubernetes::Cluster
- dependsOn:
- cluster
key: namespace
label: Namespace
valueFrom:
config:
tagSelector: cluster=$(.var.cluster)
types:
- Kubernetes::Namespace
status: {}

Column Filters

Enable columns[].filter.type: multiselect to expose server-side filters without re-running the view. Mission Control gathers distinct values from the cached Postgres table (scoped to the current request_fingerprint), builds dropdown options, and applies PostgREST filters. Labels columns support include/exclude tokens so you can target specific keys.

ingress.yaml
apiVersion: mission-control.flanksource.com/v1
kind: View
metadata:
name: ingresses
namespace: default
spec:
description: Ingress view with card rendering support
display:
title: Ingresses
icon: ingress
sidebar: true
card:
columns: 2
default: true
queries:
ingress:
configs:
search: "@order=name"
types:
- Kubernetes::Ingress
columns:
- name: id
type: string
primaryKey: true
hidden: true
- name: name
type: config_item
card:
position: title
- name: namespace
type: string
card:
position: subtitle
- name: status
type: status
icon: row.health
card:
position: subtitle
filter:
type: multiselect
- name: health
type: health
hidden: true
card:
useForAccent: true
filter:
type: multiselect
- name: hosts
type: string
card:
position: body
- name: class
type: string
card:
position: body
- name: address
type: string
card:
position: body
- name: created
type: datetime
card:
position: body
mapping:
namespace: row.tags.namespace
hosts: >
has(row.config.spec.rules) && size(row.config.spec.rules) > 0
? row.config.spec.rules.map(r, has(r.host) ? r.host : "").join(", ")
: "N/A"
class: >
has(row.config.spec.ingressClassName) ? row.config.spec.ingressClassName : "default"
address: >
has(row.config.status.loadBalancer.ingress) && size(row.config.status.loadBalancer.ingress) > 0
? row.config.status.loadBalancer.ingress.map(i, has(i.ip) ? i.ip : has(i.hostname) ? i.hostname : "").join(", ")
: "N/A"
created: row.created_at

Column URLs

columns[].url can link to Mission Control objects or external destinations:

  • config: CEL expression resolving to a config ID or search query (redirects to catalog page)
  • view: Link to another view with optional query params built from CEL expressions
  • template: Go template that renders a custom URL
deployments.yaml
apiVersion: mission-control.flanksource.com/v1
kind: View
metadata:
name: deployments
namespace: mc
spec:
columns:
- description: The id of the deployment.
hidden: true
name: id
primaryKey: true
type: string
- card:
position: title
description: The deployment name.
name: name
type: config_item
- card:
position: subtitle
description: The namespace name.
filter:
type: multiselect
name: namespace
type: string
url:
config:
f("name=$(.namespace) tags.cluster=$(.cluster) type=Kubernetes::Namespace",
row)
- card:
position: body
description: The number of ready replicas.
name: readyReplicas
type: string
- card:
position: body
description: The desired number of replicas.
name: replicas
type: string
- card:
position: subtitle
description: The status of the deployment.
filter:
type: multiselect
icon: row.health
name: status
type: status
- card:
useForAccent: true
description: The health of the deployment.
filter:
type: multiselect
hidden: true
name: health
type: health
- card:
position: headerRight
description: CPU usage across all pods.
gauge:
thresholds:
- color: "#8BC34A"
percent: 0
- color: "#F4B23C"
percent: 70
- color: "#F25C54"
percent: 85
name: cpu
type: gauge
unit: millicore
- card:
position: headerRight
description: Memory usage across all pods.
gauge:
max: row.memory_limit
thresholds:
- color: green
percent: 0
- color: orange
percent: 75
- color: red
percent: 90
name: memory
type: gauge
unit: bytes
- card:
position: body
description: The creation timestamp.
name: createdAt
type: datetime
- card:
position: body
description: The last updated time.
name: lastUpdated
type: datetime
display:
icon: kubernetes::deployment
sidebar: true
title: Deployments
mapping:
cpu: row.cpu
createdAt: row.created_at
lastUpdated: row.updated_at
memory: row.memory
memory_limit: row.memory_limit
merge: |
SELECT
deployments.id,
deployments.name,
json_extract(deployments.tags, '$.namespace') AS namespace,
json_extract(deployments.tags, '$.cluster') AS cluster,
deployments.status,
deployments.health,
deployments.created_at,
deployments.updated_at,
CAST(CASE
WHEN json_extract(deployments.config, '$.status.readyReplicas') IS NULL THEN 0
ELSE CAST(json_extract(deployments.config, '$.status.readyReplicas') AS INTEGER)
END AS TEXT) AS readyReplicas,
CAST(json_extract(deployments.config, '$.spec.replicas') AS TEXT) AS replicas,
COALESCE(cpu_usage.value, 0) as cpu,
COALESCE(memory_usage.value, 0) as memory,
COALESCE(memory_limit.value, 0) as memory_limit
FROM deployments
LEFT JOIN cpu_usage_by_deployment AS cpu_usage
ON deployments.name = cpu_usage.deployment
AND json_extract(deployments.tags, '$.namespace') = cpu_usage.namespace
LEFT JOIN memory_usage_by_deployment AS memory_usage
ON deployments.name = memory_usage.deployment
AND json_extract(deployments.tags, '$.namespace') = memory_usage.namespace
LEFT JOIN memory_limit_by_deployment AS memory_limit
ON deployments.name = memory_limit.deployment
AND json_extract(deployments.tags, '$.namespace') = memory_limit.namespace
panels:
- description: Deployments grouped by health
name: Health
piechart:
colors:
healthy: "#28C19B"
unhealthy: "#F04E6E"
unknown: "#666666"
warning: "#F4B23C"
showLabels: true
query: SELECT COUNT(*) AS count, health FROM deployments GROUP BY health
type: piechart
- description: Deployments grouped by status
name: Status
query: SELECT COUNT(*) AS count, status FROM deployments GROUP BY status
type: piechart
queries:
cpu_usage_by_deployment:
columns:
deployment: string
namespace: string
value: decimal
prometheus:
connection: connection://mc/prometheus
query: |
sum by (namespace, deployment) (
label_replace(
rate(container_cpu_usage_seconds_total{
container!="",
container!="POD"
}[5m]),
"deployment", "$1", "pod", "^(.*)-[0-9a-f]+-[0-9a-z]+$"
)
) * 1000
deployments:
configs:
agent: all
tagSelector: cluster=$(.var.cluster)
types:
- Kubernetes::Deployment
memory_limit_by_deployment:
columns:
deployment: string
namespace: string
value: decimal
prometheus:
connection: connection://mc/prometheus
query: |
sum by (namespace, deployment) (
label_replace(
kube_pod_container_resource_limits{
resource="memory",
container!="",
container!="POD"
},
"deployment", "$1", "pod", "^(.*)-[0-9a-f]+-[0-9a-z]+$"
)
)
memory_usage_by_deployment:
columns:
deployment: string
namespace: string
value: decimal
prometheus:
connection: connection://mc/prometheus
query: |
sum by (namespace, deployment) (
label_replace(
container_memory_working_set_bytes{
container!="",
container!="POD"
},
"deployment", "$1", "pod", "^(.*)-[0-9a-f]+-[0-9a-z]+$"
)
)
templating:
- key: cluster
label: Cluster
valueFrom:
config:
agent: all
types:
- Kubernetes::Cluster

Row Attributes and Grants

Mission Control appends hidden, reserved columns to every view table:

  • __row__attributes (row_attributes type) stores per-column metadata generated during mapping: evaluated icons, URLs, gauge min/max overrides, and config item details (id, type, class, health, status). The UI uses these attributes to render icons, clickable links, and card accents.
  • __grants (grants type) stores scope IDs computed for config queries so row-level security policies can filter PostgREST responses.

You do not need to declare these columns, but they appear in the materialized Postgres table and PostgREST output.

View Table Selector

Reference cached data from another view instead of re-querying sources. The selector matches views by name, namespace, or labelSelector, then treats their materialized tables as a query source.

deployments-summary.yaml
apiVersion: mission-control.flanksource.com/v1
kind: View
metadata:
name: deployments-summary
namespace: mc
spec:
description: Summarize cached deployment health by namespace using a view table selector.
display:
title: Deployment Health Summary
icon: view-details
sidebar: true
queries:
deployments:
viewTableSelector:
name: deployments
namespace: mc
merge: |
SELECT
namespace,
SUM(CASE WHEN health = 'healthy' THEN 1 ELSE 0 END) AS healthy,
SUM(CASE WHEN health IN ('unhealthy', 'warning') THEN 1 ELSE 0 END) AS unhealthy,
COUNT(*) AS total
FROM deployments
GROUP BY namespace
columns:
- name: namespace
type: string
primaryKey: true
filter:
type: multiselect
- name: healthy
type: number
- name: unhealthy
type: number
- name: total
type: number
panels:
- name: Health Mix
description: Health distribution across all deployments
type: piechart
query: SELECT COUNT(*) AS count, health FROM deployments GROUP BY health

Sections

Render multiple views on one page. Section-only views can omit panels and columns; each section points at another view and is rendered with shared variable controls.

workload-overview.yaml
apiVersion: mission-control.flanksource.com/v1
kind: View
metadata:
name: workload-overview
namespace: mc
spec:
description: Overview page that stitches together multiple workload views.
display:
title: Workload Overview
icon: view-details
sidebar: true
sections:
- title: Deployments
icon: kubernetes::deployment
viewRef:
namespace: mc
name: deployments
- title: Pods
icon: kubernetes::pod
viewRef:
namespace: mc
name: pods
- title: Pipelines
icon: github
viewRef:
namespace: mc
name: pipelines