talos/pkg/userdata/networking.go
Seán C McCord f7ad24ec4f feat: allow network interface to be ignored
Added a property to userdata to allow a network interface to be ignored,
such that Talos will perform no operations on it (including DHCP).

Also added kernel commandline parameter (talos.network.interface.ignore)
to specify a network interface should be ignored.

Also allows chaining of kernel cmdline parameter Contains() where the
parameter in question does not exist.

Fixes #1124

Signed-off-by: Seán C McCord <ulexus@gmail.com>
2019-09-07 16:33:52 -07:00

124 lines
3.5 KiB
Go

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Package userdata provides internal representation of machine configs
// nolint: dupl
package userdata
import (
"net"
"strconv"
"github.com/hashicorp/go-multierror"
"golang.org/x/xerrors"
)
// Device represents a network interface
type Device struct {
Interface string `yaml:"interface"`
CIDR string `yaml:"cidr"`
Routes []Route `yaml:"routes"`
Bond *Bond `yaml:"bond"`
MTU int `yaml:"mtu"`
DHCP bool `yaml:"dhcp"`
// Ignore indicates that the device should be ignored by any talos setup routines
Ignore bool `yaml:"ignore"`
}
// NetworkDeviceCheck defines the function type for checks
type NetworkDeviceCheck func(*Device) error
// Validate triggers the specified validation checks to run
func (d *Device) Validate(checks ...NetworkDeviceCheck) error {
var result *multierror.Error
if d.Ignore {
return result.ErrorOrNil()
}
for _, check := range checks {
result = multierror.Append(result, check(d))
}
return result.ErrorOrNil()
}
// CheckDeviceInterface ensures that the interface has been specified
func CheckDeviceInterface() NetworkDeviceCheck {
return func(d *Device) error {
var result *multierror.Error
if d.Interface == "" {
result = multierror.Append(result, xerrors.Errorf("[%s] %q: %w", "networking.os.device.interface", "", ErrRequiredSection))
}
return result.ErrorOrNil()
}
}
// CheckDeviceAddressing ensures that an appropriate addressing method
// has been specified
func CheckDeviceAddressing() NetworkDeviceCheck {
return func(d *Device) error {
var result *multierror.Error
// Test for both dhcp and cidr specified
if d.DHCP && d.CIDR != "" {
result = multierror.Append(result, xerrors.Errorf("[%s] %q: %w", "networking.os.device", "", ErrBadAddressing))
}
// test for neither dhcp nor cidr specified
if !d.DHCP && d.CIDR == "" {
result = multierror.Append(result, xerrors.Errorf("[%s] %q: %w", "networking.os.device", "", ErrBadAddressing))
}
// ensure cidr is a valid address
if d.CIDR != "" {
if _, _, err := net.ParseCIDR(d.CIDR); err != nil {
result = multierror.Append(result, xerrors.Errorf("[%s] %q: %w", "networking.os.device.CIDR", "", err))
}
}
return result.ErrorOrNil()
}
}
// CheckDeviceRoutes ensures that the specified routes are valid
func CheckDeviceRoutes() NetworkDeviceCheck {
return func(d *Device) error {
var result *multierror.Error
if len(d.Routes) == 0 {
return result.ErrorOrNil()
}
for idx, route := range d.Routes {
if _, _, err := net.ParseCIDR(route.Network); err != nil {
result = multierror.Append(result, xerrors.Errorf("[%s] %q: %w", "networking.os.device.route["+strconv.Itoa(idx)+"].Network", route.Network, ErrInvalidAddress))
}
if ip := net.ParseIP(route.Gateway); ip == nil {
result = multierror.Append(result, xerrors.Errorf("[%s] %q: %w", "networking.os.device.route["+strconv.Itoa(idx)+"].Gateway", route.Gateway, ErrInvalidAddress))
}
}
return result.ErrorOrNil()
}
}
// Bond contains the various options for configuring a
// bonded interface
type Bond struct {
Mode string `yaml:"mode"`
HashPolicy string `yaml:"hashpolicy"`
LACPRate string `yaml:"lacprate"`
Interfaces []string `yaml:"interfaces"`
}
// Route represents a network route
type Route struct {
Network string `yaml:"network"`
Gateway string `yaml:"gateway"`
}