go.temporal.io/server@v1.23.0/common/config/loader.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package config 26 27 import ( 28 "fmt" 29 stdlog "log" 30 "os" 31 32 "gopkg.in/validator.v2" 33 "gopkg.in/yaml.v3" 34 ) 35 36 const ( 37 // EnvKeyRoot the environment variable key for runtime root dir 38 EnvKeyRoot = "TEMPORAL_ROOT" 39 // EnvKeyConfigDir the environment variable key for config dir 40 EnvKeyConfigDir = "TEMPORAL_CONFIG_DIR" 41 // EnvKeyEnvironment is the environment variable key for environment 42 EnvKeyEnvironment = "TEMPORAL_ENVIRONMENT" 43 // EnvKeyAvailabilityZone is the environment variable key for AZ 44 EnvKeyAvailabilityZone = "TEMPORAL_AVAILABILITY_ZONE" 45 // EnvKeyAvailabilityZoneTypo is the old environment variable key for AZ that 46 // included a typo. This is deprecated and only here to support backwards 47 // compatibility. 48 EnvKeyAvailabilityZoneTypo = "TEMPORAL_AVAILABILTY_ZONE" 49 // EnvKeyAllowNoAuth is the environment variable key for setting no authorizer 50 EnvKeyAllowNoAuth = "TEMPORAL_ALLOW_NO_AUTH" 51 ) 52 53 const ( 54 baseFile = "base.yaml" 55 envDevelopment = "development" 56 defaultConfigDir = "config" 57 ) 58 59 // Load loads the configuration from a set of 60 // yaml config files found in the config directory 61 // 62 // The loader first fetches the set of files matching 63 // a pre-determined naming convention, then sorts 64 // them by hierarchy order and after that, simply 65 // loads the files one after another with the 66 // key/values in the later files overriding the key/values 67 // in the earlier files 68 // 69 // The hierarchy is as follows from lowest to highest 70 // 71 // base.yaml 72 // env.yaml -- environment is one of the input params ex-development 73 // env_az.yaml -- zone is another input param 74 func Load(env string, configDir string, zone string, config interface{}) error { 75 if len(env) == 0 { 76 env = envDevelopment 77 } 78 if len(configDir) == 0 { 79 configDir = defaultConfigDir 80 } 81 82 // TODO: remove log dependency. 83 stdlog.Printf("Loading config; env=%v,zone=%v,configDir=%v\n", env, zone, configDir) 84 85 files, err := getConfigFiles(env, configDir, zone) 86 if err != nil { 87 return err 88 } 89 90 // TODO: remove log dependency. 91 stdlog.Printf("Loading config files=%v\n", files) 92 93 for _, f := range files { 94 // This is tagged nosec because the file names being read are for config files that are not user supplied 95 // #nosec 96 data, err := os.ReadFile(f) 97 if err != nil { 98 return err 99 } 100 err = yaml.Unmarshal(data, config) 101 if err != nil { 102 return err 103 } 104 } 105 106 return validator.Validate(config) 107 } 108 109 // Helper function for loading configuration 110 func LoadConfig(env string, configDir string, zone string) (*Config, error) { 111 config := Config{} 112 err := Load(env, configDir, zone, &config) 113 if err != nil { 114 return nil, fmt.Errorf("config file corrupted: %w", err) 115 } 116 return &config, nil 117 } 118 119 // getConfigFiles returns the list of config files to 120 // process in the hierarchy order 121 func getConfigFiles(env string, configDir string, zone string) ([]string, error) { 122 123 candidates := []string{ 124 path(configDir, baseFile), 125 path(configDir, file(env, "yaml")), 126 } 127 128 if len(zone) > 0 { 129 f := file(concat(env, zone), "yaml") 130 candidates = append(candidates, path(configDir, f)) 131 } 132 133 var result []string 134 135 for _, c := range candidates { 136 if _, err := os.Stat(c); err != nil { 137 continue 138 } 139 result = append(result, c) 140 } 141 142 if len(result) == 0 { 143 return nil, fmt.Errorf("no config files found within %v", configDir) 144 } 145 146 return result, nil 147 } 148 149 func concat(a, b string) string { 150 return a + "_" + b 151 } 152 153 func file(name string, suffix string) string { 154 return name + "." + suffix 155 } 156 157 func path(dir string, file string) string { 158 return dir + "/" + file 159 }