mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15: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
|
# Combine installation steps for Nginx and Go to avoid repetitive update/cleanup commands
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
|
|
|
@ -2,6 +2,7 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -54,7 +55,7 @@ func removeAllTempContainers(ctx context.Context, cli *client.Client) (err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpgradeStepOne Trigger in the OTA upgrade
|
// UpgradeStepOne Trigger in the OTA upgrade
|
||||||
func UpgradeStepOne(channel string) (err error) {
|
func UpgradeStepOne(channel string, progressChan chan<- float64) (err error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// 1. Get the tag of the latest release
|
// 1. Get the tag of the latest release
|
||||||
|
@ -78,8 +79,57 @@ func UpgradeStepOne(channel string) (err error) {
|
||||||
}
|
}
|
||||||
defer out.Close()
|
defer out.Close()
|
||||||
|
|
||||||
// Wait for pull to complete by reading the output
|
// Parse JSON stream and send progress updates through channel
|
||||||
io.Copy(os.Stdout, out)
|
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
|
// 3. Create a temp container
|
||||||
// Clean up any existing temp containers
|
// Clean up any existing temp containers
|
||||||
|
|
|
@ -13,6 +13,7 @@ type Control struct {
|
||||||
Channel string `json:"channel"`
|
Channel string `json:"channel"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BinaryUpgrade Upgrade the binary
|
||||||
func BinaryUpgrade(ws *websocket.Conn, control *Control) {
|
func BinaryUpgrade(ws *websocket.Conn, control *Control) {
|
||||||
_ = ws.WriteJSON(CoreUpgradeResp{
|
_ = ws.WriteJSON(CoreUpgradeResp{
|
||||||
Status: UpgradeStatusInfo,
|
Status: UpgradeStatusInfo,
|
||||||
|
|
|
@ -6,14 +6,42 @@ import (
|
||||||
"github.com/uozi-tech/cosy/logger"
|
"github.com/uozi-tech/cosy/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DockerUpgrade Upgrade the Docker container
|
||||||
func DockerUpgrade(ws *websocket.Conn, control *Control) {
|
func DockerUpgrade(ws *websocket.Conn, control *Control) {
|
||||||
err := docker.UpgradeStepOne(control.Channel)
|
progressChan := make(chan float64)
|
||||||
if err != nil {
|
|
||||||
_ = ws.WriteJSON(CoreUpgradeResp{
|
// Start a goroutine to listen for progress updates and send them via WebSocket
|
||||||
Status: UpgradeStatusError,
|
go func() {
|
||||||
Message: err.Error(),
|
for progress := range progressChan {
|
||||||
})
|
err := ws.WriteJSON(CoreUpgradeResp{
|
||||||
logger.Error(err)
|
Status: UpgradeStatusProgress,
|
||||||
return
|
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