KubeSnapIt.psm1
#!/usr/bin/env pwsh # MARKER: NEW PARAM BLOCK # Dot Source all functions in all ps1 files located in this module # Define the path to the local Private directory and Krew storage directory for KubeSnapIt $localPrivateDir = "$PSScriptRoot/Private" # Local Private directory $krewStorageDir = "$HOME/.krew/store/KubeSnapIt" # Krew storage directory $foundScripts = $false # Flag to track if any scripts were found and executed # Check if the local Private directory exists and source scripts if available if (Test-Path -Path $localPrivateDir) { Write-Verbose "Executing scripts from local Private directory." # Get all .ps1 files in the local Private directory $localScripts = Get-ChildItem -Path "$localPrivateDir/*.ps1" # Execute each .ps1 script found in the local Private directory foreach ($script in $localScripts) { Write-Verbose "Executing script: $($script.FullName)" . $script.FullName # Call the script $foundScripts = $true } } # If no scripts found in local directory, check Krew storage directory if (-not $foundScripts -and (Test-Path -Path $krewStorageDir)) { Write-Verbose "Local Private directory empty or missing. Checking Krew storage directory." # Get all version directories (assuming they follow a vX.X.X naming pattern) $versionDirs = Get-ChildItem -Path $krewStorageDir -Directory | Where-Object { $_.Name -match '^v\d+\.\d+\.\d+$' } # Check if any version directories were found if ($versionDirs) { # Get the latest version directory based on the version number $latestVersionDir = $versionDirs | Sort-Object { [Version]$_.Name.Substring(1) } -Descending | Select-Object -First 1 Write-Verbose "Latest version found: $($latestVersionDir.Name)" # Construct the path to the Private directory for the latest version $kubePrivateDir = Join-Path -Path $latestVersionDir.FullName -ChildPath "Private" # Check if the Private directory exists in the latest version if (Test-Path -Path $kubePrivateDir) { # Get all .ps1 files in the Private directory $scripts = Get-ChildItem -Path "$kubePrivateDir/*.ps1" # Execute each .ps1 script found foreach ($script in $scripts) { Write-Verbose "Executing script: $($script.FullName)" . $script.FullName # Call the script $foundScripts = $true } } else { Write-Verbose "No Private directory found for the latest version: $($latestVersionDir.Name)." } } else { Write-Verbose "No version directories found in $krewStorageDir." } } # If no scripts were found and sourced, throw an error if (-not $foundScripts) { Write-Error "Error: Unable to source any .ps1 files from either the local Private directory or Krew storage directory. Exiting." exit 1 } function Invoke-KubeSnapIt { # START PARAM BLOCK [CmdletBinding()] param ( [string]$Namespace = "", [string]$OutputPath = "./snapshots", [string]$InputPath = "", [string]$ComparePath = "", [switch]$ClusterResources, [switch]$AllNamespaces, [switch]$AllNonSystemNamespaces, [string]$Labels = "", [string]$Objects = "", [switch]$DryRun, [switch]$Restore, [switch]$CompareWithCluster, [switch]$CompareSnapshots, [switch]$Force, [switch]$UI, [switch]$SnapshotHelm, [switch]$SnapshotHelmUsedValues, [switch]$RestoreHelmSnapshot, [Alias("h")] [switch]$Help ) # END PARAM BLOCK # Display help message if the Help switch is used if ($Help) { Write-Host "" Write-Host "KubeSnapIt Parameters:" Write-Host " -Namespace Specify the Kubernetes namespace to take a snapshot from." Write-Host " -OutputPath Path to save the snapshot files." Write-Host " -InputPath Path to restore snapshots from or the first snapshot for comparison." Write-Host " -ComparePath Path to the second snapshot for comparison (optional)." Write-Host " -ClusterResources Capture cluster-wide resources (e.g., crd's, namespaces)." Write-Host " -AllNamespaces Capture all namespaces. If this is provided, -Namespace will be ignored." Write-Host " -AllNonSystemNamespaces Capture all non-system namespaces. If this is provided, -Namespace and -AllNamespaces will be ignored." Write-Host " -Labels Specify labels to filter Kubernetes objects (e.g., app=nginx)." Write-Host " -Objects Comma-separated list of specific objects in the kind/name format (e.g., pod/my-pod, deployment/my-deployment)." Write-Host " -DryRun Simulate taking or restoring the snapshot without saving or applying files." Write-Host " -Restore Restore snapshots from the specified directory or file." Write-Host " -CompareWithCluster Compare a snapshot with the current cluster state." Write-Host " -CompareSnapshots Compare two snapshots." Write-Host " -Force Force the action without prompting for confirmation." Write-Host " -SnapshotHelm Backup Helm releases and their values." Write-Host " -SnapshotHelmUsedValues Backup Helm release values." write-Host " -RestoreHelmSnapshot Restore Helm release from a snapshot." Write-Host " -Help Display this help message." return } if (!$UI) { Show-KubeSnapItBanner } # Check if kubectl is installed for actions that require it 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 KubeSnapIt." -ForegroundColor Red Write-Host "You can install 'kubectl' from: https://kubernetes.io/docs/tasks/tools/install-kubectl/" -ForegroundColor Yellow exit } # Get the current Kubernetes context $context = kubectl config current-context if ($context) { # Add lines and styling to make it stand out Write-Host "" Write-Host "=========================================" -ForegroundColor Cyan Write-Host "YOU ARE CONNECTED TO A KUBERNETES CLUSTER" -ForegroundColor Cyan Write-Host "=========================================" -ForegroundColor Cyan Write-Host "" Write-Host "Kubernetes Context: $context" -ForegroundColor Green # Get cluster details from current context $clusterInfo = kubectl config view -o jsonpath="{.contexts[?(@.name=='$context')].context.cluster}" Write-Host "Kubernetes Cluster: $clusterInfo" -ForegroundColor Green Write-Host "" Write-Host "=========================================" -ForegroundColor Cyan Write-Host "" } else { Write-Host "You are not connected to any Kubernetes cluster." -ForegroundColor Red Write-Host "Please configure a Kubernetes cluster to connect to." -ForegroundColor Red Write-Host "Instructions to set up a cluster can be found here: https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/" -ForegroundColor Yellow Write-Host "You can set the current context using the command: 'kubectl config use-context <context-name>'." -ForegroundColor Yellow exit } # Determine the operation type using switch switch ($true) { { $Restore } { if (-not $InputPath) { Write-Host "Error: Input path required for restore." -ForegroundColor Red return } Restore-KubeSnapshot -InputPath $InputPath -Force $Force -Verbose:$Verbose return } { $CompareWithCluster } { if (-not $InputPath) { Write-Host "Error: Snapshot path required for comparison." -ForegroundColor Red return } Compare-Files -LocalFile $InputPath -Verbose:$Verbose return } { $CompareSnapshots } { if (-not $InputPath -or -not $ComparePath) { Write-Host "Error: Both -InputPath and -ComparePath required for snapshot comparison." -ForegroundColor Red return } Compare-Files -LocalFile $InputPath -CompareFile $ComparePath -Verbose:$Verbose return } { $SnapshotHelm } { if (-not ($Namespace -or $AllNamespaces -or $AllNonSystemNamespaces)) { Write-Host "Error: -Namespace, -AllNamespaces, or -AllNonSystemNamespaces is required with -SnapshotHelm." -ForegroundColor Red return } if (-not (Test-Path -Path $OutputPath)) { New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null Write-Verbose "Output directory created: $OutputPath" } Write-Verbose "Starting Helm backup..." if ($DryRun) { Write-Host "Dry run enabled. No files will be saved." -ForegroundColor Yellow } # Helm backup function call try { Save-HelmBackup -Namespace $Namespace -AllNamespaces:$AllNamespaces -AllNonSystemNamespaces:$AllNonSystemNamespaces -OutputPath $OutputPath -DryRun:$DryRun -Verbose:$Verbose -SnapshotHelm } catch { Write-Host "Error during Helm backup: $_" -ForegroundColor Red } return } # Only Helm used values snapshot { $SnapshotHelmUsedValues } { if (-not ($Namespace -or $AllNamespaces -or $AllNonSystemNamespaces)) { Write-Host "Error: -Namespace, -AllNamespaces, or -AllNonSystemNamespaces is required with -SnapshotHelmUsedValues." -ForegroundColor Red return } if (-not (Test-Path -Path $OutputPath)) { New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null Write-Verbose "Output directory created: $OutputPath" } Write-Verbose "Starting Helm used values backup..." if ($DryRun) { Write-Host "Dry run enabled. No files will be saved." -ForegroundColor Yellow } try { Save-HelmBackup ` -Namespace $Namespace ` -AllNamespaces:$AllNamespaces ` -AllNonSystemNamespaces:$AllNonSystemNamespaces ` -OutputPath $OutputPath ` -DryRun:$DryRun ` -Verbose:$Verbose ` -SnapshotHelmUsedValues } catch { Write-Host "Error during Helm used values backup: $_" -ForegroundColor Red } return } # Only Helm used values snapshot { $SnapshotHelmUsedValues -and $SnapshotHelm } { if (-not ($Namespace -or $AllNamespaces -or $AllNonSystemNamespaces)) { Write-Host "Error: -Namespace, -AllNamespaces, or -AllNonSystemNamespaces is required with -SnapshotHelm and -SnapshotHelmUsedValues." -ForegroundColor Red return } if (-not (Test-Path -Path $OutputPath)) { New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null Write-Verbose "Output directory created: $OutputPath" } Write-Verbose "Starting Helm backup..." if ($DryRun) { Write-Host "Dry run enabled. No files will be saved." -ForegroundColor Yellow } try { Save-HelmBackup ` -Namespace $Namespace ` -AllNamespaces:$AllNamespaces ` -AllNonSystemNamespaces:$AllNonSystemNamespaces ` -OutputPath $OutputPath ` -DryRun:$DryRun ` -Verbose:$Verbose ` -SnapshotHelm ` -SnapshotHelmUsedValues } catch { Write-Host "Error during Helm backup: $_" -ForegroundColor Red } return } { $RestoreHelmSnapshot } { if (-not $InputPath) { Write-Host "Error: Input path required for restore." -ForegroundColor Red return } Restore-HelmBackup -ManifestFilePath:$InputPath -Namespace:$Namespace -DryRun:$DryRun -Verbose:$Verbose return } { $Namespace -or $ClusterResources -or $AllNonSystemNamespaces } { if (-not (Test-Path -Path $OutputPath)) { New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null Write-Verbose "Output directory created: $OutputPath" } Write-Verbose "Starting snapshot..." if ($DryRun) { Write-Host "Dry run enabled. No files will be saved." -ForegroundColor Yellow } # Snapshot function call try { Save-KubeSnapshot -Namespace $Namespace -ClusterResources:$ClusterResources -AllNonSystemNamespaces:$AllNonSystemNamespaces -Labels $Labels -Objects $Objects -OutputPath $OutputPath -DryRun:$DryRun -Verbose:$Verbose } catch { Write-Host "Error during snapshot: $_" -ForegroundColor Red } return } default { Write-Host "Error: Specify -Restore, -CompareWithCluster, -CompareSnapshots, or -SnapshotHelm, or -ClusterResources with necessary parameters." -ForegroundColor Red return } } } |