From f3ce62216cfd2920dca38944d68b72452f810f7a Mon Sep 17 00:00:00 2001 From: mudler Date: Fri, 12 Aug 2022 12:21:12 +0200 Subject: [PATCH] art: Expose interactive install to providers In this way install can be driven from providers too Part of: https://github.com/c3os-io/c3os/issues/68 --- sdk/bus/events.go | 14 ++++++++ sdk/unstructured/yaml.go | 72 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 sdk/unstructured/yaml.go diff --git a/sdk/bus/events.go b/sdk/bus/events.go index efd63e9..e505977 100644 --- a/sdk/bus/events.go +++ b/sdk/bus/events.go @@ -25,6 +25,8 @@ const ( // EventRecovery emitted while booting into recovery mode EventRecovery pluggable.EventType = "agent.recovery" EventRecoveryStop pluggable.EventType = "agent.recovery.stop" + + EventInteractiveInstall pluggable.EventType = "agent.interactive-install" ) type InstallPayload struct { @@ -32,6 +34,17 @@ type InstallPayload struct { Config string `json:"config"` } +type YAMLPrompt struct { + YAMLSection string + Bool bool + Prompt string + Default string + AskFirst bool + AskPrompt string + IfEmpty string + PlaceHolder string +} + type BootstrapPayload struct { APIAddress string `json:"api"` Config string `json:"config"` @@ -49,6 +62,7 @@ var AllEvents = []pluggable.EventType{ EventBoot, EventInstall, EventRecovery, + EventInteractiveInstall, EventRecoveryStop, } diff --git a/sdk/unstructured/yaml.go b/sdk/unstructured/yaml.go new file mode 100644 index 0000000..474fbb8 --- /dev/null +++ b/sdk/unstructured/yaml.go @@ -0,0 +1,72 @@ +package unstructured + +import ( + "errors" + "fmt" + + "github.com/hashicorp/go-multierror" + "github.com/itchyny/gojq" + "gopkg.in/yaml.v3" +) + +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 ToYAML(v map[string]interface{}) ([]byte, error) { + data := map[string]interface{}{} + var errs error + + for k, value := range v { + tmpl := ".%s=\"%s\"" + // support boolean types + if value == "true" || value == "false" { + tmpl = ".%s=%s" + } + newData, err := jq(fmt.Sprintf(tmpl, 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, errs +} + +// ToYAMLMap turns a map string interface in dot.yaml format to a fully deep marshalled yaml +func ToYAMLMap(v map[string]interface{}) (map[string]interface{}, error) { + result := map[string]interface{}{} + tempData, err := ToYAML(v) + if err != nil { + return result, err + } + err = yaml.Unmarshal(tempData, &result) + + return result, err +}