Skip to content

Commit 23a6ed2

Browse files
committed
e2e test fix
1 parent de8defb commit 23a6ed2

File tree

13 files changed

+415
-485
lines changed

13 files changed

+415
-485
lines changed

cmd/server/app/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ func (p *Proxy) Run(o *options.ProxyRunOptions, stopCh <-chan struct{}) error {
168168
)
169169
klog.V(1).Infoln("Starting lease acquisition and garbage collection controller.")
170170
leaseController.Run(ctx)
171+
defer leaseController.Stop()
171172
}
172173

173174
klog.V(1).Infoln("Starting admin server for debug connections.")

e2e/lease_count_test.go

Lines changed: 73 additions & 293 deletions
Large diffs are not rendered by default.

e2e/main_test.go

Lines changed: 147 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"context"
66
"flag"
77
"fmt"
8+
"io"
89
"log"
910
"os"
1011
"path"
@@ -13,9 +14,14 @@ import (
1314
"time"
1415

1516
appsv1api "k8s.io/api/apps/v1"
17+
corev1 "k8s.io/api/core/v1"
18+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
19+
"k8s.io/apimachinery/pkg/labels"
1620
"k8s.io/apimachinery/pkg/runtime/schema"
21+
"k8s.io/client-go/kubernetes"
1722
"k8s.io/client-go/kubernetes/scheme"
1823
"sigs.k8s.io/controller-runtime/pkg/client"
24+
"sigs.k8s.io/e2e-framework/klient/k8s"
1925
"sigs.k8s.io/e2e-framework/klient/wait"
2026
"sigs.k8s.io/e2e-framework/klient/wait/conditions"
2127
"sigs.k8s.io/e2e-framework/pkg/env"
@@ -48,7 +54,7 @@ func TestMain(m *testing.M) {
4854
kindCluster := kind.NewCluster(kindClusterName).WithOpts(kind.WithImage(*kindImage))
4955

5056
testenv.Setup(
51-
envfuncs.CreateCluster(kindCluster, kindClusterName),
57+
envfuncs.CreateClusterWithConfig(kindCluster, kindClusterName, "templates/kind.config"),
5258
envfuncs.LoadImageToCluster(kindClusterName, *agentImage),
5359
envfuncs.LoadImageToCluster(kindClusterName, *serverImage),
5460
renderAndApplyManifests,
@@ -84,15 +90,16 @@ func renderTemplate(file string, params any) (client.Object, *schema.GroupVersio
8490
return obj.(client.Object), gvk, nil
8591
}
8692

87-
type KeyValue struct {
88-
Key string
89-
Value string
93+
type CLIFlag struct {
94+
Flag string
95+
Value string
96+
EmptyValue bool
9097
}
9198

9299
type DeploymentConfig struct {
93100
Replicas int
94101
Image string
95-
Args []KeyValue
102+
Args []CLIFlag
96103
}
97104

98105
func renderAndApplyManifests(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
@@ -111,10 +118,6 @@ func renderAndApplyManifests(ctx context.Context, cfg *envconf.Config) (context.
111118
if err != nil {
112119
return ctx, err
113120
}
114-
agentService, _, err := renderTemplate("agent/service.yaml", struct{}{})
115-
if err != nil {
116-
return ctx, err
117-
}
118121

119122
// Submit agent RBAC templates to k8s.
120123
err = client.Resources().Create(ctx, agentServiceAccount)
@@ -129,10 +132,6 @@ func renderAndApplyManifests(ctx context.Context, cfg *envconf.Config) (context.
129132
if err != nil {
130133
return ctx, err
131134
}
132-
err = client.Resources().Create(ctx, agentService)
133-
if err != nil {
134-
return ctx, err
135-
}
136135

137136
// Render server RBAC and Service templates.
138137
serverClusterRoleBinding, _, err := renderTemplate("server/clusterrolebinding.yaml", struct{}{})
@@ -157,50 +156,172 @@ func renderAndApplyManifests(ctx context.Context, cfg *envconf.Config) (context.
157156
return ctx, nil
158157
}
159158

160-
func deployAndWaitForDeployment(obj client.Object) func(context.Context, *testing.T, *envconf.Config) context.Context {
159+
func createDeployment(obj client.Object) func(context.Context, *testing.T, *envconf.Config) context.Context {
161160
return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
162-
client := cfg.Client()
163-
err := client.Resources().Create(ctx, obj)
161+
deployment, ok := obj.(*appsv1api.Deployment)
162+
if !ok {
163+
t.Fatalf("object %q is not a deployment", obj.GetName())
164+
}
165+
166+
err := cfg.Client().Resources(deployment.Namespace).Create(ctx, deployment)
167+
if err != nil {
168+
t.Fatalf("could not create deployment %q: %v", deployment.Name, err)
169+
}
170+
171+
newDeployment := &appsv1api.Deployment{}
172+
err = cfg.Client().Resources(deployment.Namespace).Get(ctx, deployment.Name, deployment.Namespace, newDeployment)
173+
if err != nil {
174+
t.Fatalf("could not get deployment %q after creation: %v", deployment.Name, err)
175+
}
176+
177+
return ctx
178+
}
179+
}
180+
181+
func deleteDeployment(obj client.Object) func(context.Context, *testing.T, *envconf.Config) context.Context {
182+
return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
183+
deployment, ok := obj.(*appsv1api.Deployment)
184+
if !ok {
185+
t.Fatalf("object %q is not a deployment", obj.GetName())
186+
}
187+
188+
k8sClient := kubernetes.NewForConfigOrDie(cfg.Client().RESTConfig())
189+
pods, err := k8sClient.CoreV1().Pods(deployment.Namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.FormatLabels(deployment.Spec.Selector.MatchLabels)})
164190
if err != nil {
165-
t.Fatalf("could not create Deployment: %v", err)
191+
t.Fatalf("could not get pods for deployment %q: %v", deployment.Name, err)
166192
}
167193

194+
cfg.Client().Resources(deployment.Namespace).Delete(ctx, deployment)
195+
168196
err = wait.For(
169-
conditions.New(client.Resources()).DeploymentAvailable(obj.GetName(), obj.GetNamespace()),
170-
wait.WithTimeout(1*time.Minute),
171-
wait.WithInterval(10*time.Second),
197+
conditions.New(cfg.Client().Resources(deployment.Namespace)).ResourcesDeleted(pods),
198+
wait.WithTimeout(60*time.Second),
199+
wait.WithInterval(5*time.Second),
200+
)
201+
if err != nil {
202+
pods, err := k8sClient.CoreV1().Pods(deployment.Namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.FormatLabels(deployment.Spec.Selector.MatchLabels)})
203+
if err != nil {
204+
t.Fatalf("could not get pods for deployment %q: %v", deployment.Name, err)
205+
}
206+
207+
for _, pod := range pods.Items {
208+
logs, err := dumpPodLogs(ctx, k8sClient, pod.Namespace, pod.Name)
209+
if err != nil {
210+
t.Fatalf("could not dump logs for pod %q: %v", pod.Name, err)
211+
}
212+
t.Errorf("logs for pod %q: %v", pod.Name, logs)
213+
}
214+
t.Fatalf("waiting for deletion of pods for deployment %q failed, dumped pod logs", deployment.Name)
215+
}
216+
217+
return ctx
218+
}
219+
}
220+
221+
func sleepFor(duration time.Duration) func(context.Context, *testing.T, *envconf.Config) context.Context {
222+
return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
223+
time.Sleep(duration)
224+
return ctx
225+
}
226+
}
227+
228+
func waitForDeployment(obj client.Object) func(context.Context, *testing.T, *envconf.Config) context.Context {
229+
return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
230+
deployment, ok := obj.(*appsv1api.Deployment)
231+
if !ok {
232+
t.Fatalf("object %q is not a deployment", obj.GetName())
233+
}
234+
235+
k8sClient := kubernetes.NewForConfigOrDie(cfg.Client().RESTConfig())
236+
err := wait.For(
237+
conditions.New(cfg.Client().Resources(deployment.Namespace)).DeploymentAvailable(deployment.Name, deployment.Namespace),
238+
wait.WithTimeout(60*time.Second),
239+
wait.WithInterval(5*time.Second),
172240
)
173241
if err != nil {
174-
t.Fatalf("waiting for Deployment failed: %v", err)
242+
pods, err := k8sClient.CoreV1().Pods(deployment.Namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.FormatLabels(deployment.Spec.Selector.MatchLabels)})
243+
if err != nil {
244+
t.Fatalf("could not get pods for deployment %q: %v", deployment.Name, err)
245+
}
246+
247+
for _, pod := range pods.Items {
248+
if isPodReady(&pod) {
249+
continue
250+
}
251+
252+
logs, err := dumpPodLogs(ctx, k8sClient, pod.Namespace, pod.Name)
253+
if err != nil {
254+
t.Fatalf("could not dump logs for pod %q: %v", pod.Name, err)
255+
}
256+
t.Errorf("logs for pod %q: %v", pod.Name, logs)
257+
}
258+
t.Fatalf("waiting for deployment %q failed, dumped pod logs", deployment.Name)
175259
}
176260

177261
return ctx
178262
}
179263
}
180264

265+
func isPodReady(pod *corev1.Pod) bool {
266+
for _, condition := range pod.Status.Conditions {
267+
if condition.Type == corev1.PodReady {
268+
return condition.Status == corev1.ConditionTrue
269+
}
270+
}
271+
return false
272+
}
273+
274+
func dumpPodLogs(ctx context.Context, k8sClient kubernetes.Interface, namespace, name string) (string, error) {
275+
req := k8sClient.CoreV1().Pods(namespace).GetLogs(name, &corev1.PodLogOptions{})
276+
podLogs, err := req.Stream(ctx)
277+
if err != nil {
278+
return "", fmt.Errorf("could not stream logs for pod %q in namespace %q: %w", name, namespace, err)
279+
}
280+
defer podLogs.Close()
281+
282+
b, err := io.ReadAll(podLogs)
283+
if err != nil {
284+
return "", fmt.Errorf("could not read logs for pod %q in namespace %q from stream: %w", name, namespace, err)
285+
}
286+
287+
return string(b), nil
288+
}
289+
181290
func scaleDeployment(obj client.Object, replicas int) func(context.Context, *testing.T, *envconf.Config) context.Context {
182291
return func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
183292
deployment, ok := obj.(*appsv1api.Deployment)
184293
if !ok {
185294
t.Fatalf("provided object is not a deployment")
186295
}
187296

297+
err := cfg.Client().Resources().Get(ctx, deployment.Name, deployment.Namespace, deployment)
298+
if err != nil {
299+
t.Fatalf("could not get Deployment to update (name: %q, namespace: %q): %v", deployment.Name, deployment.Namespace, err)
300+
}
301+
188302
newReplicas := int32(replicas)
189303
deployment.Spec.Replicas = &newReplicas
190304

191305
client := cfg.Client()
192-
err := client.Resources().Update(ctx, deployment)
306+
err = client.Resources().Update(ctx, deployment)
193307
if err != nil {
194308
t.Fatalf("could not update Deployment replicas: %v", err)
195309
}
196310

197311
err = wait.For(
198-
conditions.New(client.Resources()).DeploymentAvailable(deployment.GetName(), deployment.GetNamespace()),
199-
wait.WithTimeout(1*time.Minute),
200-
wait.WithInterval(10*time.Second),
312+
conditions.New(cfg.Client().Resources(deployment.Namespace)).ResourceScaled(deployment, func(obj k8s.Object) int32 {
313+
deployment, ok := obj.(*appsv1api.Deployment)
314+
if !ok {
315+
t.Fatalf("provided object is not a deployment")
316+
}
317+
318+
return deployment.Status.AvailableReplicas
319+
}, int32(replicas)),
320+
wait.WithTimeout(60*time.Second),
321+
wait.WithInterval(5*time.Second),
201322
)
202323
if err != nil {
203-
t.Fatalf("waiting for Deployment failed: %v", err)
324+
t.Fatalf("waiting for deployment %q to scale failed", deployment.Name)
204325
}
205326

206327
return ctx

0 commit comments

Comments
 (0)