fix: apply talos config before bootstrap
This commit is contained in:
parent
7678d614f9
commit
8916d6ee4c
|
|
@ -51,9 +51,6 @@ func (r Runner) Run() error {
|
||||||
if err := os.WriteFile(filepath.Join(terraformDir, r.Config.Talos.ConfigFileName), []byte(renderTerraformTFVars(r.Config)), 0644); err != nil {
|
if err := os.WriteFile(filepath.Join(terraformDir, r.Config.Talos.ConfigFileName), []byte(renderTerraformTFVars(r.Config)), 0644); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ensureTalosConfig(generatedDir); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.Config.Talos.AutoRunTerraform {
|
if r.Config.Talos.AutoRunTerraform {
|
||||||
if err := utils.RunCommandInDir(terraformDir, "terraform", "init"); err != nil {
|
if err := utils.RunCommandInDir(terraformDir, "terraform", "init"); err != nil {
|
||||||
|
|
@ -63,11 +60,18 @@ func (r Runner) Run() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := ensureTalosConfig(generatedDir, r.Config); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if r.Config.Talos.AutoBootstrap {
|
if r.Config.Talos.AutoBootstrap {
|
||||||
|
configFile := filepath.Join("clusterconfig", fmt.Sprintf("%s-%s.yaml", r.Config.Talos.Cluster.Name, r.Config.Talos.Nodes[0].Name))
|
||||||
|
if err := utils.RunCommandInDir(generatedDir, "talosctl", "apply-config", "--insecure", "--nodes="+r.Config.Talos.BootstrapNode, "--endpoints="+r.Config.Talos.BootstrapEndpoint, "--file="+configFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := utils.RunCommandInDir(generatedDir, "talosctl", "bootstrap", "--talosconfig=./clusterconfig/talosconfig", "--endpoints="+r.Config.Talos.BootstrapEndpoint, "--nodes="+r.Config.Talos.BootstrapNode); err != nil {
|
if err := utils.RunCommandInDir(generatedDir, "talosctl", "bootstrap", "--talosconfig=./clusterconfig/talosconfig", "--endpoints="+r.Config.Talos.BootstrapEndpoint, "--nodes="+r.Config.Talos.BootstrapNode); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := utils.RunCommandInDir(generatedDir, "talosctl", "kubeconfig", "--talosconfig=./clusterconfig/talosconfig", "--endpoints="+r.Config.Talos.KubeconfigEndpoint, "--nodes="+r.Config.Talos.KubeconfigNode, "."); err != nil {
|
if err := utils.RunCommandInDir(generatedDir, "talosctl", "kubeconfig", "--talosconfig=./clusterconfig/talosconfig", "--nodes="+r.Config.Talos.KubeconfigNode, "."); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -89,10 +93,11 @@ func ensureRepo(dir, repoURL, ref string) error {
|
||||||
return utils.RunCommandInDir(dir, "git", "checkout", ref)
|
return utils.RunCommandInDir(dir, "git", "checkout", ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureTalosConfig(generatedDir string) error {
|
func ensureTalosConfig(generatedDir string, cfg config.Config) error {
|
||||||
|
talhelperPath := "talhelper"
|
||||||
secretPath := filepath.Join(generatedDir, "talsecret.sops.yaml")
|
secretPath := filepath.Join(generatedDir, "talsecret.sops.yaml")
|
||||||
if _, err := os.Stat(secretPath); os.IsNotExist(err) {
|
if _, err := os.Stat(secretPath); os.IsNotExist(err) {
|
||||||
secrets, err := utils.RunCommandOutputInDir(generatedDir, "talhelper", "gensecret", "--from-configfile", "talconfig.yaml")
|
secrets, err := utils.RunCommandOutputInDir(generatedDir, talhelperPath, "gensecret")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -100,7 +105,32 @@ func ensureTalosConfig(generatedDir string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return utils.RunCommandInDir(generatedDir, "talhelper", "genconfig")
|
kubernetesVersion := cfg.Talos.Image.TalosVersion
|
||||||
|
talconfigPath := writeTalconfigWithKubernetesVersion(generatedDir, kubernetesVersion)
|
||||||
|
return utils.RunCommandInDir(generatedDir, talhelperPath, "genconfig", "--config-file", filepath.Base(talconfigPath), "--secret-file", filepath.Base(secretPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeTalconfigWithKubernetesVersion(generatedDir, kubernetesVersion string) string {
|
||||||
|
path := filepath.Join(generatedDir, "talconfig.yaml")
|
||||||
|
content, _ := os.ReadFile(path)
|
||||||
|
if strings.HasPrefix(kubernetesVersion, "v1.13.") {
|
||||||
|
kubernetesVersion = "v1.33.4"
|
||||||
|
}
|
||||||
|
text := string(content)
|
||||||
|
if strings.Contains(text, "\nkubernetesVersion:") {
|
||||||
|
start := strings.Index(text, "\nkubernetesVersion:") + 1
|
||||||
|
end := strings.Index(text[start:], "\n")
|
||||||
|
if end == -1 {
|
||||||
|
text = text[:start] + "kubernetesVersion: " + kubernetesVersion
|
||||||
|
} else {
|
||||||
|
text = text[:start] + "kubernetesVersion: " + kubernetesVersion + text[start+end:]
|
||||||
|
}
|
||||||
|
_ = os.WriteFile(path, []byte(text), 0644)
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
updated := strings.Replace(text, "\nendpoint:", "\nkubernetesVersion: "+kubernetesVersion+"\nendpoint:", 1)
|
||||||
|
_ = os.WriteFile(path, []byte(updated), 0644)
|
||||||
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderTerraformTFVars(cfg config.Config) string {
|
func renderTerraformTFVars(cfg config.Config) string {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/Pingu-Studio/MaidnCLI/internal/talos"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -111,6 +112,9 @@ func Validate(cfg Config) error {
|
||||||
if cfg.Talos.Image.TalosVersion == "" || cfg.Talos.Image.SchematicID == "" {
|
if cfg.Talos.Image.TalosVersion == "" || cfg.Talos.Image.SchematicID == "" {
|
||||||
return errors.New("talos version and schematicId are required")
|
return errors.New("talos version and schematicId are required")
|
||||||
}
|
}
|
||||||
|
if err := talos.RequireCLICompatibility(cfg.Talos.Image.TalosVersion); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if cfg.Talos.Image.UpdateMode != "manual" && cfg.Talos.Image.UpdateMode != "download" {
|
if cfg.Talos.Image.UpdateMode != "manual" && cfg.Talos.Image.UpdateMode != "download" {
|
||||||
return errors.New("talos image updateMode must be manual or download")
|
return errors.New("talos image updateMode must be manual or download")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -66,6 +68,64 @@ func NormalizeVersion(version string) string {
|
||||||
return "v" + version
|
return "v" + version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RequireCLICompatibility(version string) error {
|
||||||
|
version = NormalizeVersion(version)
|
||||||
|
if err := requireTalhelper(version); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return requireTalosctl(version)
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireTalhelper(version string) error {
|
||||||
|
output, err := exec.Command("talhelper", "--version").Output()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("talhelper is required for Talos %s; install a compatible version and try again", version)
|
||||||
|
}
|
||||||
|
major, minor, ok := parseToolVersion(string(output))
|
||||||
|
if !ok || major < 3 || (major == 3 && minor < 1) {
|
||||||
|
return fmt.Errorf("talhelper %s may be incompatible with Talos %s; check that you have the right talhelper version", strings.TrimSpace(string(output)), version)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func requireTalosctl(version string) error {
|
||||||
|
output, err := exec.Command("talosctl", "version", "--client", "--short").Output()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("talosctl is required for Talos %s; install a compatible version and try again", version)
|
||||||
|
}
|
||||||
|
major, minor, ok := parseToolVersion(string(output))
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unable to parse talosctl version %q; check that it matches Talos %s", strings.TrimSpace(string(output)), version)
|
||||||
|
}
|
||||||
|
talosMajor, talosMinor, ok := parseToolVersion(version)
|
||||||
|
if !ok || major != talosMajor || minor != talosMinor {
|
||||||
|
return fmt.Errorf("talosctl %s may be incompatible with Talos %s; check that you have the right talosctl version", strings.TrimSpace(string(output)), version)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseToolVersion(raw string) (int, int, bool) {
|
||||||
|
raw = strings.TrimSpace(raw)
|
||||||
|
fields := strings.Fields(raw)
|
||||||
|
if len(fields) > 0 {
|
||||||
|
raw = fields[len(fields)-1]
|
||||||
|
}
|
||||||
|
raw = strings.TrimPrefix(raw, "v")
|
||||||
|
parts := strings.Split(raw, ".")
|
||||||
|
if len(parts) < 2 {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
major, err := strconv.Atoi(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
minor, err := strconv.Atoi(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
return major, minor, true
|
||||||
|
}
|
||||||
|
|
||||||
func FactoryURL(version, arch string) string {
|
func FactoryURL(version, arch string) string {
|
||||||
version = NormalizeVersion(version)
|
version = NormalizeVersion(version)
|
||||||
return fmt.Sprintf("https://factory.talos.dev/?arch=%s&extensions=-&extensions=%s&extensions=%s&extensions=%s&extensions=%s&platform=%s&target=%s&version=%s",
|
return fmt.Sprintf("https://factory.talos.dev/?arch=%s&extensions=-&extensions=%s&extensions=%s&extensions=%s&extensions=%s&platform=%s&target=%s&version=%s",
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,9 @@ func RunBootstrapWizard(initial config.Config) (config.Config, error) {
|
||||||
|
|
||||||
latestTalos := talos.LatestVersion()
|
latestTalos := talos.LatestVersion()
|
||||||
cfg.Talos.Image.TalosVersion = talos.NormalizeVersion(prompt(reader, "Talos version", fallback(cfg.Talos.Image.TalosVersion, latestTalos)))
|
cfg.Talos.Image.TalosVersion = talos.NormalizeVersion(prompt(reader, "Talos version", fallback(cfg.Talos.Image.TalosVersion, latestTalos)))
|
||||||
|
if err := talos.RequireCLICompatibility(cfg.Talos.Image.TalosVersion); err != nil {
|
||||||
|
return cfg, err
|
||||||
|
}
|
||||||
cfg.Talos.Image.Architecture = chooseArchitecture(reader, cfg.Talos.Image.Architecture)
|
cfg.Talos.Image.Architecture = chooseArchitecture(reader, cfg.Talos.Image.Architecture)
|
||||||
fmt.Printf("Talos factory: %s\n", talos.FactoryURL(cfg.Talos.Image.TalosVersion, fallback(cfg.Talos.Image.Architecture, "amd64")))
|
fmt.Printf("Talos factory: %s\n", talos.FactoryURL(cfg.Talos.Image.TalosVersion, fallback(cfg.Talos.Image.Architecture, "amd64")))
|
||||||
schematicID, err := talos.ResolveSchematicID()
|
schematicID, err := talos.ResolveSchematicID()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue