00e78a6b6d
* Daemon: support remote configuration This: * Adds support for fetching the configuration from a remote HTTP location: `ipfs-cluster-service init http://localhost:8080/ipfs/Qm...` will instruct cluster to read the configuration file from ipfs on start (potentially making use of ipns and dnslink). This is done by creating a `service.json` like `{ "source": <url> }`. The source is then read when loading that configuration every time the daemon starts. This allows to let users always use a mutating remote configuration, potentially adding/removing trusted peers from the list or adjusting other things. * Configuration and state helpers from ipfs-cluster-service have been extracted to its own cmdutils package. This will help supporting something like an `ipfs-cluster-follow` command in the next releases. * Allows to disable the rest api by not defining it in the configuration (I thought this was already so, but apparently only affected the ipfsproxy). * Removes informer/allocator configurations from the daemon (--alloc). No one used a non default pair. In fact, it was potentially buggy to use the reposize one.
179 lines
2.9 KiB
Go
179 lines
2.9 KiB
Go
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
var mockJSON = []byte(`{
|
|
"cluster": {
|
|
"a": "b"
|
|
},
|
|
"consensus": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"api": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"ipfs_connector": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"state": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"pin_tracker": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"monitor": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"allocator": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"informer": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"observations": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
},
|
|
"datastore": {
|
|
"mock": {
|
|
"a": "b"
|
|
}
|
|
}
|
|
}`)
|
|
|
|
type mockCfg struct {
|
|
Saver
|
|
}
|
|
|
|
func (m *mockCfg) ConfigKey() string {
|
|
return "mock"
|
|
}
|
|
|
|
func (m *mockCfg) LoadJSON([]byte) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *mockCfg) ToJSON() ([]byte, error) {
|
|
return []byte(`{"a":"b"}`), nil
|
|
}
|
|
|
|
func (m *mockCfg) Default() error {
|
|
return nil
|
|
}
|
|
|
|
func (m *mockCfg) ApplyEnvVars() error {
|
|
return nil
|
|
}
|
|
|
|
func (m *mockCfg) Validate() error {
|
|
return nil
|
|
}
|
|
|
|
func setupConfigManager() *Manager {
|
|
cfg := NewManager()
|
|
mockCfg := &mockCfg{}
|
|
cfg.RegisterComponent(Cluster, mockCfg)
|
|
for _, sect := range SectionTypes() {
|
|
cfg.RegisterComponent(sect, mockCfg)
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
func TestManager_ToJSON(t *testing.T) {
|
|
cfgMgr := setupConfigManager()
|
|
err := cfgMgr.Default()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got, err := cfgMgr.ToJSON()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
if !bytes.Equal(got, mockJSON) {
|
|
t.Errorf("mismatch between got: %s and want: %s", got, mockJSON)
|
|
}
|
|
}
|
|
|
|
func TestLoadFromHTTPSourceRedirect(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) {
|
|
json := fmt.Sprintf(`{ "source" : "http://%s/config" }`, r.Host)
|
|
w.Write([]byte(json))
|
|
})
|
|
s := httptest.NewServer(mux)
|
|
defer s.Close()
|
|
|
|
cfgMgr := NewManager()
|
|
err := cfgMgr.LoadJSONFromHTTPSource(s.URL + "/config")
|
|
if err != errSourceRedirect {
|
|
t.Fatal("expected errSourceRedirect")
|
|
}
|
|
}
|
|
|
|
func TestLoadFromHTTPSource(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) {
|
|
w.Write(mockJSON)
|
|
})
|
|
s := httptest.NewServer(mux)
|
|
defer s.Close()
|
|
|
|
cfgMgr := setupConfigManager()
|
|
err := cfgMgr.LoadJSONFromHTTPSource(s.URL + "/config")
|
|
if err != nil {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
cfgMgr.Source = ""
|
|
newJSON, err := cfgMgr.ToJSON()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !bytes.Equal(newJSON, mockJSON) {
|
|
t.Error("generated json different than loaded")
|
|
}
|
|
}
|
|
|
|
func TestSaveWithSource(t *testing.T) {
|
|
cfgMgr := setupConfigManager()
|
|
cfgMgr.Default()
|
|
cfgMgr.Source = "http://a.b.c"
|
|
newJSON, err := cfgMgr.ToJSON()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
expected := []byte(`{
|
|
"source": "http://a.b.c"
|
|
}`)
|
|
|
|
if !bytes.Equal(newJSON, expected) {
|
|
t.Error("should have generated a source-only json")
|
|
}
|
|
}
|