package main import ( "encoding/json" "fmt" "os" "strings" "text/tabwriter" "warpbox/lib/config" "github.com/spf13/cobra" ) func newEnvCommand() *cobra.Command { cmd := &cobra.Command{ Use: "env", Short: "Explore environment variable options", Long: "List and inspect WarpBox environment variables sourced from the codebase.", } cmd.AddCommand(newEnvListCommand()) cmd.AddCommand(newEnvDescribeCommand()) return cmd } func newEnvListCommand() *cobra.Command { var format string var includeHidden bool cmd := &cobra.Command{ Use: "ls", Aliases: []string{"list"}, Short: "List all environment variables", RunE: func(cmd *cobra.Command, args []string) error { return formatEnvList(format, includeHidden) }, } cmd.Flags().StringVarP(&format, "format", "o", "table", "Output format: table, json, env") cmd.Flags().BoolVar(&includeHidden, "hidden", false, "Include non-editable and hard-limit settings") return cmd } func newEnvDescribeCommand() *cobra.Command { cmd := &cobra.Command{ Use: "describe", Aliases: []string{"show", "info", "get"}, Short: "Describe an environment variable", Long: "Show detailed info about a specific env var or setting key.", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { return describeEnvVar(args[0]) }, } return cmd } type envRow struct { EnvName string Key string Label string Type config.SettingType Default string Editable bool HardLimit bool Minimum int64 } type describeRow struct { EnvName string Key string Label string Type config.SettingType Default string Value string Source string Editable bool HardLimit bool Minimum int64 } func formatEnvList(format string, includeHidden bool) error { allRows := buildAllEnvRows(includeHidden) switch format { case "json": type envOut struct { EnvName string `json:"env_name"` Key string `json:"key"` Label string `json:"label"` Type string `json:"type"` Default string `json:"default"` Editable bool `json:"editable"` HardLimit bool `json:"hard_limit"` Minimum int64 `json:"minimum,omitempty"` } out := make([]envOut, len(allRows)) for i, r := range allRows { out[i] = envOut{ EnvName: r.EnvName, Key: r.Key, Label: r.Label, Type: string(r.Type), Default: r.Default, Editable: r.Editable, HardLimit: r.HardLimit, Minimum: r.Minimum, } } enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") return enc.Encode(out) case "env": for _, r := range allRows { fmt.Printf("%s=\"%s\"\n", r.EnvName, r.Default) } return nil case "table", "": w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintln(w, "ENV NAME\tKey\tLabel\tType\tDefault\tEditable") for _, r := range allRows { fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%v\n", r.EnvName, r.Key, r.Label, r.Type, r.Default, r.Editable) } return w.Flush() default: return fmt.Errorf("unknown format: %s (use 'table', 'json', or 'env')", format) } } func buildAllEnvRows(includeHidden bool) []envRow { cfg, loadErr := config.Load() var rows []envRow for _, def := range config.Definitions { if !includeHidden && (!def.Editable || def.HardLimit) { continue } row := envRow{ EnvName: def.EnvName, Key: def.Key, Label: def.Label, Type: def.Type, Editable: def.Editable, HardLimit: def.HardLimit, Minimum: def.Minimum, } if loadErr == nil { row.Default = getEnvDefault(cfg, def) } rows = append(rows, row) } extra := buildExtraEnvRows(includeHidden) rows = append(rows, extra...) return rows } func getEnvDefault(cfg *config.Config, def config.SettingDefinition) string { for _, row := range cfg.SettingRows() { if row.Definition.Key == def.Key && row.Source == config.SourceDefault { return row.Value } } return "" } func buildExtraEnvRows(includeHidden bool) []envRow { extra := []envRow{ {EnvName: "WARPBOX_ADMIN_ENABLED", Key: "admin_enabled", Label: "Admin interface mode", Type: config.SettingTypeText, Editable: false, Default: "auto"}, {EnvName: "WARPBOX_ADMIN_USERNAME", Key: "admin_username", Label: "Admin username", Type: config.SettingTypeText, Editable: false, Default: "admin"}, {EnvName: "WARPBOX_ADMIN_PASSWORD", Key: "admin_password", Label: "Admin password", Type: config.SettingTypeText, Editable: false, Default: "(none)"}, {EnvName: "WARPBOX_ADMIN_EMAIL", Key: "admin_email", Label: "Admin email", Type: config.SettingTypeText, Editable: false, Default: "(none)"}, {EnvName: "WARPBOX_ADMIN_COOKIE_SECURE", Key: "admin_cookie_secure", Label: "Admin cookie secure flag", Type: config.SettingTypeBool, Editable: false, Default: "false"}, {EnvName: "WARPBOX_ALLOW_ADMIN_SETTINGS_OVERRIDE", Key: "allow_admin_override", Label: "Allow admin UI to override settings", Type: config.SettingTypeBool, Editable: false, HardLimit: true, Default: "true"}, } sizePairs := []struct { bytesEnv string mbEnv string label string }{ {"WARPBOX_GLOBAL_MAX_FILE_SIZE_BYTES", "WARPBOX_GLOBAL_MAX_FILE_SIZE_MB", "Global max file size"}, {"WARPBOX_GLOBAL_MAX_BOX_SIZE_BYTES", "WARPBOX_GLOBAL_MAX_BOX_SIZE_MB", "Global max box size"}, {"WARPBOX_DEFAULT_USER_MAX_FILE_SIZE_BYTES", "WARPBOX_DEFAULT_USER_MAX_FILE_SIZE_MB", "Default user max file size"}, {"WARPBOX_DEFAULT_USER_MAX_BOX_SIZE_BYTES", "WARPBOX_DEFAULT_USER_MAX_BOX_SIZE_MB", "Default user max box size"}, } for _, pair := range sizePairs { extra = append(extra, envRow{EnvName: pair.bytesEnv, Key: pair.bytesEnv, Label: pair.label + " (bytes)", Type: config.SettingTypeInt64, Editable: false, HardLimit: true, Minimum: 0, Default: "(use bytes or MB variant)"}) extra = append(extra, envRow{EnvName: pair.mbEnv, Key: pair.mbEnv, Label: pair.label + " (MB)", Type: config.SettingTypeInt64, Editable: false, HardLimit: true, Minimum: 0, Default: "(use bytes or MB variant)"}) } return extra } func describeEnvVar(query string) error { cfg, loadErr := config.Load() for _, def := range config.Definitions { if matchEnv(query, def.EnvName, def.Key) { row := describeRow{ EnvName: def.EnvName, Key: def.Key, Label: def.Label, Type: def.Type, Editable: def.Editable, HardLimit: def.HardLimit, Minimum: def.Minimum, } if loadErr == nil { for _, r := range cfg.SettingRows() { if r.Definition.Key == def.Key { row.Value = r.Value row.Source = string(r.Source) break } } } printDescribeRow(row) return nil } } extras := buildExtraEnvRows(true) for _, er := range extras { if matchEnv(query, er.EnvName, er.Key) { row := describeRow{ EnvName: er.EnvName, Key: er.Key, Label: er.Label, Type: er.Type, Editable: er.Editable, HardLimit: er.HardLimit, Minimum: er.Minimum, Default: er.Default, } printDescribeRow(row) return nil } } return fmt.Errorf("no environment variable found matching: %s\n\nUse 'warpbox env ls' to list all available options.", query) } func matchEnv(query, envName, key string) bool { return strings.EqualFold(query, envName) || strings.EqualFold(query, key) } func printDescribeRow(r describeRow) { w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintf(w, "Environment Variable:\t%s\n", r.EnvName) fmt.Fprintf(w, "Setting Key:\t%s\n", r.Key) fmt.Fprintf(w, "Label:\t%s\n", r.Label) fmt.Fprintf(w, "Type:\t%s\n", r.Type) fmt.Fprintf(w, "Editable (runtime):\t%v\n", r.Editable) fmt.Fprintf(w, "Hard Limit:\t%v\n", r.HardLimit) if r.Minimum > 0 { fmt.Fprintf(w, "Minimum:\t%d\n", r.Minimum) } if r.Default != "" { fmt.Fprintf(w, "Default:\t%s\n", r.Default) } if r.Value != "" { fmt.Fprintf(w, "Current Value:\t%s\n", r.Value) } if r.Source != "" { fmt.Fprintf(w, "Source:\t%s\n", r.Source) } w.Flush() }