ipfs-cluster/config/config_test.go
Hector Sanjuan 00e78a6b6d
Daemon: support remote configuration (#868)
* 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.
2019-08-09 12:56:27 +02:00

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")
}
}