mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-06-03 01:44:53 +00:00
Merge elemental config into agent config (#102)
This commit is contained in:
parent
5b945303c9
commit
f7bdba2dda
2
go.mod
2
go.mod
@ -12,7 +12,7 @@ require (
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/jaypipes/ghw v0.12.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/kairos-io/kairos-sdk v0.0.9
|
||||
github.com/kairos-io/kairos-sdk v0.0.10
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/mudler/go-nodepair v0.0.0-20221223092639-ba399a66fdfb
|
||||
|
2
go.sum
2
go.sum
@ -358,6 +358,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kairos-io/kairos-sdk v0.0.9 h1:DnuvmnCTDBQg0nr3siaXb5pspi+GUsf1rPb0MFOTdTc=
|
||||
github.com/kairos-io/kairos-sdk v0.0.9/go.mod h1:Z+1CLqMZq97bzwX2XSIArr8EoniMth3mMYkOOb8L3QY=
|
||||
github.com/kairos-io/kairos-sdk v0.0.10 h1:TUgrGSGP6Z1CPfA4gjmbb+cCaJg1OR18c+LD+ZRGqMk=
|
||||
github.com/kairos-io/kairos-sdk v0.0.10/go.mod h1:AK9poWisuhnzri04diXnTG8L7EkOSUArSeeDn2LYFU0=
|
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o=
|
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4=
|
||||
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c h1:eKb4PqwAMhlqwXw0W3atpKaYaPGlXE/Fwh+xpCEYaPk=
|
||||
|
@ -10,7 +10,6 @@ type Interface interface {
|
||||
}
|
||||
|
||||
var AfterInstall = []Interface{
|
||||
&RunStage{}, // Shells out to stages defined from the container image
|
||||
&GrubOptions{}, // Set custom GRUB options
|
||||
&BundleOption{},
|
||||
&CustomMounts{},
|
||||
|
@ -1,22 +0,0 @@
|
||||
package hook
|
||||
|
||||
import (
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
)
|
||||
|
||||
type RunStage struct{}
|
||||
|
||||
func (r RunStage) Run(c config.Config, _ v1.Spec) error {
|
||||
cfg, err := elementalConfig.ReadConfigRunFromAgentConfig(&c)
|
||||
if err != nil {
|
||||
cfg.Logger.Errorf("Error reading config: %s\n", err)
|
||||
}
|
||||
_ = utils.RunStage(cfg, "kairos-install.after")
|
||||
events.RunHookScript("/usr/bin/kairos-agent.install.after.hook") //nolint:errcheck
|
||||
return nil
|
||||
}
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
@ -16,7 +17,6 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/cmd"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
elementalUtils "github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
@ -51,17 +51,6 @@ func displayInfo(agentConfig *Config) {
|
||||
}
|
||||
}
|
||||
|
||||
func mergeOption(cloudConfig string, r map[string]string) {
|
||||
c := &config.Config{}
|
||||
yaml.Unmarshal([]byte(cloudConfig), c) //nolint:errcheck
|
||||
for k, v := range c.Options {
|
||||
if k == "cc" {
|
||||
continue
|
||||
}
|
||||
r[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
func ManualInstall(c, device string, reboot, poweroff, strictValidations bool) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
@ -223,22 +212,21 @@ func RunInstall(c *config.Config) error {
|
||||
c.Install.Device = detectDevice()
|
||||
}
|
||||
|
||||
// Load the installation Config from the system
|
||||
installConfig, installSpec, err := elementalConfig.ReadInstallConfigFromAgentConfig(c)
|
||||
// Load the installation spec from the Config
|
||||
installSpec, err := config.ReadInstallSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := elementalUtils.TempFile(installConfig.Fs, "", "kairos-install-config-xxx.yaml")
|
||||
f, err := fsutils.TempFile(c.Fs, "", "kairos-install-config-xxx.yaml")
|
||||
if err != nil {
|
||||
installConfig.Logger.Error("Error creating temporal file for install config: %s\n", err.Error())
|
||||
c.Logger.Error("Error creating temporary file for install config: %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(f.Name())
|
||||
|
||||
ccstring, err := c.String()
|
||||
if err != nil {
|
||||
installConfig.Logger.Error("Error creating temporary file for install config: %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(f.Name(), []byte(ccstring), os.ModePerm)
|
||||
@ -247,6 +235,7 @@ func RunInstall(c *config.Config) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: This should not be neccessary
|
||||
installSpec.NoFormat = c.Install.NoFormat
|
||||
|
||||
// Set our cloud-init to the file we just created
|
||||
@ -267,18 +256,20 @@ func RunInstall(c *config.Config) error {
|
||||
}
|
||||
|
||||
// Add user's cloud-config (to run user defined "before-install" stages)
|
||||
installConfig.CloudInitPaths = append(installConfig.CloudInitPaths, installSpec.CloudInit...)
|
||||
c.CloudInitPaths = append(c.CloudInitPaths, installSpec.CloudInit...)
|
||||
|
||||
// Run pre-install stage
|
||||
_ = elementalUtils.RunStage(installConfig, "kairos-install.pre")
|
||||
_ = elementalUtils.RunStage(c, "kairos-install.pre")
|
||||
events.RunHookScript("/usr/bin/kairos-agent.install.pre.hook") //nolint:errcheck
|
||||
// Create the action
|
||||
installAction := action.NewInstallAction(installConfig, installSpec)
|
||||
installAction := action.NewInstallAction(c, installSpec)
|
||||
// Run it
|
||||
if err := installAction.Run(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
_ = elementalUtils.RunStage(c, "kairos-install.after")
|
||||
events.RunHookScript("/usr/bin/kairos-agent.install.after.hook") //nolint:errcheck
|
||||
|
||||
return hook.Run(*c, installSpec, hook.AfterInstall...)
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ import (
|
||||
"fmt"
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
"github.com/twpayne/go-vfs"
|
||||
"github.com/twpayne/go-vfs/vfst"
|
||||
@ -84,10 +84,10 @@ var _ = Describe("RunInstall", func() {
|
||||
fs, cleanup, err = vfst.NewTestFS(map[string]interface{}{"/proc/cmdline": ""})
|
||||
Expect(err).Should(BeNil())
|
||||
// Create tmp dir
|
||||
utils.MkdirAll(fs, "/tmp", constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, "/tmp", constants.DirPerm)
|
||||
// Create grub confg
|
||||
grubCfg := filepath.Join(constants.ActiveDir, constants.GrubConf)
|
||||
err = utils.MkdirAll(fs, filepath.Dir(grubCfg), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(grubCfg), constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
_, err = fs.Create(grubCfg)
|
||||
Expect(err).To(BeNil())
|
||||
@ -133,7 +133,7 @@ var _ = Describe("RunInstall", func() {
|
||||
}
|
||||
|
||||
device := "/some/device"
|
||||
err = utils.MkdirAll(fs, filepath.Dir(device), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(device), constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
_, err = fs.Create(device)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
@ -12,7 +12,6 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/cmd"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
sdk "github.com/kairos-io/kairos-sdk/bus"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
"github.com/kairos-io/kairos-sdk/machine"
|
||||
@ -78,7 +77,7 @@ func Reset(dir ...string) error {
|
||||
utils.SetEnv(c.Env)
|
||||
|
||||
// Load the installation Config from the cloud-config data
|
||||
resetConfig, resetSpec, err := elementalConfig.ReadResetConfigFromAgentConfig(c)
|
||||
resetSpec, err := config.ReadResetSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -92,11 +91,11 @@ func Reset(dir ...string) error {
|
||||
resetSpec.FormatOEM = o == "true"
|
||||
}
|
||||
if s := optionsFromEvent["strict"]; s != "" {
|
||||
resetConfig.Strict = s == "true"
|
||||
c.Strict = s == "true"
|
||||
}
|
||||
}
|
||||
|
||||
resetAction := action.NewResetAction(resetConfig, resetSpec)
|
||||
resetAction := action.NewResetAction(c, resetSpec)
|
||||
if err := resetAction.Run(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/bus"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/github"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
@ -100,7 +99,7 @@ func Upgrade(
|
||||
utils.SetEnv(c.Env)
|
||||
|
||||
// Load the upgrade Config from the system
|
||||
upgradeConfig, upgradeSpec, err := elementalConfig.ReadUpgradeConfigFromAgentConfig(c)
|
||||
upgradeSpec, err := config.ReadUpgradeSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -118,7 +117,7 @@ func Upgrade(
|
||||
return err
|
||||
}
|
||||
|
||||
upgradeAction := action.NewUpgradeAction(upgradeConfig, upgradeSpec)
|
||||
upgradeAction := action.NewUpgradeAction(c, upgradeSpec)
|
||||
|
||||
err = upgradeAction.Run()
|
||||
if err != nil {
|
||||
|
37
main.go
37
main.go
@ -15,8 +15,7 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/bus"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/common"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/webui"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-sdk/bundles"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
@ -279,7 +278,7 @@ E.g. kairos-agent install-bundle container:quay.io/kairos/kairos...
|
||||
Description: "Show the runtime configuration of the machine. It will scan the machine for all the configuration and will return the config file processed and found.",
|
||||
Aliases: []string{"s"},
|
||||
Action: func(c *cli.Context) error {
|
||||
config, err := config.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
||||
config, err := agentConfig.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -308,7 +307,7 @@ enabled: true`,
|
||||
Description: "It allows to navigate the YAML config file by searching with 'yq' style keywords as `config get k3s` to retrieve the k3s config block",
|
||||
Aliases: []string{"g"},
|
||||
Action: func(c *cli.Context) error {
|
||||
config, err := config.Scan(collector.Directories(configScanDir...), collector.NoLogs, collector.StrictValidation(c.Bool("strict-validation")))
|
||||
config, err := agentConfig.Scan(collector.Directories(configScanDir...), collector.NoLogs, collector.StrictValidation(c.Bool("strict-validation")))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -527,24 +526,20 @@ The validate command expects a configuration file as its only argument. Local fi
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
stage := c.Args().First()
|
||||
config, err := config.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg, err := elementalConfig.ReadConfigRunFromAgentConfig(config)
|
||||
cfg.Strict = c.Bool("strict")
|
||||
config, err := agentConfig.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
||||
config.Strict = c.Bool("strict")
|
||||
|
||||
if len(c.StringSlice("cloud-init-paths")) > 0 {
|
||||
cfg.CloudInitPaths = append(cfg.CloudInitPaths, c.StringSlice("cloud-init-paths")...)
|
||||
config.CloudInitPaths = append(config.CloudInitPaths, c.StringSlice("cloud-init-paths")...)
|
||||
}
|
||||
if c.Bool("debug") {
|
||||
cfg.Logger.SetLevel(logrus.DebugLevel)
|
||||
config.Logger.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
cfg.Logger.Errorf("Error reading config: %s\n", err)
|
||||
config.Logger.Errorf("Error reading config: %s\n", err)
|
||||
}
|
||||
return utils.RunStage(cfg, stage)
|
||||
return utils.RunStage(config, stage)
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -578,24 +573,16 @@ The validate command expects a configuration file as its only argument. Local fi
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid path %s", destination)
|
||||
}
|
||||
config, err := config.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
||||
config, err := agentConfig.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfg, err := elementalConfig.ReadConfigRunFromAgentConfig(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c.Bool("debug") {
|
||||
cfg.Logger.SetLevel(logrus.DebugLevel)
|
||||
}
|
||||
|
||||
cfg.Logger.Infof("Starting download and extraction for image %s to %s\n", image, destination)
|
||||
config.Logger.Infof("Starting download and extraction for image %s to %s\n", image, destination)
|
||||
e := v1.OCIImageExtractor{}
|
||||
if err = e.ExtractImage(image, destination, c.String("platform")); err != nil {
|
||||
return err
|
||||
}
|
||||
cfg.Logger.Infof("Image %s downloaded and extracted to %s correctly\n", image, destination)
|
||||
config.Logger.Infof("Image %s downloaded and extracted to %s correctly\n", image, destination)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
@ -17,13 +17,13 @@ limitations under the License.
|
||||
package action
|
||||
|
||||
import (
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
config "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
)
|
||||
|
||||
// Hook is RunStage wrapper that only adds logic to ignore errors
|
||||
// in case v1.Config.Strict is set to false
|
||||
func Hook(config *v1.Config, hook string) error {
|
||||
func Hook(config *config.Config, hook string) error {
|
||||
config.Logger.Infof("Running %s hook", hook)
|
||||
err := utils.RunStage(config, hook)
|
||||
if !config.Strict {
|
||||
@ -33,7 +33,7 @@ func Hook(config *v1.Config, hook string) error {
|
||||
}
|
||||
|
||||
// ChrootHook executes Hook inside a chroot environment
|
||||
func ChrootHook(config *v1.Config, hook string, chrootDir string, bindMounts map[string]string) (err error) {
|
||||
func ChrootHook(config *config.Config, hook string, chrootDir string, bindMounts map[string]string) (err error) {
|
||||
callback := func() error {
|
||||
return Hook(config, hook)
|
||||
}
|
||||
|
@ -18,7 +18,9 @@ package action
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
@ -107,11 +109,11 @@ func (i *InstallAction) createInstallStateYaml(sysMeta, recMeta interface{}) err
|
||||
}
|
||||
|
||||
type InstallAction struct {
|
||||
cfg *v1.Config
|
||||
cfg *config.Config
|
||||
spec *v1.InstallSpec
|
||||
}
|
||||
|
||||
func NewInstallAction(cfg *v1.Config, spec *v1.InstallSpec) *InstallAction {
|
||||
func NewInstallAction(cfg *config.Config, spec *v1.InstallSpec) *InstallAction {
|
||||
return &InstallAction{cfg: cfg, spec: spec}
|
||||
}
|
||||
|
||||
@ -259,7 +261,10 @@ func (i InstallAction) Run() (err error) {
|
||||
}
|
||||
|
||||
// If we want to eject the cd, create the required executable so the cd is ejected at shutdown
|
||||
if i.cfg.EjectCD && utils.BootedFrom(i.cfg.Runner, "cdroot") {
|
||||
out, _ := i.cfg.Runner.Run("cat", "/proc/cmdline")
|
||||
bootedFromCD := strings.Contains(string(out), "cdroot")
|
||||
|
||||
if i.cfg.EjectCD && bootedFromCD {
|
||||
i.cfg.Logger.Infof("Writing eject script")
|
||||
err = i.cfg.Fs.WriteFile("/usr/lib/systemd/system-shutdown/eject", []byte(cnst.EjectScript), 0744)
|
||||
if err != nil {
|
||||
|
@ -20,13 +20,14 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
conf "github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
@ -42,7 +43,7 @@ const partTmpl = `
|
||||
%d:%ss:%ss:2048s:ext4::type=83;`
|
||||
|
||||
var _ = Describe("Install action tests", func() {
|
||||
var config *v1.Config
|
||||
var config *agentConfig.Config
|
||||
var runner *v1mock.FakeRunner
|
||||
var fs vfs.FS
|
||||
var logger v1.Logger
|
||||
@ -69,15 +70,15 @@ var _ = Describe("Install action tests", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
cloudInit = &v1mock.FakeCloudInitRunner{}
|
||||
config = conf.NewConfig(
|
||||
conf.WithFs(fs),
|
||||
conf.WithRunner(runner),
|
||||
conf.WithLogger(logger),
|
||||
conf.WithMounter(mounter),
|
||||
conf.WithSyscall(syscall),
|
||||
conf.WithClient(client),
|
||||
conf.WithCloudInitRunner(cloudInit),
|
||||
conf.WithImageExtractor(extractor),
|
||||
config = agentConfig.NewConfig(
|
||||
agentConfig.WithFs(fs),
|
||||
agentConfig.WithRunner(runner),
|
||||
agentConfig.WithLogger(logger),
|
||||
agentConfig.WithMounter(mounter),
|
||||
agentConfig.WithSyscall(syscall),
|
||||
agentConfig.WithClient(client),
|
||||
agentConfig.WithCloudInitRunner(cloudInit),
|
||||
agentConfig.WithImageExtractor(extractor),
|
||||
)
|
||||
})
|
||||
|
||||
@ -94,7 +95,7 @@ var _ = Describe("Install action tests", func() {
|
||||
|
||||
BeforeEach(func() {
|
||||
device = "/some/device"
|
||||
err = utils.MkdirAll(fs, filepath.Dir(device), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(device), constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
_, err = fs.Create(device)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
@ -143,14 +144,14 @@ var _ = Describe("Install action tests", func() {
|
||||
}
|
||||
}
|
||||
// Need to create the IsoBaseTree, like if we are booting from iso
|
||||
err = utils.MkdirAll(fs, constants.IsoBaseTree, constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, constants.IsoBaseTree, constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
spec = conf.NewInstallSpec(config)
|
||||
spec = agentConfig.NewInstallSpec(config)
|
||||
spec.Active.Size = 16
|
||||
|
||||
grubCfg := filepath.Join(spec.Active.MountPoint, constants.GrubConf)
|
||||
err = utils.MkdirAll(fs, filepath.Dir(grubCfg), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(grubCfg), constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
_, err = fs.Create(grubCfg)
|
||||
Expect(err).To(BeNil())
|
||||
@ -215,7 +216,7 @@ var _ = Describe("Install action tests", func() {
|
||||
})
|
||||
|
||||
It("Sets the executable /run/cos/ejectcd so systemd can eject the cd on restart", func() {
|
||||
_ = utils.MkdirAll(fs, "/usr/lib/systemd/system-shutdown", constants.DirPerm)
|
||||
_ = fsutils.MkdirAll(fs, "/usr/lib/systemd/system-shutdown", constants.DirPerm)
|
||||
_, err := fs.Stat("/usr/lib/systemd/system-shutdown/eject")
|
||||
Expect(err).To(HaveOccurred())
|
||||
// Override cmdline to return like we are booting from cd
|
||||
@ -233,7 +234,7 @@ var _ = Describe("Install action tests", func() {
|
||||
})
|
||||
|
||||
It("ejectcd does nothing if we are not booting from cd", func() {
|
||||
_ = utils.MkdirAll(fs, "/usr/lib/systemd/system-shutdown", constants.DirPerm)
|
||||
_ = fsutils.MkdirAll(fs, "/usr/lib/systemd/system-shutdown", constants.DirPerm)
|
||||
_, err := fs.Stat("/usr/lib/systemd/system-shutdown/eject")
|
||||
Expect(err).To(HaveOccurred())
|
||||
spec.Target = device
|
||||
@ -265,7 +266,7 @@ var _ = Describe("Install action tests", func() {
|
||||
It("Successfully installs and adds remote cloud-config", Label("cloud-config"), func() {
|
||||
spec.Target = device
|
||||
spec.CloudInit = []string{"http://my.config.org"}
|
||||
utils.MkdirAll(fs, constants.OEMDir, constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, constants.OEMDir, constants.DirPerm)
|
||||
_, err := fs.Create(filepath.Join(constants.OEMDir, "90_custom.yaml"))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(installer.Run()).To(BeNil())
|
||||
|
@ -18,6 +18,7 @@ package action
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
@ -44,11 +45,11 @@ func (r *ResetAction) resetHook(hook string, chroot bool) error {
|
||||
}
|
||||
|
||||
type ResetAction struct {
|
||||
cfg *v1.Config
|
||||
cfg *agentConfig.Config
|
||||
spec *v1.ResetSpec
|
||||
}
|
||||
|
||||
func NewResetAction(cfg *v1.Config, spec *v1.ResetSpec) *ResetAction {
|
||||
func NewResetAction(cfg *agentConfig.Config, spec *v1.ResetSpec) *ResetAction {
|
||||
return &ResetAction{cfg: cfg, spec: spec}
|
||||
}
|
||||
|
||||
|
@ -20,13 +20,14 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
conf "github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
@ -37,7 +38,7 @@ import (
|
||||
)
|
||||
|
||||
var _ = Describe("Reset action tests", func() {
|
||||
var config *v1.Config
|
||||
var config *agentConfig.Config
|
||||
var runner *v1mock.FakeRunner
|
||||
var fs vfs.FS
|
||||
var logger v1.Logger
|
||||
@ -63,15 +64,15 @@ var _ = Describe("Reset action tests", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
cloudInit = &v1mock.FakeCloudInitRunner{}
|
||||
config = conf.NewConfig(
|
||||
conf.WithFs(fs),
|
||||
conf.WithRunner(runner),
|
||||
conf.WithLogger(logger),
|
||||
conf.WithMounter(mounter),
|
||||
conf.WithSyscall(syscall),
|
||||
conf.WithClient(client),
|
||||
conf.WithCloudInitRunner(cloudInit),
|
||||
conf.WithImageExtractor(extractor),
|
||||
config = agentConfig.NewConfig(
|
||||
agentConfig.WithFs(fs),
|
||||
agentConfig.WithRunner(runner),
|
||||
agentConfig.WithLogger(logger),
|
||||
agentConfig.WithMounter(mounter),
|
||||
agentConfig.WithSyscall(syscall),
|
||||
agentConfig.WithClient(client),
|
||||
agentConfig.WithCloudInitRunner(cloudInit),
|
||||
agentConfig.WithImageExtractor(extractor),
|
||||
)
|
||||
})
|
||||
|
||||
@ -87,7 +88,7 @@ var _ = Describe("Reset action tests", func() {
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
cmdFail = ""
|
||||
recoveryImg := filepath.Join(constants.RunningStateDir, "cOS", constants.RecoveryImgFile)
|
||||
err = utils.MkdirAll(fs, filepath.Dir(recoveryImg), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(recoveryImg), constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
_, err = fs.Create(recoveryImg)
|
||||
Expect(err).To(BeNil())
|
||||
@ -140,14 +141,14 @@ var _ = Describe("Reset action tests", func() {
|
||||
}
|
||||
}
|
||||
|
||||
spec, err = conf.NewResetSpec(config)
|
||||
spec, err = agentConfig.NewResetSpec(config)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Active.Source.IsEmpty()).To(BeFalse())
|
||||
|
||||
spec.Active.Size = 16
|
||||
|
||||
grubCfg := filepath.Join(spec.Active.MountPoint, spec.GrubConf)
|
||||
err = utils.MkdirAll(fs, filepath.Dir(grubCfg), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(grubCfg), constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
_, err = fs.Create(grubCfg)
|
||||
Expect(err).To(BeNil())
|
||||
@ -175,7 +176,7 @@ var _ = Describe("Reset action tests", func() {
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets from a squashfs recovery image", Label("channel"), func() {
|
||||
err := utils.MkdirAll(config.Fs, constants.IsoBaseTree, constants.DirPerm)
|
||||
err := fsutils.MkdirAll(config.Fs, constants.IsoBaseTree, constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
spec.Active.Source = v1.NewDirSrc(constants.IsoBaseTree)
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
|
@ -18,6 +18,8 @@ package action
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
@ -29,11 +31,11 @@ import (
|
||||
|
||||
// UpgradeAction represents the struct that will run the upgrade from start to finish
|
||||
type UpgradeAction struct {
|
||||
config *v1.Config
|
||||
config *agentConfig.Config
|
||||
spec *v1.UpgradeSpec
|
||||
}
|
||||
|
||||
func NewUpgradeAction(config *v1.Config, spec *v1.UpgradeSpec) *UpgradeAction {
|
||||
func NewUpgradeAction(config *agentConfig.Config, spec *v1.UpgradeSpec) *UpgradeAction {
|
||||
return &UpgradeAction{config: config, spec: spec}
|
||||
}
|
||||
|
||||
@ -154,7 +156,7 @@ func (u *UpgradeAction) Run() (err error) {
|
||||
persistentPart := u.spec.Partitions.Persistent
|
||||
if persistentPart != nil {
|
||||
// Create the dir otherwise the check for mounted dir fails
|
||||
_ = utils.MkdirAll(u.config.Fs, persistentPart.MountPoint, constants.DirPerm)
|
||||
_ = fsutils.MkdirAll(u.config.Fs, persistentPart.MountPoint, constants.DirPerm)
|
||||
if mnt, err := utils.IsMounted(u.config, persistentPart); !mnt && err == nil {
|
||||
u.Debug("mounting persistent partition")
|
||||
umount, err = e.MountRWPartition(persistentPart)
|
||||
@ -281,7 +283,7 @@ func (u *UpgradeAction) Run() (err error) {
|
||||
|
||||
// remove attempts to remove the given path. Does nothing if it doesn't exist
|
||||
func (u *UpgradeAction) remove(path string) error {
|
||||
if exists, _ := utils.Exists(u.config.Fs, path); exists {
|
||||
if exists, _ := fsutils.Exists(u.config.Fs, path); exists {
|
||||
u.Debug("[Cleanup] Removing %s", path)
|
||||
return u.config.Fs.RemoveAll(path)
|
||||
}
|
||||
|
@ -19,14 +19,14 @@ package action_test
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
conf "github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
@ -36,7 +36,7 @@ import (
|
||||
)
|
||||
|
||||
var _ = Describe("Runtime Actions", func() {
|
||||
var config *v1.Config
|
||||
var config *agentConfig.Config
|
||||
var runner *v1mock.FakeRunner
|
||||
var fs vfs.FS
|
||||
var logger v1.Logger
|
||||
@ -63,16 +63,16 @@ var _ = Describe("Runtime Actions", func() {
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
cloudInit = &v1mock.FakeCloudInitRunner{}
|
||||
config = conf.NewConfig(
|
||||
conf.WithFs(fs),
|
||||
conf.WithRunner(runner),
|
||||
conf.WithLogger(logger),
|
||||
conf.WithMounter(mounter),
|
||||
conf.WithSyscall(syscall),
|
||||
conf.WithClient(client),
|
||||
conf.WithCloudInitRunner(cloudInit),
|
||||
conf.WithImageExtractor(extractor),
|
||||
conf.WithPlatform("linux/amd64"),
|
||||
config = agentConfig.NewConfig(
|
||||
agentConfig.WithFs(fs),
|
||||
agentConfig.WithRunner(runner),
|
||||
agentConfig.WithLogger(logger),
|
||||
agentConfig.WithMounter(mounter),
|
||||
agentConfig.WithSyscall(syscall),
|
||||
agentConfig.WithClient(client),
|
||||
agentConfig.WithCloudInitRunner(cloudInit),
|
||||
agentConfig.WithImageExtractor(extractor),
|
||||
agentConfig.WithPlatform("linux/amd64"),
|
||||
)
|
||||
})
|
||||
|
||||
@ -98,8 +98,8 @@ var _ = Describe("Runtime Actions", func() {
|
||||
logger.SetLevel(logrus.DebugLevel)
|
||||
|
||||
// Create paths used by tests
|
||||
utils.MkdirAll(fs, fmt.Sprintf("%s/cOS", constants.RunningStateDir), constants.DirPerm)
|
||||
utils.MkdirAll(fs, fmt.Sprintf("%s/cOS", constants.LiveDir), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, fmt.Sprintf("%s/cOS", constants.RunningStateDir), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, fmt.Sprintf("%s/cOS", constants.LiveDir), constants.DirPerm)
|
||||
|
||||
mainDisk := block.Disk{
|
||||
Name: "device",
|
||||
@ -143,10 +143,10 @@ var _ = Describe("Runtime Actions", func() {
|
||||
Describe(fmt.Sprintf("Booting from %s", constants.ActiveLabel), Label("active_label"), func() {
|
||||
var err error
|
||||
BeforeEach(func() {
|
||||
spec, err = conf.NewUpgradeSpec(config)
|
||||
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
err = utils.MkdirAll(config.Fs, filepath.Join(spec.Active.MountPoint, "etc"), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(config.Fs, filepath.Join(spec.Active.MountPoint, "etc"), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
err = fs.WriteFile(
|
||||
@ -303,7 +303,7 @@ var _ = Describe("Runtime Actions", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
It("Successfully upgrades from directory", Label("directory"), func() {
|
||||
dirSrc, _ := utils.TempDir(fs, "", "elementalupgrade")
|
||||
dirSrc, _ := fsutils.TempDir(fs, "", "elementalupgrade")
|
||||
// Create the dir on real os as rsync works on the real os
|
||||
defer fs.RemoveAll(dirSrc)
|
||||
spec.Active.Source = v1.NewDirSrc(dirSrc)
|
||||
@ -346,10 +346,10 @@ var _ = Describe("Runtime Actions", func() {
|
||||
Describe(fmt.Sprintf("Booting from %s", constants.PassiveLabel), Label("passive_label"), func() {
|
||||
var err error
|
||||
BeforeEach(func() {
|
||||
spec, err = conf.NewUpgradeSpec(config)
|
||||
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
err = utils.MkdirAll(config.Fs, filepath.Join(spec.Active.MountPoint, "etc"), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(config.Fs, filepath.Join(spec.Active.MountPoint, "etc"), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
err = fs.WriteFile(
|
||||
@ -428,7 +428,7 @@ var _ = Describe("Runtime Actions", func() {
|
||||
err = fs.WriteFile(recoveryImgSquash, []byte("recovery"), constants.FilePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
spec, err = conf.NewUpgradeSpec(config)
|
||||
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
spec.Active.Size = 10
|
||||
spec.Passive.Size = 10
|
||||
@ -484,7 +484,7 @@ var _ = Describe("Runtime Actions", func() {
|
||||
|
||||
})
|
||||
It("Successfully upgrades recovery from directory", Label("directory"), func() {
|
||||
srcDir, _ := utils.TempDir(fs, "", "elemental")
|
||||
srcDir, _ := fsutils.TempDir(fs, "", "elemental")
|
||||
// create a random file on it
|
||||
_ = fs.WriteFile(fmt.Sprintf("%s/file.file", srcDir), []byte("something"), constants.FilePerm)
|
||||
|
||||
@ -513,7 +513,7 @@ var _ = Describe("Runtime Actions", func() {
|
||||
err = fs.WriteFile(recoveryImg, []byte("recovery"), constants.FilePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
spec, err = conf.NewUpgradeSpec(config)
|
||||
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
spec.Active.Size = 10
|
||||
@ -569,7 +569,7 @@ var _ = Describe("Runtime Actions", func() {
|
||||
}
|
||||
})
|
||||
It("Successfully upgrades recovery from directory", Label("directory"), func() {
|
||||
srcDir, _ := utils.TempDir(fs, "", "elemental")
|
||||
srcDir, _ := fsutils.TempDir(fs, "", "elemental")
|
||||
// create a random file on it
|
||||
_ = fs.WriteFile(fmt.Sprintf("%s/file.file", srcDir), []byte("something"), constants.FilePerm)
|
||||
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
@ -29,7 +30,6 @@ import (
|
||||
. "github.com/kairos-io/kairos-agent/v2/pkg/cloudinit"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
"github.com/twpayne/go-vfs/vfst"
|
||||
|
||||
@ -110,9 +110,9 @@ stages:
|
||||
logger = v1.NewBufferLogger(logs)
|
||||
|
||||
afs, cleanup, _ = vfst.NewTestFS(nil)
|
||||
err := utils.MkdirAll(afs, "/some/yip", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(afs, "/some/yip", constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
_ = utils.MkdirAll(afs, "/dev", constants.DirPerm)
|
||||
_ = fsutils.MkdirAll(afs, "/dev", constants.DirPerm)
|
||||
device = "/dev/device"
|
||||
_, err = afs.Create(device)
|
||||
Expect(err).To(BeNil())
|
||||
|
@ -2,17 +2,24 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/viper"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/cloudinit"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/http"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-sdk/bundles"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
"github.com/kairos-io/kairos-sdk/schema"
|
||||
yip "github.com/mudler/yip/pkg/schema"
|
||||
|
||||
"github.com/twpayne/go-vfs"
|
||||
"gopkg.in/yaml.v3"
|
||||
"k8s.io/mount-utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -36,6 +43,60 @@ type Install struct {
|
||||
BindMounts []string `yaml:"bind_mounts,omitempty"`
|
||||
}
|
||||
|
||||
func NewConfig(opts ...GenericOptions) *Config {
|
||||
log := v1.NewLogger()
|
||||
|
||||
hostPlatform, err := v1.NewPlatformFromArch(runtime.GOARCH)
|
||||
if err != nil {
|
||||
log.Errorf("error parsing default platform (%s): %s", runtime.GOARCH, err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
arch, err := golangArchToArch(runtime.GOARCH)
|
||||
if err != nil {
|
||||
log.Errorf("invalid arch: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
c := &Config{
|
||||
Fs: vfs.OSFS,
|
||||
Logger: log,
|
||||
Syscall: &v1.RealSyscall{},
|
||||
Client: http.NewClient(),
|
||||
Arch: arch,
|
||||
Platform: hostPlatform,
|
||||
SquashFsCompressionConfig: constants.GetDefaultSquashfsCompressionOptions(),
|
||||
ImageExtractor: v1.OCIImageExtractor{},
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(c)
|
||||
}
|
||||
|
||||
// delay runner creation after we have run over the options in case we use WithRunner
|
||||
if c.Runner == nil {
|
||||
c.Runner = &v1.RealRunner{Logger: c.Logger}
|
||||
}
|
||||
|
||||
// Now check if the runner has a logger inside, otherwise point our logger into it
|
||||
// This can happen if we set the WithRunner option as that doesn't set a logger
|
||||
if c.Runner.GetLogger() == nil {
|
||||
c.Runner.SetLogger(c.Logger)
|
||||
}
|
||||
|
||||
// Delay the yip runner creation, so we set the proper logger instead of blindly setting it to the logger we create
|
||||
// at the start of NewConfig, as WithLogger can be passed on init, and that would result in 2 different logger
|
||||
// instances, on the config.Logger and the other on config.CloudInitRunner
|
||||
if c.CloudInitRunner == nil {
|
||||
c.CloudInitRunner = cloudinit.NewYipCloudInitRunner(c.Logger, c.Runner, vfs.OSFS)
|
||||
}
|
||||
|
||||
if c.Mounter == nil {
|
||||
c.Mounter = mount.New(constants.MountBinary)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Install *Install `yaml:"install,omitempty"`
|
||||
collector.Config `yaml:"-"`
|
||||
@ -46,6 +107,148 @@ type Config struct {
|
||||
Bundles Bundles `yaml:"bundles,omitempty"`
|
||||
GrubOptions map[string]string `yaml:"grub_options,omitempty"`
|
||||
Env []string `yaml:"env,omitempty"`
|
||||
// From elemental
|
||||
Debug bool `yaml:"debug,omitempty" mapstructure:"debug"`
|
||||
Strict bool `yaml:"strict,omitempty" mapstructure:"strict"`
|
||||
CloudInitPaths []string `yaml:"cloud-init-paths,omitempty" mapstructure:"cloud-init-paths"`
|
||||
EjectCD bool `yaml:"eject-cd,omitempty" mapstructure:"eject-cd"`
|
||||
Logger v1.Logger
|
||||
Fs v1.FS
|
||||
Mounter mount.Interface
|
||||
Runner v1.Runner
|
||||
Syscall v1.SyscallInterface
|
||||
CloudInitRunner v1.CloudInitRunner
|
||||
ImageExtractor v1.ImageExtractor
|
||||
Client v1.HTTPClient
|
||||
Platform *v1.Platform `yaml:"platform,omitempty" mapstructure:"platform"`
|
||||
Cosign bool `yaml:"cosign,omitempty" mapstructure:"cosign"`
|
||||
Verify bool `yaml:"verify,omitempty" mapstructure:"verify"`
|
||||
CosignPubKey string `yaml:"cosign-key,omitempty" mapstructure:"cosign-key"`
|
||||
Arch string `yaml:"arch,omitempty" mapstructure:"arch"`
|
||||
SquashFsCompressionConfig []string `yaml:"squash-compression,omitempty" mapstructure:"squash-compression"`
|
||||
SquashFsNoCompression bool `yaml:"squash-no-compression,omitempty" mapstructure:"squash-no-compression"`
|
||||
}
|
||||
|
||||
// WriteInstallState writes the state.yaml file to the given state and recovery paths
|
||||
func (c Config) WriteInstallState(i *v1.InstallState, statePath, recoveryPath string) error {
|
||||
data, err := yaml.Marshal(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data = append([]byte("# Autogenerated file by elemental client, do not edit\n\n"), data...)
|
||||
|
||||
err = c.Fs.WriteFile(statePath, data, constants.FilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Fs.WriteFile(recoveryPath, data, constants.FilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadInstallState loads the state.yaml file and unmarshals it to an InstallState object
|
||||
func (c Config) LoadInstallState() (*v1.InstallState, error) {
|
||||
installState := &v1.InstallState{}
|
||||
data, err := c.Fs.ReadFile(filepath.Join(constants.RunningStateDir, constants.InstallStateFile))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = yaml.Unmarshal(data, installState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return installState, nil
|
||||
}
|
||||
|
||||
// Sanitize checks the consistency of the struct, returns error
|
||||
// if unsolvable inconsistencies are found
|
||||
func (c *Config) Sanitize() error {
|
||||
// If no squashcompression is set, zero the compression parameters
|
||||
// By default on NewConfig the SquashFsCompressionConfig is set to the default values, and then override
|
||||
// on config unmarshall.
|
||||
if c.SquashFsNoCompression {
|
||||
c.SquashFsCompressionConfig = []string{}
|
||||
}
|
||||
if c.Arch != "" {
|
||||
p, err := v1.NewPlatformFromArch(c.Arch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Platform = p
|
||||
}
|
||||
|
||||
if c.Platform == nil {
|
||||
p, err := v1.NewPlatformFromArch(runtime.GOARCH)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Platform = p
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GenericOptions func(a *Config)
|
||||
|
||||
func WithFs(fs v1.FS) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
r.Fs = fs
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogger(logger v1.Logger) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
r.Logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
func WithSyscall(syscall v1.SyscallInterface) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
r.Syscall = syscall
|
||||
}
|
||||
}
|
||||
|
||||
func WithMounter(mounter mount.Interface) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
r.Mounter = mounter
|
||||
}
|
||||
}
|
||||
|
||||
func WithRunner(runner v1.Runner) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
r.Runner = runner
|
||||
}
|
||||
}
|
||||
|
||||
func WithClient(client v1.HTTPClient) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
r.Client = client
|
||||
}
|
||||
}
|
||||
|
||||
func WithCloudInitRunner(ci v1.CloudInitRunner) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
r.CloudInitRunner = ci
|
||||
}
|
||||
}
|
||||
|
||||
func WithPlatform(platform string) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
p, err := v1.ParsePlatform(platform)
|
||||
if err == nil {
|
||||
r.Platform = p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithImageExtractor(extractor v1.ImageExtractor) func(r *Config) {
|
||||
return func(r *Config) {
|
||||
r.ImageExtractor = extractor
|
||||
}
|
||||
}
|
||||
|
||||
type Bundles []Bundle
|
||||
@ -113,7 +316,8 @@ func FilterKeys(d []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
func Scan(opts ...collector.Option) (c *Config, err error) {
|
||||
result := &Config{}
|
||||
// Init new config with some default options
|
||||
result := NewConfig()
|
||||
|
||||
o := &collector.Options{}
|
||||
if err := o.Apply(opts...); err != nil {
|
||||
@ -157,6 +361,13 @@ func Scan(opts ...collector.Option) (c *Config, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
// If we got debug enabled via cloud config, set it on viper so its available everywhere
|
||||
if result.Debug {
|
||||
viper.Set("debug", true)
|
||||
}
|
||||
// Config the logger
|
||||
configLogger(result.Logger, result.Fs)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@ -207,3 +418,16 @@ func MergeYAML(objs ...interface{}) ([]byte, error) {
|
||||
func AddHeader(header, data string) string {
|
||||
return fmt.Sprintf("%s\n%s", header, data)
|
||||
}
|
||||
|
||||
var errInvalidArch = fmt.Errorf("invalid arch")
|
||||
|
||||
func golangArchToArch(arch string) (string, error) {
|
||||
switch strings.ToLower(arch) {
|
||||
case constants.ArchAmd64:
|
||||
return constants.Archx86, nil
|
||||
case constants.ArchArm64:
|
||||
return constants.ArchArm64, nil
|
||||
default:
|
||||
return "", errInvalidArch
|
||||
}
|
||||
}
|
||||
|
@ -17,36 +17,22 @@ package config_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
v1mocks "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
"github.com/twpayne/go-vfs"
|
||||
"github.com/twpayne/go-vfs/vfst"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
. "github.com/kairos-io/kairos-sdk/schema"
|
||||
. "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
. "github.com/kairos-io/kairos-sdk/schema"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
type TConfig struct {
|
||||
Kairos struct {
|
||||
OtherKey string `yaml:"other_key"`
|
||||
NetworkToken string `yaml:"network_token"`
|
||||
} `yaml:"kairos"`
|
||||
}
|
||||
|
||||
var _ = Describe("Config", func() {
|
||||
var d string
|
||||
BeforeEach(func() {
|
||||
d, _ = os.MkdirTemp("", "xxxx")
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
if d != "" {
|
||||
os.RemoveAll(d)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
func getTagName(s string) string {
|
||||
if len(s) < 1 {
|
||||
return ""
|
||||
@ -59,7 +45,12 @@ func getTagName(s string) string {
|
||||
f := func(c rune) bool {
|
||||
return c == '"' || c == ','
|
||||
}
|
||||
return s[:strings.IndexFunc(s, f)]
|
||||
index := strings.IndexFunc(s, f)
|
||||
if index == -1 {
|
||||
return s
|
||||
}
|
||||
|
||||
return s[:index]
|
||||
}
|
||||
|
||||
func structContainsField(f, t string, str interface{}) bool {
|
||||
@ -118,4 +109,91 @@ var _ = Describe("Schema", func() {
|
||||
structFieldsContainedInOtherStruct(Bundle{}, BundleSchema{})
|
||||
})
|
||||
})
|
||||
Describe("Write and load installation state", func() {
|
||||
var config *Config
|
||||
var runner *v1mocks.FakeRunner
|
||||
var fs vfs.FS
|
||||
var mounter *v1mocks.ErrorMounter
|
||||
var cleanup func()
|
||||
var err error
|
||||
var dockerState, channelState *v1.ImageState
|
||||
var installState *v1.InstallState
|
||||
var statePath, recoveryPath string
|
||||
|
||||
BeforeEach(func() {
|
||||
runner = v1mocks.NewFakeRunner()
|
||||
mounter = v1mocks.NewErrorMounter()
|
||||
fs, cleanup, err = vfst.NewTestFS(map[string]interface{}{})
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
config = NewConfig(
|
||||
WithFs(fs),
|
||||
WithRunner(runner),
|
||||
WithMounter(mounter),
|
||||
)
|
||||
dockerState = &v1.ImageState{
|
||||
Source: v1.NewDockerSrc("registry.org/my/image:tag"),
|
||||
Label: "active_label",
|
||||
FS: "ext2",
|
||||
SourceMetadata: &v1.DockerImageMeta{
|
||||
Digest: "adadgadg",
|
||||
Size: 23452345,
|
||||
},
|
||||
}
|
||||
installState = &v1.InstallState{
|
||||
Date: "somedate",
|
||||
Partitions: map[string]*v1.PartitionState{
|
||||
"state": {
|
||||
FSLabel: "state_label",
|
||||
Images: map[string]*v1.ImageState{
|
||||
"active": dockerState,
|
||||
},
|
||||
},
|
||||
"recovery": {
|
||||
FSLabel: "state_label",
|
||||
Images: map[string]*v1.ImageState{
|
||||
"recovery": channelState,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
statePath = filepath.Join(constants.RunningStateDir, constants.InstallStateFile)
|
||||
recoveryPath = "/recoverypart/state.yaml"
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(recoveryPath), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(statePath), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
})
|
||||
AfterEach(func() {
|
||||
cleanup()
|
||||
})
|
||||
It("Writes and loads an installation data", func() {
|
||||
err = config.WriteInstallState(installState, statePath, recoveryPath)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
loadedInstallState, err := config.LoadInstallState()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
Expect(*loadedInstallState).To(Equal(*installState))
|
||||
})
|
||||
It("Fails writing to state partition", func() {
|
||||
err = fs.RemoveAll(filepath.Dir(statePath))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = config.WriteInstallState(installState, statePath, recoveryPath)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
It("Fails writing to recovery partition", func() {
|
||||
err = fs.RemoveAll(filepath.Dir(statePath))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = config.WriteInstallState(installState, statePath, recoveryPath)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
It("Fails loading state file", func() {
|
||||
err = config.WriteInstallState(installState, statePath, recoveryPath)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = fs.RemoveAll(filepath.Dir(statePath))
|
||||
_, err = config.LoadInstallState()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -14,156 +14,38 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package elementalConfig
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/common"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/cloudinit"
|
||||
agentConfig "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/http"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/sanity-io/litter"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/twpayne/go-vfs"
|
||||
"k8s.io/mount-utils"
|
||||
)
|
||||
|
||||
type GenericOptions func(a *v1.Config)
|
||||
|
||||
func WithFs(fs v1.FS) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
r.Fs = fs
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogger(logger v1.Logger) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
r.Logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
func WithSyscall(syscall v1.SyscallInterface) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
r.Syscall = syscall
|
||||
}
|
||||
}
|
||||
|
||||
func WithMounter(mounter mount.Interface) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
r.Mounter = mounter
|
||||
}
|
||||
}
|
||||
|
||||
func WithRunner(runner v1.Runner) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
r.Runner = runner
|
||||
}
|
||||
}
|
||||
|
||||
func WithClient(client v1.HTTPClient) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
r.Client = client
|
||||
}
|
||||
}
|
||||
|
||||
func WithCloudInitRunner(ci v1.CloudInitRunner) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
r.CloudInitRunner = ci
|
||||
}
|
||||
}
|
||||
|
||||
func WithPlatform(platform string) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
p, err := v1.ParsePlatform(platform)
|
||||
if err == nil {
|
||||
r.Platform = p
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithImageExtractor(extractor v1.ImageExtractor) func(r *v1.Config) {
|
||||
return func(r *v1.Config) {
|
||||
r.ImageExtractor = extractor
|
||||
}
|
||||
}
|
||||
|
||||
func NewConfig(opts ...GenericOptions) *v1.Config {
|
||||
log := v1.NewLogger()
|
||||
|
||||
defaultPlatform, err := v1.NewPlatformFromArch(runtime.GOARCH)
|
||||
if err != nil {
|
||||
log.Errorf("error parsing default platform (%s): %s", runtime.GOARCH, err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
arch, err := utils.GolangArchToArch(runtime.GOARCH)
|
||||
if err != nil {
|
||||
log.Errorf("invalid arch: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
c := &v1.Config{
|
||||
Fs: vfs.OSFS,
|
||||
Logger: log,
|
||||
Syscall: &v1.RealSyscall{},
|
||||
Client: http.NewClient(),
|
||||
Arch: arch,
|
||||
Platform: defaultPlatform,
|
||||
SquashFsCompressionConfig: constants.GetDefaultSquashfsCompressionOptions(),
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(c)
|
||||
}
|
||||
|
||||
// delay runner creation after we have run over the options in case we use WithRunner
|
||||
if c.Runner == nil {
|
||||
c.Runner = &v1.RealRunner{Logger: c.Logger}
|
||||
}
|
||||
|
||||
// Now check if the runner has a logger inside, otherwise point our logger into it
|
||||
// This can happen if we set the WithRunner option as that doesn't set a logger
|
||||
if c.Runner.GetLogger() == nil {
|
||||
c.Runner.SetLogger(c.Logger)
|
||||
}
|
||||
|
||||
// Delay the yip runner creation, so we set the proper logger instead of blindly setting it to the logger we create
|
||||
// at the start of NewConfig, as WithLogger can be passed on init, and that would result in 2 different logger
|
||||
// instances, on the config.Logger and the other on config.CloudInitRunner
|
||||
if c.CloudInitRunner == nil {
|
||||
c.CloudInitRunner = cloudinit.NewYipCloudInitRunner(c.Logger, c.Runner, vfs.OSFS)
|
||||
}
|
||||
|
||||
if c.Mounter == nil {
|
||||
c.Mounter = mount.New(constants.MountBinary)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// NewInstallSpec returns an InstallSpec struct all based on defaults and basic host checks (e.g. EFI vs BIOS)
|
||||
func NewInstallSpec(cfg *v1.Config) *v1.InstallSpec {
|
||||
func NewInstallSpec(cfg *Config) *v1.InstallSpec {
|
||||
var firmware string
|
||||
var recoveryImg, activeImg, passiveImg v1.Image
|
||||
|
||||
recoveryImgFile := filepath.Join(constants.LiveDir, constants.RecoverySquashFile)
|
||||
|
||||
// Check if current host has EFI firmware
|
||||
efiExists, _ := utils.Exists(cfg.Fs, constants.EfiDevice)
|
||||
efiExists, _ := fsutils.Exists(cfg.Fs, constants.EfiDevice)
|
||||
// Check the default ISO installation media is available
|
||||
isoRootExists, _ := utils.Exists(cfg.Fs, constants.IsoBaseTree)
|
||||
isoRootExists, _ := fsutils.Exists(cfg.Fs, constants.IsoBaseTree)
|
||||
// Check the default ISO recovery installation media is available)
|
||||
recoveryExists, _ := utils.Exists(cfg.Fs, recoveryImgFile)
|
||||
recoveryExists, _ := fsutils.Exists(cfg.Fs, recoveryImgFile)
|
||||
|
||||
if efiExists {
|
||||
firmware = v1.EFI
|
||||
@ -206,7 +88,7 @@ func NewInstallSpec(cfg *v1.Config) *v1.InstallSpec {
|
||||
return &v1.InstallSpec{
|
||||
Firmware: firmware,
|
||||
PartTable: v1.GPT,
|
||||
Partitions: NewInstallElementalParitions(),
|
||||
Partitions: NewInstallElementalPartitions(),
|
||||
GrubConf: constants.GrubConf,
|
||||
Tty: constants.DefaultTty,
|
||||
Active: activeImg,
|
||||
@ -215,9 +97,9 @@ func NewInstallSpec(cfg *v1.Config) *v1.InstallSpec {
|
||||
}
|
||||
}
|
||||
|
||||
func NewInstallElementalParitions() v1.ElementalPartitions {
|
||||
partitions := v1.ElementalPartitions{}
|
||||
partitions.OEM = &v1.Partition{
|
||||
func NewInstallElementalPartitions() v1.ElementalPartitions {
|
||||
pt := v1.ElementalPartitions{}
|
||||
pt.OEM = &v1.Partition{
|
||||
FilesystemLabel: constants.OEMLabel,
|
||||
Size: constants.OEMSize,
|
||||
Name: constants.OEMPartName,
|
||||
@ -226,7 +108,7 @@ func NewInstallElementalParitions() v1.ElementalPartitions {
|
||||
Flags: []string{},
|
||||
}
|
||||
|
||||
partitions.Recovery = &v1.Partition{
|
||||
pt.Recovery = &v1.Partition{
|
||||
FilesystemLabel: constants.RecoveryLabel,
|
||||
Size: constants.RecoverySize,
|
||||
Name: constants.RecoveryPartName,
|
||||
@ -235,7 +117,7 @@ func NewInstallElementalParitions() v1.ElementalPartitions {
|
||||
Flags: []string{},
|
||||
}
|
||||
|
||||
partitions.State = &v1.Partition{
|
||||
pt.State = &v1.Partition{
|
||||
FilesystemLabel: constants.StateLabel,
|
||||
Size: constants.StateSize,
|
||||
Name: constants.StatePartName,
|
||||
@ -244,7 +126,7 @@ func NewInstallElementalParitions() v1.ElementalPartitions {
|
||||
Flags: []string{},
|
||||
}
|
||||
|
||||
partitions.Persistent = &v1.Partition{
|
||||
pt.Persistent = &v1.Partition{
|
||||
FilesystemLabel: constants.PersistentLabel,
|
||||
Size: constants.PersistentSize,
|
||||
Name: constants.PersistentPartName,
|
||||
@ -252,11 +134,11 @@ func NewInstallElementalParitions() v1.ElementalPartitions {
|
||||
MountPoint: constants.PersistentDir,
|
||||
Flags: []string{},
|
||||
}
|
||||
return partitions
|
||||
return pt
|
||||
}
|
||||
|
||||
// NewUpgradeSpec returns an UpgradeSpec struct all based on defaults and current host state
|
||||
func NewUpgradeSpec(cfg *v1.Config) (*v1.UpgradeSpec, error) {
|
||||
func NewUpgradeSpec(cfg *Config) (*v1.UpgradeSpec, error) {
|
||||
var recLabel, recFs, recMnt string
|
||||
var active, passive, recovery v1.Image
|
||||
|
||||
@ -265,7 +147,7 @@ func NewUpgradeSpec(cfg *v1.Config) (*v1.UpgradeSpec, error) {
|
||||
cfg.Logger.Warnf("failed reading installation state: %s", err.Error())
|
||||
}
|
||||
|
||||
parts, err := utils.GetAllPartitions()
|
||||
parts, err := partitions.GetAllPartitions()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read host partitions")
|
||||
}
|
||||
@ -273,17 +155,17 @@ func NewUpgradeSpec(cfg *v1.Config) (*v1.UpgradeSpec, error) {
|
||||
|
||||
if ep.Recovery == nil {
|
||||
// We could have recovery in lvm which won't appear in ghw list
|
||||
ep.Recovery = utils.GetPartitionViaDM(cfg.Fs, constants.RecoveryLabel)
|
||||
ep.Recovery = partitions.GetPartitionViaDM(cfg.Fs, constants.RecoveryLabel)
|
||||
}
|
||||
|
||||
if ep.OEM == nil {
|
||||
// We could have OEM in lvm which won't appear in ghw list
|
||||
ep.OEM = utils.GetPartitionViaDM(cfg.Fs, constants.OEMLabel)
|
||||
ep.OEM = partitions.GetPartitionViaDM(cfg.Fs, constants.OEMLabel)
|
||||
}
|
||||
|
||||
if ep.Persistent == nil {
|
||||
// We could have persistent encrypted or in lvm which won't appear in ghw list
|
||||
ep.Persistent = utils.GetPartitionViaDM(cfg.Fs, constants.PersistentLabel)
|
||||
ep.Persistent = partitions.GetPartitionViaDM(cfg.Fs, constants.PersistentLabel)
|
||||
}
|
||||
|
||||
if ep.Recovery != nil {
|
||||
@ -291,7 +173,7 @@ func NewUpgradeSpec(cfg *v1.Config) (*v1.UpgradeSpec, error) {
|
||||
ep.Recovery.MountPoint = constants.RecoveryDir
|
||||
}
|
||||
|
||||
squashedRec, err := utils.HasSquashedRecovery(cfg, ep.Recovery)
|
||||
squashedRec, err := hasSquashedRecovery(cfg, ep.Recovery)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed checking for squashed recovery")
|
||||
}
|
||||
@ -361,23 +243,23 @@ func NewUpgradeSpec(cfg *v1.Config) (*v1.UpgradeSpec, error) {
|
||||
}
|
||||
|
||||
// NewResetSpec returns a ResetSpec struct all based on defaults and current host state
|
||||
func NewResetSpec(cfg *v1.Config) (*v1.ResetSpec, error) {
|
||||
func NewResetSpec(cfg *Config) (*v1.ResetSpec, error) {
|
||||
var imgSource *v1.ImageSource
|
||||
|
||||
//TODO find a way to pre-load current state values such as labels
|
||||
if !utils.BootedFrom(cfg.Runner, constants.RecoverySquashFile) &&
|
||||
!utils.BootedFrom(cfg.Runner, constants.SystemLabel) {
|
||||
if !BootedFrom(cfg.Runner, constants.RecoverySquashFile) &&
|
||||
!BootedFrom(cfg.Runner, constants.SystemLabel) {
|
||||
return nil, fmt.Errorf("reset can only be called from the recovery system")
|
||||
}
|
||||
|
||||
efiExists, _ := utils.Exists(cfg.Fs, constants.EfiDevice)
|
||||
efiExists, _ := fsutils.Exists(cfg.Fs, constants.EfiDevice)
|
||||
|
||||
installState, err := cfg.LoadInstallState()
|
||||
if err != nil {
|
||||
cfg.Logger.Warnf("failed reading installation state: %s", err.Error())
|
||||
}
|
||||
|
||||
parts, err := utils.GetAllPartitions()
|
||||
parts, err := partitions.GetAllPartitions()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read host partitions")
|
||||
}
|
||||
@ -403,7 +285,7 @@ func NewResetSpec(cfg *v1.Config) (*v1.ResetSpec, error) {
|
||||
|
||||
if ep.Recovery == nil {
|
||||
// We could have recovery in lvm which won't appear in ghw list
|
||||
ep.Recovery = utils.GetPartitionViaDM(cfg.Fs, constants.RecoveryLabel)
|
||||
ep.Recovery = partitions.GetPartitionViaDM(cfg.Fs, constants.RecoveryLabel)
|
||||
if ep.Recovery == nil {
|
||||
return nil, fmt.Errorf("recovery partition not found")
|
||||
}
|
||||
@ -422,7 +304,7 @@ func NewResetSpec(cfg *v1.Config) (*v1.ResetSpec, error) {
|
||||
ep.OEM.Name = constants.OEMPartName
|
||||
} else {
|
||||
// We could have oem in lvm which won't appear in ghw list
|
||||
ep.OEM = utils.GetPartitionViaDM(cfg.Fs, constants.OEMLabel)
|
||||
ep.OEM = partitions.GetPartitionViaDM(cfg.Fs, constants.OEMLabel)
|
||||
}
|
||||
|
||||
if ep.OEM == nil {
|
||||
@ -437,7 +319,7 @@ func NewResetSpec(cfg *v1.Config) (*v1.ResetSpec, error) {
|
||||
ep.Persistent.Name = constants.PersistentPartName
|
||||
} else {
|
||||
// We could have persistent encrypted or in lvm which won't appear in ghw list
|
||||
ep.Persistent = utils.GetPartitionViaDM(cfg.Fs, constants.PersistentLabel)
|
||||
ep.Persistent = partitions.GetPartitionViaDM(cfg.Fs, constants.PersistentLabel)
|
||||
}
|
||||
if ep.Persistent == nil {
|
||||
cfg.Logger.Warnf("no Persistent partition found")
|
||||
@ -446,11 +328,11 @@ func NewResetSpec(cfg *v1.Config) (*v1.ResetSpec, error) {
|
||||
recoveryImg := filepath.Join(constants.RunningStateDir, "cOS", constants.RecoveryImgFile)
|
||||
recoveryImg2 := filepath.Join(constants.RunningRecoveryStateDir, "cOS", constants.RecoveryImgFile)
|
||||
|
||||
if exists, _ := utils.Exists(cfg.Fs, recoveryImg); exists {
|
||||
if exists, _ := fsutils.Exists(cfg.Fs, recoveryImg); exists {
|
||||
imgSource = v1.NewFileSrc(recoveryImg)
|
||||
} else if exists, _ = utils.Exists(cfg.Fs, recoveryImg2); exists {
|
||||
} else if exists, _ = fsutils.Exists(cfg.Fs, recoveryImg2); exists {
|
||||
imgSource = v1.NewFileSrc(recoveryImg2)
|
||||
} else if exists, _ = utils.Exists(cfg.Fs, constants.IsoBaseTree); exists {
|
||||
} else if exists, _ = fsutils.Exists(cfg.Fs, constants.IsoBaseTree); exists {
|
||||
imgSource = v1.NewDirSrc(constants.IsoBaseTree)
|
||||
} else {
|
||||
imgSource = v1.NewEmptySrc()
|
||||
@ -484,35 +366,38 @@ func NewResetSpec(cfg *v1.Config) (*v1.ResetSpec, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ReadConfigRunFromAgentConfig reads the configuration directly from a given cloud config string
|
||||
func ReadConfigRunFromAgentConfig(c *agentConfig.Config) (*v1.Config, error) {
|
||||
cfg := NewConfig(WithLogger(v1.NewLogger()), WithImageExtractor(v1.OCIImageExtractor{}))
|
||||
var err error
|
||||
|
||||
ccString, err := c.Config.String()
|
||||
// ReadResetSpecFromConfig will return a proper v1.ResetSpec based on an agent Config
|
||||
func ReadResetSpecFromConfig(c *Config) (*v1.ResetSpec, error) {
|
||||
sp, err := ReadSpecFromCloudConfig(c, "reset")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &v1.ResetSpec{}, err
|
||||
}
|
||||
resetSpec := sp.(*v1.ResetSpec)
|
||||
return resetSpec, nil
|
||||
}
|
||||
|
||||
// Load any cloud-config values that override our default Config
|
||||
err = yaml.Unmarshal([]byte(ccString), &cfg)
|
||||
// ReadInstallSpecFromConfig will return a proper v1.InstallSpec based on an agent Config
|
||||
func ReadInstallSpecFromConfig(c *Config) (*v1.InstallSpec, error) {
|
||||
sp, err := ReadSpecFromCloudConfig(c, "install")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &v1.InstallSpec{}, err
|
||||
}
|
||||
// If we got debug enabled via cloud config, set it on viper so its available everywhere
|
||||
if cfg.Debug {
|
||||
viper.Set("debug", true)
|
||||
installSpec := sp.(*v1.InstallSpec)
|
||||
return installSpec, nil
|
||||
}
|
||||
configLogger(cfg.Logger, cfg.Fs)
|
||||
// Store the full cloud-config in here, so we can reuse it afterward for the spec
|
||||
cfg.FullCloudConfig = ccString
|
||||
err = cfg.Sanitize()
|
||||
cfg.Logger.Debugf("Full config loaded: %s", litter.Sdump(cfg))
|
||||
return cfg, err
|
||||
|
||||
// ReadUpgradeSpecFromConfig will return a proper v1.UpgradeSpec based on an agent Config
|
||||
func ReadUpgradeSpecFromConfig(c *Config) (*v1.UpgradeSpec, error) {
|
||||
sp, err := ReadSpecFromCloudConfig(c, "reset")
|
||||
if err != nil {
|
||||
return &v1.UpgradeSpec{}, err
|
||||
}
|
||||
upgradeSpec := sp.(*v1.UpgradeSpec)
|
||||
return upgradeSpec, nil
|
||||
}
|
||||
|
||||
// ReadSpecFromCloudConfig returns a v1.Spec for the given spec
|
||||
func ReadSpecFromCloudConfig(r *v1.Config, spec string) (v1.Spec, error) {
|
||||
func ReadSpecFromCloudConfig(r *Config, spec string) (v1.Spec, error) {
|
||||
var sp v1.Spec
|
||||
var err error
|
||||
|
||||
@ -531,8 +416,12 @@ func ReadSpecFromCloudConfig(r *v1.Config, spec string) (v1.Spec, error) {
|
||||
}
|
||||
|
||||
// Load the config into viper from the raw cloud config string
|
||||
ccString, err := r.String()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed initializing spec: %v", err)
|
||||
}
|
||||
viper.SetConfigType("yaml")
|
||||
viper.ReadConfig(strings.NewReader(r.FullCloudConfig))
|
||||
viper.ReadConfig(strings.NewReader(ccString))
|
||||
vp := viper.Sub(spec)
|
||||
if vp == nil {
|
||||
vp = viper.New()
|
||||
@ -546,47 +435,6 @@ func ReadSpecFromCloudConfig(r *v1.Config, spec string) (v1.Spec, error) {
|
||||
return sp, err
|
||||
}
|
||||
|
||||
// readConfigAndSpecFromAgentConfig will return the config and spec for the given action based off the agent Config
|
||||
func readConfigAndSpecFromAgentConfig(c *agentConfig.Config, action string) (*v1.Config, v1.Spec, error) {
|
||||
config, err := ReadConfigRunFromAgentConfig(c)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
spec, err := ReadSpecFromCloudConfig(config, action)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return config, spec, nil
|
||||
}
|
||||
|
||||
// ReadResetConfigFromAgentConfig will return a proper v1.Config and v1.ResetSpec based on an agent Config
|
||||
func ReadResetConfigFromAgentConfig(c *agentConfig.Config) (*v1.Config, *v1.ResetSpec, error) {
|
||||
config, spec, err := readConfigAndSpecFromAgentConfig(c, "reset")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
resetSpec := spec.(*v1.ResetSpec)
|
||||
return config, resetSpec, nil
|
||||
}
|
||||
|
||||
func ReadInstallConfigFromAgentConfig(c *agentConfig.Config) (*v1.Config, *v1.InstallSpec, error) {
|
||||
config, spec, err := readConfigAndSpecFromAgentConfig(c, "install")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
installSpec := spec.(*v1.InstallSpec)
|
||||
return config, installSpec, nil
|
||||
}
|
||||
|
||||
func ReadUpgradeConfigFromAgentConfig(c *agentConfig.Config) (*v1.Config, *v1.UpgradeSpec, error) {
|
||||
config, spec, err := readConfigAndSpecFromAgentConfig(c, "upgrade")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
upgradeSpec := spec.(*v1.UpgradeSpec)
|
||||
return config, upgradeSpec, nil
|
||||
}
|
||||
|
||||
func configLogger(log v1.Logger, vfs v1.FS) {
|
||||
// Set debug level
|
||||
if viper.GetBool("debug") {
|
||||
@ -676,3 +524,52 @@ func setDecoder(config *mapstructure.DecoderConfig) {
|
||||
// we got form configs.
|
||||
config.ZeroFields = true
|
||||
}
|
||||
|
||||
// BootedFrom will check if we are booting from the given label
|
||||
func BootedFrom(runner v1.Runner, label string) bool {
|
||||
out, _ := runner.Run("cat", "/proc/cmdline")
|
||||
return strings.Contains(string(out), label)
|
||||
}
|
||||
|
||||
// HasSquashedRecovery returns true if a squashed recovery image is found in the system
|
||||
func hasSquashedRecovery(config *Config, recovery *v1.Partition) (squashed bool, err error) {
|
||||
mountPoint := recovery.MountPoint
|
||||
if mnt, _ := isMounted(config, recovery); !mnt {
|
||||
tmpMountDir, err := fsutils.TempDir(config.Fs, "", "elemental")
|
||||
if err != nil {
|
||||
config.Logger.Errorf("failed creating temporary dir: %v", err)
|
||||
return false, err
|
||||
}
|
||||
defer config.Fs.RemoveAll(tmpMountDir) // nolint:errcheck
|
||||
err = config.Mounter.Mount(recovery.Path, tmpMountDir, "auto", []string{})
|
||||
if err != nil {
|
||||
config.Logger.Errorf("failed mounting recovery partition: %v", err)
|
||||
return false, err
|
||||
}
|
||||
mountPoint = tmpMountDir
|
||||
defer func() {
|
||||
err = config.Mounter.Unmount(tmpMountDir)
|
||||
if err != nil {
|
||||
squashed = false
|
||||
}
|
||||
}()
|
||||
}
|
||||
return fsutils.Exists(config.Fs, filepath.Join(mountPoint, "cOS", constants.RecoverySquashFile))
|
||||
}
|
||||
|
||||
func isMounted(config *Config, part *v1.Partition) (bool, error) {
|
||||
if part == nil {
|
||||
return false, fmt.Errorf("nil partition")
|
||||
}
|
||||
|
||||
if part.MountPoint == "" {
|
||||
return false, nil
|
||||
}
|
||||
// Using IsLikelyNotMountPoint seams to be safe as we are not checking
|
||||
// for bind mounts here
|
||||
notMnt, err := config.Mounter.IsLikelyNotMountPoint(part.MountPoint)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !notMnt, nil
|
||||
}
|
@ -14,11 +14,14 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package elementalConfig_test
|
||||
package config_test
|
||||
|
||||
import (
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"fmt"
|
||||
config "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
"github.com/sanity-io/litter"
|
||||
"github.com/sirupsen/logrus"
|
||||
"k8s.io/mount-utils"
|
||||
"os"
|
||||
@ -26,9 +29,7 @@ import (
|
||||
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
@ -46,7 +47,7 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
var sysc *v1mock.FakeSyscall
|
||||
var logger v1.Logger
|
||||
var ci *v1mock.FakeCloudInitRunner
|
||||
var c *v1.Config
|
||||
var c *config.Config
|
||||
BeforeEach(func() {
|
||||
fs, cleanup, err = vfst.NewTestFS(nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -56,15 +57,15 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
sysc = &v1mock.FakeSyscall{}
|
||||
logger = v1.NewNullLogger()
|
||||
ci = &v1mock.FakeCloudInitRunner{}
|
||||
c = elementalConfig.NewConfig(
|
||||
elementalConfig.WithFs(fs),
|
||||
elementalConfig.WithMounter(mounter),
|
||||
elementalConfig.WithRunner(runner),
|
||||
elementalConfig.WithSyscall(sysc),
|
||||
elementalConfig.WithLogger(logger),
|
||||
elementalConfig.WithCloudInitRunner(ci),
|
||||
elementalConfig.WithClient(client),
|
||||
elementalConfig.WithPlatform("linux/arm64"),
|
||||
c = config.NewConfig(
|
||||
config.WithFs(fs),
|
||||
config.WithMounter(mounter),
|
||||
config.WithRunner(runner),
|
||||
config.WithSyscall(sysc),
|
||||
config.WithLogger(logger),
|
||||
config.WithCloudInitRunner(ci),
|
||||
config.WithClient(client),
|
||||
config.WithPlatform("linux/arm64"),
|
||||
)
|
||||
})
|
||||
AfterEach(func() {
|
||||
@ -87,24 +88,24 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
fs, cleanup, err := vfst.NewTestFS(nil)
|
||||
defer cleanup()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
c := elementalConfig.NewConfig(
|
||||
elementalConfig.WithFs(fs),
|
||||
elementalConfig.WithMounter(mounter),
|
||||
c := config.NewConfig(
|
||||
config.WithFs(fs),
|
||||
config.WithMounter(mounter),
|
||||
)
|
||||
Expect(c.Fs).To(Equal(fs))
|
||||
Expect(c.Mounter).To(Equal(mounter))
|
||||
Expect(c.Runner).ToNot(BeNil())
|
||||
})
|
||||
It("defaults to sane platform if the platform is broken", func() {
|
||||
c = elementalConfig.NewConfig(
|
||||
elementalConfig.WithFs(fs),
|
||||
elementalConfig.WithMounter(mounter),
|
||||
elementalConfig.WithRunner(runner),
|
||||
elementalConfig.WithSyscall(sysc),
|
||||
elementalConfig.WithLogger(logger),
|
||||
elementalConfig.WithCloudInitRunner(ci),
|
||||
elementalConfig.WithClient(client),
|
||||
elementalConfig.WithPlatform("wwwwwww"),
|
||||
c = config.NewConfig(
|
||||
config.WithFs(fs),
|
||||
config.WithMounter(mounter),
|
||||
config.WithRunner(runner),
|
||||
config.WithSyscall(sysc),
|
||||
config.WithLogger(logger),
|
||||
config.WithCloudInitRunner(ci),
|
||||
config.WithClient(client),
|
||||
config.WithPlatform("wwwwwww"),
|
||||
)
|
||||
Expect(c.Platform.OS).To(Equal("linux"))
|
||||
Expect(c.Platform.Arch).To(Equal("x86_64"))
|
||||
@ -116,41 +117,41 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
runner := v1mock.NewFakeRunner()
|
||||
sysc := &v1mock.FakeSyscall{}
|
||||
logger := v1.NewNullLogger()
|
||||
c := elementalConfig.NewConfig(
|
||||
elementalConfig.WithRunner(runner),
|
||||
elementalConfig.WithSyscall(sysc),
|
||||
elementalConfig.WithLogger(logger),
|
||||
c := config.NewConfig(
|
||||
config.WithRunner(runner),
|
||||
config.WithSyscall(sysc),
|
||||
config.WithLogger(logger),
|
||||
)
|
||||
Expect(c.Mounter).To(Equal(mount.New(constants.MountBinary)))
|
||||
})
|
||||
})
|
||||
Describe("Config", func() {
|
||||
cfg := elementalConfig.NewConfig(elementalConfig.WithMounter(mounter))
|
||||
cfg := config.NewConfig(config.WithMounter(mounter))
|
||||
Expect(cfg.Mounter).To(Equal(mounter))
|
||||
Expect(cfg.Runner).NotTo(BeNil())
|
||||
})
|
||||
Describe("InstallSpec", func() {
|
||||
It("sets installation defaults from install efi media with recovery", Label("install", "efi"), func() {
|
||||
// Set EFI firmware detection
|
||||
err = utils.MkdirAll(fs, filepath.Dir(constants.EfiDevice), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(constants.EfiDevice), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(constants.EfiDevice)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
// Set ISO base tree detection
|
||||
err = utils.MkdirAll(fs, filepath.Dir(constants.IsoBaseTree), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(constants.IsoBaseTree), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(constants.IsoBaseTree)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
// Set recovery image detection detection
|
||||
recoveryImgFile := filepath.Join(constants.LiveDir, constants.RecoverySquashFile)
|
||||
err = utils.MkdirAll(fs, filepath.Dir(recoveryImgFile), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(recoveryImgFile), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(recoveryImgFile)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
spec := elementalConfig.NewInstallSpec(c)
|
||||
spec := config.NewInstallSpec(c)
|
||||
Expect(spec.Firmware).To(Equal(v1.EFI))
|
||||
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
||||
Expect(spec.Recovery.Source.Value()).To(Equal(recoveryImgFile))
|
||||
@ -166,12 +167,12 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
})
|
||||
It("sets installation defaults from install bios media without recovery", Label("install", "bios"), func() {
|
||||
// Set ISO base tree detection
|
||||
err = utils.MkdirAll(fs, filepath.Dir(constants.IsoBaseTree), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(constants.IsoBaseTree), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(constants.IsoBaseTree)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
spec := elementalConfig.NewInstallSpec(c)
|
||||
spec := config.NewInstallSpec(c)
|
||||
Expect(spec.Firmware).To(Equal(v1.BIOS))
|
||||
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
||||
Expect(spec.Recovery.Source.Value()).To(Equal(spec.Active.File))
|
||||
@ -186,7 +187,7 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
Expect(spec.Partitions.BIOS).NotTo(BeNil())
|
||||
})
|
||||
It("sets installation defaults without being on installation media", Label("install"), func() {
|
||||
spec := elementalConfig.NewInstallSpec(c)
|
||||
spec := config.NewInstallSpec(c)
|
||||
Expect(spec.Firmware).To(Equal(v1.BIOS))
|
||||
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
||||
Expect(spec.Recovery.Source.Value()).To(Equal(spec.Active.File))
|
||||
@ -245,18 +246,18 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
})
|
||||
It("sets reset defaults on efi from squashed recovery", func() {
|
||||
// Set EFI firmware detection
|
||||
err = utils.MkdirAll(fs, filepath.Dir(constants.EfiDevice), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(constants.EfiDevice), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(constants.EfiDevice)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
// Set squashfs detection
|
||||
err = utils.MkdirAll(fs, filepath.Dir(constants.IsoBaseTree), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(constants.IsoBaseTree), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(constants.IsoBaseTree)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
spec, err := elementalConfig.NewResetSpec(c)
|
||||
spec, err := config.NewResetSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
||||
Expect(spec.Partitions.EFI.MountPoint).To(Equal(constants.EfiDir))
|
||||
@ -264,17 +265,17 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
It("sets reset defaults on bios from non-squashed recovery", func() {
|
||||
// Set non-squashfs recovery image detection
|
||||
recoveryImg := filepath.Join(constants.RunningStateDir, "cOS", constants.RecoveryImgFile)
|
||||
err = utils.MkdirAll(fs, filepath.Dir(recoveryImg), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(recoveryImg), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(recoveryImg)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
spec, err := elementalConfig.NewResetSpec(c)
|
||||
spec, err := config.NewResetSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Active.Source.Value()).To(Equal(recoveryImg))
|
||||
})
|
||||
It("sets reset defaults on bios from unknown recovery", func() {
|
||||
spec, err := elementalConfig.NewResetSpec(c)
|
||||
spec, err := config.NewResetSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
||||
})
|
||||
@ -312,13 +313,13 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
ghwTest.Clean()
|
||||
})
|
||||
It("fails to set defaults if not booted from recovery", func() {
|
||||
_, err := elementalConfig.NewResetSpec(c)
|
||||
_, err := config.NewResetSpec(c)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("reset can only be called from the recovery system"))
|
||||
})
|
||||
It("fails to set defaults if no recovery partition detected", func() {
|
||||
bootedFrom = constants.SystemLabel
|
||||
_, err := elementalConfig.NewResetSpec(c)
|
||||
_, err := config.NewResetSpec(c)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("recovery partition not found"))
|
||||
})
|
||||
@ -333,19 +334,19 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
defer ghwTest.Clean()
|
||||
|
||||
bootedFrom = constants.SystemLabel
|
||||
_, err := elementalConfig.NewResetSpec(c)
|
||||
_, err := config.NewResetSpec(c)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("state partition not found"))
|
||||
})
|
||||
It("fails to set defaults if no efi partition on efi firmware", func() {
|
||||
// Set EFI firmware detection
|
||||
err = utils.MkdirAll(fs, filepath.Dir(constants.EfiDevice), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(constants.EfiDevice), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(constants.EfiDevice)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
bootedFrom = constants.SystemLabel
|
||||
_, err := elementalConfig.NewResetSpec(c)
|
||||
_, err := config.NewResetSpec(c)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("EFI partition not found"))
|
||||
})
|
||||
@ -394,12 +395,12 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
ghwTest.Clean()
|
||||
})
|
||||
It("sets upgrade defaults for active upgrade", func() {
|
||||
spec, err := elementalConfig.NewUpgradeSpec(c)
|
||||
spec, err := config.NewUpgradeSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
||||
})
|
||||
It("sets upgrade defaults for non-squashed recovery upgrade", func() {
|
||||
spec, err := elementalConfig.NewUpgradeSpec(c)
|
||||
spec, err := config.NewUpgradeSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Recovery.Source.IsEmpty()).To(BeTrue())
|
||||
Expect(spec.Recovery.FS).To(Equal(constants.LinuxImgFs))
|
||||
@ -408,12 +409,12 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
//Set squashed recovery detection
|
||||
mounter.Mount("device3", constants.LiveDir, "auto", []string{})
|
||||
img := filepath.Join(constants.LiveDir, "cOS", constants.RecoverySquashFile)
|
||||
err = utils.MkdirAll(fs, filepath.Dir(img), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(img), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(img)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
spec, err := elementalConfig.NewUpgradeSpec(c)
|
||||
spec, err := config.NewUpgradeSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Recovery.Source.IsEmpty()).To(BeTrue())
|
||||
Expect(spec.Recovery.FS).To(Equal(constants.SquashFs))
|
||||
@ -501,25 +502,25 @@ cloud-init-paths:
|
||||
It("Reads properly the cloud config for install", func() {
|
||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
installConfig, installSpec, err := elementalConfig.ReadInstallConfigFromAgentConfig(cfg)
|
||||
fmt.Print(litter.Sdump(cfg))
|
||||
installSpec, err := config.ReadInstallSpecFromConfig(cfg)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(installConfig.Strict).To(BeTrue())
|
||||
Expect(cfg.Strict).To(BeTrue())
|
||||
Expect(installSpec.GrubDefEntry).To(Equal("MyCustomOS"))
|
||||
Expect(installSpec.Active.Size).To(Equal(uint(666)))
|
||||
Expect(installConfig.CloudInitPaths).To(ContainElement("/what"))
|
||||
Expect(cfg.CloudInitPaths).To(ContainElement("/what"))
|
||||
|
||||
})
|
||||
It("Reads properly the cloud config for reset", func() {
|
||||
bootedFrom = constants.SystemLabel
|
||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||
config, err := elementalConfig.ReadConfigRunFromAgentConfig(cfg)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Override the config with our test params
|
||||
config.Runner = runner
|
||||
config.Fs = fs
|
||||
config.Mounter = mounter
|
||||
config.CloudInitRunner = ci
|
||||
spec, err := elementalConfig.ReadSpecFromCloudConfig(config, "reset")
|
||||
cfg.Runner = runner
|
||||
cfg.Fs = fs
|
||||
cfg.Mounter = mounter
|
||||
cfg.CloudInitRunner = ci
|
||||
spec, err := config.ReadSpecFromCloudConfig(cfg, "reset")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
resetSpec := spec.(*v1.ResetSpec)
|
||||
Expect(resetSpec.FormatPersistent).To(BeTrue())
|
||||
@ -528,32 +529,28 @@ cloud-init-paths:
|
||||
})
|
||||
It("Reads properly the cloud config for upgrade", func() {
|
||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||
config, err := elementalConfig.ReadConfigRunFromAgentConfig(cfg)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// Override the config with our test params
|
||||
config.Runner = runner
|
||||
config.Fs = fs
|
||||
config.Mounter = mounter
|
||||
config.CloudInitRunner = ci
|
||||
spec, err := elementalConfig.ReadSpecFromCloudConfig(config, "upgrade")
|
||||
cfg.Runner = runner
|
||||
cfg.Fs = fs
|
||||
cfg.Mounter = mounter
|
||||
cfg.CloudInitRunner = ci
|
||||
spec, err := config.ReadSpecFromCloudConfig(cfg, "upgrade")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
upgradeSpec := spec.(*v1.UpgradeSpec)
|
||||
Expect(upgradeSpec.RecoveryUpgrade).To(BeTrue())
|
||||
})
|
||||
It("Fails when a wrong action is read", func() {
|
||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||
config, err := elementalConfig.ReadConfigRunFromAgentConfig(cfg)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = elementalConfig.ReadSpecFromCloudConfig(config, "nope")
|
||||
_, err = config.ReadSpecFromCloudConfig(cfg, "nope")
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
It("Sets info level if its not on the cloud-config", func() {
|
||||
// Now again but with no config
|
||||
cfg, err := config.Scan(collector.Directories([]string{""}...), collector.NoLogs)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
installConfig, _, err := elementalConfig.ReadInstallConfigFromAgentConfig(cfg)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(installConfig.Logger.GetLevel()).To(Equal(logrus.InfoLevel))
|
||||
Expect(cfg.Logger.GetLevel()).To(Equal(logrus.InfoLevel))
|
||||
})
|
||||
It("Sets debug level if its on the cloud-config", func() {
|
||||
ccdata := []byte(`#cloud-config
|
||||
@ -563,11 +560,19 @@ debug: true
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
installConfig, _, err := elementalConfig.ReadInstallConfigFromAgentConfig(cfg)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(installConfig.Logger.GetLevel()).To(Equal(logrus.DebugLevel))
|
||||
Expect(cfg.Logger.GetLevel()).To(Equal(logrus.DebugLevel))
|
||||
|
||||
})
|
||||
})
|
||||
Describe("TestBootedFrom", Label("BootedFrom"), func() {
|
||||
It("returns true if we are booting from label FAKELABEL", func() {
|
||||
runner.ReturnValue = []byte("")
|
||||
Expect(config.BootedFrom(runner, "FAKELABEL")).To(BeFalse())
|
||||
})
|
||||
It("returns false if we are not booting from label FAKELABEL", func() {
|
||||
runner.ReturnValue = []byte("FAKELABEL")
|
||||
Expect(config.BootedFrom(runner, "FAKELABEL")).To(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
@ -19,21 +19,23 @@ package elemental
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/partitioner"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
)
|
||||
|
||||
// Elemental is the struct meant to self-contain most utils and actions related to Elemental, like installing or applying selinux
|
||||
type Elemental struct {
|
||||
config *v1.Config
|
||||
config *agentConfig.Config
|
||||
}
|
||||
|
||||
func NewElemental(config *v1.Config) *Elemental {
|
||||
func NewElemental(config *agentConfig.Config) *Elemental {
|
||||
return &Elemental{
|
||||
config: config,
|
||||
}
|
||||
@ -177,7 +179,7 @@ func (e Elemental) MountRWPartition(part *v1.Partition) (umount func() error, er
|
||||
// MountPartition mounts a partition with the given mount options
|
||||
func (e Elemental) MountPartition(part *v1.Partition, opts ...string) error {
|
||||
e.config.Logger.Debugf("Mounting partition %s", part.FilesystemLabel)
|
||||
err := utils.MkdirAll(e.config.Fs, part.MountPoint, cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(e.config.Fs, part.MountPoint, cnst.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -211,7 +213,7 @@ func (e Elemental) UnmountPartition(part *v1.Partition) error {
|
||||
// MountImage mounts an image with the given mount options
|
||||
func (e Elemental) MountImage(img *v1.Image, opts ...string) error {
|
||||
e.config.Logger.Debugf("Mounting image %s", img.Label)
|
||||
err := utils.MkdirAll(e.config.Fs, img.MountPoint, cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(e.config.Fs, img.MountPoint, cnst.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -251,7 +253,7 @@ func (e Elemental) UnmountImage(img *v1.Image) error {
|
||||
// CreateFileSystemImage creates the image file for config.target
|
||||
func (e Elemental) CreateFileSystemImage(img *v1.Image) error {
|
||||
e.config.Logger.Infof("Creating file system image %s", img.File)
|
||||
err := utils.MkdirAll(e.config.Fs, filepath.Dir(img.File), cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(e.config.Fs, filepath.Dir(img.File), cnst.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -298,7 +300,7 @@ func (e *Elemental) DeployImage(img *v1.Image, leaveMounted bool) (info interfac
|
||||
}
|
||||
} else {
|
||||
target = utils.GetTempDir(e.config, "")
|
||||
err := utils.MkdirAll(e.config.Fs, target, cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(e.config.Fs, target, cnst.DirPerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -374,7 +376,7 @@ func (e *Elemental) DumpSource(target string, imgSrc *v1.ImageSource) (info inte
|
||||
return nil, err
|
||||
}
|
||||
} else if imgSrc.IsFile() {
|
||||
err := utils.MkdirAll(e.config.Fs, filepath.Dir(target), cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(e.config.Fs, filepath.Dir(target), cnst.DirPerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -412,7 +414,7 @@ func (e *Elemental) CopyCloudConfig(cloudInit []string) (err error) {
|
||||
func (e *Elemental) SelinuxRelabel(rootDir string, raiseError bool) error {
|
||||
policyFile, err := utils.FindFileWithPrefix(e.config.Fs, filepath.Join(rootDir, cnst.SELinuxTargetedPolicyPath), "policy.")
|
||||
contextFile := filepath.Join(rootDir, cnst.SELinuxTargetedContextFile)
|
||||
contextExists, _ := utils.Exists(e.config.Fs, contextFile)
|
||||
contextExists, _ := fsutils.Exists(e.config.Fs, contextFile)
|
||||
|
||||
if err == nil && contextExists && utils.CommandExists("setfiles") {
|
||||
var out []byte
|
||||
@ -452,7 +454,7 @@ func (e *Elemental) CheckActiveDeployment(labels []string) bool {
|
||||
// in cnst.DownloadedIsoMnt
|
||||
func (e *Elemental) GetIso(iso string) (tmpDir string, err error) {
|
||||
//TODO support ISO download in persistent storage?
|
||||
tmpDir, err = utils.TempDir(e.config.Fs, "", "elemental")
|
||||
tmpDir, err = fsutils.TempDir(e.config.Fs, "", "elemental")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -470,7 +472,7 @@ func (e *Elemental) GetIso(iso string) (tmpDir string, err error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = utils.MkdirAll(e.config.Fs, isoMnt, cnst.DirPerm)
|
||||
err = fsutils.MkdirAll(e.config.Fs, isoMnt, cnst.DirPerm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -486,7 +488,7 @@ func (e *Elemental) GetIso(iso string) (tmpDir string, err error) {
|
||||
}()
|
||||
|
||||
e.config.Logger.Infof("Mounting squashfs image from iso into %s", rootfsMnt)
|
||||
err = utils.MkdirAll(e.config.Fs, rootfsMnt, cnst.DirPerm)
|
||||
err = fsutils.MkdirAll(e.config.Fs, rootfsMnt, cnst.DirPerm)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -505,7 +507,7 @@ func (e Elemental) UpdateSourcesFormDownloadedISO(workDir string, activeImg *v1.
|
||||
}
|
||||
if recoveryImg != nil {
|
||||
squashedImgSource := filepath.Join(isoMnt, cnst.RecoverySquashFile)
|
||||
if exists, _ := utils.Exists(e.config.Fs, squashedImgSource); exists {
|
||||
if exists, _ := fsutils.Exists(e.config.Fs, squashedImgSource); exists {
|
||||
recoveryImg.Source = v1.NewFileSrc(squashedImgSource)
|
||||
recoveryImg.FS = cnst.SquashFs
|
||||
} else if activeImg != nil {
|
||||
|
@ -19,6 +19,8 @@ package elemental_test
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@ -28,7 +30,6 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elemental"
|
||||
conf "github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
@ -49,7 +50,7 @@ func TestElementalSuite(t *testing.T) {
|
||||
}
|
||||
|
||||
var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
var config *v1.Config
|
||||
var config *agentConfig.Config
|
||||
var runner *v1mock.FakeRunner
|
||||
var logger v1.Logger
|
||||
var syscall v1.SyscallInterface
|
||||
@ -67,14 +68,14 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
logger = v1.NewNullLogger()
|
||||
fs, cleanup, _ = vfst.NewTestFS(nil)
|
||||
extractor = v1mock.NewFakeImageExtractor(logger)
|
||||
config = conf.NewConfig(
|
||||
conf.WithFs(fs),
|
||||
conf.WithRunner(runner),
|
||||
conf.WithLogger(logger),
|
||||
conf.WithMounter(mounter),
|
||||
conf.WithSyscall(syscall),
|
||||
conf.WithClient(client),
|
||||
conf.WithImageExtractor(extractor),
|
||||
config = agentConfig.NewConfig(
|
||||
agentConfig.WithFs(fs),
|
||||
agentConfig.WithRunner(runner),
|
||||
agentConfig.WithLogger(logger),
|
||||
agentConfig.WithMounter(mounter),
|
||||
agentConfig.WithSyscall(syscall),
|
||||
agentConfig.WithClient(client),
|
||||
agentConfig.WithImageExtractor(extractor),
|
||||
)
|
||||
})
|
||||
AfterEach(func() { cleanup() })
|
||||
@ -82,9 +83,9 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
var el *elemental.Elemental
|
||||
var parts v1.ElementalPartitions
|
||||
BeforeEach(func() {
|
||||
parts = conf.NewInstallElementalParitions()
|
||||
parts = agentConfig.NewInstallElementalPartitions()
|
||||
|
||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = fs.Create("/some/device")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -146,9 +147,9 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
var el *elemental.Elemental
|
||||
var parts v1.ElementalPartitions
|
||||
BeforeEach(func() {
|
||||
parts = conf.NewInstallElementalParitions()
|
||||
parts = agentConfig.NewInstallElementalPartitions()
|
||||
|
||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = fs.Create("/some/device")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -194,9 +195,9 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
var el *elemental.Elemental
|
||||
var parts v1.ElementalPartitions
|
||||
BeforeEach(func() {
|
||||
parts = conf.NewInstallElementalParitions()
|
||||
parts = agentConfig.NewInstallElementalPartitions()
|
||||
|
||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = fs.Create("/some/device")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -292,7 +293,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
MountPoint: cnst.ActiveDir,
|
||||
Source: v1.NewDirSrc(cnst.IsoBaseTree),
|
||||
}
|
||||
_ = utils.MkdirAll(fs, cnst.IsoBaseTree, cnst.DirPerm)
|
||||
_ = fsutils.MkdirAll(fs, cnst.IsoBaseTree, cnst.DirPerm)
|
||||
el = elemental.NewElemental(config)
|
||||
})
|
||||
|
||||
@ -341,10 +342,10 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
cInit = &v1mock.FakeCloudInitRunner{ExecStages: []string{}, Error: false}
|
||||
config.CloudInitRunner = cInit
|
||||
el = elemental.NewElemental(config)
|
||||
install = conf.NewInstallSpec(config)
|
||||
install = agentConfig.NewInstallSpec(config)
|
||||
install.Target = "/some/device"
|
||||
|
||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = fs.Create("/some/device")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -355,7 +356,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
var efiPartCmds, partCmds, biosPartCmds [][]string
|
||||
BeforeEach(func() {
|
||||
partNum, printOut = 0, printOutput
|
||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
efiPartCmds = [][]string{
|
||||
{
|
||||
@ -435,7 +436,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
Describe("Run with failures", func() {
|
||||
var runFunc func(cmd string, args ...string) ([]byte, error)
|
||||
BeforeEach(func() {
|
||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
partNum, printOut = 0, printOutput
|
||||
runFunc = func(cmd string, args ...string) ([]byte, error) {
|
||||
@ -486,9 +487,9 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
var img *v1.Image
|
||||
var cmdFail string
|
||||
BeforeEach(func() {
|
||||
sourceDir, err := utils.TempDir(fs, "", "elemental")
|
||||
sourceDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
destDir, err := utils.TempDir(fs, "", "elemental")
|
||||
destDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
cmdFail = ""
|
||||
el = elemental.NewElemental(config)
|
||||
@ -532,7 +533,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
sourceImg := "/source.img"
|
||||
_, err := fs.Create(sourceImg)
|
||||
Expect(err).To(BeNil())
|
||||
destDir, err := utils.TempDir(fs, "", "elemental")
|
||||
destDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||
Expect(err).To(BeNil())
|
||||
img.Source = v1.NewFileSrc(sourceImg)
|
||||
img.MountPoint = destDir
|
||||
@ -542,7 +543,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
sourceImg := "/source.img"
|
||||
_, err := fs.Create(sourceImg)
|
||||
Expect(err).To(BeNil())
|
||||
destDir, err := utils.TempDir(fs, "", "elemental")
|
||||
destDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||
Expect(err).To(BeNil())
|
||||
img.Source = v1.NewFileSrc(sourceImg)
|
||||
img.MountPoint = destDir
|
||||
@ -554,7 +555,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
sourceImg := "/source.img"
|
||||
_, err := fs.Create(sourceImg)
|
||||
Expect(err).To(BeNil())
|
||||
destDir, err := utils.TempDir(fs, "", "elemental")
|
||||
destDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||
Expect(err).To(BeNil())
|
||||
img.Source = v1.NewFileSrc(sourceImg)
|
||||
img.MountPoint = destDir
|
||||
@ -596,7 +597,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
BeforeEach(func() {
|
||||
var err error
|
||||
e = elemental.NewElemental(config)
|
||||
destDir, err = utils.TempDir(fs, "", "elemental")
|
||||
destDir, err = fsutils.TempDir(fs, "", "elemental")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
})
|
||||
It("Copies files from a directory source", func() {
|
||||
@ -682,7 +683,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
var relabelCmd []string
|
||||
BeforeEach(func() {
|
||||
// to mock the existance of setfiles command on non selinux hosts
|
||||
err := utils.MkdirAll(fs, "/usr/sbin", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/usr/sbin", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
sbin, err := fs.RawPath("/usr/sbin")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
@ -696,11 +697,11 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
|
||||
// to mock SELinux policy files
|
||||
policyFile = filepath.Join(constants.SELinuxTargetedPolicyPath, "policy.31")
|
||||
err = utils.MkdirAll(fs, filepath.Dir(constants.SELinuxTargetedContextFile), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(constants.SELinuxTargetedContextFile), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(constants.SELinuxTargetedContextFile)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = utils.MkdirAll(fs, constants.SELinuxTargetedPolicyPath, constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, constants.SELinuxTargetedPolicyPath, constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(policyFile)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
@ -749,12 +750,12 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
})
|
||||
It("relabels the given root-tree path", func() {
|
||||
contextFile := filepath.Join("/root", constants.SELinuxTargetedContextFile)
|
||||
err := utils.MkdirAll(fs, filepath.Dir(contextFile), constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, filepath.Dir(contextFile), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(contextFile)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
policyFile = filepath.Join("/root", policyFile)
|
||||
err = utils.MkdirAll(fs, filepath.Join("/root", constants.SELinuxTargetedPolicyPath), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Join("/root", constants.SELinuxTargetedPolicyPath), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create(policyFile)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
@ -774,7 +775,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
e = elemental.NewElemental(config)
|
||||
})
|
||||
It("Gets the iso and returns the temporary where it is stored", func() {
|
||||
tmpDir, err := utils.TempDir(fs, "", "elemental-test")
|
||||
tmpDir, err := fsutils.TempDir(fs, "", "elemental-test")
|
||||
Expect(err).To(BeNil())
|
||||
err = fs.WriteFile(fmt.Sprintf("%s/fake.iso", tmpDir), []byte("Hi"), cnst.FilePerm)
|
||||
Expect(err).To(BeNil())
|
||||
@ -782,7 +783,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
isoDir, err := e.GetIso(iso)
|
||||
Expect(err).To(BeNil())
|
||||
// Confirm that the iso is stored in isoDir
|
||||
utils.Exists(fs, filepath.Join(isoDir, "cOs.iso"))
|
||||
fsutils.Exists(fs, filepath.Join(isoDir, "cOs.iso"))
|
||||
})
|
||||
It("Fails if it cant find the iso", func() {
|
||||
iso := "whatever"
|
||||
@ -792,7 +793,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
})
|
||||
It("Fails if it cannot mount the iso", func() {
|
||||
mounter.ErrorOnMount = true
|
||||
tmpDir, err := utils.TempDir(fs, "", "elemental-test")
|
||||
tmpDir, err := fsutils.TempDir(fs, "", "elemental-test")
|
||||
Expect(err).To(BeNil())
|
||||
err = fs.WriteFile(fmt.Sprintf("%s/fake.iso", tmpDir), []byte("Hi"), cnst.FilePerm)
|
||||
Expect(err).To(BeNil())
|
||||
@ -831,7 +832,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
It("updates recovery only image", func() {
|
||||
recoveryImg = &v1.Image{}
|
||||
isoMnt := "/some/dir/iso"
|
||||
err := utils.MkdirAll(fs, isoMnt, cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, isoMnt, cnst.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
recoverySquash := filepath.Join(isoMnt, cnst.RecoverySquashFile)
|
||||
_, err = fs.Create(recoverySquash)
|
||||
@ -883,7 +884,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
Expect(runner.CmdsMatch([][]string{{"grub2-editenv"}})).NotTo(BeNil())
|
||||
})
|
||||
It("loads /etc/os-release on empty default entry", func() {
|
||||
err := utils.MkdirAll(config.Fs, "/imgMountPoint/etc", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(config.Fs, "/imgMountPoint/etc", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = config.Fs.WriteFile("/imgMountPoint/etc/os-release", []byte("GRUB_ENTRY_NAME=test"), constants.FilePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
@ -904,7 +905,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
||||
})
|
||||
Describe("FindKernelInitrd", Label("find"), func() {
|
||||
BeforeEach(func() {
|
||||
err := utils.MkdirAll(fs, "/path/boot", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/path/boot", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
})
|
||||
It("finds kernel and initrd files", func() {
|
||||
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
Copyright © 2022 SUSE LLC
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package elementalConfig_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestTypes(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "config initializer test suite")
|
||||
}
|
@ -19,13 +19,14 @@ package partitioner
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
"github.com/twpayne/go-vfs"
|
||||
)
|
||||
|
||||
@ -327,7 +328,7 @@ func (dev Disk) FindPartitionDevice(partNum int) (string, error) {
|
||||
for tries := 0; tries <= partitionTries; tries++ {
|
||||
dev.logger.Debugf("Trying to find the partition device %d of device %s (try number %d)", partNum, dev, tries+1)
|
||||
_, _ = dev.runner.Run("udevadm", "settle")
|
||||
if exists, _ := utils.Exists(dev.fs, device); exists {
|
||||
if exists, _ := fsutils.Exists(dev.fs, device); exists {
|
||||
return device, nil
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
@ -401,7 +402,7 @@ func (dev Disk) expandFilesystem(device string) (string, error) {
|
||||
var out []byte
|
||||
var err error
|
||||
|
||||
fs, err := utils.GetPartitionFS(device)
|
||||
fs, err := partitions.GetPartitionFS(device)
|
||||
if err != nil {
|
||||
return fs, err
|
||||
}
|
||||
@ -419,7 +420,7 @@ func (dev Disk) expandFilesystem(device string) (string, error) {
|
||||
}
|
||||
case "xfs":
|
||||
// to grow an xfs fs it needs to be mounted :/
|
||||
tmpDir, err := utils.TempDir(dev.fs, "", "partitioner")
|
||||
tmpDir, err := fsutils.TempDir(dev.fs, "", "partitioner")
|
||||
defer func(fs v1.FS, path string) {
|
||||
_ = fs.RemoveAll(path)
|
||||
}(dev.fs, tmpDir)
|
||||
|
@ -18,13 +18,13 @@ package partitioner_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"testing"
|
||||
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
part "github.com/kairos-io/kairos-agent/v2/pkg/partitioner"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
mocks "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
@ -211,7 +211,7 @@ var _ = Describe("Partitioner", Label("disk", "partition", "partitioner"), func(
|
||||
BeforeEach(func() {
|
||||
fs, cleanup, _ = vfst.NewTestFS(nil)
|
||||
|
||||
err := utils.MkdirAll(fs, "/dev", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/dev", constants.DirPerm)
|
||||
Expect(err).To(BeNil())
|
||||
_, err = fs.Create("/dev/device")
|
||||
Expect(err).To(BeNil())
|
||||
|
@ -19,12 +19,10 @@ package v1
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
"gopkg.in/yaml.v3"
|
||||
"k8s.io/mount-utils"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -43,94 +41,6 @@ type Spec interface {
|
||||
ShouldShutdown() bool
|
||||
}
|
||||
|
||||
// Config is the struct that includes basic and generic configuration of elemental binary runtime.
|
||||
// It mostly includes the interfaces used around many methods in elemental code
|
||||
type Config struct {
|
||||
Debug bool `yaml:"debug,omitempty" mapstructure:"debug"`
|
||||
Strict bool `yaml:"strict,omitempty" mapstructure:"strict"`
|
||||
CloudInitPaths []string `yaml:"cloud-init-paths,omitempty" mapstructure:"cloud-init-paths"`
|
||||
EjectCD bool `yaml:"eject-cd,omitempty" mapstructure:"eject-cd"`
|
||||
FullCloudConfig string // Stores the full cloud config used to generate the spec afterwards
|
||||
Logger Logger
|
||||
Fs FS
|
||||
Mounter mount.Interface
|
||||
Runner Runner
|
||||
Syscall SyscallInterface
|
||||
CloudInitRunner CloudInitRunner
|
||||
ImageExtractor ImageExtractor
|
||||
Client HTTPClient
|
||||
Platform *Platform `yaml:"platform,omitempty" mapstructure:"platform"`
|
||||
Cosign bool `yaml:"cosign,omitempty" mapstructure:"cosign"`
|
||||
Verify bool `yaml:"verify,omitempty" mapstructure:"verify"`
|
||||
CosignPubKey string `yaml:"cosign-key,omitempty" mapstructure:"cosign-key"`
|
||||
Arch string `yaml:"arch,omitempty" mapstructure:"arch"`
|
||||
SquashFsCompressionConfig []string `yaml:"squash-compression,omitempty" mapstructure:"squash-compression"`
|
||||
SquashFsNoCompression bool `yaml:"squash-no-compression,omitempty" mapstructure:"squash-no-compression"`
|
||||
}
|
||||
|
||||
// WriteInstallState writes the state.yaml file to the given state and recovery paths
|
||||
func (c Config) WriteInstallState(i *InstallState, statePath, recoveryPath string) error {
|
||||
data, err := yaml.Marshal(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data = append([]byte("# Autogenerated file by elemental client, do not edit\n\n"), data...)
|
||||
|
||||
err = c.Fs.WriteFile(statePath, data, constants.FilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Fs.WriteFile(recoveryPath, data, constants.FilePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadInstallState loads the state.yaml file and unmarshals it to an InstallState object
|
||||
func (c Config) LoadInstallState() (*InstallState, error) {
|
||||
installState := &InstallState{}
|
||||
data, err := c.Fs.ReadFile(filepath.Join(constants.RunningStateDir, constants.InstallStateFile))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = yaml.Unmarshal(data, installState)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return installState, nil
|
||||
}
|
||||
|
||||
// Sanitize checks the consistency of the struct, returns error
|
||||
// if unsolvable inconsistencies are found
|
||||
func (c *Config) Sanitize() error {
|
||||
// If no squashcompression is set, zero the compression parameters
|
||||
// By default on NewConfig the SquashFsCompressionConfig is set to the default values, and then override
|
||||
// on config unmarshall.
|
||||
if c.SquashFsNoCompression {
|
||||
c.SquashFsCompressionConfig = []string{}
|
||||
}
|
||||
if c.Arch != "" {
|
||||
p, err := NewPlatformFromArch(c.Arch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Platform = p
|
||||
}
|
||||
|
||||
if c.Platform == nil {
|
||||
p, err := NewPlatformFromArch(runtime.GOARCH)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.Platform = p
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InstallSpec struct represents all the installation action details
|
||||
type InstallSpec struct {
|
||||
Target string `yaml:"device,omitempty" mapstructure:"device"`
|
||||
|
@ -17,108 +17,13 @@ limitations under the License.
|
||||
package v1_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
conf "github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mocks "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs"
|
||||
"github.com/twpayne/go-vfs/vfst"
|
||||
)
|
||||
|
||||
var _ = Describe("Types", Label("types", "config"), func() {
|
||||
Describe("Write and load installation state", func() {
|
||||
var config *v1.Config
|
||||
var runner *v1mocks.FakeRunner
|
||||
var fs vfs.FS
|
||||
var mounter *v1mocks.ErrorMounter
|
||||
var cleanup func()
|
||||
var err error
|
||||
var dockerState, channelState *v1.ImageState
|
||||
var installState *v1.InstallState
|
||||
var statePath, recoveryPath string
|
||||
|
||||
BeforeEach(func() {
|
||||
runner = v1mocks.NewFakeRunner()
|
||||
mounter = v1mocks.NewErrorMounter()
|
||||
fs, cleanup, err = vfst.NewTestFS(map[string]interface{}{})
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
config = conf.NewConfig(
|
||||
conf.WithFs(fs),
|
||||
conf.WithRunner(runner),
|
||||
conf.WithMounter(mounter),
|
||||
)
|
||||
dockerState = &v1.ImageState{
|
||||
Source: v1.NewDockerSrc("registry.org/my/image:tag"),
|
||||
Label: "active_label",
|
||||
FS: "ext2",
|
||||
SourceMetadata: &v1.DockerImageMeta{
|
||||
Digest: "adadgadg",
|
||||
Size: 23452345,
|
||||
},
|
||||
}
|
||||
installState = &v1.InstallState{
|
||||
Date: "somedate",
|
||||
Partitions: map[string]*v1.PartitionState{
|
||||
"state": {
|
||||
FSLabel: "state_label",
|
||||
Images: map[string]*v1.ImageState{
|
||||
"active": dockerState,
|
||||
},
|
||||
},
|
||||
"recovery": {
|
||||
FSLabel: "state_label",
|
||||
Images: map[string]*v1.ImageState{
|
||||
"recovery": channelState,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
statePath = filepath.Join(constants.RunningStateDir, constants.InstallStateFile)
|
||||
recoveryPath = "/recoverypart/state.yaml"
|
||||
err = utils.MkdirAll(fs, filepath.Dir(recoveryPath), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = utils.MkdirAll(fs, filepath.Dir(statePath), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
})
|
||||
AfterEach(func() {
|
||||
cleanup()
|
||||
})
|
||||
It("Writes and loads an installation data", func() {
|
||||
err = config.WriteInstallState(installState, statePath, recoveryPath)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
loadedInstallState, err := config.LoadInstallState()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
Expect(*loadedInstallState).To(Equal(*installState))
|
||||
})
|
||||
It("Fails writing to state partition", func() {
|
||||
err = fs.RemoveAll(filepath.Dir(statePath))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = config.WriteInstallState(installState, statePath, recoveryPath)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
It("Fails writing to recovery partition", func() {
|
||||
err = fs.RemoveAll(filepath.Dir(statePath))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = config.WriteInstallState(installState, statePath, recoveryPath)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
It("Fails loading state file", func() {
|
||||
err = config.WriteInstallState(installState, statePath, recoveryPath)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = fs.RemoveAll(filepath.Dir(statePath))
|
||||
_, err = config.LoadInstallState()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
})
|
||||
Describe("ElementalPartitions", func() {
|
||||
var p v1.PartitionList
|
||||
var ep v1.ElementalPartitions
|
||||
@ -319,151 +224,4 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
Expect(p.GetByName("nonexistent")).To(BeNil())
|
||||
})
|
||||
})
|
||||
Describe("Config", func() {
|
||||
It("runs sanitize method", func() {
|
||||
cfg := elementalConfig.NewConfig(elementalConfig.WithMounter(v1mocks.NewErrorMounter()))
|
||||
cfg.Verify = true
|
||||
|
||||
err := cfg.Sanitize()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
})
|
||||
})
|
||||
Describe("InstallSpec", func() {
|
||||
var spec *v1.InstallSpec
|
||||
|
||||
BeforeEach(func() {
|
||||
cfg := elementalConfig.NewConfig(elementalConfig.WithMounter(v1mocks.NewErrorMounter()))
|
||||
spec = elementalConfig.NewInstallSpec(cfg)
|
||||
})
|
||||
Describe("sanitize", func() {
|
||||
It("runs method", func() {
|
||||
Expect(spec.Partitions.EFI).To(BeNil())
|
||||
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
||||
|
||||
// Creates firmware partitions
|
||||
spec.Active.Source = v1.NewDirSrc("/dir")
|
||||
spec.Firmware = v1.EFI
|
||||
err := spec.Sanitize()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Partitions.EFI).NotTo(BeNil())
|
||||
|
||||
// Sets recovery image file to squashfs file
|
||||
spec.Recovery.FS = constants.SquashFs
|
||||
err = spec.Sanitize()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Recovery.File).To(ContainSubstring(constants.RecoverySquashFile))
|
||||
|
||||
// Sets recovery image file to img file
|
||||
spec.Recovery.FS = constants.LinuxImgFs
|
||||
err = spec.Sanitize()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Recovery.File).To(ContainSubstring(constants.RecoveryImgFile))
|
||||
|
||||
// Fails without state partition
|
||||
spec.Partitions.State = nil
|
||||
err = spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
|
||||
// Fails without an install source
|
||||
spec.Active.Source = v1.NewEmptySrc()
|
||||
err = spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
Describe("with extra partitions", func() {
|
||||
BeforeEach(func() {
|
||||
// Set a source for the install
|
||||
spec.Active.Source = v1.NewDirSrc("/dir")
|
||||
})
|
||||
It("fails if persistent and an extra partition have size == 0", func() {
|
||||
spec.ExtraPartitions = append(spec.ExtraPartitions, &v1.Partition{Size: 0})
|
||||
err := spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("both persistent partition and extra partitions have size set to 0"))
|
||||
})
|
||||
It("fails if more than one extra partition has size == 0", func() {
|
||||
spec.Partitions.Persistent.Size = 10
|
||||
spec.ExtraPartitions = append(spec.ExtraPartitions, &v1.Partition{Name: "1", Size: 0})
|
||||
spec.ExtraPartitions = append(spec.ExtraPartitions, &v1.Partition{Name: "2", Size: 0})
|
||||
err := spec.Sanitize()
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("more than one extra partition has its size set to 0"))
|
||||
})
|
||||
It("does not fail if persistent size is > 0 and an extra partition has size == 0", func() {
|
||||
spec.ExtraPartitions = append(spec.ExtraPartitions, &v1.Partition{Size: 0})
|
||||
spec.Partitions.Persistent.Size = 10
|
||||
err := spec.Sanitize()
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
Describe("ResetSpec", func() {
|
||||
It("runs sanitize method", func() {
|
||||
spec := &v1.ResetSpec{
|
||||
Active: v1.Image{
|
||||
Source: v1.NewDirSrc("/dir"),
|
||||
},
|
||||
Partitions: v1.ElementalPartitions{
|
||||
State: &v1.Partition{
|
||||
MountPoint: "mountpoint",
|
||||
},
|
||||
},
|
||||
}
|
||||
err := spec.Sanitize()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
//Fails on missing state partition
|
||||
spec.Partitions.State = nil
|
||||
err = spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
|
||||
//Fails on empty source
|
||||
spec.Active.Source = v1.NewEmptySrc()
|
||||
err = spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
})
|
||||
Describe("UpgradeSpec", func() {
|
||||
It("runs sanitize method", func() {
|
||||
spec := &v1.UpgradeSpec{
|
||||
Active: v1.Image{
|
||||
Source: v1.NewDirSrc("/dir"),
|
||||
},
|
||||
Recovery: v1.Image{
|
||||
Source: v1.NewDirSrc("/dir"),
|
||||
},
|
||||
Partitions: v1.ElementalPartitions{
|
||||
State: &v1.Partition{
|
||||
MountPoint: "mountpoint",
|
||||
},
|
||||
Recovery: &v1.Partition{
|
||||
MountPoint: "mountpoint",
|
||||
},
|
||||
},
|
||||
}
|
||||
err := spec.Sanitize()
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
//Fails on empty source for active upgrade
|
||||
spec.Active.Source = v1.NewEmptySrc()
|
||||
err = spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
|
||||
//Fails on missing state partition for active upgrade
|
||||
spec.Partitions.State = nil
|
||||
err = spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
|
||||
//Fails on empty source for recovery upgrade
|
||||
spec.RecoveryUpgrade = true
|
||||
spec.Recovery.Source = v1.NewEmptySrc()
|
||||
err = spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
|
||||
//Fails on missing recovery partition for recovery upgrade
|
||||
spec.Partitions.Recovery = nil
|
||||
err = spec.Sanitize()
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -19,12 +19,13 @@ package utils
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
)
|
||||
|
||||
// Chroot represents the struct that will allow us to run commands inside a given chroot
|
||||
@ -33,10 +34,10 @@ type Chroot struct {
|
||||
defaultMounts []string
|
||||
extraMounts map[string]string
|
||||
activeMounts []string
|
||||
config *v1.Config
|
||||
config *agentConfig.Config
|
||||
}
|
||||
|
||||
func NewChroot(path string, config *v1.Config) *Chroot {
|
||||
func NewChroot(path string, config *agentConfig.Config) *Chroot {
|
||||
return &Chroot{
|
||||
path: path,
|
||||
defaultMounts: []string{"/dev", "/dev/pts", "/proc", "/sys"},
|
||||
@ -47,7 +48,7 @@ func NewChroot(path string, config *v1.Config) *Chroot {
|
||||
}
|
||||
|
||||
// ChrootedCallback runs the given callback in a chroot environment
|
||||
func ChrootedCallback(cfg *v1.Config, path string, bindMounts map[string]string, callback func() error) error {
|
||||
func ChrootedCallback(cfg *agentConfig.Config, path string, bindMounts map[string]string, callback func() error) error {
|
||||
chroot := NewChroot(path, cfg)
|
||||
chroot.SetExtraMounts(bindMounts)
|
||||
return chroot.RunCallback(callback)
|
||||
@ -78,7 +79,7 @@ func (c *Chroot) Prepare() error {
|
||||
|
||||
for _, mnt := range c.defaultMounts {
|
||||
mountPoint := fmt.Sprintf("%s%s", strings.TrimSuffix(c.path, "/"), mnt)
|
||||
err = MkdirAll(c.config.Fs, mountPoint, constants.DirPerm)
|
||||
err = fsutils.MkdirAll(c.config.Fs, mountPoint, constants.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -95,7 +96,7 @@ func (c *Chroot) Prepare() error {
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
mountPoint := fmt.Sprintf("%s%s", strings.TrimSuffix(c.path, "/"), c.extraMounts[k])
|
||||
err = MkdirAll(c.config.Fs, mountPoint, constants.DirPerm)
|
||||
err = fsutils.MkdirAll(c.config.Fs, mountPoint, constants.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
|
||||
"io"
|
||||
random "math/rand"
|
||||
"net/url"
|
||||
@ -42,12 +45,6 @@ func CommandExists(command string) bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// BootedFrom will check if we are booting from the given label
|
||||
func BootedFrom(runner v1.Runner, label string) bool {
|
||||
out, _ := runner.Run("cat", "/proc/cmdline")
|
||||
return strings.Contains(string(out), label)
|
||||
}
|
||||
|
||||
// GetDeviceByLabel will try to return the device that matches the given label.
|
||||
// attempts value sets the number of attempts to find the device, it
|
||||
// waits a second between attempts.
|
||||
@ -64,7 +61,7 @@ func GetDeviceByLabel(runner v1.Runner, label string, attempts int) (string, err
|
||||
func GetFullDeviceByLabel(runner v1.Runner, label string, attempts int) (*v1.Partition, error) {
|
||||
for tries := 0; tries < attempts; tries++ {
|
||||
_, _ = runner.Run("udevadm", "settle")
|
||||
parts, err := GetAllPartitions()
|
||||
parts, err := partitions.GetAllPartitions()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -91,7 +88,7 @@ func ConcatFiles(fs v1.FS, sources []string, target string) (err error) {
|
||||
if len(sources) == 0 {
|
||||
return fmt.Errorf("Empty sources list")
|
||||
}
|
||||
if dir, _ := IsDir(fs, target); dir {
|
||||
if dir, _ := fsutils.IsDir(fs, target); dir {
|
||||
target = filepath.Join(target, filepath.Base(sources[0]))
|
||||
}
|
||||
|
||||
@ -129,18 +126,18 @@ func ConcatFiles(fs v1.FS, sources []string, target string) (err error) {
|
||||
// Copies source file to target file using Fs interface
|
||||
func CreateDirStructure(fs v1.FS, target string) error {
|
||||
for _, dir := range []string{"/run", "/dev", "/boot", "/usr/local", "/oem"} {
|
||||
err := MkdirAll(fs, filepath.Join(target, dir), cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, filepath.Join(target, dir), cnst.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, dir := range []string{"/proc", "/sys"} {
|
||||
err := MkdirAll(fs, filepath.Join(target, dir), cnst.NoWriteDirPerm)
|
||||
err := fsutils.MkdirAll(fs, filepath.Join(target, dir), cnst.NoWriteDirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err := MkdirAll(fs, filepath.Join(target, "/tmp"), cnst.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, filepath.Join(target, "/tmp"), cnst.DirPerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -245,7 +242,7 @@ func CosignVerify(fs v1.FS, runner v1.Runner, image string, publicKey string, de
|
||||
args = append(args, image)
|
||||
|
||||
// Give each cosign its own tuf dir so it doesnt collide with others accessing the same files at the same time
|
||||
tmpDir, err := TempDir(fs, "", "cosign-tuf-")
|
||||
tmpDir, err := fsutils.TempDir(fs, "", "cosign-tuf-")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -301,7 +298,7 @@ func LoadEnvFile(fs v1.FS, file string) (map[string]string, error) {
|
||||
return envMap, err
|
||||
}
|
||||
|
||||
func IsMounted(config *v1.Config, part *v1.Partition) (bool, error) {
|
||||
func IsMounted(config *agentConfig.Config, part *v1.Partition) (bool, error) {
|
||||
if part == nil {
|
||||
return false, fmt.Errorf("nil partition")
|
||||
}
|
||||
@ -318,37 +315,11 @@ func IsMounted(config *v1.Config, part *v1.Partition) (bool, error) {
|
||||
return !notMnt, nil
|
||||
}
|
||||
|
||||
// HasSquashedRecovery returns true if a squashed recovery image is found in the system
|
||||
func HasSquashedRecovery(config *v1.Config, recovery *v1.Partition) (squashed bool, err error) {
|
||||
mountPoint := recovery.MountPoint
|
||||
if mnt, _ := IsMounted(config, recovery); !mnt {
|
||||
tmpMountDir, err := TempDir(config.Fs, "", "elemental")
|
||||
if err != nil {
|
||||
config.Logger.Errorf("failed creating temporary dir: %v", err)
|
||||
return false, err
|
||||
}
|
||||
defer config.Fs.RemoveAll(tmpMountDir) // nolint:errcheck
|
||||
err = config.Mounter.Mount(recovery.Path, tmpMountDir, "auto", []string{})
|
||||
if err != nil {
|
||||
config.Logger.Errorf("failed mounting recovery partition: %v", err)
|
||||
return false, err
|
||||
}
|
||||
mountPoint = tmpMountDir
|
||||
defer func() {
|
||||
err = config.Mounter.Unmount(tmpMountDir)
|
||||
if err != nil {
|
||||
squashed = false
|
||||
}
|
||||
}()
|
||||
}
|
||||
return Exists(config.Fs, filepath.Join(mountPoint, "cOS", cnst.RecoverySquashFile))
|
||||
}
|
||||
|
||||
// GetTempDir returns the dir for storing related temporal files
|
||||
// It will respect TMPDIR and use that if exists, fallback to try the persistent partition if its mounted
|
||||
// and finally the default /tmp/ dir
|
||||
// suffix is what is appended to the dir name elemental-suffix. If empty it will randomly generate a number
|
||||
func GetTempDir(config *v1.Config, suffix string) string {
|
||||
func GetTempDir(config *agentConfig.Config, suffix string) string {
|
||||
// if we got a TMPDIR var, respect and use that
|
||||
if suffix == "" {
|
||||
random.Seed(time.Now().UnixNano())
|
||||
@ -360,7 +331,7 @@ func GetTempDir(config *v1.Config, suffix string) string {
|
||||
config.Logger.Debugf("Got tmpdir from TMPDIR var: %s", dir)
|
||||
return filepath.Join(dir, elementalTmpDir)
|
||||
}
|
||||
parts, err := GetAllPartitions()
|
||||
parts, err := partitions.GetAllPartitions()
|
||||
if err != nil {
|
||||
config.Logger.Debug("Could not get partitions, defaulting to /tmp")
|
||||
return filepath.Join("/", "tmp", elementalTmpDir)
|
||||
@ -414,7 +385,7 @@ func IsHTTPURI(uri string) (bool, error) {
|
||||
|
||||
// GetSource copies given source to destination, if source is a local path it simply
|
||||
// copies files, if source is a remote URL it tries to download URL to destination.
|
||||
func GetSource(config *v1.Config, source string, destination string) error {
|
||||
func GetSource(config *agentConfig.Config, source string, destination string) error {
|
||||
local, err := IsLocalURI(source)
|
||||
if err != nil {
|
||||
config.Logger.Errorf("Not a valid url: %s", source)
|
||||
@ -484,7 +455,7 @@ func FindFileWithPrefix(fs v1.FS, path string, prefixes ...string) (string, erro
|
||||
if !filepath.IsAbs(found) {
|
||||
found = filepath.Join(path, found)
|
||||
}
|
||||
if exists, _ := Exists(fs, found); exists {
|
||||
if exists, _ := fsutils.Exists(fs, found); exists {
|
||||
return found, nil
|
||||
}
|
||||
}
|
||||
@ -497,19 +468,6 @@ func FindFileWithPrefix(fs v1.FS, path string, prefixes ...string) (string, erro
|
||||
return "", fmt.Errorf("No file found with prefixes: %v", prefixes)
|
||||
}
|
||||
|
||||
var errInvalidArch = fmt.Errorf("invalid arch")
|
||||
|
||||
func GolangArchToArch(arch string) (string, error) {
|
||||
switch strings.ToLower(arch) {
|
||||
case cnst.ArchAmd64:
|
||||
return cnst.Archx86, nil
|
||||
case cnst.ArchArm64:
|
||||
return cnst.ArchArm64, nil
|
||||
default:
|
||||
return "", errInvalidArch
|
||||
}
|
||||
}
|
||||
|
||||
// CalcFileChecksum opens the given file and returns the sha256 checksum of it.
|
||||
func CalcFileChecksum(fs v1.FS, fileName string) (string, error) {
|
||||
f, err := fs.Open(fileName)
|
||||
|
@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
package fsutils
|
||||
|
||||
import (
|
||||
"io/fs"
|
@ -18,21 +18,22 @@ package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
)
|
||||
|
||||
// Grub is the struct that will allow us to install grub to the target device
|
||||
type Grub struct {
|
||||
config *v1.Config
|
||||
config *agentConfig.Config
|
||||
}
|
||||
|
||||
func NewGrub(config *v1.Config) *Grub {
|
||||
func NewGrub(config *agentConfig.Config) *Grub {
|
||||
g := &Grub{
|
||||
config: config,
|
||||
}
|
||||
@ -71,7 +72,7 @@ func (g Grub) Install(target, rootDir, bootDir, grubConf, tty string, efi bool,
|
||||
|
||||
// Select the proper dir for grub - this assumes that we previously run a grub install command, which is not the case in EFI
|
||||
// In the EFI case we default to grub2
|
||||
if ok, _ := IsDir(g.config.Fs, filepath.Join(bootDir, "grub")); ok {
|
||||
if ok, _ := fsutils.IsDir(g.config.Fs, filepath.Join(bootDir, "grub")); ok {
|
||||
systemgrub = "grub"
|
||||
}
|
||||
}
|
||||
@ -86,7 +87,7 @@ func (g Grub) Install(target, rootDir, bootDir, grubConf, tty string, efi bool,
|
||||
}
|
||||
|
||||
// Create Needed dir under state partition to store the grub.cfg and any needed modules
|
||||
err = MkdirAll(g.config.Fs, filepath.Join(bootDir, fmt.Sprintf("%s/%s-efi", systemgrub, g.config.Arch)), cnst.DirPerm)
|
||||
err = fsutils.MkdirAll(g.config.Fs, filepath.Join(bootDir, fmt.Sprintf("%s/%s-efi", systemgrub, g.config.Arch)), cnst.DirPerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating grub dir: %s", err)
|
||||
}
|
||||
@ -108,7 +109,7 @@ func (g Grub) Install(target, rootDir, bootDir, grubConf, tty string, efi bool,
|
||||
}
|
||||
}
|
||||
|
||||
ttyExists, _ := Exists(g.config.Fs, fmt.Sprintf("/dev/%s", tty))
|
||||
ttyExists, _ := fsutils.Exists(g.config.Fs, fmt.Sprintf("/dev/%s", tty))
|
||||
|
||||
if ttyExists && tty != "" && tty != "console" && tty != constants.DefaultTty {
|
||||
// We need to add a tty to the grub file
|
||||
@ -134,7 +135,7 @@ func (g Grub) Install(target, rootDir, bootDir, grubConf, tty string, efi bool,
|
||||
g.config.Logger.Infof("Generating grub files for efi on %s", target)
|
||||
var foundModules bool
|
||||
for _, m := range []string{"loopback.mod", "squash4.mod", "xzio.mod", "gzio.mod"} {
|
||||
err = WalkDirFs(g.config.Fs, rootDir, func(path string, d fs.DirEntry, err error) error {
|
||||
err = fsutils.WalkDirFs(g.config.Fs, rootDir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -159,7 +160,7 @@ func (g Grub) Install(target, rootDir, bootDir, grubConf, tty string, efi bool,
|
||||
}
|
||||
}
|
||||
|
||||
err = MkdirAll(g.config.Fs, filepath.Join(cnst.EfiDir, "EFI/boot/"), cnst.DirPerm)
|
||||
err = fsutils.MkdirAll(g.config.Fs, filepath.Join(cnst.EfiDir, "EFI/boot/"), cnst.DirPerm)
|
||||
if err != nil {
|
||||
g.config.Logger.Errorf("Error creating dirs: %s", err)
|
||||
return err
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package utils
|
||||
package partitions
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -18,11 +18,12 @@ package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/mudler/yip/pkg/schema"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@ -43,7 +44,7 @@ func onlyYAMLPartialErrors(er error) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func checkYAMLError(cfg *v1.Config, allErrors, err error) error {
|
||||
func checkYAMLError(cfg *agentConfig.Config, allErrors, err error) error {
|
||||
if !onlyYAMLPartialErrors(err) {
|
||||
// here we absorb errors only if are related to YAML unmarshalling
|
||||
// As cmdline is parsed out as a yaml file
|
||||
@ -57,7 +58,7 @@ func checkYAMLError(cfg *v1.Config, allErrors, err error) error {
|
||||
}
|
||||
|
||||
// RunStage will run yip
|
||||
func RunStage(cfg *v1.Config, stage string) error {
|
||||
func RunStage(cfg *agentConfig.Config, stage string) error {
|
||||
var cmdLineYipURI string
|
||||
var allErrors error
|
||||
var cloudInitPaths []string
|
||||
@ -67,7 +68,7 @@ func RunStage(cfg *v1.Config, stage string) error {
|
||||
|
||||
// Make sure cloud init path specified are existing in the system
|
||||
for _, cp := range cloudInitPaths {
|
||||
err := MkdirAll(cfg.Fs, cp, constants.DirPerm)
|
||||
err := fsutils.MkdirAll(cfg.Fs, cp, constants.DirPerm)
|
||||
if err != nil {
|
||||
cfg.Logger.Debugf("Failed creating cloud-init config path: %s %s", cp, err.Error())
|
||||
}
|
||||
|
@ -19,10 +19,11 @@ package utils_test
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"os"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/cloudinit"
|
||||
conf "github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
@ -41,7 +42,7 @@ func writeCmdline(s string, fs v1.FS) error {
|
||||
}
|
||||
|
||||
var _ = Describe("run stage", Label("RunStage"), func() {
|
||||
var config *v1.Config
|
||||
var config *agentConfig.Config
|
||||
var runner *v1mock.FakeRunner
|
||||
var logger v1.Logger
|
||||
var syscall *v1mock.FakeSyscall
|
||||
@ -61,13 +62,13 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
||||
logger.SetLevel(log.DebugLevel)
|
||||
fs, cleanup, _ = vfst.NewTestFS(nil)
|
||||
|
||||
config = conf.NewConfig(
|
||||
conf.WithFs(fs),
|
||||
conf.WithRunner(runner),
|
||||
conf.WithLogger(logger),
|
||||
conf.WithMounter(mounter),
|
||||
conf.WithSyscall(syscall),
|
||||
conf.WithClient(client),
|
||||
config = agentConfig.NewConfig(
|
||||
agentConfig.WithFs(fs),
|
||||
agentConfig.WithRunner(runner),
|
||||
agentConfig.WithLogger(logger),
|
||||
agentConfig.WithMounter(mounter),
|
||||
agentConfig.WithSyscall(syscall),
|
||||
agentConfig.WithClient(client),
|
||||
)
|
||||
|
||||
config.CloudInitRunner = cloudinit.NewYipCloudInitRunner(config.Logger, config.Runner, fs)
|
||||
@ -75,7 +76,7 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
||||
AfterEach(func() { cleanup() })
|
||||
|
||||
It("fails if strict mode is enabled", Label("strict"), func() {
|
||||
d, err := utils.TempDir(fs, "", "elemental")
|
||||
d, err := fsutils.TempDir(fs, "", "elemental")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_ = fs.WriteFile(fmt.Sprintf("%s/test.yaml", d), []byte("stages: [foo,bar]"), os.ModePerm)
|
||||
config.Strict = true
|
||||
@ -92,7 +93,7 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
||||
})
|
||||
|
||||
It("Goes over extra paths", func() {
|
||||
d, err := utils.TempDir(fs, "", "elemental")
|
||||
d, err := fsutils.TempDir(fs, "", "elemental")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
config.Logger.SetLevel(log.DebugLevel)
|
||||
config.CloudInitPaths = []string{d}
|
||||
@ -105,7 +106,7 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
||||
})
|
||||
|
||||
It("parses cmdline uri", func() {
|
||||
d, _ := utils.TempDir(fs, "", "elemental")
|
||||
d, _ := fsutils.TempDir(fs, "", "elemental")
|
||||
_ = fs.WriteFile(fmt.Sprintf("%s/test.yaml", d), []byte{}, os.ModePerm)
|
||||
|
||||
writeCmdline(fmt.Sprintf("cos.setup=%s/test.yaml", d), fs)
|
||||
|
@ -20,6 +20,8 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@ -27,8 +29,8 @@ import (
|
||||
|
||||
"github.com/jaypipes/ghw/pkg/block"
|
||||
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
conf "github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
@ -47,7 +49,7 @@ func getNamesFromListFiles(list []os.FileInfo) []string {
|
||||
}
|
||||
|
||||
var _ = Describe("Utils", Label("utils"), func() {
|
||||
var config *v1.Config
|
||||
var config *agentConfig.Config
|
||||
var runner *v1mock.FakeRunner
|
||||
var logger v1.Logger
|
||||
var syscall *v1mock.FakeSyscall
|
||||
@ -70,13 +72,13 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
fs.Mkdir("/run", constants.DirPerm)
|
||||
fs.Mkdir("/etc", constants.DirPerm)
|
||||
|
||||
config = conf.NewConfig(
|
||||
conf.WithFs(fs),
|
||||
conf.WithRunner(runner),
|
||||
conf.WithLogger(logger),
|
||||
conf.WithMounter(mounter),
|
||||
conf.WithSyscall(syscall),
|
||||
conf.WithClient(client),
|
||||
config = agentConfig.NewConfig(
|
||||
agentConfig.WithFs(fs),
|
||||
agentConfig.WithRunner(runner),
|
||||
agentConfig.WithLogger(logger),
|
||||
agentConfig.WithMounter(mounter),
|
||||
agentConfig.WithSyscall(syscall),
|
||||
agentConfig.WithClient(client),
|
||||
)
|
||||
})
|
||||
AfterEach(func() { cleanup() })
|
||||
@ -176,16 +178,6 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
})
|
||||
})
|
||||
})
|
||||
Describe("TestBootedFrom", Label("BootedFrom"), func() {
|
||||
It("returns true if we are booting from label FAKELABEL", func() {
|
||||
runner.ReturnValue = []byte("")
|
||||
Expect(utils.BootedFrom(runner, "FAKELABEL")).To(BeFalse())
|
||||
})
|
||||
It("returns false if we are not booting from label FAKELABEL", func() {
|
||||
runner.ReturnValue = []byte("FAKELABEL")
|
||||
Expect(utils.BootedFrom(runner, "FAKELABEL")).To(BeTrue())
|
||||
})
|
||||
})
|
||||
Describe("GetDeviceByLabel", Label("lsblk", "partitions"), func() {
|
||||
var cmds [][]string
|
||||
BeforeEach(func() {
|
||||
@ -246,7 +238,7 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
ghwTest.Clean()
|
||||
})
|
||||
It("returns all found partitions", func() {
|
||||
parts, err := utils.GetAllPartitions()
|
||||
parts, err := partitions.GetAllPartitions()
|
||||
Expect(err).To(BeNil())
|
||||
var partNames []string
|
||||
for _, p := range parts {
|
||||
@ -277,17 +269,17 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
ghwTest.Clean()
|
||||
})
|
||||
It("returns found device with plain partition device", func() {
|
||||
pFS, err := utils.GetPartitionFS("device1")
|
||||
pFS, err := partitions.GetPartitionFS("device1")
|
||||
Expect(err).To(BeNil())
|
||||
Expect(pFS).To(Equal("xfs"))
|
||||
})
|
||||
It("returns found device with full partition device", func() {
|
||||
pFS, err := utils.GetPartitionFS("/dev/device1")
|
||||
pFS, err := partitions.GetPartitionFS("/dev/device1")
|
||||
Expect(err).To(BeNil())
|
||||
Expect(pFS).To(Equal("xfs"))
|
||||
})
|
||||
It("fails if no partition is found", func() {
|
||||
_, err := utils.GetPartitionFS("device2")
|
||||
_, err := partitions.GetPartitionFS("device2")
|
||||
Expect(err).NotTo(BeNil())
|
||||
})
|
||||
})
|
||||
@ -377,40 +369,40 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
})
|
||||
Describe("CopyFile", Label("CopyFile"), func() {
|
||||
It("Copies source file to target file", func() {
|
||||
err := utils.MkdirAll(fs, "/some", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create("/some/file")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Stat("/some/otherfile")
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(utils.CopyFile(fs, "/some/file", "/some/otherfile")).ShouldNot(HaveOccurred())
|
||||
e, err := utils.Exists(fs, "/some/otherfile")
|
||||
e, err := fsutils.Exists(fs, "/some/otherfile")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(e).To(BeTrue())
|
||||
})
|
||||
It("Copies source file to target folder", func() {
|
||||
err := utils.MkdirAll(fs, "/some", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = utils.MkdirAll(fs, "/someotherfolder", constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, "/someotherfolder", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Create("/some/file")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = fs.Stat("/someotherfolder/file")
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(utils.CopyFile(fs, "/some/file", "/someotherfolder")).ShouldNot(HaveOccurred())
|
||||
e, err := utils.Exists(fs, "/someotherfolder/file")
|
||||
e, err := fsutils.Exists(fs, "/someotherfolder/file")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(e).To(BeTrue())
|
||||
})
|
||||
It("Fails to open non existing file", func() {
|
||||
err := utils.MkdirAll(fs, "/some", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(utils.CopyFile(fs, "/some/file", "/some/otherfile")).NotTo(BeNil())
|
||||
_, err = fs.Stat("/some/otherfile")
|
||||
Expect(err).NotTo(BeNil())
|
||||
})
|
||||
It("Fails to copy on non writable target", func() {
|
||||
err := utils.MkdirAll(fs, "/some", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/some", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
fs.Create("/some/file")
|
||||
_, err = fs.Stat("/some/otherfile")
|
||||
@ -448,13 +440,13 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
})
|
||||
Describe("SyncData", Label("SyncData"), func() {
|
||||
It("Copies all files from source to target", func() {
|
||||
sourceDir, err := utils.TempDir(fs, "", "elementalsource")
|
||||
sourceDir, err := fsutils.TempDir(fs, "", "elementalsource")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
destDir, err := utils.TempDir(fs, "", "elementaltarget")
|
||||
destDir, err := fsutils.TempDir(fs, "", "elementaltarget")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
_, _ = utils.TempFile(fs, sourceDir, "file*")
|
||||
_, _ = fsutils.TempFile(fs, sourceDir, "file*")
|
||||
}
|
||||
|
||||
Expect(utils.SyncData(logger, realRunner, fs, sourceDir, destDir)).To(BeNil())
|
||||
@ -473,19 +465,19 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
})
|
||||
|
||||
It("Copies all files from source to target respecting excludes", func() {
|
||||
sourceDir, err := utils.TempDir(fs, "", "elementalsource")
|
||||
sourceDir, err := fsutils.TempDir(fs, "", "elementalsource")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
destDir, err := utils.TempDir(fs, "", "elementaltarget")
|
||||
destDir, err := fsutils.TempDir(fs, "", "elementaltarget")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "host"), constants.DirPerm)
|
||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "run"), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "host"), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "run"), constants.DirPerm)
|
||||
|
||||
// /tmp/run would be excluded as well, as we define an exclude without the "/" prefix
|
||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "tmp", "run"), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "tmp", "run"), constants.DirPerm)
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
_, _ = utils.TempFile(fs, sourceDir, "file*")
|
||||
_, _ = fsutils.TempFile(fs, sourceDir, "file*")
|
||||
}
|
||||
|
||||
Expect(utils.SyncData(logger, realRunner, fs, sourceDir, destDir, "host", "run")).To(BeNil())
|
||||
@ -512,19 +504,19 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
Expect(destNames).To(Equal(expected))
|
||||
|
||||
// /tmp/run is not copied over
|
||||
Expect(utils.Exists(fs, filepath.Join(destDir, "tmp", "run"))).To(BeFalse())
|
||||
Expect(fsutils.Exists(fs, filepath.Join(destDir, "tmp", "run"))).To(BeFalse())
|
||||
})
|
||||
|
||||
It("Copies all files from source to target respecting excludes with '/' prefix", func() {
|
||||
sourceDir, err := utils.TempDir(fs, "", "elementalsource")
|
||||
sourceDir, err := fsutils.TempDir(fs, "", "elementalsource")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
destDir, err := utils.TempDir(fs, "", "elementaltarget")
|
||||
destDir, err := fsutils.TempDir(fs, "", "elementaltarget")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "host"), constants.DirPerm)
|
||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "run"), constants.DirPerm)
|
||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "var", "run"), constants.DirPerm)
|
||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "tmp", "host"), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "host"), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "run"), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "var", "run"), constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "tmp", "host"), constants.DirPerm)
|
||||
|
||||
Expect(utils.SyncData(logger, realRunner, fs, sourceDir, destDir, "/host", "/run")).To(BeNil())
|
||||
|
||||
@ -541,16 +533,16 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
// Shouldn't be the same
|
||||
Expect(destNames).ToNot(Equal(SourceNames))
|
||||
|
||||
Expect(utils.Exists(fs, filepath.Join(destDir, "var", "run"))).To(BeTrue())
|
||||
Expect(utils.Exists(fs, filepath.Join(destDir, "tmp", "host"))).To(BeTrue())
|
||||
Expect(utils.Exists(fs, filepath.Join(destDir, "host"))).To(BeFalse())
|
||||
Expect(utils.Exists(fs, filepath.Join(destDir, "run"))).To(BeFalse())
|
||||
Expect(fsutils.Exists(fs, filepath.Join(destDir, "var", "run"))).To(BeTrue())
|
||||
Expect(fsutils.Exists(fs, filepath.Join(destDir, "tmp", "host"))).To(BeTrue())
|
||||
Expect(fsutils.Exists(fs, filepath.Join(destDir, "host"))).To(BeFalse())
|
||||
Expect(fsutils.Exists(fs, filepath.Join(destDir, "run"))).To(BeFalse())
|
||||
})
|
||||
|
||||
It("should not fail if dirs are empty", func() {
|
||||
sourceDir, err := utils.TempDir(fs, "", "elementalsource")
|
||||
sourceDir, err := fsutils.TempDir(fs, "", "elementalsource")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
destDir, err := utils.TempDir(fs, "", "elementaltarget")
|
||||
destDir, err := fsutils.TempDir(fs, "", "elementaltarget")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(utils.SyncData(logger, realRunner, fs, sourceDir, destDir)).To(BeNil())
|
||||
})
|
||||
@ -672,7 +664,7 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
})
|
||||
Describe("DirSize", Label("fs"), func() {
|
||||
BeforeEach(func() {
|
||||
err := utils.MkdirAll(fs, "/folder/subfolder", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/folder/subfolder", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
f, err := fs.Create("/folder/file")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
@ -684,14 +676,14 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
})
|
||||
It("Returns the expected size of a test folder", func() {
|
||||
size, err := utils.DirSize(fs, "/folder")
|
||||
size, err := fsutils.DirSize(fs, "/folder")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(size).To(Equal(int64(3072)))
|
||||
})
|
||||
})
|
||||
Describe("FindFileWithPrefix", Label("find"), func() {
|
||||
BeforeEach(func() {
|
||||
err := utils.MkdirAll(fs, "/path/inner", constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, "/path/inner", constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
_, err = fs.Create("/path/onefile")
|
||||
@ -740,7 +732,7 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
It("doesn't find any matching file in path", func() {
|
||||
utils.MkdirAll(fs, "/path", constants.DirPerm)
|
||||
fsutils.MkdirAll(fs, "/path", constants.DirPerm)
|
||||
_, err := utils.FindFileWithPrefix(fs, "/path", "prefix", "anotherprefix")
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
@ -773,10 +765,10 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
logger.SetLevel(v1.DebugLevel())
|
||||
config.Logger = logger
|
||||
|
||||
err := utils.MkdirAll(fs, filepath.Join(bootDir, "grub2"), constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, filepath.Join(bootDir, "grub2"), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
err = utils.MkdirAll(fs, filepath.Dir(filepath.Join(rootDir, constants.GrubConf)), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Dir(filepath.Join(rootDir, constants.GrubConf)), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
err = fs.WriteFile(filepath.Join(rootDir, constants.GrubConf), []byte("console=tty1"), 0644)
|
||||
@ -798,17 +790,17 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
|
||||
})
|
||||
It("installs with efi firmware", Label("efi"), func() {
|
||||
err := utils.MkdirAll(fs, filepath.Join(rootDir, "/usr/share/efi/x86_64/"), constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, filepath.Join(rootDir, "/usr/share/efi/x86_64/"), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = fs.WriteFile(filepath.Join(rootDir, "/usr/share/efi/x86_64/", constants.SignedShim), []byte(""), constants.FilePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = fs.WriteFile(filepath.Join(rootDir, "/usr/share/efi/x86_64/grub.efi"), []byte(""), constants.FilePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = utils.MkdirAll(fs, filepath.Join(rootDir, "/x86_64/"), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Join(rootDir, "/x86_64/"), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = fs.WriteFile(filepath.Join(rootDir, "/x86_64/loopback.mod"), []byte(""), constants.FilePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = utils.MkdirAll(fs, filepath.Join(rootDir, "/etc/"), constants.DirPerm)
|
||||
err = fsutils.MkdirAll(fs, filepath.Join(rootDir, "/etc/"), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = fs.WriteFile(filepath.Join(rootDir, "/etc/os-release"), []byte("ID=\"suse\""), constants.FilePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
@ -839,7 +831,7 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
Expect(err.Error()).To(ContainSubstring("modules"))
|
||||
})
|
||||
It("fails with efi if no grub files exist", Label("efi"), func() {
|
||||
err := utils.MkdirAll(fs, filepath.Join(rootDir, "/x86_64/"), constants.DirPerm)
|
||||
err := fsutils.MkdirAll(fs, filepath.Join(rootDir, "/x86_64/"), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = fs.WriteFile(filepath.Join(rootDir, "/x86_64/loopback.mod"), []byte(""), constants.FilePerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
@ -993,65 +985,6 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
Expect(mnt).To(BeFalse())
|
||||
})
|
||||
})
|
||||
Describe("HasSquashedRecovery", Label("squashedRec"), func() {
|
||||
var squashedImg string
|
||||
var part *v1.Partition
|
||||
BeforeEach(func() {
|
||||
squashedImg = filepath.Join(constants.LiveDir, "cOS", constants.RecoverySquashFile)
|
||||
part = &v1.Partition{
|
||||
MountPoint: constants.LiveDir,
|
||||
Path: "/some/device",
|
||||
}
|
||||
})
|
||||
It("has squashed image from a mounted recovery", func() {
|
||||
// mount recovery
|
||||
err := mounter.Mount(part.Path, constants.LiveDir, "auto", []string{})
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
// create squashfs
|
||||
err = utils.MkdirAll(config.Fs, filepath.Dir(squashedImg), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = config.Fs.Create(squashedImg)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
squash, err := utils.HasSquashedRecovery(config, part)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(squash).To(BeTrue())
|
||||
})
|
||||
It("does not have squashed image from a mounted recovery", func() {
|
||||
// mount recovery
|
||||
err := mounter.Mount(part.Path, constants.LiveDir, "auto", []string{})
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
squash, err := utils.HasSquashedRecovery(config, part)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(squash).To(BeFalse())
|
||||
})
|
||||
It("has squashed image from a not mounted recovery", func() {
|
||||
// squashed image on temp dir
|
||||
squashedImg = filepath.Join("/tmp/elemental", "cOS", constants.RecoverySquashFile)
|
||||
// create squashfs
|
||||
err := utils.MkdirAll(config.Fs, filepath.Dir(squashedImg), constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
_, err = config.Fs.Create(squashedImg)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
squash, err := utils.HasSquashedRecovery(config, part)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(squash).To(BeTrue())
|
||||
})
|
||||
It("does not have squashed image from a not mounted recovery", func() {
|
||||
squash, err := utils.HasSquashedRecovery(config, part)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(squash).To(BeFalse())
|
||||
})
|
||||
It("fails to mount recovery", func() {
|
||||
mounter.ErrorOnMount = true
|
||||
squash, err := utils.HasSquashedRecovery(config, part)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(squash).To(BeFalse())
|
||||
})
|
||||
})
|
||||
Describe("CleanStack", Label("CleanStack"), func() {
|
||||
var cleaner *utils.CleanStack
|
||||
BeforeEach(func() {
|
||||
|
Loading…
Reference in New Issue
Block a user