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/hashicorp/go-multierror v1.1.1
|
||||||
github.com/jaypipes/ghw v0.12.0
|
github.com/jaypipes/ghw v0.12.0
|
||||||
github.com/joho/godotenv v1.5.1
|
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/labstack/echo/v4 v4.10.2
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/mudler/go-nodepair v0.0.0-20221223092639-ba399a66fdfb
|
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/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 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.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 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o=
|
||||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4=
|
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=
|
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{
|
var AfterInstall = []Interface{
|
||||||
&RunStage{}, // Shells out to stages defined from the container image
|
|
||||||
&GrubOptions{}, // Set custom GRUB options
|
&GrubOptions{}, // Set custom GRUB options
|
||||||
&BundleOption{},
|
&BundleOption{},
|
||||||
&CustomMounts{},
|
&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"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -16,7 +17,6 @@ import (
|
|||||||
"github.com/kairos-io/kairos-agent/v2/internal/cmd"
|
"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/action"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
"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"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
elementalUtils "github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
elementalUtils "github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||||
events "github.com/kairos-io/kairos-sdk/bus"
|
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 {
|
func ManualInstall(c, device string, reboot, poweroff, strictValidations bool) error {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@ -223,22 +212,21 @@ func RunInstall(c *config.Config) error {
|
|||||||
c.Install.Device = detectDevice()
|
c.Install.Device = detectDevice()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the installation Config from the system
|
// Load the installation spec from the Config
|
||||||
installConfig, installSpec, err := elementalConfig.ReadInstallConfigFromAgentConfig(c)
|
installSpec, err := config.ReadInstallSpecFromConfig(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
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
|
return err
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(f.Name())
|
defer os.RemoveAll(f.Name())
|
||||||
|
|
||||||
ccstring, err := c.String()
|
ccstring, err := c.String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
installConfig.Logger.Error("Error creating temporary file for install config: %s\n", err.Error())
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = os.WriteFile(f.Name(), []byte(ccstring), os.ModePerm)
|
err = os.WriteFile(f.Name(), []byte(ccstring), os.ModePerm)
|
||||||
@ -247,6 +235,7 @@ func RunInstall(c *config.Config) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This should not be neccessary
|
||||||
installSpec.NoFormat = c.Install.NoFormat
|
installSpec.NoFormat = c.Install.NoFormat
|
||||||
|
|
||||||
// Set our cloud-init to the file we just created
|
// 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)
|
// 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
|
// 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
|
events.RunHookScript("/usr/bin/kairos-agent.install.pre.hook") //nolint:errcheck
|
||||||
// Create the action
|
// Create the action
|
||||||
installAction := action.NewInstallAction(installConfig, installSpec)
|
installAction := action.NewInstallAction(c, installSpec)
|
||||||
// Run it
|
// Run it
|
||||||
if err := installAction.Run(); err != nil {
|
if err := installAction.Run(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
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...)
|
return hook.Run(*c, installSpec, hook.AfterInstall...)
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jaypipes/ghw/pkg/block"
|
"github.com/jaypipes/ghw/pkg/block"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
"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"
|
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||||
"github.com/twpayne/go-vfs"
|
"github.com/twpayne/go-vfs"
|
||||||
"github.com/twpayne/go-vfs/vfst"
|
"github.com/twpayne/go-vfs/vfst"
|
||||||
@ -84,10 +84,10 @@ var _ = Describe("RunInstall", func() {
|
|||||||
fs, cleanup, err = vfst.NewTestFS(map[string]interface{}{"/proc/cmdline": ""})
|
fs, cleanup, err = vfst.NewTestFS(map[string]interface{}{"/proc/cmdline": ""})
|
||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
// Create tmp dir
|
// Create tmp dir
|
||||||
utils.MkdirAll(fs, "/tmp", constants.DirPerm)
|
fsutils.MkdirAll(fs, "/tmp", constants.DirPerm)
|
||||||
// Create grub confg
|
// Create grub confg
|
||||||
grubCfg := filepath.Join(constants.ActiveDir, constants.GrubConf)
|
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())
|
Expect(err).To(BeNil())
|
||||||
_, err = fs.Create(grubCfg)
|
_, err = fs.Create(grubCfg)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
@ -133,7 +133,7 @@ var _ = Describe("RunInstall", func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
device := "/some/device"
|
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())
|
Expect(err).To(BeNil())
|
||||||
_, err = fs.Create(device)
|
_, err = fs.Create(device)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
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/internal/cmd"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
"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/config"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/elementalConfig"
|
|
||||||
sdk "github.com/kairos-io/kairos-sdk/bus"
|
sdk "github.com/kairos-io/kairos-sdk/bus"
|
||||||
"github.com/kairos-io/kairos-sdk/collector"
|
"github.com/kairos-io/kairos-sdk/collector"
|
||||||
"github.com/kairos-io/kairos-sdk/machine"
|
"github.com/kairos-io/kairos-sdk/machine"
|
||||||
@ -78,7 +77,7 @@ func Reset(dir ...string) error {
|
|||||||
utils.SetEnv(c.Env)
|
utils.SetEnv(c.Env)
|
||||||
|
|
||||||
// Load the installation Config from the cloud-config data
|
// Load the installation Config from the cloud-config data
|
||||||
resetConfig, resetSpec, err := elementalConfig.ReadResetConfigFromAgentConfig(c)
|
resetSpec, err := config.ReadResetSpecFromConfig(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -92,11 +91,11 @@ func Reset(dir ...string) error {
|
|||||||
resetSpec.FormatOEM = o == "true"
|
resetSpec.FormatOEM = o == "true"
|
||||||
}
|
}
|
||||||
if s := optionsFromEvent["strict"]; s != "" {
|
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 {
|
if err := resetAction.Run(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/kairos-io/kairos-agent/v2/internal/bus"
|
"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/action"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
"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"
|
"github.com/kairos-io/kairos-agent/v2/pkg/github"
|
||||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
events "github.com/kairos-io/kairos-sdk/bus"
|
events "github.com/kairos-io/kairos-sdk/bus"
|
||||||
@ -100,7 +99,7 @@ func Upgrade(
|
|||||||
utils.SetEnv(c.Env)
|
utils.SetEnv(c.Env)
|
||||||
|
|
||||||
// Load the upgrade Config from the system
|
// Load the upgrade Config from the system
|
||||||
upgradeConfig, upgradeSpec, err := elementalConfig.ReadUpgradeConfigFromAgentConfig(c)
|
upgradeSpec, err := config.ReadUpgradeSpecFromConfig(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -118,7 +117,7 @@ func Upgrade(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
upgradeAction := action.NewUpgradeAction(upgradeConfig, upgradeSpec)
|
upgradeAction := action.NewUpgradeAction(c, upgradeSpec)
|
||||||
|
|
||||||
err = upgradeAction.Run()
|
err = upgradeAction.Run()
|
||||||
if err != nil {
|
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/bus"
|
||||||
"github.com/kairos-io/kairos-agent/v2/internal/common"
|
"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/internal/webui"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
agentConfig "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"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
"github.com/kairos-io/kairos-sdk/bundles"
|
"github.com/kairos-io/kairos-sdk/bundles"
|
||||||
"github.com/kairos-io/kairos-sdk/collector"
|
"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.",
|
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"},
|
Aliases: []string{"s"},
|
||||||
Action: func(c *cli.Context) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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",
|
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"},
|
Aliases: []string{"g"},
|
||||||
Action: func(c *cli.Context) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
Action: func(c *cli.Context) error {
|
||||||
stage := c.Args().First()
|
stage := c.Args().First()
|
||||||
config, err := config.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
config, err := agentConfig.Scan(collector.Directories(configScanDir...), collector.NoLogs)
|
||||||
if err != nil {
|
config.Strict = c.Bool("strict")
|
||||||
return err
|
|
||||||
}
|
|
||||||
cfg, err := elementalConfig.ReadConfigRunFromAgentConfig(config)
|
|
||||||
cfg.Strict = c.Bool("strict")
|
|
||||||
|
|
||||||
if len(c.StringSlice("cloud-init-paths")) > 0 {
|
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") {
|
if c.Bool("debug") {
|
||||||
cfg.Logger.SetLevel(logrus.DebugLevel)
|
config.Logger.SetLevel(logrus.DebugLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid path %s", destination)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cfg, err := elementalConfig.ReadConfigRunFromAgentConfig(config)
|
config.Logger.Infof("Starting download and extraction for image %s to %s\n", image, destination)
|
||||||
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)
|
|
||||||
e := v1.OCIImageExtractor{}
|
e := v1.OCIImageExtractor{}
|
||||||
if err = e.ExtractImage(image, destination, c.String("platform")); err != nil {
|
if err = e.ExtractImage(image, destination, c.String("platform")); err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -17,13 +17,13 @@ limitations under the License.
|
|||||||
package action
|
package action
|
||||||
|
|
||||||
import (
|
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"
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hook is RunStage wrapper that only adds logic to ignore errors
|
// Hook is RunStage wrapper that only adds logic to ignore errors
|
||||||
// in case v1.Config.Strict is set to false
|
// 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)
|
config.Logger.Infof("Running %s hook", hook)
|
||||||
err := utils.RunStage(config, hook)
|
err := utils.RunStage(config, hook)
|
||||||
if !config.Strict {
|
if !config.Strict {
|
||||||
@ -33,7 +33,7 @@ func Hook(config *v1.Config, hook string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ChrootHook executes Hook inside a chroot environment
|
// 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 {
|
callback := func() error {
|
||||||
return Hook(config, hook)
|
return Hook(config, hook)
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@ package action
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
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 {
|
type InstallAction struct {
|
||||||
cfg *v1.Config
|
cfg *config.Config
|
||||||
spec *v1.InstallSpec
|
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}
|
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 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")
|
i.cfg.Logger.Infof("Writing eject script")
|
||||||
err = i.cfg.Fs.WriteFile("/usr/lib/systemd/system-shutdown/eject", []byte(cnst.EjectScript), 0744)
|
err = i.cfg.Fs.WriteFile("/usr/lib/systemd/system-shutdown/eject", []byte(cnst.EjectScript), 0744)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -20,13 +20,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/jaypipes/ghw/pkg/block"
|
"github.com/jaypipes/ghw/pkg/block"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"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"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||||
@ -42,7 +43,7 @@ const partTmpl = `
|
|||||||
%d:%ss:%ss:2048s:ext4::type=83;`
|
%d:%ss:%ss:2048s:ext4::type=83;`
|
||||||
|
|
||||||
var _ = Describe("Install action tests", func() {
|
var _ = Describe("Install action tests", func() {
|
||||||
var config *v1.Config
|
var config *agentConfig.Config
|
||||||
var runner *v1mock.FakeRunner
|
var runner *v1mock.FakeRunner
|
||||||
var fs vfs.FS
|
var fs vfs.FS
|
||||||
var logger v1.Logger
|
var logger v1.Logger
|
||||||
@ -69,15 +70,15 @@ var _ = Describe("Install action tests", func() {
|
|||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
|
|
||||||
cloudInit = &v1mock.FakeCloudInitRunner{}
|
cloudInit = &v1mock.FakeCloudInitRunner{}
|
||||||
config = conf.NewConfig(
|
config = agentConfig.NewConfig(
|
||||||
conf.WithFs(fs),
|
agentConfig.WithFs(fs),
|
||||||
conf.WithRunner(runner),
|
agentConfig.WithRunner(runner),
|
||||||
conf.WithLogger(logger),
|
agentConfig.WithLogger(logger),
|
||||||
conf.WithMounter(mounter),
|
agentConfig.WithMounter(mounter),
|
||||||
conf.WithSyscall(syscall),
|
agentConfig.WithSyscall(syscall),
|
||||||
conf.WithClient(client),
|
agentConfig.WithClient(client),
|
||||||
conf.WithCloudInitRunner(cloudInit),
|
agentConfig.WithCloudInitRunner(cloudInit),
|
||||||
conf.WithImageExtractor(extractor),
|
agentConfig.WithImageExtractor(extractor),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,7 +95,7 @@ var _ = Describe("Install action tests", func() {
|
|||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
device = "/some/device"
|
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())
|
Expect(err).To(BeNil())
|
||||||
_, err = fs.Create(device)
|
_, err = fs.Create(device)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
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
|
// 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())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
spec = conf.NewInstallSpec(config)
|
spec = agentConfig.NewInstallSpec(config)
|
||||||
spec.Active.Size = 16
|
spec.Active.Size = 16
|
||||||
|
|
||||||
grubCfg := filepath.Join(spec.Active.MountPoint, constants.GrubConf)
|
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())
|
Expect(err).To(BeNil())
|
||||||
_, err = fs.Create(grubCfg)
|
_, err = fs.Create(grubCfg)
|
||||||
Expect(err).To(BeNil())
|
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() {
|
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")
|
_, err := fs.Stat("/usr/lib/systemd/system-shutdown/eject")
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
// Override cmdline to return like we are booting from cd
|
// 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() {
|
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")
|
_, err := fs.Stat("/usr/lib/systemd/system-shutdown/eject")
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
spec.Target = device
|
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() {
|
It("Successfully installs and adds remote cloud-config", Label("cloud-config"), func() {
|
||||||
spec.Target = device
|
spec.Target = device
|
||||||
spec.CloudInit = []string{"http://my.config.org"}
|
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"))
|
_, err := fs.Create(filepath.Join(constants.OEMDir, "90_custom.yaml"))
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
Expect(installer.Run()).To(BeNil())
|
Expect(installer.Run()).To(BeNil())
|
||||||
|
@ -18,6 +18,7 @@ package action
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -44,11 +45,11 @@ func (r *ResetAction) resetHook(hook string, chroot bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ResetAction struct {
|
type ResetAction struct {
|
||||||
cfg *v1.Config
|
cfg *agentConfig.Config
|
||||||
spec *v1.ResetSpec
|
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}
|
return &ResetAction{cfg: cfg, spec: spec}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,13 +20,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/jaypipes/ghw/pkg/block"
|
"github.com/jaypipes/ghw/pkg/block"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"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"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||||
@ -37,7 +38,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Reset action tests", func() {
|
var _ = Describe("Reset action tests", func() {
|
||||||
var config *v1.Config
|
var config *agentConfig.Config
|
||||||
var runner *v1mock.FakeRunner
|
var runner *v1mock.FakeRunner
|
||||||
var fs vfs.FS
|
var fs vfs.FS
|
||||||
var logger v1.Logger
|
var logger v1.Logger
|
||||||
@ -63,15 +64,15 @@ var _ = Describe("Reset action tests", func() {
|
|||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
|
|
||||||
cloudInit = &v1mock.FakeCloudInitRunner{}
|
cloudInit = &v1mock.FakeCloudInitRunner{}
|
||||||
config = conf.NewConfig(
|
config = agentConfig.NewConfig(
|
||||||
conf.WithFs(fs),
|
agentConfig.WithFs(fs),
|
||||||
conf.WithRunner(runner),
|
agentConfig.WithRunner(runner),
|
||||||
conf.WithLogger(logger),
|
agentConfig.WithLogger(logger),
|
||||||
conf.WithMounter(mounter),
|
agentConfig.WithMounter(mounter),
|
||||||
conf.WithSyscall(syscall),
|
agentConfig.WithSyscall(syscall),
|
||||||
conf.WithClient(client),
|
agentConfig.WithClient(client),
|
||||||
conf.WithCloudInitRunner(cloudInit),
|
agentConfig.WithCloudInitRunner(cloudInit),
|
||||||
conf.WithImageExtractor(extractor),
|
agentConfig.WithImageExtractor(extractor),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ var _ = Describe("Reset action tests", func() {
|
|||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
cmdFail = ""
|
cmdFail = ""
|
||||||
recoveryImg := filepath.Join(constants.RunningStateDir, "cOS", constants.RecoveryImgFile)
|
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())
|
Expect(err).To(BeNil())
|
||||||
_, err = fs.Create(recoveryImg)
|
_, err = fs.Create(recoveryImg)
|
||||||
Expect(err).To(BeNil())
|
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(err).ShouldNot(HaveOccurred())
|
||||||
Expect(spec.Active.Source.IsEmpty()).To(BeFalse())
|
Expect(spec.Active.Source.IsEmpty()).To(BeFalse())
|
||||||
|
|
||||||
spec.Active.Size = 16
|
spec.Active.Size = 16
|
||||||
|
|
||||||
grubCfg := filepath.Join(spec.Active.MountPoint, spec.GrubConf)
|
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())
|
Expect(err).To(BeNil())
|
||||||
_, err = fs.Create(grubCfg)
|
_, err = fs.Create(grubCfg)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
@ -175,7 +176,7 @@ var _ = Describe("Reset action tests", func() {
|
|||||||
Expect(reset.Run()).To(BeNil())
|
Expect(reset.Run()).To(BeNil())
|
||||||
})
|
})
|
||||||
It("Successfully resets from a squashfs recovery image", Label("channel"), func() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
spec.Active.Source = v1.NewDirSrc(constants.IsoBaseTree)
|
spec.Active.Source = v1.NewDirSrc(constants.IsoBaseTree)
|
||||||
Expect(reset.Run()).To(BeNil())
|
Expect(reset.Run()).To(BeNil())
|
||||||
|
@ -18,6 +18,8 @@ package action
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -29,11 +31,11 @@ import (
|
|||||||
|
|
||||||
// UpgradeAction represents the struct that will run the upgrade from start to finish
|
// UpgradeAction represents the struct that will run the upgrade from start to finish
|
||||||
type UpgradeAction struct {
|
type UpgradeAction struct {
|
||||||
config *v1.Config
|
config *agentConfig.Config
|
||||||
spec *v1.UpgradeSpec
|
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}
|
return &UpgradeAction{config: config, spec: spec}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +156,7 @@ func (u *UpgradeAction) Run() (err error) {
|
|||||||
persistentPart := u.spec.Partitions.Persistent
|
persistentPart := u.spec.Partitions.Persistent
|
||||||
if persistentPart != nil {
|
if persistentPart != nil {
|
||||||
// Create the dir otherwise the check for mounted dir fails
|
// 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 {
|
if mnt, err := utils.IsMounted(u.config, persistentPart); !mnt && err == nil {
|
||||||
u.Debug("mounting persistent partition")
|
u.Debug("mounting persistent partition")
|
||||||
umount, err = e.MountRWPartition(persistentPart)
|
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
|
// remove attempts to remove the given path. Does nothing if it doesn't exist
|
||||||
func (u *UpgradeAction) remove(path string) error {
|
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)
|
u.Debug("[Cleanup] Removing %s", path)
|
||||||
return u.config.Fs.RemoveAll(path)
|
return u.config.Fs.RemoveAll(path)
|
||||||
}
|
}
|
||||||
|
@ -19,14 +19,14 @@ package action_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/jaypipes/ghw/pkg/block"
|
"github.com/jaypipes/ghw/pkg/block"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"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"
|
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"
|
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@ -36,7 +36,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Runtime Actions", func() {
|
var _ = Describe("Runtime Actions", func() {
|
||||||
var config *v1.Config
|
var config *agentConfig.Config
|
||||||
var runner *v1mock.FakeRunner
|
var runner *v1mock.FakeRunner
|
||||||
var fs vfs.FS
|
var fs vfs.FS
|
||||||
var logger v1.Logger
|
var logger v1.Logger
|
||||||
@ -63,16 +63,16 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
|
|
||||||
cloudInit = &v1mock.FakeCloudInitRunner{}
|
cloudInit = &v1mock.FakeCloudInitRunner{}
|
||||||
config = conf.NewConfig(
|
config = agentConfig.NewConfig(
|
||||||
conf.WithFs(fs),
|
agentConfig.WithFs(fs),
|
||||||
conf.WithRunner(runner),
|
agentConfig.WithRunner(runner),
|
||||||
conf.WithLogger(logger),
|
agentConfig.WithLogger(logger),
|
||||||
conf.WithMounter(mounter),
|
agentConfig.WithMounter(mounter),
|
||||||
conf.WithSyscall(syscall),
|
agentConfig.WithSyscall(syscall),
|
||||||
conf.WithClient(client),
|
agentConfig.WithClient(client),
|
||||||
conf.WithCloudInitRunner(cloudInit),
|
agentConfig.WithCloudInitRunner(cloudInit),
|
||||||
conf.WithImageExtractor(extractor),
|
agentConfig.WithImageExtractor(extractor),
|
||||||
conf.WithPlatform("linux/amd64"),
|
agentConfig.WithPlatform("linux/amd64"),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -98,8 +98,8 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
logger.SetLevel(logrus.DebugLevel)
|
logger.SetLevel(logrus.DebugLevel)
|
||||||
|
|
||||||
// Create paths used by tests
|
// Create paths used by tests
|
||||||
utils.MkdirAll(fs, fmt.Sprintf("%s/cOS", constants.RunningStateDir), constants.DirPerm)
|
fsutils.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.LiveDir), constants.DirPerm)
|
||||||
|
|
||||||
mainDisk := block.Disk{
|
mainDisk := block.Disk{
|
||||||
Name: "device",
|
Name: "device",
|
||||||
@ -143,10 +143,10 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
Describe(fmt.Sprintf("Booting from %s", constants.ActiveLabel), Label("active_label"), func() {
|
Describe(fmt.Sprintf("Booting from %s", constants.ActiveLabel), Label("active_label"), func() {
|
||||||
var err error
|
var err error
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
spec, err = conf.NewUpgradeSpec(config)
|
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
err = fs.WriteFile(
|
err = fs.WriteFile(
|
||||||
@ -303,7 +303,7 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
})
|
})
|
||||||
It("Successfully upgrades from directory", Label("directory"), func() {
|
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
|
// Create the dir on real os as rsync works on the real os
|
||||||
defer fs.RemoveAll(dirSrc)
|
defer fs.RemoveAll(dirSrc)
|
||||||
spec.Active.Source = v1.NewDirSrc(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() {
|
Describe(fmt.Sprintf("Booting from %s", constants.PassiveLabel), Label("passive_label"), func() {
|
||||||
var err error
|
var err error
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
spec, err = conf.NewUpgradeSpec(config)
|
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
err = fs.WriteFile(
|
err = fs.WriteFile(
|
||||||
@ -428,7 +428,7 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
err = fs.WriteFile(recoveryImgSquash, []byte("recovery"), constants.FilePerm)
|
err = fs.WriteFile(recoveryImgSquash, []byte("recovery"), constants.FilePerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec, err = conf.NewUpgradeSpec(config)
|
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
spec.Active.Size = 10
|
spec.Active.Size = 10
|
||||||
spec.Passive.Size = 10
|
spec.Passive.Size = 10
|
||||||
@ -484,7 +484,7 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
|
|
||||||
})
|
})
|
||||||
It("Successfully upgrades recovery from directory", Label("directory"), 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
|
// create a random file on it
|
||||||
_ = fs.WriteFile(fmt.Sprintf("%s/file.file", srcDir), []byte("something"), constants.FilePerm)
|
_ = 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)
|
err = fs.WriteFile(recoveryImg, []byte("recovery"), constants.FilePerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec, err = conf.NewUpgradeSpec(config)
|
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec.Active.Size = 10
|
spec.Active.Size = 10
|
||||||
@ -569,7 +569,7 @@ var _ = Describe("Runtime Actions", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
It("Successfully upgrades recovery from directory", Label("directory"), 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
|
// create a random file on it
|
||||||
_ = fs.WriteFile(fmt.Sprintf("%s/file.file", srcDir), []byte("something"), constants.FilePerm)
|
_ = fs.WriteFile(fmt.Sprintf("%s/file.file", srcDir), []byte("something"), constants.FilePerm)
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -29,7 +30,6 @@ import (
|
|||||||
. "github.com/kairos-io/kairos-agent/v2/pkg/cloudinit"
|
. "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/constants"
|
||||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
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"
|
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||||
"github.com/twpayne/go-vfs/vfst"
|
"github.com/twpayne/go-vfs/vfst"
|
||||||
|
|
||||||
@ -110,9 +110,9 @@ stages:
|
|||||||
logger = v1.NewBufferLogger(logs)
|
logger = v1.NewBufferLogger(logs)
|
||||||
|
|
||||||
afs, cleanup, _ = vfst.NewTestFS(nil)
|
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())
|
Expect(err).To(BeNil())
|
||||||
_ = utils.MkdirAll(afs, "/dev", constants.DirPerm)
|
_ = fsutils.MkdirAll(afs, "/dev", constants.DirPerm)
|
||||||
device = "/dev/device"
|
device = "/dev/device"
|
||||||
_, err = afs.Create(device)
|
_, err = afs.Create(device)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
@ -2,17 +2,24 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"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/bundles"
|
||||||
"github.com/kairos-io/kairos-sdk/collector"
|
"github.com/kairos-io/kairos-sdk/collector"
|
||||||
"github.com/kairos-io/kairos-sdk/schema"
|
"github.com/kairos-io/kairos-sdk/schema"
|
||||||
yip "github.com/mudler/yip/pkg/schema"
|
yip "github.com/mudler/yip/pkg/schema"
|
||||||
|
"github.com/twpayne/go-vfs"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"k8s.io/mount-utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -36,6 +43,60 @@ type Install struct {
|
|||||||
BindMounts []string `yaml:"bind_mounts,omitempty"`
|
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 {
|
type Config struct {
|
||||||
Install *Install `yaml:"install,omitempty"`
|
Install *Install `yaml:"install,omitempty"`
|
||||||
collector.Config `yaml:"-"`
|
collector.Config `yaml:"-"`
|
||||||
@ -46,6 +107,148 @@ type Config struct {
|
|||||||
Bundles Bundles `yaml:"bundles,omitempty"`
|
Bundles Bundles `yaml:"bundles,omitempty"`
|
||||||
GrubOptions map[string]string `yaml:"grub_options,omitempty"`
|
GrubOptions map[string]string `yaml:"grub_options,omitempty"`
|
||||||
Env []string `yaml:"env,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
|
type Bundles []Bundle
|
||||||
@ -113,7 +316,8 @@ func FilterKeys(d []byte) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Scan(opts ...collector.Option) (c *Config, err error) {
|
func Scan(opts ...collector.Option) (c *Config, err error) {
|
||||||
result := &Config{}
|
// Init new config with some default options
|
||||||
|
result := NewConfig()
|
||||||
|
|
||||||
o := &collector.Options{}
|
o := &collector.Options{}
|
||||||
if err := o.Apply(opts...); err != nil {
|
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
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,3 +418,16 @@ func MergeYAML(objs ...interface{}) ([]byte, error) {
|
|||||||
func AddHeader(header, data string) string {
|
func AddHeader(header, data string) string {
|
||||||
return fmt.Sprintf("%s\n%s", header, data)
|
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 (
|
import (
|
||||||
"fmt"
|
"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"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
. "github.com/kairos-io/kairos-sdk/schema"
|
|
||||||
. "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
. "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
. "github.com/kairos-io/kairos-sdk/schema"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "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 {
|
func getTagName(s string) string {
|
||||||
if len(s) < 1 {
|
if len(s) < 1 {
|
||||||
return ""
|
return ""
|
||||||
@ -59,7 +45,12 @@ func getTagName(s string) string {
|
|||||||
f := func(c rune) bool {
|
f := func(c rune) bool {
|
||||||
return c == '"' || c == ','
|
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 {
|
func structContainsField(f, t string, str interface{}) bool {
|
||||||
@ -118,4 +109,91 @@ var _ = Describe("Schema", func() {
|
|||||||
structFieldsContainedInOtherStruct(Bundle{}, BundleSchema{})
|
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.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package elementalConfig
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/internal/common"
|
"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/constants"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/http"
|
|
||||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
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/mitchellh/mapstructure"
|
||||||
"github.com/sanity-io/litter"
|
"github.com/sanity-io/litter"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/viper"
|
"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)
|
// 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 firmware string
|
||||||
var recoveryImg, activeImg, passiveImg v1.Image
|
var recoveryImg, activeImg, passiveImg v1.Image
|
||||||
|
|
||||||
recoveryImgFile := filepath.Join(constants.LiveDir, constants.RecoverySquashFile)
|
recoveryImgFile := filepath.Join(constants.LiveDir, constants.RecoverySquashFile)
|
||||||
|
|
||||||
// Check if current host has EFI firmware
|
// 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
|
// 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)
|
// Check the default ISO recovery installation media is available)
|
||||||
recoveryExists, _ := utils.Exists(cfg.Fs, recoveryImgFile)
|
recoveryExists, _ := fsutils.Exists(cfg.Fs, recoveryImgFile)
|
||||||
|
|
||||||
if efiExists {
|
if efiExists {
|
||||||
firmware = v1.EFI
|
firmware = v1.EFI
|
||||||
@ -206,7 +88,7 @@ func NewInstallSpec(cfg *v1.Config) *v1.InstallSpec {
|
|||||||
return &v1.InstallSpec{
|
return &v1.InstallSpec{
|
||||||
Firmware: firmware,
|
Firmware: firmware,
|
||||||
PartTable: v1.GPT,
|
PartTable: v1.GPT,
|
||||||
Partitions: NewInstallElementalParitions(),
|
Partitions: NewInstallElementalPartitions(),
|
||||||
GrubConf: constants.GrubConf,
|
GrubConf: constants.GrubConf,
|
||||||
Tty: constants.DefaultTty,
|
Tty: constants.DefaultTty,
|
||||||
Active: activeImg,
|
Active: activeImg,
|
||||||
@ -215,9 +97,9 @@ func NewInstallSpec(cfg *v1.Config) *v1.InstallSpec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInstallElementalParitions() v1.ElementalPartitions {
|
func NewInstallElementalPartitions() v1.ElementalPartitions {
|
||||||
partitions := v1.ElementalPartitions{}
|
pt := v1.ElementalPartitions{}
|
||||||
partitions.OEM = &v1.Partition{
|
pt.OEM = &v1.Partition{
|
||||||
FilesystemLabel: constants.OEMLabel,
|
FilesystemLabel: constants.OEMLabel,
|
||||||
Size: constants.OEMSize,
|
Size: constants.OEMSize,
|
||||||
Name: constants.OEMPartName,
|
Name: constants.OEMPartName,
|
||||||
@ -226,7 +108,7 @@ func NewInstallElementalParitions() v1.ElementalPartitions {
|
|||||||
Flags: []string{},
|
Flags: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
partitions.Recovery = &v1.Partition{
|
pt.Recovery = &v1.Partition{
|
||||||
FilesystemLabel: constants.RecoveryLabel,
|
FilesystemLabel: constants.RecoveryLabel,
|
||||||
Size: constants.RecoverySize,
|
Size: constants.RecoverySize,
|
||||||
Name: constants.RecoveryPartName,
|
Name: constants.RecoveryPartName,
|
||||||
@ -235,7 +117,7 @@ func NewInstallElementalParitions() v1.ElementalPartitions {
|
|||||||
Flags: []string{},
|
Flags: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
partitions.State = &v1.Partition{
|
pt.State = &v1.Partition{
|
||||||
FilesystemLabel: constants.StateLabel,
|
FilesystemLabel: constants.StateLabel,
|
||||||
Size: constants.StateSize,
|
Size: constants.StateSize,
|
||||||
Name: constants.StatePartName,
|
Name: constants.StatePartName,
|
||||||
@ -244,7 +126,7 @@ func NewInstallElementalParitions() v1.ElementalPartitions {
|
|||||||
Flags: []string{},
|
Flags: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
partitions.Persistent = &v1.Partition{
|
pt.Persistent = &v1.Partition{
|
||||||
FilesystemLabel: constants.PersistentLabel,
|
FilesystemLabel: constants.PersistentLabel,
|
||||||
Size: constants.PersistentSize,
|
Size: constants.PersistentSize,
|
||||||
Name: constants.PersistentPartName,
|
Name: constants.PersistentPartName,
|
||||||
@ -252,11 +134,11 @@ func NewInstallElementalParitions() v1.ElementalPartitions {
|
|||||||
MountPoint: constants.PersistentDir,
|
MountPoint: constants.PersistentDir,
|
||||||
Flags: []string{},
|
Flags: []string{},
|
||||||
}
|
}
|
||||||
return partitions
|
return pt
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUpgradeSpec returns an UpgradeSpec struct all based on defaults and current host state
|
// 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 recLabel, recFs, recMnt string
|
||||||
var active, passive, recovery v1.Image
|
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())
|
cfg.Logger.Warnf("failed reading installation state: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
parts, err := utils.GetAllPartitions()
|
parts, err := partitions.GetAllPartitions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not read host partitions")
|
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 {
|
if ep.Recovery == nil {
|
||||||
// We could have recovery in lvm which won't appear in ghw list
|
// 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 {
|
if ep.OEM == nil {
|
||||||
// We could have OEM in lvm which won't appear in ghw list
|
// 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 {
|
if ep.Persistent == nil {
|
||||||
// We could have persistent encrypted or in lvm which won't appear in ghw list
|
// 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 {
|
if ep.Recovery != nil {
|
||||||
@ -291,7 +173,7 @@ func NewUpgradeSpec(cfg *v1.Config) (*v1.UpgradeSpec, error) {
|
|||||||
ep.Recovery.MountPoint = constants.RecoveryDir
|
ep.Recovery.MountPoint = constants.RecoveryDir
|
||||||
}
|
}
|
||||||
|
|
||||||
squashedRec, err := utils.HasSquashedRecovery(cfg, ep.Recovery)
|
squashedRec, err := hasSquashedRecovery(cfg, ep.Recovery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed checking for squashed recovery")
|
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
|
// 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
|
var imgSource *v1.ImageSource
|
||||||
|
|
||||||
//TODO find a way to pre-load current state values such as labels
|
//TODO find a way to pre-load current state values such as labels
|
||||||
if !utils.BootedFrom(cfg.Runner, constants.RecoverySquashFile) &&
|
if !BootedFrom(cfg.Runner, constants.RecoverySquashFile) &&
|
||||||
!utils.BootedFrom(cfg.Runner, constants.SystemLabel) {
|
!BootedFrom(cfg.Runner, constants.SystemLabel) {
|
||||||
return nil, fmt.Errorf("reset can only be called from the recovery system")
|
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()
|
installState, err := cfg.LoadInstallState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cfg.Logger.Warnf("failed reading installation state: %s", err.Error())
|
cfg.Logger.Warnf("failed reading installation state: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
parts, err := utils.GetAllPartitions()
|
parts, err := partitions.GetAllPartitions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not read host partitions")
|
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 {
|
if ep.Recovery == nil {
|
||||||
// We could have recovery in lvm which won't appear in ghw list
|
// 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 {
|
if ep.Recovery == nil {
|
||||||
return nil, fmt.Errorf("recovery partition not found")
|
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
|
ep.OEM.Name = constants.OEMPartName
|
||||||
} else {
|
} else {
|
||||||
// We could have oem in lvm which won't appear in ghw list
|
// 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 {
|
if ep.OEM == nil {
|
||||||
@ -437,7 +319,7 @@ func NewResetSpec(cfg *v1.Config) (*v1.ResetSpec, error) {
|
|||||||
ep.Persistent.Name = constants.PersistentPartName
|
ep.Persistent.Name = constants.PersistentPartName
|
||||||
} else {
|
} else {
|
||||||
// We could have persistent encrypted or in lvm which won't appear in ghw list
|
// 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 {
|
if ep.Persistent == nil {
|
||||||
cfg.Logger.Warnf("no Persistent partition found")
|
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)
|
recoveryImg := filepath.Join(constants.RunningStateDir, "cOS", constants.RecoveryImgFile)
|
||||||
recoveryImg2 := filepath.Join(constants.RunningRecoveryStateDir, "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)
|
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)
|
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)
|
imgSource = v1.NewDirSrc(constants.IsoBaseTree)
|
||||||
} else {
|
} else {
|
||||||
imgSource = v1.NewEmptySrc()
|
imgSource = v1.NewEmptySrc()
|
||||||
@ -484,35 +366,38 @@ func NewResetSpec(cfg *v1.Config) (*v1.ResetSpec, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadConfigRunFromAgentConfig reads the configuration directly from a given cloud config string
|
// ReadResetSpecFromConfig will return a proper v1.ResetSpec based on an agent Config
|
||||||
func ReadConfigRunFromAgentConfig(c *agentConfig.Config) (*v1.Config, error) {
|
func ReadResetSpecFromConfig(c *Config) (*v1.ResetSpec, error) {
|
||||||
cfg := NewConfig(WithLogger(v1.NewLogger()), WithImageExtractor(v1.OCIImageExtractor{}))
|
sp, err := ReadSpecFromCloudConfig(c, "reset")
|
||||||
var err error
|
|
||||||
|
|
||||||
ccString, err := c.Config.String()
|
|
||||||
if err != nil {
|
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
|
// ReadInstallSpecFromConfig will return a proper v1.InstallSpec based on an agent Config
|
||||||
err = yaml.Unmarshal([]byte(ccString), &cfg)
|
func ReadInstallSpecFromConfig(c *Config) (*v1.InstallSpec, error) {
|
||||||
|
sp, err := ReadSpecFromCloudConfig(c, "install")
|
||||||
if err != nil {
|
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
|
installSpec := sp.(*v1.InstallSpec)
|
||||||
if cfg.Debug {
|
return installSpec, nil
|
||||||
viper.Set("debug", true)
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
configLogger(cfg.Logger, cfg.Fs)
|
upgradeSpec := sp.(*v1.UpgradeSpec)
|
||||||
// Store the full cloud-config in here, so we can reuse it afterward for the spec
|
return upgradeSpec, nil
|
||||||
cfg.FullCloudConfig = ccString
|
|
||||||
err = cfg.Sanitize()
|
|
||||||
cfg.Logger.Debugf("Full config loaded: %s", litter.Sdump(cfg))
|
|
||||||
return cfg, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadSpecFromCloudConfig returns a v1.Spec for the given spec
|
// 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 sp v1.Spec
|
||||||
var err error
|
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
|
// 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.SetConfigType("yaml")
|
||||||
viper.ReadConfig(strings.NewReader(r.FullCloudConfig))
|
viper.ReadConfig(strings.NewReader(ccString))
|
||||||
vp := viper.Sub(spec)
|
vp := viper.Sub(spec)
|
||||||
if vp == nil {
|
if vp == nil {
|
||||||
vp = viper.New()
|
vp = viper.New()
|
||||||
@ -546,47 +435,6 @@ func ReadSpecFromCloudConfig(r *v1.Config, spec string) (v1.Spec, error) {
|
|||||||
return sp, err
|
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) {
|
func configLogger(log v1.Logger, vfs v1.FS) {
|
||||||
// Set debug level
|
// Set debug level
|
||||||
if viper.GetBool("debug") {
|
if viper.GetBool("debug") {
|
||||||
@ -676,3 +524,52 @@ func setDecoder(config *mapstructure.DecoderConfig) {
|
|||||||
// we got form configs.
|
// we got form configs.
|
||||||
config.ZeroFields = true
|
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.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package elementalConfig_test
|
package config_test
|
||||||
|
|
||||||
import (
|
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/kairos-io/kairos-sdk/collector"
|
||||||
|
"github.com/sanity-io/litter"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"k8s.io/mount-utils"
|
"k8s.io/mount-utils"
|
||||||
"os"
|
"os"
|
||||||
@ -26,9 +29,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jaypipes/ghw/pkg/block"
|
"github.com/jaypipes/ghw/pkg/block"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"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"
|
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"
|
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@ -46,7 +47,7 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
var sysc *v1mock.FakeSyscall
|
var sysc *v1mock.FakeSyscall
|
||||||
var logger v1.Logger
|
var logger v1.Logger
|
||||||
var ci *v1mock.FakeCloudInitRunner
|
var ci *v1mock.FakeCloudInitRunner
|
||||||
var c *v1.Config
|
var c *config.Config
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
fs, cleanup, err = vfst.NewTestFS(nil)
|
fs, cleanup, err = vfst.NewTestFS(nil)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -56,15 +57,15 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
sysc = &v1mock.FakeSyscall{}
|
sysc = &v1mock.FakeSyscall{}
|
||||||
logger = v1.NewNullLogger()
|
logger = v1.NewNullLogger()
|
||||||
ci = &v1mock.FakeCloudInitRunner{}
|
ci = &v1mock.FakeCloudInitRunner{}
|
||||||
c = elementalConfig.NewConfig(
|
c = config.NewConfig(
|
||||||
elementalConfig.WithFs(fs),
|
config.WithFs(fs),
|
||||||
elementalConfig.WithMounter(mounter),
|
config.WithMounter(mounter),
|
||||||
elementalConfig.WithRunner(runner),
|
config.WithRunner(runner),
|
||||||
elementalConfig.WithSyscall(sysc),
|
config.WithSyscall(sysc),
|
||||||
elementalConfig.WithLogger(logger),
|
config.WithLogger(logger),
|
||||||
elementalConfig.WithCloudInitRunner(ci),
|
config.WithCloudInitRunner(ci),
|
||||||
elementalConfig.WithClient(client),
|
config.WithClient(client),
|
||||||
elementalConfig.WithPlatform("linux/arm64"),
|
config.WithPlatform("linux/arm64"),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
AfterEach(func() {
|
AfterEach(func() {
|
||||||
@ -87,24 +88,24 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
fs, cleanup, err := vfst.NewTestFS(nil)
|
fs, cleanup, err := vfst.NewTestFS(nil)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
c := elementalConfig.NewConfig(
|
c := config.NewConfig(
|
||||||
elementalConfig.WithFs(fs),
|
config.WithFs(fs),
|
||||||
elementalConfig.WithMounter(mounter),
|
config.WithMounter(mounter),
|
||||||
)
|
)
|
||||||
Expect(c.Fs).To(Equal(fs))
|
Expect(c.Fs).To(Equal(fs))
|
||||||
Expect(c.Mounter).To(Equal(mounter))
|
Expect(c.Mounter).To(Equal(mounter))
|
||||||
Expect(c.Runner).ToNot(BeNil())
|
Expect(c.Runner).ToNot(BeNil())
|
||||||
})
|
})
|
||||||
It("defaults to sane platform if the platform is broken", func() {
|
It("defaults to sane platform if the platform is broken", func() {
|
||||||
c = elementalConfig.NewConfig(
|
c = config.NewConfig(
|
||||||
elementalConfig.WithFs(fs),
|
config.WithFs(fs),
|
||||||
elementalConfig.WithMounter(mounter),
|
config.WithMounter(mounter),
|
||||||
elementalConfig.WithRunner(runner),
|
config.WithRunner(runner),
|
||||||
elementalConfig.WithSyscall(sysc),
|
config.WithSyscall(sysc),
|
||||||
elementalConfig.WithLogger(logger),
|
config.WithLogger(logger),
|
||||||
elementalConfig.WithCloudInitRunner(ci),
|
config.WithCloudInitRunner(ci),
|
||||||
elementalConfig.WithClient(client),
|
config.WithClient(client),
|
||||||
elementalConfig.WithPlatform("wwwwwww"),
|
config.WithPlatform("wwwwwww"),
|
||||||
)
|
)
|
||||||
Expect(c.Platform.OS).To(Equal("linux"))
|
Expect(c.Platform.OS).To(Equal("linux"))
|
||||||
Expect(c.Platform.Arch).To(Equal("x86_64"))
|
Expect(c.Platform.Arch).To(Equal("x86_64"))
|
||||||
@ -116,41 +117,41 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
runner := v1mock.NewFakeRunner()
|
runner := v1mock.NewFakeRunner()
|
||||||
sysc := &v1mock.FakeSyscall{}
|
sysc := &v1mock.FakeSyscall{}
|
||||||
logger := v1.NewNullLogger()
|
logger := v1.NewNullLogger()
|
||||||
c := elementalConfig.NewConfig(
|
c := config.NewConfig(
|
||||||
elementalConfig.WithRunner(runner),
|
config.WithRunner(runner),
|
||||||
elementalConfig.WithSyscall(sysc),
|
config.WithSyscall(sysc),
|
||||||
elementalConfig.WithLogger(logger),
|
config.WithLogger(logger),
|
||||||
)
|
)
|
||||||
Expect(c.Mounter).To(Equal(mount.New(constants.MountBinary)))
|
Expect(c.Mounter).To(Equal(mount.New(constants.MountBinary)))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
Describe("Config", func() {
|
Describe("Config", func() {
|
||||||
cfg := elementalConfig.NewConfig(elementalConfig.WithMounter(mounter))
|
cfg := config.NewConfig(config.WithMounter(mounter))
|
||||||
Expect(cfg.Mounter).To(Equal(mounter))
|
Expect(cfg.Mounter).To(Equal(mounter))
|
||||||
Expect(cfg.Runner).NotTo(BeNil())
|
Expect(cfg.Runner).NotTo(BeNil())
|
||||||
})
|
})
|
||||||
Describe("InstallSpec", func() {
|
Describe("InstallSpec", func() {
|
||||||
It("sets installation defaults from install efi media with recovery", Label("install", "efi"), func() {
|
It("sets installation defaults from install efi media with recovery", Label("install", "efi"), func() {
|
||||||
// Set EFI firmware detection
|
// 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(constants.EfiDevice)
|
_, err = fs.Create(constants.EfiDevice)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
// Set ISO base tree detection
|
// 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(constants.IsoBaseTree)
|
_, err = fs.Create(constants.IsoBaseTree)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
// Set recovery image detection detection
|
// Set recovery image detection detection
|
||||||
recoveryImgFile := filepath.Join(constants.LiveDir, constants.RecoverySquashFile)
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(recoveryImgFile)
|
_, err = fs.Create(recoveryImgFile)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec := elementalConfig.NewInstallSpec(c)
|
spec := config.NewInstallSpec(c)
|
||||||
Expect(spec.Firmware).To(Equal(v1.EFI))
|
Expect(spec.Firmware).To(Equal(v1.EFI))
|
||||||
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
||||||
Expect(spec.Recovery.Source.Value()).To(Equal(recoveryImgFile))
|
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() {
|
It("sets installation defaults from install bios media without recovery", Label("install", "bios"), func() {
|
||||||
// Set ISO base tree detection
|
// 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(constants.IsoBaseTree)
|
_, err = fs.Create(constants.IsoBaseTree)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec := elementalConfig.NewInstallSpec(c)
|
spec := config.NewInstallSpec(c)
|
||||||
Expect(spec.Firmware).To(Equal(v1.BIOS))
|
Expect(spec.Firmware).To(Equal(v1.BIOS))
|
||||||
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
||||||
Expect(spec.Recovery.Source.Value()).To(Equal(spec.Active.File))
|
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())
|
Expect(spec.Partitions.BIOS).NotTo(BeNil())
|
||||||
})
|
})
|
||||||
It("sets installation defaults without being on installation media", Label("install"), func() {
|
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.Firmware).To(Equal(v1.BIOS))
|
||||||
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
||||||
Expect(spec.Recovery.Source.Value()).To(Equal(spec.Active.File))
|
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() {
|
It("sets reset defaults on efi from squashed recovery", func() {
|
||||||
// Set EFI firmware detection
|
// 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(constants.EfiDevice)
|
_, err = fs.Create(constants.EfiDevice)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
// Set squashfs detection
|
// 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(constants.IsoBaseTree)
|
_, err = fs.Create(constants.IsoBaseTree)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec, err := elementalConfig.NewResetSpec(c)
|
spec, err := config.NewResetSpec(c)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
Expect(spec.Active.Source.Value()).To(Equal(constants.IsoBaseTree))
|
||||||
Expect(spec.Partitions.EFI.MountPoint).To(Equal(constants.EfiDir))
|
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() {
|
It("sets reset defaults on bios from non-squashed recovery", func() {
|
||||||
// Set non-squashfs recovery image detection
|
// Set non-squashfs recovery image detection
|
||||||
recoveryImg := filepath.Join(constants.RunningStateDir, "cOS", constants.RecoveryImgFile)
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(recoveryImg)
|
_, err = fs.Create(recoveryImg)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec, err := elementalConfig.NewResetSpec(c)
|
spec, err := config.NewResetSpec(c)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
Expect(spec.Active.Source.Value()).To(Equal(recoveryImg))
|
Expect(spec.Active.Source.Value()).To(Equal(recoveryImg))
|
||||||
})
|
})
|
||||||
It("sets reset defaults on bios from unknown recovery", func() {
|
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(err).ShouldNot(HaveOccurred())
|
||||||
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
||||||
})
|
})
|
||||||
@ -312,13 +313,13 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
ghwTest.Clean()
|
ghwTest.Clean()
|
||||||
})
|
})
|
||||||
It("fails to set defaults if not booted from recovery", func() {
|
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).Should(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("reset can only be called from the recovery system"))
|
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() {
|
It("fails to set defaults if no recovery partition detected", func() {
|
||||||
bootedFrom = constants.SystemLabel
|
bootedFrom = constants.SystemLabel
|
||||||
_, err := elementalConfig.NewResetSpec(c)
|
_, err := config.NewResetSpec(c)
|
||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("recovery partition not found"))
|
Expect(err.Error()).To(ContainSubstring("recovery partition not found"))
|
||||||
})
|
})
|
||||||
@ -333,19 +334,19 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
defer ghwTest.Clean()
|
defer ghwTest.Clean()
|
||||||
|
|
||||||
bootedFrom = constants.SystemLabel
|
bootedFrom = constants.SystemLabel
|
||||||
_, err := elementalConfig.NewResetSpec(c)
|
_, err := config.NewResetSpec(c)
|
||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("state partition not found"))
|
Expect(err.Error()).To(ContainSubstring("state partition not found"))
|
||||||
})
|
})
|
||||||
It("fails to set defaults if no efi partition on efi firmware", func() {
|
It("fails to set defaults if no efi partition on efi firmware", func() {
|
||||||
// Set EFI firmware detection
|
// 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(constants.EfiDevice)
|
_, err = fs.Create(constants.EfiDevice)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
bootedFrom = constants.SystemLabel
|
bootedFrom = constants.SystemLabel
|
||||||
_, err := elementalConfig.NewResetSpec(c)
|
_, err := config.NewResetSpec(c)
|
||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("EFI partition not found"))
|
Expect(err.Error()).To(ContainSubstring("EFI partition not found"))
|
||||||
})
|
})
|
||||||
@ -394,12 +395,12 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
ghwTest.Clean()
|
ghwTest.Clean()
|
||||||
})
|
})
|
||||||
It("sets upgrade defaults for active upgrade", func() {
|
It("sets upgrade defaults for active upgrade", func() {
|
||||||
spec, err := elementalConfig.NewUpgradeSpec(c)
|
spec, err := config.NewUpgradeSpec(c)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
Expect(spec.Active.Source.IsEmpty()).To(BeTrue())
|
||||||
})
|
})
|
||||||
It("sets upgrade defaults for non-squashed recovery upgrade", func() {
|
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(err).ShouldNot(HaveOccurred())
|
||||||
Expect(spec.Recovery.Source.IsEmpty()).To(BeTrue())
|
Expect(spec.Recovery.Source.IsEmpty()).To(BeTrue())
|
||||||
Expect(spec.Recovery.FS).To(Equal(constants.LinuxImgFs))
|
Expect(spec.Recovery.FS).To(Equal(constants.LinuxImgFs))
|
||||||
@ -408,12 +409,12 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
//Set squashed recovery detection
|
//Set squashed recovery detection
|
||||||
mounter.Mount("device3", constants.LiveDir, "auto", []string{})
|
mounter.Mount("device3", constants.LiveDir, "auto", []string{})
|
||||||
img := filepath.Join(constants.LiveDir, "cOS", constants.RecoverySquashFile)
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(img)
|
_, err = fs.Create(img)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
spec, err := elementalConfig.NewUpgradeSpec(c)
|
spec, err := config.NewUpgradeSpec(c)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
Expect(spec.Recovery.Source.IsEmpty()).To(BeTrue())
|
Expect(spec.Recovery.Source.IsEmpty()).To(BeTrue())
|
||||||
Expect(spec.Recovery.FS).To(Equal(constants.SquashFs))
|
Expect(spec.Recovery.FS).To(Equal(constants.SquashFs))
|
||||||
@ -501,25 +502,25 @@ cloud-init-paths:
|
|||||||
It("Reads properly the cloud config for install", func() {
|
It("Reads properly the cloud config for install", func() {
|
||||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
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(err).ToNot(HaveOccurred())
|
||||||
Expect(installConfig.Strict).To(BeTrue())
|
Expect(cfg.Strict).To(BeTrue())
|
||||||
Expect(installSpec.GrubDefEntry).To(Equal("MyCustomOS"))
|
Expect(installSpec.GrubDefEntry).To(Equal("MyCustomOS"))
|
||||||
Expect(installSpec.Active.Size).To(Equal(uint(666)))
|
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() {
|
It("Reads properly the cloud config for reset", func() {
|
||||||
bootedFrom = constants.SystemLabel
|
bootedFrom = constants.SystemLabel
|
||||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||||
config, err := elementalConfig.ReadConfigRunFromAgentConfig(cfg)
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
// Override the config with our test params
|
// Override the config with our test params
|
||||||
config.Runner = runner
|
cfg.Runner = runner
|
||||||
config.Fs = fs
|
cfg.Fs = fs
|
||||||
config.Mounter = mounter
|
cfg.Mounter = mounter
|
||||||
config.CloudInitRunner = ci
|
cfg.CloudInitRunner = ci
|
||||||
spec, err := elementalConfig.ReadSpecFromCloudConfig(config, "reset")
|
spec, err := config.ReadSpecFromCloudConfig(cfg, "reset")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
resetSpec := spec.(*v1.ResetSpec)
|
resetSpec := spec.(*v1.ResetSpec)
|
||||||
Expect(resetSpec.FormatPersistent).To(BeTrue())
|
Expect(resetSpec.FormatPersistent).To(BeTrue())
|
||||||
@ -528,32 +529,28 @@ cloud-init-paths:
|
|||||||
})
|
})
|
||||||
It("Reads properly the cloud config for upgrade", func() {
|
It("Reads properly the cloud config for upgrade", func() {
|
||||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||||
config, err := elementalConfig.ReadConfigRunFromAgentConfig(cfg)
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
// Override the config with our test params
|
// Override the config with our test params
|
||||||
config.Runner = runner
|
cfg.Runner = runner
|
||||||
config.Fs = fs
|
cfg.Fs = fs
|
||||||
config.Mounter = mounter
|
cfg.Mounter = mounter
|
||||||
config.CloudInitRunner = ci
|
cfg.CloudInitRunner = ci
|
||||||
spec, err := elementalConfig.ReadSpecFromCloudConfig(config, "upgrade")
|
spec, err := config.ReadSpecFromCloudConfig(cfg, "upgrade")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
upgradeSpec := spec.(*v1.UpgradeSpec)
|
upgradeSpec := spec.(*v1.UpgradeSpec)
|
||||||
Expect(upgradeSpec.RecoveryUpgrade).To(BeTrue())
|
Expect(upgradeSpec.RecoveryUpgrade).To(BeTrue())
|
||||||
})
|
})
|
||||||
It("Fails when a wrong action is read", func() {
|
It("Fails when a wrong action is read", func() {
|
||||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||||
config, err := elementalConfig.ReadConfigRunFromAgentConfig(cfg)
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = elementalConfig.ReadSpecFromCloudConfig(config, "nope")
|
_, err = config.ReadSpecFromCloudConfig(cfg, "nope")
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
})
|
})
|
||||||
It("Sets info level if its not on the cloud-config", func() {
|
It("Sets info level if its not on the cloud-config", func() {
|
||||||
// Now again but with no config
|
// Now again but with no config
|
||||||
cfg, err := config.Scan(collector.Directories([]string{""}...), collector.NoLogs)
|
cfg, err := config.Scan(collector.Directories([]string{""}...), collector.NoLogs)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
installConfig, _, err := elementalConfig.ReadInstallConfigFromAgentConfig(cfg)
|
Expect(cfg.Logger.GetLevel()).To(Equal(logrus.InfoLevel))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
Expect(installConfig.Logger.GetLevel()).To(Equal(logrus.InfoLevel))
|
|
||||||
})
|
})
|
||||||
It("Sets debug level if its on the cloud-config", func() {
|
It("Sets debug level if its on the cloud-config", func() {
|
||||||
ccdata := []byte(`#cloud-config
|
ccdata := []byte(`#cloud-config
|
||||||
@ -563,11 +560,19 @@ debug: true
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
cfg, err := config.Scan(collector.Directories([]string{dir}...), collector.NoLogs)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
installConfig, _, err := elementalConfig.ReadInstallConfigFromAgentConfig(cfg)
|
Expect(cfg.Logger.GetLevel()).To(Equal(logrus.DebugLevel))
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
Expect(installConfig.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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
cnst "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/partitioner"
|
"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"
|
"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
|
// Elemental is the struct meant to self-contain most utils and actions related to Elemental, like installing or applying selinux
|
||||||
type Elemental struct {
|
type Elemental struct {
|
||||||
config *v1.Config
|
config *agentConfig.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewElemental(config *v1.Config) *Elemental {
|
func NewElemental(config *agentConfig.Config) *Elemental {
|
||||||
return &Elemental{
|
return &Elemental{
|
||||||
config: config,
|
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
|
// MountPartition mounts a partition with the given mount options
|
||||||
func (e Elemental) MountPartition(part *v1.Partition, opts ...string) error {
|
func (e Elemental) MountPartition(part *v1.Partition, opts ...string) error {
|
||||||
e.config.Logger.Debugf("Mounting partition %s", part.FilesystemLabel)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -211,7 +213,7 @@ func (e Elemental) UnmountPartition(part *v1.Partition) error {
|
|||||||
// MountImage mounts an image with the given mount options
|
// MountImage mounts an image with the given mount options
|
||||||
func (e Elemental) MountImage(img *v1.Image, opts ...string) error {
|
func (e Elemental) MountImage(img *v1.Image, opts ...string) error {
|
||||||
e.config.Logger.Debugf("Mounting image %s", img.Label)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -251,7 +253,7 @@ func (e Elemental) UnmountImage(img *v1.Image) error {
|
|||||||
// CreateFileSystemImage creates the image file for config.target
|
// CreateFileSystemImage creates the image file for config.target
|
||||||
func (e Elemental) CreateFileSystemImage(img *v1.Image) error {
|
func (e Elemental) CreateFileSystemImage(img *v1.Image) error {
|
||||||
e.config.Logger.Infof("Creating file system image %s", img.File)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -298,7 +300,7 @@ func (e *Elemental) DeployImage(img *v1.Image, leaveMounted bool) (info interfac
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target = utils.GetTempDir(e.config, "")
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -374,7 +376,7 @@ func (e *Elemental) DumpSource(target string, imgSrc *v1.ImageSource) (info inte
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else if imgSrc.IsFile() {
|
} 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -412,7 +414,7 @@ func (e *Elemental) CopyCloudConfig(cloudInit []string) (err error) {
|
|||||||
func (e *Elemental) SelinuxRelabel(rootDir string, raiseError bool) error {
|
func (e *Elemental) SelinuxRelabel(rootDir string, raiseError bool) error {
|
||||||
policyFile, err := utils.FindFileWithPrefix(e.config.Fs, filepath.Join(rootDir, cnst.SELinuxTargetedPolicyPath), "policy.")
|
policyFile, err := utils.FindFileWithPrefix(e.config.Fs, filepath.Join(rootDir, cnst.SELinuxTargetedPolicyPath), "policy.")
|
||||||
contextFile := filepath.Join(rootDir, cnst.SELinuxTargetedContextFile)
|
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") {
|
if err == nil && contextExists && utils.CommandExists("setfiles") {
|
||||||
var out []byte
|
var out []byte
|
||||||
@ -452,7 +454,7 @@ func (e *Elemental) CheckActiveDeployment(labels []string) bool {
|
|||||||
// in cnst.DownloadedIsoMnt
|
// in cnst.DownloadedIsoMnt
|
||||||
func (e *Elemental) GetIso(iso string) (tmpDir string, err error) {
|
func (e *Elemental) GetIso(iso string) (tmpDir string, err error) {
|
||||||
//TODO support ISO download in persistent storage?
|
//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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -470,7 +472,7 @@ func (e *Elemental) GetIso(iso string) (tmpDir string, err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
err = utils.MkdirAll(e.config.Fs, isoMnt, cnst.DirPerm)
|
err = fsutils.MkdirAll(e.config.Fs, isoMnt, cnst.DirPerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
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)
|
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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -505,7 +507,7 @@ func (e Elemental) UpdateSourcesFormDownloadedISO(workDir string, activeImg *v1.
|
|||||||
}
|
}
|
||||||
if recoveryImg != nil {
|
if recoveryImg != nil {
|
||||||
squashedImgSource := filepath.Join(isoMnt, cnst.RecoverySquashFile)
|
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.Source = v1.NewFileSrc(squashedImgSource)
|
||||||
recoveryImg.FS = cnst.SquashFs
|
recoveryImg.FS = cnst.SquashFs
|
||||||
} else if activeImg != nil {
|
} else if activeImg != nil {
|
||||||
|
@ -19,6 +19,8 @@ package elemental_test
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@ -28,7 +30,6 @@ import (
|
|||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||||
cnst "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"
|
"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"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
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 _ = Describe("Elemental", Label("elemental"), func() {
|
||||||
var config *v1.Config
|
var config *agentConfig.Config
|
||||||
var runner *v1mock.FakeRunner
|
var runner *v1mock.FakeRunner
|
||||||
var logger v1.Logger
|
var logger v1.Logger
|
||||||
var syscall v1.SyscallInterface
|
var syscall v1.SyscallInterface
|
||||||
@ -67,14 +68,14 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
logger = v1.NewNullLogger()
|
logger = v1.NewNullLogger()
|
||||||
fs, cleanup, _ = vfst.NewTestFS(nil)
|
fs, cleanup, _ = vfst.NewTestFS(nil)
|
||||||
extractor = v1mock.NewFakeImageExtractor(logger)
|
extractor = v1mock.NewFakeImageExtractor(logger)
|
||||||
config = conf.NewConfig(
|
config = agentConfig.NewConfig(
|
||||||
conf.WithFs(fs),
|
agentConfig.WithFs(fs),
|
||||||
conf.WithRunner(runner),
|
agentConfig.WithRunner(runner),
|
||||||
conf.WithLogger(logger),
|
agentConfig.WithLogger(logger),
|
||||||
conf.WithMounter(mounter),
|
agentConfig.WithMounter(mounter),
|
||||||
conf.WithSyscall(syscall),
|
agentConfig.WithSyscall(syscall),
|
||||||
conf.WithClient(client),
|
agentConfig.WithClient(client),
|
||||||
conf.WithImageExtractor(extractor),
|
agentConfig.WithImageExtractor(extractor),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
AfterEach(func() { cleanup() })
|
AfterEach(func() { cleanup() })
|
||||||
@ -82,9 +83,9 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
var el *elemental.Elemental
|
var el *elemental.Elemental
|
||||||
var parts v1.ElementalPartitions
|
var parts v1.ElementalPartitions
|
||||||
BeforeEach(func() {
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = fs.Create("/some/device")
|
_, err = fs.Create("/some/device")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -146,9 +147,9 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
var el *elemental.Elemental
|
var el *elemental.Elemental
|
||||||
var parts v1.ElementalPartitions
|
var parts v1.ElementalPartitions
|
||||||
BeforeEach(func() {
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = fs.Create("/some/device")
|
_, err = fs.Create("/some/device")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -194,9 +195,9 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
var el *elemental.Elemental
|
var el *elemental.Elemental
|
||||||
var parts v1.ElementalPartitions
|
var parts v1.ElementalPartitions
|
||||||
BeforeEach(func() {
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = fs.Create("/some/device")
|
_, err = fs.Create("/some/device")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -292,7 +293,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
MountPoint: cnst.ActiveDir,
|
MountPoint: cnst.ActiveDir,
|
||||||
Source: v1.NewDirSrc(cnst.IsoBaseTree),
|
Source: v1.NewDirSrc(cnst.IsoBaseTree),
|
||||||
}
|
}
|
||||||
_ = utils.MkdirAll(fs, cnst.IsoBaseTree, cnst.DirPerm)
|
_ = fsutils.MkdirAll(fs, cnst.IsoBaseTree, cnst.DirPerm)
|
||||||
el = elemental.NewElemental(config)
|
el = elemental.NewElemental(config)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -341,10 +342,10 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
cInit = &v1mock.FakeCloudInitRunner{ExecStages: []string{}, Error: false}
|
cInit = &v1mock.FakeCloudInitRunner{ExecStages: []string{}, Error: false}
|
||||||
config.CloudInitRunner = cInit
|
config.CloudInitRunner = cInit
|
||||||
el = elemental.NewElemental(config)
|
el = elemental.NewElemental(config)
|
||||||
install = conf.NewInstallSpec(config)
|
install = agentConfig.NewInstallSpec(config)
|
||||||
install.Target = "/some/device"
|
install.Target = "/some/device"
|
||||||
|
|
||||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_, err = fs.Create("/some/device")
|
_, err = fs.Create("/some/device")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -355,7 +356,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
var efiPartCmds, partCmds, biosPartCmds [][]string
|
var efiPartCmds, partCmds, biosPartCmds [][]string
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
partNum, printOut = 0, printOutput
|
partNum, printOut = 0, printOutput
|
||||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
efiPartCmds = [][]string{
|
efiPartCmds = [][]string{
|
||||||
{
|
{
|
||||||
@ -435,7 +436,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
Describe("Run with failures", func() {
|
Describe("Run with failures", func() {
|
||||||
var runFunc func(cmd string, args ...string) ([]byte, error)
|
var runFunc func(cmd string, args ...string) ([]byte, error)
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
err := utils.MkdirAll(fs, "/some", cnst.DirPerm)
|
err := fsutils.MkdirAll(fs, "/some", cnst.DirPerm)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
partNum, printOut = 0, printOutput
|
partNum, printOut = 0, printOutput
|
||||||
runFunc = func(cmd string, args ...string) ([]byte, error) {
|
runFunc = func(cmd string, args ...string) ([]byte, error) {
|
||||||
@ -486,9 +487,9 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
var img *v1.Image
|
var img *v1.Image
|
||||||
var cmdFail string
|
var cmdFail string
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
sourceDir, err := utils.TempDir(fs, "", "elemental")
|
sourceDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
destDir, err := utils.TempDir(fs, "", "elemental")
|
destDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
cmdFail = ""
|
cmdFail = ""
|
||||||
el = elemental.NewElemental(config)
|
el = elemental.NewElemental(config)
|
||||||
@ -532,7 +533,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
sourceImg := "/source.img"
|
sourceImg := "/source.img"
|
||||||
_, err := fs.Create(sourceImg)
|
_, err := fs.Create(sourceImg)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
destDir, err := utils.TempDir(fs, "", "elemental")
|
destDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
img.Source = v1.NewFileSrc(sourceImg)
|
img.Source = v1.NewFileSrc(sourceImg)
|
||||||
img.MountPoint = destDir
|
img.MountPoint = destDir
|
||||||
@ -542,7 +543,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
sourceImg := "/source.img"
|
sourceImg := "/source.img"
|
||||||
_, err := fs.Create(sourceImg)
|
_, err := fs.Create(sourceImg)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
destDir, err := utils.TempDir(fs, "", "elemental")
|
destDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
img.Source = v1.NewFileSrc(sourceImg)
|
img.Source = v1.NewFileSrc(sourceImg)
|
||||||
img.MountPoint = destDir
|
img.MountPoint = destDir
|
||||||
@ -554,7 +555,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
sourceImg := "/source.img"
|
sourceImg := "/source.img"
|
||||||
_, err := fs.Create(sourceImg)
|
_, err := fs.Create(sourceImg)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
destDir, err := utils.TempDir(fs, "", "elemental")
|
destDir, err := fsutils.TempDir(fs, "", "elemental")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
img.Source = v1.NewFileSrc(sourceImg)
|
img.Source = v1.NewFileSrc(sourceImg)
|
||||||
img.MountPoint = destDir
|
img.MountPoint = destDir
|
||||||
@ -596,7 +597,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
var err error
|
var err error
|
||||||
e = elemental.NewElemental(config)
|
e = elemental.NewElemental(config)
|
||||||
destDir, err = utils.TempDir(fs, "", "elemental")
|
destDir, err = fsutils.TempDir(fs, "", "elemental")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
It("Copies files from a directory source", func() {
|
It("Copies files from a directory source", func() {
|
||||||
@ -682,7 +683,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
var relabelCmd []string
|
var relabelCmd []string
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
// to mock the existance of setfiles command on non selinux hosts
|
// 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
sbin, err := fs.RawPath("/usr/sbin")
|
sbin, err := fs.RawPath("/usr/sbin")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
@ -696,11 +697,11 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
|
|
||||||
// to mock SELinux policy files
|
// to mock SELinux policy files
|
||||||
policyFile = filepath.Join(constants.SELinuxTargetedPolicyPath, "policy.31")
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(constants.SELinuxTargetedContextFile)
|
_, err = fs.Create(constants.SELinuxTargetedContextFile)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
err = utils.MkdirAll(fs, constants.SELinuxTargetedPolicyPath, constants.DirPerm)
|
err = fsutils.MkdirAll(fs, constants.SELinuxTargetedPolicyPath, constants.DirPerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(policyFile)
|
_, err = fs.Create(policyFile)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
@ -749,12 +750,12 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
})
|
})
|
||||||
It("relabels the given root-tree path", func() {
|
It("relabels the given root-tree path", func() {
|
||||||
contextFile := filepath.Join("/root", constants.SELinuxTargetedContextFile)
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(contextFile)
|
_, err = fs.Create(contextFile)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
policyFile = filepath.Join("/root", policyFile)
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create(policyFile)
|
_, err = fs.Create(policyFile)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
@ -774,7 +775,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
e = elemental.NewElemental(config)
|
e = elemental.NewElemental(config)
|
||||||
})
|
})
|
||||||
It("Gets the iso and returns the temporary where it is stored", func() {
|
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())
|
Expect(err).To(BeNil())
|
||||||
err = fs.WriteFile(fmt.Sprintf("%s/fake.iso", tmpDir), []byte("Hi"), cnst.FilePerm)
|
err = fs.WriteFile(fmt.Sprintf("%s/fake.iso", tmpDir), []byte("Hi"), cnst.FilePerm)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
@ -782,7 +783,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
isoDir, err := e.GetIso(iso)
|
isoDir, err := e.GetIso(iso)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
// Confirm that the iso is stored in isoDir
|
// 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() {
|
It("Fails if it cant find the iso", func() {
|
||||||
iso := "whatever"
|
iso := "whatever"
|
||||||
@ -792,7 +793,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
})
|
})
|
||||||
It("Fails if it cannot mount the iso", func() {
|
It("Fails if it cannot mount the iso", func() {
|
||||||
mounter.ErrorOnMount = true
|
mounter.ErrorOnMount = true
|
||||||
tmpDir, err := utils.TempDir(fs, "", "elemental-test")
|
tmpDir, err := fsutils.TempDir(fs, "", "elemental-test")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
err = fs.WriteFile(fmt.Sprintf("%s/fake.iso", tmpDir), []byte("Hi"), cnst.FilePerm)
|
err = fs.WriteFile(fmt.Sprintf("%s/fake.iso", tmpDir), []byte("Hi"), cnst.FilePerm)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
@ -831,7 +832,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
It("updates recovery only image", func() {
|
It("updates recovery only image", func() {
|
||||||
recoveryImg = &v1.Image{}
|
recoveryImg = &v1.Image{}
|
||||||
isoMnt := "/some/dir/iso"
|
isoMnt := "/some/dir/iso"
|
||||||
err := utils.MkdirAll(fs, isoMnt, cnst.DirPerm)
|
err := fsutils.MkdirAll(fs, isoMnt, cnst.DirPerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
recoverySquash := filepath.Join(isoMnt, cnst.RecoverySquashFile)
|
recoverySquash := filepath.Join(isoMnt, cnst.RecoverySquashFile)
|
||||||
_, err = fs.Create(recoverySquash)
|
_, err = fs.Create(recoverySquash)
|
||||||
@ -883,7 +884,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
Expect(runner.CmdsMatch([][]string{{"grub2-editenv"}})).NotTo(BeNil())
|
Expect(runner.CmdsMatch([][]string{{"grub2-editenv"}})).NotTo(BeNil())
|
||||||
})
|
})
|
||||||
It("loads /etc/os-release on empty default entry", func() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
err = config.Fs.WriteFile("/imgMountPoint/etc/os-release", []byte("GRUB_ENTRY_NAME=test"), constants.FilePerm)
|
err = config.Fs.WriteFile("/imgMountPoint/etc/os-release", []byte("GRUB_ENTRY_NAME=test"), constants.FilePerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
@ -904,7 +905,7 @@ var _ = Describe("Elemental", Label("elemental"), func() {
|
|||||||
})
|
})
|
||||||
Describe("FindKernelInitrd", Label("find"), func() {
|
Describe("FindKernelInitrd", Label("find"), func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
err := utils.MkdirAll(fs, "/path/boot", constants.DirPerm)
|
err := fsutils.MkdirAll(fs, "/path/boot", constants.DirPerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
It("finds kernel and initrd files", func() {
|
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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
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"
|
"github.com/twpayne/go-vfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -327,7 +328,7 @@ func (dev Disk) FindPartitionDevice(partNum int) (string, error) {
|
|||||||
for tries := 0; tries <= partitionTries; tries++ {
|
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.logger.Debugf("Trying to find the partition device %d of device %s (try number %d)", partNum, dev, tries+1)
|
||||||
_, _ = dev.runner.Run("udevadm", "settle")
|
_, _ = dev.runner.Run("udevadm", "settle")
|
||||||
if exists, _ := utils.Exists(dev.fs, device); exists {
|
if exists, _ := fsutils.Exists(dev.fs, device); exists {
|
||||||
return device, nil
|
return device, nil
|
||||||
}
|
}
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
@ -401,7 +402,7 @@ func (dev Disk) expandFilesystem(device string) (string, error) {
|
|||||||
var out []byte
|
var out []byte
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
fs, err := utils.GetPartitionFS(device)
|
fs, err := partitions.GetPartitionFS(device)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fs, err
|
return fs, err
|
||||||
}
|
}
|
||||||
@ -419,7 +420,7 @@ func (dev Disk) expandFilesystem(device string) (string, error) {
|
|||||||
}
|
}
|
||||||
case "xfs":
|
case "xfs":
|
||||||
// to grow an xfs fs it needs to be mounted :/
|
// 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) {
|
defer func(fs v1.FS, path string) {
|
||||||
_ = fs.RemoveAll(path)
|
_ = fs.RemoveAll(path)
|
||||||
}(dev.fs, tmpDir)
|
}(dev.fs, tmpDir)
|
||||||
|
@ -18,13 +18,13 @@ package partitioner_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/jaypipes/ghw/pkg/block"
|
"github.com/jaypipes/ghw/pkg/block"
|
||||||
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||||
part "github.com/kairos-io/kairos-agent/v2/pkg/partitioner"
|
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"
|
mocks "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@ -211,7 +211,7 @@ var _ = Describe("Partitioner", Label("disk", "partition", "partitioner"), func(
|
|||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
fs, cleanup, _ = vfst.NewTestFS(nil)
|
fs, cleanup, _ = vfst.NewTestFS(nil)
|
||||||
|
|
||||||
err := utils.MkdirAll(fs, "/dev", constants.DirPerm)
|
err := fsutils.MkdirAll(fs, "/dev", constants.DirPerm)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
_, err = fs.Create("/dev/device")
|
_, err = fs.Create("/dev/device")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
@ -19,12 +19,10 @@ package v1
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"k8s.io/mount-utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -43,94 +41,6 @@ type Spec interface {
|
|||||||
ShouldShutdown() bool
|
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
|
// InstallSpec struct represents all the installation action details
|
||||||
type InstallSpec struct {
|
type InstallSpec struct {
|
||||||
Target string `yaml:"device,omitempty" mapstructure:"device"`
|
Target string `yaml:"device,omitempty" mapstructure:"device"`
|
||||||
|
@ -17,108 +17,13 @@ limitations under the License.
|
|||||||
package v1_test
|
package v1_test
|
||||||
|
|
||||||
import (
|
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"
|
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/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
"github.com/twpayne/go-vfs"
|
|
||||||
"github.com/twpayne/go-vfs/vfst"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Types", Label("types", "config"), func() {
|
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() {
|
Describe("ElementalPartitions", func() {
|
||||||
var p v1.PartitionList
|
var p v1.PartitionList
|
||||||
var ep v1.ElementalPartitions
|
var ep v1.ElementalPartitions
|
||||||
@ -319,151 +224,4 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
|||||||
Expect(p.GetByName("nonexistent")).To(BeNil())
|
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 (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"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
|
// Chroot represents the struct that will allow us to run commands inside a given chroot
|
||||||
@ -33,10 +34,10 @@ type Chroot struct {
|
|||||||
defaultMounts []string
|
defaultMounts []string
|
||||||
extraMounts map[string]string
|
extraMounts map[string]string
|
||||||
activeMounts []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{
|
return &Chroot{
|
||||||
path: path,
|
path: path,
|
||||||
defaultMounts: []string{"/dev", "/dev/pts", "/proc", "/sys"},
|
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
|
// 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 := NewChroot(path, cfg)
|
||||||
chroot.SetExtraMounts(bindMounts)
|
chroot.SetExtraMounts(bindMounts)
|
||||||
return chroot.RunCallback(callback)
|
return chroot.RunCallback(callback)
|
||||||
@ -78,7 +79,7 @@ func (c *Chroot) Prepare() error {
|
|||||||
|
|
||||||
for _, mnt := range c.defaultMounts {
|
for _, mnt := range c.defaultMounts {
|
||||||
mountPoint := fmt.Sprintf("%s%s", strings.TrimSuffix(c.path, "/"), mnt)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -95,7 +96,7 @@ func (c *Chroot) Prepare() error {
|
|||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
mountPoint := fmt.Sprintf("%s%s", strings.TrimSuffix(c.path, "/"), c.extraMounts[k])
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,9 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"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"
|
"io"
|
||||||
random "math/rand"
|
random "math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -42,12 +45,6 @@ func CommandExists(command string) bool {
|
|||||||
return err == nil
|
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.
|
// GetDeviceByLabel will try to return the device that matches the given label.
|
||||||
// attempts value sets the number of attempts to find the device, it
|
// attempts value sets the number of attempts to find the device, it
|
||||||
// waits a second between attempts.
|
// 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) {
|
func GetFullDeviceByLabel(runner v1.Runner, label string, attempts int) (*v1.Partition, error) {
|
||||||
for tries := 0; tries < attempts; tries++ {
|
for tries := 0; tries < attempts; tries++ {
|
||||||
_, _ = runner.Run("udevadm", "settle")
|
_, _ = runner.Run("udevadm", "settle")
|
||||||
parts, err := GetAllPartitions()
|
parts, err := partitions.GetAllPartitions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -91,7 +88,7 @@ func ConcatFiles(fs v1.FS, sources []string, target string) (err error) {
|
|||||||
if len(sources) == 0 {
|
if len(sources) == 0 {
|
||||||
return fmt.Errorf("Empty sources list")
|
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]))
|
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
|
// Copies source file to target file using Fs interface
|
||||||
func CreateDirStructure(fs v1.FS, target string) error {
|
func CreateDirStructure(fs v1.FS, target string) error {
|
||||||
for _, dir := range []string{"/run", "/dev", "/boot", "/usr/local", "/oem"} {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, dir := range []string{"/proc", "/sys"} {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := MkdirAll(fs, filepath.Join(target, "/tmp"), cnst.DirPerm)
|
err := fsutils.MkdirAll(fs, filepath.Join(target, "/tmp"), cnst.DirPerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -245,7 +242,7 @@ func CosignVerify(fs v1.FS, runner v1.Runner, image string, publicKey string, de
|
|||||||
args = append(args, image)
|
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
|
// 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 {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -301,7 +298,7 @@ func LoadEnvFile(fs v1.FS, file string) (map[string]string, error) {
|
|||||||
return envMap, err
|
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 {
|
if part == nil {
|
||||||
return false, fmt.Errorf("nil partition")
|
return false, fmt.Errorf("nil partition")
|
||||||
}
|
}
|
||||||
@ -318,37 +315,11 @@ func IsMounted(config *v1.Config, part *v1.Partition) (bool, error) {
|
|||||||
return !notMnt, nil
|
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
|
// 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
|
// It will respect TMPDIR and use that if exists, fallback to try the persistent partition if its mounted
|
||||||
// and finally the default /tmp/ dir
|
// 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
|
// 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 we got a TMPDIR var, respect and use that
|
||||||
if suffix == "" {
|
if suffix == "" {
|
||||||
random.Seed(time.Now().UnixNano())
|
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)
|
config.Logger.Debugf("Got tmpdir from TMPDIR var: %s", dir)
|
||||||
return filepath.Join(dir, elementalTmpDir)
|
return filepath.Join(dir, elementalTmpDir)
|
||||||
}
|
}
|
||||||
parts, err := GetAllPartitions()
|
parts, err := partitions.GetAllPartitions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
config.Logger.Debug("Could not get partitions, defaulting to /tmp")
|
config.Logger.Debug("Could not get partitions, defaulting to /tmp")
|
||||||
return filepath.Join("/", "tmp", elementalTmpDir)
|
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
|
// 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.
|
// 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)
|
local, err := IsLocalURI(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
config.Logger.Errorf("Not a valid url: %s", source)
|
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) {
|
if !filepath.IsAbs(found) {
|
||||||
found = filepath.Join(path, found)
|
found = filepath.Join(path, found)
|
||||||
}
|
}
|
||||||
if exists, _ := Exists(fs, found); exists {
|
if exists, _ := fsutils.Exists(fs, found); exists {
|
||||||
return found, nil
|
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)
|
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.
|
// CalcFileChecksum opens the given file and returns the sha256 checksum of it.
|
||||||
func CalcFileChecksum(fs v1.FS, fileName string) (string, error) {
|
func CalcFileChecksum(fs v1.FS, fileName string) (string, error) {
|
||||||
f, err := fs.Open(fileName)
|
f, err := fs.Open(fileName)
|
||||||
|
@ -17,7 +17,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package utils
|
package fsutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/fs"
|
"io/fs"
|
@ -18,21 +18,22 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||||
cnst "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
|
// Grub is the struct that will allow us to install grub to the target device
|
||||||
type Grub struct {
|
type Grub struct {
|
||||||
config *v1.Config
|
config *agentConfig.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGrub(config *v1.Config) *Grub {
|
func NewGrub(config *agentConfig.Config) *Grub {
|
||||||
g := &Grub{
|
g := &Grub{
|
||||||
config: config,
|
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
|
// 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
|
// 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"
|
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
|
// 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 {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating grub dir: %s", err)
|
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 {
|
if ttyExists && tty != "" && tty != "console" && tty != constants.DefaultTty {
|
||||||
// We need to add a tty to the grub file
|
// 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)
|
g.config.Logger.Infof("Generating grub files for efi on %s", target)
|
||||||
var foundModules bool
|
var foundModules bool
|
||||||
for _, m := range []string{"loopback.mod", "squash4.mod", "xzio.mod", "gzio.mod"} {
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
g.config.Logger.Errorf("Error creating dirs: %s", err)
|
g.config.Logger.Errorf("Error creating dirs: %s", err)
|
||||||
return err
|
return err
|
||||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package utils
|
package partitions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@ -18,11 +18,12 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
"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"
|
"github.com/mudler/yip/pkg/schema"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@ -43,7 +44,7 @@ func onlyYAMLPartialErrors(er error) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkYAMLError(cfg *v1.Config, allErrors, err error) error {
|
func checkYAMLError(cfg *agentConfig.Config, allErrors, err error) error {
|
||||||
if !onlyYAMLPartialErrors(err) {
|
if !onlyYAMLPartialErrors(err) {
|
||||||
// here we absorb errors only if are related to YAML unmarshalling
|
// here we absorb errors only if are related to YAML unmarshalling
|
||||||
// As cmdline is parsed out as a yaml file
|
// 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
|
// RunStage will run yip
|
||||||
func RunStage(cfg *v1.Config, stage string) error {
|
func RunStage(cfg *agentConfig.Config, stage string) error {
|
||||||
var cmdLineYipURI string
|
var cmdLineYipURI string
|
||||||
var allErrors error
|
var allErrors error
|
||||||
var cloudInitPaths []string
|
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
|
// Make sure cloud init path specified are existing in the system
|
||||||
for _, cp := range cloudInitPaths {
|
for _, cp := range cloudInitPaths {
|
||||||
err := MkdirAll(cfg.Fs, cp, constants.DirPerm)
|
err := fsutils.MkdirAll(cfg.Fs, cp, constants.DirPerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cfg.Logger.Debugf("Failed creating cloud-init config path: %s %s", cp, err.Error())
|
cfg.Logger.Debugf("Failed creating cloud-init config path: %s %s", cp, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,11 @@ package utils_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/cloudinit"
|
"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"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
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 _ = Describe("run stage", Label("RunStage"), func() {
|
||||||
var config *v1.Config
|
var config *agentConfig.Config
|
||||||
var runner *v1mock.FakeRunner
|
var runner *v1mock.FakeRunner
|
||||||
var logger v1.Logger
|
var logger v1.Logger
|
||||||
var syscall *v1mock.FakeSyscall
|
var syscall *v1mock.FakeSyscall
|
||||||
@ -61,13 +62,13 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
|||||||
logger.SetLevel(log.DebugLevel)
|
logger.SetLevel(log.DebugLevel)
|
||||||
fs, cleanup, _ = vfst.NewTestFS(nil)
|
fs, cleanup, _ = vfst.NewTestFS(nil)
|
||||||
|
|
||||||
config = conf.NewConfig(
|
config = agentConfig.NewConfig(
|
||||||
conf.WithFs(fs),
|
agentConfig.WithFs(fs),
|
||||||
conf.WithRunner(runner),
|
agentConfig.WithRunner(runner),
|
||||||
conf.WithLogger(logger),
|
agentConfig.WithLogger(logger),
|
||||||
conf.WithMounter(mounter),
|
agentConfig.WithMounter(mounter),
|
||||||
conf.WithSyscall(syscall),
|
agentConfig.WithSyscall(syscall),
|
||||||
conf.WithClient(client),
|
agentConfig.WithClient(client),
|
||||||
)
|
)
|
||||||
|
|
||||||
config.CloudInitRunner = cloudinit.NewYipCloudInitRunner(config.Logger, config.Runner, fs)
|
config.CloudInitRunner = cloudinit.NewYipCloudInitRunner(config.Logger, config.Runner, fs)
|
||||||
@ -75,7 +76,7 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
|||||||
AfterEach(func() { cleanup() })
|
AfterEach(func() { cleanup() })
|
||||||
|
|
||||||
It("fails if strict mode is enabled", Label("strict"), func() {
|
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())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
_ = fs.WriteFile(fmt.Sprintf("%s/test.yaml", d), []byte("stages: [foo,bar]"), os.ModePerm)
|
_ = fs.WriteFile(fmt.Sprintf("%s/test.yaml", d), []byte("stages: [foo,bar]"), os.ModePerm)
|
||||||
config.Strict = true
|
config.Strict = true
|
||||||
@ -92,7 +93,7 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("Goes over extra paths", func() {
|
It("Goes over extra paths", func() {
|
||||||
d, err := utils.TempDir(fs, "", "elemental")
|
d, err := fsutils.TempDir(fs, "", "elemental")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
config.Logger.SetLevel(log.DebugLevel)
|
config.Logger.SetLevel(log.DebugLevel)
|
||||||
config.CloudInitPaths = []string{d}
|
config.CloudInitPaths = []string{d}
|
||||||
@ -105,7 +106,7 @@ var _ = Describe("run stage", Label("RunStage"), func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("parses cmdline uri", 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)
|
_ = fs.WriteFile(fmt.Sprintf("%s/test.yaml", d), []byte{}, os.ModePerm)
|
||||||
|
|
||||||
writeCmdline(fmt.Sprintf("cos.setup=%s/test.yaml", d), fs)
|
writeCmdline(fmt.Sprintf("cos.setup=%s/test.yaml", d), fs)
|
||||||
|
@ -20,6 +20,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||||
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -27,8 +29,8 @@ import (
|
|||||||
|
|
||||||
"github.com/jaypipes/ghw/pkg/block"
|
"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"
|
"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"
|
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
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 _ = Describe("Utils", Label("utils"), func() {
|
||||||
var config *v1.Config
|
var config *agentConfig.Config
|
||||||
var runner *v1mock.FakeRunner
|
var runner *v1mock.FakeRunner
|
||||||
var logger v1.Logger
|
var logger v1.Logger
|
||||||
var syscall *v1mock.FakeSyscall
|
var syscall *v1mock.FakeSyscall
|
||||||
@ -70,13 +72,13 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
fs.Mkdir("/run", constants.DirPerm)
|
fs.Mkdir("/run", constants.DirPerm)
|
||||||
fs.Mkdir("/etc", constants.DirPerm)
|
fs.Mkdir("/etc", constants.DirPerm)
|
||||||
|
|
||||||
config = conf.NewConfig(
|
config = agentConfig.NewConfig(
|
||||||
conf.WithFs(fs),
|
agentConfig.WithFs(fs),
|
||||||
conf.WithRunner(runner),
|
agentConfig.WithRunner(runner),
|
||||||
conf.WithLogger(logger),
|
agentConfig.WithLogger(logger),
|
||||||
conf.WithMounter(mounter),
|
agentConfig.WithMounter(mounter),
|
||||||
conf.WithSyscall(syscall),
|
agentConfig.WithSyscall(syscall),
|
||||||
conf.WithClient(client),
|
agentConfig.WithClient(client),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
AfterEach(func() { cleanup() })
|
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() {
|
Describe("GetDeviceByLabel", Label("lsblk", "partitions"), func() {
|
||||||
var cmds [][]string
|
var cmds [][]string
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
@ -246,7 +238,7 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
ghwTest.Clean()
|
ghwTest.Clean()
|
||||||
})
|
})
|
||||||
It("returns all found partitions", func() {
|
It("returns all found partitions", func() {
|
||||||
parts, err := utils.GetAllPartitions()
|
parts, err := partitions.GetAllPartitions()
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
var partNames []string
|
var partNames []string
|
||||||
for _, p := range parts {
|
for _, p := range parts {
|
||||||
@ -277,17 +269,17 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
ghwTest.Clean()
|
ghwTest.Clean()
|
||||||
})
|
})
|
||||||
It("returns found device with plain partition device", func() {
|
It("returns found device with plain partition device", func() {
|
||||||
pFS, err := utils.GetPartitionFS("device1")
|
pFS, err := partitions.GetPartitionFS("device1")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
Expect(pFS).To(Equal("xfs"))
|
Expect(pFS).To(Equal("xfs"))
|
||||||
})
|
})
|
||||||
It("returns found device with full partition device", func() {
|
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(err).To(BeNil())
|
||||||
Expect(pFS).To(Equal("xfs"))
|
Expect(pFS).To(Equal("xfs"))
|
||||||
})
|
})
|
||||||
It("fails if no partition is found", func() {
|
It("fails if no partition is found", func() {
|
||||||
_, err := utils.GetPartitionFS("device2")
|
_, err := partitions.GetPartitionFS("device2")
|
||||||
Expect(err).NotTo(BeNil())
|
Expect(err).NotTo(BeNil())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -377,40 +369,40 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
})
|
})
|
||||||
Describe("CopyFile", Label("CopyFile"), func() {
|
Describe("CopyFile", Label("CopyFile"), func() {
|
||||||
It("Copies source file to target file", 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create("/some/file")
|
_, err = fs.Create("/some/file")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Stat("/some/otherfile")
|
_, err = fs.Stat("/some/otherfile")
|
||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
Expect(utils.CopyFile(fs, "/some/file", "/some/otherfile")).ShouldNot(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(err).ShouldNot(HaveOccurred())
|
||||||
Expect(e).To(BeTrue())
|
Expect(e).To(BeTrue())
|
||||||
})
|
})
|
||||||
It("Copies source file to target folder", func() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
err = utils.MkdirAll(fs, "/someotherfolder", constants.DirPerm)
|
err = fsutils.MkdirAll(fs, "/someotherfolder", constants.DirPerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Create("/some/file")
|
_, err = fs.Create("/some/file")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
_, err = fs.Stat("/someotherfolder/file")
|
_, err = fs.Stat("/someotherfolder/file")
|
||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
Expect(utils.CopyFile(fs, "/some/file", "/someotherfolder")).ShouldNot(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(err).ShouldNot(HaveOccurred())
|
||||||
Expect(e).To(BeTrue())
|
Expect(e).To(BeTrue())
|
||||||
})
|
})
|
||||||
It("Fails to open non existing file", func() {
|
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(err).ShouldNot(HaveOccurred())
|
||||||
Expect(utils.CopyFile(fs, "/some/file", "/some/otherfile")).NotTo(BeNil())
|
Expect(utils.CopyFile(fs, "/some/file", "/some/otherfile")).NotTo(BeNil())
|
||||||
_, err = fs.Stat("/some/otherfile")
|
_, err = fs.Stat("/some/otherfile")
|
||||||
Expect(err).NotTo(BeNil())
|
Expect(err).NotTo(BeNil())
|
||||||
})
|
})
|
||||||
It("Fails to copy on non writable target", func() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
fs.Create("/some/file")
|
fs.Create("/some/file")
|
||||||
_, err = fs.Stat("/some/otherfile")
|
_, err = fs.Stat("/some/otherfile")
|
||||||
@ -448,13 +440,13 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
})
|
})
|
||||||
Describe("SyncData", Label("SyncData"), func() {
|
Describe("SyncData", Label("SyncData"), func() {
|
||||||
It("Copies all files from source to target", 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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
destDir, err := utils.TempDir(fs, "", "elementaltarget")
|
destDir, err := fsutils.TempDir(fs, "", "elementaltarget")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
for i := 0; i < 5; i++ {
|
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())
|
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() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
destDir, err := utils.TempDir(fs, "", "elementaltarget")
|
destDir, err := fsutils.TempDir(fs, "", "elementaltarget")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "host"), constants.DirPerm)
|
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "host"), constants.DirPerm)
|
||||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "run"), 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
|
// /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++ {
|
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())
|
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))
|
Expect(destNames).To(Equal(expected))
|
||||||
|
|
||||||
// /tmp/run is not copied over
|
// /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() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
destDir, err := utils.TempDir(fs, "", "elementaltarget")
|
destDir, err := fsutils.TempDir(fs, "", "elementaltarget")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "host"), constants.DirPerm)
|
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "host"), constants.DirPerm)
|
||||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "run"), constants.DirPerm)
|
fsutils.MkdirAll(fs, filepath.Join(sourceDir, "run"), constants.DirPerm)
|
||||||
utils.MkdirAll(fs, filepath.Join(sourceDir, "var", "run"), constants.DirPerm)
|
fsutils.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, "tmp", "host"), constants.DirPerm)
|
||||||
|
|
||||||
Expect(utils.SyncData(logger, realRunner, fs, sourceDir, destDir, "/host", "/run")).To(BeNil())
|
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
|
// Shouldn't be the same
|
||||||
Expect(destNames).ToNot(Equal(SourceNames))
|
Expect(destNames).ToNot(Equal(SourceNames))
|
||||||
|
|
||||||
Expect(utils.Exists(fs, filepath.Join(destDir, "var", "run"))).To(BeTrue())
|
Expect(fsutils.Exists(fs, filepath.Join(destDir, "var", "run"))).To(BeTrue())
|
||||||
Expect(utils.Exists(fs, filepath.Join(destDir, "tmp", "host"))).To(BeTrue())
|
Expect(fsutils.Exists(fs, filepath.Join(destDir, "tmp", "host"))).To(BeTrue())
|
||||||
Expect(utils.Exists(fs, filepath.Join(destDir, "host"))).To(BeFalse())
|
Expect(fsutils.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, "run"))).To(BeFalse())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should not fail if dirs are empty", func() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
destDir, err := utils.TempDir(fs, "", "elementaltarget")
|
destDir, err := fsutils.TempDir(fs, "", "elementaltarget")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
Expect(utils.SyncData(logger, realRunner, fs, sourceDir, destDir)).To(BeNil())
|
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() {
|
Describe("DirSize", Label("fs"), func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
err := utils.MkdirAll(fs, "/folder/subfolder", constants.DirPerm)
|
err := fsutils.MkdirAll(fs, "/folder/subfolder", constants.DirPerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
f, err := fs.Create("/folder/file")
|
f, err := fs.Create("/folder/file")
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
@ -684,14 +676,14 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
It("Returns the expected size of a test folder", func() {
|
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(err).ShouldNot(HaveOccurred())
|
||||||
Expect(size).To(Equal(int64(3072)))
|
Expect(size).To(Equal(int64(3072)))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
Describe("FindFileWithPrefix", Label("find"), func() {
|
Describe("FindFileWithPrefix", Label("find"), func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
err := utils.MkdirAll(fs, "/path/inner", constants.DirPerm)
|
err := fsutils.MkdirAll(fs, "/path/inner", constants.DirPerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
_, err = fs.Create("/path/onefile")
|
_, err = fs.Create("/path/onefile")
|
||||||
@ -740,7 +732,7 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
})
|
})
|
||||||
It("doesn't find any matching file in path", func() {
|
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")
|
_, err := utils.FindFileWithPrefix(fs, "/path", "prefix", "anotherprefix")
|
||||||
Expect(err).Should(HaveOccurred())
|
Expect(err).Should(HaveOccurred())
|
||||||
})
|
})
|
||||||
@ -773,10 +765,10 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
logger.SetLevel(v1.DebugLevel())
|
logger.SetLevel(v1.DebugLevel())
|
||||||
config.Logger = logger
|
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())
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
|
|
||||||
err = fs.WriteFile(filepath.Join(rootDir, constants.GrubConf), []byte("console=tty1"), 0644)
|
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() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
err = fs.WriteFile(filepath.Join(rootDir, "/usr/share/efi/x86_64/", constants.SignedShim), []byte(""), constants.FilePerm)
|
err = fs.WriteFile(filepath.Join(rootDir, "/usr/share/efi/x86_64/", constants.SignedShim), []byte(""), constants.FilePerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
err = fs.WriteFile(filepath.Join(rootDir, "/usr/share/efi/x86_64/grub.efi"), []byte(""), constants.FilePerm)
|
err = fs.WriteFile(filepath.Join(rootDir, "/usr/share/efi/x86_64/grub.efi"), []byte(""), constants.FilePerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
err = fs.WriteFile(filepath.Join(rootDir, "/x86_64/loopback.mod"), []byte(""), constants.FilePerm)
|
err = fs.WriteFile(filepath.Join(rootDir, "/x86_64/loopback.mod"), []byte(""), constants.FilePerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
err = fs.WriteFile(filepath.Join(rootDir, "/etc/os-release"), []byte("ID=\"suse\""), constants.FilePerm)
|
err = fs.WriteFile(filepath.Join(rootDir, "/etc/os-release"), []byte("ID=\"suse\""), constants.FilePerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
@ -839,7 +831,7 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
Expect(err.Error()).To(ContainSubstring("modules"))
|
Expect(err.Error()).To(ContainSubstring("modules"))
|
||||||
})
|
})
|
||||||
It("fails with efi if no grub files exist", Label("efi"), func() {
|
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())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
err = fs.WriteFile(filepath.Join(rootDir, "/x86_64/loopback.mod"), []byte(""), constants.FilePerm)
|
err = fs.WriteFile(filepath.Join(rootDir, "/x86_64/loopback.mod"), []byte(""), constants.FilePerm)
|
||||||
Expect(err).ShouldNot(HaveOccurred())
|
Expect(err).ShouldNot(HaveOccurred())
|
||||||
@ -993,65 +985,6 @@ var _ = Describe("Utils", Label("utils"), func() {
|
|||||||
Expect(mnt).To(BeFalse())
|
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() {
|
Describe("CleanStack", Label("CleanStack"), func() {
|
||||||
var cleaner *utils.CleanStack
|
var cleaner *utils.CleanStack
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
|
Loading…
Reference in New Issue
Block a user