From b1daabfab81d403266ab35903f3cc6a5dae3be9a Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Thu, 26 Sep 2024 14:34:55 -0400 Subject: [PATCH] add new 'headless' config option (#224) --- cmd/zrok/accessPrivate.go | 6 +++++- cmd/zrok/configGet.go | 6 ++++++ cmd/zrok/configSet.go | 19 +++++++++++++++++++ cmd/zrok/configUnset.go | 3 +++ cmd/zrok/sharePrivate.go | 6 +++++- cmd/zrok/sharePublic.go | 6 +++++- cmd/zrok/shareReserved.go | 6 +++++- cmd/zrok/status.go | 2 ++ environment/env_core/model.go | 2 ++ environment/env_v0_3/api.go | 21 +++++++++++++++++++++ environment/env_v0_4/api.go | 21 +++++++++++++++++++++ environment/env_v0_4/root.go | 8 +++++++- 12 files changed, 101 insertions(+), 5 deletions(-) diff --git a/cmd/zrok/accessPrivate.go b/cmd/zrok/accessPrivate.go index 5a746bac..5745c65b 100644 --- a/cmd/zrok/accessPrivate.go +++ b/cmd/zrok/accessPrivate.go @@ -50,7 +50,11 @@ func newAccessPrivateCommand() *accessPrivateCommand { Args: cobra.ExactArgs(1), } command := &accessPrivateCommand{cmd: cmd} - cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless") + headless := false + if root, err := environment.LoadRoot(); err == nil { + headless, _ = root.Headless() + } + cmd.Flags().BoolVar(&command.headless, "headless", headless, "Disable TUI and run headless") cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable subordinate mode") cmd.MarkFlagsMutuallyExclusive("headless", "subordinate") cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode") diff --git a/cmd/zrok/configGet.go b/cmd/zrok/configGet.go index 0d1905d0..a9b0ddd5 100644 --- a/cmd/zrok/configGet.go +++ b/cmd/zrok/configGet.go @@ -46,6 +46,12 @@ func (cmd *configGetCommand) run(_ *cobra.Command, args []string) { } else { fmt.Println("defaultFrontend = ") } + case "headless": + if env.Config() != nil { + fmt.Printf("headless = %v\n", env.Config().Headless) + } else { + fmt.Println("headless = ") + } default: fmt.Printf("unknown config name '%v'\n", configName) } diff --git a/cmd/zrok/configSet.go b/cmd/zrok/configSet.go index 44773fbf..d075a124 100644 --- a/cmd/zrok/configSet.go +++ b/cmd/zrok/configSet.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" "net/url" "os" + "strconv" ) func init() { @@ -77,6 +78,24 @@ func (cmd *configSetCommand) run(_ *cobra.Command, args []string) { } fmt.Println("zrok configuration updated") + case "headless": + headless, err := strconv.ParseBool(value) + if err != nil { + tui.Error("unable to parse value for 'headless': %v", err) + } + if env.Config() == nil { + if err := env.SetConfig(&env_core.Config{Headless: headless}); err != nil { + tui.Error("unable to save config", err) + } + } else { + cfg := env.Config() + cfg.Headless = headless + if err := env.SetConfig(cfg); err != nil { + tui.Error("unable to save config", err) + } + } + fmt.Println("zrok configuration updated") + default: fmt.Printf("unknown config name '%v'\n", configName) os.Exit(1) diff --git a/cmd/zrok/configUnset.go b/cmd/zrok/configUnset.go index 34e5d292..5fbb817b 100644 --- a/cmd/zrok/configUnset.go +++ b/cmd/zrok/configUnset.go @@ -47,6 +47,9 @@ func (cmd *configUnsetCommand) run(_ *cobra.Command, args []string) { case "defaultFrontend": cfg.DefaultFrontend = "" + case "headless": + cfg.Headless = false + default: fmt.Printf("unknown config name '%v'\n", configName) os.Exit(1) diff --git a/cmd/zrok/sharePrivate.go b/cmd/zrok/sharePrivate.go index 582c388b..1fa4976c 100644 --- a/cmd/zrok/sharePrivate.go +++ b/cmd/zrok/sharePrivate.go @@ -50,8 +50,12 @@ func newSharePrivateCommand() *sharePrivateCommand { Args: cobra.RangeArgs(0, 1), } command := &sharePrivateCommand{cmd: cmd} + headless := false + if root, err := environment.LoadRoot(); err == nil { + headless, _ = root.Headless() + } cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, tcpTunnel, udpTunnel, caddy, drive, socks, vpn}") - cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless") + cmd.Flags().BoolVar(&command.headless, "headless", headless, "Disable TUI and run headless") cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable agent mode") cmd.MarkFlagsMutuallyExclusive("headless", "subordinate") cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode") diff --git a/cmd/zrok/sharePublic.go b/cmd/zrok/sharePublic.go index 799949b5..761478e2 100644 --- a/cmd/zrok/sharePublic.go +++ b/cmd/zrok/sharePublic.go @@ -58,9 +58,13 @@ func newSharePublicCommand() *sharePublicCommand { defaultFrontend, _ := root.DefaultFrontend() defaultFrontends = []string{defaultFrontend} } + headless := false + if root, err := environment.LoadRoot(); err == nil { + headless, _ = root.Headless() + } cmd.Flags().StringArrayVar(&command.frontendSelection, "frontend", defaultFrontends, "Selected frontends to use for the share") cmd.Flags().StringVarP(&command.backendMode, "backend-mode", "b", "proxy", "The backend mode {proxy, web, caddy, drive}") - cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless") + cmd.Flags().BoolVar(&command.headless, "headless", headless, "Disable TUI and run headless") cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable agent mode") cmd.MarkFlagsMutuallyExclusive("headless", "subordinate") cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode") diff --git a/cmd/zrok/shareReserved.go b/cmd/zrok/shareReserved.go index 7e50c6f8..b723e64d 100644 --- a/cmd/zrok/shareReserved.go +++ b/cmd/zrok/shareReserved.go @@ -47,8 +47,12 @@ func newShareReservedCommand() *shareReservedCommand { Args: cobra.ExactArgs(1), } command := &shareReservedCommand{cmd: cmd} + headless := false + if root, err := environment.LoadRoot(); err == nil { + headless, _ = root.Headless() + } cmd.Flags().StringVar(&command.overrideEndpoint, "override-endpoint", "", "Override the stored target endpoint with a replacement") - cmd.Flags().BoolVar(&command.headless, "headless", false, "Disable TUI and run headless") + cmd.Flags().BoolVar(&command.headless, "headless", headless, "Disable TUI and run headless") cmd.Flags().BoolVar(&command.subordinate, "subordinate", false, "Enable agent mode") cmd.MarkFlagsMutuallyExclusive("headless", "subordinate") cmd.Flags().BoolVar(&command.forceLocal, "force-local", false, "Skip agent detection and force local mode") diff --git a/cmd/zrok/status.go b/cmd/zrok/status.go index f54f83cb..304b7dca 100644 --- a/cmd/zrok/status.go +++ b/cmd/zrok/status.go @@ -52,6 +52,8 @@ func (cmd *statusCommand) run(_ *cobra.Command, _ []string) { t.AppendRow(table.Row{"apiEndpoint", apiEndpoint, apiEndpointFrom}) defaultFrontend, defaultFrontendFrom := env.DefaultFrontend() t.AppendRow(table.Row{"defaultFrontend", defaultFrontend, defaultFrontendFrom}) + headless, headlessFrom := env.Headless() + t.AppendRow(table.Row{"headless", headless, headlessFrom}) t.Render() _, _ = fmt.Fprintf(os.Stderr, "\n") diff --git a/environment/env_core/model.go b/environment/env_core/model.go index de3eeb70..39624774 100644 --- a/environment/env_core/model.go +++ b/environment/env_core/model.go @@ -14,6 +14,7 @@ type Root interface { Client() (*rest_client_zrok.Zrok, error) ApiEndpoint() (string, string) DefaultFrontend() (string, string) + Headless() (bool, string) IsEnabled() bool Environment() *Environment @@ -39,6 +40,7 @@ type Environment struct { type Config struct { ApiEndpoint string DefaultFrontend string + Headless bool } type Metadata struct { diff --git a/environment/env_v0_3/api.go b/environment/env_v0_3/api.go index c4a0a090..e71df04c 100644 --- a/environment/env_v0_3/api.go +++ b/environment/env_v0_3/api.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" "regexp" + "strconv" ) func (r *Root) Metadata() *env_core.Metadata { @@ -103,6 +104,26 @@ func (r *Root) DefaultFrontend() (string, string) { return defaultFrontend, from } +func (r *Root) Headless() (bool, string) { + headless := false + from := "binary" + + if r.Config() != nil { + headless = r.Config().Headless + from = "config" + } + + env := os.Getenv("ZROK_HEADLESS") + if env != "" { + if v, err := strconv.ParseBool(env); err == nil { + headless = v + from = "ZROK_HEADLESS" + } + } + + return headless, from +} + func (r *Root) Environment() *env_core.Environment { return r.env } diff --git a/environment/env_v0_4/api.go b/environment/env_v0_4/api.go index e2123197..cfe589c2 100644 --- a/environment/env_v0_4/api.go +++ b/environment/env_v0_4/api.go @@ -12,6 +12,7 @@ import ( "os" "path/filepath" "regexp" + "strconv" ) func (r *Root) Metadata() *env_core.Metadata { @@ -103,6 +104,26 @@ func (r *Root) DefaultFrontend() (string, string) { return defaultFrontend, from } +func (r *Root) Headless() (bool, string) { + headless := false + from := "binary" + + if r.Config() != nil { + headless = r.Config().Headless + from = "config" + } + + env := os.Getenv("ZROK_HEADLESS") + if env != "" { + if v, err := strconv.ParseBool(env); err == nil { + headless = v + from = "ZROK_HEADLESS" + } + } + + return headless, from +} + func (r *Root) Environment() *env_core.Environment { return r.env } diff --git a/environment/env_v0_4/root.go b/environment/env_v0_4/root.go index f085f3f6..329c7fd1 100644 --- a/environment/env_v0_4/root.go +++ b/environment/env_v0_4/root.go @@ -225,12 +225,17 @@ func loadConfig() (*env_core.Config, error) { out := &env_core.Config{ ApiEndpoint: cfg.ApiEndpoint, DefaultFrontend: cfg.DefaultFrontend, + Headless: cfg.Headless, } return out, nil } func saveConfig(cfg *env_core.Config) error { - in := &config{ApiEndpoint: cfg.ApiEndpoint, DefaultFrontend: cfg.DefaultFrontend} + in := &config{ + ApiEndpoint: cfg.ApiEndpoint, + DefaultFrontend: cfg.DefaultFrontend, + Headless: cfg.Headless, + } data, err := json.MarshalIndent(in, "", " ") if err != nil { return errors.Wrap(err, "error marshaling config") @@ -326,6 +331,7 @@ type metadata struct { type config struct { ApiEndpoint string `json:"api_endpoint"` DefaultFrontend string `json:"default_frontend"` + Headless bool `json:"headless"` } type environment struct {