Skip to content

Commit

Permalink
Fix every_test_custom_ns test
Browse files Browse the repository at this point in the history
  • Loading branch information
maruina committed May 5, 2023
1 parent 64d85de commit 75e43ce
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 27 deletions.
42 changes: 27 additions & 15 deletions examples/every_test_custom_ns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ a custom namespace for every test. This could easily be done for every
feature as well if that is your preference.

First, you'll have to set up the env. In this example we assume an in-cluster configuration.

```go
var testenv env.Environment

func TestMain(m *testing.M) {
testenv = env.New()
...
testenv = env.New()
...
}
```

Second, set the BeforeEachTest hook to create the namespace. We store it in the
context so that it can be looked up on a per-test basis for deletion.

```go
testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return createNSForTest(ctx,cfg,t,runID)
Expand All @@ -23,7 +26,9 @@ testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing
// The creation uses the typical c.Resources() object.
cfg.Client().Resources().Create(ctx,&nsObj)
```

Third, set the AfterEachTest hook to lookup and delete the namespace.

```go
testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return deleteNSForTest(ctx,cfg,t,runID)
Expand All @@ -33,23 +38,30 @@ testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.
cfg.Client().Resources().Delete(ctx,&nsObj)
```

Forth, in your test you can lookup the namespace and casting to a string

```go
namespace := ctx.Value(GetNamespaceKey(t)).(string)
```

So, tying it all together, the `TestMain` looks like this:

```go
func TestMain(m *testing.M) {
testenv = env.New()
testenv = env.New()

// Specifying a run ID so that multiple runs wouldn't collide.
runID := envconf.RandomName("", 4)
// Specifying a run ID so that multiple runs wouldn't collide.
runID := envconf.RandomName("", 4)

/* Skipping cluster creation for brevity */
testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return createNSForTest(ctx, cfg, t, runID)
})
testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return deleteNSForTest(ctx, cfg, t, runID)
})
/* Skipping cluster creation for brevity */
testenv.BeforeEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return createNSForTest(ctx, cfg, t, runID)
})
testenv.AfterEachTest(func(ctx context.Context, cfg *envconf.Config, t *testing.T) (context.Context, error) {
return deleteNSForTest(ctx, cfg, t, runID)
})

os.Exit(testenv.Run(m))
os.Exit(testenv.Run(m))
}
```
```
10 changes: 4 additions & 6 deletions examples/every_test_custom_ns/k8s_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,14 @@ import (

func TestListPods(t *testing.T) {
f := features.New("pod list").
Assess("pods from kube-system", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
Assess("pods from namespace", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
var pods corev1.PodList
err := cfg.Client().Resources("kube-system").List(context.TODO(), &pods)
namespace := ctx.Value(GetNamespaceKey(t)).(string)
err := cfg.Client().Resources(namespace).List(context.TODO(), &pods)
if err != nil {
t.Fatal(err)
}
t.Logf("found %d pods", len(pods.Items))
if len(pods.Items) == 0 {
t.Fatal("no pods in namespace kube-system")
}
t.Logf("found %d pods in namespace %s", len(pods.Items), namespace)
return ctx
})

Expand Down
26 changes: 20 additions & 6 deletions examples/every_test_custom_ns/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"fmt"
"os"
"strings"
"testing"
"time"

Expand All @@ -29,6 +30,9 @@ import (
"sigs.k8s.io/e2e-framework/support/kind"
)

type NamespaceCtxKey string
type ClusterCtxKey string

var testenv env.Environment

func TestMain(m *testing.M) {
Expand All @@ -53,11 +57,14 @@ func TestMain(m *testing.M) {
cfg.WithKubeconfigFile(kubeconfig)

// propagate cluster value
return context.WithValue(ctx, "cluster", cluster), nil
return context.WithValue(ctx, ClusterCtxKey("cluster"), cluster), nil
}).Finish(
// Teardown func: delete kind cluster
func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
cluster := ctx.Value("cluster").(*kind.Cluster) // nil should be tested
cluster := ctx.Value(ClusterCtxKey("cluster")).(*kind.Cluster) // nil should be tested
if cluster == nil {
return ctx, fmt.Errorf("error getting kind cluster from context")
}
if err := cluster.Destroy(); err != nil {
return ctx, err
}
Expand All @@ -79,7 +86,7 @@ func TestMain(m *testing.M) {
// so that the deleteNSForTest routine can look it up and delete it.
func createNSForTest(ctx context.Context, cfg *envconf.Config, t *testing.T, runID string) (context.Context, error) {
ns := envconf.RandomName(runID, 10)
ctx = context.WithValue(ctx, nsKey(t), ns)
ctx = context.WithValue(ctx, GetNamespaceKey(t), ns)

t.Logf("Creating NS %v for test %v", ns, t.Name())
nsObj := v1.Namespace{}
Expand All @@ -89,14 +96,21 @@ func createNSForTest(ctx context.Context, cfg *envconf.Config, t *testing.T, run

// DeleteNSForTest looks up the namespace corresponding to the given test and deletes it.
func deleteNSForTest(ctx context.Context, cfg *envconf.Config, t *testing.T, runID string) (context.Context, error) {
ns := fmt.Sprint(ctx.Value(nsKey(t)))
ns := fmt.Sprint(ctx.Value(GetNamespaceKey(t)))
t.Logf("Deleting NS %v for test %v", ns, t.Name())

nsObj := v1.Namespace{}
nsObj.Name = ns
return ctx, cfg.Client().Resources().Delete(ctx, &nsObj)
}

func nsKey(t *testing.T) string {
return "NS-for-%v" + t.Name()
// GetNamespaceKey returns the context key for a given test
func GetNamespaceKey(t *testing.T) NamespaceCtxKey {
// When we pass t.Name() from inside an `assess` step, the name is in the form TestName/Features/Assess
if strings.Contains(t.Name(), "/") {
return NamespaceCtxKey(strings.Split(t.Name(), "/")[0])
}

// When pass t.Name() from inside a `testenv.BeforeEachTest` function, the name is just TestName
return NamespaceCtxKey(t.Name())
}

0 comments on commit 75e43ce

Please sign in to comment.