func (c *config) GetFelixConfig(name, node string) (string, bool, error) {
	value, err := c.getValue(getFelixConfigKey(name, node))
	if err != nil {
		return "", false, err
	} else if value == nil {
		return "", false, nil
	} else {
		return *value, true, nil
	}
}
GetFelixConfig provides a mechanism for getting arbitrary Felix configuration
in the datastore.  A blank value for the node will get the global
configuration.  If the boolean value returned is false, the configurations
is unset and the return value should be ignored.
package client
import (
	"context"
	"encoding/json"
	"fmt"
	"strconv"
	log "github.com/sirupsen/logrus"
	"github.com/projectcalico/api/pkg/lib/numorstring"
	"github.com/projectcalico/libcalico-go/lib/backend/model"
	"github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/net"
)
type ConfigLocation int8
const (
	ConfigLocationNone ConfigLocation = iota
	ConfigLocationNode
	ConfigLocationGlobal
)
var logToBgp = map[string]string{
	"none":     "none",
	"debug":    "debug",
	"info":     "info",
	"warning":  "none",
	"error":    "none",
	"critical": "none",
}
const (
	GlobalDefaultASNumber       = 64512
	GlobalDefaultLogLevel       = "info"
	GlobalDefaultIPIP           = false
	GlobalDefaultNodeToNodeMesh = true
)
type ConfigInterface interface {
	SetNodeToNodeMesh(bool) error
	GetNodeToNodeMesh() (bool, error)
	SetGlobalASNumber(numorstring.ASNumber) error
	GetGlobalASNumber() (numorstring.ASNumber, error)
	SetGlobalIPIP(bool) error
	GetGlobalIPIP() (bool, error)
	SetNodeIPIPTunnelAddress(string, *net.IP) error
	GetNodeIPIPTunnelAddress(string) (*net.IP, error)
	SetGlobalLogLevel(string) error
	GetGlobalLogLevel() (string, error)
	SetNodeLogLevel(string, string) error
	SetNodeLogLevelUseGlobal(string) error
	GetNodeLogLevel(string) (string, ConfigLocation, error)
	GetFelixConfig(string, string) (string, bool, error)
	SetFelixConfig(string, string, string) error
	UnsetFelixConfig(string, string) error
	GetBGPConfig(string, string) (string, bool, error)
	SetBGPConfig(string, string, string) error
	UnsetBGPConfig(string, string) error
}
type config struct {
	c *Client
}
func newConfigs(c *Client) ConfigInterface {
	return &config{c}
}
func (c *config) SetNodeToNodeMesh(enabled bool) error {
	b, _ := json.Marshal(enabled)
	_, err := c.c.Backend.Apply(context.Background(), &model.KVPair{
		Key:   model.GlobalBGPConfigKey{Name: "NodeMeshEnabled"},
		Value: string(b),
	})
	return err
}
func (c *config) GetNodeToNodeMesh() (bool, error) {
	var n bool
	if s, err := c.getValue(model.GlobalBGPConfigKey{Name: "NodeMeshEnabled"}); err != nil {
		log.Info("Error getting node mesh")
		return false, err
	} else if s == nil {
		log.Info("Return default node to node mesh")
		return GlobalDefaultNodeToNodeMesh, nil
	} else if err = json.Unmarshal([]byte(*s), &n); err != nil {
		log.WithField("NodeMeshEnabled", *s).Error("Error parsing node to node mesh")
		return false, err
	} else {
		log.Info("Returning configured node to node mesh")
		return n, nil
	}
}
func (c *config) SetGlobalASNumber(asNumber numorstring.ASNumber) error {
	_, err := c.c.Backend.Apply(context.Background(), &model.KVPair{
		Key:   model.GlobalBGPConfigKey{Name: "AsNumber"},
		Value: asNumber.String(),
	})
	return err
}
func (c *config) GetGlobalASNumber() (numorstring.ASNumber, error) {
	if s, err := c.getValue(model.GlobalBGPConfigKey{Name: "AsNumber"}); err != nil {
		return 0, err
	} else if s == nil {
		return GlobalDefaultASNumber, nil
	} else if asn, err := numorstring.ASNumberFromString(*s); err != nil {
		return 0, err
	} else {
		return asn, nil
	}
}
func (c *config) SetGlobalIPIP(enabled bool) error {
	_, err := c.c.Backend.Apply(context.Background(), &model.KVPair{
		Key:   model.GlobalConfigKey{Name: "IpInIpEnabled"},
		Value: strconv.FormatBool(enabled),
	})
	return err
}
func (c *config) GetGlobalIPIP() (bool, error) {
	if s, err := c.getValue(model.GlobalConfigKey{Name: "IpInIpEnabled"}); err != nil {
		return false, err
	} else if s == nil {
		return GlobalDefaultIPIP, nil
	} else if enabled, err := strconv.ParseBool(*s); err != nil {
		return false, err
	} else {
		return enabled, nil
	}
}
func (c *config) SetNodeIPIPTunnelAddress(node string, ip *net.IP) error {
	key := model.HostConfigKey{Hostname: node, Name: "IpInIpTunnelAddr"}
	if ip == nil {
		err := c.deleteConfig(key)
		return err
	} else {
		_, err := c.c.Backend.Apply(context.Background(), &model.KVPair{
			Key:   key,
			Value: ip.String(),
		})
		return err
	}
}
func (c *config) GetNodeIPIPTunnelAddress(node string) (*net.IP, error) {
	ip := &net.IP{}
	if s, err := c.getValue(model.HostConfigKey{Hostname: node, Name: "IpInIpTunnelAddr"}); err != nil {
		return nil, err
	} else if s == nil {
		return nil, nil
	} else if err = ip.UnmarshalText([]byte(*s)); err != nil {
		return nil, err
	} else {
		return ip, nil
	}
}
func (c *config) SetGlobalLogLevel(level string) error {
	return c.setLogLevel(
		level,
		model.GlobalConfigKey{Name: "LogSeverityScreen"},
		model.GlobalBGPConfigKey{Name: "loglevel"})
}
func (c *config) GetGlobalLogLevel() (string, error) {
	s, err := c.getValue(model.GlobalConfigKey{Name: "LogSeverityScreen"})
	if err != nil {
		return "", err
	} else if s == nil {
		return GlobalDefaultLogLevel, nil
	} else {
		return *s, nil
	}
}
func (c *config) SetNodeLogLevel(node string, level string) error {
	return c.setLogLevel(level,
		model.HostConfigKey{Hostname: node, Name: "LogSeverityScreen"},
		model.NodeBGPConfigKey{Nodename: node, Name: "loglevel"})
}
func (c *config) SetNodeLogLevelUseGlobal(node string) error {
	kf := model.HostConfigKey{Hostname: node, Name: "LogSeverityScreen"}
	kb := model.NodeBGPConfigKey{Nodename: node, Name: "loglevel"}
	err1 := c.deleteConfig(kf)
	err2 := c.deleteConfig(kb)
	if err1 != nil {
		return err1
	}
	return err2
}
func (c *config) GetNodeLogLevel(node string) (string, ConfigLocation, error) {
	s, err := c.getValue(model.HostConfigKey{Hostname: node, Name: "LogSeverityScreen"})
	if err != nil {
		return "", ConfigLocationNone, err
	} else if s == nil {
		l, err := c.GetGlobalLogLevel()
		return l, ConfigLocationGlobal, err
	} else {
		return *s, ConfigLocationNode, nil
	}
}