feat: show Ubuntu phased updates apart and leave them out of pending counts
apt lists phased updates as upgradable while an upgrade defers them until Ubuntu selects the host, so a freshly patched server kept reporting pending updates. The agent now flags them; the server stores the flag and leaves them out of patch run counts, and the server page shows them in their own section.
This commit is contained in:
+1
-1
@@ -47,7 +47,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
gitea.hostxtra.co.uk/vantage/vantage-shared v0.5.0
|
||||
gitea.hostxtra.co.uk/vantage/vantage-shared v0.6.0
|
||||
github.com/bytedance/sonic v1.15.3 // indirect
|
||||
github.com/bytedance/sonic/loader v0.5.2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
gitea.hostxtra.co.uk/vantage/vantage-shared v0.5.0 h1:xwSIEkQKTd4Qk+BYHvoGN+h84Isr2h5qqnitUWF1m2w=
|
||||
gitea.hostxtra.co.uk/vantage/vantage-shared v0.5.0/go.mod h1:Zo66XhqF8No3dveIowLCepvMxVg8KnhsNMz0k0Xpuck=
|
||||
gitea.hostxtra.co.uk/vantage/vantage-shared v0.6.0 h1:EtojZ1d3cN9foHpc/CAI3KzBewYGn4sKWdkWs2MV78Q=
|
||||
gitea.hostxtra.co.uk/vantage/vantage-shared v0.6.0/go.mod h1:Zo66XhqF8No3dveIowLCepvMxVg8KnhsNMz0k0Xpuck=
|
||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30xLN2sUZcMXl50hg+PJCIDdJgIvIbVcKqLJ/ZrtM=
|
||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
|
||||
github.com/aquasecurity/trivy-db v0.0.0-20260813095258-0e0340a01b57 h1:A3Lz/9ip/qigafSxqBWcu7S8i+tJbQS7DB2V0XibOKs=
|
||||
|
||||
@@ -1389,6 +1389,10 @@
|
||||
},
|
||||
"new_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"phased": {
|
||||
"description": "Phased is an Ubuntu phased update the host is not yet selected for: apt\nlists it but an upgrade defers it, so pending counts leave it out.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
|
||||
@@ -103,6 +103,7 @@ func (s *vantageServer) ReportUpdates(ctx context.Context, req *pb.ReportUpdates
|
||||
Name: u.Name,
|
||||
CurrentVersion: u.CurrentVersion,
|
||||
NewVersion: u.NewVersion,
|
||||
Phased: u.Phased,
|
||||
}
|
||||
}
|
||||
if err := services.StoreAvailableUpdates(srv.ServerID, pkgs); err != nil {
|
||||
|
||||
@@ -80,6 +80,8 @@ type pendingUpdate struct {
|
||||
Package string `json:"package"`
|
||||
CurrentVersion string `json:"current_version,omitempty"`
|
||||
NewVersion string `json:"new_version"`
|
||||
// Phased is an Ubuntu phased update apt defers until the host is selected.
|
||||
Phased bool `json:"phased,omitempty"`
|
||||
}
|
||||
|
||||
type listPendingUpdatesResult struct {
|
||||
@@ -390,7 +392,7 @@ func init() {
|
||||
}
|
||||
out = append(out, pendingUpdate{
|
||||
ServerID: srv.ServerID, Hostname: srv.Hostname,
|
||||
Package: u.Name, CurrentVersion: u.CurrentVersion, NewVersion: u.NewVersion,
|
||||
Package: u.Name, CurrentVersion: u.CurrentVersion, NewVersion: u.NewVersion, Phased: u.Phased,
|
||||
})
|
||||
}
|
||||
return listPendingUpdatesResult{Updates: out, Shown: len(out)}, nil
|
||||
@@ -411,7 +413,7 @@ func init() {
|
||||
}
|
||||
out = append(out, pendingUpdate{
|
||||
ServerID: srv.ServerID, Hostname: srv.Hostname,
|
||||
Package: u.Name, CurrentVersion: u.CurrentVersion, NewVersion: u.NewVersion,
|
||||
Package: u.Name, CurrentVersion: u.CurrentVersion, NewVersion: u.NewVersion, Phased: u.Phased,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ type PackageUpdate struct {
|
||||
Name string `bson:"name" json:"name"`
|
||||
CurrentVersion string `bson:"current_version,omitempty" json:"current_version,omitempty"`
|
||||
NewVersion string `bson:"new_version" json:"new_version"`
|
||||
// Phased is an Ubuntu phased update the host is not yet selected for: apt
|
||||
// lists it but an upgrade defers it, so pending counts leave it out.
|
||||
Phased bool `bson:"phased,omitempty" json:"phased,omitempty"`
|
||||
}
|
||||
|
||||
type CPUInfo struct {
|
||||
|
||||
@@ -83,7 +83,7 @@ func serverBootTime(ctx context.Context, instanceID, serverID string) *time.Time
|
||||
}
|
||||
|
||||
func newServerRun(s models.Server, now time.Time) models.PatchServerRun {
|
||||
r := models.PatchServerRun{ServerID: s.ServerID, Hostname: s.Hostname, Status: models.PatchSrvQueued, PendingBefore: len(s.AvailableUpdates)}
|
||||
r := models.PatchServerRun{ServerID: s.ServerID, Hostname: s.Hostname, Status: models.PatchSrvQueued, PendingBefore: InstallableUpdateCount(s.AvailableUpdates)}
|
||||
if !patchrun.AgentSupportsPatchResults(s.AgentVersion) {
|
||||
v := s.AgentVersion
|
||||
if v == "" {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package services
|
||||
|
||||
import "gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/models"
|
||||
|
||||
// InstallableUpdateCount is the number of pending updates an upgrade would
|
||||
// install now. Ubuntu phased updates are listed by apt but deferred until the
|
||||
// host's phase comes up, so they are not counted: counting them made a patch
|
||||
// run look as if it installed less than it did.
|
||||
func InstallableUpdateCount(ups []models.PackageUpdate) int {
|
||||
n := 0
|
||||
for _, u := range ups {
|
||||
if !u.Phased {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/models"
|
||||
)
|
||||
|
||||
// Phased updates are listed but not installable yet, so they never count as
|
||||
// pending: they must not lower "updates installed" on a patch run.
|
||||
func TestInstallableUpdateCount(t *testing.T) {
|
||||
ups := []models.PackageUpdate{
|
||||
{Name: "curl"},
|
||||
{Name: "netplan.io", Phased: true},
|
||||
{Name: "openssl"},
|
||||
}
|
||||
if got := InstallableUpdateCount(ups); got != 2 {
|
||||
t.Fatalf("got %d, want 2", got)
|
||||
}
|
||||
if got := InstallableUpdateCount(nil); got != 0 {
|
||||
t.Fatalf("got %d for nil, want 0", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user