mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-09-25 21:43:58 +00:00
seedling: Return configuration data from the agent (#567)
* 🌱 Return configuration data from the agent Signed-off-by: Ettore Di Giacinto <mudler@users.noreply.github.com> * 🤖 Cover query by tests Signed-off-by: Ettore Di Giacinto <mudler@users.noreply.github.com> Signed-off-by: Ettore Di Giacinto <mudler@users.noreply.github.com>
This commit is contained in:
committed by
Itxaka
parent
2bf4793c41
commit
a909c44620
@@ -10,12 +10,13 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
retry "github.com/avast/retry-go"
|
retry "github.com/avast/retry-go"
|
||||||
|
"github.com/itchyny/gojq"
|
||||||
"github.com/kairos-io/kairos/pkg/machine"
|
"github.com/kairos-io/kairos/pkg/machine"
|
||||||
"github.com/kairos-io/kairos/sdk/bundles"
|
"github.com/kairos-io/kairos/sdk/bundles"
|
||||||
"github.com/kairos-io/kairos/sdk/unstructured"
|
"github.com/kairos-io/kairos/sdk/unstructured"
|
||||||
yip "github.com/mudler/yip/pkg/schema"
|
yip "github.com/mudler/yip/pkg/schema"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Install struct {
|
type Install struct {
|
||||||
@@ -106,6 +107,38 @@ func (c Config) String() string {
|
|||||||
return string(dat)
|
return string(dat)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Config) Query(s string) (res string, err error) {
|
||||||
|
s = fmt.Sprintf(".%s", s)
|
||||||
|
jsondata := map[string]interface{}{}
|
||||||
|
|
||||||
|
err = yaml.Unmarshal([]byte(c.String()), &jsondata)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
query, err := gojq.Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
iter := query.Run(jsondata) // or query.RunWithContext
|
||||||
|
for {
|
||||||
|
v, ok := iter.Next()
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err, ok := v.(error); ok {
|
||||||
|
return res, fmt.Errorf("failed parsing, error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dat, err := yaml.Marshal(v)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
res += string(dat)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func allFiles(dir []string) []string {
|
func allFiles(dir []string) []string {
|
||||||
files := []string{}
|
files := []string{}
|
||||||
for _, d := range dir {
|
for _, d := range dir {
|
||||||
@@ -122,7 +155,7 @@ func Scan(opts ...Option) (c *Config, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c = parseConfig(o.ScanDir)
|
c = parseConfig(o.ScanDir, o.NoLogs)
|
||||||
|
|
||||||
if o.MergeBootCMDLine {
|
if o.MergeBootCMDLine {
|
||||||
d, err := machine.DotToYAML(o.BootCMDLineFile)
|
d, err := machine.DotToYAML(o.BootCMDLineFile)
|
||||||
@@ -291,18 +324,22 @@ func FindYAMLWithKey(s string, opts ...Option) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseConfig merges all config back in one structure.
|
// parseConfig merges all config back in one structure.
|
||||||
func parseConfig(dir []string) *Config {
|
func parseConfig(dir []string, nologs bool) *Config {
|
||||||
files := allFiles(dir)
|
files := allFiles(dir)
|
||||||
c := &Config{}
|
c := &Config{}
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if fileSize(f) > 1.0 {
|
if fileSize(f) > 1.0 {
|
||||||
fmt.Printf("warning: skipping %s. too big (>1MB)\n", f)
|
if !nologs {
|
||||||
|
fmt.Printf("warning: skipping %s. too big (>1MB)\n", f)
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.Contains(f, "userdata") || filepath.Ext(f) == ".yml" || filepath.Ext(f) == ".yaml" {
|
if strings.Contains(f, "userdata") || filepath.Ext(f) == ".yml" || filepath.Ext(f) == ".yaml" {
|
||||||
b, err := os.ReadFile(f)
|
b, err := os.ReadFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("warning: skipping %s. %s\n", f, err.Error())
|
if !nologs {
|
||||||
|
fmt.Printf("warning: skipping %s. %s\n", f, err.Error())
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
yaml.Unmarshal(b, c) //nolint:errcheck
|
yaml.Unmarshal(b, c) //nolint:errcheck
|
||||||
@@ -311,7 +348,9 @@ func parseConfig(dir []string) *Config {
|
|||||||
c.header = header
|
c.header = header
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("warning: skipping %s (extension).\n", f)
|
if !nologs {
|
||||||
|
fmt.Printf("warning: skipping %s (extension).\n", f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -50,7 +50,7 @@ var _ = Describe("Config", func() {
|
|||||||
ExpectWithOffset(1, header).To(Equal(DefaultHeader))
|
ExpectWithOffset(1, header).To(Equal(DefaultHeader))
|
||||||
}
|
}
|
||||||
|
|
||||||
It("reads from bootargs", func() {
|
It("reads from bootargs and can query", func() {
|
||||||
err := os.WriteFile(filepath.Join(d, "b"), []byte(`zz.foo="baa" options.foo=bar`), os.ModePerm)
|
err := os.WriteFile(filepath.Join(d, "b"), []byte(`zz.foo="baa" options.foo=bar`), os.ModePerm)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
|
||||||
@@ -58,6 +58,8 @@ var _ = Describe("Config", func() {
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
headerCheck(c)
|
headerCheck(c)
|
||||||
Expect(c.Options["foo"]).To(Equal("bar"))
|
Expect(c.Options["foo"]).To(Equal("bar"))
|
||||||
|
Expect(c.Query("options")).To(Equal("foo: bar\n"))
|
||||||
|
Expect(c.Query("options.foo")).To(Equal("bar\n"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("reads multiple config files", func() {
|
It("reads multiple config files", func() {
|
||||||
@@ -96,7 +98,7 @@ c: d
|
|||||||
var cc string = `#kairos-config
|
var cc string = `#kairos-config
|
||||||
baz: bar
|
baz: bar
|
||||||
kairos:
|
kairos:
|
||||||
network_token: foo
|
network_token: foo
|
||||||
`
|
`
|
||||||
|
|
||||||
err := os.WriteFile(filepath.Join(d, "test.yaml"), []byte(cc), os.ModePerm)
|
err := os.WriteFile(filepath.Join(d, "test.yaml"), []byte(cc), os.ModePerm)
|
||||||
@@ -114,7 +116,8 @@ fooz:
|
|||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(providerCfg.Kairos).ToNot(BeNil())
|
Expect(providerCfg.Kairos).ToNot(BeNil())
|
||||||
Expect(providerCfg.Kairos.NetworkToken).To(Equal("foo"))
|
Expect(providerCfg.Kairos.NetworkToken).To(Equal("foo"))
|
||||||
Expect(c.String()).To(Equal(cc))
|
Expect(c.String()).To(Equal(cc), c.String(), cc)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("merges with bootargs", func() {
|
It("merges with bootargs", func() {
|
||||||
|
@@ -4,10 +4,16 @@ type Options struct {
|
|||||||
ScanDir []string
|
ScanDir []string
|
||||||
BootCMDLineFile string
|
BootCMDLineFile string
|
||||||
MergeBootCMDLine bool
|
MergeBootCMDLine bool
|
||||||
|
NoLogs bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Option func(o *Options) error
|
type Option func(o *Options) error
|
||||||
|
|
||||||
|
var NoLogs Option = func(o *Options) error {
|
||||||
|
o.NoLogs = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Options) Apply(opts ...Option) error {
|
func (o *Options) Apply(opts ...Option) error {
|
||||||
for _, oo := range opts {
|
for _, oo := range opts {
|
||||||
if err := oo(o); err != nil {
|
if err := oo(o); err != nil {
|
||||||
|
Reference in New Issue
Block a user