ipfs-cluster/ipfsconn/ipfshttp/config.go
Hector Sanjuan a9a58a50a0 Config: provide utility to parse duration arguments. Use it.
Should reduce complexity (codeclimate).

License: MIT
Signed-off-by: Hector Sanjuan <code@hector.link>
2018-03-16 14:22:11 +01:00

198 lines
5.9 KiB
Go

package ipfshttp
import (
"encoding/json"
"errors"
"fmt"
"time"
"github.com/ipfs/ipfs-cluster/config"
ma "github.com/multiformats/go-multiaddr"
)
const configKey = "ipfshttp"
// Default values for Config.
const (
DefaultProxyAddr = "/ip4/127.0.0.1/tcp/9095"
DefaultNodeAddr = "/ip4/127.0.0.1/tcp/5001"
DefaultConnectSwarmsDelay = 30 * time.Second
DefaultProxyReadTimeout = 10 * time.Minute
DefaultProxyReadHeaderTimeout = 5 * time.Second
DefaultProxyWriteTimeout = 10 * time.Minute
DefaultProxyIdleTimeout = 60 * time.Second
DefaultPinMethod = "pin"
)
// Config is used to initialize a Connector and allows to customize
// its behaviour. It implements the config.ComponentConfig interface.
type Config struct {
config.Saver
// Listen parameters for the IPFS Proxy. Used by the IPFS
// connector component.
ProxyAddr ma.Multiaddr
// Host/Port for the IPFS daemon.
NodeAddr ma.Multiaddr
// ConnectSwarmsDelay specifies how long to wait after startup before
// attempting to open connections from this peer's IPFS daemon to the
// IPFS daemons of other peers.
ConnectSwarmsDelay time.Duration
// Maximum duration before timing out reading a full request
ProxyReadTimeout time.Duration
// Maximum duration before timing out reading the headers of a request
ProxyReadHeaderTimeout time.Duration
// Maximum duration before timing out write of the response
ProxyWriteTimeout time.Duration
// Server-side amount of time a Keep-Alive connection will be
// kept idle before being reused
ProxyIdleTimeout time.Duration
// "pin" or "refs". "pin" uses a "pin/add" call. "refs" uses a
// "refs -r" call followed by "pin/add". "refs" allows fetching in
// parallel but should be used with GC disabled.
PinMethod string
}
type jsonConfig struct {
ProxyListenMultiaddress string `json:"proxy_listen_multiaddress"`
NodeMultiaddress string `json:"node_multiaddress"`
ConnectSwarmsDelay string `json:"connect_swarms_delay"`
ProxyReadTimeout string `json:"proxy_read_timeout"`
ProxyReadHeaderTimeout string `json:"proxy_read_header_timeout"`
ProxyWriteTimeout string `json:"proxy_write_timeout"`
ProxyIdleTimeout string `json:"proxy_idle_timeout"`
PinMethod string `json:"pin_method"`
}
// ConfigKey provides a human-friendly identifier for this type of Config.
func (cfg *Config) ConfigKey() string {
return configKey
}
// Default sets the fields of this Config to sensible default values.
func (cfg *Config) Default() error {
proxy, _ := ma.NewMultiaddr(DefaultProxyAddr)
node, _ := ma.NewMultiaddr(DefaultNodeAddr)
cfg.ProxyAddr = proxy
cfg.NodeAddr = node
cfg.ConnectSwarmsDelay = DefaultConnectSwarmsDelay
cfg.ProxyReadTimeout = DefaultProxyReadTimeout
cfg.ProxyReadHeaderTimeout = DefaultProxyReadHeaderTimeout
cfg.ProxyWriteTimeout = DefaultProxyWriteTimeout
cfg.ProxyIdleTimeout = DefaultProxyIdleTimeout
cfg.PinMethod = DefaultPinMethod
return nil
}
// Validate checks that the fields of this Config have sensible values,
// at least in appearance.
func (cfg *Config) Validate() error {
if cfg.ProxyAddr == nil {
return errors.New("ipfshttp.proxy_listen_multiaddress not set")
}
if cfg.NodeAddr == nil {
return errors.New("ipfshttp.node_multiaddress not set")
}
if cfg.ConnectSwarmsDelay < 0 {
return errors.New("ipfshttp.connect_swarms_delay is invalid")
}
if cfg.ProxyReadTimeout < 0 {
return errors.New("ipfshttp.proxy_read_timeout is invalid")
}
if cfg.ProxyReadHeaderTimeout < 0 {
return errors.New("ipfshttp.proxy_read_header_timeout is invalid")
}
if cfg.ProxyWriteTimeout < 0 {
return errors.New("ipfshttp.proxy_write_timeout is invalid")
}
if cfg.ProxyIdleTimeout < 0 {
return errors.New("ipfshttp.proxy_idle_timeout invalid")
}
switch cfg.PinMethod {
case "refs", "pin":
default:
return errors.New("ipfshttp.pin_method invalid value")
}
return nil
}
// LoadJSON parses a JSON representation of this Config as generated by ToJSON.
func (cfg *Config) LoadJSON(raw []byte) error {
jcfg := &jsonConfig{}
err := json.Unmarshal(raw, jcfg)
if err != nil {
logger.Error("Error unmarshaling ipfshttp config")
return err
}
cfg.Default()
proxyAddr, err := ma.NewMultiaddr(jcfg.ProxyListenMultiaddress)
if err != nil {
return fmt.Errorf("error parsing ipfs_proxy_listen_multiaddress: %s", err)
}
nodeAddr, err := ma.NewMultiaddr(jcfg.NodeMultiaddress)
if err != nil {
return fmt.Errorf("error parsing ipfs_node_multiaddress: %s", err)
}
cfg.ProxyAddr = proxyAddr
cfg.NodeAddr = nodeAddr
err = config.ParseDurations(
"ipfshttp",
&config.DurationOpt{jcfg.ProxyReadTimeout, &cfg.ProxyReadTimeout, "proxy_read_timeout"},
&config.DurationOpt{jcfg.ProxyReadHeaderTimeout, &cfg.ProxyReadHeaderTimeout, "proxy_read_header_timeout"},
&config.DurationOpt{jcfg.ProxyWriteTimeout, &cfg.ProxyWriteTimeout, "proxy_write_timeout"},
&config.DurationOpt{jcfg.ProxyIdleTimeout, &cfg.ProxyIdleTimeout, "proxy_idle_timeout"},
&config.DurationOpt{jcfg.ConnectSwarmsDelay, &cfg.ConnectSwarmsDelay, "connect_swarms_delay"},
)
if err != nil {
return err
}
config.SetIfNotDefault(jcfg.PinMethod, &cfg.PinMethod)
return cfg.Validate()
}
// ToJSON generates a human-friendly JSON representation of this Config.
func (cfg *Config) ToJSON() (raw []byte, err error) {
// Multiaddress String() may panic
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("%s", r)
}
}()
jcfg := &jsonConfig{}
// Set all configuration fields
jcfg.ProxyListenMultiaddress = cfg.ProxyAddr.String()
jcfg.NodeMultiaddress = cfg.NodeAddr.String()
jcfg.ProxyReadTimeout = cfg.ProxyReadTimeout.String()
jcfg.ProxyReadHeaderTimeout = cfg.ProxyReadHeaderTimeout.String()
jcfg.ProxyWriteTimeout = cfg.ProxyWriteTimeout.String()
jcfg.ProxyIdleTimeout = cfg.ProxyIdleTimeout.String()
jcfg.ConnectSwarmsDelay = cfg.ConnectSwarmsDelay.String()
jcfg.PinMethod = cfg.PinMethod
raw, err = config.DefaultJSONMarshal(jcfg)
return
}