Implement initial go test for network.Create

This commit is contained in:
Brian Picciano 2024-10-05 23:03:26 +02:00
parent 168b65ea1d
commit 71bc182ab4
2 changed files with 190 additions and 32 deletions

View File

@ -6,8 +6,8 @@ import (
"io" "io"
"isle/bootstrap" "isle/bootstrap"
"isle/toolkit" "isle/toolkit"
"isle/yamlutil"
"net" "net"
"os"
"strconv" "strconv"
_ "embed" _ "embed"
@ -71,7 +71,7 @@ type NetworkConfig struct {
Tun ConfigTun `yaml:"tun"` Tun ConfigTun `yaml:"tun"`
} `yaml:"vpn"` } `yaml:"vpn"`
Storage struct { Storage struct {
Allocations []ConfigStorageAllocation Allocations []ConfigStorageAllocation `yaml:"allocations"`
} `yaml:"storage"` } `yaml:"storage"`
} }
@ -145,6 +145,18 @@ func (c *NetworkConfig) fillDefaults() {
) )
} }
// UnmarshalYAML implements the yaml.Unmarshaler interface. It will attempt to
// fill in default values where it can.
func (c *NetworkConfig) UnmarshalYAML(n *yaml.Node) error {
type wrap NetworkConfig
if err := n.Decode((*wrap)(c)); err != nil {
return fmt.Errorf("decoding into %T: %w", c, err)
}
c.fillDefaults()
return nil
}
// Config describes the structure of the daemon config file. // Config describes the structure of the daemon config file.
type Config struct { type Config struct {
Networks map[string]NetworkConfig `yaml:"networks"` Networks map[string]NetworkConfig `yaml:"networks"`
@ -186,6 +198,30 @@ func CopyDefaultConfig(into io.Writer) error {
return err return err
} }
// UnmarshalYAML implements the yaml.Unmarshaler interface. It will attempt to
// fill in default values where it can.
func (c *Config) UnmarshalYAML(n *yaml.Node) error {
{ // DEPRECATED
var networkConfig NetworkConfig
_ = n.Decode(&networkConfig)
if !toolkit.IsZero(networkConfig) {
*c = Config{
Networks: map[string]NetworkConfig{
DeprecatedNetworkID: networkConfig,
},
}
return c.Validate()
}
}
type wrap Config
if err := n.Decode((*wrap)(c)); err != nil {
return fmt.Errorf("yaml unmarshaling back into Config struct: %w", err)
}
return c.Validate()
}
// LoadConfig loads the daemon config from userConfigPath. // LoadConfig loads the daemon config from userConfigPath.
// //
// If userConfigPath is not given then the default is loaded and returned. // If userConfigPath is not given then the default is loaded and returned.
@ -194,37 +230,9 @@ func LoadConfig(userConfigPath string) (Config, error) {
return Config{}, nil return Config{}, nil
} }
userConfigB, err := os.ReadFile(userConfigPath)
if err != nil {
return Config{}, fmt.Errorf("reading from file: %w", err)
}
{ // DEPRECATED
var networkConfig NetworkConfig
_ = yaml.Unmarshal(userConfigB, &networkConfig)
if !toolkit.IsZero(networkConfig) {
networkConfig.fillDefaults()
config := Config{
Networks: map[string]NetworkConfig{
DeprecatedNetworkID: networkConfig,
},
}
return config, config.Validate()
}
}
var config Config var config Config
if err := yaml.Unmarshal(userConfigB, &config); err != nil { err := yamlutil.LoadYamlFile(&config, userConfigPath)
return Config{}, fmt.Errorf("yaml unmarshaling back into Config struct: %w", err) return config, err
}
for id := range config.Networks {
network := config.Networks[id]
network.fillDefaults()
config.Networks[id] = network
}
return config, config.Validate()
} }
// BootstrapGarageHostForAlloc returns the bootstrap.GarageHostInstance which // BootstrapGarageHostForAlloc returns the bootstrap.GarageHostInstance which

