added network config
This commit is contained in:
parent
ce335164ff
commit
d7e0591576
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
.idea/
|
||||
test_*
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
||||
module gitlab.com/bboehmke/raspi-alpine-builder
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/stretchr/testify v1.4.0
|
13
go.sum
Normal file
13
go.sum
Normal file
@ -0,0 +1,13 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
|
||||
github.com/kataras/iris v11.1.1+incompatible/go.mod h1:ki9XPua5SyAJbIxDdsssxevgGrbpBmmvoQmo/A0IodY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
171
network.go
Normal file
171
network.go
Normal file
@ -0,0 +1,171 @@
|
||||
package alpine_builder
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// network configuration
|
||||
var networkConfig = "/data/etc/network/interfaces"
|
||||
var networkInterface = "eth0"
|
||||
|
||||
// regular expressions
|
||||
var reSectionStart = regexp.MustCompile("^(iface|mapping|auto|allow-|source)")
|
||||
var reIface = regexp.MustCompile("^iface (\\w+) inet (\\w+)")
|
||||
var reStaticAddress = regexp.MustCompile("^(\\s*)address ([0-9.]+)")
|
||||
var reStaticNetmask = regexp.MustCompile("^(\\s*)netmask ([0-9.]+)")
|
||||
var reStaticGateway = regexp.MustCompile("^(\\s*)gateway ([0-9.]+)")
|
||||
|
||||
// NetworkInfo represents the actual network configuration
|
||||
type NetworkInfo struct {
|
||||
IsStatic bool
|
||||
Address string
|
||||
Netmask string
|
||||
Gateway string
|
||||
}
|
||||
|
||||
// GetNetworkInfo from config file
|
||||
func GetNetworkInfo() (*NetworkInfo, error) {
|
||||
// load config file
|
||||
file, err := os.Open(networkConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open network config: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var info *NetworkInfo
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
|
||||
// check for section start
|
||||
if reSectionStart.MatchString(line) {
|
||||
infLine := reIface.FindStringSubmatch(line)
|
||||
if infLine != nil {
|
||||
// interface found
|
||||
if infLine[1] == networkInterface {
|
||||
info = &NetworkInfo{
|
||||
IsStatic: infLine[2] == "static",
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// info set -> stop here
|
||||
if info != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
} else if info != nil {
|
||||
// interface config
|
||||
address := reStaticAddress.FindStringSubmatch(line)
|
||||
if address != nil {
|
||||
info.Address = address[2]
|
||||
}
|
||||
netmask := reStaticNetmask.FindStringSubmatch(line)
|
||||
if netmask != nil {
|
||||
info.Netmask = netmask[2]
|
||||
}
|
||||
gateway := reStaticGateway.FindStringSubmatch(line)
|
||||
if gateway != nil {
|
||||
info.Gateway = gateway[2]
|
||||
}
|
||||
}
|
||||
}
|
||||
if info != nil {
|
||||
return info, nil
|
||||
}
|
||||
return nil, errors.New("invalid network config")
|
||||
}
|
||||
|
||||
// NetworkEnableDHCP configures the network to use DHCP client
|
||||
func NetworkEnableDHCP() error {
|
||||
// load config file
|
||||
file, err := os.Open(networkConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open network config: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var buffer bytes.Buffer
|
||||
var infFound bool
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
|
||||
// check for section start
|
||||
if reSectionStart.MatchString(line) {
|
||||
infLine := reIface.FindStringSubmatch(line)
|
||||
if infLine != nil {
|
||||
// interface found
|
||||
if infLine[1] == networkInterface {
|
||||
infFound = true
|
||||
buffer.WriteString(fmt.Sprintf("iface %s inet dhcp\n", networkInterface))
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if infFound {
|
||||
infFound = false
|
||||
}
|
||||
}
|
||||
buffer.WriteString(line + "\n")
|
||||
|
||||
} else if !infFound {
|
||||
buffer.WriteString(line + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
// write config file
|
||||
return ioutil.WriteFile(networkConfig, buffer.Bytes(), os.ModePerm)
|
||||
}
|
||||
|
||||
// NetworkSetStatic IP configuration
|
||||
func NetworkSetStatic(address, netmask, gateway string) error {
|
||||
// load config file
|
||||
file, err := os.Open(networkConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open network config: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var buffer bytes.Buffer
|
||||
var infFound bool
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
|
||||
// check for section start
|
||||
if reSectionStart.MatchString(line) {
|
||||
infLine := reIface.FindStringSubmatch(line)
|
||||
if infLine != nil {
|
||||
// interface found
|
||||
if infLine[1] == networkInterface {
|
||||
infFound = true
|
||||
buffer.WriteString(fmt.Sprintf("iface %s inet static\n", networkInterface))
|
||||
buffer.WriteString(fmt.Sprintf(" address %s\n", address))
|
||||
buffer.WriteString(fmt.Sprintf(" netmask %s\n", netmask))
|
||||
buffer.WriteString(fmt.Sprintf(" gateway %s\n", gateway))
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
if infFound {
|
||||
infFound = false
|
||||
}
|
||||
}
|
||||
buffer.WriteString(line + "\n")
|
||||
|
||||
} else if !infFound {
|
||||
buffer.WriteString(line + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
// write config file
|
||||
return ioutil.WriteFile(networkConfig, buffer.Bytes(), os.ModePerm)
|
||||
}
|
116
network_test.go
Normal file
116
network_test.go
Normal file
@ -0,0 +1,116 @@
|
||||
package alpine_builder
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func init() {
|
||||
networkConfig = "test_interfaces"
|
||||
}
|
||||
|
||||
func TestGetNetworkInfo(t *testing.T) {
|
||||
ass := assert.New(t)
|
||||
|
||||
// file does not exist
|
||||
_, err := GetNetworkInfo()
|
||||
ass.EqualError(err, "failed to open network config: open test_interfaces: no such file or directory")
|
||||
|
||||
// invalid config file
|
||||
ass.NoError(ioutil.WriteFile(networkConfig, []byte(""), os.ModePerm))
|
||||
_, err = GetNetworkInfo()
|
||||
ass.EqualError(err, "invalid network config")
|
||||
|
||||
// dynamic config
|
||||
ass.NoError(ioutil.WriteFile(networkConfig, []byte(`auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet dhcp`), os.ModePerm))
|
||||
info, err := GetNetworkInfo()
|
||||
ass.NoError(err)
|
||||
ass.False(info.IsStatic)
|
||||
|
||||
// static config
|
||||
ass.NoError(ioutil.WriteFile(networkConfig, []byte(`auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address 1.2.3.4
|
||||
netmask 255.255.255.0
|
||||
gateway 4.3.2.1`), os.ModePerm))
|
||||
info, err = GetNetworkInfo()
|
||||
ass.NoError(err)
|
||||
ass.True(info.IsStatic)
|
||||
ass.Equal("1.2.3.4", info.Address)
|
||||
ass.Equal("255.255.255.0", info.Netmask)
|
||||
ass.Equal("4.3.2.1", info.Gateway)
|
||||
|
||||
_ = os.Remove(networkConfig)
|
||||
}
|
||||
|
||||
func TestNetworkEnableDHCP(t *testing.T) {
|
||||
ass := assert.New(t)
|
||||
|
||||
// file does not exist
|
||||
_, err := GetNetworkInfo()
|
||||
ass.EqualError(err, "failed to open network config: open test_interfaces: no such file or directory")
|
||||
|
||||
ass.NoError(ioutil.WriteFile(networkConfig, []byte(`auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address 1.2.3.4
|
||||
netmask 255.255.255.0
|
||||
gateway 4.3.2.1`), os.ModePerm))
|
||||
|
||||
ass.NoError(NetworkEnableDHCP())
|
||||
|
||||
data, err := ioutil.ReadFile(networkConfig)
|
||||
ass.NoError(err)
|
||||
|
||||
ass.Equal(`auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet dhcp
|
||||
`, string(data))
|
||||
|
||||
_ = os.Remove(networkConfig)
|
||||
}
|
||||
|
||||
func TestNetworkSetStatic(t *testing.T) {
|
||||
ass := assert.New(t)
|
||||
|
||||
// file does not exist
|
||||
_, err := GetNetworkInfo()
|
||||
ass.EqualError(err, "failed to open network config: open test_interfaces: no such file or directory")
|
||||
|
||||
ass.NoError(ioutil.WriteFile(networkConfig, []byte(`auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet dhcp`), os.ModePerm))
|
||||
|
||||
ass.NoError(NetworkSetStatic("1.2.3.4", "255.255.255.0", "4.3.2.1"))
|
||||
|
||||
data, err := ioutil.ReadFile(networkConfig)
|
||||
ass.NoError(err)
|
||||
|
||||
ass.Equal(`auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address 1.2.3.4
|
||||
netmask 255.255.255.0
|
||||
gateway 4.3.2.1
|
||||
`, string(data))
|
||||
|
||||
_ = os.Remove(networkConfig)
|
||||
}
|
@ -99,7 +99,7 @@ EOF
|
||||
|
||||
# prepare network
|
||||
chroot_exec rc-update add networking default
|
||||
ln -fs /data/etc/interfaces ${ROOTFS_PATH}/etc/network/interfaces
|
||||
ln -fs /data/etc/network/interfaces ${ROOTFS_PATH}/etc/network/interfaces
|
||||
|
||||
# run local before network -> local brings up the interface
|
||||
sed -i '/^\tneed/ s/$/ local/' ${ROOTFS_PATH}/etc/init.d/networking
|
||||
@ -200,8 +200,8 @@ root_pw=\$(mkpasswd -m sha-512 -s "${DEFAULT_ROOT_PASSWORD}")
|
||||
echo "root:\${root_pw}:0:0:::::" > /data/etc/shadow
|
||||
|
||||
# interface
|
||||
if [ ! -f /data/etc/interfaces ]; then
|
||||
cat > /data/etc/interfaces <<EOF2
|
||||
if [ ! -f /data/etc/network/interfaces ]; then
|
||||
cat > /data/etc/network/interfaces <<EOF2
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user