From a28288e6386bd310b25c14bb98277b6ffd5913aa Mon Sep 17 00:00:00 2001 From: Tulip Blossom Date: Wed, 4 Dec 2024 23:19:53 -0300 Subject: [PATCH 1/5] refactor: move system updater-related logic to unified driver --- cmd/imageOutdated.go | 14 ++-- cmd/updateCheck.go | 19 ++++-- drv/bootc.go | 157 ------------------------------------------- drv/system.go | 151 ++++++++++++++++++++++++++++++++++++++--- 4 files changed, 159 insertions(+), 182 deletions(-) delete mode 100644 drv/bootc.go diff --git a/cmd/imageOutdated.go b/cmd/imageOutdated.go index 948ce49..2e3e9bb 100644 --- a/cmd/imageOutdated.go +++ b/cmd/imageOutdated.go @@ -1,20 +1,18 @@ package cmd import ( - "log" + "log/slog" "github.com/spf13/cobra" "github.com/ublue-os/uupd/drv" ) func ImageOutdated(cmd *cobra.Command, args []string) { - systemDriver, err := drv.GetSystemUpdateDriver() + systemUpdater, err := drv.SystemUpdater{}.New(drv.UpdaterInitConfiguration{}) if err != nil { - log.Fatalf("Failed to get system update driver: %v", err) + slog.Error("Failed getting system driver", slog.Any("error", err)) + return } - outdated, err := systemDriver.ImageOutdated() - if err != nil { - log.Fatalf("Cannot determine if image is outdated: %v", err) - } - log.Printf("%t", outdated) + + println(systemUpdater.Outdated) } diff --git a/cmd/updateCheck.go b/cmd/updateCheck.go index 8b08307..377d295 100644 --- a/cmd/updateCheck.go +++ b/cmd/updateCheck.go @@ -1,19 +1,26 @@ package cmd import ( + "log/slog" + "github.com/spf13/cobra" "github.com/ublue-os/uupd/drv" - "log" ) func UpdateCheck(cmd *cobra.Command, args []string) { - systemDriver, err := drv.GetSystemUpdateDriver() + systemUpdater, err := drv.SystemUpdater{}.New(drv.UpdaterInitConfiguration{}) if err != nil { - log.Fatalf("Failed to get system update driver: %v", err) + slog.Error("Failed getting system driver", slog.Any("error", err)) + return } - update, err := systemDriver.UpdateAvailable() + updateAvailable, err := systemUpdater.Check() if err != nil { - log.Fatalf("Failed to check for updates: %v", err) + slog.Error("Failed checking for updates", slog.Any("error", err)) + return + } + if updateAvailable { + slog.Info("Update Available") + } else { + slog.Info("No updates available") } - log.Printf("Update Available: %v", update) } diff --git a/drv/bootc.go b/drv/bootc.go deleted file mode 100644 index 8c5a820..0000000 --- a/drv/bootc.go +++ /dev/null @@ -1,157 +0,0 @@ -package drv - -import ( - "encoding/json" - "os/exec" - "strings" - "time" -) - -// implementation of bootc and rpm-ostree commands (rpm-ostree support will be removed in the future) - -type bootcStatus struct { - Status struct { - Booted struct { - Incompatible bool `json:"incompatible"` - Image struct { - Timestamp string `json:"timestamp"` - } `json:"image"` - } `json:"booted"` - Staged struct { - Incompatible bool `json:"incompatible"` - Image struct { - Timestamp string `json:"timestamp"` - } `json:"image"` - } - } `json:"status"` -} - -type rpmOstreeStatus struct { - Deployments []struct { - Timestamp int64 `json:"timestamp"` - } `json:"deployments"` -} - -func BootcCompat() (bool, error) { - cmd := exec.Command("bootc", "status", "--format=json") - out, err := cmd.CombinedOutput() - if err != nil { - return false, nil - } - var status bootcStatus - err = json.Unmarshal(out, &status) - if err != nil { - return false, nil - } - return !(status.Status.Booted.Incompatible || status.Status.Staged.Incompatible), nil -} - -func IsBootcImageOutdated() (bool, error) { - cmd := exec.Command("bootc", "status", "--format=json") - out, err := cmd.CombinedOutput() - if err != nil { - return false, err - } - var status bootcStatus - err = json.Unmarshal(out, &status) - if err != nil { - return false, err - } - timestamp, err := time.Parse(time.RFC3339Nano, status.Status.Booted.Image.Timestamp) - if err != nil { - return false, nil - } - oneMonthAgo := time.Now().UTC().AddDate(0, -1, 0) - - return timestamp.Before(oneMonthAgo), nil -} - -func BootcUpdate() ([]byte, error) { - cmd := exec.Command("/usr/bin/bootc", "upgrade") - out, err := cmd.CombinedOutput() - if err != nil { - return out, err - } - return out, nil -} - -func CheckForBootcImageUpdate() (bool, error) { - cmd := exec.Command("/usr/bin/bootc", "upgrade", "--check") - out, err := cmd.CombinedOutput() - if err != nil { - return true, err - } - return !strings.Contains(string(out), "No changes in:"), nil -} - -func IsRpmOstreeImageOutdated() (bool, error) { - cmd := exec.Command("rpm-ostree", "status", "--json", "--booted") - out, err := cmd.CombinedOutput() - if err != nil { - return false, err - } - var status rpmOstreeStatus - err = json.Unmarshal(out, &status) - if err != nil { - return false, err - } - timestamp := time.Unix(status.Deployments[0].Timestamp, 0).UTC() - oneMonthAgo := time.Now().AddDate(0, -1, 0) - - return timestamp.Before(oneMonthAgo), nil -} - -func RpmOstreeUpdate() ([]byte, error) { - cmd := exec.Command("/usr/bin/rpm-ostree", "upgrade") - out, err := cmd.CombinedOutput() - if err != nil { - return out, err - } - return out, nil -} - -func CheckForRpmOstreeImageUpdate() (bool, error) { - // This function may or may not be accurate, rpm-ostree updgrade --check has issues... https://github.com/coreos/rpm-ostree/issues/1579 - // Not worried because we will end up removing rpm-ostree from the equation soon - cmd := exec.Command("/usr/bin/rpm-ostree", "upgrade", "--check") - out, err := cmd.CombinedOutput() - if err != nil { - return true, err - } - return strings.Contains(string(out), "AvailableUpdate"), nil -} - -// Generalize bootc and rpm-ostree drivers into this struct as system updaters -type SystemUpdateDriver struct { - ImageOutdated func() (bool, error) - Update func() ([]byte, error) - UpdateAvailable func() (bool, error) - Name string -} - -func GetSystemUpdateDriver() (SystemUpdateDriver, error) { - useBootc, err := BootcCompat() - if err != nil { - // bootc isn't on the current system if there's an error - return SystemUpdateDriver{ - IsRpmOstreeImageOutdated, - RpmOstreeUpdate, - CheckForRpmOstreeImageUpdate, - "rpm-ostree", - }, nil - } - if useBootc { - return SystemUpdateDriver{ - IsBootcImageOutdated, - BootcUpdate, - CheckForBootcImageUpdate, - "Bootc", - }, nil - } - return SystemUpdateDriver{ - IsRpmOstreeImageOutdated, - RpmOstreeUpdate, - CheckForRpmOstreeImageUpdate, - "rpm-ostree", - }, nil -} diff --git a/drv/system.go b/drv/system.go index d5883b7..864f12d 100644 --- a/drv/system.go +++ b/drv/system.go @@ -1,12 +1,127 @@ package drv +import ( + "encoding/json" + "os/exec" + "strings" + "time" +) + +type bootcStatus struct { + Status struct { + Booted struct { + Incompatible bool `json:"incompatible"` + Image struct { + Timestamp string `json:"timestamp"` + } `json:"image"` + } `json:"booted"` + Staged struct { + Incompatible bool `json:"incompatible"` + Image struct { + Timestamp string `json:"timestamp"` + } `json:"image"` + } + } `json:"status"` +} + +// TODO: Temporary: WILL get removed at some point. +type rpmOstreeStatus struct { + Deployments []struct { + Timestamp int64 `json:"timestamp"` + } `json:"deployments"` +} + type SystemUpdater struct { Config DriverConfiguration - SystemDriver SystemUpdateDriver + SystemDriver SystemDriver Outdated bool UpdateAvailable bool } +type SystemDriver int + +const ( + Bootc SystemDriver = iota + RpmOstree +) + +func (dr SystemDriver) Outdated() (bool, error) { + oneMonthAgo := time.Now().AddDate(0, -1, 0) + var timestamp time.Time + switch dr { + case Bootc: + cmd := exec.Command("bootc", "status", "--format=json") + out, err := cmd.CombinedOutput() + if err != nil { + return false, err + } + var status bootcStatus + err = json.Unmarshal(out, &status) + if err != nil { + return false, err + } + timestamp, err = time.Parse(time.RFC3339Nano, status.Status.Booted.Image.Timestamp) + if err != nil { + return false, nil + } + case RpmOstree: + cmd := exec.Command("rpm-ostree", "status", "--json", "--booted") + out, err := cmd.CombinedOutput() + if err != nil { + return false, err + } + var status rpmOstreeStatus + err = json.Unmarshal(out, &status) + if err != nil { + return false, err + } + timestamp = time.Unix(status.Deployments[0].Timestamp, 0).UTC() + } + + return timestamp.Before(oneMonthAgo), nil +} + +func (dr SystemDriver) Update() (*[]CommandOutput, error) { + var finalOutput = []CommandOutput{} + var cmd *exec.Cmd = nil + switch dr { + case Bootc: + cmd = exec.Command("/usr/bin/bootc", "upgrade") + case RpmOstree: + cmd = exec.Command("/usr/bin/rpm-ostree", "upgrade") + } + out, err := cmd.CombinedOutput() + tmpout := CommandOutput{}.New(out, err) + if err != nil { + tmpout.SetFailureContext("System update") + } + finalOutput = append(finalOutput, *tmpout) + return &finalOutput, err +} + +func (dr SystemDriver) UpdateAvailable() (bool, error) { + switch dr { + case Bootc: + cmd := exec.Command("/usr/bin/bootc", "upgrade", "--check") + out, err := cmd.CombinedOutput() + if err != nil { + return true, err + } + return !strings.Contains(string(out), "No changes in:"), nil + case RpmOstree: + // This function may or may not be accurate, rpm-ostree updgrade --check has issues... https://github.com/coreos/rpm-ostree/issues/1579 + // Not worried because we will end up removing rpm-ostree from the equation soon + cmd := exec.Command("/usr/bin/rpm-ostree", "upgrade", "--check") + out, err := cmd.CombinedOutput() + if err != nil { + return true, err + } + return strings.Contains(string(out), "AvailableUpdate"), nil + } + + return false, nil +} + func (up SystemUpdater) Steps() int { if up.Config.Enabled { return 1 @@ -14,6 +129,20 @@ func (up SystemUpdater) Steps() int { return 0 } +func BootcCompatible() (bool, error) { + cmd := exec.Command("bootc", "status", "--format=json") + out, err := cmd.CombinedOutput() + if err != nil { + return false, nil + } + var status bootcStatus + err = json.Unmarshal(out, &status) + if err != nil { + return false, nil + } + return !(status.Status.Booted.Incompatible || status.Status.Staged.Incompatible), nil +} + func (up SystemUpdater) New(initconfig UpdaterInitConfiguration) (SystemUpdater, error) { up.Config = DriverConfiguration{ Title: "System", @@ -27,18 +156,22 @@ func (up SystemUpdater) New(initconfig UpdaterInitConfiguration) (SystemUpdater, return up, nil } - systemDriver, err := GetSystemUpdateDriver() + isBootc, err := BootcCompatible() if err != nil { return up, err } - up.SystemDriver = systemDriver + if isBootc { + up.SystemDriver = Bootc + } else { + up.SystemDriver = RpmOstree + } - outdated, err := up.SystemDriver.ImageOutdated() + outdated, err := up.SystemDriver.Outdated() if err != nil { return up, err } - up.Outdated = outdated + return up, nil } @@ -58,11 +191,7 @@ func (up SystemUpdater) Update() (*[]CommandOutput, error) { } out, err := up.SystemDriver.Update() - tmpout := CommandOutput{}.New(out, err) - if err != nil { - tmpout.SetFailureContext("System update") - } - final_output = append(final_output, *tmpout) + final_output = append(final_output, *out...) - return &final_output, nil + return &final_output, err } From 6ebb0ac53079fa1232289facc2c1ea353dd7f380 Mon Sep 17 00:00:00 2001 From: Tulip Blossom Date: Wed, 11 Dec 2024 18:24:54 -0300 Subject: [PATCH 2/5] refactor: separate rpm-ostree and bootc drivers w/ new format --- cmd/update.go | 75 ++++++++++++++++------ drv/rpm-ostree.go | 121 +++++++++++++++++++++++++++++++++++ drv/system.go | 156 +++++++++++----------------------------------- 3 files changed, 215 insertions(+), 137 deletions(-) create mode 100644 drv/rpm-ostree.go diff --git a/cmd/update.go b/cmd/update.go index 6de9a19..30123cd 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -62,20 +62,6 @@ func Update(cmd *cobra.Command, args []string) { initConfiguration.DryRun = dryRun initConfiguration.Verbose = verboseRun - systemUpdater, err := drv.SystemUpdater{}.New(*initConfiguration) - if err != nil { - systemUpdater.Config.Enabled = false - } else { - enableUpd, err := systemUpdater.Check() - if err != nil { - slog.Error("Failed checking for updates") - } - systemUpdater.Config.Enabled = enableUpd - if !enableUpd { - slog.Debug("No system update found, disabiling module") - } - } - brewUpdater, err := drv.BrewUpdater{}.New(*initConfiguration) brewUpdater.Config.Enabled = err == nil @@ -87,7 +73,45 @@ func Update(cmd *cobra.Command, args []string) { distroboxUpdater.Config.Enabled = err == nil distroboxUpdater.SetUsers(users) - totalSteps := brewUpdater.Steps() + systemUpdater.Steps() + flatpakUpdater.Steps() + distroboxUpdater.Steps() + var enableUpd bool = true + var systemOutdated bool = false + + rpmOstreeUpdater, err := drv.RpmOstreeUpdater{}.New(*initConfiguration) + if err != nil { + enableUpd = false + } + + systemUpdater, err := drv.SystemUpdater{}.New(*initConfiguration) + if err != nil { + enableUpd = false + } + + // FIXME: Bootc can also only be used whenever there are no layered packages, we should account for that! + isBootc, err := drv.BootcCompatible(systemUpdater.BinaryPath) + if err != nil { + isBootc = false + } + + if !isBootc { + slog.Debug("Using rpm-ostree fallback as system driver") + } + + systemUpdater.Config.Enabled = enableUpd && isBootc + rpmOstreeUpdater.Config.Enabled = enableUpd && !isBootc + + if systemUpdater.Config.Enabled { + enableUpd, err = systemUpdater.Check() + } else { + enableUpd, err = rpmOstreeUpdater.Check() + } + if err != nil { + slog.Error("Failed checking for updates") + } + if !enableUpd { + slog.Debug("No system update found, disabiling module") + } + + totalSteps := brewUpdater.Steps() + systemUpdater.Steps() + rpmOstreeUpdater.Steps() + flatpakUpdater.Steps() + distroboxUpdater.Steps() pw := lib.NewProgressWriter() pw.SetNumTrackersExpected(1) pw.SetAutoStop(false) @@ -118,7 +142,17 @@ func Update(cmd *cobra.Command, args []string) { var outputs = []drv.CommandOutput{} - if systemUpdater.Outdated { + if systemUpdater.Config.Enabled { + systemOutdated, err = systemUpdater.Outdated() + } else { + systemOutdated, err = rpmOstreeUpdater.Outdated() + } + + if err != nil { + slog.Error("Failed checking if system is out of date") + } + + if systemOutdated { const OUTDATED_WARNING = "There hasn't been an update in over a month. Consider rebooting or running updates manually" err := lib.Notify("System Warning", OUTDATED_WARNING) if err != nil { @@ -127,9 +161,14 @@ func Update(cmd *cobra.Command, args []string) { slog.Warn(OUTDATED_WARNING) } - if systemUpdater.Config.Enabled { + if enableUpd { lib.ChangeTrackerMessageFancy(pw, tracker, progressEnabled, lib.TrackerMessage{Title: systemUpdater.Config.Title, Description: systemUpdater.Config.Description}) - out, err := systemUpdater.Update() + var out *[]drv.CommandOutput + if rpmOstreeUpdater.Config.Enabled { + out, err = rpmOstreeUpdater.Update() + } else { + out, err = systemUpdater.Update() + } outputs = append(outputs, *out...) tracker.IncrementSection(err) } diff --git a/drv/rpm-ostree.go b/drv/rpm-ostree.go new file mode 100644 index 0000000..468850e --- /dev/null +++ b/drv/rpm-ostree.go @@ -0,0 +1,121 @@ +package drv + +// Temporary: WILL get removed at some point. +// FIXME: Remove this on Spring 2025 when we all move to dnf5 and bootc ideally + +import ( + "encoding/json" + "os/exec" + "strings" + "time" +) + +type rpmOstreeStatus struct { + Deployments []struct { + Timestamp int64 `json:"timestamp"` + } `json:"deployments"` +} + +type RpmOstreeUpdater struct { + Config DriverConfiguration + BinaryPath string +} + +func (dr RpmOstreeUpdater) Outdated() (bool, error) { + if dr.Config.DryRun { + return false, nil + } + oneMonthAgo := time.Now().AddDate(0, -1, 0) + var timestamp time.Time + + cmd := exec.Command(dr.BinaryPath, "status", "--json", "--booted") + out, err := cmd.CombinedOutput() + if err != nil { + return false, err + } + var status rpmOstreeStatus + err = json.Unmarshal(out, &status) + if err != nil { + return false, err + } + timestamp = time.Unix(status.Deployments[0].Timestamp, 0).UTC() + + return timestamp.Before(oneMonthAgo), nil +} + +func (dr RpmOstreeUpdater) Update() (*[]CommandOutput, error) { + var finalOutput = []CommandOutput{} + var cmd *exec.Cmd = nil + binaryPath := dr.BinaryPath + cli := []string{binaryPath, "upgrade"} + cmd = exec.Command(cli[0], cli[1:]...) + out, err := cmd.CombinedOutput() + tmpout := CommandOutput{}.New(out, err) + tmpout.Cli = cli + tmpout.Failure = err != nil + tmpout.Context = "System Update" + finalOutput = append(finalOutput, *tmpout) + return &finalOutput, err +} + +func (dr RpmOstreeUpdater) UpdateAvailable() (bool, error) { + // This function may or may not be accurate, rpm-ostree updgrade --check has issues... https://github.com/coreos/rpm-ostree/issues/1579 + // Not worried because we will end up removing rpm-ostree from the equation soon + cmd := exec.Command(dr.BinaryPath, "upgrade", "--check") + out, err := cmd.CombinedOutput() + if err != nil { + return true, err + } + return strings.Contains(string(out), "AvailableUpdate"), nil +} + +func (up RpmOstreeUpdater) Steps() int { + if up.Config.Enabled { + return 1 + } + return 0 +} + +func BootcCompatible(binaryPath string) (bool, error) { + cmd := exec.Command(binaryPath, "status", "--format=json") + out, err := cmd.CombinedOutput() + if err != nil { + return false, nil + } + var status bootcStatus + err = json.Unmarshal(out, &status) + if err != nil { + return false, nil + } + return !(status.Status.Booted.Incompatible || status.Status.Staged.Incompatible), nil +} + +func (up RpmOstreeUpdater) New(config UpdaterInitConfiguration) (RpmOstreeUpdater, error) { + up.Config = DriverConfiguration{ + Title: "System", + Description: "System Updates", + Enabled: !config.Ci, + DryRun: config.DryRun, + } + + if up.Config.DryRun { + return up, nil + } + + binaryPath, exists := config.Environment["UUPD_RPMOSTREE_BINARY"] + if !exists || binaryPath == "" { + up.BinaryPath = "/usr/bin/rpm-ostree" + } else { + up.BinaryPath = binaryPath + } + + return up, nil +} + +func (up RpmOstreeUpdater) Check() (bool, error) { + if up.Config.DryRun { + return true, nil + } + + return up.UpdateAvailable() +} diff --git a/drv/system.go b/drv/system.go index 864f12d..3db6609 100644 --- a/drv/system.go +++ b/drv/system.go @@ -24,72 +24,41 @@ type bootcStatus struct { } `json:"status"` } -// TODO: Temporary: WILL get removed at some point. -type rpmOstreeStatus struct { - Deployments []struct { - Timestamp int64 `json:"timestamp"` - } `json:"deployments"` -} - type SystemUpdater struct { - Config DriverConfiguration - SystemDriver SystemDriver - Outdated bool - UpdateAvailable bool + Config DriverConfiguration + BinaryPath string } -type SystemDriver int - -const ( - Bootc SystemDriver = iota - RpmOstree -) - -func (dr SystemDriver) Outdated() (bool, error) { +func (dr SystemUpdater) Outdated() (bool, error) { + if dr.Config.DryRun { + return false, nil + } oneMonthAgo := time.Now().AddDate(0, -1, 0) var timestamp time.Time - switch dr { - case Bootc: - cmd := exec.Command("bootc", "status", "--format=json") - out, err := cmd.CombinedOutput() - if err != nil { - return false, err - } - var status bootcStatus - err = json.Unmarshal(out, &status) - if err != nil { - return false, err - } - timestamp, err = time.Parse(time.RFC3339Nano, status.Status.Booted.Image.Timestamp) - if err != nil { - return false, nil - } - case RpmOstree: - cmd := exec.Command("rpm-ostree", "status", "--json", "--booted") - out, err := cmd.CombinedOutput() - if err != nil { - return false, err - } - var status rpmOstreeStatus - err = json.Unmarshal(out, &status) - if err != nil { - return false, err - } - timestamp = time.Unix(status.Deployments[0].Timestamp, 0).UTC() + cmd := exec.Command(dr.BinaryPath, "status", "--format=json") + out, err := cmd.CombinedOutput() + if err != nil { + return false, err + } + var status bootcStatus + err = json.Unmarshal(out, &status) + if err != nil { + return false, err + } + timestamp, err = time.Parse(time.RFC3339Nano, status.Status.Booted.Image.Timestamp) + if err != nil { + return false, nil } - return timestamp.Before(oneMonthAgo), nil } -func (dr SystemDriver) Update() (*[]CommandOutput, error) { +func (dr SystemUpdater) Update() (*[]CommandOutput, error) { var finalOutput = []CommandOutput{} var cmd *exec.Cmd = nil - switch dr { - case Bootc: - cmd = exec.Command("/usr/bin/bootc", "upgrade") - case RpmOstree: - cmd = exec.Command("/usr/bin/rpm-ostree", "upgrade") - } + var binaryPath string + binaryPath = dr.BinaryPath + cli := []string{binaryPath, "upgrade"} + cmd = exec.Command(cli[0], cli[1:]...) out, err := cmd.CombinedOutput() tmpout := CommandOutput{}.New(out, err) if err != nil { @@ -99,27 +68,13 @@ func (dr SystemDriver) Update() (*[]CommandOutput, error) { return &finalOutput, err } -func (dr SystemDriver) UpdateAvailable() (bool, error) { - switch dr { - case Bootc: - cmd := exec.Command("/usr/bin/bootc", "upgrade", "--check") - out, err := cmd.CombinedOutput() - if err != nil { - return true, err - } - return !strings.Contains(string(out), "No changes in:"), nil - case RpmOstree: - // This function may or may not be accurate, rpm-ostree updgrade --check has issues... https://github.com/coreos/rpm-ostree/issues/1579 - // Not worried because we will end up removing rpm-ostree from the equation soon - cmd := exec.Command("/usr/bin/rpm-ostree", "upgrade", "--check") - out, err := cmd.CombinedOutput() - if err != nil { - return true, err - } - return strings.Contains(string(out), "AvailableUpdate"), nil +func (dr SystemUpdater) UpdateAvailable() (bool, error) { + cmd := exec.Command(dr.BinaryPath, "upgrade", "--check") + out, err := cmd.CombinedOutput() + if err != nil { + return true, err } - - return false, nil + return !strings.Contains(string(out), "No changes in:"), nil } func (up SystemUpdater) Steps() int { @@ -129,21 +84,7 @@ func (up SystemUpdater) Steps() int { return 0 } -func BootcCompatible() (bool, error) { - cmd := exec.Command("bootc", "status", "--format=json") - out, err := cmd.CombinedOutput() - if err != nil { - return false, nil - } - var status bootcStatus - err = json.Unmarshal(out, &status) - if err != nil { - return false, nil - } - return !(status.Status.Booted.Incompatible || status.Status.Staged.Incompatible), nil -} - -func (up SystemUpdater) New(initconfig UpdaterInitConfiguration) (SystemUpdater, error) { +func (up SystemUpdater) New(config UpdaterInitConfiguration) (SystemUpdater, error) { up.Config = DriverConfiguration{ Title: "System", Description: "System Updates", @@ -152,46 +93,23 @@ func (up SystemUpdater) New(initconfig UpdaterInitConfiguration) (SystemUpdater, } if up.Config.DryRun { - up.Outdated = false return up, nil } - isBootc, err := BootcCompatible() - if err != nil { - return up, err - } - if isBootc { - up.SystemDriver = Bootc + bootcBinaryPath, exists := config.Environment["UUPD_BOOTC_BINARY"] + if !exists || bootcBinaryPath == "" { + up.BinaryPath = "/usr/bin/bootc" } else { - up.SystemDriver = RpmOstree - } - - outdated, err := up.SystemDriver.Outdated() - if err != nil { - return up, err + up.BinaryPath = bootcBinaryPath } - up.Outdated = outdated return up, nil } -func (up *SystemUpdater) Check() (bool, error) { +func (up SystemUpdater) Check() (bool, error) { if up.Config.DryRun { return true, nil } - updateAvailable, err := up.SystemDriver.UpdateAvailable() - return updateAvailable, err -} - -func (up SystemUpdater) Update() (*[]CommandOutput, error) { - var final_output = []CommandOutput{} - - if up.Config.DryRun { - return &final_output, nil - } - - out, err := up.SystemDriver.Update() - final_output = append(final_output, *out...) - return &final_output, err + return up.UpdateAvailable() } From d5a77e4206e372ec28055d1e80e4ccf6c74934e3 Mon Sep 17 00:00:00 2001 From: Tulip Blossom Date: Wed, 11 Dec 2024 19:57:41 -0300 Subject: [PATCH 3/5] fix: linting --- cmd/update.go | 2 +- drv/rpm-ostree.go | 4 ++-- drv/system.go | 9 ++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/cmd/update.go b/cmd/update.go index 30123cd..9788be7 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -74,7 +74,7 @@ func Update(cmd *cobra.Command, args []string) { distroboxUpdater.SetUsers(users) var enableUpd bool = true - var systemOutdated bool = false + var systemOutdated bool rpmOstreeUpdater, err := drv.RpmOstreeUpdater{}.New(*initConfiguration) if err != nil { diff --git a/drv/rpm-ostree.go b/drv/rpm-ostree.go index 468850e..8eae935 100644 --- a/drv/rpm-ostree.go +++ b/drv/rpm-ostree.go @@ -45,13 +45,13 @@ func (dr RpmOstreeUpdater) Outdated() (bool, error) { func (dr RpmOstreeUpdater) Update() (*[]CommandOutput, error) { var finalOutput = []CommandOutput{} - var cmd *exec.Cmd = nil + var cmd *exec.Cmd binaryPath := dr.BinaryPath cli := []string{binaryPath, "upgrade"} cmd = exec.Command(cli[0], cli[1:]...) out, err := cmd.CombinedOutput() tmpout := CommandOutput{}.New(out, err) - tmpout.Cli = cli + // tmpout.Cli = cli tmpout.Failure = err != nil tmpout.Context = "System Update" finalOutput = append(finalOutput, *tmpout) diff --git a/drv/system.go b/drv/system.go index 3db6609..ef2a8fe 100644 --- a/drv/system.go +++ b/drv/system.go @@ -54,9 +54,8 @@ func (dr SystemUpdater) Outdated() (bool, error) { func (dr SystemUpdater) Update() (*[]CommandOutput, error) { var finalOutput = []CommandOutput{} - var cmd *exec.Cmd = nil - var binaryPath string - binaryPath = dr.BinaryPath + var cmd *exec.Cmd + binaryPath := dr.BinaryPath cli := []string{binaryPath, "upgrade"} cmd = exec.Command(cli[0], cli[1:]...) out, err := cmd.CombinedOutput() @@ -88,8 +87,8 @@ func (up SystemUpdater) New(config UpdaterInitConfiguration) (SystemUpdater, err up.Config = DriverConfiguration{ Title: "System", Description: "System Updates", - Enabled: !initconfig.Ci, - DryRun: initconfig.DryRun, + Enabled: !config.Ci, + DryRun: config.DryRun, } if up.Config.DryRun { From ee355218b67c8e87c32bd9583d672645cbffef95 Mon Sep 17 00:00:00 2001 From: Tulip Blossom Date: Wed, 11 Dec 2024 20:30:50 -0300 Subject: [PATCH 4/5] refactor: use interface for single system driver --- cmd/update.go | 25 +++++++++---------------- drv/system.go | 10 ++++++++++ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/cmd/update.go b/cmd/update.go index 9788be7..6c7c82c 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -86,7 +86,6 @@ func Update(cmd *cobra.Command, args []string) { enableUpd = false } - // FIXME: Bootc can also only be used whenever there are no layered packages, we should account for that! isBootc, err := drv.BootcCompatible(systemUpdater.BinaryPath) if err != nil { isBootc = false @@ -99,19 +98,21 @@ func Update(cmd *cobra.Command, args []string) { systemUpdater.Config.Enabled = enableUpd && isBootc rpmOstreeUpdater.Config.Enabled = enableUpd && !isBootc - if systemUpdater.Config.Enabled { - enableUpd, err = systemUpdater.Check() - } else { - enableUpd, err = rpmOstreeUpdater.Check() + var mainSystemDriver drv.SystemUpdateDriver = systemUpdater + if !systemUpdater.Config.Enabled { + mainSystemDriver = rpmOstreeUpdater } + + enableUpd, err = mainSystemDriver.Check() if err != nil { slog.Error("Failed checking for updates") } + if !enableUpd { slog.Debug("No system update found, disabiling module") } - totalSteps := brewUpdater.Steps() + systemUpdater.Steps() + rpmOstreeUpdater.Steps() + flatpakUpdater.Steps() + distroboxUpdater.Steps() + totalSteps := brewUpdater.Steps() + mainSystemDriver.Steps() + flatpakUpdater.Steps() + distroboxUpdater.Steps() pw := lib.NewProgressWriter() pw.SetNumTrackersExpected(1) pw.SetAutoStop(false) @@ -142,11 +143,7 @@ func Update(cmd *cobra.Command, args []string) { var outputs = []drv.CommandOutput{} - if systemUpdater.Config.Enabled { - systemOutdated, err = systemUpdater.Outdated() - } else { - systemOutdated, err = rpmOstreeUpdater.Outdated() - } + systemOutdated, err = mainSystemDriver.Outdated() if err != nil { slog.Error("Failed checking if system is out of date") @@ -164,11 +161,7 @@ func Update(cmd *cobra.Command, args []string) { if enableUpd { lib.ChangeTrackerMessageFancy(pw, tracker, progressEnabled, lib.TrackerMessage{Title: systemUpdater.Config.Title, Description: systemUpdater.Config.Description}) var out *[]drv.CommandOutput - if rpmOstreeUpdater.Config.Enabled { - out, err = rpmOstreeUpdater.Update() - } else { - out, err = systemUpdater.Update() - } + out, err = mainSystemDriver.Update() outputs = append(outputs, *out...) tracker.IncrementSection(err) } diff --git a/drv/system.go b/drv/system.go index ef2a8fe..21d4fec 100644 --- a/drv/system.go +++ b/drv/system.go @@ -24,6 +24,16 @@ type bootcStatus struct { } `json:"status"` } +// Workaround interface to decouple individual drivers +// (TODO: Remove this whenever rpm-ostree driver gets deprecated) +type SystemUpdateDriver interface { + Steps() int + Outdated() (bool, error) + UpdateAvailable() (bool, error) + Check() (bool, error) + Update() (*[]CommandOutput, error) +} + type SystemUpdater struct { Config DriverConfiguration BinaryPath string From a86859555f182f01044cf701d65403a42293c566 Mon Sep 17 00:00:00 2001 From: Tulip Blossom Date: Wed, 11 Dec 2024 21:15:45 -0300 Subject: [PATCH 5/5] fix: proper number of steps for main system driver --- cmd/update.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/update.go b/cmd/update.go index 6c7c82c..24c59c9 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -112,7 +112,10 @@ func Update(cmd *cobra.Command, args []string) { slog.Debug("No system update found, disabiling module") } - totalSteps := brewUpdater.Steps() + mainSystemDriver.Steps() + flatpakUpdater.Steps() + distroboxUpdater.Steps() + totalSteps := brewUpdater.Steps() + flatpakUpdater.Steps() + distroboxUpdater.Steps() + if enableUpd { + totalSteps += mainSystemDriver.Steps() + } pw := lib.NewProgressWriter() pw.SetNumTrackersExpected(1) pw.SetAutoStop(false)