mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-10 18:05:48 +02:00
feat(ota): enhance Docker upgrade process with progress tracking
This commit is contained in:
parent
d0cf93d5e3
commit
ff7f2e4f73
4 changed files with 91 additions and 12 deletions
|
@ -1,4 +1,4 @@
|
|||
FROM mcr.microsoft.com/devcontainers/base:jammy
|
||||
FROM mcr.microsoft.com/devcontainers/base:noble
|
||||
|
||||
# Combine installation steps for Nginx and Go to avoid repetitive update/cleanup commands
|
||||
RUN apt-get update && \
|
||||
|
|
|
@ -2,6 +2,7 @@ package docker
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -54,7 +55,7 @@ func removeAllTempContainers(ctx context.Context, cli *client.Client) (err error
|
|||
}
|
||||
|
||||
// UpgradeStepOne Trigger in the OTA upgrade
|
||||
func UpgradeStepOne(channel string) (err error) {
|
||||
func UpgradeStepOne(channel string, progressChan chan<- float64) (err error) {
|
||||
ctx := context.Background()
|
||||
|
||||
// 1. Get the tag of the latest release
|
||||
|
@ -78,8 +79,57 @@ func UpgradeStepOne(channel string) (err error) {
|
|||
}
|
||||
defer out.Close()
|
||||
|
||||
// Wait for pull to complete by reading the output
|
||||
io.Copy(os.Stdout, out)
|
||||
// Parse JSON stream and send progress updates through channel
|
||||
decoder := json.NewDecoder(out)
|
||||
type ProgressDetail struct {
|
||||
Current int64 `json:"current"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
type PullStatus struct {
|
||||
Status string `json:"status"`
|
||||
ProgressDetail ProgressDetail `json:"progressDetail"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
layers := make(map[string]float64)
|
||||
var status PullStatus
|
||||
var lastProgress float64
|
||||
|
||||
for {
|
||||
if err := decoder.Decode(&status); err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
logger.Error("Error decoding Docker pull status:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Only process layers with progress information
|
||||
if status.ProgressDetail.Total > 0 {
|
||||
progress := float64(status.ProgressDetail.Current) / float64(status.ProgressDetail.Total) * 100
|
||||
layers[status.ID] = progress
|
||||
|
||||
// Calculate overall progress (average of all layers)
|
||||
var totalProgress float64
|
||||
for _, p := range layers {
|
||||
totalProgress += p
|
||||
}
|
||||
overallProgress := totalProgress / float64(len(layers))
|
||||
|
||||
// Only send progress updates when there's a meaningful change
|
||||
if overallProgress > lastProgress+1 || overallProgress >= 100 {
|
||||
if progressChan != nil {
|
||||
progressChan <- overallProgress
|
||||
}
|
||||
lastProgress = overallProgress
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure we send 100% at the end
|
||||
if progressChan != nil && lastProgress < 100 {
|
||||
progressChan <- 100
|
||||
}
|
||||
|
||||
// 3. Create a temp container
|
||||
// Clean up any existing temp containers
|
||||
|
|
|
@ -13,6 +13,7 @@ type Control struct {
|
|||
Channel string `json:"channel"`
|
||||
}
|
||||
|
||||
// BinaryUpgrade Upgrade the binary
|
||||
func BinaryUpgrade(ws *websocket.Conn, control *Control) {
|
||||
_ = ws.WriteJSON(CoreUpgradeResp{
|
||||
Status: UpgradeStatusInfo,
|
||||
|
|
|
@ -6,14 +6,42 @@ import (
|
|||
"github.com/uozi-tech/cosy/logger"
|
||||
)
|
||||
|
||||
// DockerUpgrade Upgrade the Docker container
|
||||
func DockerUpgrade(ws *websocket.Conn, control *Control) {
|
||||
err := docker.UpgradeStepOne(control.Channel)
|
||||
if err != nil {
|
||||
_ = ws.WriteJSON(CoreUpgradeResp{
|
||||
Status: UpgradeStatusError,
|
||||
Message: err.Error(),
|
||||
})
|
||||
logger.Error(err)
|
||||
return
|
||||
progressChan := make(chan float64)
|
||||
|
||||
// Start a goroutine to listen for progress updates and send them via WebSocket
|
||||
go func() {
|
||||
for progress := range progressChan {
|
||||
err := ws.WriteJSON(CoreUpgradeResp{
|
||||
Status: UpgradeStatusProgress,
|
||||
Progress: progress,
|
||||
Message: "Pulling Docker image...",
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("Failed to send progress update:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer close(progressChan)
|
||||
|
||||
if !control.DryRun {
|
||||
err := docker.UpgradeStepOne(control.Channel, progressChan)
|
||||
if err != nil {
|
||||
_ = ws.WriteJSON(CoreUpgradeResp{
|
||||
Status: UpgradeStatusError,
|
||||
Message: err.Error(),
|
||||
})
|
||||
logger.Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Send completion message
|
||||
_ = ws.WriteJSON(CoreUpgradeResp{
|
||||
Status: UpgradeStatusInfo,
|
||||
Progress: 100,
|
||||
Message: "Docker image pull completed, upgrading...",
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue