bug: Do not merge all cmdline arguments to generic config (#1256)

* Do not merge all cmdline arguments to generic config

Instead allow only specific Kairos config ones, this should not be known by the collector but doing it this way as a temporary hack to release 2.0 and then we can do properly

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* Remove fmt.Println

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* Lint

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* imports

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* Filter using a cloud config structure

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* Pass a filter function

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* Exclude collector config from config.Config yaml

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* Fix issue with test now that a yaml tag gets ignored

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* cleanup FilterKeys func

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

* Add comment

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>

---------

Signed-off-by: Mauro Morales <mauro.morales@spectrocloud.com>
This commit is contained in:
Mauro Morales 2023-04-06 15:18:15 +02:00 committed by Itxaka
parent d7fc1ee026
commit b8b3e83ef1
4 changed files with 48 additions and 44 deletions

View File

@ -12,11 +12,11 @@ import (
"time" "time"
"unicode" "unicode"
"github.com/kairos-io/kairos-sdk/machine"
"github.com/avast/retry-go" "github.com/avast/retry-go"
"github.com/google/shlex"
"github.com/imdario/mergo" "github.com/imdario/mergo"
"github.com/itchyny/gojq" "github.com/itchyny/gojq"
"github.com/kairos-io/kairos-sdk/unstructured"
"gopkg.in/yaml.v1" "gopkg.in/yaml.v1"
) )
@ -93,13 +93,13 @@ func (cs Configs) Merge() (*Config, error) {
return result, nil return result, nil
} }
func Scan(o *Options) (*Config, error) { func Scan(o *Options, filter func(d []byte) ([]byte, error)) (*Config, error) {
configs := Configs{} configs := Configs{}
configs = append(configs, parseFiles(o.ScanDir, o.NoLogs)...) configs = append(configs, parseFiles(o.ScanDir, o.NoLogs)...)
if o.MergeBootCMDLine { if o.MergeBootCMDLine {
cConfig, err := ParseCmdLine(o.BootCMDLineFile) cConfig, err := ParseCmdLine(o.BootCMDLineFile, filter)
o.SoftErr("parsing cmdline", err) o.SoftErr("parsing cmdline", err)
if err == nil { // best-effort if err == nil { // best-effort
configs = append(configs, cConfig) configs = append(configs, cConfig)
@ -201,41 +201,24 @@ func listFiles(dir string) ([]string, error) {
// ParseCmdLine reads options from the kernel cmdline and returns the equivalent // ParseCmdLine reads options from the kernel cmdline and returns the equivalent
// Config. // Config.
func ParseCmdLine(file string) (*Config, error) { func ParseCmdLine(file string, filter func(d []byte) ([]byte, error)) (*Config, error) {
result := &Config{} result := Config{}
dotToYAML, err := machine.DotToYAML(file)
if file == "" {
file = "/proc/cmdline"
}
dat, err := os.ReadFile(file)
if err != nil { if err != nil {
return result, err return &result, err
} }
d, err := unstructured.ToYAML(stringToConfig(string(dat))) filteredYAML, err := filter(dotToYAML)
if err != nil { if err != nil {
return result, err return &result, err
}
err = yaml.Unmarshal(d, &result)
return result, err
}
func stringToConfig(s string) Config {
v := Config{}
splitted, _ := shlex.Split(s)
for _, item := range splitted {
parts := strings.SplitN(item, "=", 2)
value := "true"
if len(parts) > 1 {
value = strings.Trim(parts[1], `"`)
}
key := strings.Trim(parts[0], `"`)
v[key] = value
} }
return v err = yaml.Unmarshal(filteredYAML, &result)
if err != nil {
return &result, err
}
return &result, nil
} }
// ConfigURL returns the value of config_url if set or empty string otherwise. // ConfigURL returns the value of config_url if set or empty string otherwise.

View File

@ -6,6 +6,8 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"github.com/kairos-io/kairos/v2/pkg/config"
. "github.com/kairos-io/kairos/v2/pkg/config/collector" . "github.com/kairos-io/kairos/v2/pkg/config/collector"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@ -273,12 +275,12 @@ options:
) )
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
c, err := Scan(o) c, err := Scan(o, config.FilterKeys)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
config_url, ok := (*c)["config_url"].(string) configURL, ok := (*c)["config_url"].(string)
Expect(ok).To(BeTrue()) Expect(ok).To(BeTrue())
Expect(config_url).To(MatchRegexp("remote_config_2.yaml")) Expect(configURL).To(MatchRegexp("remote_config_2.yaml"))
k := (*c)["local_key_1"].(string) k := (*c)["local_key_1"].(string)
Expect(k).To(Equal("local_value_1")) Expect(k).To(Equal("local_value_1"))
@ -301,7 +303,7 @@ options:
Expect(options["remote_option_2"]).To(Equal("remote_option_value_2")) Expect(options["remote_option_2"]).To(Equal("remote_option_value_2"))
player := (*c)["player"].(map[interface{}]interface{}) player := (*c)["player"].(map[interface{}]interface{})
Expect(player["name"]).To(Equal("Dimitris")) Expect(player["name"]).NotTo(Equal("Toad"))
Expect(player["surname"]).To(Equal("Bros")) Expect(player["surname"]).To(Equal("Bros"))
}) })
}) })
@ -358,7 +360,7 @@ remote_key_2: remote_value_2`), os.ModePerm)
err := o.Apply(Directories(tmpDir), NoLogs) err := o.Apply(Directories(tmpDir), NoLogs)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
c, err := Scan(o) c, err := Scan(o, config.FilterKeys)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect((*c)["local_key_2"]).To(BeNil()) Expect((*c)["local_key_2"]).To(BeNil())
@ -426,7 +428,7 @@ some:
) )
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
c, err := Scan(o) c, err := Scan(o, config.FilterKeys)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
v, err := c.Query("local_key_1") v, err := c.Query("local_key_1")
@ -446,7 +448,6 @@ func createRemoteConfigs(serverDir string, port int) string {
config_url: http://127.0.0.1:%d/remote_config_2.yaml config_url: http://127.0.0.1:%d/remote_config_2.yaml
player: player:
name: Dimitris
remote_key_1: remote_value_1 remote_key_1: remote_value_1
`, port)), os.ModePerm) `, port)), os.ModePerm)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
@ -460,7 +461,7 @@ remote_key_2: remote_value_2
cmdLinePath := filepath.Join(serverDir, "cmdline") cmdLinePath := filepath.Join(serverDir, "cmdline")
// We put the cmdline in the same dir, it doesn't matter. // We put the cmdline in the same dir, it doesn't matter.
cmdLine := fmt.Sprintf(`config_url="http://127.0.0.1:%d/remote_config_1.yaml" player.name="Mario" options.foo=bar`, port) cmdLine := fmt.Sprintf(`config_url="http://127.0.0.1:%d/remote_config_1.yaml" player.name="Toad" options.foo=bar`, port)
err = os.WriteFile(cmdLinePath, []byte(cmdLine), os.ModePerm) err = os.WriteFile(cmdLinePath, []byte(cmdLine), os.ModePerm)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())

View File

@ -37,7 +37,7 @@ type Install struct {
type Config struct { type Config struct {
Install *Install `yaml:"install,omitempty"` Install *Install `yaml:"install,omitempty"`
collector.Config collector.Config `yaml:"-"`
// TODO: Remove this too? // TODO: Remove this too?
ConfigURL string `yaml:"config_url,omitempty"` ConfigURL string `yaml:"config_url,omitempty"`
Options map[string]string `yaml:"options,omitempty"` Options map[string]string `yaml:"options,omitempty"`
@ -95,6 +95,22 @@ func (c Config) HasConfigURL() bool {
return c.ConfigURL != "" return c.ConfigURL != ""
} }
// FilterKeys is used to pass to any other pkg which might want to see which part of the config matches the Kairos config.
func FilterKeys(d []byte) ([]byte, error) {
cmdLineFilter := Config{}
err := yaml.Unmarshal(d, &cmdLineFilter)
if err != nil {
return []byte{}, err
}
out, err := yaml.Marshal(cmdLineFilter)
if err != nil {
return []byte{}, err
}
return out, nil
}
func Scan(opts ...collector.Option) (c *Config, err error) { func Scan(opts ...collector.Option) (c *Config, err error) {
result := &Config{} result := &Config{}
@ -103,7 +119,7 @@ func Scan(opts ...collector.Option) (c *Config, err error) {
return result, err return result, err
} }
genericConfig, err := collector.Scan(o) genericConfig, err := collector.Scan(o, FilterKeys)
if err != nil { if err != nil {
return result, err return result, err

View File

@ -16,6 +16,10 @@ func getTagName(s string) string {
return "" return ""
} }
if s == "-" {
return ""
}
f := func(c rune) bool { f := func(c rune) bool {
return c == '"' || c == ',' return c == '"' || c == ','
} }