Skip to Content

YAML Commands & Tools Cheatsheet

Table of Contents

  1. YAML Basics
  2. Data Types
  3. Advanced Syntax
  4. YAML Tools
  5. yq - YAML Processor
  6. Python YAML
  7. Ruby YAML
  8. Go YAML
  9. Kubernetes YAML
  10. Docker Compose YAML
  11. GitHub Actions YAML
  12. Ansible YAML
  13. YAML Validation
  14. YAML Best Practices
  15. Interview Scenarios

YAML Basics

1. Basic Key-Value Pairs

name: John Doe age: 30 email: john@example.com

2. Nested Objects (Mappings)

person: name: John Doe age: 30 contact: email: john@example.com phone: 123-456-7890

3. Lists (Sequences)

# Dash style fruits: - apple - banana - cherry # Inline style numbers: [1, 2, 3, 4, 5]

4. Comments

# This is a comment name: John # Inline comment # Multi-line comment # Line 1 # Line 2 age: 30

5. Strings

# Unquoted name: John Doe # Single quoted (literal) message: 'Hello, World!' # Double quoted (allows escapes) path: "C:\\Users\\John" escaped: "Line 1\nLine 2"

6. Multi-line Strings

# Literal block (preserves newlines) literal: | Line 1 Line 2 Line 3 # Folded block (folds newlines) folded: > This is a long sentence that will be folded into one line. # Strip final newlines (|-) stripped: |- Line 1 Line 2 # Keep final newlines (|+) kept: |+ Line 1 Line 2

Data Types

7. Numbers

integer: 42 float: 3.14 negative: -10 scientific: 1.5e+10 octal: 0o14 hexadecimal: 0xC

8. Booleans

enabled: true disabled: false yes_value: yes no_value: no on_value: on off_value: off

9. Null Values

nothing: null tilde: ~ empty:

10. Dates and Timestamps

date: 2026-02-15 datetime: 2026-02-15T10:30:00Z timestamp: 2026-02-15 10:30:00

11. Lists of Objects

users: - name: John age: 30 email: john@example.com - name: Jane age: 25 email: jane@example.com

12. Mixed Lists

mixed: - string - 42 - true - null - name: nested object value: 123

Advanced Syntax

13. Anchors and Aliases (Reuse)

defaults: &defaults timeout: 30 retries: 3 development: <<: *defaults host: dev.example.com production: <<: *defaults host: prod.example.com timeout: 60 # Override

14. Merge Keys

base: &base name: Base version: 1.0 app1: <<: *base port: 8080 app2: <<: *base port: 8081

15. Multiple Anchors

auth: &auth username: admin password: secret database: &db host: localhost port: 5432 app: <<: [*auth, *db] name: MyApp

16. Explicit Types

# Force string version: !!str 1.0 numbers: !!str 123 # Force integer count: !!int "42" # Force float price: !!float 99 # Binary data data: !!binary | R0lGODlhDAAMAIQAAP//9/X

17. Multi-line Keys

? - key1 - key2 : value # Or ? | This is a multi-line key : value

18. Sets

# Unique values (rarely used) colors: !!set ? red ? green ? blue

19. Ordered Maps

# Preserves order (rarely used) ordered: !!omap - first: 1 - second: 2 - third: 3

20. Environment Variable Style

database: host: ${DB_HOST} port: ${DB_PORT:-5432} # With default name: ${DB_NAME}

YAML Tools

21. Install yq (YAML Processor)

# macOS brew install yq # Linux wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 chmod +x yq_linux_amd64 sudo mv yq_linux_amd64 /usr/local/bin/yq # Via Go go install github.com/mikefarah/yq/v4@latest

22. yamllint (Linter)

pip install yamllint yamllint file.yaml yamllint -d relaxed file.yaml

23. Online Validators


yq - YAML Processor

24. Basic yq Usage

# Pretty print yq '.' file.yaml # Evaluate expression yq '.name' file.yaml # Multiple files yq '.' file1.yaml file2.yaml # In-place edit yq -i '.name = "John"' file.yaml

25. Read Values

# Single value yq '.name' config.yaml # Nested value yq '.database.host' config.yaml # Array element yq '.users[0].name' config.yaml # All array elements yq '.users[].name' config.yaml

26. Write/Update Values

# Set value yq '.name = "John"' file.yaml # Set nested value yq '.database.host = "localhost"' file.yaml # Add to array yq '.items += "new-item"' file.yaml # Delete key yq 'del(.obsolete)' file.yaml

