diff --git a/internal/machine/bootcmdline.go b/internal/machine/bootcmdline.go new file mode 100644 index 0000000..8ef744d --- /dev/null +++ b/internal/machine/bootcmdline.go @@ -0,0 +1,88 @@ +package machine + +import ( + "errors" + "fmt" + "io/ioutil" + "strings" + + "github.com/google/shlex" + "github.com/hashicorp/go-multierror" + "github.com/itchyny/gojq" + "gopkg.in/yaml.v2" +) + +func DotToYAML(file string) ([]byte, error) { + if file == "" { + file = "/proc/cmdline" + } + dat, err := ioutil.ReadFile(file) + if err != nil { + return []byte{}, err + } + + v := stringToMap(string(dat)) + + return dotToYAML(v) +} + +func stringToMap(s string) map[string]interface{} { + v := map[string]interface{}{} + + 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 +} +func jq(command string, data map[string]interface{}) (map[string]interface{}, error) { + query, err := gojq.Parse(command) + if err != nil { + return nil, err + } + code, err := gojq.Compile(query) + if err != nil { + return nil, err + } + iter := code.Run(data) + + v, ok := iter.Next() + if !ok { + return nil, errors.New("failed getting rsult from gojq") + } + if err, ok := v.(error); ok { + return nil, err + } + if t, ok := v.(map[string]interface{}); ok { + return t, nil + } + + return make(map[string]interface{}), nil +} + +func dotToYAML(v map[string]interface{}) ([]byte, error) { + data := map[string]interface{}{} + var errs error + + for k, value := range v { + newData, err := jq(fmt.Sprintf(".%s=\"%s\"", k, value), data) + if err != nil { + errs = multierror.Append(errs, err) + continue + } + data = newData + } + + out, err := yaml.Marshal(&data) + if err != nil { + errs = multierror.Append(errs, err) + } + return out, err +} diff --git a/internal/machine/bootcmdline_test.go b/internal/machine/bootcmdline_test.go new file mode 100644 index 0000000..b689ade --- /dev/null +++ b/internal/machine/bootcmdline_test.go @@ -0,0 +1,29 @@ +package machine_test + +import ( + "io/ioutil" + "os" + + . "github.com/c3os-io/c3os/internal/machine" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("BootCMDLine", func() { + Context("parses data", func() { + + It("returns cmdline if provided", func() { + f, err := ioutil.TempFile("", "test") + Expect(err).ToNot(HaveOccurred()) + defer os.RemoveAll(f.Name()) + + err = ioutil.WriteFile(f.Name(), []byte(`config_url="foo bar" baz.bar=""`), os.ModePerm) + Expect(err).ToNot(HaveOccurred()) + + b, err := DotToYAML(f.Name()) + Expect(err).ToNot(HaveOccurred()) + + Expect(string(b)).To(Equal("baz:\n bar: \"\"\nconfig_url: foo bar\n")) + }) + }) +}) diff --git a/internal/machine/machine_suite_test.go b/internal/machine/machine_suite_test.go new file mode 100644 index 0000000..51bc130 --- /dev/null +++ b/internal/machine/machine_suite_test.go @@ -0,0 +1,13 @@ +package machine_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestInstaller(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Machine Suite") +}