1"use strict";(globalThis.webpackChunkmission_control=globalThis.webpackChunkmission_control||[]).push([[2949,5109],{31964(e,n,s){s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>l,default:()=>m,frontMatter:()=>c,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"guide/playbooks/actions/logs","title":"Logs","description":"The Logs action fetches and queries logs from various backends. Use it to retrieve logs for debugging, analysis, or to pass to downstream actions like AI analysis.","source":"@site/docs/guide/playbooks/actions/logs.mdx","sourceDirName":"guide/playbooks/actions","slug":"/guide/playbooks/actions/logs","permalink":"/docs/guide/playbooks/actions/logs","draft":false,"unlisted":false,"editUrl":"https://github.com/flanksource/docs/tree/main/docs/guide/playbooks/actions/logs.mdx","tags":[],"version":"current","frontMatter":{"title":"Logs","sidebar_custom_props":{"icon":"logs"}},"sidebar":"guide","previous":{"title":"HTTP","permalink":"/docs/guide/playbooks/actions/http"},"next":{"title":"Notification","permalink":"/docs/guide/playbooks/actions/notification"}}');var t=s(74848),o=s(28453),r=s(41085);const c={title:"Logs",sidebar_custom_props:{icon:"logs"}},l=" Logs Action",a={},d=[{value:"Logs",id:"logs",level:2},{value:"Post processing",id:"post-processing",level:3},{value:"Time range",id:"time-range",level:3},{value:"CloudWatch",id:"cloudwatch",level:3},{value:"Kubernetes",id:"kubernetes",level:3},{value:"Loki",id:"loki",level:3},{value:"OpenSearch",id:"opensearch",level:3},{value:"Output",id:"output",level:2},{value:"Log line",id:"log-line",level:3},{value:"Using Results in Subsequent Actions",id:"using-results-in-subsequent-actions",level:3},{value:"Templating",id:"templating",level:2},...r.toc];function h(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",...(0,o.R)(),...e.components},{Action:s,Details:i,Fields:c,Icon:l}=n;return s||p("Action",!0),i||p("Details",!0),c||p("Fields",!0),l||p("Icon",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsxs)(n.h1,{id:"-logs-action",children:[(0,t.jsx)(l,{name:"logs"})," Logs Action"]})}),"\n",(0,t.jsx)(n.p,{children:"The Logs action fetches and queries logs from various backends. Use it to retrieve logs for debugging, analysis, or to pass to downstream actions like AI analysis."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="kubernetes-logs.yaml" file=<rootDir>/modules/mission-control/fixtures/playbooks/logs/k8s.yaml',children:'apiVersion: mission-control.flanksource.com/v1\nkind: Playbook\nmetadata:\n name: kubernetes-logs\n namespace: mc\nspec:\n title: Kubernetes Logs\n icon: logs\n category: Logs\n description: Fetch logs from Kubernetes\n configs:\n - types:\n - Kubernetes::Pod\n - Kubernetes::Deployment\n - Kubernetes::StatefulSet\n - Kubernetes::DaemonSet\n parameters:\n - name: limit\n label: Limit\n description: The maximum number of logs to fetch\n required: false\n default: "100"\n actions:\n - name: Fetch logs from Loki\n logs:\n kubernetes:\n kind: $(.config.config_class)\n apiVersion: $(.config.config.apiVersion)\n namespace: $(.config.tags.namespace)\n name: $(.config.name)\n limit: $(.params.limit)\n start: now-2h\n'})}),"\n",(0,t.jsx)(s,{rows:[{field:"logs",description:"Logs Action",scheme:"[Logs](#logs)"}]}),"\n",(0,t.jsx)(n.h2,{id:"logs",children:"Logs"}),"\n",(0,t.jsxs)(n.p,{children:["Specify exactly one backend. All of the ",(0,t.jsx)(n.a,{href:"#post-processing",children:"post processing"})," fields are set inside the backend, alongside its query."]}),"\n",(0,t.jsx)(c,{oneOf:["loki","cloudwatch","opensearch","kubernetes"],rows:[{field:"cloudwatch",description:"Query logs from AWS CloudWatch Logs",scheme:"[CloudWatch](#cloudwatch)"},{field:"kubernetes",description:"Fetch logs directly from Kubernetes pods",scheme:"[Kubernetes](#kubernetes)"},{field:"loki",description:"Query logs from Grafana Loki",scheme:"[Loki](#loki)"},{field:"opensearch",description:"Query logs from OpenSearch/Elasticsearch",scheme:"[OpenSearch](#opensearch)"}]}),"\n",(0,t.jsx)(n.h3,{id:"post-processing",children:"Post processing"}),"\n",(0,t.jsx)(n.p,{children:"Every backend accepts the following fields to filter, parse and deduplicate logs after they have been retrieved."}),"\n",(0,t.jsx)(c,{rows:[{field:"dedupe.window",description:"Time window for deduplication (e.g., `5m`, `1h`). Logs with identical dedupe fields within this window are merged",scheme:"duration"}
1,{field:"dedupe.fields",description:"Fields to use for identifying duplicate log entries (e.g., `['message', 'level']`). Two logs that have an empty value for a field are still deduped",scheme:"[]string"},{field:"match",description:"CEL expressions to filter logs after retrieval. A log is kept if any of the expressions match",scheme:"[[]MatchExpression](/docs/reference/types#match-expression)"},{field:"parse",description:"Log format to parse the message with",scheme:"`logfmt` | `klogfmt` | `json` | `syslog` | `autodetect`"},{field:"mapping.id",description:"Source field names for the unique log identifier",scheme:"[]string"},{field:"mapping.message",description:"Source field names for the log message content",scheme:"[]string"},{field:"mapping.timestamp",description:"Source field names for the timestamp (tries each until non-empty)",scheme:"[]string"},{field:"mapping.severity",description:"Source field names for the log level/severity",scheme:"[]string"},{field:"mapping.host",description:"Source field names for the host",scheme:"[]string"},{field:"mapping.source",description:"Source field names for the log source",scheme:"[]string"},{field:"mapping.ignore",description:"Fields to drop from the log labels",scheme:"[]string"},{field:"mapping.groupBy",description:"Fields to group the returned logs by",scheme:"[]string"},{field:"mapping.dedupBy",description:"Fields to dedupe the returned logs by",scheme:"[]string"}]}),"\n",(0,t.jsx)(n.h3,{id:"time-range",children:"Time range"}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"cloudwatch"}),", ",(0,t.jsx)(n.code,{children:"kubernetes"})," and ",(0,t.jsx)(n.code,{children:"loki"})," backends share a common time range and limit."]}),"\n",(0,t.jsx)(c,{rows:[{field:"start",description:"Start time of the query. Supports [datemath](https://opensearch.org/docs/latest/field-types/supported-field-types/date/#date-math) e.g. `now-24h`",scheme:"string"},{field:"end",description:"End time of the query. Defaults to now",scheme:"string"},{field:"limit",description:"Maximum number of log lines to return",scheme:"string",templatable:!0}]}),"\n",(0,t.jsx)(n.h3,{id:"cloudwatch",children:"CloudWatch"}),"\n",(0,t.jsxs)(n.p,{children:["Query logs from ",(0,t.jsx)(n.a,{href:"https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/",children:"AWS CloudWatch Logs"})," using CloudWatch Logs Insights."]}),"\n",(0,t.jsx)(c,{rows:[{field:"connection",description:"AWS connection for credentials",scheme:"[AWSConnection](/docs/reference/connections/aws)"},{field:"accessKey",description:"AWS access key ID",scheme:"[EnvVar](/docs/reference/env-var)"},{field:"secretKey",description:"AWS secret access key",scheme:"[EnvVar](/docs/reference/env-var)"},{field:"sessionToken",description:"AWS session token",scheme:"[EnvVar](/docs/reference/env-var)"},{field:"assumeRole",description:"ARN of the role to assume",scheme:"string"},{field:"region",description:"AWS region (e.g., `us-east-1`)",scheme:"string"},{field:"endpoint",description:"Custom AWS endpoint",scheme:"string"},{field:"skipTLSVerify",description:"Skip TLS verification when connecting to AWS",scheme:"bool"},{field:"logGroup",description:"CloudWatch log group to query",scheme:"string",required:!0,templatable:!0},{field:"query",description:"CloudWatch Logs Insights query to run on the log group",scheme:"string",required:!0,templatable:!0}]}),"\n",(0,t.jsx)(i,{summary:"Example",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="cloudwatch.yaml" file=<rootDir>/modules/mission-control/fixtures/playbooks/logs/cloudwatch.yaml',children:"apiVersion: mission-control.flanksource.com/v1\nkind: Playbook\nmetadata:\n name: cloudwatch-events\n namespace: mc\nspec:\n title: Cloudwatch Events\n icon: cloudwatch\n category: Logs\n description: Fetch events from Cloudwatch\n parameters:\n - name: logGroup\n label: Log Group\n description: The log group to fetch events from\n required: true\n - name: limit\n label: Limit\n description: The maximum number of events to fetch\n required: false\n default: '100'\n configs:\n - types:\n - AWS::::Account\n actions:\n - name: Fetch events from CloudWatch\n logs:\n cloudwatch:\n start: now-24h\n limit: $(.params.limit)\n logGroup: $(.params.logGroup)\n query: |\n fields @message, @timestamp, @logStream, @log\n | sort @timestamp desc\n | limit $(.params.limit)\n"})})}),"\n",(0,t.jsx)(n.h3,{id:"kubernetes",children:"Kubernetes"}),"\n",(0,t.jsxs)(n.p,{children:["Fetch logs directly from Kubernetes pods using the Kubernetes API. Logs are fetched for the resource identified by ",(0,t.jsx)(n.code,{children:"kind"}),", ",(0,t.jsx)(n.code,{children:"apiVersion"}),", ",(0,t.jsx)(n.code,{children:"namespace"})," and ",(0,t.jsx)(n.code,{children:"name"})," \u2014 for a workload such as a Deployment, logs from all of its pods are returned."]}),"\n",(0,t.jsx)(c,{rows:[{field:"connection",description:"Kubernetes connection for cluster access",
1scheme:"[KubernetesConnection](/docs/reference/connections/kubernetes)"},{field:"kubeconfig",description:"Kubeconfig content or path",scheme:"[EnvVar](/docs/reference/env-var)"},{field:"kind",description:"Kind of the resource to fetch logs for e.g. `Pod`, `Deployment`, `StatefulSet`, `DaemonSet`",scheme:"string",templatable:!0},{field:"apiVersion",description:"API version of the resource",scheme:"string",templatable:!0},{field:"namespace",description:"Namespace of the resource",scheme:"string",templatable:!0},{field:"name",description:"Name of the resource",scheme:"string",templatable:!0},{field:"pods",description:"Include pods matching any of these selectors. Applies when fetching logs at a higher resource level, such as a deployment spanning multiple pods",scheme:"[[]ResourceSelector](/docs/reference/resource-selector)"},{field:"containers",description:"Fetch logs from only these containers",scheme:"[[]MatchExpression](/docs/reference/types#match-expression)"}]}),"\n",(0,t.jsx)(i,{summary:"Example",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="k8s.yaml" file=<rootDir>/modules/mission-control/fixtures/playbooks/logs/k8s.yaml',children:'apiVersion: mission-control.flanksource.com/v1\nkind: Playbook\nmetadata:\n name: kubernetes-logs\n namespace: mc\nspec:\n title: Kubernetes Logs\n icon: logs\n category: Logs\n description: Fetch logs from Kubernetes\n configs:\n - types:\n - Kubernetes::Pod\n - Kubernetes::Deployment\n - Kubernetes::StatefulSet\n - Kubernetes::DaemonSet\n parameters:\n - name: limit\n label: Limit\n description: The maximum number of logs to fetch\n required: false\n default: "100"\n actions:\n - name: Fetch logs from Loki\n logs:\n kubernetes:\n kind: $(.config.config_class)\n apiVersion: $(.config.config.apiVersion)\n namespace: $(.config.tags.namespace)\n name: $(.config.name)\n limit: $(.params.limit)\n start: now-2h\n'})})}),"\n",(0,t.jsx)(n.h3,{id:"loki",children:"Loki"}),"\n",(0,t.jsxs)(n.p,{children:["Query logs from ",(0,t.jsx)(n.a,{href:"https://grafana.com/oss/loki/",children:"Grafana Loki"})," using LogQL."]}),"\n",(0,t.jsx)(c,{rows:[{field:"connection",description:"Connection name for Loki credentials",scheme:"[Connection](/docs/reference/connections/http)"},{field:"url",description:"Loki server URL (e.g., `http://loki:3100`)",scheme:"string"},{field:"username",description:"Basic auth username",scheme:"[EnvVar](/docs/reference/env-var)"},{field:"password",description:"Basic auth password",scheme:"[EnvVar](/docs/reference/env-var)"},{field:"query",description:'LogQL query (e.g., `{app="myservice"} |= "error"`)',scheme:"string",required:!0,templatable:!0},{field:"since",description:"Duration used to calculate `start` relative to `end`. Any value set for `start` supersedes this",scheme:"string"},{field:"step",description:"Query resolution step width, as a duration or a number of seconds",scheme:"string"},{field:"interval",description:"Only return entries at or greater than this interval",scheme:"string"},{field:"direction",description:"Query direction: `forward` (oldest first) or `backward` (newest first)",scheme:"`forward` | `backward`"}]}),"\n",(0,t.jsx)(i,{summary:"Example",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="loki.yaml" file=<rootDir>/modules/mission-control/fixtures/playbooks/logs/loki.yaml',children:'apiVersion: mission-control.flanksource.com/v1\nkind: Playbook\nmetadata:\n name: loki-logs\n namespace: mc\nspec:\n title: Loki Logs\n icon: logs\n category: Logs\n description: Fetch logs from Loki\n configs:\n - types:\n - Kubernetes::Pod\n - Kubernetes::Deployment\n parameters:\n - name: limit\n label: Limit\n description: The maximum number of logs to fetch\n required: false\n default: "100"\n actions:\n - name: Fetch logs from Loki\n logs:\n loki:\n url: https://logs-prod-111.grafana.net\n username:\n valueFrom:\n secretKeyRef:\n name: loki-grafana-cloud\n key: userid\n password:\n valueFrom:\n secretKeyRef:\n name: loki-grafana-cloud\n key: password\n query: |\n {namespace="{{ .config.tags.namespace }}",{{.config.config_class | toLower}}="{{ .config.name }}"}\n limit: $(.params.limit)\n start: now-2h\n match:\n - severity != "info" && severity != "unknown"\n - labels.service == \'payment\'\n dedupe:\n window: 1h\n fields:\n - message\n'})})}),"\n",(0,t.jsx)(n.h3,{id:"opensearch",children:"OpenSearch"}),"\n",(0,t.jsxs)(n.p,{children:["Query logs from ",(0,t.jsx)(n.a,{href:"https://opensearch.org/",children:"OpenSearch"})," or Elasticsearch clusters."]}),"\n",(0,t.jsx)(c,{rows:[{field:"connection",description:"Connection name for OpenSearch credentials",scheme:"[Connection](/docs/reference/connections/opensearch)"},{field:"address",description:"OpenSearch cluster address",scheme:"string"},{field:"username",description:"Basic auth username",scheme:"[EnvVar](/docs/reference/env-var)"},{field:"password",description:"Basic auth password",scheme:"[EnvVar](/docs/reference/env-var)"},{field:"index",description:"Index name or pattern (e.g., `logs-*`, `app-logs-2024.01.*`)",scheme:"string",required:!0,templatable:!0},{field:"query",description:"OpenSearch query DSL",scheme:"string",required:!0,templatable:!0},{field:"limit",description:"Maximum number of documents to return",scheme:"string",templatable:!0}]}),"\n",(0,t.jsx)(i,{summary:"Example",children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="opensearch.yaml" file=<rootDir>/modules/mission-control/fixtures/playbooks/logs/opensearch.yaml',children:'apiVersion: mission-control.flanksource.com/v1\nkind: Playbook\nmetadata:\n name: opensearch-logs\n namespace: mc\nspec:\n title: OpenSearch Logs\n icon: elasticsearch\n category: Logs\n description: Fetch logs from OpenSearch\n configs:\n - types:\n - Kubernetes::Pod\n - Kubernetes::Deployment\n parameters:\n - name: limit\n label: Limit\n description: The maximum number of logs to fetch\n required: false\n default: \'100\'\n actions:\n - name: Fetch logs from OpenSearch\n logs:\n opensearch:\n address: http://localhost:9200\n query: |\n {\n "query": {\n "bool": {\n "filter": [\n { "term": { "kubernetes.namespace": "$(.config.tags.namespace)" } },\n { "term": { "kubernetes.labels.app": "$(.config.name)" } }\n ]\n }\n }\n }\n index: k8s-logs\n limit: $(.params.limit)\n'})})}),"\n",(0,t.jsx)(n.h2,{id:"output",children:"Output"}),"\n",(0,t.jsx)(n.p,{children:"The action returns a structured result containing the retrieved logs."}),"\n",(0,t.jsx)(c,{rows:[{field:"logs",description:"Log entries with normalized fields",scheme:"[[]LogLine](#log-line)"},{field:"groups",description:"Logs grouped by `mapping.groupBy`, when set",scheme:"[]LogGroup"},{field:"metadata",description:"Backend specific metadata about the query",scheme:"map[string]any"}
1]}),"\n",(0,t.jsx)(n.h3,{id:"log-line",children:"Log line"}),"\n",(0,t.jsx)(c,{rows:[{field:"id",description:"Unique identifier of the log line",scheme:"string"},{field:"message",description:"Log message",scheme:"string"},{field:"severity",description:"Log level",scheme:"string"},{field:"firstObserved",description:"Time the log line was first seen",scheme:"time"},{field:"lastObserved",description:"Time the log line was last seen. Set when the line has been deduped",scheme:"time"},{field:"count",description:"Number of occurrences the line was deduped from",scheme:"int"},{field:"hash",description:"Hash of the tokenized message, used to group similar lines",scheme:"string"},{field:"host",description:"Host the log originated from",scheme:"string"},{field:"source",description:"Source of the log",scheme:"string"},{field:"labels",description:"Remaining fields from the log line",scheme:"map[string]string"}]}),"\n",(0,t.jsx)(n.h3,{id:"using-results-in-subsequent-actions",children:"Using Results in Subsequent Actions"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"actions:\n - name: fetch-logs\n logs:\n kubernetes:\n kind: Deployment\n apiVersion: apps/v1\n namespace: production\n name: api\n start: now-1h\n - name: analyze\n if: 'size(getAction(\"fetch-logs\").result.logs) > 0'\n ai:\n prompt: |\n Analyze these log entries:\n {{.actions.fetch-logs.result.logs | toJSON}}\n"})}),"\n",(0,t.jsx)(n.h2,{id:"templating",children:"Templating"}),"\n",(0,t.jsx)(r.default,{})]})}function m(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(h,{...e})}):h(e)}function p(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}},41085(e,n,s){s.r(n),s.d(n,{assets:()=>l,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>i,toc:()=>a});const i=JSON.parse('{"id":"reference/playbooks/context","title":"Context","description":"CEL Expressions","source":"@site/docs/reference/playbooks/context.mdx","sourceDirName":"reference/playbooks","slug":"/reference/playbooks/context","permalink":"/docs/reference/playbooks/context","draft":false,"unlisted":false,"editUrl":"https://github.com/flanksource/docs/tree/main/docs/reference/playbooks/context.mdx","tags":[],"version":"current","frontMatter":{"title":"Context"},"sidebar":"reference","previous":{"title":"Playbook","permalink":"/docs/reference/playbooks/"},"next":{"title":"Env Vars","permalink":"/docs/reference/playbooks/env-vars"}}');var t=s(74848),o=s(28453);const r={title:"Context"},c=void 0,l={},a=[{value:"CEL Expressions",id:"cel-expressions",level:3},{value:"Go Templating",id:"go-templating",level:3},{value:"Functions",id:"functions",level:3}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,o.R)(),...e.components},{Details:s}=n;return s||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h3,{id:"cel-expressions",children:"CEL Expressions"}),"\n",(0,t.jsxs)(n.p,{children:["The following variables can be used within the ",(0,t.jsx)(n.a,{href:"/docs/reference/scripting/cel",children:"CEL"})," expressions of ",(0,t.jsx)(n.code,{children:"filter"}),", ",(0,t.jsx)(n.code,{children:"if"}),", ",(0,t.jsx)(n.code,{children:"delays"})," and ",(0,t.jsx)(n.code,{children:"parameters.default"}),":"]}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Schema"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"config"})}),(0,t.jsx)(n.td,{children:"Config passed to the playbook"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"/docs/reference/config-db",children:(0,t.jsx)(n.code,{children:"ConfigItem"})})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"check"})}),(0,t.jsx)(n.td,{children:"Canary Check passed to the playbook"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"/docs/reference/canary-checker/check",children:(0,t.jsx)(n.code,{children:"Check"})})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"playbook"})}),(0,t.jsx)(n.td,{children:"Playbook passed to the playbook"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"/docs/reference/playbooks",children:(0,t.jsx)(n.code,{children:"Playbook"})})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"run"})}),(0,t.jsx)(n.td,{children:"Current run"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"/docs/reference/playbooks/#run",children:(0,t.jsx)(n.code,{children:"Run"})})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"params"})}),(0,t.jsx)(n.td,{children:"User provided parameters to the playbook"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"map[string]any"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"request"})}),(0,t.jsx)(n.td,{children:"Webhook request"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.a,{href:"/docs/reference/playbooks/webhooks",children:(0,t.jsx)(n.code,{children:"Webhook Request"})})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"env"})}),(0,t.jsx)(n.td,{children:"Environment variables defined on the playbook"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"map[string]any"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"user.name"})}),(0,t.jsx)(n.td,{children:"Name of the user who invoked the action"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"string"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"user.email"})}),(0,t.jsx)(n.td,{children:"Email of the user who invoked the action"}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"string"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"agent.i
1d"})}),(0,t.jsx)(n.td,{children:"ID of the agent the resource belongs to."}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"string"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"agent.name"})}),(0,t.jsx)(n.td,{children:"Name of the agent the resource belongs to."}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"string"})})]})]})]}),"\n",(0,t.jsx)(s,{summary:"Conditionally Running Actions",children:(0,t.jsxs)("div",{children:[(0,t.jsx)(n.p,{children:"Playbook actions can be selectively executed based on CEL expressions. These expressions must either return"}),(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["a boolean value (",(0,t.jsx)(n.code,{children:"true"})," indicating run the action & skip the action otherwise)"]}),"\n",(0,t.jsx)(n.li,{children:"or a special function among the ones listed below"}),"\n"]}),(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Function"}),(0,t.jsx)(n.th,{children:"Description"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"always()"})}),(0,t.jsx)(n.td,{children:"run no matter what; even if the playbook is cancelled/fails"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"failure()"})}),(0,t.jsx)(n.td,{children:"run if any of the previous actions failed"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"skip()"})}),(0,t.jsx)(n.td,{children:"skip running this action"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"success()"})}),(0,t.jsx)(n.td,{children:"run only if all previous actions succeeded (default)"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"timeout()"})}),(0,t.jsx)(n.td,{children:"run only if any of the previous actions timed out"})]})]})]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="delete-kubernetes-pod.yaml" file=<rootDir>/modules/mission-control/fixtures/playbooks/exec-filter.yaml',children:'---\napiVersion: mission-control.flanksource.com/v1\nkind: Playbook\nmetadata:\n name: notify-send-with-filter\nspec:\n parameters:\n - name: message\n label: The message for notification\n default: \'{{.config.name}}\'\n configs:\n - types: \n - Kubernetes::Pod\n actions:\n - name: Send notification\n exec:\n script: notify-send "{{.config.name}} was created"\n - name: Bad script\n exec:\n script: deltaforce\n - name: Send all success notification\n if: success() # this filter practically skips this action as the second action above always fail
1s\n exec:\n script: notify-send "Everything went successfully"\n - name: Send notification regardless\n if: always()\n exec:\n script: notify-send "a Pod config was created"\n'})})]})}),"\n",(0,t.jsx)(s,{summary:"Defaulting Parameters",children:(0,t.jsx)("div",{children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="delete-kubernetes-pod.yaml"',children:"apiVersion:\n mission-control.flanksource.com/v1\n kind: Playbook\n metadata:\n name: edit\n spec:\n title: 'Edit Kustomize Resource'\n icon: flux\n parameters:\n //highlight-next-line\n - default: 'chore: update $(.config.type)/$(.config.name)'\n name: commit_message\n"})})})}),"\n",(0,t.jsx)(n.h3,{id:"go-templating",children:"Go Templating"}),"\n",(0,t.jsxs)(n.p,{children:["When templating ",(0,t.jsx)(n.code,{children:"actions"})," with ",(0,t.jsx)(n.a,{href:"/docs/reference/scripting/gotemplate",children:"Go Templates"}),", the context variables are available as fields of the template's context object ",(0,t.jsx)(n.code,{children:"."})," eg ",(0,t.jsx)(n.code,{children:".config"}),", ",(0,t.jsx)(n.code,{children:".user.email"})]}),"\n",(0,t.jsx)(s,{summary:"Templating Actions",children:(0,t.jsx)("div",{children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="delete-kubernetes-pod.yaml" file=<rootDir>/modules/mission-control/fixtures/playbooks/scale-deployment.yaml',children:"apiVersion: mission-control.flanksource.com/v1\nkind: Playbook\nmetadata:\n name: scale-deployment\nspec:\n description: Scale Deployment\n configs:\n - types:\n - Kubernetes::Deployment\n parameters:\n - name: replicas\n label: The new desired number of replicas.\n actions:\n - name: kubectl scale\n exec:\n script: |\n kubectl scale --replicas={{.params.replicas}} \\\n --namespace={{.config.tags.namespace}} \\\n deployment {{.config.name}}\n"})})})}),"\n",(0,t.jsx)(n.h3,{id:"functions",children:"Functions"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Function"}),(0,t.jsx)(n.th,{children:"Description"}),(0,t.jsx)(n.th,{children:"Return"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"getLastAction()"})}),(0,t.jsx)(n.td,{children:"Returns the result of the action that just run"}),(0,t.jsx)(n.td,{children:"Action Specific"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"getAction({action})"})}),(0,t.jsx)(n.td,{children:"Return the result of a specific action"}),(0,t.jsx)(n.td,{children:"Action Specific"})]})]})]}),"\n",(0,t.jsx)(n.admonition,{title:"Printing out Results",type:"tip"}),"\n",(0,t.jsx)(s,{summary:"Reusing Action Results",children:(0,t.jsx)("div",{children:(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",metastring:'title="action-results.yaml" file=<rootDir>/modules/mission-control/fixtures/playbooks/action-result.yaml',children:"apiVersion: mission-control.flanksource.com/v1\nkind: Playbook\nmetadata:\n name: use-previous-action-result\nspec:\n description: Creates a file with the content of the config\n configs:\n - types:\n - Kubernetes::Pod\n actions:\n - name: Fetch all changes\n sql:\n query: SELECT id FROM config_changes WHERE config_id = '{{.config.id}}'\n driver: postgres\n connection: connection://postgres/local\n - name: Send notification\n if: 'last_result().count > 0'\n notification:\n title: 'Changes summary for {{.config.name}}'\n connection: connection://slack/flanksource\n message: |\n {{$rows:=index last_result \"count\"}}\n Found {{$rows}} changes\n"})})})})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},28453(e,n,s){s.d(n,{R:()=>r,x:()=>c});var i=s(96540);const t={},o=i.createContext(t);function r(e){const n=i.useContext(o);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.