diff --git a/bundles/bundle_test.go b/bundles/bundle_test.go index a016170..cf8ca7f 100644 --- a/bundles/bundle_test.go +++ b/bundles/bundle_test.go @@ -1,10 +1,13 @@ package bundles_test import ( + "debug/elf" + "fmt" "io" "os" "path" "path/filepath" + "runtime" . "github.com/kairos-io/kairos-sdk/bundles" . "github.com/onsi/ginkgo/v2" @@ -29,7 +32,29 @@ var _ = Describe("Bundle", func() { defer os.RemoveAll(dir) err = RunBundles([]BundleOption{WithDBPath(dir), WithRootFS(dir), WithTarget("container://quay.io/mocaccino/extra:edgevpn-utils-0.15.0")}) Expect(err).ToNot(HaveOccurred()) - Expect(filepath.Join(dir, "usr", "bin", "edgevpn")).To(BeARegularFile()) + binPath := filepath.Join(dir, "usr", "bin", "edgevpn") + Expect(binPath).To(BeARegularFile()) + expectBinaryArch(binPath, runtime.GOARCH) + }) + + When("platform is specified", func() { + for _, arch := range []string{"amd64", "arm64", "arm/v7"} { + It(fmt.Sprintf("install with %s", arch), func() { + dir, err := os.MkdirTemp("", "test") + Expect(err).ToNot(HaveOccurred()) + defer os.RemoveAll(dir) + err = RunBundles([]BundleOption{ + WithDBPath(dir), + WithRootFS(dir), + WithTarget("container://quay.io/luet/base:0.35.5"), + WithPlatform(fmt.Sprintf("linux/%s", arch)), + }) + Expect(err).ToNot(HaveOccurred()) + binPath := filepath.Join(dir, "usr", "bin", "luet") + Expect(binPath).To(BeARegularFile()) + expectBinaryArch(binPath, arch) + }) + } }) When("local is true", func() { @@ -205,3 +230,18 @@ func expectInstalled(installer BundleInstaller, config *BundleConfig) { _, err = os.Stat("/etc/cos/grub.cfg") Expect(err).ToNot(HaveOccurred()) } + +func expectBinaryArch(path string, arch string) { + f, err := elf.Open(path) + Expect(err).ToNot(HaveOccurred()) + switch arch { + case "amd64": + Expect(f.Machine.String()).To(Equal(elf.EM_X86_64.String())) + case "arm64": + Expect(f.Machine.String()).To(Equal(elf.EM_AARCH64.String())) + case "arm/v7": + Expect(f.Machine.String()).To(Equal(elf.EM_ARM.String())) + default: + Fail(fmt.Sprintf("unsupported arch: %s", arch)) + } +} diff --git a/bundles/bundles.go b/bundles/bundles.go index 451717a..356cc5a 100644 --- a/bundles/bundles.go +++ b/bundles/bundles.go @@ -27,6 +27,7 @@ type BundleConfig struct { LocalFile bool Auth *registrytypes.AuthConfig Transport http.RoundTripper + Platform string } // BundleOption defines a configuration option for a bundle. @@ -93,6 +94,13 @@ func WithTransport(t http.RoundTripper) BundleOption { } } +func WithPlatform(p string) BundleOption { + return func(bc *BundleConfig) error { + bc.Platform = p + return nil + } +} + func (bc *BundleConfig) extractRepo() (string, string, error) { s := strings.Split(bc.Repository, "://") if len(s) != 2 { @@ -204,10 +212,11 @@ func (e OCIImageExtractor) Install(config *BundleConfig) error { if err != nil { return err } + if e.Local { img, err = tarball.ImageFromPath(target, nil) } else { - img, err = utils.GetImage(target, utils.GetCurrentPlatform(), config.Auth, config.Transport) + img, err = utils.GetImage(target, config.Platform, config.Auth, config.Transport) } if err != nil { return err @@ -233,10 +242,11 @@ func (e OCIImageRunner) Install(config *BundleConfig) error { if err != nil { return err } + if e.Local { img, err = tarball.ImageFromPath(target, nil) } else { - img, err = utils.GetImage(target, utils.GetCurrentPlatform(), config.Auth, config.Transport) + img, err = utils.GetImage(target, config.Platform, config.Auth, config.Transport) } if err != nil { return err