// Package cmd holds the cobra command tree. package cmd import ( "fmt" "os" "github.com/spf13/cobra" "schlundtech-dns/internal/api" ) // 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 are read from a .env file in the working directory, falling back to the environment. Real environment variables win over .env, so a one-off override needs no edit: SCHLUNDTECH_CONTEXT=1 ./schlundtech-dns zones Copy .env.example to .env and fill it in: SCHLUNDTECH_USER the gateway user SCHLUNDTECH_PASSWORD the gateway password SCHLUNDTECH_CONTEXT the project the records belong to (Schlundtech uses 10) SCHLUNDTECH_TOKEN six-digit 2FA code, if two-factor authentication is on SCHLUNDTECH_ENDPOINT override the gateway URL, e.g. the demo system Keep .env out of git and readable only by you: chmod 600 .env DNS changes are public and propagate within seconds, so every command that writes has a --dry-run flag. Use it first.`, Example: ` cp .env.example .env && chmod 600 .env ./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) } } // 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, warning, err := loadCredentials() if warning != "" { // A warning, not an error: the credentials are still usable. fmt.Fprintln(os.Stderr, "warning:", warning) } 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(creds, opts...), nil }