hub v0.1.7: Infrastructure backup endpoints for disaster recovery
Add infra-backup push/pull API for controller DR:
- POST /api/v1/infra-backup — controller pushes infrastructure snapshot
- GET /api/v1/infra-backup/{customer_id} — fresh controller pulls backup
- infra_backups SQLite table with per-customer snapshots
- Customer detail page shows infra backup status card
- README.md with full API docs and DR flow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -191,6 +191,9 @@ func (s *Server) handleCustomerDetail(w http.ResponseWriter, r *http.Request, cu
|
||||
notifPrefs, _ := s.store.GetNotificationPrefs(customerID)
|
||||
recentNotifs, _ := s.store.GetRecentNotifications(customerID, 10)
|
||||
|
||||
// Get infra backup metadata
|
||||
infraMeta, _ := s.store.GetInfraBackupMeta(customerID)
|
||||
|
||||
type detailData struct {
|
||||
Customer *store.CustomerSummary
|
||||
Report map[string]interface{}
|
||||
@@ -198,6 +201,8 @@ func (s *Server) handleCustomerDetail(w http.ResponseWriter, r *http.Request, cu
|
||||
OverallStatus string
|
||||
NotifPrefs *store.NotificationPrefs
|
||||
RecentNotifications []store.NotificationLogEntry
|
||||
InfraBackup *store.InfraBackupMeta
|
||||
InfraBackupAge string
|
||||
}
|
||||
|
||||
overallStatus := "ok"
|
||||
@@ -211,6 +216,11 @@ func (s *Server) handleCustomerDetail(w http.ResponseWriter, r *http.Request, cu
|
||||
overallStatus = "down"
|
||||
}
|
||||
|
||||
var infraBackupAge string
|
||||
if infraMeta != nil {
|
||||
infraBackupAge = timeAgo(infraMeta.UpdatedAt)
|
||||
}
|
||||
|
||||
data := detailData{
|
||||
Customer: customer,
|
||||
Report: report,
|
||||
@@ -218,6 +228,8 @@ func (s *Server) handleCustomerDetail(w http.ResponseWriter, r *http.Request, cu
|
||||
OverallStatus: overallStatus,
|
||||
NotifPrefs: notifPrefs,
|
||||
RecentNotifications: recentNotifs,
|
||||
InfraBackup: infraMeta,
|
||||
InfraBackupAge: infraBackupAge,
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
|
||||
@@ -127,6 +127,29 @@
|
||||
{{end}}
|
||||
</section>
|
||||
|
||||
<!-- Infra Backup (Disaster Recovery) -->
|
||||
<section class="card">
|
||||
<h2>Infra Backup</h2>
|
||||
{{if .InfraBackup}}
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<span class="label">Last Updated</span>
|
||||
<span class="value">{{.InfraBackupAge}}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Deployed Stacks</span>
|
||||
<span class="value">{{.InfraBackup.StackCount}}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">Disks</span>
|
||||
<span class="value">{{.InfraBackup.DiskCount}}</span>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<p style="color: #facc15">No infra backup received yet</p>
|
||||
{{end}}
|
||||
</section>
|
||||
|
||||
<!-- Health -->
|
||||
<section class="card">
|
||||
<h2>Health</h2>
|
||||
|
||||
Reference in New Issue
Block a user