View File

@ -0,0 +1,150 @@
package network
import (
"context"
"fmt"
"os"
"path/filepath"
"sync/atomic"
"testing"
"isle/bootstrap"
"isle/daemon/daecommon"
"isle/nebula"
"isle/toolkit"
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
"gopkg.in/yaml.v3"
)
var (
envBinDirPath = func() string {
appDirPath := os.Getenv("APPDIR")
if appDirPath == "" {
panic("APPDIR not set")
}
return filepath.Join(appDirPath, "bin")
}()
ipNetCounter uint64
)
func newIPNet(t *testing.T) nebula.IPNet {
var (
ipNet nebula.IPNet
ipNetStr = fmt.Sprintf(
"172.16.%d.0/24", atomic.AddUint64(&ipNetCounter, 1),
)
)
if err := ipNet.UnmarshalText([]byte(ipNetStr)); err != nil {
t.Fatalf("parsing IPNet from %q: %v", ipNetStr, err)
}
return ipNet
}
func mustParseNetworkConfigf(str string, args ...any) daecommon.NetworkConfig {
str = fmt.Sprintf(str, args...)
var networkConfig daecommon.NetworkConfig
if err := yaml.Unmarshal([]byte(str), &networkConfig); err != nil {
panic(fmt.Sprintf("parsing network config: %v", err))
}
return networkConfig
}
type harness struct {
ctx context.Context
logger *mlog.Logger
rootDir toolkit.Dir
dirCounter uint64
}
func newHarness(t *testing.T) *harness {
return &harness{
ctx: context.Background(),
logger: mlog.NewLogger(nil),
rootDir: toolkit.Dir{Path: t.TempDir()},
}
}
func (h *harness) mkDir(t *testing.T, name string) toolkit.Dir {
fullName := fmt.Sprintf("%s-%d", name, atomic.AddUint64(&h.dirCounter, 1))
t.Logf("Creating directory %q", fullName)
d, err := h.rootDir.MkChildDir(fullName, false)
if err != nil {
t.Fatalf("creating %q: %v", fullName, err)
}
return d
}
func TestCreate(t *testing.T) {
var (
h = newHarness(t)
creationParams = bootstrap.NewCreationParams("test", "test.localnet")
networkConfig = mustParseNetworkConfigf(`
vpn:
public_addr: "127.0.0.1:10000"
tun:
device: isle-test
storage:
allocations:
- data_path: %s
meta_path: %s
capacity: 1
- data_path: %s
meta_path: %s
capacity: 1
- data_path: %s
meta_path: %s
capacity: 1
`,
h.mkDir(t, "data").Path,
h.mkDir(t, "meta").Path,
h.mkDir(t, "data").Path,
h.mkDir(t, "meta").Path,
h.mkDir(t, "data").Path,
h.mkDir(t, "meta").Path,
)
stateDir = h.mkDir(t, "state")
runtimeDir = h.mkDir(t, "runtime")
ipNet = newIPNet(t)
hostName = nebula.HostName("primus")
)
network, err := Create(
h.ctx,
h.logger.WithNamespace("network"),
networkConfig,
envBinDirPath,
stateDir,
runtimeDir,
creationParams,
ipNet,
hostName,
nil,
)
if err != nil {
t.Fatalf("creating Network: %v", err)
}
t.Cleanup(func() {
t.Log("Shutting down Network")
if err := network.Shutdown(); err != nil {
t.Logf("Shutting down Network failed: %v", err)
}
})
gotCreationParams, err := network.GetNetworkCreationParams(h.ctx)
if err != nil {
t.Fatalf("calling GetNetworkCreationParams: %v", err)
} else if creationParams != gotCreationParams {
t.Fatalf(
"expected CreationParams %+v, got %+v",
creationParams,
gotCreationParams,
)
}
}