27. Filter and Select

# Filter array yq '.users[] | select(.age > 30)' file.yaml # Multiple conditions yq '.users[] | select(.age > 30 and .active == true)' file.yaml

28. Convert YAML to JSON

yq -o json '.' file.yaml # Pretty JSON yq -o json -I 2 '.' file.yaml

29. Convert JSON to YAML

yq -p json '.' file.json # Or with jq jq -r '.' file.json | yq -P '.'

30. Merge YAML Files

# Merge two files yq ea '. as $item ireduce ({}; . * $item)' file1.yaml file2.yaml # Merge arrays yq ea '[.]' file1.yaml file2.yaml # Merge specific keys yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' file1.yaml file2.yaml

31. Extract Specific Fields

# Create new structure yq '{name: .user.name, email: .user.email}' file.yaml # Multiple items yq '.users[] | {name, email}' file.yaml

32. Loop Through Items

# With bash yq '.users[].name' file.yaml | while read name; do echo "User: $name" done

33. Sort Arrays

# Sort by field yq '.users |= sort_by(.age)' file.yaml # Reverse sort yq '.users |= sort_by(.age) | reverse' file.yaml

34. Length/Count

# Array length yq '.users | length' file.yaml # String length yq '.name | length' file.yaml

35. Keys

# Get all keys yq 'keys' file.yaml # Nested keys yq '.database | keys' file.yaml

36. Conditional Updates

# Update if condition met yq '(.users[] | select(.name == "John") | .age) = 31' file.yaml # Add field conditionally yq '.users[] |= . + (if .age > 30 then {"senior": true} else {} end)' file.yaml

37. Array Operations

# Map array yq '.users |= map(. + {"active": true})' file.yaml # Filter and transform yq '.users |= map(select(.age > 25) | {name, email})' file.yaml

38. String Operations

# Concatenate yq '.fullname = .firstname + " " + .lastname' file.yaml # Uppercase/Lowercase yq '.name |= upcase' file.yaml yq '.name |= downcase' file.yaml # Replace yq '.message |= sub("old", "new")' file.yaml

39. Math Operations

# Add yq '.age += 1' file.yaml # Multiply yq '.price *= 1.1' file.yaml # Calculate yq '.total = .price * .quantity' file.yaml

40. Environment Variables

# Use env variable export USERNAME="john" yq '.user.name = env(USERNAME)' file.yaml # With default yq '.port = (env(PORT) // 8080)' file.yaml

Python YAML

41. Install PyYAML

pip install pyyaml

42. Load YAML

import yaml # From string yaml_string = """ name: John age: 30 """ data = yaml.safe_load(yaml_string) # From file with open('config.yaml', 'r') as file: data = yaml.safe_load(file) print(data['name'])

43. Load Multiple Documents

# file.yaml --- document: first --- document: second
with open('file.yaml', 'r') as file: documents = yaml.safe_load_all(file) for doc in documents: print(doc)

44. Dump YAML

import yaml data = { 'name': 'John', 'age': 30, 'emails': ['john@example.com'] } # To string yaml_string = yaml.dump(data) # Pretty print yaml_string = yaml.dump(data, default_flow_style=False) # To file with open('output.yaml', 'w') as file: yaml.dump(data, file, default_flow_style=False)

45. Custom Constructors

import yaml def person_constructor(loader, node): values = loader.construct_mapping(node) return f"{values['first']} {values['last']}" yaml.add_constructor('!person', person_constructor) yaml_string = """ user: !person first: John last: Doe """ data = yaml.safe_load(yaml_string)

46. Preserve Order

from collections import OrderedDict import yaml def ordered_load(stream): class OrderedLoader(yaml.SafeLoader): pass def construct_mapping(loader, node): return OrderedDict(loader.construct_pairs(node)) OrderedLoader.add_constructor( yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping ) return yaml.load(stream, OrderedLoader)

Ruby YAML

47. Load YAML (Ruby)

require 'yaml' # From file data = YAML.load_file('config.yaml') # From string yaml_string = <<~YAML name: John age: 30 YAML data = YAML.load(yaml_string) puts data['name']

48. Dump YAML (Ruby)

require 'yaml' data = { 'name' => 'John', 'age' => 30 } # To string yaml_string = data.to_yaml # To file File.open('output.yaml', 'w') { |f| f.write(data.to_yaml) }

Go YAML

49. Load YAML (Go)

