spf13 / viper

Go configuration with fangs
MIT License
26.47k stars 2.01k forks source link

viper.ReadinConfig() errors with references to real filepath instead of only referencing in memory fs paths #1667

Open discentem opened 9 months ago

discentem commented 9 months ago

Preflight Checklist

Viper Version

1.17.0

Go Version

1.21

Config Source

Files

Format

JSON

Repl.it link

https://replit.com/@kurtzbrandon/viperreadinconfigbug

Code reproducing the issue

package main

import (
    "errors"
    "fmt"
    "log"
    "path/filepath"

    "github.com/spf13/afero"
    "github.com/spf13/viper"
)

type Config struct {
    Version int `json:"version"`
}

func Load(fs afero.Fs, cfgDest ...*Config) error {
    // Defaults set here will be used if they do not exist in the config file
    viper.SetFs(fs)
    // Set up the config file details
    viper.SetConfigName("config")
    viper.SetConfigType("json")
    viper.AddConfigPath(".")
    viper.AddConfigPath(".viper")

    // Retrieve from EnvVars if they exist...
    viper.AutomaticEnv()

    // Read from the config file path
    err := viper.ReadInConfig()
    if err != nil {
        return fmt.Errorf("error with viper.ReadInConfig(): %w", err)
    }

    if cfgDest == nil {
        return errors.New("cfg cannot be nil")
    }

    return viper.Unmarshal(cfgDest[0])
}

func load(createFn func(fs afero.Fs, name string) (afero.File, error)) error {
    fs := afero.NewMemMapFs()

    err := fs.Mkdir(".viper", 0o777)
    if err != nil {
        return err
    }

    file, err := createFn(fs, ".viper/config")
    if err != nil {
        return err
    }

    cfg := Config{}

    _, err = file.Write([]byte(`{
        "version": 1
       }`),
    )
    if err != nil {
        return err
    }
    file.Close()

    err = Load(fs, &cfg)
    if err != nil {
        return err
    }
    return nil
}

func main() {
    createWithAbsolute := func(fs afero.Fs, name string) (afero.File, error) {
        s, err := filepath.Abs(name)
        if err != nil {
            return nil, fmt.Errorf("createWithAbsolute failed: %w", err)
        }
        return fs.Create(s)
    }

    if err := load(createWithAbsolute); err != nil {
        log.Fatal(err)
    }
    fmt.Println("load with createWithAbsolute succeeded")
    createWithoutAbsolute := func(fs afero.Fs, name string) (afero.File, error) {
        return fs.Create(name)
    }

    if err := load(createWithoutAbsolute); err != nil {
        log.Fatal(err)
    }
    /*
        load with createWithAbsolute succeeded
        2023/10/22 21:54:33 error with viper.ReadInConfig(): Config File "config" Not Found in "[/Users/bk/project /Users/home/project/.viper]"
        exit status 1
    */
    fmt.Println("load with createWithoutAbsolute succeeded")
}

Expected Behavior

The second call to load() with createWithoutAbsolute is expected to fail but it should not mention my real OsFs in the error message. Instead I expect the error message to only reference the in memory filesystem. It seems viper.ReadInConfig() has some fallback behavior maybe? If such behavior exists as a feature, fallback should be off by default.

Actual Behavior

2023/10/22 21:54:33 error with viper.ReadInConfig(): Config File "config" Not Found in "[/Users/bk/project /Users/home/project/.viper]"
exit status 1

The error message from viper.ReadInConfig() is referencing filepaths on my real OsFs even though I told viper to only read from in-mem

Steps To Reproduce

No response

Additional Information

No response

github-actions[bot] commented 9 months ago

👋 Thanks for reporting!

A maintainer will take a look at your issue shortly. 👀

In the meantime: We are working on Viper v2 and we would love to hear your thoughts about what you like or don't like about Viper, so we can improve or fix those issues.

⏰ If you have a couple minutes, please take some time and share your thoughts: https://forms.gle/R6faU74qPRPAzchZ9

📣 If you've already given us your feedback, you can still help by spreading the news, either by sharing the above link or telling people about this on Twitter:

https://twitter.com/sagikazarmark/status/1306904078967074816

Thank you! ❤️