Add documentation to public functions and types
This commit is contained in:
parent
3a882eb112
commit
5d1acc1fab
|
@ -14,8 +14,10 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// KeyLen is the fixed length of cluster keys, must be checked by callers
|
||||||
const KeyLen = 32
|
const KeyLen = 32
|
||||||
|
|
||||||
|
// Cluster represents a running cluster configuration
|
||||||
type Cluster struct {
|
type Cluster struct {
|
||||||
LocalName string // used to avoid LocalNode(); should not change
|
LocalName string // used to avoid LocalNode(); should not change
|
||||||
ml *memberlist.Memberlist
|
ml *memberlist.Memberlist
|
||||||
|
@ -24,6 +26,8 @@ type Cluster struct {
|
||||||
events chan memberlist.NodeEvent
|
events chan memberlist.NodeEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New is used to create a new Cluster instance
|
||||||
|
// The returned instance is ready to be updated with the local node settings then joined
|
||||||
func New(init bool, clusterKey []byte, bindAddr string, bindPort int, useIPAsName bool) (*Cluster, error) {
|
func New(init bool, clusterKey []byte, bindAddr string, bindPort int, useIPAsName bool) (*Cluster, error) {
|
||||||
state := &State{}
|
state := &State{}
|
||||||
if !init {
|
if !init {
|
||||||
|
@ -65,6 +69,11 @@ func New(init bool, clusterKey []byte, bindAddr string, bindPort int, useIPAsNam
|
||||||
return &cluster, nil
|
return &cluster, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Join tries to join the cluster by contacting provided addresses
|
||||||
|
// Provided addresses are passed as is, if no address is provided, known
|
||||||
|
// cluster nodes are contacted instead.
|
||||||
|
// Joining fail if none of the provided addresses or none of the known
|
||||||
|
// nodes can be joined.
|
||||||
func (c *Cluster) Join(addrs []string) error {
|
func (c *Cluster) Join(addrs []string) error {
|
||||||
if len(addrs) == 0 {
|
if len(addrs) == 0 {
|
||||||
for _, n := range c.state.Nodes {
|
for _, n := range c.state.Nodes {
|
||||||
|
@ -80,17 +89,24 @@ func (c *Cluster) Join(addrs []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Leave saves the current state before leaving, then leaves the cluster
|
||||||
func (c *Cluster) Leave() {
|
func (c *Cluster) Leave() {
|
||||||
c.saveState()
|
c.saveState()
|
||||||
c.ml.Leave(10 * time.Second)
|
c.ml.Leave(10 * time.Second)
|
||||||
c.ml.Shutdown() //nolint: errcheck
|
c.ml.Shutdown() //nolint: errcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update takes a new local node configuration into account
|
||||||
|
// If the node is already joined, update also gossips the new local node
|
||||||
|
// configuration
|
||||||
func (c *Cluster) Update(localNode common.Node) {
|
func (c *Cluster) Update(localNode common.Node) {
|
||||||
c.localNode = localNode
|
c.localNode = localNode
|
||||||
c.ml.UpdateNode(1 * time.Second) // we currently do not update after creation
|
c.ml.UpdateNode(1 * time.Second) // we currently do not update after creation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Members provides a channel notifying of cluster changes
|
||||||
|
// Everytime a change happens inside the cluster (except for local changes),
|
||||||
|
// the updated list of cluster nodes is pushed to the channel.
|
||||||
func (c *Cluster) Members() <-chan []common.Node {
|
func (c *Cluster) Members() <-chan []common.Node {
|
||||||
changes := make(chan []common.Node)
|
changes := make(chan []common.Node)
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -5,10 +5,14 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NotifyConflict implements the memberlist deletage interface
|
||||||
func (c *Cluster) NotifyConflict(node, other *memberlist.Node) {
|
func (c *Cluster) NotifyConflict(node, other *memberlist.Node) {
|
||||||
logrus.Errorf("node name conflict detected: %s", other.Name)
|
logrus.Errorf("node name conflict detected: %s", other.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NodeMeta implements the memberlist deletage interface
|
||||||
|
// Metadata is provided by the local node settings, encoding is handled
|
||||||
|
// by the node implementation directly
|
||||||
func (c *Cluster) NodeMeta(limit int) []byte {
|
func (c *Cluster) NodeMeta(limit int) []byte {
|
||||||
encoded, err := c.localNode.Encode(limit)
|
encoded, err := c.localNode.Encode(limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -18,8 +22,14 @@ func (c *Cluster) NodeMeta(limit int) []byte {
|
||||||
return encoded
|
return encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
// none of these are used
|
// NotifyMsg implements the memberlist deletage interface
|
||||||
func (c *Cluster) NotifyMsg([]byte) {}
|
func (c *Cluster) NotifyMsg([]byte) {}
|
||||||
|
|
||||||
|
// GetBroadcasts implements the memberlist deletage interface
|
||||||
func (c *Cluster) GetBroadcasts(overhead, limit int) [][]byte { return nil }
|
func (c *Cluster) GetBroadcasts(overhead, limit int) [][]byte { return nil }
|
||||||
|
|
||||||
|
// LocalState implements the memberlist deletage interface
|
||||||
func (c *Cluster) LocalState(join bool) []byte { return nil }
|
func (c *Cluster) LocalState(join bool) []byte { return nil }
|
||||||
|
|
||||||
|
// MergeRemoteState implements the memberlist deletage interface
|
||||||
func (c *Cluster) MergeRemoteState(buf []byte, join bool) {}
|
func (c *Cluster) MergeRemoteState(buf []byte, join bool) {}
|
||||||
|
|
|
@ -38,6 +38,7 @@ func (n *Node) Encode(limit int) ([]byte, error) {
|
||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode the node Meta field into its metadata
|
||||||
func (n *Node) Decode() error {
|
func (n *Node) Decode() error {
|
||||||
// TODO: we blindly trust the info we get from the peers; We should be more defensive to limit the damage a leaked
|
// TODO: we blindly trust the info we get from the peers; We should be more defensive to limit the damage a leaked
|
||||||
// PSK can cause.
|
// PSK can cause.
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WgState holds the configured state of a Wesher Wireguard interface
|
||||||
type WgState struct {
|
type WgState struct {
|
||||||
iface string
|
iface string
|
||||||
client *wgctrl.Client
|
client *wgctrl.Client
|
||||||
|
@ -21,6 +22,9 @@ type WgState struct {
|
||||||
PubKey wgtypes.Key
|
PubKey wgtypes.Key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewWGConfig creates a new Wesher Wireguard state
|
||||||
|
// The Wireguard keys are generated for every new interface
|
||||||
|
// The interface must later be setup using SetUpInterface
|
||||||
func NewWGConfig(iface string, port int) (*WgState, error) {
|
func NewWGConfig(iface string, port int) (*WgState, error) {
|
||||||
client, err := wgctrl.New()
|
client, err := wgctrl.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -43,6 +47,11 @@ func NewWGConfig(iface string, port int) (*WgState, error) {
|
||||||
return &wgState, nil
|
return &wgState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AssignOverlayAddr assigns a new address to the interface
|
||||||
|
// The address is assigned inside the provided network and depends on the
|
||||||
|
// provided name deterministically
|
||||||
|
// Currently, the address is assigned by hashing the name and mapping that
|
||||||
|
// hash in the target network space
|
||||||
func (wg *WgState) AssignOverlayAddr(ipnet *net.IPNet, name string) {
|
func (wg *WgState) AssignOverlayAddr(ipnet *net.IPNet, name string) {
|
||||||
// TODO: this is way too brittle and opaque
|
// TODO: this is way too brittle and opaque
|
||||||
bits, size := ipnet.Mask.Size()
|
bits, size := ipnet.Mask.Size()
|
||||||
|
@ -63,6 +72,7 @@ func (wg *WgState) AssignOverlayAddr(ipnet *net.IPNet, name string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DownInterface shuts down the associated network interface
|
||||||
func (wg *WgState) DownInterface() error {
|
func (wg *WgState) DownInterface() error {
|
||||||
if _, err := wg.client.Device(wg.iface); err != nil {
|
if _, err := wg.client.Device(wg.iface); err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -77,12 +87,13 @@ func (wg *WgState) DownInterface() error {
|
||||||
return netlink.LinkDel(link)
|
return netlink.LinkDel(link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetUpInterface creates and setup the associated network interface
|
||||||
func (wg *WgState) SetUpInterface(nodes []common.Node) error {
|
func (wg *WgState) SetUpInterface(nodes []common.Node) error {
|
||||||
if err := netlink.LinkAdd(&wireguard{LinkAttrs: netlink.LinkAttrs{Name: wg.iface}}); err != nil && !os.IsExist(err) {
|
if err := netlink.LinkAdd(&wireguard{LinkAttrs: netlink.LinkAttrs{Name: wg.iface}}); err != nil && !os.IsExist(err) {
|
||||||
return errors.Wrapf(err, "could not create interface %s", wg.iface)
|
return errors.Wrapf(err, "could not create interface %s", wg.iface)
|
||||||
}
|
}
|
||||||
|
|
||||||
peerCfgs, err := wg.NodesToPeerConfigs(nodes)
|
peerCfgs, err := wg.nodesToPeerConfigs(nodes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error converting received node information to wireguard format")
|
return errors.Wrap(err, "error converting received node information to wireguard format")
|
||||||
}
|
}
|
||||||
|
@ -122,7 +133,7 @@ func (wg *WgState) SetUpInterface(nodes []common.Node) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wg *WgState) NodesToPeerConfigs(nodes []common.Node) ([]wgtypes.PeerConfig, error) {
|
func (wg *WgState) nodesToPeerConfigs(nodes []common.Node) ([]wgtypes.PeerConfig, error) {
|
||||||
peerCfgs := make([]wgtypes.PeerConfig, len(nodes))
|
peerCfgs := make([]wgtypes.PeerConfig, len(nodes))
|
||||||
for i, node := range nodes {
|
for i, node := range nodes {
|
||||||
pubKey, err := wgtypes.ParseKey(node.PubKey)
|
pubKey, err := wgtypes.ParseKey(node.PubKey)
|
||||||
|
|
Loading…
Reference in New Issue