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

fix: correctly handle migration of configs #9995

Merged
merged 1 commit into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func Path(configroot, extension string) (string, error) {
// - If the user-provided configuration file path is only a file name, use the
// configuration root directory, otherwise use only the user-provided path
// and ignore the configuration root.
func Filename(configroot string, userConfigFile string) (string, error) {
func Filename(configroot, userConfigFile string) (string, error) {
if userConfigFile == "" {
return Path(configroot, DefaultConfigFile)
}
Expand Down
13 changes: 9 additions & 4 deletions config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,9 +415,9 @@ func (p OptionalString) String() string {
var _ json.Unmarshaler = (*OptionalInteger)(nil)
var _ json.Marshaler = (*OptionalInteger)(nil)

type swarmLimits struct{}
type swarmLimits doNotUse

var _ json.Unmarshaler = swarmLimits{}
var _ json.Unmarshaler = swarmLimits(false)

func (swarmLimits) UnmarshalJSON(b []byte) error {
d := json.NewDecoder(bytes.NewReader(b))
Expand All @@ -439,9 +439,9 @@ func (swarmLimits) UnmarshalJSON(b []byte) error {
}
}

type experimentalAcceleratedDHTClient struct{}
type experimentalAcceleratedDHTClient doNotUse

var _ json.Unmarshaler = experimentalAcceleratedDHTClient{}
var _ json.Unmarshaler = experimentalAcceleratedDHTClient(false)

func (experimentalAcceleratedDHTClient) UnmarshalJSON(b []byte) error {
d := json.NewDecoder(bytes.NewReader(b))
Expand All @@ -462,3 +462,8 @@ func (experimentalAcceleratedDHTClient) UnmarshalJSON(b []byte) error {
}
}
}

// doNotUse is a type you must not use, it should be struct{} but encoding/json
// does not support omitempty on structs and I can't be bothered to write custom
// marshalers on all structs that have a doNotUse field.
type doNotUse bool
38 changes: 32 additions & 6 deletions plugin/loader/loader.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package loader

import (
"encoding/json"
"fmt"
"io"
"os"
Expand All @@ -9,7 +10,6 @@ import (
"strings"

config "github.com/ipfs/kubo/config"
cserialize "github.com/ipfs/kubo/config/serialize"
"github.com/ipld/go-ipld-prime/multicodec"

"github.com/ipfs/kubo/core"
Expand Down Expand Up @@ -97,11 +97,10 @@ type PluginLoader struct {
func NewPluginLoader(repo string) (*PluginLoader, error) {
loader := &PluginLoader{plugins: make([]plugin.Plugin, 0, len(preloadPlugins)), repo: repo}
if repo != "" {
cfg, err := cserialize.Load(filepath.Join(repo, config.DefaultConfigFile))
switch err {
case cserialize.ErrNotInitialized:
case nil:
loader.config = cfg.Plugins
switch plugins, err := readPluginsConfig(repo, config.DefaultConfigFile); {
case err == nil:
loader.config = plugins
case os.IsNotExist(err):
default:
return nil, err
}
Expand All @@ -119,6 +118,33 @@ func NewPluginLoader(repo string) (*PluginLoader, error) {
return loader, nil
}

// readPluginsConfig reads the Plugins section of the IPFS config, avoiding
// reading anything other than the Plugin section. That way, we're free to
// make arbitrary changes to all _other_ sections in migrations.
func readPluginsConfig(repoRoot string, userConfigFile string) (config.Plugins, error) {
var cfg struct {
Plugins config.Plugins
}

cfgPath, err := config.Filename(repoRoot, userConfigFile)
if err != nil {
return config.Plugins{}, err
}

cfgFile, err := os.Open(cfgPath)
if err != nil {
return config.Plugins{}, err
}
defer cfgFile.Close()

err = json.NewDecoder(cfgFile).Decode(&cfg)
if err != nil {
return config.Plugins{}, err
}

return cfg.Plugins, nil
}

func (loader *PluginLoader) assertState(state loaderState) error {
if loader.state != state {
return fmt.Errorf("loader state must be %s, was %s", state, loader.state)
Expand Down