Add documentation to public functions and types

This commit is contained in:
kaiyou 2020-05-07 14:33:29 +02:00 committed by Leo Antunes
parent 3a882eb112
commit 5d1acc1fab
4 changed files with 44 additions and 6 deletions

View File

@ -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() {

View File

@ -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) {}

View File

@ -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.

View File

@ -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)