maidn-cli/internal/bootstrap/bootstrap.go

160 lines
6.3 KiB
Go

package bootstrap
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/Pingu-Studio/MaidnCLI/internal/config"
ghrepo "github.com/Pingu-Studio/MaidnCLI/internal/github"
"github.com/Pingu-Studio/MaidnCLI/internal/utils"
)
type Runner struct {
Config config.Config
}
func (r Runner) Run() error {
workspace := r.Config.WorkspaceDir
if err := os.MkdirAll(workspace, 0755); err != nil {
return err
}
if err := ghrepo.NewRepoManager(r.Config.GitHub.Org, "cicd-deployment-manifests", r.Config.Flux.RepoName).InitializeAll(); err != nil {
return err
}
repoDir := filepath.Join(workspace, r.Config.Talos.RepoDirName)
if err := ensureRepo(repoDir, r.Config.Talos.RepoURL, r.Config.Talos.RepoRef); err != nil {
return err
}
terraformDir := filepath.Join(repoDir, r.Config.Talos.TerraformDir)
generatedDir := filepath.Join(repoDir, r.Config.Talos.GeneratedDir)
if err := os.MkdirAll(generatedDir, 0755); err != nil {
return err
}
if err := os.WriteFile(filepath.Join(terraformDir, r.Config.Talos.ConfigFileName), []byte(renderTerraformTFVars(r.Config)), 0644); err != nil {
return err
}
if r.Config.Talos.AutoRunTerraform {
if err := utils.RunCommandInDir(terraformDir, "terraform", "init"); err != nil {
return err
}
if err := utils.RunCommandInDir(terraformDir, "terraform", "apply", "-auto-approve"); err != nil {
return err
}
}
if r.Config.Talos.AutoBootstrap {
if err := utils.RunCommandInDir(generatedDir, "talosctl", "bootstrap", "--talosconfig=./clusterconfig/talosconfig", "--nodes="+r.Config.Talos.BootstrapNode); err != nil {
return err
}
if err := utils.RunCommandInDir(generatedDir, "talosctl", "kubeconfig", "--talosconfig=./clusterconfig/talosconfig", "--nodes="+r.Config.Talos.KubeconfigNode, "."); err != nil {
return err
}
}
if r.Config.Talos.AutoBootstrapFlux {
if err := utils.RunCommand("flux", "bootstrap", "github", "--owner="+r.Config.Flux.Owner, "--repository="+r.Config.Flux.RepoName, "--branch="+r.Config.Flux.Branch, "--path="+r.Config.Flux.ClusterPath, "--cluster-domain="+r.Config.Flux.ClusterDomain); err != nil {
return err
}
}
return nil
}
func ensureRepo(dir, repoURL, ref string) error {
if _, err := os.Stat(dir); os.IsNotExist(err) {
return utils.RunCommand("git", "clone", "--branch", ref, repoURL, dir)
}
if err := utils.RunCommandInDir(dir, "git", "fetch", "origin"); err != nil {
return err
}
return utils.RunCommandInDir(dir, "git", "checkout", ref)
}
func renderTerraformTFVars(cfg config.Config) string {
var builder strings.Builder
builder.WriteString(fmt.Sprintf("proxmox_api_url = %q\n", cfg.Talos.Proxmox.APIURL))
builder.WriteString(fmt.Sprintf("proxmox_node = %q\n", cfg.Talos.Proxmox.DefaultNode))
builder.WriteString(fmt.Sprintf("proxmox_api_token = %q\n", cfg.Talos.Proxmox.APIToken))
builder.WriteString(fmt.Sprintf("proxmox_pool = %q\n", cfg.Talos.Proxmox.Pool))
builder.WriteString(fmt.Sprintf("cluster_name = %q\n", cfg.Talos.Cluster.Name))
builder.WriteString(fmt.Sprintf("cluster_domain = %q\n", cfg.Talos.Cluster.Domain))
builder.WriteString(fmt.Sprintf("talos_factory_schematic_id = %q\n", cfg.Talos.Image.FactorySchematicID))
builder.WriteString(fmt.Sprintf("talos_version = %q\n", cfg.Talos.Image.TalosVersion))
builder.WriteString(fmt.Sprintf("cni_name = %q\n", cfg.Talos.Cluster.CNI))
builder.WriteString(fmt.Sprintf("talos_iso_file = %q\n", cfg.Talos.Image.TalosISOFile))
updateMode := cfg.Talos.Image.UpdateMode
if updateMode == "" {
updateMode = "manual"
}
storage := cfg.Talos.Image.Storage
if storage == "" {
storage = "local"
}
architecture := cfg.Talos.Image.Architecture
if architecture == "" {
architecture = "amd64"
}
builder.WriteString(fmt.Sprintf("talos_image_update_mode = %q\n", updateMode))
builder.WriteString(fmt.Sprintf("talos_image_storage = %q\n", storage))
builder.WriteString(fmt.Sprintf("talos_image_architecture = %q\n", architecture))
builder.WriteString(fmt.Sprintf("disk_storage = %q\n", cfg.Talos.Cluster.DiskStorage))
builder.WriteString(fmt.Sprintf("additional_disk_storage = %q\n", cfg.Talos.Cluster.AdditionalStorage))
builder.WriteString(fmt.Sprintf("dns_servers = [%s]\n", quoteList(cfg.Talos.Cluster.DNSServers)))
builder.WriteString(fmt.Sprintf("control_plane_vip = %q\n", cfg.Talos.Cluster.ControlPlaneVIP))
builder.WriteString("node_interfaces = {\n")
for node, iface := range cfg.Talos.Proxmox.NodeInterfaces {
builder.WriteString(fmt.Sprintf(" %q = %q\n", node, iface))
}
builder.WriteString("}\n")
builder.WriteString(fmt.Sprintf("create_vlan_interface = %t\n", cfg.Talos.Cluster.CreateVLANInterface))
builder.WriteString("image_cache_proxy = { enabled = false, ip = \"\", port = 3128 }\n")
builder.WriteString("nodes = [\n")
for _, node := range cfg.Talos.Nodes {
builder.WriteString(" {\n")
builder.WriteString(fmt.Sprintf(" name = %q\n", node.Name))
builder.WriteString(fmt.Sprintf(" vmid = %d\n", node.VMID))
builder.WriteString(fmt.Sprintf(" role = %q\n", node.Role))
builder.WriteString(fmt.Sprintf(" cores = %d\n", node.Cores))
builder.WriteString(fmt.Sprintf(" memory = %d\n", node.Memory))
builder.WriteString(fmt.Sprintf(" disk_size = %q\n", node.DiskSize))
if node.AdditionalDiskSize != "" {
builder.WriteString(fmt.Sprintf(" additional_disk_size = %q\n", node.AdditionalDiskSize))
}
builder.WriteString(fmt.Sprintf(" tags = [%s]\n", quoteList(node.Tags)))
builder.WriteString(fmt.Sprintf(" proxmox_node = %q\n", node.ProxmoxNode))
builder.WriteString(" networks = [\n")
for _, net := range node.Networks {
builder.WriteString(" {\n")
builder.WriteString(fmt.Sprintf(" mac_address = %q\n", net.MACAddress))
builder.WriteString(fmt.Sprintf(" cidr = %q\n", net.CIDR))
if net.IP != "" {
builder.WriteString(fmt.Sprintf(" ip = %q\n", net.IP))
}
if net.Gateway != "" {
builder.WriteString(fmt.Sprintf(" gateway = %q\n", net.Gateway))
}
builder.WriteString(fmt.Sprintf(" vlan_id = %d\n", net.VLANID))
builder.WriteString(" },\n")
}
builder.WriteString(" ]\n")
builder.WriteString(" },\n")
}
builder.WriteString("]\n")
return builder.String()
}
func quoteList(values []string) string {
quoted := make([]string, 0, len(values))
for _, value := range values {
quoted = append(quoted, fmt.Sprintf("%q", value))
}
return strings.Join(quoted, ", ")
}