Skip to content

Commit f39df71

Browse files
committed
Clean up envtest when it cannot start locally
When CRDs are invalid, envtest returns an error after starting etcd and kube-apiserver. These are cleaned up now. After that, tests that need Kubernetes skip rather than starting and stopping envtest over and over.
1 parent 71b7c08 commit f39df71

File tree

1 file changed

+49
-36
lines changed

1 file changed

+49
-36
lines changed

internal/testing/require/kubernetes.go

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ var kubernetes struct {
5858
// Count references to the started Environment.
5959
count int
6060
env *envtest.Environment
61+
err error
6162
}
6263

6364
// Kubernetes starts or connects to a Kubernetes API and returns a client that uses it.
@@ -118,44 +119,50 @@ func kubernetes3(t TestingT) (*envtest.Environment, client.Client) {
118119
t.SkipNow()
119120
}
120121

121-
frames := func() *goruntime.Frames {
122-
var pcs [5]uintptr
123-
n := goruntime.Callers(2, pcs[:])
124-
return goruntime.CallersFrames(pcs[0:n])
125-
}()
126-
127-
// Calculate the project directory as reported by [goruntime.CallersFrames].
128-
frame, ok := frames.Next()
129-
self := frame.File
130-
root := strings.TrimSuffix(self,
131-
filepath.Join("internal", "testing", "require", "kubernetes.go"))
132-
133-
// Find the first caller that is not in this file.
134-
for ok && frame.File == self {
135-
frame, ok = frames.Next()
136-
}
137-
caller := frame.File
138-
139-
// Calculate the project directory path relative to the caller.
140-
base, err := filepath.Rel(filepath.Dir(caller), root)
141-
assert.NilError(t, err)
142-
143-
// Calculate the snapshotter module directory path relative to the project directory.
144-
var snapshotter string
145-
if pkgs, err := packages.Load(
146-
&packages.Config{Mode: packages.NeedModule},
147-
"github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1",
148-
); assert.Check(t,
149-
err == nil && len(pkgs) > 0 && pkgs[0].Module != nil, "got %v\n%#v", err, pkgs,
150-
) {
151-
snapshotter, err = filepath.Rel(root, pkgs[0].Module.Dir)
152-
assert.NilError(t, err)
153-
}
154-
155122
kubernetes.Lock()
156123
defer kubernetes.Unlock()
157124

125+
// Skip any remaining tests after the environment fails to start once.
126+
// The test that tried to start the environment has reported the error.
127+
if kubernetes.err != nil {
128+
t.SkipNow()
129+
}
130+
158131
if kubernetes.env == nil {
132+
// Get the current call stack, minus the closure below.
133+
frames := func() *goruntime.Frames {
134+
var pcs [5]uintptr
135+
n := goruntime.Callers(2, pcs[:])
136+
return goruntime.CallersFrames(pcs[0:n])
137+
}()
138+
139+
// Calculate the project directory as reported by [goruntime.CallersFrames].
140+
frame, ok := frames.Next()
141+
self := frame.File
142+
root := strings.TrimSuffix(self,
143+
filepath.Join("internal", "testing", "require", "kubernetes.go"))
144+
145+
// Find the first caller that is not in this file.
146+
for ok && frame.File == self {
147+
frame, ok = frames.Next()
148+
}
149+
caller := frame.File
150+
151+
// Calculate the project directory path relative to the caller.
152+
base := Value(filepath.Rel(filepath.Dir(caller), root))
153+
154+
// Calculate the snapshotter module directory path relative to the project directory.
155+
var snapshotter string
156+
if pkgs, err := packages.Load(
157+
&packages.Config{Mode: packages.NeedModule},
158+
"github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1",
159+
); assert.Check(t,
160+
err == nil && len(pkgs) > 0 && pkgs[0].Module != nil, "got %v\n%#v", err, pkgs,
161+
) {
162+
snapshotter, err = filepath.Rel(root, pkgs[0].Module.Dir)
163+
assert.NilError(t, err)
164+
}
165+
159166
env := EnvTest(t, envtest.CRDInstallOptions{
160167
ErrorIfPathMissing: true,
161168
Paths: []string{
@@ -165,8 +172,13 @@ func kubernetes3(t TestingT) (*envtest.Environment, client.Client) {
165172
Scheme: runtime.Scheme,
166173
})
167174

168-
_, err := env.Start()
169-
assert.NilError(t, err)
175+
// There are multiple components in an environment; stop them all when any fail to start.
176+
// Keep the error so other tests know not to try again.
177+
_, kubernetes.err = env.Start()
178+
if kubernetes.err != nil {
179+
assert.Check(t, env.Stop())
180+
assert.NilError(t, kubernetes.err)
181+
}
170182

171183
kubernetes.env = env
172184
}
@@ -182,6 +194,7 @@ func kubernetes3(t TestingT) (*envtest.Environment, client.Client) {
182194
if kubernetes.count == 0 {
183195
assert.Check(t, kubernetes.env.Stop())
184196
kubernetes.env = nil
197+
kubernetes.err = nil
185198
}
186199
})
187200

0 commit comments

Comments
 (0)