|
#!/bin/bash |
|
# |
|
# ArgoCD Load Testing Script |
|
# |
|
# Creates realistic ArgoCD applications for load testing Cased CD Enterprise. |
|
# |
|
# USAGE: |
|
# ./load-test-argocd.sh [NUM_APPS] |
|
# |
|
# EXAMPLES: |
|
# ./load-test-argocd.sh # Create 50 apps (default) |
|
# ./load-test-argocd.sh 1000 # Create 1000 apps |
|
# |
|
# WHAT IT CREATES: |
|
# - 4 repositories (ArgoCD examples, Kubernetes examples, Bitnami, NGINX) |
|
# - 32 namespaces (8 teams × 4 environments: team-environment pattern) |
|
# - N applications distributed across shared namespaces |
|
# - Realistic labels: team, service, environment, app-type |
|
# - 70% auto-sync, 30% manual sync (realistic distribution) |
|
# |
|
# CLEANUP: |
|
# kubectl delete applications -n argocd -l load-test=true --wait=false |
|
# kubectl delete namespaces -l load-test=true --wait=false |
|
# |
|
# FILTERING: |
|
# kubectl get applications -n argocd -l load-test=true |
|
# kubectl get applications -n argocd -l load-test=true,environment=prod |
|
# kubectl get applications -n argocd -l load-test=true,team=platform |
|
# |
|
|
|
set -e |
|
|
|
# Number of applications to create (default: 50) |
|
NUM_APPS=${1:-50} |
|
BATCH_SIZE=50 # Create apps in batches for better performance |
|
|
|
echo "Load Testing ArgoCD with $NUM_APPS realistic applications..." |
|
echo "" |
|
|
|
# Add test repositories using kubectl |
|
echo "Adding test repositories..." |
|
|
|
# ArgoCD example apps repo |
|
cat <<EEOF | kubectl apply -f - > /dev/null |
|
apiVersion: v1 |
|
kind: Secret |
|
metadata: |
|
name: repo-argocd-examples |
|
namespace: argocd |
|
labels: |
|
argocd.argoproj.io/secret-type: repository |
|
stringData: |
|
url: https://github.com/argoproj/argocd-example-apps.git |
|
type: git |
|
name: argocd-examples |
|
EEOF |
|
echo " - Added argocd-example-apps" |
|
|
|
# Kubernetes examples repo |
|
cat <<EEOF | kubectl apply -f - > /dev/null |
|
apiVersion: v1 |
|
kind: Secret |
|
metadata: |
|
name: repo-kubernetes-examples |
|
namespace: argocd |
|
labels: |
|
argocd.argoproj.io/secret-type: repository |
|
stringData: |
|
url: https://github.com/kubernetes/examples.git |
|
type: git |
|
name: kubernetes-examples |
|
EEOF |
|
echo " - Added kubernetes-examples" |
|
|
|
# Bitnami Helm repo |
|
cat <<EEOF | kubectl apply -f - > /dev/null |
|
apiVersion: v1 |
|
kind: Secret |
|
metadata: |
|
name: repo-bitnami |
|
namespace: argocd |
|
labels: |
|
argocd.argoproj.io/secret-type: repository |
|
stringData: |
|
url: https://charts.bitnami.com/bitnami |
|
type: helm |
|
name: bitnami |
|
EEOF |
|
echo " - Added Bitnami Helm repo" |
|
|
|
# NGINX Helm repo |
|
cat <<EEOF | kubectl apply -f - > /dev/null |
|
apiVersion: v1 |
|
kind: Secret |
|
metadata: |
|
name: repo-nginx |
|
namespace: argocd |
|
labels: |
|
argocd.argoproj.io/secret-type: repository |
|
stringData: |
|
url: https://kubernetes.github.io/ingress-nginx |
|
type: helm |
|
name: nginx |
|
EEOF |
|
echo " - Added NGINX Helm repo" |
|
|
|
echo "" |
|
echo "Creating realistic namespaces..." |
|
echo "" |
|
|
|
# Realistic app components and environments |
|
SERVICES=("api" "web" "worker" "frontend" "backend" "db" "cache" "queue" "auth" "payments" "notifications" "analytics" "search" "admin" "mobile-api") |
|
TEAMS=("platform" "product" "data" "infrastructure" "security" "payments" "growth" "mobile") |
|
ENVS=("prod" "staging" "dev" "qa") |
|
|
|
# Create team-environment namespaces (realistic: 8 teams × 4 envs = 32 namespaces) |
|
NAMESPACE_COUNT=0 |
|
for team in "${TEAMS[@]}"; do |
|
for env in "${ENVS[@]}"; do |
|
NAMESPACE="$team-$env" |
|
cat <<EEOF | kubectl apply -f - > /dev/null 2>&1 |
|
apiVersion: v1 |
|
kind: Namespace |
|
metadata: |
|
name: $NAMESPACE |
|
labels: |
|
load-test: "true" |
|
team: "$team" |
|
environment: "$env" |
|
EEOF |
|
NAMESPACE_COUNT=$((NAMESPACE_COUNT + 1)) |
|
done |
|
done |
|
|
|
echo " - Created $NAMESPACE_COUNT namespaces (team-environment combinations)" |
|
echo "" |
|
echo "Creating $NUM_APPS realistic applications..." |
|
echo " Using batch size of $BATCH_SIZE for optimal performance" |
|
echo "" |
|
|
|
# App templates with more variety |
|
APPS=( |
|
"guestbook|https://github.com/argoproj/argocd-example-apps.git|guestbook" |
|
"helm-guestbook|https://github.com/argoproj/argocd-example-apps.git|helm-guestbook" |
|
"kustomize-guestbook|https://github.com/argoproj/argocd-example-apps.git|kustomize-guestbook" |
|
"sock-shop|https://github.com/argoproj/argocd-example-apps.git|sock-shop" |
|
"ksonnet-guestbook|https://github.com/argoproj/argocd-example-apps.git|ksonnet-guestbook" |
|
) |
|
|
|
# Function to generate realistic app name |
|
generate_app_name() { |
|
local idx=$1 |
|
local service_idx=$((idx % ${#SERVICES[@]})) |
|
local team_idx=$((idx % ${#TEAMS[@]})) |
|
local env_idx=$((idx % ${#ENVS[@]})) |
|
|
|
echo "${TEAMS[$team_idx]}-${SERVICES[$service_idx]}-${ENVS[$env_idx]}-$idx" |
|
} |
|
|
|
# Function to generate sync policy (mix of auto and manual) |
|
generate_sync_policy() { |
|
local idx=$1 |
|
|
|
# 70% auto-sync, 30% manual |
|
if [ $((idx % 10)) -lt 7 ]; then |
|
cat <<'POLICY' |
|
syncPolicy: |
|
automated: |
|
prune: true |
|
selfHeal: true |
|
POLICY |
|
else |
|
echo "" |
|
fi |
|
} |
|
|
|
# Create applications in batches |
|
START_TIME=$(date +%s) |
|
BATCH_FILE="/tmp/argocd-batch-apps-$$.yaml" |
|
|
|
for i in $(seq 1 $NUM_APPS); do |
|
# Pick app template |
|
TEMPLATE_IDX=$((i % ${#APPS[@]})) |
|
TEMPLATE=${APPS[$TEMPLATE_IDX]} |
|
|
|
# Parse template using bash parameter expansion |
|
IFS='|' read -r BASE_APP REPO_URL APP_PATH <<< "$TEMPLATE" |
|
|
|
# Generate realistic names |
|
APP_NAME=$(generate_app_name $i) |
|
|
|
# Parse app name using bash parameter expansion |
|
IFS='-' read -r TEAM SERVICE ENV REST <<< "$APP_NAME" |
|
|
|
# Use shared team-environment namespace (realistic!) |
|
NAMESPACE="$TEAM-$ENV" |
|
|
|
# Get sync policy |
|
SYNC_POLICY=$(generate_sync_policy $i) |
|
|
|
# Append application to batch file |
|
cat <<EEOF >> $BATCH_FILE |
|
--- |
|
apiVersion: argoproj.io/v1alpha1 |
|
kind: Application |
|
metadata: |
|
name: $APP_NAME |
|
namespace: argocd |
|
labels: |
|
load-test: "true" |
|
app-type: "$BASE_APP" |
|
team: "$TEAM" |
|
service: "$SERVICE" |
|
environment: "$ENV" |
|
annotations: |
|
load-test/created-at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)" |
|
spec: |
|
project: default |
|
source: |
|
repoURL: $REPO_URL |
|
targetRevision: HEAD |
|
path: $APP_PATH |
|
destination: |
|
server: https://kubernetes.default.svc |
|
namespace: $NAMESPACE |
|
$SYNC_POLICY |
|
EEOF |
|
|
|
# Apply in batches |
|
if [ $((i % BATCH_SIZE)) -eq 0 ] || [ $i -eq $NUM_APPS ]; then |
|
kubectl apply -f $BATCH_FILE |
|
rm -f $BATCH_FILE |
|
|
|
CURRENT_TIME=$(date +%s) |
|
ELAPSED=$((CURRENT_TIME - START_TIME)) |
|
RATE=$((i / (ELAPSED + 1))) |
|
echo " - Created $i/$NUM_APPS applications... (${RATE} apps/sec)" |
|
fi |
|
done |
|
|
|
# Clean up batch file if it exists |
|
rm -f $BATCH_FILE |
|
|
|
END_TIME=$(date +%s) |
|
TOTAL_TIME=$((END_TIME - START_TIME)) |
|
|
|
echo "" |
|
echo "Load test setup complete in ${TOTAL_TIME} seconds!" |
|
echo "" |
|
echo "SUMMARY:" |
|
echo " - 4 repositories added" |
|
echo " - $NAMESPACE_COUNT namespaces created (team-environment combinations)" |
|
echo " - $NUM_APPS applications created" |
|
echo " - Average: $((NUM_APPS / (TOTAL_TIME + 1))) apps/second" |
|
echo "" |
|
|
|
# Count apps by type |
|
echo "Application distribution:" |
|
for app in "${APPS[@]}"; do |
|
IFS='|' read -r BASE_NAME _ _ <<< "$app" |
|
COUNT=$(kubectl get applications -n argocd -l app-type=$BASE_NAME --no-headers 2>/dev/null | wc -l | tr -d ' ') |
|
echo " - $BASE_NAME: $COUNT apps" |
|
done |
|
|
|
echo "" |
|
|
|
# Count apps by environment |
|
echo "Environment distribution:" |
|
for env in "${ENVS[@]}"; do |
|
COUNT=$(kubectl get applications -n argocd -l environment=$env,load-test=true --no-headers 2>/dev/null | wc -l | tr -d ' ') |
|
echo " - $env: $COUNT apps" |
|
done |
|
|
|
echo "" |
|
|
|
# Count sync policies |
|
AUTO_COUNT=$(kubectl get applications -n argocd -l load-test=true -o jsonpath='{range .items[*]}{.spec.syncPolicy.automated}{"\n"}{end}' 2>/dev/null | grep -c -v '^$' || echo "0") |
|
MANUAL_COUNT=$((NUM_APPS - AUTO_COUNT)) |
|
echo "Sync policies:" |
|
echo " - Auto-sync: $AUTO_COUNT apps (~$((AUTO_COUNT * 100 / NUM_APPS))%)" |
|
echo " - Manual sync: $MANUAL_COUNT apps (~$((MANUAL_COUNT * 100 / NUM_APPS))%)" |
|
|
|
echo "" |
|
echo "To clean up all test apps, run:" |
|
echo " kubectl delete applications -n argocd -l load-test=true --wait=false" |
|
echo " kubectl delete namespaces -l load-test=true --wait=false" |
|
echo "" |
|
echo "To view status:" |
|
echo " kubectl get applications -n argocd -l load-test=true" |
|
echo " kubectl get applications -n argocd -l load-test=true,environment=prod" |
|
echo " kubectl get applications -n argocd -l load-test=true,team=platform" |
|
echo "" |