Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config ignores fields when using typact.Option #334

Closed
l0nax opened this issue Nov 22, 2024 · 1 comment
Closed

Config ignores fields when using typact.Option #334

l0nax opened this issue Nov 22, 2024 · 1 comment
Labels
question Further information is requested

Comments

@l0nax
Copy link

l0nax commented Nov 22, 2024

First, I want to say that I really love this project – it has become my default go-to to handle config files.
Thanks!

Describe the bug

When I'm using my typact library, koanf seems to "forget" some fields.

Given the following config struct:

// Config is the configuration structure.
type Config struct {
	// Version holds the config version.
	Version Version `koanf:"version"`

	// ChangelogDir is the relative path to the config file
	// where all the changelog files are stored.
	ChangelogDir string `koanf:"changelog_dir"`

	// OutputPath is the path to the file where the resulting
	// file should be stored.
	//
	// Defaults to "CHANGELOG.md".
	OutputPath typact.Option[string] `koanf:"output_path"`
}

When I'm now marshaling the config, the OutputPath will be null regardless whether it contains a value or not.

To Reproduce

// CreateDefault creates a file at path with the contents
// of [Default].
func CreateDefault(path string, force bool) error {
	k := koanf.New(".")
	defaultCfg := Config{
		Version:      "2",
		ChangelogDir: ".changelogs",
		OutputPath:   typact.Some("CHANGELOG.md"),
	}

	if err := k.Load(structs.Provider(defaultCfg, "koanf"), nil); err != nil {
		return err
	}

	tomlRaw, err := k.Marshal(toml.Parser())
	if err != nil {
		return err
	}

	fmt.Printf("%s\n", string(tomlRaw))
}

The output will be:

changelog_dir = '.changelogs'
output_path = 'null'
version = '2'

Expected behavior

The output should be

changelog_dir = '.changelogs'
output_path = 'CHANGELOG.md'
version = '2'

Please provide the following information):

  • OS: Linux <REDACTED> 6.11.5-arch1-1 #1 SMP PREEMPT_DYNAMIC Tue, 22 Oct 2024 18:31:38 +0000 x86_64 GNU/Linux
  • Koanf Version: v2.1.2

Additional context

I debugged the problem and traced it down to the following code:

  1. The Koanf.Marshal method calls ko.Raw
  2. The Koanf.Raw method calls maps.Copy.
  3. The maps.Copy function clones the map but skips over unexported fields.

This behavior is documented in the copystructure module:

// See https://github.com/mitchellh/copystructure/blob/d4ce1f938f7a7ea2a40bff4544b56be9c00b5e84/copystructure.go#L15-L17
// ...

// Copy returns a deep copy of v.
//
// Copy is unable to copy unexported fields in a struct (lowercase field names).
// Unexported fields can't be reflected by the Go runtime and therefore
// copystructure can't perform any data copies.
//
// ...

This could be addressed by allowing the callee to define a custom map clone function or using a Cloner interface to clone values – if implemented.

@l0nax l0nax added the bug Something isn't working label Nov 22, 2024
@knadh
Copy link
Owner

knadh commented Dec 4, 2024

Hi @l0nax. Missed this issue.

koanf has switched away from the obsolete mitchellh/mapstructure lib to the go-viper fork #331. From the linked comment, it looks like it's not a bug, but documented behaviour.

That said, the structs provider is a simple abstraction on top of fatih/structs -> mapstructure (related: #299). I think the better approach is to write a custom Provider that uses custom cloning logic rather.

@knadh knadh added question Further information is requested and removed bug Something isn't working labels Dec 4, 2024
@knadh knadh closed this as completed Dec 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants