Viper AddConfigPath only finding file in current folder "." - go

Have code that looks like
viper.AddConfigPath(".")
viper.AddConfigPath("$HOME/.config/myprogram")
viper.AddConfigPath("$HOME/configs")
viper.SetConfigFile("myprogram.yaml")
If I place myprogram.yaml in the current folder it works. However if I try putting it on either
$HOME/.config/myprogram$HOME/configs
The yaml file is not found. Any ideas or suggestions?

From the viper docs:
SetConfigFile explicitly defines the path, name and extension of the
config file. Viper will use this and not check any of the config
paths.
So if you use SetConfigFile the paths will be ignored. Try (as per the example):
viper.SetConfigName("myprogram")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AddConfigPath("$HOME/configs")
viper.AddConfigPath("$HOME/.config/myprogram")

Related

How to resolve user environment variables in filepath

Golang on windows. Trying to use
os.Open("%userprofile%\\myfile.txt")
Getting file path not found and golang is not resolving %userprofile% to my C:\users\myusername folder.
To get a file handle, and make your program a little portable too, try
userprofile := os.Getenv("USERPROFILE")
f, err := os.Open(path.Join(userprofile, "myfile.txt"))
The os.Getenv() will read the environment variable and path.Join() will take care of properly constructing the path (so no need to do \\).
Instead of os.Getenv() you might also want to look at os.LookupEnv(). This will tell you if the environment variable you're looking for is empty or simply not existing. A good example of how you can use that to set default values can be found in this answer on SO.
userprofile := os.Getenv("USERPROFILE")
os.Open(userprofile+"\\myfile.txt")
Just written a package to do this. Feedback welcome
https://gitlab.com/stu-b-doo/windowspathenv/
fmt.Println(windowspathenv.Resolve("%USERPROFILE%/Documents"))
// C:\Users\YourName\Documents
Have a look at http://www.golangprograms.com/how-to-set-get-and-list-environment-variables.html
You can read the 'userprofile' environment value and and build the path before passing it to os.Open

Config file type usage

Usually I saw config file in many examples out there are in .env or .json file.
What if I decide to use .go file instead , is it uncommon, how it should be done?
I was thinking since .env file is static, if I want to put config like this
var currentDate = time.Now()
var currentDateFormat = currentDate.Format("2006-01-02")
var logPath = dir + "/log/" + currentDateFormat + ".log"
It can't be done in .env file so should I just keep the above config within function somewhere and stick with .env file?
What if I decide to use .go file instead
Then it is no longer a config file (static content), but a source file, which needs to be compiled and part of your exe (runtime content).
It then could be part of an init() function for instance.
Or part of a config package source, in charge of loading your config as well as initializing the variables in your question.

File path in golang

I have a project with next structure:
|_main.go
|_config
|_config.go
|_config_test.go
|_config.json
I'm having next code line in config.go:
file, _ := os.Open("config/config.json")
When I'm executing method contained this code line from main.go all is working. But when I'm trying to execute this method from config_test.go it produces error:
open config/config.json: no such file or directory
As I understood it is a working directory issue because I'm launching same code with relative path from different directories. How can I fix this problem without using full path in config.go?
Relative paths are always resolved basis your current directory. Hence it's better to avoid relative paths.
Use command line flags or a configuration management tool (better approach) like Viper
Also according to The Twelve-Factor App your config files should be outside your project.
Eg usage with Viper:
import "github.com/spf13/viper"
func init() {
viper.SetConfigName("config")
// Config files are stored here; multiple locations can be added
viper.AddConfigPath("$HOME/configs")
errViper := viper.ReadInConfig()
if errViper != nil {
panic(errViper)
}
// Get values from config.json
val := viper.GetString("some_key")
// Use the value
}

Spring with spring.config.location

I am trying to point at path to external configuration file like this:
--spring.config.location=file: C:/Users/some_user/workspace/repository1/payment-api/payment.yml
and it doesn't work. Any idea why?
The proper prefix is file://. On Windows you need an extra "/" in the file URL if it is absolute with a drive prefix
Try file:///C:/Users/some_user/workspace/repository1/payment-api/payment.yml instead.

Look for a configuration file with Ruby

I written a Ruby tool, named foobar, having a default configuration into a
file (called .foobar).
When the tool is executed without any params, the configuration file's params
can be used: ~/.foobar.
But, if the current tool's path is ~/projects/foobar and if
~/projects/foobar/.foobar exists, then this file should be used instead of
~/.foobar.
That's why the way to look for this configuration file should start from the
current folder until the current user folder.
Is there a simple way to look for this file?
cfg_file = File.open(".foobar", "r") rescue File.open("~/.foobar", "r")
Although to be honest, I almost always do two things: provide an option for a config file path, and allow overriding of default config values. The problem with the latter is that unless you know config files are ordered/have precedence, it can be confusing.
I would do this:
if File.exists(".foobar")
# open .foobar
else
# open ~/..
end

Resources