33800 Docs

← Retour
#!/bin/bash # ═══════════════════════════════════════════════════════════════════════════ # PARSE-YAML.SH - Parser YAML simple pour conf.gouroubleu.yml # Usage: parse_yaml fichier.yml "PREFIX_" # Crée des variables bash : PREFIX_name, PREFIX_target, PREFIX_port, etc. # ═══════════════════════════════════════════════════════════════════════════ parse_yaml() { local yaml_file="$1" local prefix="${2:-}" if [[ ! -f "$yaml_file" ]]; then echo "❌ Fichier YAML non trouvé: $yaml_file" >&2 return 1 fi # Parser simple avec sed/awk # Gère les cas basiques : key: value, key: "value", key: 'value' local s='[[:space:]]*' local w='[a-zA-Z0-9_]*' # Extraire les paires clé: valeur de premier niveau while IFS= read -r line; do # Ignorer commentaires et lignes vides [[ "$line" =~ ^[[:space:]]*# ]] && continue [[ -z "$line" ]] && continue # Extraire clé et valeur if [[ "$line" =~ ^([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*:[[:space:]]*(.*) ]]; then local key="${BASH_REMATCH[1]}" local value="${BASH_REMATCH[2]}" # Nettoyer la valeur # Supprimer quotes value="${value#\"}" value="${value%\"}" value="${value#\'}" value="${value%\'}" # Supprimer commentaires inline value="${value%%#*}" # Trim whitespace value="${value%"${value##*[![:space:]]}"}" value="${value#"${value%%[![:space:]]*}"}" # Si la valeur est vide ou commence par un tableau/objet, on skip pour l'instant if [[ -z "$value" ]] || [[ "$value" == "[" ]] || [[ "$value" == "{" ]]; then continue fi # Convertir true/false en bash [[ "$value" == "true" ]] && value="true" [[ "$value" == "false" ]] && value="false" # Exporter la variable local var_name="${prefix}${key}" export "$var_name"="$value" fi done < "$yaml_file" return 0 } # ─────────────────────────────────────────────────────────────────────────── # Parser avancé pour les sections imbriquées (nginx, storage, crons, etc.) # # Usage: parse_yaml_section fichier.yml "section" "PREFIX_" # # IMPORTANT: Variables créées avec format: ${PREFIX}${section}_${key} # # Exemple pour nginx: # nginx: # domain: api.33800.nowhere84.com # private: true # # parse_yaml_section conf.yml "nginx" "CFG_" # → Crée: CFG_nginx_domain, CFG_nginx_private # # Donc dans le code, utiliser: ${CFG_nginx_domain:-} (PAS ${CFG_domain}) # ─────────────────────────────────────────────────────────────────────────── parse_yaml_section() { local yaml_file="$1" local section="$2" local prefix="${3:-}" if [[ ! -f "$yaml_file" ]]; then echo "❌ Fichier YAML non trouvé: $yaml_file" >&2 return 1 fi local in_section=false local section_indent=0 while IFS= read -r line; do # Calculer l'indentation local stripped="${line#"${line%%[![:space:]]*}"}" local indent=$(( ${#line} - ${#stripped} )) # Ignorer commentaires et lignes vides [[ "$stripped" =~ ^# ]] && continue [[ -z "$stripped" ]] && continue # Détecter début de section if [[ "$stripped" =~ ^${section}:[[:space:]]*$ ]]; then in_section=true section_indent=$indent continue fi # Si on est dans la section if $in_section; then # Sortir si on revient au niveau parent if [[ $indent -le $section_indent ]] && [[ ! "$stripped" =~ ^[[:space:]] ]]; then in_section=false continue fi # Parser les clés de la section if [[ "$stripped" =~ ^([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*:[[:space:]]*(.*) ]]; then local key="${BASH_REMATCH[1]}" local value="${BASH_REMATCH[2]}" # Nettoyer la valeur value="${value#\"}" value="${value%\"}" value="${value#\'}" value="${value%\'}" value="${value%%#*}" value="${value%"${value##*[![:space:]]}"}" if [[ -n "$value" ]]; then local var_name="${prefix}${section}_${key}" export "$var_name"="$value" fi fi fi done < "$yaml_file" return 0 } # ─────────────────────────────────────────────────────────────────────────── # Vérifier si une clé existe et est true # ─────────────────────────────────────────────────────────────────────────── yaml_is_true() { local var_name="$1" local value="${!var_name:-false}" [[ "$value" == "true" ]] } # ─────────────────────────────────────────────────────────────────────────── # Obtenir une valeur avec défaut # ─────────────────────────────────────────────────────────────────────────── yaml_get() { local var_name="$1" local default="${2:-}" echo "${!var_name:-$default}" } # ─────────────────────────────────────────────────────────────────────────── # Parser les listes YAML simples (format "- valeur") # # Usage: parse_yaml_list fichier.yml "section" "sous_section" # Retourne les éléments un par ligne sur stdout # # Exemple pour: # nginx: # public_paths: # - /api/oauth/callback # - /health # # parse_yaml_list conf.yml "nginx" "public_paths" # → /api/oauth/callback # → /health # ─────────────────────────────────────────────────────────────────────────── parse_yaml_list() { local yaml_file="$1" local section="$2" local key="$3" if [[ ! -f "$yaml_file" ]]; then return 1 fi local in_section=false local in_key=false local section_indent=0 local key_indent=0 while IFS= read -r line; do local stripped="${line#"${line%%[![:space:]]*}"}" local indent=$(( ${#line} - ${#stripped} )) [[ "$stripped" =~ ^# ]] && continue [[ -z "$stripped" ]] && continue # Detect section start if [[ "$stripped" =~ ^${section}:[[:space:]]*$ ]]; then in_section=true section_indent=$indent in_key=false continue fi if $in_section; then # Exit section if back to parent level if [[ $indent -le $section_indent ]] && [[ ! "$stripped" =~ ^[[:space:]] ]]; then in_section=false in_key=false continue fi # Detect key start if [[ "$stripped" =~ ^${key}:[[:space:]]*$ ]]; then in_key=true key_indent=$indent continue fi if $in_key; then # Exit key if back to key level or above if [[ $indent -le $key_indent ]] && [[ ! "$stripped" =~ ^- ]]; then in_key=false continue fi # Parse list item "- value" if [[ "$stripped" =~ ^-[[:space:]]+(.*) ]]; then local value="${BASH_REMATCH[1]}" # Clean quotes value="${value#\"}" value="${value%\"}" value="${value#\'}" value="${value%\'}" value="${value%%#*}" value="${value%"${value##*[![:space:]]}"}" [[ -n "$value" ]] && echo "$value" fi fi fi done < "$yaml_file" } # ─────────────────────────────────────────────────────────────────────────── # Parser les sidecars YAML (liste d'objets) # # Usage: parse_yaml_sidecars fichier.yml # # Exporte: # SIDECARS_COUNT : nombre de sidecars # SIDECAR_0_name, SIDECAR_0_image, SIDECAR_0_ports, etc. # Les sous-listes (ports, cap_add, devices, sysctls, volumes, networks) # sont stockées en comma-separated # Les sous-sections env: → SIDECAR_N_env_KEY=val # # Exemple pour: # sidecars: # - name: "wireguard-sidecar" # image: "registry.../wireguard-sidecar:latest" # ports: # - "5410:5410" # cap_add: # - NET_ADMIN # env: # PORT: "5410" # health: "/health" # # → SIDECARS_COUNT=1 # → SIDECAR_0_name=wireguard-sidecar # → SIDECAR_0_image=registry.../wireguard-sidecar:latest # → SIDECAR_0_ports=5410:5410 # → SIDECAR_0_cap_add=NET_ADMIN # → SIDECAR_0_env_PORT=5410 # → SIDECAR_0_health=/health # ─────────────────────────────────────────────────────────────────────────── parse_yaml_sidecars() { local yaml_file="$1" if [[ ! -f "$yaml_file" ]]; then echo "❌ Fichier YAML non trouvé: $yaml_file" >&2 return 1 fi local in_sidecars=false local sidecars_indent=0 local index=-1 local current_list_key="" local current_list_values="" local in_env=false local env_indent=0 local item_indent=0 # Liste des clés qui contiennent des sous-listes local list_keys="ports cap_add devices sysctls volumes networks" # Fonction interne pour finaliser une liste en cours _flush_list() { if [[ -n "$current_list_key" ]] && [[ -n "$current_list_values" ]] && [[ $index -ge 0 ]]; then # Supprimer le comma de tête current_list_values="${current_list_values#,}" export "SIDECAR_${index}_${current_list_key}=${current_list_values}" fi current_list_key="" current_list_values="" } while IFS= read -r line; do local stripped="${line#"${line%%[![:space:]]*}"}" local indent=$(( ${#line} - ${#stripped} )) # Ignorer commentaires et lignes vides [[ "$stripped" =~ ^# ]] && continue [[ -z "$stripped" ]] && continue # Détecter début de section sidecars: if [[ "$stripped" =~ ^sidecars:[[:space:]]*$ ]]; then in_sidecars=true sidecars_indent=$indent continue fi if ! $in_sidecars; then continue fi # Sortir de sidecars si on revient au niveau parent ou en dessous if [[ $indent -le $sidecars_indent ]] && [[ ! "$stripped" =~ ^[[:space:]] ]]; then _flush_list in_sidecars=false in_env=false continue fi # Détecter un nouvel item de sidecar (- name: xxx) if [[ "$stripped" =~ ^-[[:space:]]+name:[[:space:]]+(.*) ]]; then # Finaliser la liste précédente si en cours _flush_list in_env=false index=$((index + 1)) item_indent=$indent local value="${BASH_REMATCH[1]}" value="${value#\"}" ; value="${value%\"}" value="${value#\'}" ; value="${value%\'}" value="${value%%#*}" value="${value%"${value##*[![:space:]]}"}" export "SIDECAR_${index}_name=${value}" continue fi # On doit être dans un sidecar (index >= 0) [[ $index -lt 0 ]] && continue # Détecter si on est dans une sous-section env: if $in_env; then if [[ $indent -le $env_indent ]]; then in_env=false # Fall through pour traiter la ligne courante else # Parser clé: valeur dans env if [[ "$stripped" =~ ^([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*:[[:space:]]*(.*) ]]; then local key="${BASH_REMATCH[1]}" local value="${BASH_REMATCH[2]}" value="${value#\"}" ; value="${value%\"}" value="${value#\'}" ; value="${value%\'}" value="${value%%#*}" value="${value%"${value##*[![:space:]]}"}" export "SIDECAR_${index}_env_${key}=${value}" fi continue fi fi # Détecter si on collecte des items de liste (- value) if [[ -n "$current_list_key" ]]; then if [[ "$stripped" =~ ^-[[:space:]]+(.*) ]] && [[ "$stripped" != -\ name:* ]]; then local value="${BASH_REMATCH[1]}" value="${value#\"}" ; value="${value%\"}" value="${value#\'}" ; value="${value%\'}" value="${value%%#*}" value="${value%"${value##*[![:space:]]}"}" current_list_values="${current_list_values},${value}" continue else # Plus de list items, finaliser _flush_list # Fall through pour traiter la ligne courante fi fi # Parser les clés du sidecar if [[ "$stripped" =~ ^([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*:[[:space:]]*(.*) ]]; then local key="${BASH_REMATCH[1]}" local value="${BASH_REMATCH[2]}" # Nettoyer la valeur value="${value#\"}" ; value="${value%\"}" value="${value#\'}" ; value="${value%\'}" value="${value%%#*}" value="${value%"${value##*[![:space:]]}"}" # Vérifier si c'est la section env: if [[ "$key" == "env" ]] && [[ -z "$value" ]]; then in_env=true env_indent=$indent continue fi # Vérifier si c'est une clé de liste (valeur vide = liste qui suit) local is_list=false for lk in $list_keys; do if [[ "$key" == "$lk" ]]; then is_list=true break fi done if $is_list && [[ -z "$value" ]]; then # Début d'une sous-liste current_list_key="$key" current_list_values="" continue fi # Clé simple avec valeur if [[ -n "$value" ]]; then export "SIDECAR_${index}_${key}=${value}" fi fi done < "$yaml_file" # Finaliser dernière liste si en cours _flush_list # Exporter le count export SIDECARS_COUNT=$((index + 1)) return 0 } # ─────────────────────────────────────────────────────────────────────────── # Parser les hooks YAML (liste d'objets sous hooks.pre_deploy / hooks.post_deploy) # # Format YAML: # hooks: # pre_deploy: # - action: http # method: POST # url: "http://..." # description: "Pause worker" # - action: wait_http # url: "http://..." # jq_condition: '.status == "paused"' # timeout: 60 # post_deploy: # - action: http # method: POST # url: "http://..." # # Exports: HOOKS_pre_deploy_COUNT, HOOKS_pre_deploy_0_action, HOOKS_pre_deploy_0_url, etc. # HOOKS_post_deploy_COUNT, HOOKS_post_deploy_0_action, etc. # ─────────────────────────────────────────────────────────────────────────── parse_yaml_hooks() { local yaml_file="$1" if [[ ! -f "$yaml_file" ]]; then return 1 fi local in_hooks=false local hooks_indent=0 local in_phase=false local phase="" local phase_indent=0 local index=-1 while IFS= read -r line; do local stripped="${line#"${line%%[![:space:]]*}"}" local indent=$(( ${#line} - ${#stripped} )) # Skip comments and empty lines [[ "$stripped" =~ ^# ]] && continue [[ -z "$stripped" ]] && continue # Detect hooks: section if [[ "$stripped" =~ ^hooks:[[:space:]]*$ ]]; then in_hooks=true hooks_indent=$indent continue fi if ! $in_hooks; then continue fi # Exit hooks if back to parent level if [[ $indent -le $hooks_indent ]] && [[ ! "$stripped" =~ ^[[:space:]] ]]; then in_hooks=false in_phase=false continue fi # Detect phase (pre_deploy: or post_deploy:) if [[ "$stripped" =~ ^(pre_deploy|post_deploy):[[:space:]]*$ ]]; then # Save previous phase count if $in_phase && [[ -n "$phase" ]]; then export "HOOKS_${phase}_COUNT=$((index + 1))" fi phase="${BASH_REMATCH[1]}" phase_indent=$indent in_phase=true index=-1 continue fi if ! $in_phase; then continue fi # Exit phase if back to phase level or above if [[ $indent -le $phase_indent ]] && [[ ! "$stripped" =~ ^- ]]; then export "HOOKS_${phase}_COUNT=$((index + 1))" in_phase=false continue fi # Detect new hook item (- action: xxx or - key: value) if [[ "$stripped" =~ ^-[[:space:]]+([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*:[[:space:]]*(.*) ]]; then index=$((index + 1)) local key="${BASH_REMATCH[1]}" local value="${BASH_REMATCH[2]}" # Clean value value="${value#\"}" ; value="${value%\"}" value="${value#\'}" ; value="${value%\'}" value="${value%%#*}" value="${value%"${value##*[![:space:]]}"}" export "HOOKS_${phase}_${index}_${key}=${value}" continue fi # Parse key:value within a hook item (continuation lines) if [[ $index -ge 0 ]] && [[ "$stripped" =~ ^([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*:[[:space:]]*(.*) ]]; then local key="${BASH_REMATCH[1]}" local value="${BASH_REMATCH[2]}" # Clean value value="${value#\"}" ; value="${value%\"}" value="${value#\'}" ; value="${value%\'}" value="${value%%#*}" value="${value%"${value##*[![:space:]]}"}" export "HOOKS_${phase}_${index}_${key}=${value}" fi done < "$yaml_file" # Finalize last phase count if $in_phase && [[ -n "$phase" ]]; then export "HOOKS_${phase}_COUNT=$((index + 1))" fi return 0 }