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.
225 lines
6.7 KiB
Go
225 lines
6.7 KiB
Go
package cmdutils
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
ipfscluster "github.com/ipfs/ipfs-cluster"
|
|
"github.com/ipfs/ipfs-cluster/api/ipfsproxy"
|
|
"github.com/ipfs/ipfs-cluster/api/rest"
|
|
"github.com/ipfs/ipfs-cluster/config"
|
|
"github.com/ipfs/ipfs-cluster/consensus/crdt"
|
|
"github.com/ipfs/ipfs-cluster/consensus/raft"
|
|
"github.com/ipfs/ipfs-cluster/datastore/badger"
|
|
"github.com/ipfs/ipfs-cluster/informer/disk"
|
|
"github.com/ipfs/ipfs-cluster/informer/numpin"
|
|
"github.com/ipfs/ipfs-cluster/ipfsconn/ipfshttp"
|
|
"github.com/ipfs/ipfs-cluster/monitor/pubsubmon"
|
|
"github.com/ipfs/ipfs-cluster/observations"
|
|
"github.com/ipfs/ipfs-cluster/pintracker/maptracker"
|
|
"github.com/ipfs/ipfs-cluster/pintracker/stateless"
|
|
)
|
|
|
|
// Configs carries config types used by a Cluster Peer.
|
|
type Configs struct {
|
|
Cluster *ipfscluster.Config
|
|
Restapi *rest.Config
|
|
Ipfsproxy *ipfsproxy.Config
|
|
Ipfshttp *ipfshttp.Config
|
|
Raft *raft.Config
|
|
Crdt *crdt.Config
|
|
Maptracker *maptracker.Config
|
|
Statelesstracker *stateless.Config
|
|
Pubsubmon *pubsubmon.Config
|
|
Diskinf *disk.Config
|
|
Numpininf *numpin.Config
|
|
Metrics *observations.MetricsConfig
|
|
Tracing *observations.TracingConfig
|
|
Badger *badger.Config
|
|
}
|
|
|
|
// ConfigHelper helps managing the configuration and identity files with the
|
|
// standard set of cluster components.
|
|
type ConfigHelper struct {
|
|
identity *config.Identity
|
|
manager *config.Manager
|
|
configs *Configs
|
|
|
|
configPath string
|
|
identityPath string
|
|
}
|
|
|
|
// NewConfigHelper creates a config helper given the paths to the
|
|
// configuration and identity files.
|
|
func NewConfigHelper(configPath, identityPath string) *ConfigHelper {
|
|
ch := &ConfigHelper{
|
|
configPath: configPath,
|
|
identityPath: identityPath,
|
|
}
|
|
ch.init()
|
|
return ch
|
|
}
|
|
|
|
// LoadConfigFromDisk parses the configuration from disk.
|
|
func (ch *ConfigHelper) LoadConfigFromDisk() error {
|
|
return ch.manager.LoadJSONFileAndEnv(ch.configPath)
|
|
}
|
|
|
|
// LoadIdentityFromDisk parses the identity from disk.
|
|
func (ch *ConfigHelper) LoadIdentityFromDisk() error {
|
|
// load identity with hack for 0.11.0 - identity separation.
|
|
_, err := os.Stat(ch.identityPath)
|
|
ident := &config.Identity{}
|
|
// temporary hack to convert identity
|
|
if os.IsNotExist(err) {
|
|
clusterConfig, err := config.GetClusterConfig(ch.configPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = ident.LoadJSON(clusterConfig)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error loading identity")
|
|
}
|
|
|
|
err = ident.SaveJSON(ch.identityPath)
|
|
if err != nil {
|
|
return errors.Wrap(err, "error saving identity")
|
|
}
|
|
|
|
fmt.Fprintf(
|
|
os.Stderr,
|
|
"\nNOTICE: identity information extracted from %s and saved as %s.\n\n",
|
|
ch.configPath,
|
|
ch.identityPath,
|
|
)
|
|
} else { // leave this part when the hack is removed.
|
|
err = ident.LoadJSONFromFile(ch.identityPath)
|
|
if err != nil {
|
|
return fmt.Errorf("error loading identity from %s: %s", ch.identityPath, err)
|
|
}
|
|
}
|
|
|
|
err = ident.ApplyEnvVars()
|
|
if err != nil {
|
|
return errors.Wrap(err, "error applying environment variables to the identity")
|
|
}
|
|
ch.identity = ident
|
|
return nil
|
|
}
|
|
|
|
// LoadFromDisk loads both configuration and identity from disk.
|
|
func (ch *ConfigHelper) LoadFromDisk() error {
|
|
err := ch.LoadConfigFromDisk()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return ch.LoadIdentityFromDisk()
|
|
}
|
|
|
|
// Identity returns the Identity object. It returns an empty identity
|
|
// if not loaded yet.
|
|
func (ch *ConfigHelper) Identity() *config.Identity {
|
|
return ch.identity
|
|
}
|
|
|
|
// Manager returns the config manager with all the
|
|
// cluster configurations registered.
|
|
func (ch *ConfigHelper) Manager() *config.Manager {
|
|
return ch.manager
|
|
}
|
|
|
|
// Configs returns the Configs object which holds all the cluster
|
|
// configurations. Configurations are empty if they have not been loaded from
|
|
// disk.
|
|
func (ch *ConfigHelper) Configs() *Configs {
|
|
return ch.configs
|
|
}
|
|
|
|
// register all current cluster components
|
|
func (ch *ConfigHelper) init() {
|
|
man := config.NewManager()
|
|
cfgs := &Configs{
|
|
Cluster: &ipfscluster.Config{},
|
|
Restapi: &rest.Config{},
|
|
Ipfsproxy: &ipfsproxy.Config{},
|
|
Ipfshttp: &ipfshttp.Config{},
|
|
Raft: &raft.Config{},
|
|
Crdt: &crdt.Config{},
|
|
Maptracker: &maptracker.Config{},
|
|
Statelesstracker: &stateless.Config{},
|
|
Pubsubmon: &pubsubmon.Config{},
|
|
Diskinf: &disk.Config{},
|
|
Metrics: &observations.MetricsConfig{},
|
|
Tracing: &observations.TracingConfig{},
|
|
Badger: &badger.Config{},
|
|
}
|
|
man.RegisterComponent(config.Cluster, cfgs.Cluster)
|
|
man.RegisterComponent(config.API, cfgs.Restapi)
|
|
man.RegisterComponent(config.API, cfgs.Ipfsproxy)
|
|
man.RegisterComponent(config.IPFSConn, cfgs.Ipfshttp)
|
|
man.RegisterComponent(config.Consensus, cfgs.Raft)
|
|
man.RegisterComponent(config.Consensus, cfgs.Crdt)
|
|
man.RegisterComponent(config.PinTracker, cfgs.Maptracker)
|
|
man.RegisterComponent(config.PinTracker, cfgs.Statelesstracker)
|
|
man.RegisterComponent(config.Monitor, cfgs.Pubsubmon)
|
|
man.RegisterComponent(config.Informer, cfgs.Diskinf)
|
|
man.RegisterComponent(config.Observations, cfgs.Metrics)
|
|
man.RegisterComponent(config.Observations, cfgs.Tracing)
|
|
man.RegisterComponent(config.Datastore, cfgs.Badger)
|
|
|
|
ch.identity = &config.Identity{}
|
|
ch.manager = man
|
|
ch.configs = cfgs
|
|
}
|
|
|
|
// MakeConfigFolder creates the folder to hold
|
|
// configuration and identity files.
|
|
func (ch *ConfigHelper) MakeConfigFolder() error {
|
|
f := filepath.Dir(ch.configPath)
|
|
if _, err := os.Stat(f); os.IsNotExist(err) {
|
|
err := os.MkdirAll(f, 0700)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SaveConfigToDisk saves the configuration file to disk.
|
|
func (ch *ConfigHelper) SaveConfigToDisk() error {
|
|
err := ch.MakeConfigFolder()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return ch.manager.SaveJSON(ch.configPath)
|
|
}
|
|
|
|
// SaveIdentityToDisk saves the identity file to disk.
|
|
func (ch *ConfigHelper) SaveIdentityToDisk() error {
|
|
err := ch.MakeConfigFolder()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return ch.Identity().SaveJSON(ch.identityPath)
|
|
}
|
|
|
|
// SetupTracing propagates tracingCfg.EnableTracing to all other
|
|
// configurations. Use only when identity has been loaded or generated. The
|
|
// forceEnabled parameter allows to override the EnableTracing value.
|
|
func (ch *ConfigHelper) SetupTracing(forceEnabled bool) {
|
|
enabled := forceEnabled || ch.configs.Tracing.EnableTracing
|
|
|
|
ch.configs.Tracing.ClusterID = ch.Identity().ID.Pretty()
|
|
ch.configs.Tracing.ClusterPeername = ch.configs.Cluster.Peername
|
|
ch.configs.Tracing.EnableTracing = enabled
|
|
ch.configs.Cluster.Tracing = enabled
|
|
ch.configs.Raft.Tracing = enabled
|
|
ch.configs.Crdt.Tracing = enabled
|
|
ch.configs.Restapi.Tracing = enabled
|
|
ch.configs.Ipfshttp.Tracing = enabled
|
|
ch.configs.Ipfsproxy.Tracing = enabled
|
|
}
|