// Package cmd holds the cobra command tree. package cmd import ( "fmt" "os" "github.com/spf13/cobra" "schlundtech-dns/internal/api" "schlundtech-dns/internal/config" "schlundtech-dns/internal/output" ) // global flags shared by every command. var ( flagOutput string flagEndpoint string flagDryRun bool ) var rootCmd = &cobra.Command{ Use: "schlundtech-dns", Short: "Manage Schlundtech DNS zones and records", Long: `schlundtech-dns talks to the Schlundtech DNS gateway and lets you list your zones, read their records and change them. Credentials come from the environment: SCHLUNDTECH_USER the gateway user SCHLUNDTECH_PASSWORD the gateway password SCHLUNDTECH_CONTEXT the project the records belong to (Schlundtech uses 10) SCHLUNDTECH_TOKEN optional second-factor token, if 2FA is enabled DNS changes are public and propagate within seconds, so every command that writes has a --dry-run flag. Use it first.`, Example: ` export SCHLUNDTECH_USER=... SCHLUNDTECH_PASSWORD=... SCHLUNDTECH_CONTEXT=10 schlundtech-dns zones schlundtech-dns records list example.com schlundtech-dns records set example.com --name @ --type TXT --value 'v=spf1 -all' --dry-run`, SilenceUsage: true, SilenceErrors: true, } func init() { rootCmd.PersistentFlags().StringVar(&flagOutput, "output", "table", "output format: table or json") rootCmd.PersistentFlags().StringVar(&flagEndpoint, "endpoint", "", "override the gateway URL (default "+api.DefaultEndpoint+")") rootCmd.PersistentFlags().BoolVar(&flagDryRun, "dry-run", false, "show what would change without sending it") } // Execute runs the command tree. Errors go to stderr so that stdout stays // pipeable. func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Fprintln(os.Stderr, "error:", err) os.Exit(1) } } // format returns the parsed output format. func format() (output.Format, error) { return output.Parse(flagOutput) } // client builds an API client from the environment. Commands that do not talk // to the gateway never call it, so --help works without credentials. func client() (*api.Client, error) { creds, err := config.FromEnv() if err != nil { return nil, err } endpoint := flagEndpoint if endpoint == "" { endpoint = creds.Endpoint } opts := []api.Option{} if endpoint != "" { opts = append(opts, api.WithEndpoint(endpoint)) } return api.New(api.Credentials{ User: creds.User, Password: creds.Password, Context: creds.Context, Token: creds.Token, }, opts...), nil }