package main import ( "gopkg.in/yaml.v3" "io/ioutil" "log" ) type Config struct { Name string `yaml:"name"` Age int `yaml:"age"` Email string `yaml:"email"` } func main() { data, err := ioutil.ReadFile("config.yaml") if err != nil { log.Fatal(err) } var config Config err = yaml.Unmarshal(data, &config) if err != nil { log.Fatal(err) } log.Printf("Name: %s", config.Name) }

50. Dump YAML (Go)

package main import ( "gopkg.in/yaml.v3" "io/ioutil" "log" ) type Config struct { Name string `yaml:"name"` Age int `yaml:"age"` } func main() { config := Config{ Name: "John", Age: 30, } data, err := yaml.Marshal(&config) if err != nil { log.Fatal(err) } err = ioutil.WriteFile("output.yaml", data, 0644) if err != nil { log.Fatal(err) } }

Kubernetes YAML

51. Pod Definition

apiVersion: v1 kind: Pod metadata: name: nginx-pod labels: app: nginx spec: containers: - name: nginx image: nginx:1.21 ports: - containerPort: 80 env: - name: ENV_VAR value: "value" resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"

52. Deployment

apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.21 ports: - containerPort: 80

53. Service

apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancer

54. ConfigMap

apiVersion: v1 kind: ConfigMap metadata: name: app-config data: database.host: "localhost" database.port: "5432" app.properties: | key1=value1 key2=value2

55. Secret

apiVersion: v1 kind: Secret metadata: name: app-secret type: Opaque data: username: YWRtaW4= # base64 encoded password: cGFzc3dvcmQ= stringData: email: admin@example.com # Plain text

Docker Compose YAML

56. Basic Docker Compose

version: '3.8' services: web: image: nginx:latest ports: - "8080:80" volumes: - ./html:/usr/share/nginx/html environment: - NGINX_HOST=localhost - NGINX_PORT=80 networks: - webnet database: image: postgres:14 environment: POSTGRES_DB: mydb POSTGRES_USER: user POSTGRES_PASSWORD: password volumes: - db-data:/var/lib/postgresql/data networks: - webnet networks: webnet: volumes: db-data:

57. Docker Compose with Build

version: '3.8' services: app: build: context: . dockerfile: Dockerfile args: - NODE_ENV=production ports: - "3000:3000" depends_on: - redis - postgres environment: - DATABASE_URL=postgres://user:pass@postgres:5432/db - REDIS_URL=redis://redis:6379 redis: image: redis:7-alpine command: redis-server --appendonly yes volumes: - redis-data:/data postgres: image: postgres:14-alpine environment: POSTGRES_DB: ${DB_NAME:-mydb} POSTGRES_USER: ${DB_USER:-user} POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - postgres-data:/var/lib/postgresql/data volumes: redis-data: postgres-data:

58. Health Checks

services: web: image: nginx healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 start_period: 40s

GitHub Actions YAML

59. Basic Workflow

name: CI on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 'lts/*' - name: Install dependencies run: npm ci - name: Run tests run: npm test - name: Build run: npm run build

60. Matrix Strategy

name: Matrix Test on: [push] jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] node: ['lts/*', 'current'] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - run: npm test

61. Reusable Workflows

name: Reusable Workflow on: workflow_call: inputs: environment: required: true type: string secrets: token: required: true jobs: deploy: runs-on: ubuntu-latest environment: ${{ inputs.environment }} steps: - uses: actions/checkout@v4 - name: Deploy run: ./deploy.sh env: TOKEN: ${{ secrets.token }}

Ansible YAML

62. Ansible Playbook

--- - name: Configure web servers hosts: webservers become: yes vars: http_port: 80 domain: example.com tasks: - name: Install nginx apt: name: nginx state: present update_cache: yes - name: Start nginx service service: name: nginx state: started enabled: yes - name: Copy config file template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: restart nginx handlers: - name: restart nginx service: name: nginx state: restarted

63. Ansible Inventory

all: children: webservers: hosts: web1: ansible_host: 192.168.1.10 web2: ansible_host: 192.168.1.11 vars: ansible_user: ubuntu databases: hosts: db1: ansible_host: 192.168.1.20 db2: ansible_host: 192.168.1.21 vars: ansible_user: admin

64. Ansible Roles

# playbook.yml --- - hosts: webservers roles: - common - nginx - { role: database, db_name: myapp }

YAML Validation

65. Validate with yamllint

