Files
wild-cloud/wild-cli/cmd/wild/root.go

147 lines
3.9 KiB
Go

package main
import (
"context"
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/wild-cloud/wild-cli/cmd/wild/app"
"github.com/wild-cloud/wild-cli/cmd/wild/cluster"
"github.com/wild-cloud/wild-cli/cmd/wild/config"
"github.com/wild-cloud/wild-cli/cmd/wild/secret"
"github.com/wild-cloud/wild-cli/cmd/wild/setup"
"github.com/wild-cloud/wild-cli/cmd/wild/util"
"github.com/wild-cloud/wild-cli/internal/environment"
"github.com/wild-cloud/wild-cli/internal/output"
)
var (
// Global flags
cfgDir string
verbose bool
dryRun bool
noColor bool
wcRoot string
wcHome string
)
func newRootCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "wild",
Short: "Wild Cloud - Personal cloud infrastructure management",
Long: `Wild Cloud CLI provides comprehensive management of your personal cloud infrastructure
built on Talos Linux and Kubernetes.
This tool replaces the collection of wild-* bash scripts with a single, unified CLI
that provides better error handling, progress tracking, and cross-platform support.`,
Version: "0.1.0-dev",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return initializeConfig(cmd.Context())
},
SilenceUsage: true,
SilenceErrors: true,
}
// Add persistent flags
pflags := cmd.PersistentFlags()
pflags.StringVar(&cfgDir, "config-dir", "", "config directory (default: current directory)")
pflags.BoolVarP(&verbose, "verbose", "v", false, "enable verbose logging")
pflags.BoolVar(&dryRun, "dry-run", false, "show what would be done without making changes")
pflags.BoolVar(&noColor, "no-color", false, "disable colored output")
pflags.StringVar(&wcRoot, "wc-root", "", "Wild Cloud installation directory")
pflags.StringVar(&wcHome, "wc-home", "", "Wild Cloud project directory")
// Bind flags to viper
_ = viper.BindPFlag("verbose", pflags.Lookup("verbose"))
_ = viper.BindPFlag("dry-run", pflags.Lookup("dry-run"))
_ = viper.BindPFlag("no-color", pflags.Lookup("no-color"))
// Add subcommands
cmd.AddCommand(
setup.NewSetupCommand(),
app.NewAppCommand(),
cluster.NewClusterCommand(),
config.NewConfigCommand(),
secret.NewSecretCommand(),
util.NewBackupCommand(),
util.NewDashboardCommand(),
util.NewTemplateCommand(),
util.NewStatusCommand(),
util.NewVersionCommand(),
)
return cmd
}
func initializeConfig(ctx context.Context) error {
// Set up output formatting based on flags
if noColor {
output.DisableColor()
}
if verbose {
output.SetVerbose(true)
}
// Initialize environment
env := environment.New()
// Set WC_ROOT
if wcRoot != "" {
env.SetWCRoot(wcRoot)
} else if envRoot := os.Getenv("WC_ROOT"); envRoot != "" {
env.SetWCRoot(envRoot)
}
// Detect or set WC_HOME
if wcHome != "" {
env.SetWCHome(wcHome)
} else if cfgDir != "" {
env.SetWCHome(cfgDir)
} else {
// Try to auto-detect WC_HOME by looking for .wildcloud marker
detected, err := env.DetectWCHome()
if err != nil {
return fmt.Errorf("failed to detect Wild Cloud project directory: %w", err)
}
if detected == "" {
// Only require WC_HOME for commands that need it
// Some commands like "wild setup scaffold" don't need an existing project
return nil
}
env.SetWCHome(detected)
}
// Validate environment
if err := env.Validate(ctx); err != nil {
return fmt.Errorf("environment validation failed: %w", err)
}
// Set up viper configuration
if env.WCHome() != "" {
viper.AddConfigPath(env.WCHome())
viper.SetConfigName("config")
viper.SetConfigType("yaml")
// Try to read config file (not required)
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
return fmt.Errorf("error reading config file: %w", err)
}
}
}
// Set environment variables for child processes and internal use
if env.WCRoot() != "" {
_ = os.Setenv("WC_ROOT", env.WCRoot())
}
if env.WCHome() != "" {
_ = os.Setenv("WC_HOME", env.WCHome())
}
return nil
}