maidn-cli/cmd/bootstrap.go

95 lines
3.3 KiB
Go

package cmd
import (
"fmt"
"github.com/Pingu-Studio/MaidnCLI/internal/bootstrap"
"github.com/Pingu-Studio/MaidnCLI/internal/config"
"github.com/Pingu-Studio/MaidnCLI/internal/openbao"
"github.com/Pingu-Studio/MaidnCLI/internal/ui"
"github.com/spf13/cobra"
)
var bootstrapConfigPath string
var bootstrapOutputPath string
var bootstrapMode string
var bootstrapYes bool
var bootstrapPromptDemocraticCSI bool
var bootstrapPromptOperationalSecrets bool
var bootstrapInitializeOpenBaoRecovery bool
var bootstrapCmd = &cobra.Command{
Use: "bootstrap",
Short: "Bootstrap Talos and Flux from config or an interactive wizard.",
RunE: runBootstrap,
}
func init() {
rootCmd.AddCommand(bootstrapCmd)
bootstrapCmd.Flags().StringVar(&bootstrapConfigPath, "config", "", "Path to bootstrap config YAML")
bootstrapCmd.Flags().StringVar(&bootstrapOutputPath, "out", "maidn-bootstrap.yaml", "Path to save generated config")
bootstrapCmd.Flags().StringVar(&bootstrapMode, "mode", string(bootstrap.Reconcile), "Lifecycle mode: reconcile or rebuild")
bootstrapCmd.Flags().BoolVar(&bootstrapYes, "yes", false, "Confirm destructive rebuild")
bootstrapCmd.Flags().BoolVar(&bootstrapPromptDemocraticCSI, "prompt-democratic-csi", false, "Prompt for and save Democratic CSI settings in --config")
bootstrapCmd.Flags().BoolVar(&bootstrapPromptOperationalSecrets, "prompt-operational-secrets", false, "Prompt for and encrypt operational secrets for --config")
bootstrapCmd.Flags().BoolVar(&bootstrapInitializeOpenBaoRecovery, "initialize-openbao-recovery", false, "Create and save a separate OpenBao recovery age identity for --config")
}
func runBootstrap(cmd *cobra.Command, args []string) error {
var cfg config.Config
var err error
if bootstrapConfigPath != "" {
if bootstrapPromptDemocraticCSI || bootstrapPromptOperationalSecrets || bootstrapInitializeOpenBaoRecovery {
cfg, err = config.LoadRaw(bootstrapConfigPath)
if err == nil {
if bootstrapPromptDemocraticCSI {
cfg = ui.PromptDemocraticCSI(cfg)
}
cfg, err = config.Resolve(cfg)
}
if err == nil && bootstrapPromptOperationalSecrets {
var secrets map[string]map[string]string
secrets, err = ui.PromptOperationalSecrets(cfg)
if err == nil {
var authorization string
authorization, err = bootstrap.NewWebhookAuthorization()
if err == nil {
secrets["cicd/forgejo-webhook"] = map[string]string{"authorization": authorization}
err = bootstrap.WriteOperationalSecrets(cfg.SOPS.OperationalSecretsPath, cfg.SOPS.AgeKeyPath, secrets)
}
}
}
if err == nil && bootstrapInitializeOpenBaoRecovery {
var recipient string
recipient, err = openbao.EnsureRecoveryIdentity(cfg.SOPS.RecoveryIdentityPath)
if err == nil {
cfg.SOPS.RecoveryRecipient = recipient
}
}
if err == nil {
err = config.Save(bootstrapConfigPath, cfg)
}
} else {
cfg, err = config.Load(bootstrapConfigPath)
}
} else {
cfg, err = ui.RunBootstrapWizard(config.Config{})
if err == nil {
cfg, err = config.Resolve(cfg)
}
if err == nil {
err = config.Save(bootstrapOutputPath, cfg)
if err == nil {
fmt.Printf("[INFO] Saved config to %s\n", bootstrapOutputPath)
}
}
}
if err != nil {
return err
}
runner := bootstrap.Runner{Config: cfg, Mode: bootstrap.Mode(bootstrapMode), ConfirmRebuild: bootstrapYes}
return runner.Run()
}