diff --git a/internal/agent/upgrade.go b/internal/agent/upgrade.go index 774692e..7ac4158 100644 --- a/internal/agent/upgrade.go +++ b/internal/agent/upgrade.go @@ -65,18 +65,18 @@ func ListNewerReleases(includePrereleases bool) ([]string, error) { } func Upgrade( - source string, force, strictValidations bool, dirs []string, preReleases, upgradeRecovery bool) error { + source string, force, strictValidations bool, dirs []string, singleEntry string, preReleases, upgradeRecovery bool) error { bus.Manager.Initialize() if internalutils.UkiBootMode() == internalutils.UkiHDD { - return upgradeUki(source, dirs, strictValidations, upgradeRecovery) + return upgradeUki(source, dirs, singleEntry, strictValidations, upgradeRecovery) } else { return upgrade(source, force, strictValidations, dirs, preReleases, upgradeRecovery) } } func upgrade(source string, force, strictValidations bool, dirs []string, preReleases, upgradeRecovery bool) error { - upgradeSpec, c, err := generateUpgradeSpec(source, force, strictValidations, dirs, preReleases, upgradeRecovery) + upgradeSpec, c, err := generateUpgradeSpec(source, force, strictValidations, dirs, "", preReleases, upgradeRecovery) if err != nil { return err } @@ -135,13 +135,17 @@ func newerReleases() (versioneer.TagList, error) { // generateUpgradeConfForCLIArgs creates a kairos configuration for `--source` and `--recovery` // command line arguments. It will be added to the rest of the configurations. -func generateUpgradeConfForCLIArgs(source string, upgradeRecovery bool) (string, error) { +func generateUpgradeConfForCLIArgs(source, singleEntry string, upgradeRecovery bool) (string, error) { upgradeConfig := ExtraConfigUpgrade{} if upgradeRecovery { upgradeConfig.Upgrade.Recovery = true } + // if upgradeSingleEntry { + // upgradeConfig.Upgrade.Recovery = true + // } + // Set uri both for active and recovery because we don't know what we are // actually upgrading. The "upgradeRecovery" is just the command line argument. // The user might have set it to "true" in the kairos config. Since we don't @@ -157,8 +161,8 @@ func generateUpgradeConfForCLIArgs(source string, upgradeRecovery bool) (string, return string(d), err } -func generateUpgradeSpec(sourceImageURL string, force, strictValidations bool, dirs []string, preReleases, upgradeRecovery bool) (*v1.UpgradeSpec, *config.Config, error) { - cliConf, err := generateUpgradeConfForCLIArgs(sourceImageURL, upgradeRecovery) +func generateUpgradeSpec(sourceImageURL string, force, strictValidations bool, dirs []string, singleEntry string, preReleases, upgradeRecovery bool) (*v1.UpgradeSpec, *config.Config, error) { + cliConf, err := generateUpgradeConfForCLIArgs(sourceImageURL, singleEntry, upgradeRecovery) if err != nil { return nil, nil, err } @@ -201,8 +205,8 @@ func getReleasesFromProvider(includePrereleases bool) ([]string, error) { return result, nil } -func upgradeUki(source string, dirs []string, strictValidations, upgradeRecovery bool) error { - cliConf, err := generateUpgradeConfForCLIArgs(source, upgradeRecovery) +func upgradeUki(source string, dirs []string, singleEntry string, strictValidations, upgradeRecovery bool) error { + cliConf, err := generateUpgradeConfForCLIArgs(source, singleEntry, upgradeRecovery) if err != nil { return err } @@ -240,7 +244,8 @@ func upgradeUki(source string, dirs []string, strictValidations, upgradeRecovery // ExtraConfigUpgrade is the struct that holds the upgrade options that come from flags and events type ExtraConfigUpgrade struct { Upgrade struct { - Recovery bool `json:"recovery,omitempty"` + Recovery bool `json:"recovery,omitempty"` + SingleEntry string `json:"single-entry,omitempty"` RecoverySystem struct { URI string `json:"uri,omitempty"` } `json:"recovery-system,omitempty"` diff --git a/main.go b/main.go index a25068a..374086f 100644 --- a/main.go +++ b/main.go @@ -185,8 +185,11 @@ See https://kairos.io/docs/upgrade/manual/ for documentation. source = fmt.Sprintf("oci:%s", image) } + // TODO: Too many flags? Merge --recovery and --single-entry somehow? + // Does the new flag make sense in non-uki? (No) return agent.Upgrade(source, c.Bool("force"), c.Bool("strict-validation"), constants.GetConfigScanDirs(), + c.String("single-entry"), c.Bool("pre"), c.Bool("recovery"), ) }, diff --git a/pkg/action/bootentries.go b/pkg/action/bootentries.go index 821da59..b336783 100644 --- a/pkg/action/bootentries.go +++ b/pkg/action/bootentries.go @@ -214,7 +214,7 @@ func systemdConfToBootName(conf string) (string, error) { return bootName, nil } - return "", fmt.Errorf("unknown systemd-boot conf: %s", conf) + return strings.ReplaceAll(fileName, "_", " "), nil } func bootNameToSystemdConf(name string) (string, error) { @@ -253,10 +253,9 @@ func bootNameToSystemdConf(name string) (string, error) { differenciator = "_" + strings.TrimPrefix(name, "statereset ") } return "statereset" + differenciator + ".conf", nil - } - return "", fmt.Errorf("unknown boot name: %s", name) + return strings.ReplaceAll(name, " ", "_") + ".conf", nil } // listBootEntriesSystemd lists the boot entries available in the systemd-boot config files @@ -320,6 +319,10 @@ func listBootEntriesSystemd(cfg *config.Config) error { func listSystemdEntries(cfg *config.Config, efiPartition *v1.Partition) ([]string, error) { var entries []string err := fsutils.WalkDirFs(cfg.Fs, filepath.Join(efiPartition.MountPoint, "loader/entries/"), func(path string, info os.DirEntry, err error) error { + if err != nil { + cfg.Logger.Errorf("Walking the dir %s", err.Error()) + } + cfg.Logger.Debugf("Checking file %s", path) if info == nil { return nil diff --git a/pkg/types/v1/config.go b/pkg/types/v1/config.go index c4fbe73..49e3260 100644 --- a/pkg/types/v1/config.go +++ b/pkg/types/v1/config.go @@ -528,11 +528,12 @@ func (i *InstallUkiSpec) GetPartitions() ElementalPartitions { return i.Partitio func (i *InstallUkiSpec) GetExtraPartitions() PartitionList { return i.ExtraPartitions } type UpgradeUkiSpec struct { - RecoveryUpgrade bool `yaml:"recovery,omitempty" mapstructure:"recovery"` - Active Image `yaml:"system,omitempty" mapstructure:"system"` - Reboot bool `yaml:"reboot,omitempty" mapstructure:"reboot"` - PowerOff bool `yaml:"poweroff,omitempty" mapstructure:"poweroff"` - EfiPartition *Partition `yaml:"efi-partition,omitempty" mapstructure:"efi-partition"` + RecoveryUpgrade bool `yaml:"recovery,omitempty" mapstructure:"recovery"` + UpgradeSingleEntry string `yaml:"upgrade-single-entry,omitempty" mapstructure:"upgrade-single-entry"` + Active Image `yaml:"system,omitempty" mapstructure:"system"` + Reboot bool `yaml:"reboot,omitempty" mapstructure:"reboot"` + PowerOff bool `yaml:"poweroff,omitempty" mapstructure:"poweroff"` + EfiPartition *Partition `yaml:"efi-partition,omitempty" mapstructure:"efi-partition"` } func (i *UpgradeUkiSpec) Sanitize() error { diff --git a/pkg/uki/upgrade.go b/pkg/uki/upgrade.go index a88660e..9064283 100644 --- a/pkg/uki/upgrade.go +++ b/pkg/uki/upgrade.go @@ -58,6 +58,10 @@ func (i *UpgradeAction) Run() (err error) { return i.installRecovery() } + if i.spec.UpgradeSingleEntry != "" { + return i.installEntry(i.spec.UpgradeSingleEntry) + } + // Dump artifact to efi dir _, err = e.DumpSource(constants.UkiEfiDir, i.spec.Active.Source) if err != nil {