# Basic validation yamllint file.yaml # Custom config yamllint -d '{extends: default, rules: {line-length: {max: 120}}}' file.yaml # Configuration file (.yamllint) cat > .yamllint << 'EOF' extends: default rules: line-length: max: 120 indentation: spaces: 2 comments: min-spaces-from-content: 1 EOF yamllint .

66. Validate with Python

import yaml import sys try: with open('config.yaml', 'r') as file: data = yaml.safe_load(file) print("Valid YAML") except yaml.YAMLError as e: print(f"Invalid YAML: {e}") sys.exit(1)

67. Validate Kubernetes YAML

# Dry run kubectl apply -f deployment.yaml --dry-run=client # Validate kubectl apply -f deployment.yaml --validate=true --dry-run=server # Using kubeval kubeval deployment.yaml # Using kustomize kustomize build . | kubectl apply --dry-run=client -f -

YAML Best Practices

68. Indentation

# Use 2 spaces (recommended) parent: child: grandchild: value # Never use tabs # ❌ Bad parent: → child: value # ✅ Good parent: child: value

69. Quotes

# When to use quotes numeric_string: "123" # Force string special_chars: "yes@no" # Contains special chars starts_with_space: " text" # Starts with space colons_in_value: "key: value" # Contains colon # When not needed simple_string: hello number: 123 boolean: true

70. Long Lines

# Bad - too long description: "This is a very long description that exceeds the recommended line length and makes the file hard to read" # Good - use folded style description: > This is a very long description that is split across multiple lines for better readability # Or literal style script: | #!/bin/bash echo "Line 1" echo "Line 2"

71. Consistent Naming

# Choose one style and stick with it # snake_case (Python) database_host: localhost api_key: secret # camelCase (JavaScript) databaseHost: localhost apiKey: secret # kebab-case (YAML/Kubernetes) database-host: localhost api-key: secret

72. Comments

# Section comment explaining the purpose database: # Host configuration host: localhost # Can override with DB_HOST port: 5432 # Default PostgreSQL port # Authentication username: admin password: secret # Store in vault for production

73. Anchors Best Practices

# Bad - overusing anchors item1: &anchor1 <<: *base <<: *auth <<: *network value: 1 # Good - use anchors for repeated configurations defaults: &defaults timeout: 30 retries: 3 service1: <<: *defaults name: api service2: <<: *defaults name: worker

Interview Scenarios

Scenario 1: Parse Multi-Environment Config

Question: Extract database config for specific environment

# config.yaml cat > config.yaml << 'EOF' environments: development: database: host: localhost port: 5432 production: database: host: prod-db.example.com port: 5432 EOF # Extract production database config yq '.environments.production.database' config.yaml

Scenario 2: Update Kubernetes Image

Question: Update container image in deployment

yq '.spec.template.spec.containers[0].image = "nginx:1.22"' deployment.yaml # Update in-place yq -i '.spec.template.spec.containers[0].image = "nginx:1.22"' deployment.yaml # Update all containers yq -i '.spec.template.spec.containers[].image = "nginx:1.22"' deployment.yaml

Scenario 3: Merge Environment-Specific Configs

Question: Merge base and environment-specific configurations

# base.yaml cat > base.yaml << 'EOF' app: name: myapp timeout: 30 EOF # prod.yaml cat > prod.yaml << 'EOF' app: host: prod.example.com replicas: 5 EOF # Merge yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' base.yaml prod.yaml

Scenario 4: Extract All Container Images

Question: List all container images from Kubernetes manifests

# From single file yq '.spec.template.spec.containers[].image' deployment.yaml # From multiple files yq '.spec.template.spec.containers[].image' k8s/*.yaml | sort -u # From complex structure find . -name "*.yaml" -exec yq '.. | .image? | select(.)' {} \; | sort -u

Scenario 5: Validate Required Fields

Question: Check if all deployments have resource limits

yq ' .spec.template.spec.containers[] | select(.resources.limits.memory == null or .resources.limits.cpu == null) | "Missing limits for: " + .name ' deployment.yaml

Scenario 6: Generate ConfigMap from Files

Question: Create Kubernetes ConfigMap from multiple files

#!/bin/bash echo "apiVersion: v1" echo "kind: ConfigMap" echo "metadata:" echo " name: app-config" echo "data:" for file in config/*.properties; do key=$(basename "$file") echo " $key: |" sed 's/^/ /' "$file" done

Scenario 7: Convert Between Formats

