Skip to content

Instantly share code, notes, and snippets.

@karlkfi
Last active January 16, 2025 01:31
Show Gist options
  • Save karlkfi/22d3da7603ceac4239c157a180454ea2 to your computer and use it in GitHub Desktop.
Save karlkfi/22d3da7603ceac4239c157a180454ea2 to your computer and use it in GitHub Desktop.
count-k8s-objects.sh - Count the number of Kubernetes objects in a directory and error if there are too many
#!/bin/bash
# This script recursively counts the number of Kubernetes objects in YAML and JSON files within a directory.
# It uses `yq` to parse YAML and JSON, prints the object count for each file,
# and also prints the total count for each directory. It errors if the total object count exceeds 2000.
# It skips directories that start with "."
set -euo pipefail
# --- Configuration ---
readonly MAX_OBJECTS=2000
# --- Functions ---
# Usage: count_objects_in_file <file>
# Counts the number of Kubernetes objects in the specified file.
count_objects_in_file() {
local file="$1"
yq -eN '[[select(documentIndex >= 0)] | length]' "$file" | yq -e '.[] as $n ireduce (0; . + $n)'
}
# Usage: process_directory <directory> [indent]
# Processes a directory, counts objects in files, prints file and directory totals.
process_directory() {
local directory="$1"
local indent="${2:-""}" # Default indent to empty string if not provided
local dir_total_objects=0
local file_count
local subdir_total
# Iterate over each subdirectory
while IFS= read -r -d $'\0' subdir; do
# Skip directories that start with "." using find's -not -path option
subdir_total=$(process_directory "$subdir" "${indent} ") # Capture output from recursive call
dir_total_objects=$((dir_total_objects + subdir_total))
done < <(find "$directory" -mindepth 1 -maxdepth 1 -type d -not -path '*/.*' -print0)
# Iterate over each file in the directory
while IFS= read -r -d $'\0' file; do
file_count=$(count_objects_in_file "$file")
# Safely print the file count with indentation
>&2 echo "${file} (${file_count})"
dir_total_objects=$((dir_total_objects + file_count))
done < <(find "$directory" -maxdepth 1 -type f \( -name "*.yaml" -o -name "*.yml" -o -name "*.json" \) -print0)
# Print object count for this directory
echo "${dir_total_objects}"
}
# Usage: validate_count <count>
# Checks if the object count exceeds the maximum allowed.
validate_count() {
local count="$1"
if (( count > MAX_OBJECTS )); then
echo "Error: Too many Kubernetes objects found ($count). Maximum allowed is $MAX_OBJECTS." >&2
return 1
fi
return 0
}
# --- Main ---
main() {
local directory="$1"
local total_objects
if [[ -z "$directory" ]]; then
echo "Usage: $0 <directory>" >&2
return 1
fi
if [[ ! -d "$directory" ]]; then
echo "Error: Directory '$directory' does not exist." >&2
return 1
fi
# Process the directory, which updates the global total_objects
total_objects=$(process_directory "$directory")
if ! validate_count "$total_objects"; then
return 1
fi
echo "Total number of Kubernetes objects: $total_objects"
return 0
}
# --- Script Execution ---
main "$@"
@karlkfi
Copy link
Author

karlkfi commented Jan 16, 2025

$ git clone https://github.com/config-sync-examples/crontab-crs
$ cd crontab-crs
$ ./count-k8s-objects.sh .
./configs/crs.yaml (13060)
./configs/ns.yaml (1)
./root-sync-cr.yaml (1)
./config-management-multi.yaml (1)
Error: Too many Kubernetes objects found (13063). Maximum allowed is 2000.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment