-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathKubeSnapIt.psm1
301 lines (269 loc) · 13.6 KB
/
KubeSnapIt.psm1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
#!/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
}
}
}