Private/Save-HelmBackup.ps1
function Save-HelmBackup { param ( [string]$Namespace, [string]$OutputPath, [switch]$DryRun, [switch]$Verbose, [switch]$AllNamespaces, [switch]$AllNonSystemNamespaces ) # Set the verbose preference based on the switch if ($Verbose) { $VerbosePreference = "Continue" } # Check if Helm is installed if (!(Get-Command "helm" -ErrorAction SilentlyContinue)) { Write-Host "'helm' is not installed or not found in your system's PATH." -ForegroundColor Red Write-Host "Please install 'helm' before running Save-HelmBackup." -ForegroundColor Red Write-Host "You can install 'helm' from: https://helm.sh/docs/intro/install/" -ForegroundColor Yellow return } # Check if kubectl is installed if (!(Get-Command "kubectl" -ErrorAction SilentlyContinue)) { Write-Host "'kubectl' is not installed or not found in your system's PATH." -ForegroundColor Red Write-Host "Please install 'kubectl' before running Save-HelmBackup." -ForegroundColor Red Write-Host "You can install 'kubectl' from: https://kubernetes.io/docs/tasks/tools/install-kubectl/" -ForegroundColor Yellow return } # Function to run helm command and return output function Invoke-HelmCommand { param ( [string]$command # helm command without the 'helm' part ) $processInfo = New-Object System.Diagnostics.ProcessStartInfo $processInfo.FileName = "helm" $processInfo.Arguments = $command $processInfo.RedirectStandardOutput = $true $processInfo.RedirectStandardError = $true $processInfo.UseShellExecute = $false $processInfo.CreateNoWindow = $true $process = New-Object System.Diagnostics.Process $process.StartInfo = $processInfo # Start the helm process $process.Start() | Out-Null # Capture output and error $output = $process.StandardOutput.ReadToEnd() $stderr = $process.StandardError.ReadToEnd() $process.WaitForExit() if ($stderr) { Write-Host "Error running helm command: $stderr" -ForegroundColor Red } return $output } # Function to process a namespace function Process-Namespace { param ( [string]$Namespace ) $namespaceOption = "" if ($Namespace) { $namespaceOption = "-n $Namespace" } $helmListCmd = "list $namespaceOption --output json" Write-Verbose "Running command: helm $helmListCmd" $releasesOutput = Invoke-HelmCommand $helmListCmd if ($releasesOutput) { $releases = $releasesOutput | ConvertFrom-Json if ($releases.Count -eq 0) { Write-Host "No Helm releases found in the namespace '$Namespace'." -ForegroundColor Yellow return } foreach ($release in $releases) { $releaseName = $release.name $releaseNamespace = $release.namespace $timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss" if ($DryRun) { Write-Host "Dry run: Found Helm release '$releaseName' in namespace '$releaseNamespace'." } else { # Fetch values for each release $helmGetValuesCmd = "get values $releaseName $namespaceOption -o yaml" Write-Verbose "Running command: helm $helmGetValuesCmd" $valuesOutput = Invoke-HelmCommand $helmGetValuesCmd if ($valuesOutput) { # Sanitize the release name by replacing invalid characters with underscores $safeReleaseName = $releaseName -replace "[:\\/]", "_" # Generate a filename based on the release name and timestamp $valuesFile = Join-Path -Path $OutputPath -ChildPath "${safeReleaseName}_values_$timestamp.yaml" Write-Verbose "Saving Helm release '$releaseName' values to: $valuesFile" $valuesOutput | Out-File -FilePath $valuesFile -Force Write-Host "Helm release '$releaseName' values saved: $valuesFile" -ForegroundColor Green } # Fetch manifest for each release $helmGetManifestCmd = "get manifest $releaseName $namespaceOption" Write-Verbose "Running command: helm $helmGetManifestCmd" $manifestOutput = Invoke-HelmCommand $helmGetManifestCmd if ($manifestOutput) { # Generate a filename based on the release name and timestamp $manifestFile = Join-Path -Path $OutputPath -ChildPath "${safeReleaseName}_manifest_$timestamp.yaml" Write-Verbose "Saving Helm release '$releaseName' manifest to: $manifestFile" $manifestOutput | Out-File -FilePath $manifestFile -Force Write-Host "Helm release '$releaseName' manifest saved: $manifestFile" -ForegroundColor Green } # Fetch release history for each release $helmHistoryCmd = "history $releaseName $namespaceOption --output yaml" Write-Verbose "Running command: helm $helmHistoryCmd" $historyOutput = Invoke-HelmCommand $helmHistoryCmd if ($historyOutput) { # Generate a filename based on the release name and timestamp $historyFile = Join-Path -Path $OutputPath -ChildPath "${safeReleaseName}_history_$timestamp.yaml" Write-Verbose "Saving Helm release '$releaseName' history to: $historyFile" $historyOutput | Out-File -FilePath $historyFile -Force Write-Host "Helm release '$releaseName' history saved: $historyFile" -ForegroundColor Green } } } } else { Write-Host "No Helm releases found in the namespace '$Namespace'." -ForegroundColor Yellow } } try { # Determine the namespace option if ($AllNamespaces) { # Get all namespaces $namespaces = kubectl get namespaces -o json | ConvertFrom-Json $allClusterNamespaces = $namespaces.items | ForEach-Object { $_.metadata.name } } elseif ($AllNonSystemNamespaces) { # Get all non-system namespaces $namespaces = kubectl get namespaces -o json | ConvertFrom-Json $allClusterNamespaces = $namespaces.items | Where-Object { $_.metadata.name -notmatch "^(kube-system|kube-public|kube-node-lease|default)$" } | ForEach-Object { $_.metadata.name } } elseif ($Namespace) { $allClusterNamespaces = @($Namespace) } else { Write-Host "No namespace specified." -ForegroundColor Red return } # Process each namespace $allClusterNamespaces | ForEach-Object { Write-Host "Processing namespace: $_" Process-Namespace -Namespace $_ } } catch { Write-Host "Error occurred while backing up Helm releases: $_" -ForegroundColor Red } } |