@@ -16,6 +16,7 @@ import (
1616 "github.com/knadh/koanf/providers/basicflag"
1717 "github.com/knadh/koanf/providers/env"
1818 "github.com/kubernetes-sigs/headlamp/backend/pkg/logger"
19+ "github.com/kubernetes-sigs/headlamp/backend/pkg/spa"
1920)
2021
2122const (
@@ -31,10 +32,14 @@ const (
3132)
3233
3334type Config struct {
34- Version bool `koanf:"version"`
35- InCluster bool `koanf:"in-cluster"`
36- DevMode bool `koanf:"dev"`
37- InsecureSsl bool `koanf:"insecure-ssl"`
35+ Version bool `koanf:"version"`
36+ InCluster bool `koanf:"in-cluster"`
37+ DevMode bool `koanf:"dev"`
38+ InsecureSsl bool `koanf:"insecure-ssl"`
39+ // NoBrowser disables automatically opening the default browser when running
40+ // a locally embedded Headlamp binary (non in-cluster with spa.UseEmbeddedFiles == true).
41+ // It has no effect in in-cluster mode or when running without embedded frontend.
42+ NoBrowser bool `koanf:"no-browser"`
3843 CacheEnabled bool `koanf:"cache-enabled"`
3944 EnableHelm bool `koanf:"enable-helm"`
4045 EnableDynamicClusters bool `koanf:"enable-dynamic-clusters"`
@@ -320,7 +325,13 @@ func Parse(args []string) (*Config, error) {
320325 setKubeConfigPath (& config )
321326 setMeDefaults (& config )
322327
323- // 8. Validate parsed config.
328+ // 8. Validate flags that depend on build-time behaviour.
329+ if err := validateOpenBrowser (& config , explicitFlags ); err != nil {
330+ logger .Log (logger .LevelError , nil , err , "validating open-browser flag" )
331+ return nil , err
332+ }
333+
334+ // 9. Validate parsed config.
324335 if err := config .Validate (); err != nil {
325336 logger .Log (logger .LevelError , nil , err , "validating config" )
326337 return nil , err
@@ -369,6 +380,24 @@ func DefaultHeadlampKubeConfigFile() (string, error) {
369380 return filepath .Join (kubeConfigDir , "config" ), nil
370381}
371382
383+ // validateOpenBrowser ensures the open-browser option is only used when the
384+ // binary was built with embedded static files.
385+ func validateOpenBrowser (config * Config , explicitFlags map [string ]bool ) error {
386+ // no-browser is only meaningful when running locally (non in-cluster) with
387+ // an embedded frontend. Validate explicit usage accordingly.
388+ if explicitFlags ["no-browser" ] {
389+ if config .InCluster {
390+ return errors .New ("no-browser cannot be used in in-cluster mode" )
391+ }
392+
393+ if ! spa .UseEmbeddedFiles {
394+ return errors .New ("no-browser cannot be used when running without embedded frontend" )
395+ }
396+ }
397+
398+ return nil
399+ }
400+
372401func flagset () * flag.FlagSet {
373402 f := flag .NewFlagSet ("config" , flag .ContinueOnError )
374403
@@ -385,6 +414,7 @@ func addGeneralFlags(f *flag.FlagSet) {
385414 f .Bool ("in-cluster" , false , "Set when running from a k8s cluster" )
386415 f .Bool ("dev" , false , "Allow connections from other origins" )
387416 f .Bool ("cache-enabled" , false , "K8s cache in backend" )
417+ f .Bool ("no-browser" , false , "Disable automatically opening the browser when using embedded frontend" )
388418 f .Bool ("insecure-ssl" , false , "Accept/Ignore all server SSL certificates" )
389419 f .Bool ("enable-dynamic-clusters" , false , "Enable dynamic clusters, which stores stateless clusters in the frontend." )
390420 // Note: When running in-cluster and if not explicitly set, this flag defaults to false.
0 commit comments