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
This commit is contained in:
mudler
2022-08-12 12:21:12 +02:00
committed by Itxaka
parent b17ccae684
commit 122d29cbac
4 changed files with 84 additions and 33 deletions

View File

@@ -8,9 +8,10 @@ import (
) )
type BrandingText struct { type BrandingText struct {
Install string `yaml:"install"` InteractiveInstall string `yaml:"install"`
Reset string `yaml:"reset"` Install string `yaml:"install"`
Recovery string `yaml:"recovery"` Reset string `yaml:"reset"`
Recovery string `yaml:"recovery"`
} }
type Config struct { type Config struct {
@@ -31,6 +32,13 @@ func LoadConfig(path ...string) (*Config, error) {
} }
} }
if cfg.Branding.InteractiveInstall == "" {
f, err := ioutil.ReadFile(c3os.BrandingFile("interactive_install_text"))
if err == nil {
cfg.Branding.InteractiveInstall = string(f)
}
}
if cfg.Branding.Install == "" { if cfg.Branding.Install == "" {
f, err := ioutil.ReadFile(c3os.BrandingFile("install_text")) f, err := ioutil.ReadFile(c3os.BrandingFile("install_text"))
if err == nil { if err == nil {

View File

@@ -15,7 +15,6 @@ import (
config "github.com/c3os-io/c3os/pkg/config" config "github.com/c3os-io/c3os/pkg/config"
"github.com/c3os-io/c3os/internal/bus" "github.com/c3os-io/c3os/internal/bus"
sdkBus "github.com/c3os-io/c3os/sdk/bus"
"github.com/c3os-io/c3os/internal/cmd" "github.com/c3os-io/c3os/internal/cmd"
"github.com/c3os-io/c3os/pkg/utils" "github.com/c3os-io/c3os/pkg/utils"
@@ -157,7 +156,7 @@ func Install(dir ...string) error {
pterm.Info.Println("Starting installation") pterm.Info.Println("Starting installation")
utils.SH("elemental run-stage c3os-install.pre") //nolint:errcheck utils.SH("elemental run-stage c3os-install.pre") //nolint:errcheck
sdkBus.RunHookScript("/usr/bin/c3os-agent.install.pre.hook") //nolint:errcheck events.RunHookScript("/usr/bin/c3os-agent.install.pre.hook") //nolint:errcheck
if err := RunInstall(r); err != nil { if err := RunInstall(r); err != nil {
return err return err
@@ -217,7 +216,7 @@ func RunInstall(options map[string]string) error {
os.Exit(1) os.Exit(1)
} }
utils.SH("elemental run-stage c3os-install.after") //nolint:errcheck utils.SH("elemental run-stage c3os-install.after") //nolint:errcheck
sdkBus.RunHookScript("/usr/bin/c3os-agent.install.after.hook") //nolint:errcheck events.RunHookScript("/usr/bin/c3os-agent.install.after.hook") //nolint:errcheck
if reboot || c.Install != nil && c.Install.Reboot { if reboot || c.Install != nil && c.Install.Reboot {
utils.Reboot() utils.Reboot()

View File

@@ -1,16 +1,21 @@
package agent package agent
import ( import (
"encoding/json"
"fmt" "fmt"
"strings" "strings"
"github.com/c3os-io/c3os/internal/bus"
"github.com/c3os-io/c3os/internal/cmd" "github.com/c3os-io/c3os/internal/cmd"
providerConfig "github.com/c3os-io/c3os/internal/provider/config"
config "github.com/c3os-io/c3os/pkg/config" config "github.com/c3os-io/c3os/pkg/config"
events "github.com/c3os-io/c3os/sdk/bus"
"github.com/c3os-io/c3os/sdk/unstructured"
"github.com/c3os-io/c3os/pkg/utils" "github.com/c3os-io/c3os/pkg/utils"
"github.com/erikgeiser/promptkit/textinput" "github.com/erikgeiser/promptkit/textinput"
"github.com/jaypipes/ghw" "github.com/jaypipes/ghw"
"github.com/mudler/edgevpn/pkg/node" "github.com/mudler/go-pluggable"
"github.com/mudler/yip/pkg/schema" "github.com/mudler/yip/pkg/schema"
"github.com/pterm/pterm" "github.com/pterm/pterm"
) )
@@ -49,9 +54,16 @@ const (
) )
func InteractiveInstall(spawnShell bool) error { func InteractiveInstall(spawnShell bool) error {
bus.Manager.Initialize()
cmd.PrintBranding(DefaultBanner) cmd.PrintBranding(DefaultBanner)
pterm.DefaultBox.WithTitle("Installation").WithTitleBottomRight().WithRightPadding(0).WithBottomPadding(0).Println(
`Interactive installation. Documentation is available at https://docs.c3os.io.`) agentConfig, err := LoadConfig()
if err != nil {
return err
}
cmd.PrintText(agentConfig.Branding.InteractiveInstall, "Installation")
disks := []string{} disks := []string{}
maxSize := float64(0) maxSize := float64(0)
@@ -73,7 +85,6 @@ func InteractiveInstall(spawnShell bool) error {
for _, d := range disks { for _, d := range disks {
pterm.Info.Println(" " + d) pterm.Info.Println(" " + d)
} }
var networkToken string
device, err := prompt("What's the target install device?", preferedDevice, "Cannot be empty", false, false) device, err := prompt("What's the target install device?", preferedDevice, "Cannot be empty", false, false)
if err != nil { if err != nil {
@@ -101,28 +112,66 @@ func InteractiveInstall(spawnShell bool) error {
sshUsers := strings.Split(users, ",") sshUsers := strings.Split(users, ",")
k3sAuto, err := prompt("Do you want to enable k3s automated setup? (requires multiple nodes)", "n", yesNo, true, false) // Prompt the user by prompts defined by the provider
r := []events.YAMLPrompt{}
bus.Manager.Response(events.EventInteractiveInstall, func(p *pluggable.Plugin, resp *pluggable.EventResponse) {
err := json.Unmarshal([]byte(resp.Data), &r)
if err != nil {
fmt.Println(err)
}
})
_, err = bus.Manager.Publish(events.EventInteractiveInstall, events.EventPayload{})
if err != nil { if err != nil {
return err return err
} }
if isYes(k3sAuto) { unstructuredYAML := map[string]interface{}{}
hasNetworkToken, err := prompt("Do you have a network token already?", "n", yesNo, true, false) for _, p := range r {
if err != nil { var res string
return err if p.AskFirst {
ask, err := prompt(p.AskPrompt, "n", yesNo, true, false)
if err == nil && !isYes(ask) {
continue
}
} }
if p.Bool {
if isYes(hasNetworkToken) { def := "n"
networkToken, err = prompt("Input network token", "", "", false, true) if p.Default != "" {
def = p.Default
}
val, err := prompt(p.Prompt, def, yesNo, true, false)
if err != nil { if err != nil {
return err return err
} }
if isYes(val) {
val = "true"
} else {
val = "false"
}
unstructuredYAML[p.YAMLSection] = val
res = val
} else { } else {
networkToken = node.GenerateNewConnectionData().Base64() def := ""
if p.Default != "" {
def = p.Default
}
val, err := prompt(p.Prompt, def, p.PlaceHolder, true, false)
if err != nil {
return err
}
unstructuredYAML[p.YAMLSection] = val
res = val
}
if res == "" && p.IfEmpty != "" {
res = p.IfEmpty
unstructuredYAML[p.YAMLSection] = res
} }
} }
k3sStandalone, err := prompt("Do you want to enable k3s standalone?", "n", yesNo, true, false) result, err := unstructured.ToYAMLMap(unstructuredYAML)
if err != nil { if err != nil {
return err return err
} }
@@ -142,15 +191,6 @@ func InteractiveInstall(spawnShell bool) error {
}, },
} }
providerCfg := providerConfig.Config{
C3OS: &providerConfig.C3OS{
NetworkToken: networkToken,
},
K3s: providerConfig.K3s{
Enabled: isYes(k3sStandalone),
},
}
usersToSet := map[string]schema.User{} usersToSet := map[string]schema.User{}
if userName != "" { if userName != "" {
@@ -173,16 +213,19 @@ func InteractiveInstall(spawnShell bool) error {
}, },
}}} }}}
dat, err := config.MergeYAML(cloudConfig, c, providerCfg) dat, err := config.MergeYAML(cloudConfig, c, result)
if err != nil { if err != nil {
return err return err
} }
finalCloudConfig:=config.AddHeader("#node-config", string(dat))
pterm.Info.Println("Starting installation") pterm.Info.Println("Starting installation")
pterm.Info.Println(finalCloudConfig)
err = RunInstall(map[string]string{ err = RunInstall(map[string]string{
"device": device, "device": device,
"cc": config.AddHeader("#node-config", string(dat)), "cc": finalCloudConfig,
}) })
if err != nil { if err != nil {
pterm.Error.Println(err.Error()) pterm.Error.Println(err.Error())

View File

@@ -21,7 +21,8 @@ type Bus struct {
} }
func (b *Bus) LoadProviders() { func (b *Bus) LoadProviders() {
b.Manager.Autoload("agent-provider", "/system/providers").Register() wd, _ := os.Getwd()
b.Manager.Autoload("agent-provider", "/system/providers", wd).Register()
} }
func (b *Bus) Initialize() { func (b *Bus) Initialize() {