knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/reconciler/testing/hooks_test.go (about)

     1  /*
     2  Copyright 2019 The Knative Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package testing
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"log"
    23  	"testing"
    24  	"time"
    25  
    26  	v1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/client-go/kubernetes/fake"
    30  )
    31  
    32  func ExampleHooks() {
    33  	h := NewHooks()
    34  	f := fake.NewSimpleClientset()
    35  
    36  	h.OnCreate(&f.Fake, "pods", func(obj runtime.Object) HookResult {
    37  		pod := obj.(*v1.Pod)
    38  		fmt.Printf("Pod %s has restart policy %v\n", pod.Name, pod.Spec.RestartPolicy)
    39  		return true
    40  	})
    41  
    42  	h.OnUpdate(&f.Fake, "pods", func(obj runtime.Object) HookResult {
    43  		pod := obj.(*v1.Pod)
    44  		fmt.Printf("Pod %s restart policy was updated to %v\n", pod.Name, pod.Spec.RestartPolicy)
    45  		return true
    46  	})
    47  
    48  	h.OnDelete(&f.Fake, "pods", func(name string) HookResult {
    49  		fmt.Printf("Pod %s was deleted\n", name)
    50  		return true
    51  	})
    52  
    53  	pod := &v1.Pod{
    54  		ObjectMeta: metav1.ObjectMeta{
    55  			Name: "test-pod",
    56  		},
    57  		Spec: v1.PodSpec{
    58  			RestartPolicy: v1.RestartPolicyAlways,
    59  		},
    60  	}
    61  	f.CoreV1().Pods("test").Create(context.Background(), pod, metav1.CreateOptions{})
    62  
    63  	updatedPod := pod.DeepCopy()
    64  	updatedPod.Spec.RestartPolicy = v1.RestartPolicyNever
    65  	f.CoreV1().Pods("test").Update(context.Background(), updatedPod, metav1.UpdateOptions{})
    66  
    67  	f.CoreV1().Pods("test").Delete(context.Background(), pod.Name, metav1.DeleteOptions{})
    68  	if err := h.WaitForHooks(time.Second); err != nil {
    69  		log.Fatal(err)
    70  	}
    71  
    72  	// Output:
    73  	// Pod test-pod has restart policy Always
    74  	// Pod test-pod restart policy was updated to Never
    75  	// Pod test-pod was deleted
    76  }
    77  
    78  func TestWaitWithoutHooks(t *testing.T) {
    79  	h := NewHooks()
    80  	if err := h.WaitForHooks(time.Second); err != nil {
    81  		t.Error("Expected no error without hooks, but got:", err)
    82  	}
    83  }
    84  
    85  func TestWaitTimeout(t *testing.T) {
    86  	h := NewHooks()
    87  	f := fake.NewSimpleClientset()
    88  
    89  	h.OnCreate(&f.Fake, "pods", func(obj runtime.Object) HookResult {
    90  		return true
    91  	})
    92  
    93  	err := h.WaitForHooks(time.Millisecond)
    94  	if err == nil {
    95  		t.Error("expected uncalled hook to cause a timeout error")
    96  	}
    97  }
    98  
    99  func TestWaitPartialCompletion(t *testing.T) {
   100  	h := NewHooks()
   101  	f := fake.NewSimpleClientset()
   102  
   103  	createCalled := false
   104  	h.OnCreate(&f.Fake, "pods", func(obj runtime.Object) HookResult {
   105  		createCalled = true
   106  		return true
   107  	})
   108  
   109  	h.OnUpdate(&f.Fake, "pods", func(obj runtime.Object) HookResult {
   110  		return true
   111  	})
   112  
   113  	pod := &v1.Pod{
   114  		ObjectMeta: metav1.ObjectMeta{
   115  			Name: "test-pod",
   116  		},
   117  		Spec: v1.PodSpec{
   118  			RestartPolicy: v1.RestartPolicyAlways,
   119  		},
   120  	}
   121  	f.CoreV1().Pods("test").Create(context.Background(), pod, metav1.CreateOptions{})
   122  
   123  	err := h.WaitForHooks(time.Millisecond)
   124  	if err == nil {
   125  		t.Error("expected uncalled hook to cause a timeout error")
   126  	}
   127  	if createCalled == false {
   128  		t.Error("expected create hook to be called")
   129  	}
   130  }
   131  
   132  func TestMultiUpdate(t *testing.T) {
   133  	h := NewHooks()
   134  	f := fake.NewSimpleClientset()
   135  
   136  	updates := 0
   137  	h.OnUpdate(&f.Fake, "pods", func(obj runtime.Object) HookResult {
   138  		updates++
   139  		switch updates {
   140  		case 1:
   141  		case 2:
   142  			return HookComplete
   143  		}
   144  		return HookIncomplete
   145  	})
   146  
   147  	pod := &v1.Pod{
   148  		ObjectMeta: metav1.ObjectMeta{
   149  			Name: "test-pod",
   150  		},
   151  		Spec: v1.PodSpec{
   152  			RestartPolicy: v1.RestartPolicyAlways,
   153  		},
   154  	}
   155  	f.CoreV1().Pods("test").Create(context.Background(), pod, metav1.CreateOptions{})
   156  
   157  	updatedPod := pod.DeepCopy()
   158  	updatedPod.Spec.RestartPolicy = v1.RestartPolicyNever
   159  	f.CoreV1().Pods("test").Update(context.Background(), updatedPod, metav1.UpdateOptions{})
   160  
   161  	updatedPod = pod.DeepCopy()
   162  	updatedPod.Spec.RestartPolicy = v1.RestartPolicyAlways
   163  	f.CoreV1().Pods("test").Update(context.Background(), updatedPod, metav1.UpdateOptions{})
   164  
   165  	f.CoreV1().Pods("test").Delete(context.Background(), pod.Name, metav1.DeleteOptions{})
   166  	if err := h.WaitForHooks(time.Second); err != nil {
   167  		t.Error(err)
   168  	}
   169  
   170  	if updates != 2 {
   171  		t.Error("Unexpected number of Update events; want 2, got", updates)
   172  	}
   173  }
   174  
   175  func TestWaitNoExecutionAfterWait(t *testing.T) {
   176  	h := NewHooks()
   177  	f := fake.NewSimpleClientset()
   178  
   179  	createCalled := false
   180  	h.OnCreate(&f.Fake, "pods", func(obj runtime.Object) HookResult {
   181  		createCalled = true
   182  		return true
   183  	})
   184  
   185  	pod := &v1.Pod{
   186  		ObjectMeta: metav1.ObjectMeta{
   187  			Name: "test-pod",
   188  		},
   189  		Spec: v1.PodSpec{
   190  			RestartPolicy: v1.RestartPolicyAlways,
   191  		},
   192  	}
   193  	err := h.WaitForHooks(time.Millisecond)
   194  
   195  	f.CoreV1().Pods("test").Create(context.Background(), pod, metav1.CreateOptions{})
   196  
   197  	if err == nil {
   198  		t.Error("expected uncalled hook to cause a timeout error")
   199  	}
   200  	if createCalled == true {
   201  		t.Error("expected create hook not to be called")
   202  	}
   203  }