changeset 262 | 8d3354485fc3 |
parent 260 | 445e01aede7e |
child 265 | 05c40b36d3b2 |
261:270cc4dda0c5 | 262:8d3354485fc3 |
---|---|
130 type DecoderConfigOption func(*mapstructure.DecoderConfig) |
130 type DecoderConfigOption func(*mapstructure.DecoderConfig) |
131 |
131 |
132 // DecodeHook returns a DecoderConfigOption which overrides the default |
132 // DecodeHook returns a DecoderConfigOption which overrides the default |
133 // DecoderConfig.DecodeHook value, the default is: |
133 // DecoderConfig.DecodeHook value, the default is: |
134 // |
134 // |
135 // mapstructure.ComposeDecodeHookFunc( |
135 // mapstructure.ComposeDecodeHookFunc( |
136 // mapstructure.StringToTimeDurationHookFunc(), |
136 // mapstructure.StringToTimeDurationHookFunc(), |
137 // mapstructure.StringToSliceHookFunc(","), |
137 // mapstructure.StringToSliceHookFunc(","), |
138 // ) |
138 // ) |
139 func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption { |
139 func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption { |
140 return func(c *mapstructure.DecoderConfig) { |
140 return func(c *mapstructure.DecoderConfig) { |
141 c.DecodeHook = hook |
141 c.DecodeHook = hook |
142 } |
142 } |
143 } |
143 } |
154 // 5. key/value store |
154 // 5. key/value store |
155 // 6. defaults |
155 // 6. defaults |
156 // |
156 // |
157 // For example, if values from the following sources were loaded: |
157 // For example, if values from the following sources were loaded: |
158 // |
158 // |
159 // Defaults : { |
159 // Defaults : { |
160 // "secret": "", |
160 // "secret": "", |
161 // "user": "default", |
161 // "user": "default", |
162 // "endpoint": "https://localhost" |
162 // "endpoint": "https://localhost" |
163 // } |
163 // } |
164 // Config : { |
164 // Config : { |
165 // "user": "root" |
165 // "user": "root" |
166 // "secret": "defaultsecret" |
166 // "secret": "defaultsecret" |
167 // } |
167 // } |
168 // Env : { |
168 // Env : { |
169 // "secret": "somesecretkey" |
169 // "secret": "somesecretkey" |
170 // } |
170 // } |
171 // |
171 // |
172 // The resulting config will have the following values: |
172 // The resulting config will have the following values: |
173 // |
173 // |
174 // { |
174 // { |
175 // "secret": "somesecretkey", |
175 // "secret": "somesecretkey", |
298 // In the public interface for the viper package so applications |
298 // In the public interface for the viper package so applications |
299 // can use it in their testing as well. |
299 // can use it in their testing as well. |
300 func Reset() { |
300 func Reset() { |
301 v = New() |
301 v = New() |
302 SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} |
302 SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} |
303 SupportedRemoteProviders = []string{"etcd", "consul", "firestore"} |
303 SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"} |
304 } |
304 } |
305 |
305 |
306 // TODO: make this lazy initialization instead |
306 // TODO: make this lazy initialization instead |
307 func (v *Viper) resetEncoding() { |
307 func (v *Viper) resetEncoding() { |
308 encoderRegistry := encoding.NewEncoderRegistry() |
308 encoderRegistry := encoding.NewEncoderRegistry() |
417 |
417 |
418 // SupportedExts are universally supported extensions. |
418 // SupportedExts are universally supported extensions. |
419 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} |
419 var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} |
420 |
420 |
421 // SupportedRemoteProviders are universally supported remote providers. |
421 // SupportedRemoteProviders are universally supported remote providers. |
422 var SupportedRemoteProviders = []string{"etcd", "consul", "firestore"} |
422 var SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore"} |
423 |
423 |
424 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } |
424 func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } |
425 func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) { |
425 func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) { |
426 v.onConfigChange = run |
426 v.onConfigChange = run |
427 } |
427 } |
571 } |
571 } |
572 } |
572 } |
573 |
573 |
574 // AddRemoteProvider adds a remote configuration source. |
574 // AddRemoteProvider adds a remote configuration source. |
575 // Remote Providers are searched in the order they are added. |
575 // Remote Providers are searched in the order they are added. |
576 // provider is a string value: "etcd", "consul" or "firestore" are currently supported. |
576 // provider is a string value: "etcd", "etcd3", "consul" or "firestore" are currently supported. |
577 // endpoint is the url. etcd requires http://ip:port consul requires ip:port |
577 // endpoint is the url. etcd requires http://ip:port consul requires ip:port |
578 // path is the path in the k/v store to retrieve configuration |
578 // path is the path in the k/v store to retrieve configuration |
579 // To retrieve a config file called myapp.json from /configs/myapp.json |
579 // To retrieve a config file called myapp.json from /configs/myapp.json |
580 // you should set path to /configs and set config name (SetConfigName()) to |
580 // you should set path to /configs and set config name (SetConfigName()) to |
581 // "myapp" |
581 // "myapp" |
602 return nil |
602 return nil |
603 } |
603 } |
604 |
604 |
605 // AddSecureRemoteProvider adds a remote configuration source. |
605 // AddSecureRemoteProvider adds a remote configuration source. |
606 // Secure Remote Providers are searched in the order they are added. |
606 // Secure Remote Providers are searched in the order they are added. |
607 // provider is a string value: "etcd", "consul" or "firestore" are currently supported. |
607 // provider is a string value: "etcd", "etcd3", "consul" or "firestore" are currently supported. |
608 // endpoint is the url. etcd requires http://ip:port consul requires ip:port |
608 // endpoint is the url. etcd requires http://ip:port consul requires ip:port |
609 // secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg |
609 // secretkeyring is the filepath to your openpgp secret keyring. e.g. /etc/secrets/myring.gpg |
610 // path is the path in the k/v store to retrieve configuration |
610 // path is the path in the k/v store to retrieve configuration |
611 // To retrieve a config file called myapp.json from /configs/myapp.json |
611 // To retrieve a config file called myapp.json from /configs/myapp.json |
612 // you should set path to /configs and set config name (SetConfigName()) to |
612 // you should set path to /configs and set config name (SetConfigName()) to |
783 } |
783 } |
784 |
784 |
785 // isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere |
785 // isPathShadowedInDeepMap makes sure the given path is not shadowed somewhere |
786 // on its path in the map. |
786 // on its path in the map. |
787 // e.g., if "foo.bar" has a value in the given map, it “shadows” |
787 // e.g., if "foo.bar" has a value in the given map, it “shadows” |
788 // "foo.bar.baz" in a lower-priority map |
788 // |
789 // "foo.bar.baz" in a lower-priority map |
|
789 func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string { |
790 func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]interface{}) string { |
790 var parentVal interface{} |
791 var parentVal interface{} |
791 for i := 1; i < len(path); i++ { |
792 for i := 1; i < len(path); i++ { |
792 parentVal = v.searchMap(m, path[0:i]) |
793 parentVal = v.searchMap(m, path[0:i]) |
793 if parentVal == nil { |
794 if parentVal == nil { |
808 } |
809 } |
809 |
810 |
810 // isPathShadowedInFlatMap makes sure the given path is not shadowed somewhere |
811 // isPathShadowedInFlatMap makes sure the given path is not shadowed somewhere |
811 // in a sub-path of the map. |
812 // in a sub-path of the map. |
812 // e.g., if "foo.bar" has a value in the given map, it “shadows” |
813 // e.g., if "foo.bar" has a value in the given map, it “shadows” |
813 // "foo.bar.baz" in a lower-priority map |
814 // |
815 // "foo.bar.baz" in a lower-priority map |
|
814 func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string { |
816 func (v *Viper) isPathShadowedInFlatMap(path []string, mi interface{}) string { |
815 // unify input map |
817 // unify input map |
816 var m map[string]interface{} |
818 var m map[string]interface{} |
817 switch mi.(type) { |
819 switch mi.(type) { |
818 case map[string]string, map[string]FlagValue: |
820 case map[string]string, map[string]FlagValue: |
833 } |
835 } |
834 |
836 |
835 // isPathShadowedInAutoEnv makes sure the given path is not shadowed somewhere |
837 // isPathShadowedInAutoEnv makes sure the given path is not shadowed somewhere |
836 // in the environment, when automatic env is on. |
838 // in the environment, when automatic env is on. |
837 // e.g., if "foo.bar" has a value in the environment, it “shadows” |
839 // e.g., if "foo.bar" has a value in the environment, it “shadows” |
838 // "foo.bar.baz" in a lower-priority map |
840 // |
841 // "foo.bar.baz" in a lower-priority map |
|
839 func (v *Viper) isPathShadowedInAutoEnv(path []string) string { |
842 func (v *Viper) isPathShadowedInAutoEnv(path []string) string { |
840 var parentKey string |
843 var parentKey string |
841 for i := 1; i < len(path); i++ { |
844 for i := 1; i < len(path); i++ { |
842 parentKey = strings.Join(path[0:i], v.keyDelim) |
845 parentKey = strings.Join(path[0:i], v.keyDelim) |
843 if _, ok := v.getEnv(v.mergeWithEnvPrefix(parentKey)); ok { |
846 if _, ok := v.getEnv(v.mergeWithEnvPrefix(parentKey)); ok { |
854 // For example, if a key has a default value of []string{} and the same key |
857 // For example, if a key has a default value of []string{} and the same key |
855 // is set via an environment variable to "a b c", a call to the Get function |
858 // is set via an environment variable to "a b c", a call to the Get function |
856 // would return a string slice for the key if the key's type is inferred by |
859 // would return a string slice for the key if the key's type is inferred by |
857 // the default value and the Get function would return: |
860 // the default value and the Get function would return: |
858 // |
861 // |
859 // []string {"a", "b", "c"} |
862 // []string {"a", "b", "c"} |
860 // |
863 // |
861 // Otherwise the Get function would return: |
864 // Otherwise the Get function would return: |
862 // |
865 // |
863 // "a b c" |
866 // "a b c" |
864 func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) } |
867 func SetTypeByDefaultValue(enable bool) { v.SetTypeByDefaultValue(enable) } |
865 |
868 |
866 func (v *Viper) SetTypeByDefaultValue(enable bool) { |
869 func (v *Viper) SetTypeByDefaultValue(enable bool) { |
867 v.typeByDefValue = enable |
870 v.typeByDefValue = enable |
868 } |
871 } |
986 |
989 |
987 func (v *Viper) GetUint(key string) uint { |
990 func (v *Viper) GetUint(key string) uint { |
988 return cast.ToUint(v.Get(key)) |
991 return cast.ToUint(v.Get(key)) |
989 } |
992 } |
990 |
993 |
994 // GetUint16 returns the value associated with the key as an unsigned integer. |
|
995 func GetUint16(key string) uint16 { return v.GetUint16(key) } |
|
996 |
|
997 func (v *Viper) GetUint16(key string) uint16 { |
|
998 return cast.ToUint16(v.Get(key)) |
|
999 } |
|
1000 |
|
991 // GetUint32 returns the value associated with the key as an unsigned integer. |
1001 // GetUint32 returns the value associated with the key as an unsigned integer. |
992 func GetUint32(key string) uint32 { return v.GetUint32(key) } |
1002 func GetUint32(key string) uint32 { return v.GetUint32(key) } |
993 |
1003 |
994 func (v *Viper) GetUint32(key string) uint32 { |
1004 func (v *Viper) GetUint32(key string) uint32 { |
995 return cast.ToUint32(v.Get(key)) |
1005 return cast.ToUint32(v.Get(key)) |
1135 } |
1145 } |
1136 |
1146 |
1137 // BindPFlag binds a specific key to a pflag (as used by cobra). |
1147 // BindPFlag binds a specific key to a pflag (as used by cobra). |
1138 // Example (where serverCmd is a Cobra instance): |
1148 // Example (where serverCmd is a Cobra instance): |
1139 // |
1149 // |
1140 // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") |
1150 // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") |
1141 // Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) |
1151 // Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) |
1142 // |
|
1143 func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) } |
1152 func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) } |
1144 |
1153 |
1145 func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error { |
1154 func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error { |
1146 if flag == nil { |
1155 if flag == nil { |
1147 return fmt.Errorf("flag for %q is nil", key) |
1156 return fmt.Errorf("flag for %q is nil", key) |
1868 func (v *Viper) getKeyValueConfig() error { |
1877 func (v *Viper) getKeyValueConfig() error { |
1869 if RemoteConfig == nil { |
1878 if RemoteConfig == nil { |
1870 return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") |
1879 return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") |
1871 } |
1880 } |
1872 |
1881 |
1882 if len(v.remoteProviders) == 0 { |
|
1883 return RemoteConfigError("No Remote Providers") |
|
1884 } |
|
1885 |
|
1873 for _, rp := range v.remoteProviders { |
1886 for _, rp := range v.remoteProviders { |
1874 val, err := v.getRemoteConfig(rp) |
1887 val, err := v.getRemoteConfig(rp) |
1875 if err != nil { |
1888 if err != nil { |
1876 v.logger.Error(fmt.Errorf("get remote config: %w", err).Error()) |
1889 v.logger.Error(fmt.Errorf("get remote config: %w", err).Error()) |
1877 |
1890 |
1894 return v.kvstore, err |
1907 return v.kvstore, err |
1895 } |
1908 } |
1896 |
1909 |
1897 // Retrieve the first found remote configuration. |
1910 // Retrieve the first found remote configuration. |
1898 func (v *Viper) watchKeyValueConfigOnChannel() error { |
1911 func (v *Viper) watchKeyValueConfigOnChannel() error { |
1912 if len(v.remoteProviders) == 0 { |
|
1913 return RemoteConfigError("No Remote Providers") |
|
1914 } |
|
1915 |
|
1899 for _, rp := range v.remoteProviders { |
1916 for _, rp := range v.remoteProviders { |
1900 respc, _ := RemoteConfig.WatchChannel(rp) |
1917 respc, _ := RemoteConfig.WatchChannel(rp) |
1901 // Todo: Add quit channel |
1918 // Todo: Add quit channel |
1902 go func(rc <-chan *RemoteResponse) { |
1919 go func(rc <-chan *RemoteResponse) { |
1903 for { |
1920 for { |
1911 return RemoteConfigError("No Files Found") |
1928 return RemoteConfigError("No Files Found") |
1912 } |
1929 } |
1913 |
1930 |
1914 // Retrieve the first found remote configuration. |
1931 // Retrieve the first found remote configuration. |
1915 func (v *Viper) watchKeyValueConfig() error { |
1932 func (v *Viper) watchKeyValueConfig() error { |
1933 if len(v.remoteProviders) == 0 { |
|
1934 return RemoteConfigError("No Remote Providers") |
|
1935 } |
|
1936 |
|
1916 for _, rp := range v.remoteProviders { |
1937 for _, rp := range v.remoteProviders { |
1917 val, err := v.watchRemoteConfig(rp) |
1938 val, err := v.watchRemoteConfig(rp) |
1918 if err != nil { |
1939 if err != nil { |
1940 v.logger.Error(fmt.Errorf("watch remote config: %w", err).Error()) |
|
1941 |
|
1919 continue |
1942 continue |
1920 } |
1943 } |
1921 v.kvstore = val |
1944 v.kvstore = val |
1922 return nil |
1945 return nil |
1923 } |
1946 } |
1956 return a |
1979 return a |
1957 } |
1980 } |
1958 |
1981 |
1959 // flattenAndMergeMap recursively flattens the given map into a map[string]bool |
1982 // flattenAndMergeMap recursively flattens the given map into a map[string]bool |
1960 // of key paths (used as a set, easier to manipulate than a []string): |
1983 // of key paths (used as a set, easier to manipulate than a []string): |
1961 // - each path is merged into a single key string, delimited with v.keyDelim |
1984 // - each path is merged into a single key string, delimited with v.keyDelim |
1962 // - if a path is shadowed by an earlier value in the initial shadow map, |
1985 // - if a path is shadowed by an earlier value in the initial shadow map, |
1963 // it is skipped. |
1986 // it is skipped. |
1987 // |
|
1964 // The resulting set of paths is merged to the given shadow set at the same time. |
1988 // The resulting set of paths is merged to the given shadow set at the same time. |
1965 func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool { |
1989 func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool { |
1966 if shadow != nil && prefix != "" && shadow[prefix] { |
1990 if shadow != nil && prefix != "" && shadow[prefix] { |
1967 // prefix is shadowed => nothing more to flatten |
1991 // prefix is shadowed => nothing more to flatten |
1968 return shadow |
1992 return shadow |
2109 return v.configFile, nil |
2133 return v.configFile, nil |
2110 } |
2134 } |
2111 |
2135 |
2112 // Debug prints all configuration registries for debugging |
2136 // Debug prints all configuration registries for debugging |
2113 // purposes. |
2137 // purposes. |
2114 func Debug() { v.Debug() } |
2138 func Debug() { v.Debug() } |
2115 |
2139 func DebugTo(w io.Writer) { v.DebugTo(w) } |
2116 func (v *Viper) Debug() { |
2140 |
2117 fmt.Printf("Aliases:\n%#v\n", v.aliases) |
2141 func (v *Viper) Debug() { v.DebugTo(os.Stdout) } |
2118 fmt.Printf("Override:\n%#v\n", v.override) |
2142 |
2119 fmt.Printf("PFlags:\n%#v\n", v.pflags) |
2143 func (v *Viper) DebugTo(w io.Writer) { |
2120 fmt.Printf("Env:\n%#v\n", v.env) |
2144 fmt.Fprintf(w, "Aliases:\n%#v\n", v.aliases) |
2121 fmt.Printf("Key/Value Store:\n%#v\n", v.kvstore) |
2145 fmt.Fprintf(w, "Override:\n%#v\n", v.override) |
2122 fmt.Printf("Config:\n%#v\n", v.config) |
2146 fmt.Fprintf(w, "PFlags:\n%#v\n", v.pflags) |
2123 fmt.Printf("Defaults:\n%#v\n", v.defaults) |
2147 fmt.Fprintf(w, "Env:\n%#v\n", v.env) |
2124 } |
2148 fmt.Fprintf(w, "Key/Value Store:\n%#v\n", v.kvstore) |
2149 fmt.Fprintf(w, "Config:\n%#v\n", v.config) |
|
2150 fmt.Fprintf(w, "Defaults:\n%#v\n", v.defaults) |
|
2151 } |