Question: Convert Docker Compose to Kubernetes

# Using kompose kompose convert -f docker-compose.yaml # Manual conversion with yq # Extract service name and image yq '.services | to_entries | .[] | { "name": .key, "image": .value.image }' docker-compose.yaml

Scenario 8: Bulk Update Labels

Question: Add labels to all Kubernetes resources

# Add label to all resources for file in k8s/*.yaml; do yq -i '.metadata.labels.environment = "production"' "$file" done # Add label only to deployments yq -i ' select(.kind == "Deployment") | .metadata.labels.environment = "production" ' k8s/*.yaml

Scenario 9: Find Resources by Label

Question: Find all services with specific label

yq 'select(.kind == "Service" and .metadata.labels.app == "nginx")' k8s/*.yaml # Extract just the names yq ' select(.kind == "Service" and .metadata.labels.app == "nginx") | .metadata.name ' k8s/*.yaml

Scenario 10: Template Substitution

Question: Replace placeholders with environment variables

#!/bin/bash export APP_NAME="myapp" export APP_VERSION="1.0.0" export REPLICAS="3" # Using envsubst envsubst < template.yaml > output.yaml # Using yq with env variables yq ' .metadata.name = env(APP_NAME) | .spec.replicas = env(REPLICAS) | .spec.template.spec.containers[0].image = env(APP_NAME) + ":" + env(APP_VERSION) ' template.yaml > output.yaml

Scenario 11: Split Multi-Document YAML

Question: Split multi-document YAML into separate files

#!/bin/bash # all.yaml contains multiple documents csplit -s -f resource- all.yaml '/^---$/' '{*}' # Rename based on content for file in resource-*; do kind=$(yq '.kind' "$file") name=$(yq '.metadata.name' "$file") mv "$file" "${kind}-${name}.yaml" done

Scenario 12: Validate CI/CD Pipeline

Question: Check GitHub Actions workflow for deprecated actions

yq ' .jobs.*.steps[] | select(.uses) | select(.uses | test("@v1$")) | "Deprecated action: " + .uses ' .github/workflows/*.yml

Scenario 13: Generate Documentation

Question: Extract API endpoints from OpenAPI YAML

yq ' .paths | to_entries | .[] | "Endpoint: " + .key + "\n" + " Methods: " + (.value | keys | join(", ")) ' openapi.yaml

Scenario 14: Compare Configurations

Question: Find differences between two YAML configs

# Using diff with sorted YAML diff <(yq -P 'sort_keys(..)' file1.yaml) <(yq -P 'sort_keys(..)' file2.yaml) # Using yq to show specific changes yq ' load("file1.yaml") as $old | load("file2.yaml") as $new | ($new | keys) - ($old | keys) as $added | ($old | keys) - ($new | keys) as $removed | { "added": $added, "removed": $removed } '

Scenario 15: Optimize Docker Compose

Question: Remove unused networks and volumes

# Find services that use specific network yq '.services.* | select(.networks != null) | .networks[]' docker-compose.yaml | sort -u # Clean up unused networks used_networks=$(yq '.services.*.networks[]' docker-compose.yaml | sort -u) yq -i " .networks = (.networks | with_entries( select(.key as \$k | \"$used_networks\" | contains(\$k)) )) " docker-compose.yaml

Advanced Patterns

76. Schema Validation

# schema.yaml $schema: http://json-schema.org/draft-07/schema# type: object required: - apiVersion - kind - metadata properties: apiVersion: type: string kind: type: string metadata: type: object required: - name

77. Custom Tags

# Define custom tag database: !secret password: encrypted_value # Process in Python import yaml def secret_constructor(loader, node): value = loader.construct_mapping(node) # Decrypt password return value yaml.add_constructor('!secret', secret_constructor)

78. Conditional Include

# Include file conditionally (using yq) environments: <<: *base production: $if: env(ENVIRONMENT) == "production" replicas: 5

Quick Reference

YAML Syntax

Key-value: key: value Nested: parent: child: value List: - item1 - item2 Inline list: [item1, item2] Inline object: {key1: value1, key2: value2} Multi-line |: Preserves newlines Multi-line >: Folds newlines Comment: # This is a comment Anchor: &name and *name Merge: <<: *anchor

Common Tools

yq YAML processor yamllint Linter kubectl Kubernetes validation kompose Docker Compose to K8s jsonnet Advanced templating

File Extensions

.yaml Primary extension .yml Alternative extension

Last updated on