libnetwork/osl: make constructing Interfaces more atomic
It's still not "great", but implement a `newInterface()` constructor to create a new Interface instance, instead of creating a partial instance and applying "options" after the fact. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
47f9e70385
commit
9d3b1f9419
3 changed files with 29 additions and 38 deletions
|
@ -14,6 +14,31 @@ import (
|
|||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
// newInterface creates a new interface in the given namespace using the
|
||||
// provided options.
|
||||
func newInterface(ns *Namespace, srcName, dstPrefix string, options ...IfaceOption) (*Interface, error) {
|
||||
i := &Interface{
|
||||
srcName: srcName,
|
||||
dstName: dstPrefix,
|
||||
ns: ns,
|
||||
}
|
||||
for _, opt := range options {
|
||||
if opt != nil {
|
||||
// TODO(thaJeztah): use multi-error instead of returning early.
|
||||
if err := opt(i); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if i.master != "" {
|
||||
i.dstMaster = ns.findDst(i.master, true)
|
||||
if i.dstMaster == "" {
|
||||
return nil, fmt.Errorf("could not find an appropriate master %q for %q", i.master, i.srcName)
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
// Interface represents the settings and identity of a network device.
|
||||
// It is used as a return type for Network.Link, and it is common practice
|
||||
// for the caller to use this information when moving interface SrcName from
|
||||
|
@ -135,23 +160,11 @@ func (n *Namespace) findDst(srcName string, isBridge bool) string {
|
|||
// to only provide a prefix for DstName. The AddInterface api will auto-generate
|
||||
// an appropriate suffix for the DstName to disambiguate.
|
||||
func (n *Namespace) AddInterface(srcName, dstPrefix string, options ...IfaceOption) error {
|
||||
i := &Interface{
|
||||
srcName: srcName,
|
||||
dstName: dstPrefix,
|
||||
ns: n,
|
||||
}
|
||||
if err := i.processInterfaceOptions(options...); err != nil {
|
||||
i, err := newInterface(n, srcName, dstPrefix, options...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if i.master != "" {
|
||||
i.dstMaster = n.findDst(i.master, true)
|
||||
if i.dstMaster == "" {
|
||||
return fmt.Errorf("could not find an appropriate master %q for %q",
|
||||
i.master, i.srcName)
|
||||
}
|
||||
}
|
||||
|
||||
n.mu.Lock()
|
||||
if n.isDefault {
|
||||
i.dstName = i.srcName
|
||||
|
|
|
@ -482,20 +482,10 @@ func (n *Namespace) Destroy() error {
|
|||
func (n *Namespace) Restore(interfaces map[Iface][]IfaceOption, routes []*types.StaticRoute, gw net.IP, gw6 net.IP) error {
|
||||
// restore interfaces
|
||||
for iface, opts := range interfaces {
|
||||
i := &Interface{
|
||||
srcName: iface.SrcName,
|
||||
dstName: iface.DstPrefix,
|
||||
ns: n,
|
||||
}
|
||||
if err := i.processInterfaceOptions(opts...); err != nil {
|
||||
i, err := newInterface(n, iface.SrcName, iface.DstPrefix, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if i.master != "" {
|
||||
i.dstMaster = n.findDst(i.master, true)
|
||||
if i.dstMaster == "" {
|
||||
return fmt.Errorf("could not find an appropriate master %q for %q", i.master, i.srcName)
|
||||
}
|
||||
}
|
||||
if n.isDefault {
|
||||
i.dstName = i.srcName
|
||||
} else {
|
||||
|
|
|
@ -24,18 +24,6 @@ func WithFamily(family int) NeighOption {
|
|||
}
|
||||
}
|
||||
|
||||
func (i *Interface) processInterfaceOptions(options ...IfaceOption) error {
|
||||
for _, opt := range options {
|
||||
if opt != nil {
|
||||
// TODO(thaJeztah): use multi-error instead of returning early.
|
||||
if err := opt(i); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithIsBridge sets whether the interface is a bridge.
|
||||
func WithIsBridge(isBridge bool) IfaceOption {
|
||||
return func(i *Interface) error {
|
||||
|
|
Loading…
Reference in a new issue