Skip to main content

GitOps Action

GitOps action allows you to make commits and push to a remote repository.

edit-kubernetes-manifests-gitops.yaml
apiVersion: mission-control.flanksource.com/v1
kind: Playbook
metadata:
name: edit-kubernetes-manifests-gitops
spec:
title: 'Edit Kustomize Resource'
icon: 'flux'
parameters:
- default: 'chore: update $(.config.type)/$(.config.name)'
label: 'Commit Message'
name: 'commit_message'
- default: '$(.config.config | toJSON | neat | json | toYAML)'
label: 'Changes'
name: 'yamlInput'
properties:
size: 'large'
type: 'code'
configs:
- labelSelector: 'kustomize.toolkit.fluxcd.io/name'
actions:
- name: 'Create Pull Request With Changes'
gitops:
repo:
url: 'https://github.com/flanksource/flux'
connection: 'connection://default/github'
base: 'main'
branch: 'edit-manifest-$(random.Alpha 8)'
commit:
author: '$(.user.name)'
email: '$(.user.email)'
message: '$(.params.commit_message)'
pr:
title: '$(.params.commit_message)'
patches:
- path: 'prod/kustomization.yaml'
yq: |
select(
.kind=="$(.config.config | jq `.kind`)" and
.metadata.name=="$(.config.config | jq `.metadata.name`)"
) |= $(.params.yamlInput | yaml | toJSON)
FieldDescriptionScheme
commit*

Commit details

Commit

name*

Step Name

string

repo*

The repository details

Repository

files

List of files to create

[]File

patches

List of JQ/YQ patches to apply

[]Patch

pr

Create a Pull Request instead of a commit (Only available for github and gitlab)

PullRequest

delay

A delay before running the action e.g. 8h

Duration or CEL with Playbook Context

filter

Conditionally run an action

CEL with Playbook Context

runsOn

Which runner (agent) to run the action on

[]Agent

templatesOn

Where templating (and secret management) of actions should occur

host or agent

timeout

Timeout on this action.

Duration

You must specify patches and/or files

Repository

FieldDescriptionScheme
base

Branch to clone. Defaults to main

string

branch

The branch to update. Defaults to base

string

connection

Connection name to use the credentials for the git repo

string

type

Git repository type

github, gitlab, azure_devops, http, git

url

URL of the git repository

string

You must specify connection or url but not both

Commit Detail

FieldDescriptionSchemeRequiredTemplatable
authorAuthor namestringtruetrue
emailAuthor emailstringtrue
messageCommit messagestringtrue

Pull Request

FieldDescriptionSchemeRequiredTemplatable
titleTitle of the Pull requeststringtruetrue
tagsTags to add to the PR[]stringtrue

Patch

Patches modify existing files on the git repo. You can either use yq to modify yaml files or jq to modify json files.

FieldDescriptionSchemeRequiredTemplatable
pathPath to patchstringtruetrue
yqyq querystringfalsetrue
jqjq querystringfalsetrue

File

Files create or delete existing files on the git repo.

FieldDescriptionSchemeRequiredTemplatable
pathPath to filestringtruetrue
contentContent of the file. Use the $delete keyword to delete an existing filestringtruetrue

Custom Origin Annotation

In the example above, you saw a playbook that edited Flux-created manifests. However, there was a slight issue - it had some variables hardcoded, specifically the git repository, git branch, and the kustomization file path. When you have configurations from multiple clusters, you'll need to duplicate the playbook for each cluster, as the git repository and kustomization file path will differ. Even if you have multiple Flux kustomizations on a single cluster, you'll need to duplicate the playbook for each of those kustomizations.

There's a better way to build a single generic GitOps playbook that works for configurations with any Flux source and kustomization.

When a GitOps action is run against a config resource that has a config.kubernetes.io/origin annotation, the following env vars are automatically available:

FieldDescriptionScheme
git.branch

The primary branch

string

git.file

Name of the file that created the config resource the playbook is run against.

string

git.url

URL of the git repository

string

kustomize.path

Path of the kustomization file that created the config resource the playbook is run against. This comes from the spec of the kustomization.

string

These env vars are extracted by traversing up the Flux Kustomization and Git Repository that created the config resource the playbook is running against. We'll see this in detail shortly.

To tag all the resources with that annotation, you'll need to add originAnnotations to the buildMetadata field as shown below:

Setting origin annotation
kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
buildMetadata: [originAnnotations]
resources:
- monitoring

The above kustomization would add the following annotation to the config resource:

monitoring/alertmanager.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
config.kubernetes.io/origin: |
path: monitoring/alertmanager.yaml
...

Example

