gitops
This commit is contained in:
@@ -0,0 +1,305 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
OUTPUT_DIR="./generated-helmops"
|
||||
API_VERSION="fleet.cattle.io/v1alpha1"
|
||||
RESOURCE_KIND="HelmOp"
|
||||
VALUES_ARGS=()
|
||||
WORKSPACE_NAMESPACE="fleet-local"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./generate-fleet-helmops-from-helm.sh [options]
|
||||
|
||||
Description:
|
||||
Legge le release presenti con `helm list -A`, recupera metadata e values
|
||||
per ogni release e genera un file YAML per release in formato HelmOp-style.
|
||||
|
||||
Options:
|
||||
-o, --output-dir <dir> Directory di output (default: ./generated-helmops)
|
||||
-w, --workspace-namespace <ns>
|
||||
Namespace dove creare la risorsa HelmOp
|
||||
(default: fleet-local)
|
||||
--api-version <value> apiVersion del manifest generato
|
||||
(default: fleet.cattle.io/v1alpha1)
|
||||
--kind <value> kind del manifest generato (default: HelmOp)
|
||||
-a, --all-values Usa `helm get values -a -o yaml`
|
||||
-h, --help Mostra questo help
|
||||
|
||||
Examples:
|
||||
./generate-fleet-helmops-from-helm.sh
|
||||
./generate-fleet-helmops-from-helm.sh -o ./clusters/idc/imported
|
||||
./generate-fleet-helmops-from-helm.sh -w fleet-default
|
||||
./generate-fleet-helmops-from-helm.sh --kind HelmChart --api-version helm.cattle.io/v1
|
||||
EOF
|
||||
}
|
||||
|
||||
require_cmd() {
|
||||
local cmd="$1"
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
echo "Errore: comando richiesto non trovato: $cmd" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
trim() {
|
||||
local value="$1"
|
||||
value="${value#"${value%%[![:space:]]*}"}"
|
||||
value="${value%"${value##*[![:space:]]}"}"
|
||||
printf '%s' "$value"
|
||||
}
|
||||
|
||||
safe_file_name() {
|
||||
printf '%s' "$1" | tr '/\\:' '---'
|
||||
}
|
||||
|
||||
extract_yaml_scalar() {
|
||||
local key="$1"
|
||||
local content="$2"
|
||||
|
||||
printf '%s\n' "$content" \
|
||||
| sed -n "s/^[[:space:]]*${key}:[[:space:]]*//p" \
|
||||
| head -n 1 \
|
||||
| sed 's/^"//; s/"$//; s/^\x27//; s/\x27$//'
|
||||
}
|
||||
|
||||
extract_first_source() {
|
||||
local content="$1"
|
||||
|
||||
awk '
|
||||
/^sources:/ { in_sources=1; next }
|
||||
in_sources && /^[^[:space:]-]/ { exit }
|
||||
in_sources && /^[[:space:]]*-[[:space:]]*/ {
|
||||
sub(/^[[:space:]]*-[[:space:]]*/, "")
|
||||
print
|
||||
exit
|
||||
}
|
||||
' <<< "$content"
|
||||
}
|
||||
|
||||
extract_chart_name_from_ref() {
|
||||
local chart_ref="$1"
|
||||
|
||||
if [[ "$chart_ref" =~ ^(.+)-([0-9][A-Za-z0-9.+_-]*)$ ]]; then
|
||||
printf '%s' "${BASH_REMATCH[1]}"
|
||||
else
|
||||
printf '%s' "$chart_ref"
|
||||
fi
|
||||
}
|
||||
|
||||
extract_chart_version_from_ref() {
|
||||
local chart_ref="$1"
|
||||
|
||||
if [[ "$chart_ref" =~ ^(.+)-([0-9][A-Za-z0-9.+_-]*)$ ]]; then
|
||||
printf '%s' "${BASH_REMATCH[2]}"
|
||||
fi
|
||||
}
|
||||
|
||||
find_repo_url_from_local_cache() {
|
||||
local chart_name="$1"
|
||||
local chart_version="$2"
|
||||
local search_json=""
|
||||
local repo_alias=""
|
||||
|
||||
[[ -z "$chart_name" ]] && return 0
|
||||
|
||||
search_json="$(helm search repo "$chart_name" --versions -o json 2>/dev/null || true)"
|
||||
[[ -z "$search_json" || "$search_json" == "[]" ]] && return 0
|
||||
|
||||
if [[ -n "$chart_version" ]]; then
|
||||
repo_alias="$(jq -r --arg chart "$chart_name" --arg version "$chart_version" '
|
||||
map(select((.name | split("/") | last) == $chart and .version == $version))
|
||||
| .[0].name // empty
|
||||
' <<< "$search_json")"
|
||||
fi
|
||||
|
||||
if [[ -z "$repo_alias" ]]; then
|
||||
repo_alias="$(jq -r --arg chart "$chart_name" '
|
||||
map(select((.name | split("/") | last) == $chart))
|
||||
| .[0].name // empty
|
||||
' <<< "$search_json")"
|
||||
fi
|
||||
|
||||
[[ -z "$repo_alias" ]] && return 0
|
||||
|
||||
repo_alias="${repo_alias%%/*}"
|
||||
|
||||
helm repo list -o json 2>/dev/null \
|
||||
| jq -r --arg alias "$repo_alias" 'map(select(.name == $alias)) | .[0].url // empty'
|
||||
}
|
||||
|
||||
indent_file() {
|
||||
local file_path="$1"
|
||||
sed 's/^/ /' "$file_path"
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-o|--output-dir)
|
||||
OUTPUT_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
-w|--workspace-namespace)
|
||||
WORKSPACE_NAMESPACE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--api-version)
|
||||
API_VERSION="$2"
|
||||
shift 2
|
||||
;;
|
||||
--kind)
|
||||
RESOURCE_KIND="$2"
|
||||
shift 2
|
||||
;;
|
||||
-a|--all-values)
|
||||
VALUES_ARGS=(-a)
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Opzione sconosciuta: $1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
require_cmd helm
|
||||
require_cmd jq
|
||||
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
releases_json="$(helm list -A -o json)"
|
||||
release_count="$(jq 'length' <<< "$releases_json")"
|
||||
|
||||
if [[ "$release_count" -eq 0 ]]; then
|
||||
echo "Nessuna release Helm trovata." >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "==> Release trovate: $release_count"
|
||||
echo "==> Directory output: $OUTPUT_DIR"
|
||||
|
||||
generated_count=0
|
||||
warning_count=0
|
||||
|
||||
while IFS= read -r release; do
|
||||
name="$(jq -r '.name' <<< "$release")"
|
||||
namespace="$(jq -r '.namespace' <<< "$release")"
|
||||
chart_ref="$(jq -r '.chart // ""' <<< "$release")"
|
||||
|
||||
metadata_yaml="$(helm get metadata "$name" -n "$namespace" -o yaml 2>/dev/null || true)"
|
||||
if [[ -z "$metadata_yaml" ]]; then
|
||||
echo "! Impossibile leggere metadata per ${namespace}/${name}, salto." >&2
|
||||
warning_count=$((warning_count + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
repo_url="$(trim "$(extract_yaml_scalar repo "$metadata_yaml")")"
|
||||
if [[ -z "$repo_url" ]]; then
|
||||
repo_url="$(trim "$(extract_yaml_scalar repository "$metadata_yaml")")"
|
||||
fi
|
||||
if [[ -z "$repo_url" ]]; then
|
||||
repo_url="$(trim "$(extract_yaml_scalar repoURL "$metadata_yaml")")"
|
||||
fi
|
||||
if [[ -z "$repo_url" ]]; then
|
||||
repo_url="$(trim "$(extract_first_source "$metadata_yaml")")"
|
||||
fi
|
||||
|
||||
chart_name="$(trim "$(extract_yaml_scalar chart "$metadata_yaml")")"
|
||||
chart_version="$(trim "$(extract_yaml_scalar version "$metadata_yaml")")"
|
||||
|
||||
if [[ -z "$chart_name" ]]; then
|
||||
chart_name="$(extract_chart_name_from_ref "$chart_ref")"
|
||||
fi
|
||||
if [[ -z "$chart_version" ]]; then
|
||||
chart_version="$(extract_chart_version_from_ref "$chart_ref")"
|
||||
fi
|
||||
|
||||
if [[ -z "$repo_url" ]]; then
|
||||
repo_url="$(trim "$(find_repo_url_from_local_cache "$chart_name" "$chart_version")")"
|
||||
fi
|
||||
|
||||
if [[ -z "$repo_url" ]]; then
|
||||
repo_url="REPO_URL_NOT_FOUND"
|
||||
echo "! Repo URL non trovato in metadata o cache locale per ${namespace}/${name}" >&2
|
||||
warning_count=$((warning_count + 1))
|
||||
fi
|
||||
|
||||
if [[ -z "$chart_name" ]]; then
|
||||
chart_name="CHART_NAME_NOT_FOUND"
|
||||
echo "! Chart name non trovato per ${namespace}/${name}" >&2
|
||||
warning_count=$((warning_count + 1))
|
||||
fi
|
||||
|
||||
values_file="$(mktemp)"
|
||||
if ! helm get values "$name" -n "$namespace" "${VALUES_ARGS[@]}" -o yaml > "$values_file" 2>/dev/null; then
|
||||
printf '{}\n' > "$values_file"
|
||||
echo "! Values non disponibili per ${namespace}/${name}, uso {}" >&2
|
||||
warning_count=$((warning_count + 1))
|
||||
fi
|
||||
|
||||
if [[ ! -s "$values_file" ]]; then
|
||||
printf '{}\n' > "$values_file"
|
||||
fi
|
||||
|
||||
values_compact="$(tr -d '[:space:]' < "$values_file")"
|
||||
|
||||
ns_dir="${OUTPUT_DIR}/${namespace}"
|
||||
mkdir -p "$ns_dir"
|
||||
|
||||
safe_name="$(safe_file_name "$name")"
|
||||
out_file="${ns_dir}/${safe_name}-helmop.yaml"
|
||||
|
||||
cat > "$out_file" <<EOF
|
||||
apiVersion: ${API_VERSION}
|
||||
kind: ${RESOURCE_KIND}
|
||||
metadata:
|
||||
name: ${safe_name}
|
||||
namespace: ${WORKSPACE_NAMESPACE}
|
||||
spec:
|
||||
namespace: ${namespace}
|
||||
helm:
|
||||
releaseName: ${name}
|
||||
repo: ${repo_url}
|
||||
chart: ${chart_name}
|
||||
EOF
|
||||
|
||||
if [[ -n "$chart_version" ]]; then
|
||||
cat >> "$out_file" <<EOF
|
||||
version: ${chart_version}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [[ "$values_compact" == "{}" ]]; then
|
||||
cat >> "$out_file" <<EOF
|
||||
values: {}
|
||||
EOF
|
||||
else
|
||||
cat >> "$out_file" <<EOF
|
||||
values:
|
||||
$(indent_file "$values_file")
|
||||
EOF
|
||||
fi
|
||||
|
||||
rm -f "$values_file"
|
||||
|
||||
echo "+ Generato ${out_file} da ${namespace}/${name}"
|
||||
generated_count=$((generated_count + 1))
|
||||
done < <(jq -c '.[]' <<< "$releases_json")
|
||||
|
||||
echo ""
|
||||
echo "=== Riepilogo ==="
|
||||
echo "File generati: $generated_count"
|
||||
echo "Warning: $warning_count"
|
||||
echo "Output: $OUTPUT_DIR"
|
||||
echo "Workspace namespace: $WORKSPACE_NAMESPACE"
|
||||
echo ""
|
||||
echo "Nota: il repo URL viene letto da 'helm get metadata' e, se assente,"
|
||||
echo " viene cercato nella cache locale di 'helm repo list/search repo'."
|
||||
echo "Se vedi REPO_URL_NOT_FOUND, completa il campo repo manualmente."
|
||||
Reference in New Issue
Block a user