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"
"unicode"
"github.com/kairos-io/kairos-sdk/machine"
"github.com/avast/retry-go"
"github.com/google/shlex"
"github.com/imdario/mergo"
"github.com/itchyny/gojq"
"github.com/kairos-io/kairos-sdk/unstructured"
"gopkg.in/yaml.v1"
)
@ -93,13 +93,13 @@ func (cs Configs) Merge() (*Config, error) {
return result, nil
}
func Scan(o *Options) (*Config, error) {
func Scan(o *Options, filter func(d []byte) ([]byte, error)) (*Config, error) {
configs := Configs{}
configs = append(configs, parseFiles(o.ScanDir, o.NoLogs)...)
if o.MergeBootCMDLine {
cConfig, err := ParseCmdLine(o.BootCMDLineFile)
cConfig, err := ParseCmdLine(o.BootCMDLineFile, filter)
o.SoftErr("parsing cmdline", err)
if err == nil { // best-effort
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
// Config.
func ParseCmdLine(file string) (*Config, error) {
result := &Config{}
if file == "" {
file = "/proc/cmdline"
}
dat, err := os.ReadFile(file)
func ParseCmdLine(file string, filter func(d []byte) ([]byte, error)) (*Config, error) {
result := Config{}
dotToYAML, err := machine.DotToYAML(file)
if err != nil {
return result, err
return &result, err
}
d, err := unstructured.ToYAML(stringToConfig(string(dat)))
filteredYAML, err := filter(dotToYAML)
if err != nil {
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 &result, err
}
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.

View File

@ -6,6 +6,8 @@ import (
"path"
"path/filepath"
"github.com/kairos-io/kairos/v2/pkg/config"
. "github.com/kairos-io/kairos/v2/pkg/config/collector"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
@ -273,12 +275,12 @@ options:
)
Expect(err).ToNot(HaveOccurred())
c, err := Scan(o)
c, err := Scan(o, config.FilterKeys)
Expect(err).ToNot(HaveOccurred())
config_url, ok := (*c)["config_url"].(string)
configURL, ok := (*c)["config_url"].(string)
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)
Expect(k).To(Equal("local_value_1"))
@ -301,7 +303,7 @@ options:
Expect(options["remote_option_2"]).To(Equal("remote_option_value_2"))
player := (*c)["player"].(map[interface{}]interface{})
Expect(player["name"]).To(Equal("Dimitris"))
Expect(player["name"]).NotTo(Equal("Toad"))
Expect(player["surname"]).To(Equal("Bros"))
})
})
@ -358,7 +360,7 @@ remote_key_2: remote_value_2`), os.ModePerm)
err := o.Apply(Directories(tmpDir), NoLogs)
Expect(err).ToNot(HaveOccurred())
c, err := Scan(o)
c, err := Scan(o, config.FilterKeys)
Expect(err).ToNot(HaveOccurred())
Expect((*c)["local_key_2"]).To(BeNil())
@ -426,7 +428,7 @@ some:
)
Expect(err).ToNot(HaveOccurred())
c, err := Scan(o)
c, err := Scan(o, config.FilterKeys)
Expect(err).ToNot(HaveOccurred())
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
player:
name: Dimitris
remote_key_1: remote_value_1
`, port)), os.ModePerm)
Expect(err).ToNot(HaveOccurred())
@ -460,7 +461,7 @@ remote_key_2: remote_value_2
cmdLinePath := filepath.Join(serverDir, "cmdline")
// 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)
Expect(err).ToNot(HaveOccurred())

View File

@ -36,8 +36,8 @@ type Install struct {
}
type Config struct {
Install *Install `yaml:"install,omitempty"`
collector.Config
Install *Install `yaml:"install,omitempty"`
collector.Config `yaml:"-"`
// TODO: Remove this too?
ConfigURL string `yaml:"config_url,omitempty"`
Options map[string]string `yaml:"options,omitempty"`
@ -95,6 +95,22 @@ func (c Config) HasConfigURL() bool {
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) {
result := &Config{}
@ -103,7 +119,7 @@ func Scan(opts ...collector.Option) (c *Config, err error) {
return result, err
}
genericConfig, err := collector.Scan(o)
genericConfig, err := collector.Scan(o, FilterKeys)
if err != nil {
return result, err

View File

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