edit-kubernetes-manifests-gitops.yaml
apiVersion: mission-control.flanksource.com/v1
kind: Playbook
metadata:
name: edit-kubernetes-manifests-gitops
spec:
title: 'Edit Kustomize Resource'
icon: flux
parameters:
- default: 'chore: update $(.config.type)/$(.config.name)'
label: Commit Message
name: commit_message
- default: $(.config.config | toJSON | neat | json | toYAML)
label: ""
name: yamlInput
properties:
size: large
type: code
configs:
- labelSelector: 'kustomize.toolkit.fluxcd.io/name'
env:
- name: file_path
value: {{ .config.config | jq `.metadata.annotations["config.kubernetes.io/origin"]` | yaml).path }}
- name: kustomization_path
value: {{ (catalog_traverse .config.id "Kubernetes::Kustomization").Config | json | jq `.spec.path` }}
- name: git_url
value: {{ (catalog_traverse .config.id "Kubernetes::Kustomization/Kubernetes::GitRepository").Config | json | jq `.spec.url` }}
- name: git_branch
value: {{ (catalog_traverse .config.id "Kubernetes::Kustomization/Kubernetes::GitRepository").Config | json | jq `.spec.ref.branch` }}
actions:
- name: Create Pull Request With Changes
gitops:
repo:
url: '$(.env.git_url)'
connection: 'connection://default/github'
base: '$(.env.git_branch)'
branch: edit-manifest-$(random.Alpha 8)
commit:
author: '$(.user.name)'
email: '$(.user.email)'
message: $(.params.commit_message)
pr:
title: $(.params.commit_message)
patches:
- path: '$(filepath.Join .env.kustomization_path .env.file_path)'
yq: |
select(
.kind=="$(.config.config | jq `.kind`)" and
.metadata.name=="$(.config.config | jq `.metadata.name`)"
) |= $(.params.yamlInput | yaml | toJSON)

Templating

CEL Expressions

The following variables can be used within the CEL expressions of filter, if, delays and parameters.default:

FieldDescriptionSchema
configConfig passed to the playbookConfigItem
componentComponent passed to the playbookComponent
checkCanary Check passed to the playbookCheck
playbookPlaybook passed to the playbookPlaybook
runCurrent runRun
paramsUser provided parameters to the playbookmap[string]any
requestWebhook requestWebhook Request
envEnvironment variables defined on the playbookmap[string]any
user.nameName of the user who invoked the actionstring
user.emailEmail of the user who invoked the actionstring
agent.idID of the agent the resource belongs to.string
agent.nameName of the agent the resource belongs to.string
Conditionally Running Actions

Playbook actions can be selectively executed based on CEL expressions. These expressions must either return

  • a boolean value (true indicating run the action & skip the action otherwise)
  • or a special function among the ones listed below
FunctionDescription
always()run no matter what; even if the playbook is cancelled/fails
failure()run if any of the previous actions failed
skip()skip running this action
success()run only if all previous actions succeeded (default)
timeout()run only if any of the previous actions timed out
delete-kubernetes-pod.yaml
---
apiVersion: mission-control.flanksource.com/v1
kind: Playbook
metadata:
name: notify-send-with-filter
spec:
parameters:
- name: message
label: The message for notification
default: '{{.config.name}}'
configs:
- types:
- Kubernetes::Pod
actions:
- name: Send notification
exec:
script: notify-send "{{.config.name}} was created"
- name: Bad script
exec:
script: deltaforce
- name: Send all success notification
if: success() # this filter practically skips this action as the second action above always fails
exec:
script: notify-send "Everything went successfully"
- name: Send notification regardless
if: always()
exec:
script: notify-send "a Pod config was created"
Defaulting Parameters
delete-kubernetes-pod.yaml
apiVersion:
mission-control.flanksource.com/v1
kind: Playbook
metadata:
name: edit
spec:
title: 'Edit Kustomize Resource'
icon: flux
parameters:
- default: 'chore: update $(.config.type)/$(.config.name)'
name: commit_message

Go Templating

When templating actions with Go Templates, the context variables are available as fields of the template's context object . eg .config, .user.email

Templating Actions
delete-kubernetes-pod.yaml
apiVersion: mission-control.flanksource.com/v1
kind: Playbook
metadata:
name: scale-deployment
spec:
description: Scale Deployment
configs:
- types:
- Kubernetes::Deployment
parameters:
- name: replicas
label: The new desired number of replicas.
actions:
- name: kubectl scale
exec:
script: |
kubectl scale --replicas={{.params.replicas}} \
--namespace={{.config.tags.namespace}} \
deployment {{.config.name}}

Functions

FunctionDescriptionReturn
getLastAction()Returns the result of the action that just runAction Specific
getAction({action})Return the result of a specific actionAction Specific
Reusing Action Results
action-results.yaml
apiVersion: mission-control.flanksource.com/v1
kind: Playbook
metadata:
name: use-previous-action-result
spec:
description: Creates a file with the content of the config
configs:
- types:
- Kubernetes::Pod
actions:
- name: Fetch all changes
sql:
query: SELECT id FROM config_changes WHERE config_id = '{{.config.id}}'
driver: postgres
connection: connection://postgres/local
- name: Send notification
if: 'last_result().count > 0'
notification:
title: 'Changes summary for {{.config.name}}'
connection: connection://slack/flanksource
message: |
{{$rows:=index last_result "count"}}
Found {{$rows}} changes