feat(clustertool): move all talhelper references to talassist

This commit is contained in:
Kjeld Schouten
2024-11-06 01:20:29 +01:00
parent 66e079fb1c
commit 16c0e0c387
18 changed files with 137 additions and 267 deletions
+15 -34
View File
@@ -1,49 +1,30 @@
package gencmd
import (
"io"
"os"
"strings"
"path/filepath"
"github.com/rs/zerolog/log"
talhelperCfg "github.com/budimanjojo/talhelper/v3/pkg/config"
"github.com/budimanjojo/talhelper/v3/pkg/generate"
"github.com/truecharts/public/clustertool/embed"
"github.com/truecharts/public/clustertool/pkg/helper"
"github.com/truecharts/public/clustertool/pkg/initfiles"
"github.com/truecharts/public/clustertool/pkg/talassist"
)
func GenApply(node string, extraFlags []string) []string {
initfiles.LoadTalEnv(false)
cfg, err := talhelperCfg.LoadAndValidateFromFile(helper.TalConfigFile, []string{helper.ClusterEnvFile}, false)
if err != nil {
log.Fatal().Err(err).Msg("failed to parse talconfig or talenv file: %s")
}
applyStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
// replace this with self-made stuff, be aware we also need to use the configfile
err = generate.GenerateApplyCommand(cfg, helper.TalosGenerated, node, extraFlags)
commands := []string{}
//extraFlags = append(extraFlags, "--preserve")
w.Close()
out, _ := io.ReadAll(r)
os.Stdout = applyStdout
sliceOut := strings.Split(string(out), ";\n")
talosPath := embed.GetTalosExec()
var slice []string
for _, str := range sliceOut {
if str != "" {
str = strings.ReplaceAll(str, "talosctl", talosPath)
slice = append(slice, str)
if node == "" {
for _, noderef := range talassist.TalConfig.Nodes {
// TODO add extraFlags
filename := talassist.TalConfig.ClusterName + "-" + noderef.Hostname + ".yaml"
cmd := talosPath + " " + "apply" + " --talosconfig " + helper.TalosConfigFile + " -n " + noderef.IPAddress + " " + "--file=" + filepath.Join(helper.TalosGenerated, filename)
commands = append(commands, cmd)
}
} else {
cmd := talosPath + " " + "apply" + " --talosconfig " + helper.TalosConfigFile + " -n " + node + " "
commands = append(commands, cmd)
}
if err != nil {
log.Fatal().Err(err).Msg("failed to generate talosctl apply command: %s")
}
return slice
return commands
}
+7 -15
View File
@@ -7,7 +7,6 @@ import (
"github.com/rs/zerolog/log"
"github.com/truecharts/public/clustertool/embed"
"github.com/truecharts/public/clustertool/pkg/fluxhandler"
"github.com/truecharts/public/clustertool/pkg/helper"
"github.com/truecharts/public/clustertool/pkg/kubectlcmds"
@@ -24,12 +23,6 @@ var manifestPaths = []string{
filepath.Join(helper.KubernetesPath, "flux-system", "flux", "clustersettings.secret.yaml"),
}
func GenBootstrap(node string, extraFlags []string) string {
talosPath := embed.GetTalosExec()
strout := talosPath + "bootstrap --talosconfig " + helper.TalosConfigFile + " -n " + talassist.IpAddresses[0]
return strout
}
func RunBootstrap(args []string) {
var extraArgs []string
if len(args) > 1 {
@@ -38,9 +31,8 @@ func RunBootstrap(args []string) {
if err := sops.DecryptFiles(); err != nil {
log.Info().Msgf("Error decrypting files: %v\n", err)
}
bootstrapcmds := GenBootstrap("", extraArgs)
bootstrapNode := helper.ExtractNode(bootstrapcmds)
bootstrapNode := talassist.TalConfig.Nodes[0].IPAddress
bootstrapcmds := GenPlain("bootstrap", bootstrapNode, extraArgs)
nodestatus.WaitForHealth(bootstrapNode, []string{"maintenance"})
@@ -52,15 +44,15 @@ func RunBootstrap(args []string) {
log.Info().Msgf("Bootstrap: At this point your system is installed to disk, please make sure not to reboot into the installer ISO/USB %s", bootstrapNode)
log.Info().Msgf("Bootstrap: running bootstrap on node: %s", bootstrapNode)
ExecCmd(bootstrapcmds)
ExecCmd(bootstrapcmds[0])
log.Info().Msgf("Bootstrap: waiting for VIP %v to come online...", helper.TalEnv["VIP_IP"])
nodestatus.WaitForHealth(helper.TalEnv["VIP_IP"], []string{"running"})
log.Info().Msgf("Bootstrap: Configuring kubectl for VIP: %v", helper.TalEnv["VIP_IP"])
// Ensure kubeconfig is loaded
kubeconfigcmds := GenKubeConfig(helper.TalEnv["VIP_IP"], extraArgs)
ExecCmd(kubeconfigcmds)
kubeconfigcmds := GenPlain("health", helper.TalEnv["VIP_IP"], extraArgs)
ExecCmd(kubeconfigcmds[0])
// Desired pod names
requiredPods := []string{
@@ -150,8 +142,8 @@ func RunBootstrap(args []string) {
log.Info().Msg("Bootstrap: Base Cluster Configuration Completed, continuing setup...")
log.Info().Msg("Bootstrap: Confirming cluster health...")
healthcmd := GenHealth(helper.TalEnv["VIP_IP"])
ExecCmd(healthcmd)
healthcmd := GenPlain("health", helper.TalEnv["VIP_IP"], []string{})
ExecCmd(healthcmd[0])
close(stopCh)
prioCharts := []fluxhandler.HelmChart{
+2 -2
View File
@@ -76,8 +76,8 @@ func ExecCmds(taloscmds []string, healthcheck bool) error {
} else {
if helper.GetYesOrNo("Do you want to check the health of the cluster? (yes/no) [y/n]: ") {
log.Info().Msg("Checking if cluster is healthy...")
healthcmd := GenHealth(helper.TalEnv["VIP_IP"])
ExecCmd(healthcmd)
healthcmd := GenPlain("health", helper.TalEnv["VIP_IP"], []string{})
ExecCmd(healthcmd[0])
} else {
skipped = true
}
+5 -102
View File
@@ -3,30 +3,23 @@ package gencmd
import (
"bytes"
"errors"
"fmt"
"os"
"path"
"github.com/rs/zerolog/log"
talhelperCfg "github.com/budimanjojo/talhelper/v3/pkg/config"
"github.com/budimanjojo/talhelper/v3/pkg/generate"
"github.com/budimanjojo/talhelper/v3/pkg/substitute"
"github.com/budimanjojo/talhelper/v3/pkg/talos"
sideroConfig "github.com/siderolabs/talos/pkg/machinery/config"
"github.com/siderolabs/talos/pkg/machinery/config/generate/secrets"
"github.com/truecharts/public/clustertool/pkg/fluxhandler"
"github.com/truecharts/public/clustertool/pkg/helper"
"github.com/truecharts/public/clustertool/pkg/initfiles"
"github.com/truecharts/public/clustertool/pkg/talassist"
)
func GenConfig(args []string) error {
initfiles.GenSchema()
talassist.GenSchema()
initfiles.GenTalEnvConfigMap()
initfiles.CheckEnvVariables()
genTalSecret()
validateTalConfig(args)
talhelperGenConfig()
talassist.TalhelperGenConfig()
initfiles.UpdateGitRepo()
if err := fluxhandler.ProcessDirectory(path.Join(helper.ClusterPath, "kubernetes")); err != nil {
@@ -56,18 +49,13 @@ func genTalSecret() error {
}
defer outfile.Close()
var s *secrets.Bundle
version, _ := sideroConfig.ParseContractFromVersion(talhelperCfg.LatestTalosVersion)
s, err = talos.NewSecretBundle(secrets.NewClock(), *version)
if err != nil {
return err
}
secretbundle := talassist.NewSecretBundle()
buf := new(bytes.Buffer)
encoder := helper.YamlNewEncoder(buf)
encoder.SetIndent(2)
err = encoder.Encode(s)
err = encoder.Encode(secretbundle)
if err != nil {
return err
@@ -86,88 +74,3 @@ func genTalSecret() error {
}
return nil
}
func talhelperGenConfig() error {
genconfigTalosMode := "metal"
genconfigNoGitignore := false
genconfigDryRun := false
genconfigOfflineMode := false
cfg, err := talhelperCfg.LoadAndValidateFromFile(helper.TalConfigFile, []string{helper.ClusterEnvFile}, false)
if err != nil {
log.Fatal().Err(err).Msgf("failed to parse TalConfig or talenv file: %s", err)
}
err = generate.GenerateConfig(cfg, genconfigDryRun, helper.TalosGenerated, helper.TalSecretFile, genconfigTalosMode, genconfigOfflineMode)
if err != nil {
log.Fatal().Err(err).Msgf("failed to generate talos config: %s", err)
}
if !genconfigNoGitignore && !genconfigDryRun {
err = cfg.GenerateGitignore(helper.TalosGenerated)
if err != nil {
log.Fatal().Err(err).Msgf("failed to generate gitignore file: %s", err)
}
}
return nil
}
func validateTalConfig(argsInt []string) error {
cfg := helper.TalConfigFile
log.Info().Msgf("start loading and validating Talconfig file for cluster %s", helper.ClusterName)
log.Debug().Msg(fmt.Sprintf("reading %s", cfg))
cfgByte, err := os.ReadFile(cfg)
if err != nil {
log.Fatal().Err(err).Msgf("failed to read Talconfig file %s: %s", helper.TalConfigFile, err)
}
if err := substitute.LoadEnvFromFiles([]string{helper.ClusterEnvFile}); err != nil {
log.Fatal().Err(err).Msg("failed to load env file: %s")
}
cfgByte, err = substitute.SubstituteEnvFromByte(cfgByte)
if err != nil {
log.Fatal().Err(err).Msg("failed trying to substitute env: %s")
}
log.Debug().Msg("Checking configfile after substitution...")
errs, warns, err := talhelperCfg.ValidateFromByte(cfgByte)
if err != nil {
log.Fatal().Err(err).Msgf("failed to validate talhelper config file: %s", err)
}
if len(errs) > 0 {
log.Trace().Msg("running talconfig validation errs...")
log.Error().Msg("There are issues with your talhelper config file:")
groupedErr := make(map[string][]string)
for _, v := range errs {
groupedErr[v.Field] = append(groupedErr[v.Field], v.Message.Error())
}
for field, list := range groupedErr {
log.Error().Msgf("field: %q\n", field)
for _, l := range list {
log.Error().Msgf(l + "\n")
}
}
os.Exit(1)
} else if len(warns) > 0 {
log.Trace().Msg("running talconfig validation warns...")
log.Warn().Msg("There might be some issues with your talhelper config file:")
groupedWarn := make(map[string][]string)
for _, v := range warns {
groupedWarn[v.Field] = append(groupedWarn[v.Field], v.Message)
}
for field, list := range groupedWarn {
log.Warn().Msgf("field: %q\n", field)
for _, l := range list {
log.Warn().Msgf(l + "\n")
}
}
} else {
log.Info().Msg("Your talhelper config file is looking great!")
}
log.Info().Msg("Finished validating talconfig")
return nil
}
-12
View File
@@ -1,12 +0,0 @@
package gencmd
import (
"github.com/truecharts/public/clustertool/embed"
"github.com/truecharts/public/clustertool/pkg/helper"
)
func GenHealth(node string) string {
talosPath := embed.GetTalosExec()
strout := talosPath + " health --talosconfig " + helper.TalosConfigFile + " -n " + node
return strout
}
-15
View File
@@ -1,15 +0,0 @@
package gencmd
import (
"github.com/truecharts/public/clustertool/embed"
"github.com/truecharts/public/clustertool/pkg/helper"
)
func GenKubeConfig(node string, extraFlags []string) string {
//extraFlags = append(extraFlags, "--preserve")
talosPath := embed.GetTalosExec()
cmd := talosPath + " kubeconfig --talosconfig " + helper.TalosConfigFile + " -n " + node + " "
return cmd
}
@@ -6,24 +6,21 @@ import (
"github.com/truecharts/public/clustertool/pkg/talassist"
)
func GenReset(node string, extraFlags []string) []string {
func GenPlain(command string, node string, extraFlags []string) []string {
commands := []string{}
//extraFlags = append(extraFlags, "--preserve")
talosPath := embed.GetTalosExec()
if node == "" {
for _, nodeRef := range talassist.IpAddresses {
talassist.LoadNodeIPs()
// TODO add extraFlags
// TODO: add images Refs
// TODO: add schematic
cmd := talosPath + " reset --talosconfig " + helper.TalosConfigFile + " -n " + nodeRef + " "
for _, noderef := range talassist.TalConfig.Nodes {
// TODO add extraFlags
cmd := talosPath + " " + command + " --talosconfig " + helper.TalosConfigFile + " -n " + noderef.IPAddress + " "
commands = append(commands, cmd)
}
} else {
cmd := talosPath + " reset --talosconfig " + helper.TalosConfigFile + " -n " + node + " "
cmd := talosPath + " " + command + " --talosconfig " + helper.TalosConfigFile + " -n " + node + " "
commands = append(commands, cmd)
}
return commands
+2 -6
View File
@@ -7,25 +7,21 @@ import (
"github.com/rs/zerolog/log"
talhelperCfg "github.com/budimanjojo/talhelper/v3/pkg/config"
"github.com/budimanjojo/talhelper/v3/pkg/generate"
"github.com/truecharts/public/clustertool/embed"
"github.com/truecharts/public/clustertool/pkg/helper"
"github.com/truecharts/public/clustertool/pkg/talassist"
)
// TODO: remove talhelper dependency for cmd creation
func GenUpgrade(node string, extraFlags []string) []string {
// TODO: get rid of this, due to double uncontrollable log output
cfg, err := talhelperCfg.LoadAndValidateFromFile(helper.TalConfigFile, []string{helper.ClusterEnvFile}, false)
if err != nil {
log.Fatal().Err(err).Msgf("failed to parse talconfig or talenv file: %s", err)
}
upgradeStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w
extraFlags = append(extraFlags, "--preserve")
err = generate.GenerateUpgradeCommand(cfg, helper.TalosGenerated, node, extraFlags)
err := generate.GenerateUpgradeCommand(talassist.TalConfig, helper.TalosGenerated, node, extraFlags)
w.Close()
out, _ := io.ReadAll(r)
-1
View File
@@ -28,7 +28,6 @@ func LoadEnvFromFile(file string, output map[string]string) error {
// Strip comments from YAML content before processing
content = StripYamlComment(content)
// See: https://github.com/budimanjojo/talhelper/issues/220
content = StripYAMLDocDelimiter(content)
if err := LoadEnv(content, output); err != nil {
return fmt.Errorf("trying to load env from %s: %s", file, err)
+2 -20
View File
@@ -2,7 +2,6 @@ package initfiles
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
@@ -17,10 +16,9 @@ import (
"sigs.k8s.io/yaml"
age "filippo.io/age"
talhelperCfg "github.com/budimanjojo/talhelper/v3/pkg/config"
"github.com/invopop/jsonschema"
"github.com/truecharts/public/clustertool/pkg/fluxhandler"
"github.com/truecharts/public/clustertool/pkg/helper"
"github.com/truecharts/public/clustertool/pkg/talassist"
corev1 "k8s.io/api/core/v1"
)
@@ -30,7 +28,7 @@ func InitFiles() error {
genBaseFiles()
UpdateRootFiles()
UpdateBaseFiles()
GenSchema()
talassist.GenSchema()
GenPatches()
genKubernetes()
GenTalEnvConfigMap()
@@ -484,19 +482,3 @@ func GenSopsSecret() error {
log.Info().Msgf("SOPS secret YAML saved to: %s\n", secretPath)
return nil
}
func GenSchema() error {
cfg := talhelperCfg.TalhelperConfig{}
r := new(jsonschema.Reflector)
r.FieldNameTag = "yaml"
r.RequiredFromJSONSchemaTags = true
os.MkdirAll(helper.ClusterPath+"/talos", os.ModePerm)
var genschemaFile = path.Join(helper.ClusterPath, "/talos/talconfig.json")
schema := r.Reflect(&cfg)
data, _ := json.MarshalIndent(schema, "", " ")
if err := os.WriteFile(genschemaFile, data, os.FileMode(0o644)); err != nil {
log.Fatal().Err(err).Msg("failed to write file to %s: %v")
}
return nil
}
-37
View File
@@ -1,37 +0,0 @@
package talassist
import (
"io/ioutil"
"github.com/truecharts/public/clustertool/pkg/helper"
"sigs.k8s.io/yaml"
)
// NodeIPConfig represents a simplified YAML structure to only parse node IP addresses
type NodeIPConfig struct {
Nodes []struct {
IPAddress string `yaml:"ipAddress"`
} `yaml:"nodes"`
}
// LoadNodeIPs loads the list of IP addresses in nodes[].ipAddress from talconfig.yaml
func LoadNodeIPs() error {
// Read the YAML file
data, err := ioutil.ReadFile(helper.TalConfigFile)
if err != nil {
return err
}
// Unmarshal only the IP addresses from the YAML
var config NodeIPConfig
if err := yaml.Unmarshal(data, &config); err != nil {
return err
}
// Extract the IP addresses into a list
for _, node := range config.Nodes {
IpAddresses = append(IpAddresses, node.IPAddress)
}
return nil
}
+76
View File
@@ -0,0 +1,76 @@
package talassist
import (
"encoding/json"
"os"
"path"
talhelperCfg "github.com/budimanjojo/talhelper/v3/pkg/config"
"github.com/budimanjojo/talhelper/v3/pkg/generate"
talhelperTalos "github.com/budimanjojo/talhelper/v3/pkg/talos"
"github.com/invopop/jsonschema"
"github.com/rs/zerolog/log"
sideroConfig "github.com/siderolabs/talos/pkg/machinery/config"
"github.com/siderolabs/talos/pkg/machinery/config/generate/secrets"
"github.com/truecharts/public/clustertool/pkg/helper"
)
var (
TalConfig *talhelperCfg.TalhelperConfig
LatestTalosVersion string
)
func LoadTalConfig() {
cfg, err := talhelperCfg.LoadAndValidateFromFile(helper.TalConfigFile, []string{helper.ClusterEnvFile}, false)
if err != nil {
log.Fatal().Err(err).Msg("failed to parse talconfig or talenv file: %s")
}
TalConfig = cfg
LatestTalosVersion = talhelperCfg.LatestTalosVersion
return
}
func GenSchema() error {
cfg := talhelperCfg.TalhelperConfig{}
r := new(jsonschema.Reflector)
r.FieldNameTag = "yaml"
r.RequiredFromJSONSchemaTags = true
os.MkdirAll(helper.ClusterPath+"/talos", os.ModePerm)
var genschemaFile = path.Join(helper.ClusterPath, "/talos/talconfig.json")
schema := r.Reflect(&cfg)
data, _ := json.MarshalIndent(schema, "", " ")
if err := os.WriteFile(genschemaFile, data, os.FileMode(0o644)); err != nil {
log.Fatal().Err(err).Msg("failed to write file to %s: %v")
}
return nil
}
func NewSecretBundle() *secrets.Bundle {
version, _ := sideroConfig.ParseContractFromVersion(LatestTalosVersion)
s, err := talhelperTalos.NewSecretBundle(secrets.NewClock(), *version)
if err != nil {
log.Error().Msgf("Error loading secret bundle %s", err)
}
return s
}
func TalhelperGenConfig() error {
genconfigTalosMode := "metal"
genconfigNoGitignore := false
genconfigDryRun := false
genconfigOfflineMode := false
err := generate.GenerateConfig(TalConfig, genconfigDryRun, helper.TalosGenerated, helper.TalSecretFile, genconfigTalosMode, genconfigOfflineMode)
if err != nil {
log.Fatal().Err(err).Msgf("failed to generate talos config: %s", err)
}
if !genconfigNoGitignore && !genconfigDryRun {
err = TalConfig.GenerateGitignore(helper.TalosGenerated)
if err != nil {
log.Fatal().Err(err).Msgf("failed to generate gitignore file: %s", err)
}
}
return nil
}
-5
View File
@@ -1,5 +0,0 @@
package talassist
var (
IpAddresses = []string{}
)