package config import ( "os" "strconv" "strings" "time" log "github.com/sirupsen/logrus" ) var ( envPrefix = "RUNNER__" ) // loadEnvVars loads configuration settings from environment variables // prefixed with "RUNNER__" and updates the provided Config struct accordingly. func loadEnvVars(config *Config) { // There probably is a better way to do this, but I'm not sure how to do it. // This implementation causes env-vars to override config file settings, // without writing to the config file. // Log loadEnvStr(config, envPrefix+"LOG__LEVEL", &config.Log.Level) loadEnvStr(config, envPrefix+"LOG__JOB_LEVEL", &config.Log.JobLevel) // Runner loadEnvStr(config, envPrefix+"RUNNER__FILE", &config.Runner.File) loadEnvInt(config, envPrefix+"RUNNER__CAPACITY", &config.Runner.Capacity) loadEnvTable(config, envPrefix+"RUNNER__ENVS", &config.Runner.Envs) loadEnvStr(config, envPrefix+"RUNNER__ENV_FILE", &config.Runner.EnvFile) loadEnvDuration(config, envPrefix+"RUNNER__SHUTDOWN_TIMEOUT", &config.Runner.ShutdownTimeout) loadEnvBool(config, envPrefix+"RUNNER__INSECURE", &config.Runner.Insecure) loadEnvDuration(config, envPrefix+"RUNNER__FETCH_TIMEOUT", &config.Runner.FetchTimeout) loadEnvDuration(config, envPrefix+"RUNNER__FETCH_INTERVAL", &config.Runner.FetchInterval) loadEnvDuration(config, envPrefix+"RUNNER__REPORT_INTERVAL", &config.Runner.ReportInterval) loadEnvList(config, envPrefix+"RUNNER__LABELS", &config.Runner.Labels) // Cache loadEnvBool(config, envPrefix+"CACHE__ENABLED", config.Cache.Enabled) loadEnvStr(config, envPrefix+"CACHE__DIR", &config.Cache.Dir) loadEnvStr(config, envPrefix+"CACHE__HOST", &config.Cache.Host) loadEnvUInt16(config, envPrefix+"CACHE__PORT", &config.Cache.Port) loadEnvStr(config, envPrefix+"CACHE__EXTERNAL_SERVER", &config.Cache.ExternalServer) // Container loadEnvStr(config, envPrefix+"CONTAINER__NETWORK", &config.Container.Network) loadEnvStr(config, envPrefix+"CONTAINER__NETWORK_MODE", &config.Container.NetworkMode) loadEnvBool(config, envPrefix+"CONTAINER__ENABLE_IPV6", &config.Container.EnableIPv6) loadEnvBool(config, envPrefix+"CONTAINER__PRIVILEGED", &config.Container.Privileged) loadEnvStr(config, envPrefix+"CONTAINER__OPTIONS", &config.Container.Options) loadEnvStr(config, envPrefix+"CONTAINER__WORKDIR_PARENT", &config.Container.WorkdirParent) loadEnvList(config, envPrefix+"CONTAINER__VALID_VOLUMES", &config.Container.ValidVolumes) loadEnvStr(config, envPrefix+"CONTAINER__DOCKER_HOST", &config.Container.DockerHost) loadEnvBool(config, envPrefix+"CONTAINER__FORCE_PULL", &config.Container.ForcePull) // Host loadEnvStr(config, envPrefix+"HOST__WORKDIR_PARENT", &config.Host.WorkdirParent) } // loadEnvStr loads an environment variable into the provided string pointer if it exists. func loadEnvStr(config *Config, key string, dest *string) { // Example: RUNNER__LOG__LEVEL = "info" if v := os.Getenv(key); v != "" { *dest = v } } // loadEnvInt loads an environment variable into the provided int pointer if it exists. func loadEnvInt(config *Config, key string, dest *int) { // Example: RUNNER__RUNNER__CAPACITY = "1" if v := os.Getenv(key); v != "" { if intValue, err := strconv.Atoi(v); err == nil { *dest = intValue } } } // loadEnvUInt16 loads an environment variable into the provided uint16 pointer if it exists. func loadEnvUInt16(config *Config, key string, dest *uint16) { // Example: RUNNER__CACHE__PORT = "8080" if v := os.Getenv(key); v != "" { if uint16Value, err := strconv.ParseUint(v, 10, 16); err == nil { *dest = uint16(uint16Value) } } } // loadEnvDuration loads an environment variable into the provided time.Duration pointer if it exists. func loadEnvDuration(config *Config, key string, dest *time.Duration) { // Example: RUNNER__RUNNER__SHUTDOWN_TIMEOUT = "3h" if v := os.Getenv(key); v != "" { if durationValue, err := time.ParseDuration(v); err == nil { *dest = durationValue } } } // loadEnvBool loads an environment variable into the provided bool pointer if it exists. func loadEnvBool(config *Config, key string, dest *bool) { // Example: RUNNER__RUNNER__INSECURE = "false" if v := os.Getenv(key); v != "" { if boolValue, err := strconv.ParseBool(v); err == nil { *dest = boolValue } } } // loadEnvTable loads an environment variable into the provided map[string]string pointer if it exists. func loadEnvTable(config *Config, key string, dest *map[string]string) { // This is a placeholder function. // This function is not yet implemented. // This function is meant to be replaced by those more competent than me. log.Warn("Loading Tables from env is not yet implemented: ", key) } // loadEnvList loads an environment variable into the provided []string pointer if it exists. func loadEnvList(config *Config, key string, dest *[]string) { // Example: RUNNER__RUNNER__LABELS = "label1, label2, label3" if v := os.Getenv(key); v != "" { *dest = splitAndTrim(v) } } func splitAndTrim(s string) []string { lines := strings.Split(s, "\n") var result []string for _, line := range lines { items := strings.Split(line, ",") for _, item := range items { trimmed := strings.TrimSpace(item) if trimmed != "" { result = append(result, trimmed) } } } return result }