Skip to content

Commit

Permalink
Add configurable opts to e2e tests
Browse files Browse the repository at this point in the history
I have added the initial frame for custom test flags.
So far just the options to:
- Skip setting up the devmapper thinpool
- Skip deleting VMs
- Skip all teardown steps
- Set log level for containerd
- Set log level for flintlockd

Unfortunately custom test flags can only be added on `init()` which is
bleh but I don't see another nice was of doing this.

These flags can only be used while running `go test ...` directly.
This means you cannot pass in flags as part of a `make` or a
`docker run -it ...` command, but you can just call `go test etc` from inside the
container or in the metal host and configure what you like.

My next step is some more work around the python tooling so that these
(and more) options can be passed up.
  • Loading branch information
Callisto13 committed Nov 9, 2021
1 parent d60a54e commit d8a07b7
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 24 deletions.
16 changes: 15 additions & 1 deletion test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ import (
u "github.com/weaveworks/flintlock/test/e2e/utils"
)

var params *u.Params

func init() {
// Call testing.Init() prior to tests.NewParams(), as otherwise custom test flags
// will not be recognised.
testing.Init()
params = u.NewParams()
}

func TestE2E(t *testing.T) {
RegisterTestingT(t)

Expand All @@ -26,7 +35,7 @@ func TestE2E(t *testing.T) {
mvmPid2 int
)

r := u.Runner{}
r := u.NewRunner(params)
defer func() {
log.Println("TEST STEP: cleaning up running processes")
r.Teardown()
Expand Down Expand Up @@ -79,6 +88,11 @@ func TestE2E(t *testing.T) {
return nil
}, "120s").Should(Succeed())

if params.SkipDelete {
log.Println("TEST STEP: skipping delete")
return
}

log.Println("TEST STEP: deleting existing MicroVMs")
Expect(u.DeleteMVM(flintlockClient, mvmID, mvmNS)).To(Succeed())
Expect(u.DeleteMVM(flintlockClient, secondMvmID, mvmNS)).To(Succeed())
Expand Down
30 changes: 30 additions & 0 deletions test/e2e/utils/params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//go:build e2e
// +build e2e

package utils

import "flag"

// Params groups all param.
type Params struct {
SkipSetupThinpool bool
SkipTeardown bool
SkipDelete bool
ContainerdLogLevel string
FlintlockdLogLevel string
}

// NewParams returns a new Params based on provided flags.
func NewParams() *Params {
params := Params{}

flag.BoolVar(&params.SkipSetupThinpool, "skip.setup.thinpool", false, "Skip setting up devicemapper thinpools")
flag.BoolVar(&params.SkipDelete, "skip.delete", false, "Skip running the 'delete vm' step of the tests (useful for debugging, this will also leave containerd and flintlockd running)")
flag.BoolVar(&params.SkipTeardown, "skip.teardown", false, "Do not stop containerd or flintlockd after test exit (note: will require manual cleanup)")
flag.StringVar(&params.ContainerdLogLevel, "level.containerd", "debug", "Set containerd's log level [trace, *debug*, info, warn, error, fatal, panic]")
flag.StringVar(&params.FlintlockdLogLevel, "level.flintlockd", "0", "Set flintlockd's log level [A level of 2 and above is debug logging. A level of 9 and above is tracing.]")

flag.Parse()

return &params
}
75 changes: 52 additions & 23 deletions test/e2e/utils/runner.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//go:build e2e
// +build e2e

package utils

import (
Expand Down Expand Up @@ -33,17 +36,22 @@ const (
devMapperRoot = containerdRootDir + "/snapshotter/devmapper"
)

// Runner is a very poorly named thing and honestly idk what to call it.
// What it does is compile flintlockd and start containerd and flintlockd.
// So 'TestSetterUpper' did not sound as slick, but that is what it is.
// I am happy for literally any suggestions.
// Runner holds test runner configuration.
type Runner struct {
params *Params
flintlockdBin string
containerdSession *gexec.Session
flintlockdSession *gexec.Session
flintlockdConn *grpc.ClientConn
}

// NewRunner creates a new instance of Runner with a set of Params.
func NewRunner(params *Params) Runner {
return Runner{
params: params,
}
}

// Setup is a helper for the e2e tests which:
// - sets up up devicemapper thinpools
// - writes containerd config
Expand All @@ -56,8 +64,8 @@ type Runner struct {
// Teardown should be called before Setup in a defer.
func (r *Runner) Setup() v1alpha1.MicroVMClient {
makeDirectories()
createThinPools()
writeContainerdConfig()
r.createThinPools()
r.writeContainerdConfig()
r.buildFLBinary()
r.startContainerd()
r.startFlintlockd()
Expand All @@ -79,6 +87,13 @@ func (r *Runner) Teardown() {
r.flintlockdConn.Close()
}

// If either of these is true, we should still close the connection held
// by the runner itself. The other processes can be killed manually after
// debugging.
if r.params.SkipTeardown || r.params.SkipDelete {
return
}

if r.flintlockdSession != nil {
r.flintlockdSession.Terminate().Wait()
}
Expand All @@ -87,7 +102,7 @@ func (r *Runner) Teardown() {
r.containerdSession.Terminate().Wait()
}

cleanupThinPools()
r.cleanupThinPools()
cleanupDirectories()

gexec.CleanupBuildArtifacts()
Expand All @@ -105,15 +120,23 @@ func cleanupDirectories() {
gm.Expect(os.RemoveAll(containerdStateDir)).To(gm.Succeed())
}

func createThinPools() {
func (r *Runner) createThinPools() {
if r.params.SkipSetupThinpool {
return
}

scriptPath := filepath.Join(baseDir(), "hack", "scripts", "devpool.sh")
command := exec.Command(scriptPath, thinpoolName, loopDeviceTag)
session, err := gexec.Start(command, gk.GinkgoWriter, gk.GinkgoWriter)
gm.Expect(err).NotTo(gm.HaveOccurred())
gm.Eventually(session).Should(gexec.Exit(0))
}

func cleanupThinPools() {
func (r *Runner) cleanupThinPools() {
if r.params.SkipSetupThinpool {
return
}

gm.Expect(dmsetup.RemoveDevice(thinpoolName, dmsetup.RemoveWithForce)).To(gm.Succeed())

cmd := exec.Command("losetup")
Expand All @@ -126,15 +149,7 @@ func cleanupThinPools() {
}
}

func writeContainerdConfig() {
dmplug := map[string]interface{}{
"pool_name": thinpoolName,
"root_path": devMapperRoot,
"base_image_size": "10GB",
"discard_blocks": "true",
}
pluginTree, err := toml.TreeFromMap(dmplug)
gm.Expect(err).NotTo(gm.HaveOccurred())
func (r *Runner) writeContainerdConfig() {
cfg := ccfg.Config{
Version: 2, //nolint:gomnd
Root: containerdRootDir,
Expand All @@ -145,14 +160,25 @@ func writeContainerdConfig() {
Metrics: ccfg.MetricsConfig{
Address: "127.0.0.1:1338",
},
Plugins: map[string]toml.Tree{
"io.containerd.snapshotter.v1.devmapper": *pluginTree,
},
Debug: ccfg.Debug{
Level: "trace",
Level: r.params.ContainerdLogLevel,
},
}

if !r.params.SkipSetupThinpool {
dmplug := map[string]interface{}{
"pool_name": thinpoolName,
"root_path": devMapperRoot,
"base_image_size": "10GB",
"discard_blocks": "true",
}
pluginTree, err := toml.TreeFromMap(dmplug)
gm.Expect(err).NotTo(gm.HaveOccurred())
cfg.Plugins = map[string]toml.Tree{
"io.containerd.snapshotter.v1.devmapper": *pluginTree,
}
}

f, err := os.Create(containerdCfg)
gm.Expect(err).NotTo(gm.HaveOccurred())
defer f.Close()
Expand All @@ -175,7 +201,10 @@ func (r *Runner) startContainerd() {
func (r *Runner) startFlintlockd() {
parentIface, err := getParentInterface()
gm.Expect(err).NotTo(gm.HaveOccurred())
flCmd := exec.Command(r.flintlockdBin, "run", "--containerd-socket", containerdSocket, "--parent-iface", parentIface) //nolint:gosec
flCmd := exec.Command(r.flintlockdBin, "run",
"--containerd-socket", containerdSocket,
"--parent-iface", parentIface,
"--verbosity", r.params.FlintlockdLogLevel) //nolint:gosec
flSess, err := gexec.Start(flCmd, gk.GinkgoWriter, gk.GinkgoWriter)
gm.Expect(err).NotTo(gm.HaveOccurred())
r.flintlockdSession = flSess
Expand Down

0 comments on commit d8a07b7

Please sign in to comment.