skills/karmab/kcli/kcli-plan-authoring

kcli-plan-authoring

SKILL.md

kcli Plan Authoring

Plan File Structure

Plans are YAML files with Jinja2 templating. Resources are defined as top-level keys with a type field.

parameters:
  param1: value1
  param2: value2

resourcename:
  type: resourcetype
  key1: value1
  key2: {{ param1 }}

Resource Types

VM (default if no type specified)

myvm:
  image: fedora40
  memory: 4096
  numcpus: 2
  disks:
    - size: 20
    - size: 10
      pool: otherpool
  nets:
    - name: default
    - name: mynet
      ip: 192.168.1.10
      netmask: 255.255.255.0
      gateway: 192.168.1.1
  cmds:
    - echo hello > /tmp/test
  files:
    - path: /etc/myconfig
      content: |
        key=value

Profile

myprofile:
  type: profile
  image: centos9stream
  memory: 2048
  numcpus: 2
  disks:
    - 10
  nets:
    - default

Network

mynetwork:
  type: network
  cidr: 192.168.100.0/24
  dhcp: true
  nat: true
  domain: mylab.local

Image

myimage:
  type: image
  url: https://example.com/image.qcow2
  pool: default

Container

mycontainer:
  type: container
  image: nginx:latest
  ports:
    - 8080:80

Jinja2 Templating

Parameter Substitution

parameters:
  cluster_name: mycluster
  worker_count: 3

{{ cluster_name }}-master:
  image: rhcos
  
{% for i in range(worker_count) %}
{{ cluster_name }}-worker-{{ i }}:
  image: rhcos
{% endfor %}

Conditionals

parameters:
  enable_storage: true

myvm:
  image: fedora40
{% if enable_storage %}
  disks:
    - size: 100
{% endif %}

Custom Filters

kcli provides custom Jinja2 filters in kvirt/jinjafilters/jinjafilters.py:

Path/File Filters:

  • basename - Get filename from path
  • dirname - Get directory from path
  • diskpath - Convert to /dev/ path if needed
  • exists - Check if file/path exists
  • pwd_path - Handle workdir paths in containers
  • real_path - Get real/absolute path
  • read_file - Read file contents

String/Data Filters:

  • none - Return empty string if None
  • type - Return type name (string, int, dict, list)
  • base64 - Base64 encode value
  • certificate - Wrap in BEGIN/END CERTIFICATE if needed
  • count - Count occurrences of character

Kubernetes/Cluster Filters:

  • kubenodes - Generate node names for cluster
  • defaultnodes - Generate default node list
  • has_ctlplane - Check if list has ctlplane/master entries

Version/Release Filters:

  • github_version - Get latest version from GitHub releases
  • min_ocp_version - Compare OpenShift versions (minimum)
  • max_ocp_version - Compare OpenShift versions (maximum)

Network Filters:

  • local_ip - Get local IP for network interface
  • network_ip - Get IP from network CIDR
  • ipv6_wrap - Wrap IPv6 addresses in brackets

Utility Filters:

  • kcli_info - Get VM info via kcli command
  • find_manifests - Find YAML manifests in directory
  • wait_crd - Generate wait script for CRD creation
  • wait_csv - Generate wait script for CSV readiness
  • filter_bgp_peers - Filter BGP peer list

Standard Jinja2 filters (default, join, upper, lower, etc.) also work

Parameter Files

Create kcli_parameters.yml alongside your plan:

cluster_name: prod
worker_count: 5
memory: 8192

Override at runtime:

kcli create plan -f myplan.yml -P worker_count=10 myplan

Common VM Parameters

Parameter Default Description
numcpus 2 Number of CPUs
memory 512 Memory in MB
pool default Storage pool
image None Base image name
nets [default] Network list
disks [{size:10}] Disk list
cmds [] Post-boot commands
files [] Files to inject
keys [] SSH public keys
start true Auto-start VM
cloudinit true Enable cloud-init

Plan Execution

# Create plan
kcli create plan -f myplan.yml myplanname

# Create with parameter overrides
kcli create plan -f myplan.yml -P memory=4096 -P image=fedora40 myplanname

# List plans
kcli list plan

# Get plan info
kcli info plan myplanname

# Delete plan (and all its resources)
kcli delete plan myplanname

# Update existing plan
kcli update plan -f myplan.yml myplanname

Debugging Plans

  1. Validate YAML syntax - Use python -c "import yaml; yaml.safe_load(open('plan.yml'))"
  2. Check Jinja2 rendering - Look for unbalanced {{ }} or {% %}
  3. Run with debug - kcli -d create plan -f plan.yml test
  4. Check dependencies - Ensure images/networks exist before VMs reference them

Example: Multi-VM Plan

parameters:
  domain: lab.local
  base_image: centos9stream

labnetwork:
  type: network
  cidr: 10.0.0.0/24
  dhcp: true
  domain: {{ domain }}

webserver:
  image: {{ base_image }}
  memory: 2048
  nets:
    - labnetwork
  cmds:
    - dnf -y install nginx
    - systemctl enable --now nginx

database:
  image: {{ base_image }}
  memory: 4096
  disks:
    - size: 20
    - size: 50
  nets:
    - labnetwork
  cmds:
    - dnf -y install postgresql-server
    - postgresql-setup --initdb
Weekly Installs
16
Repository
karmab/kcli
GitHub Stars
632
First Seen
Jan 24, 2026
Installed on
antigravity14
windsurf14
claude-code14
gemini-cli14
trae13
codex13