-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Copy any found sysextensions into active+passive efi dir (#372)
- Loading branch information
Showing
4 changed files
with
306 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
package hook_test | ||
|
||
import ( | ||
"bytes" | ||
"github.com/jaypipes/ghw/pkg/block" | ||
_ "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks" | ||
hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks" | ||
"github.com/kairos-io/kairos-agent/v2/pkg/config" | ||
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants" | ||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs" | ||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks" | ||
"github.com/kairos-io/kairos-sdk/collector" | ||
sdkTypes "github.com/kairos-io/kairos-sdk/types" | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
"github.com/twpayne/go-vfs/v4" | ||
"github.com/twpayne/go-vfs/v4/vfst" | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
) | ||
|
||
func TestConfig(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "Hooks Suite") | ||
} | ||
|
||
var _ = Describe("Hooks", func() { | ||
var cfg *config.Config | ||
var fs vfs.FS | ||
var logger sdkTypes.KairosLogger | ||
var runner *v1mock.FakeRunner | ||
var mounter *v1mock.ErrorMounter | ||
var syscallMock *v1mock.FakeSyscall | ||
var client *v1mock.FakeHTTPClient | ||
var cloudInit *v1mock.FakeCloudInitRunner | ||
var cleanup func() | ||
var memLog *bytes.Buffer | ||
var extractor *v1mock.FakeImageExtractor | ||
var ghwTest v1mock.GhwMock | ||
var err error | ||
|
||
Context("SysExtPostInstall", func() { | ||
BeforeEach(func() { | ||
runner = v1mock.NewFakeRunner() | ||
syscallMock = &v1mock.FakeSyscall{} | ||
mounter = v1mock.NewErrorMounter() | ||
client = &v1mock.FakeHTTPClient{} | ||
memLog = &bytes.Buffer{} | ||
logger = sdkTypes.NewBufferLogger(memLog) | ||
extractor = v1mock.NewFakeImageExtractor(logger) | ||
logger.SetLevel("debug") | ||
fs, cleanup, err = vfst.NewTestFS(map[string]interface{}{}) | ||
// Create proper dir structure for our EFI partition contents | ||
Expect(err).Should(BeNil()) | ||
err = fsutils.MkdirAll(fs, "/efi/loader/entries", os.ModeDir|os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fsutils.MkdirAll(fs, "/efi/EFI/BOOT", os.ModeDir|os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fsutils.MkdirAll(fs, "/efi/EFI/kairos", os.ModeDir|os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fsutils.MkdirAll(fs, "/etc/cos/", os.ModeDir|os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fsutils.MkdirAll(fs, "/run/initramfs/cos-state/grub/", os.ModeDir|os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fsutils.MkdirAll(fs, "/etc/kairos/branding/", os.ModeDir|os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
|
||
cloudInit = &v1mock.FakeCloudInitRunner{} | ||
cfg = config.NewConfig( | ||
config.WithFs(fs), | ||
config.WithRunner(runner), | ||
config.WithLogger(logger), | ||
config.WithMounter(mounter), | ||
config.WithSyscall(syscallMock), | ||
config.WithClient(client), | ||
config.WithCloudInitRunner(cloudInit), | ||
config.WithImageExtractor(extractor), | ||
) | ||
cfg.Config = collector.Config{} | ||
|
||
mainDisk := block.Disk{ | ||
Name: "device", | ||
Partitions: []*block.Partition{ | ||
{ | ||
Name: "device1", | ||
FilesystemLabel: "COS_GRUB", | ||
Type: "ext4", | ||
MountPoint: "/efi", | ||
}, | ||
}, | ||
} | ||
ghwTest = v1mock.GhwMock{} | ||
ghwTest.AddDisk(mainDisk) | ||
ghwTest.CreateDevices() | ||
}) | ||
AfterEach(func() { | ||
cleanup() | ||
}) | ||
It("should copy all files with .sysext.raw extension", func() { | ||
err = fsutils.MkdirAll(fs, cnst.LiveDir, os.ModeDir|os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fs.WriteFile(filepath.Join(cnst.LiveDir, "test1.sysext.raw"), []byte("test"), os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fs.WriteFile(filepath.Join(cnst.LiveDir, "test2.sysext.raw"), []byte("test"), os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
postInstall := hook.SysExtPostInstall{} | ||
err = postInstall.Run(*cfg, nil) | ||
Expect(err).Should(BeNil()) | ||
// we expect them to be here as its where we mount the efi partition but then we fake unmount | ||
_, err = fs.Stat(filepath.Join(cnst.EfiDir, "EFI/kairos/active.efi.extra.d/", "test1.sysext.raw")) | ||
Expect(err).Should(BeNil()) | ||
_, err = fs.Stat(filepath.Join(cnst.EfiDir, "EFI/kairos/active.efi.extra.d/", "test2.sysext.raw")) | ||
Expect(err).Should(BeNil()) | ||
}) | ||
It("should ignore files without .sysext.raw extension", func() { | ||
err = fsutils.MkdirAll(fs, cnst.LiveDir, os.ModeDir|os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fs.WriteFile(filepath.Join(cnst.LiveDir, "test1.sysext.raw"), []byte("test"), os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fs.WriteFile(filepath.Join(cnst.LiveDir, "test2.sysext.raw"), []byte("test"), os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fs.WriteFile(filepath.Join(cnst.LiveDir, "hello.raw"), []byte("test"), os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fs.WriteFile(filepath.Join(cnst.LiveDir, "hello.sysext.what.raw"), []byte("test"), os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
err = fs.WriteFile(filepath.Join(cnst.LiveDir, "hello.sysext"), []byte("test"), os.ModePerm) | ||
Expect(err).Should(BeNil()) | ||
postInstall := hook.SysExtPostInstall{} | ||
err = postInstall.Run(*cfg, nil) | ||
Expect(err).Should(BeNil()) | ||
// we expect them to be here as its where we mount the efi partition but then we fake unmount | ||
_, err = fs.Stat(filepath.Join(cnst.EfiDir, "EFI/kairos/active.efi.extra.d/", "test1.sysext.raw")) | ||
Expect(err).Should(BeNil()) | ||
_, err = fs.Stat(filepath.Join(cnst.EfiDir, "EFI/kairos/active.efi.extra.d/", "test2.sysext.raw")) | ||
Expect(err).Should(BeNil()) | ||
_, err = fs.Stat(filepath.Join(cnst.EfiDir, "EFI/kairos/active.efi.extra.d/", "hello.raw")) | ||
Expect(err).ShouldNot(BeNil()) | ||
_, err = fs.Stat(filepath.Join(cnst.EfiDir, "EFI/kairos/active.efi.extra.d/", "hello.sysext.what.raw")) | ||
Expect(err).ShouldNot(BeNil()) | ||
_, err = fs.Stat(filepath.Join(cnst.EfiDir, "EFI/kairos/active.efi.extra.d/", "hello.sysext")) | ||
Expect(err).ShouldNot(BeNil()) | ||
}) | ||
It("doesn't error if it cant find the efi partition", func() { | ||
ghwTest.Clean() | ||
postInstall := hook.SysExtPostInstall{} | ||
err = postInstall.Run(*cfg, nil) | ||
Expect(err).Should(BeNil()) | ||
}) | ||
It("errors if it cant mount the efi partition and strict is set", func() { | ||
ghwTest.Clean() | ||
cfg.FailOnBundleErrors = true | ||
postInstall := hook.SysExtPostInstall{} | ||
err = postInstall.Run(*cfg, nil) | ||
Expect(err).ShouldNot(BeNil()) | ||
}) | ||
It("doesn't error if it cant mount the efi partition", func() { | ||
mounter.ErrorOnMount = true | ||
postInstall := hook.SysExtPostInstall{} | ||
err = postInstall.Run(*cfg, nil) | ||
Expect(err).Should(BeNil()) | ||
}) | ||
It("errors if it cant mount the efi partition and strict is set", func() { | ||
mounter.ErrorOnMount = true | ||
cfg.FailOnBundleErrors = true | ||
postInstall := hook.SysExtPostInstall{} | ||
err = postInstall.Run(*cfg, nil) | ||
Expect(err).ShouldNot(BeNil()) | ||
}) | ||
It("doesn't error if it cant create the dirs", func() { | ||
ROfs := vfs.NewReadOnlyFS(fs) | ||
cfg.Fs = ROfs | ||
postInstall := hook.SysExtPostInstall{} | ||
err = postInstall.Run(*cfg, nil) | ||
Expect(err).Should(BeNil()) | ||
}) | ||
It("errors if it cant create the dirs and strict is set", func() { | ||
cfg.FailOnBundleErrors = true | ||
ROfs := vfs.NewReadOnlyFS(fs) | ||
cfg.Fs = ROfs | ||
postInstall := hook.SysExtPostInstall{} | ||
err = postInstall.Run(*cfg, nil) | ||
Expect(err).ShouldNot(BeNil()) | ||
}) | ||
|
||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package hook | ||
|
||
import ( | ||
"github.com/kairos-io/kairos-agent/v2/pkg/config" | ||
"github.com/kairos-io/kairos-agent/v2/pkg/constants" | ||
"github.com/kairos-io/kairos-agent/v2/pkg/types/v1" | ||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs" | ||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions" | ||
"io/fs" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
type SysExtPostInstall struct{} | ||
|
||
func (b SysExtPostInstall) Run(c config.Config, _ v1.Spec) error { | ||
c.Logger.Logger.Debug().Msg("Running SysExtPostInstall hook") | ||
// mount efi partition | ||
efiPart, err := partitions.GetEfiPartition() | ||
if err != nil { | ||
c.Logger.Errorf("failed to get EFI partition: %s", err) | ||
if c.FailOnBundleErrors { | ||
return err | ||
} | ||
return nil | ||
} | ||
mounted, _ := c.Mounter.IsMountPoint(constants.EfiDir) | ||
|
||
if !mounted { | ||
err = c.Mounter.Mount(efiPart.Path, constants.EfiDir, efiPart.FS, []string{"rw"}) | ||
if err != nil { | ||
c.Logger.Errorf("failed to mount EFI partition: %s", err) | ||
if c.FailOnBundleErrors { | ||
return err | ||
} | ||
return nil | ||
} | ||
defer func() { | ||
_ = c.Mounter.Unmount(constants.EfiDir) | ||
}() | ||
} else { | ||
// If its mounted, try to remount it RW | ||
err = c.Mounter.Mount(efiPart.Path, constants.EfiDir, efiPart.FS, []string{"remount,rw"}) | ||
defer func() { | ||
_ = c.Mounter.Unmount(constants.EfiDir) | ||
}() | ||
} | ||
|
||
activeDir := filepath.Join(constants.EfiDir, "EFI/kairos/active.efi.extra.d/") | ||
passiveDir := filepath.Join(constants.EfiDir, "EFI/kairos/passive.efi.extra.d/") | ||
for _, dir := range []string{activeDir, passiveDir} { | ||
err = fsutils.MkdirAll(c.Fs, dir, 0755) | ||
if err != nil { | ||
c.Logger.Errorf("failed to create directory %s: %s", dir, err) | ||
if c.FailOnBundleErrors { | ||
return err | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
err = fsutils.WalkDirFs(c.Fs, constants.LiveDir, func(path string, info fs.DirEntry, err error) error { | ||
if err != nil { | ||
return err | ||
} | ||
if info.IsDir() { | ||
return nil | ||
} | ||
if strings.HasSuffix(info.Name(), ".sysext.raw") { | ||
// copy it to /EFI/Kairos/{active,passive}.efi.extra.d/ | ||
err = fsutils.Copy(c.Fs, path, filepath.Join(activeDir, info.Name())) | ||
if err != nil { | ||
c.Logger.Errorf("failed to copy %s to %s: %s", path, activeDir, err) | ||
if c.FailOnBundleErrors { | ||
return err | ||
} | ||
return nil | ||
} | ||
c.Logger.Debugf("copied %s to %s", path, activeDir) | ||
} | ||
return nil | ||
}) | ||
if c.FailOnBundleErrors && err != nil { | ||
return err | ||
} | ||
c.Logger.Logger.Debug().Msg("Done SysExtPostInstall hook") | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters