From 15cc6073e1aec48c91cff981b60f3f8d57b0a81e Mon Sep 17 00:00:00 2001 From: Dimitris Karakasilis Date: Wed, 2 Jul 2025 11:08:10 +0300 Subject: [PATCH] Deprecate `uri` in favor of `source` (#835) * Deprecate `uri` in favor of `source` Fixes https://github.com/kairos-io/kairos/issues/3148 Signed-off-by: Dimitris Karakasilis * Switch all tests to use `source` instead of `uri` and add one test to check backwards compatibility Signed-off-by: Dimitris Karakasilis * Remove non-used key in backwards compatibility method Signed-off-by: Dimitris Karakasilis --------- Signed-off-by: Dimitris Karakasilis --- internal/agent/upgrade.go | 8 ++++---- pkg/config/spec.go | 34 ++++++++++++++++++++++++++++++++++ pkg/config/spec_test.go | 28 ++++++++++++++++++++++++---- pkg/types/v1/config.go | 3 ++- 4 files changed, 64 insertions(+), 9 deletions(-) diff --git a/internal/agent/upgrade.go b/internal/agent/upgrade.go index 38566df..ec821bc 100644 --- a/internal/agent/upgrade.go +++ b/internal/agent/upgrade.go @@ -202,8 +202,8 @@ func generateUpgradeConfForCLIArgs(source, upgradeEntry string) (string, error) // have access to that yet, we just set both uri values which shouldn't matter // anyway, the right one will be used later in the process. if source != "" { - upgradeConfig.Upgrade.RecoverySystem.URI = source - upgradeConfig.Upgrade.System.URI = source + upgradeConfig.Upgrade.RecoverySystem.Source = source + upgradeConfig.Upgrade.System.Source = source } d, err := json.Marshal(upgradeConfig) @@ -236,10 +236,10 @@ type ExtraConfigUpgrade struct { Upgrade struct { Entry string `json:"entry,omitempty"` RecoverySystem struct { - URI string `json:"uri,omitempty"` + Source string `json:"source,omitempty"` } `json:"recovery-system,omitempty"` System struct { - URI string `json:"uri,omitempty"` + Source string `json:"source,omitempty"` } `json:"system,omitempty"` } `json:"upgrade,omitempty"` } diff --git a/pkg/config/spec.go b/pkg/config/spec.go index 28a773d..5fdacd3 100644 --- a/pkg/config/spec.go +++ b/pkg/config/spec.go @@ -1074,9 +1074,43 @@ func unmarshallFullSpec(r *Config, subkey string, sp v1.Spec) error { return fmt.Errorf("error unmarshalling %s Spec: %w", subkey, err) } + // Check for deprecated URI usage and add warnings + checkDeprecatedURIUsage(r.Logger, sp) + return nil } +// checkDeprecatedURIUsage checks if any Image structs in the spec have the deprecated URI field set +// and logs a warning if found, also converts URI to Source for backwards compatibility +func checkDeprecatedURIUsage(logger types.KairosLogger, sp v1.Spec) { + switch s := sp.(type) { + case *v1.InstallSpec: + checkImageURI(&s.Active, logger, "install.system") + checkImageURI(&s.Recovery, logger, "install.recovery-system") + case *v1.UpgradeSpec: + checkImageURI(&s.Active, logger, "upgrade.system") + checkImageURI(&s.Recovery, logger, "upgrade.recovery-system") + case *v1.ResetSpec: + checkImageURI(&s.Active, logger, "reset.system") + case *v1.InstallUkiSpec: + checkImageURI(&s.Active, logger, "install-uki.system") + case *v1.UpgradeUkiSpec: + checkImageURI(&s.Active, logger, "upgrade-uki.system") + } +} + +// checkImageURI checks if an Image has the deprecated URI field set and handles the conversion +func checkImageURI(img *v1.Image, logger types.KairosLogger, fieldPath string) { + if img.URI != "" { + logger.Warnf("The 'uri' field in %s is deprecated, please use 'source' instead", fieldPath) + if img.Source == nil || img.Source.IsEmpty() { + if source, err := v1.NewSrcFromURI(img.URI); err == nil { + img.Source = source + } + } + } +} + // detectLargestDevice returns the largest disk found func detectLargestDevice() string { preferedDevice := "/dev/sda" diff --git a/pkg/config/spec_test.go b/pkg/config/spec_test.go index 2d28804..ce5b83d 100644 --- a/pkg/config/spec_test.go +++ b/pkg/config/spec_test.go @@ -510,7 +510,7 @@ var _ = Describe("Types", Label("types", "config"), func() { Expect(spec.Active.Size).To(Equal(uint(666))) }) It("sets image size to default value if not set in the config and image is smaller", func() { - cfg, err := config.ScanNoLogs(collector.Readers(strings.NewReader("#cloud-config\nupgrade:\n system:\n uri: dir:/\n"))) + cfg, err := config.ScanNoLogs(collector.Readers(strings.NewReader("#cloud-config\nupgrade:\n system:\n source: dir:/\n"))) // Set manually the config collector in the cfg file before unmarshalling the spec c.Config = cfg.Config spec, err := config.NewUpgradeSpec(c) @@ -519,7 +519,7 @@ var _ = Describe("Types", Label("types", "config"), func() { }) It("sets image size to the source if default is smaller", func() { - cfg, err := config.ScanNoLogs(collector.Readers(strings.NewReader("#cloud-config\nupgrade:\n system:\n uri: file:/tmp/waka\n"))) + cfg, err := config.ScanNoLogs(collector.Readers(strings.NewReader("#cloud-config\nupgrade:\n system:\n source: file:/tmp/waka\n"))) // Set manually the config collector in the cfg file before unmarshalling the spec c.Config = cfg.Config Expect(c.Fs.Mkdir("/tmp", 0777)).ShouldNot(HaveOccurred()) @@ -533,6 +533,26 @@ var _ = Describe("Types", Label("types", "config"), func() { Expect(spec.Active.Size).To(Equal(uint(f.Size()/1000/1000) + 100)) }) + It("parses deprecated 'uri' field into Source for backwards compatibility", func() { + // Create a test file using the virtual file system + Expect(c.Fs.Mkdir("/tmp", 0777)).ShouldNot(HaveOccurred()) + Expect(c.Fs.WriteFile("/tmp/testfile", []byte("test"), 0777)).ShouldNot(HaveOccurred()) + Expect(c.Fs.Truncate("/tmp/testfile", 1024*1024)).ShouldNot(HaveOccurred()) + + cfg, err := config.ScanNoLogs(collector.Readers(strings.NewReader(`#cloud-config +upgrade: + system: + uri: file:/tmp/testfile +`))) + Expect(err).ToNot(HaveOccurred()) + // Set manually the config collector in the cfg file before unmarshalling the spec + c.Config = cfg.Config + spec, err := config.NewUpgradeSpec(c) + Expect(err).ToNot(HaveOccurred()) + Expect(spec.Active.Source).ToNot(BeNil()) + Expect(spec.Active.Source.Value()).To(Equal("/tmp/testfile")) + }) + }) }) Describe("Config from cloudconfig", Label("cloud-config"), func() { @@ -569,9 +589,9 @@ reset: upgrade: recovery: true system: - uri: oci:busybox + source: oci:busybox recovery-system: - uri: oci:busybox + source: oci:busybox cloud-init-paths: - /what `) diff --git a/pkg/types/v1/config.go b/pkg/types/v1/config.go index bd8551d..84ee753 100644 --- a/pkg/types/v1/config.go +++ b/pkg/types/v1/config.go @@ -398,7 +398,8 @@ type Image struct { Label string `yaml:"label,omitempty" mapstructure:"label"` Size uint `yaml:"size,omitempty" mapstructure:"size"` FS string `yaml:"fs,omitempty" mapstructure:"fs"` - Source *ImageSource `yaml:"uri,omitempty" mapstructure:"uri"` + URI string `yaml:"uri,omitempty" mapstructure:"uri"` // deprecated, use Source instead + Source *ImageSource `yaml:"source,omitempty" mapstructure:"source"` MountPoint string `yaml:"-"` LoopDevice string `yaml:"-"` }