Skip to content

basicflag Provider does not exclude default values #255

Closed
@jkroepke

Description

Describe the bug
I would like to use koanf with multiple providers in a chain. In my case

defaults (struct) -> file -> env -> flags

The flagset is enriched with default values, because then --help will display all default values for each option.

With posflag Provider, everything work fine. Since it will only include changed values. However the basicflag provider does not have an behavior (see #254)

To Reproduce

package main

import (
	"flag"
	"fmt"
	"github.com/knadh/koanf/providers/basicflag"
	"log"
	"os"
	"strings"

	"github.com/knadh/koanf/providers/env"
	"github.com/knadh/koanf/providers/structs"
	"github.com/knadh/koanf/v2"
)

// Global koanf instance. Use "." as the key path delimiter. This can be "/" or any character.
var k = koanf.New(".")

type parentStruct struct {
	Name string `koanf:"name"`
	ID   int    `koanf:"id"`
}

func init() {
	os.Setenv("MYVAR_ID", "5000")
}

func main() {
	defaults := parentStruct{
		Name: "parent1",
		ID:   1234,
	}

	k.Load(structs.Provider(defaults, "koanf"), nil)

	k.Load(env.Provider("MYVAR_", ".", func(s string) string {
		return strings.Replace(strings.ToLower(
			strings.TrimPrefix(s, "MYVAR_")), "_", ".", -1)
	}), nil)

	f := flag.NewFlagSet("config", flag.ContinueOnError)
	f.String("name", defaults.Name, "")
	f.Int("id", defaults.ID, "")
	f.Parse([]string{"--name", "changed-from-flags"})

	if err := k.Load(basicflag.Provider(f, "."), nil); err != nil {
		log.Fatalf("error loading config: %v", err)
	}
	
	fmt.Printf("id is = `%d`\n", k.Int("id"))
	fmt.Printf("name is = `%s`\n", k.String("name"))
}

Output

id is = `1234`
name is = `changed-from-flags`

Expected behavior
A clear and concise description of what you expected to happen.

Defaults values from flagset are not used in final config,

Output

id is = `5000`
name is = `changed-from-flags`

Please provide the following information):

  • OS: [e.g. linux/osx/windows]
  • Koanf Version [e.g. v1.0.0]

Additional context
Add any other context about the problem here.

With posflag, everything works as expected:

package main

import (
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/knadh/koanf/providers/env"
	"github.com/knadh/koanf/providers/posflag"
	"github.com/knadh/koanf/providers/structs"
	"github.com/knadh/koanf/v2"
	flag "github.com/spf13/pflag"
)

// Global koanf instance. Use "." as the key path delimiter. This can be "/" or any character.
var k = koanf.New(".")

type parentStruct struct {
	Name string `koanf:"name"`
	ID   int    `koanf:"id"`
}

func init() {
	os.Setenv("MYVAR_ID", "5000")
}

func main() {
	defaults := parentStruct{
		Name: "parent1",
		ID:   1234,
	}

	k.Load(structs.Provider(defaults, "koanf"), nil)

	k.Load(env.Provider("MYVAR_", ".", func(s string) string {
		return strings.Replace(strings.ToLower(
			strings.TrimPrefix(s, "MYVAR_")), "_", ".", -1)
	}), nil)

	f := flag.NewFlagSet("config", flag.ContinueOnError)
	f.String("name", defaults.Name, "")
	f.Int("id", defaults.ID, "")
	f.Parse([]string{"--name", "changed-from-flags"})

	if err := k.Load(posflag.Provider(f, ".", k), nil); err != nil {
		log.Fatalf("error loading config: %v", err)
	}

	fmt.Printf("id is = `%d`\n", k.Int("id"))
	fmt.Printf("name is = `%s`\n", k.String("name"))
}

# id is = `5000`
# name is = `changed-from-flags`

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions