Vapora/scripts/backup/config-backup.nu
Jesús Pérez a395bd972f
Some checks failed
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
mdBook Build & Deploy / Build mdBook (push) Has been cancelled
Nickel Type Check / Nickel Type Checking (push) Has been cancelled
mdBook Build & Deploy / Documentation Quality Check (push) Has been cancelled
mdBook Build & Deploy / Deploy to GitHub Pages (push) Has been cancelled
mdBook Build & Deploy / Notification (push) Has been cancelled
chore: add cd/ci ops
2026-01-12 03:36:55 +00:00

336 lines
8.5 KiB
Plaintext

#!/usr/bin/env nu
# VAPORA Configuration Backup Script
# Backs up Kubernetes ConfigMaps, Secrets, and deployment configs
# Follows NUSHELL_GUIDELINES.md - 17 rules
# Get current timestamp
def get-timestamp []: string {
date now | format date "%Y%m%d-%H%M%S"
}
# Get Kubernetes namespace from environment or use default
def get-namespace []: string {
if ("VAPORA_NAMESPACE" in $env) {
$env.VAPORA_NAMESPACE
} else {
"vapora"
}
}
# Backup ConfigMaps
def backup-configmaps [
output_dir: string
namespace: string
]: record {
print $"Backing up ConfigMaps from namespace [$namespace]..."
let output_file = $"($output_dir)/configmaps-$(get-timestamp).yaml"
let result = do {
^kubectl get configmaps \
-n $namespace \
-o yaml \
> $output_file \
2>&1
} | complete
if ($result.exit_code == 0) {
{
success: true,
file: $output_file,
count: (
do {
^kubectl get configmaps -n $namespace --no-headers 2>/dev/null
} | complete | if ($in.exit_code == 0) {
($in.stdout | lines | length)
} else {
0
}
),
error: null
}
} else {
{
success: false,
file: $output_file,
count: 0,
error: ($result.stderr | str trim)
}
}
}
# Backup Secrets
def backup-secrets [
output_dir: string
namespace: string
]: record {
print $"Backing up Secrets from namespace [$namespace]..."
let output_file = $"($output_dir)/secrets-$(get-timestamp).yaml"
let result = do {
^kubectl get secrets \
-n $namespace \
-o yaml \
> $output_file \
2>&1
} | complete
if ($result.exit_code == 0) {
{
success: true,
file: $output_file,
count: (
do {
^kubectl get secrets -n $namespace --no-headers 2>/dev/null
} | complete | if ($in.exit_code == 0) {
($in.stdout | lines | length)
} else {
0
}
),
error: null
}
} else {
{
success: false,
file: $output_file,
count: 0,
error: ($result.stderr | str trim)
}
}
}
# Backup Deployment manifests
def backup-deployments [
output_dir: string
namespace: string
]: record {
print $"Backing up Deployments from namespace [$namespace]..."
let output_file = $"($output_dir)/deployments-$(get-timestamp).yaml"
let result = do {
^kubectl get deployments,statefulsets,daemonsets \
-n $namespace \
-o yaml \
> $output_file \
2>&1
} | complete
if ($result.exit_code == 0) {
{
success: true,
file: $output_file,
resource_types: ["deployments", "statefulsets", "daemonsets"],
error: null
}
} else {
{
success: false,
file: $output_file,
resource_types: [],
error: ($result.stderr | str trim)
}
}
}
# Backup Services and Ingress
def backup-networking [
output_dir: string
namespace: string
]: record {
print $"Backing up Services and Ingress from namespace [$namespace]..."
let output_file = $"($output_dir)/networking-$(get-timestamp).yaml"
let result = do {
^kubectl get services,ingresses \
-n $namespace \
-o yaml \
> $output_file \
2>&1
} | complete
if ($result.exit_code == 0) {
{
success: true,
file: $output_file,
resource_types: ["services", "ingresses"],
error: null
}
} else {
{
success: false,
file: $output_file,
resource_types: [],
error: ($result.stderr | str trim)
}
}
}
# Compress all backup files
def compress-backups [output_dir: string]: record {
print $"Compressing backup files..."
let archive_name = $"configs-$(get-timestamp).tar.gz"
let result = do {
^tar -czf $archive_name -C $output_dir . 2>&1
} | complete
if ($result.exit_code == 0) {
{
success: true,
archive: $archive_name,
size: (
do {
^ls -lh $archive_name 2>/dev/null
} | complete | if ($in.exit_code == 0) {
($in.stdout | str trim)
} else {
"unknown"
}
),
error: null
}
} else {
{
success: false,
archive: $archive_name,
size: null,
error: ($result.stderr | str trim)
}
}
}
# Upload to S3
def upload-to-s3 [
file_path: string
s3_bucket: string
s3_prefix: string
]: record {
print $"Uploading to S3 [$s3_bucket]..."
let s3_key = $"($s3_prefix)/configs-$(get-timestamp).tar.gz"
let result = do {
^aws s3 cp $file_path \
$"s3://($s3_bucket)/($s3_key)" \
--sse AES256 \
--metadata "backup-type=config,timestamp=$(get-timestamp)"
} | complete
if ($result.exit_code == 0) {
{
success: true,
s3_location: $"s3://($s3_bucket)/($s3_key)",
error: null
}
} else {
{
success: false,
s3_location: $"s3://($s3_bucket)/($s3_key)",
error: ($result.stderr | str trim)
}
}
}
# Main backup function
def main [
--namespace: string = ""
--s3-bucket: string = ""
--s3-prefix: string = "backups/config"
--work-dir: string = "/tmp/vapora-config-backups"
--keep-local: bool = false
]: void {
print "=== VAPORA Configuration Backup ==="
print ""
# Get namespace
let ns = if ($namespace == "") {
get-namespace
} else {
$namespace
}
# Validate environment
if ($s3_bucket == "") {
print "ERROR: --s3-bucket is required"
exit 1
}
# Create working directory
let work_path = $"($work_dir)/$(get-timestamp)"
let result_create = do {
^mkdir -p $work_path 2>&1
} | complete
if ($result_create.exit_code != 0) {
print "ERROR: Failed to create working directory"
exit 1
}
# Backup all configuration types
let configmaps_result = (backup-configmaps $work_path $ns)
if (not $configmaps_result.success) {
print $"WARNING: ConfigMap backup failed: ($configmaps_result.error)"
} else {
print $"✓ Backed up ($configmaps_result.count) ConfigMaps"
}
let secrets_result = (backup-secrets $work_path $ns)
if (not $secrets_result.success) {
print $"WARNING: Secret backup failed: ($secrets_result.error)"
} else {
print $"✓ Backed up ($secrets_result.count) Secrets"
}
let deployments_result = (backup-deployments $work_path $ns)
if (not $deployments_result.success) {
print $"WARNING: Deployment backup failed: ($deployments_result.error)"
} else {
print $"✓ Backed up deployments"
}
let networking_result = (backup-networking $work_path $ns)
if (not $networking_result.success) {
print $"WARNING: Networking backup failed: ($networking_result.error)"
} else {
print $"✓ Backed up networking resources"
}
# Compress backups
let compress_result = (compress-backups $work_path)
if (not $compress_result.success) {
print $"ERROR: Compression failed: ($compress_result.error)"
exit 1
}
print "✓ Backups compressed successfully"
# Upload to S3
let upload_result = (upload-to-s3 $compress_result.archive $s3_bucket $s3_prefix)
if (not $upload_result.success) {
print $"ERROR: S3 upload failed: ($upload_result.error)"
exit 1
}
print "✓ Configuration backup uploaded to S3"
# Cleanup unless requested to keep
if (not $keep_local) {
let cleanup = do {
^rm -rf $work_dir 2>&1
} | complete
if ($cleanup.exit_code == 0) {
print "✓ Temporary files cleaned up"
}
} else {
print $"Local backup kept at: ($work_dir)"
}
# Summary
print ""
print "=== Backup Complete ==="
print $"Location: ($upload_result.s3_location)"
print $"Namespace: ($ns)"
print $"Timestamp: $(get-timestamp)"
}