First commit
This commit is contained in:
@@ -0,0 +1,264 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Restaura un backup completo del sistema TIP desde un archivo ZIP.
|
||||
.DESCRIPTION
|
||||
Busca el backup más reciente (tip_backup_*.zip), extrae el contenido,
|
||||
lee el manifiesto y restaura bases de datos, configuración, SSL y sesiones.
|
||||
ADVERTENCIA: Sobrescribe datos existentes. Usar solo en recuperación.
|
||||
#>
|
||||
|
||||
Write-Host "Esta seguro que desea iniciar un proceso de restauración de backup? Esto sobrescribirá datos actuales. S/N" -ForegroundColor Red
|
||||
$confirmation = Read-Host
|
||||
if ($confirmation -notmatch "^[Ss]") {
|
||||
Write-Host "Restauración cancelada por el usuario." -ForegroundColor Yellow
|
||||
exit 0
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 1. Localizar el backup más reciente
|
||||
# ------------------------------------------------------------------
|
||||
$backup_zip = Get-ChildItem -Path "." -Filter "tip_backup_*.zip" |
|
||||
Sort-Object LastWriteTime -Descending |
|
||||
Select-Object -First 1
|
||||
|
||||
if (-not $backup_zip) {
|
||||
Write-Host "ERROR: No se encontró ningún backup con el patrón 'tip_backup_*.zip' en el directorio actual." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Backup encontrado: $($backup_zip.Name)" -ForegroundColor Green
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 2. Extraer en carpeta temporal
|
||||
# ------------------------------------------------------------------
|
||||
$tempDir = "./temp_restore"
|
||||
if (Test-Path $tempDir) {
|
||||
Remove-Item -Recurse -Force $tempDir
|
||||
}
|
||||
Expand-Archive -Path $backup_zip.FullName -DestinationPath $tempDir -Force
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 3. Leer manifiesto
|
||||
# ------------------------------------------------------------------
|
||||
$jsonPath = Join-Path $tempDir "manifest.json"
|
||||
if (-not (Test-Path $jsonPath)) {
|
||||
Write-Host "ERROR: No se encontró manifest.json en el backup." -ForegroundColor Red
|
||||
Remove-Item -Recurse -Force $tempDir
|
||||
exit 1
|
||||
}
|
||||
|
||||
$jsonContent = Get-Content -Path $jsonPath -Raw | ConvertFrom-Json
|
||||
$createdAt = $jsonContent.created_at
|
||||
$createdBy = $jsonContent.created_by
|
||||
$components = $jsonContent.components
|
||||
$warnings = $jsonContent.warnings
|
||||
|
||||
Write-Host "Backup generado el $createdAt por usuario ID: $createdBy" -ForegroundColor Cyan
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 4. Obtener credenciales de bases de datos desde docker-compose.yml
|
||||
# ------------------------------------------------------------------
|
||||
# Restaurar docker-compose.yml desde el backup si existe
|
||||
$composeBackupPath = Join-Path $tempDir "config/docker-compose.yml"
|
||||
if (Test-Path $composeBackupPath) {
|
||||
Write-Host "Restaurando docker-compose.yml desde el backup..." -ForegroundColor Yellow
|
||||
Copy-Item $composeBackupPath -Destination "./docker-compose.yml" -Force
|
||||
}
|
||||
|
||||
if (-not (Test-Path "./docker-compose.yml")) {
|
||||
Write-Host "ERROR: No se encuentra docker-compose.yml en el directorio actual." -ForegroundColor Red
|
||||
Remove-Item -Recurse -Force $tempDir
|
||||
exit 1
|
||||
}
|
||||
|
||||
try {
|
||||
$composeJson = docker-compose -f docker-compose.yml config --format json | ConvertFrom-Json
|
||||
} catch {
|
||||
Write-Host "ERROR: No se pudo obtener la configuración de docker-compose. Verifica que Docker Compose esté instalado." -ForegroundColor Red
|
||||
Remove-Item -Recurse -Force $tempDir
|
||||
exit 1
|
||||
}
|
||||
|
||||
$FEEDER_PASS = $composeJson.services.database.environment.MYSQL_ROOT_PASSWORD
|
||||
$USERS_PASS = $composeJson.services.database_users.environment.MYSQL_ROOT_PASSWORD
|
||||
|
||||
if (-not $FEEDER_PASS -or -not $USERS_PASS) {
|
||||
Write-Host "ERROR: No se pudieron obtener las contraseñas de las bases de datos." -ForegroundColor Red
|
||||
Remove-Item -Recurse -Force $tempDir
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "Credenciales obtenidas correctamente." -ForegroundColor Green
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 5. Función auxiliar para buscar archivo SQL
|
||||
# ------------------------------------------------------------------
|
||||
function Get-BackupSqlFile {
|
||||
param(
|
||||
[string]$DatabaseName,
|
||||
[string]$SearchDir
|
||||
)
|
||||
$pattern = "*${DatabaseName}*.sql"
|
||||
$file = Get-ChildItem -Path $SearchDir -Filter $pattern -File -ErrorAction SilentlyContinue |
|
||||
Select-Object -First 1
|
||||
return $file
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 6. Procesar componentes del manifiesto
|
||||
# ------------------------------------------------------------------
|
||||
foreach ($comp in $components) {
|
||||
Write-Host "`nProcesando componente: $comp" -ForegroundColor Yellow
|
||||
|
||||
# --- Bases de datos ---
|
||||
if ($comp -like "database:*") {
|
||||
$dbName = $comp.Split(':')[1]
|
||||
|
||||
switch ($dbName) {
|
||||
"feeder" {
|
||||
Write-Host " → Restaurando base de datos Feeder..."
|
||||
docker compose up -d --build database --wait
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host " ERROR: No se pudo levantar el contenedor de feeder_db." -ForegroundColor Red
|
||||
continue
|
||||
}
|
||||
|
||||
$sqlFile = Get-BackupSqlFile -DatabaseName "feeder" -SearchDir (Join-Path $tempDir "databases")
|
||||
if ($sqlFile) {
|
||||
Write-Host " Archivo de dump: $($sqlFile.Name)"
|
||||
Get-Content $sqlFile.FullName | docker exec -i feeder_db mysql -uroot -p"$FEEDER_PASS" feeder
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host " Base de datos feeder restaurada exitosamente." -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " ERROR al restaurar feeder." -ForegroundColor Red
|
||||
}
|
||||
} else {
|
||||
Write-Host " ADVERTENCIA: No se encontró archivo .sql para feeder." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
"users" {
|
||||
Write-Host " → Restaurando base de datos Users..."
|
||||
docker compose up -d --build database_users --wait
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host " ERROR: No se pudo levantar el contenedor de users_db." -ForegroundColor Red
|
||||
continue
|
||||
}
|
||||
|
||||
$sqlFile = Get-BackupSqlFile -DatabaseName "users" -SearchDir (Join-Path $tempDir "databases")
|
||||
if ($sqlFile) {
|
||||
Write-Host " Archivo de dump: $($sqlFile.Name)"
|
||||
Get-Content $sqlFile.FullName | docker exec -i users_db mysql -uroot -p"$USERS_PASS" users
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host " Base de datos users restaurada exitosamente." -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " ERROR al restaurar users." -ForegroundColor Red
|
||||
}
|
||||
} else {
|
||||
Write-Host " ADVERTENCIA: No se encontró archivo .sql para users." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
default {
|
||||
Write-Host " → Base de datos desconocida: $dbName" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- Archivos de configuración ---
|
||||
elseif ($comp -like "config:*") {
|
||||
$files = ($comp.Split(':')[1]) -split ','
|
||||
Write-Host " → Archivos de configuración: $($files -join ', ')"
|
||||
foreach ($file in $files) {
|
||||
$source = Join-Path $tempDir "config/$file"
|
||||
if (Test-Path $source) {
|
||||
switch ($file) {
|
||||
"nginx.conf" { $dest = "./nginx/nginx.conf" }
|
||||
"docker-compose.yml" { $dest = "./docker-compose.yml" }
|
||||
default { $dest = "./$file" }
|
||||
}
|
||||
Write-Host " - Copiando $file a $dest"
|
||||
Copy-Item $source -Destination $dest -Force
|
||||
} else {
|
||||
Write-Host " - Archivo $file no encontrado en el backup, se omite." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- Certificados SSL ---
|
||||
elseif ($comp -eq "ssl") {
|
||||
Write-Host " → Restaurando certificados SSL..."
|
||||
$sslSource = Join-Path $tempDir "ssl"
|
||||
if (Test-Path $sslSource) {
|
||||
$sslDest = "./nginx/ssl"
|
||||
if (-not (Test-Path $sslDest)) {
|
||||
New-Item -ItemType Directory -Path $sslDest -Force | Out-Null
|
||||
}
|
||||
# Copiar contenido del directorio
|
||||
Get-ChildItem -Path $sslSource -File -Recurse | ForEach-Object {
|
||||
$relativePath = $_.FullName.Substring($sslSource.Length + 1)
|
||||
$destFile = Join-Path $sslDest $relativePath
|
||||
$destDir = Split-Path $destFile -Parent
|
||||
if (-not (Test-Path $destDir)) {
|
||||
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
|
||||
}
|
||||
Copy-Item $_.FullName -Destination $destFile -Force
|
||||
}
|
||||
Write-Host " Certificados SSL copiados a $sslDest" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " ADVERTENCIA: No se encontraron archivos SSL en el backup." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# --- Sesiones de Telegram ---
|
||||
elseif ($comp -eq "telegram_sessions") {
|
||||
Write-Host " → Restaurando sesiones de Telegram..."
|
||||
$sessionsSource = Join-Path $tempDir "telegram_sessions"
|
||||
if (Test-Path $sessionsSource) {
|
||||
$sessionsDest = "./app/telegram_sessions"
|
||||
if (-not (Test-Path $sessionsDest)) {
|
||||
New-Item -ItemType Directory -Path $sessionsDest -Force | Out-Null
|
||||
}
|
||||
Copy-Item -Path "$sessionsSource/*" -Destination $sessionsDest -Recurse -Force
|
||||
Write-Host " Sesiones copiadas a $sessionsDest" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " ADVERTENCIA: No se encontraron sesiones en el backup." -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
Write-Host " → Componente no reconocido: $comp" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 7. Mostrar advertencias del manifiesto
|
||||
# ------------------------------------------------------------------
|
||||
if ($warnings -and $warnings.Count -gt 0) {
|
||||
Write-Host "`n⚠️ Advertencias durante la generación del backup:" -ForegroundColor Magenta
|
||||
$warnings | ForEach-Object { Write-Host " - $_" }
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 8. Limpieza
|
||||
# ------------------------------------------------------------------
|
||||
Write-Host "`nEliminando archivos temporales..." -ForegroundColor Gray
|
||||
Remove-Item -Recurse -Force $tempDir
|
||||
|
||||
Write-Host "`nRestauración completada, desea reiniciar los contenedores? S/N" -ForegroundColor Green
|
||||
$answer = Read-Host
|
||||
|
||||
if ($answer -match "^[Ss]") {
|
||||
Write-Host "Reiniciando contenedores..." -ForegroundColor Green
|
||||
docker compose down
|
||||
docker compose up -d --build
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "Contenedores reiniciados exitosamente." -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "ERROR al reiniciar los contenedores. Verifica los logs de Docker." -ForegroundColor Red
|
||||
}
|
||||
} else {
|
||||
Write-Host "Recuerda reiniciar los contenedores para aplicar los cambios." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host "Proceso de restauración completado." -ForegroundColor Green
|
||||
Reference in New Issue
Block a user