github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/config/specification.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/hellofresh/logging-go"
     8  	"github.com/kelseyhightower/envconfig"
     9  	"github.com/mitchellh/go-homedir"
    10  	"github.com/spf13/viper"
    11  )
    12  
    13  // Specification for basic configurations
    14  type Specification struct {
    15  	Port                 int           `envconfig:"PORT"`
    16  	GraceTimeOut         int64         `envconfig:"GRACE_TIMEOUT"`
    17  	MaxIdleConnsPerHost  int           `envconfig:"MAX_IDLE_CONNS_PER_HOST"`
    18  	BackendFlushInterval time.Duration `envconfig:"BACKEND_FLUSH_INTERVAL"`
    19  	IdleConnTimeout      time.Duration `envconfig:"IDLE_CONN_TIMEOUT"`
    20  	ConnPurgeInterval    time.Duration `envconfig:"CONN_PURGE_INTERVAL"`
    21  	RequestID            bool          `envconfig:"REQUEST_ID_ENABLED"`
    22  	Log                  logging.LogConfig
    23  	Web                  Web
    24  	Database             Database
    25  	Stats                Stats
    26  	Tracing              Tracing
    27  	TLS                  TLS
    28  	Cluster              Cluster
    29  	RespondingTimeouts   RespondingTimeouts
    30  }
    31  
    32  // Cluster represents the cluster configuration
    33  type Cluster struct {
    34  	UpdateFrequency time.Duration `envconfig:"BACKEND_UPDATE_FREQUENCY"`
    35  }
    36  
    37  // RespondingTimeouts contains timeout configurations for incoming requests to the Janus instance.
    38  type RespondingTimeouts struct {
    39  	ReadTimeout  time.Duration `envconfig:"RESPONDING_TIMEOUTS_READ_TIMEOUT"`
    40  	WriteTimeout time.Duration `envconfig:"RESPONDING_TIMEOUTS_WRITE_TIMEOUT"`
    41  	IdleTimeout  time.Duration `envconfig:"RESPONDING_TIMEOUTS_IDLE_TIMEOUT"`
    42  }
    43  
    44  // Web represents the API configurations
    45  type Web struct {
    46  	Port        int `envconfig:"API_PORT"`
    47  	Credentials Credentials
    48  	TLS         TLS
    49  }
    50  
    51  // TLS represents the TLS configurations
    52  type TLS struct {
    53  	Port     int    `envconfig:"PORT"`
    54  	CertFile string `envconfig:"CERT_PATH"`
    55  	KeyFile  string `envconfig:"KEY_PATH"`
    56  	Redirect bool   `envconfig:"REDIRECT"`
    57  }
    58  
    59  // IsHTTPS checks if you have https enabled
    60  func (s *TLS) IsHTTPS() bool {
    61  	return s.CertFile != "" && s.KeyFile != ""
    62  }
    63  
    64  // Database holds the configuration for a database
    65  type Database struct {
    66  	DSN string `envconfig:"DATABASE_DSN"`
    67  }
    68  
    69  // Stats holds the configuration for stats
    70  type Stats struct {
    71  	DSN                   string   `envconfig:"STATS_DSN"`
    72  	IDs                   string   `envconfig:"STATS_IDS"`
    73  	AutoDiscoverThreshold uint     `envconfig:"STATS_AUTO_DISCOVER_THRESHOLD"`
    74  	AutoDiscoverWhiteList []string `envconfig:"STATS_AUTO_DISCOVER_WHITE_LIST"`
    75  	ErrorsSection         string   `envconfig:"STATS_ERRORS_SECTION"`
    76  	Exporter              string   `envconfig:"STATS_EXPORTER"`
    77  }
    78  
    79  // Credentials represents the credentials that are going to be
    80  // used by admin JWT configuration
    81  type Credentials struct {
    82  	// Algorithm defines admin JWT signing algorithm.
    83  	// Currently the following algorithms are supported: HS256, HS384, HS512.
    84  	Algorithm      string        `envconfig:"ALGORITHM"`
    85  	Secret         string        `envconfig:"SECRET"`
    86  	JanusAdminTeam string        `envconfig:"JANUS_ADMIN_TEAM"`
    87  	Timeout        time.Duration `envconfig:"TOKEN_TIMEOUT"`
    88  	Github         Github
    89  	Basic          Basic
    90  }
    91  
    92  // Basic holds the basic users configurations
    93  type Basic struct {
    94  	Users map[string]string `envconfig:"BASIC_USERS"`
    95  }
    96  
    97  // Github holds the github configurations
    98  type Github struct {
    99  	Organizations []string          `envconfig:"GITHUB_ORGANIZATIONS"`
   100  	Teams         map[string]string `envconfig:"GITHUB_TEAMS"`
   101  }
   102  
   103  // IsConfigured checks if github is enabled
   104  func (auth *Github) IsConfigured() bool {
   105  	return len(auth.Organizations) > 0 ||
   106  		len(auth.Teams) > 0
   107  }
   108  
   109  // Tracing represents the distributed tracing configuration
   110  type Tracing struct {
   111  	Exporter         string        `envconfig:"TRACING_EXPORTER"`
   112  	ServiceName      string        `envconfig:"TRACING_SERVICE_NAME"`
   113  	SamplingStrategy string        `envconfig:"TRACING_SAMPLING_STRATEGY"`
   114  	SamplingParam    float64       `envconfig:"TRACING_SAMPLING_PARAM"`
   115  	DebugTraceKey    string        `envconfig:"TRACING_DEBUG_TRACE_KEY"`
   116  	IsPublicEndpoint bool          `envconfig:"TRACING_IS_PUBLIC_ENDPOINT"`
   117  	JaegerTracing    JaegerTracing `mapstructure:"jaeger"`
   118  }
   119  
   120  // JaegerTracing holds the Jaeger tracing configuration
   121  type JaegerTracing struct {
   122  	SamplingServerURL  string `envconfig:"TRACING_JAEGER_SAMPLING_SERVER_URL"`
   123  	SamplingServerHost string `envconfig:"JAEGER_AGENT_HOST"`
   124  	SamplingServerPort string `envconfig:"JAEGER_AGENT_PORT"`
   125  }
   126  
   127  func init() {
   128  	serviceName := "janus"
   129  
   130  	viper.SetDefault("port", "8080")
   131  	viper.SetDefault("tls.port", "8433")
   132  	viper.SetDefault("tls.redirect", true)
   133  	viper.SetDefault("backendFlushInterval", "20ms")
   134  	viper.SetDefault("requestID", true)
   135  
   136  	viper.SetDefault("respondingTimeouts.IdleTimeout", 180*time.Second)
   137  
   138  	viper.SetDefault("cluster.updateFrequency", "10s")
   139  	viper.SetDefault("database.dsn", "file:///etc/janus")
   140  
   141  	viper.SetDefault("web.port", "8081")
   142  	viper.SetDefault("web.tls.port", "8444")
   143  	viper.SetDefault("web.tls.redirect", true)
   144  	viper.SetDefault("web.credentials.algorithm", "HS256")
   145  	viper.SetDefault("web.credentials.timeout", time.Hour)
   146  	viper.SetDefault("web.credentials.basic.users", map[string]string{"admin": "admin"})
   147  	viper.SetDefault("web.credentials.github.teams", make(map[string]string))
   148  
   149  	viper.SetDefault("stats.dsn", "log://")
   150  	viper.SetDefault("stats.errorsSection", "error-log")
   151  	viper.SetDefault("stats.namespace", serviceName)
   152  
   153  	viper.SetDefault("tracing.serviceName", serviceName)
   154  	viper.SetDefault("tracing.samplingStrategy", "probabilistic")
   155  	viper.SetDefault("tracing.samplingParam", 0.15)
   156  	viper.SetDefault("tracing.debugTraceKey", "")
   157  	viper.SetDefault("tracing.isPublicEndpoint", true)
   158  
   159  	logging.InitDefaults(viper.GetViper(), "log")
   160  }
   161  
   162  // Load configuration variables
   163  func Load(configFile string) (*Specification, error) {
   164  	if configFile != "" {
   165  		viper.SetConfigFile(configFile)
   166  	} else {
   167  		dir, err := homedir.Dir()
   168  		if err != nil {
   169  			return nil, err
   170  		}
   171  
   172  		viper.SetConfigName("janus")
   173  		viper.AddConfigPath(".")
   174  		viper.AddConfigPath(dir)
   175  		viper.AddConfigPath("/etc/janus")
   176  	}
   177  
   178  	if err := viper.ReadInConfig(); err != nil {
   179  		return nil, fmt.Errorf("config file not found: %w", err)
   180  	}
   181  
   182  	var config Specification
   183  	if err := viper.Unmarshal(&config); err != nil {
   184  		return nil, err
   185  	}
   186  
   187  	return &config, nil
   188  }
   189  
   190  // LoadEnv loads configuration from environment variables
   191  func LoadEnv() (*Specification, error) {
   192  	var config Specification
   193  
   194  	// ensure the defaults are loaded
   195  	if err := viper.Unmarshal(&config); err != nil {
   196  		return nil, err
   197  	}
   198  
   199  	err := envconfig.Process("", &config)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	return &config, nil
   205  }