mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +00:00
e2e: Call AfterEach handlers in case of an abort
I was tired of aborted tests leaving debris in my cluster.
This commit is contained in:
parent
24b33964c9
commit
677d4d6dbc
@ -22,6 +22,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -189,12 +190,54 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
type CleanupActionHandle *int
|
||||||
|
|
||||||
|
var cleanupActionsLock sync.Mutex
|
||||||
|
var cleanupActions = map[CleanupActionHandle]func(){}
|
||||||
|
|
||||||
|
// AddCleanupAction installs a function that will be called in the event of the
|
||||||
|
// whole test being terminated. This allows arbitrary pieces of the overall
|
||||||
|
// test to hook into SynchronizedAfterSuite().
|
||||||
|
func AddCleanupAction(fn func()) CleanupActionHandle {
|
||||||
|
p := CleanupActionHandle(new(int))
|
||||||
|
cleanupActionsLock.Lock()
|
||||||
|
defer cleanupActionsLock.Unlock()
|
||||||
|
cleanupActions[p] = fn
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveCleanupAction removes a function that was installed by
|
||||||
|
// AddCleanupAction.
|
||||||
|
func RemoveCleanupAction(p CleanupActionHandle) {
|
||||||
|
cleanupActionsLock.Lock()
|
||||||
|
defer cleanupActionsLock.Unlock()
|
||||||
|
delete(cleanupActions, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunCleanupActions runs all functions installed by AddCleanupAction. It does
|
||||||
|
// not remove them (see RemoveCleanupAction) but it does run unlocked, so they
|
||||||
|
// may remove themselves.
|
||||||
|
func RunCleanupActions() {
|
||||||
|
list := []func(){}
|
||||||
|
func() {
|
||||||
|
cleanupActionsLock.Lock()
|
||||||
|
defer cleanupActionsLock.Unlock()
|
||||||
|
for _, fn := range cleanupActions {
|
||||||
|
list = append(list, fn)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
// Run unlocked.
|
||||||
|
for _, fn := range list {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Similar to SynchornizedBeforeSuite, we want to run some operations only once (such as collecting cluster logs).
|
// Similar to SynchornizedBeforeSuite, we want to run some operations only once (such as collecting cluster logs).
|
||||||
// Here, the order of functions is reversed; first, the function which runs everywhere,
|
// Here, the order of functions is reversed; first, the function which runs everywhere,
|
||||||
// and then the function that only runs on the first Ginkgo node.
|
// and then the function that only runs on the first Ginkgo node.
|
||||||
var _ = ginkgo.SynchronizedAfterSuite(func() {
|
var _ = ginkgo.SynchronizedAfterSuite(func() {
|
||||||
// Run on all Ginkgo nodes
|
// Run on all Ginkgo nodes
|
||||||
|
RunCleanupActions()
|
||||||
}, func() {
|
}, func() {
|
||||||
// Run only Ginkgo on node 1
|
// Run only Ginkgo on node 1
|
||||||
if testContext.ReportDir != "" {
|
if testContext.ReportDir != "" {
|
||||||
|
@ -57,6 +57,11 @@ type Framework struct {
|
|||||||
logsSizeWaitGroup sync.WaitGroup
|
logsSizeWaitGroup sync.WaitGroup
|
||||||
logsSizeCloseChannel chan bool
|
logsSizeCloseChannel chan bool
|
||||||
logsSizeVerifier *LogsSizeVerifier
|
logsSizeVerifier *LogsSizeVerifier
|
||||||
|
|
||||||
|
// To make sure that this framework cleans up after itself, no matter what,
|
||||||
|
// we install a cleanup action before each test and clear it after. If we
|
||||||
|
// should abort, the AfterSuite hook should run all cleanup actions.
|
||||||
|
cleanupHandle CleanupActionHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestDataSummary interface {
|
type TestDataSummary interface {
|
||||||
@ -80,6 +85,10 @@ func NewFramework(baseName string) *Framework {
|
|||||||
|
|
||||||
// beforeEach gets a client and makes a namespace.
|
// beforeEach gets a client and makes a namespace.
|
||||||
func (f *Framework) beforeEach() {
|
func (f *Framework) beforeEach() {
|
||||||
|
// The fact that we need this feels like a bug in ginkgo.
|
||||||
|
// https://github.com/onsi/ginkgo/issues/222
|
||||||
|
f.cleanupHandle = AddCleanupAction(f.afterEach)
|
||||||
|
|
||||||
By("Creating a kubernetes client")
|
By("Creating a kubernetes client")
|
||||||
c, err := loadClient()
|
c, err := loadClient()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -121,6 +130,8 @@ func (f *Framework) beforeEach() {
|
|||||||
|
|
||||||
// afterEach deletes the namespace, after reading its events.
|
// afterEach deletes the namespace, after reading its events.
|
||||||
func (f *Framework) afterEach() {
|
func (f *Framework) afterEach() {
|
||||||
|
RemoveCleanupAction(f.cleanupHandle)
|
||||||
|
|
||||||
// Print events if the test failed.
|
// Print events if the test failed.
|
||||||
if CurrentGinkgoTestDescription().Failed {
|
if CurrentGinkgoTestDescription().Failed {
|
||||||
By(fmt.Sprintf("Collecting events from namespace %q.", f.Namespace.Name))
|
By(fmt.Sprintf("Collecting events from namespace %q.", f.Namespace.Name))
|
||||||
|
@ -54,6 +54,9 @@ const loadBalancerLagTimeout = 2 * time.Minute
|
|||||||
//TODO: once support ticket 21807001 is resolved, reduce this timeout back to something reasonable
|
//TODO: once support ticket 21807001 is resolved, reduce this timeout back to something reasonable
|
||||||
const loadBalancerCreateTimeout = 20 * time.Minute
|
const loadBalancerCreateTimeout = 20 * time.Minute
|
||||||
|
|
||||||
|
// How long to wait for a namespace to be deleted.
|
||||||
|
const namespaceDeleteTimeout = 5 * time.Minute
|
||||||
|
|
||||||
// This should match whatever the default/configured range is
|
// This should match whatever the default/configured range is
|
||||||
var ServiceNodePortRange = utilnet.PortRange{Base: 30000, Size: 2768}
|
var ServiceNodePortRange = utilnet.PortRange{Base: 30000, Size: 2768}
|
||||||
|
|
||||||
@ -73,7 +76,7 @@ var _ = Describe("Services", func() {
|
|||||||
if testContext.DeleteNamespace {
|
if testContext.DeleteNamespace {
|
||||||
for _, ns := range extraNamespaces {
|
for _, ns := range extraNamespaces {
|
||||||
By(fmt.Sprintf("Destroying namespace %v", ns))
|
By(fmt.Sprintf("Destroying namespace %v", ns))
|
||||||
if err := deleteNS(c, ns, 5*time.Minute /* namespace deletion timeout */); err != nil {
|
if err := deleteNS(c, ns, namespaceDeleteTimeout); err != nil {
|
||||||
Failf("Couldn't delete namespace %s: %s", ns, err)
|
Failf("Couldn't delete namespace %s: %s", ns, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user