Skip to content

Commit

Permalink
Merge pull request #86177 from deads2k/configure-test
Browse files Browse the repository at this point in the history
make test framework easier to re-use
  • Loading branch information
k8s-ci-robot committed Dec 13, 2019
2 parents 873356c + 773fbea commit 5b77616
Showing 1 changed file with 52 additions and 6 deletions.
58 changes: 52 additions & 6 deletions test/e2e/framework/framework.go
Expand Up @@ -30,6 +30,8 @@ import (
"sync"
"time"

"k8s.io/apimachinery/pkg/runtime"

v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -71,6 +73,7 @@ type Framework struct {
// test multiple times in parallel.
UniqueName string

clientConfig *rest.Config
ClientSet clientset.Interface
KubemarkExternalClusterClientSet clientset.Interface

Expand Down Expand Up @@ -102,6 +105,11 @@ type Framework struct {
// should abort, the AfterSuite hook should run all Cleanup actions.
cleanupHandle CleanupActionHandle

// afterEaches is a map of name to function to be called after each test. These are not
// cleared. The call order is randomized so that no dependencies can grow between
// the various afterEaches
afterEaches map[string]AfterEachActionFunc

// configuration for framework's client
Options Options

Expand All @@ -113,6 +121,9 @@ type Framework struct {
clusterAutoscalerMetricsBeforeTest e2emetrics.Collection
}

// AfterEachActionFunc is a function that can be called after each test
type AfterEachActionFunc func(f *Framework, failed bool)

// TestDataSummary is an interface for managing test data.
type TestDataSummary interface {
SummaryKind() string
Expand Down Expand Up @@ -146,6 +157,20 @@ func NewFramework(baseName string, options Options, client clientset.Interface)
ClientSet: client,
}

f.AddAfterEach("dumpNamespaceInfo", func(f *Framework, failed bool) {
if !failed {
return
}
if !TestContext.DumpLogsOnFailure {
return
}
if !f.SkipNamespaceCreation {
for _, ns := range f.namespacesToDelete {
DumpAllNamespaceInfo(f.ClientSet, ns.Name)
}
}
})

ginkgo.BeforeEach(f.BeforeEach)
ginkgo.AfterEach(f.AfterEach)

Expand All @@ -170,6 +195,7 @@ func (f *Framework) BeforeEach() {
if TestContext.KubeAPIContentType != "" {
config.ContentType = TestContext.KubeAPIContentType
}
f.clientConfig = rest.CopyConfig(config)
f.ClientSet, err = clientset.NewForConfig(config)
ExpectNoError(err)
f.DynamicClient, err = dynamic.NewForConfig(config)
Expand Down Expand Up @@ -315,6 +341,19 @@ func printSummaries(summaries []TestDataSummary, testBaseName string) {
}
}

// AddAfterEach is a way to add a function to be called after every test. The execution order is intentionally random
// to avoid growing dependencies. If you register the same name twice, it is a coding error and will panic.
func (f *Framework) AddAfterEach(name string, fn AfterEachActionFunc) {
if _, ok := f.afterEaches[name]; ok {
panic(fmt.Sprintf("%q is already registered", name))
}

if f.afterEaches == nil {
f.afterEaches = map[string]AfterEachActionFunc{}
}
f.afterEaches[name] = fn
}

// AfterEach deletes the namespace, after reading its events.
func (f *Framework) AfterEach() {
RemoveCleanupAction(f.cleanupHandle)
Expand Down Expand Up @@ -352,6 +391,7 @@ func (f *Framework) AfterEach() {

// Paranoia-- prevent reuse!
f.Namespace = nil
f.clientConfig = nil
f.ClientSet = nil
f.namespacesToDelete = nil

Expand All @@ -365,12 +405,9 @@ func (f *Framework) AfterEach() {
}
}()

// Print events if the test failed.
if ginkgo.CurrentGinkgoTestDescription().Failed && TestContext.DumpLogsOnFailure {
// Pass both unversioned client and versioned clientset, till we have removed all uses of the unversioned client.
if !f.SkipNamespaceCreation {
DumpAllNamespaceInfo(f.ClientSet, f.Namespace.Name)
}
// run all aftereach functions in random order to ensure no dependencies grow
for _, afterEachFn := range f.afterEaches {
afterEachFn(f, ginkgo.CurrentGinkgoTestDescription().Failed)
}

if TestContext.GatherKubeSystemResourceUsageData != "false" && TestContext.GatherKubeSystemResourceUsageData != "none" && f.gatherer != nil {
Expand Down Expand Up @@ -490,6 +527,15 @@ func (f *Framework) WaitForPodNoLongerRunning(podName string) error {
return e2epod.WaitForPodNoLongerRunningInNamespace(f.ClientSet, podName, f.Namespace.Name)
}

// ClientConfig an externally accessible method for reading the kube client config.
func (f *Framework) ClientConfig() *rest.Config {
ret := rest.CopyConfig(f.clientConfig)
// json is least common denominator
ret.ContentType = runtime.ContentTypeJSON
ret.AcceptContentTypes = runtime.ContentTypeJSON
return ret
}

// TestContainerOutput runs the given pod in the given namespace and waits
// for all of the containers in the podSpec to move into the 'Success' status, and tests
// the specified container log against the given expected output using a substring matcher.
Expand Down

0 comments on commit 5b77616

Please sign in to comment.