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 }