github.com/kubeshop/testkube@v1.17.23/pkg/triggers/watcher.go (about) 1 package triggers 2 3 import ( 4 "context" 5 "strings" 6 "time" 7 8 "github.com/google/go-cmp/cmp" 9 appsv1 "k8s.io/api/apps/v1" 10 corev1 "k8s.io/api/core/v1" 11 networkingv1 "k8s.io/api/networking/v1" 12 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 "k8s.io/client-go/informers" 14 appsinformerv1 "k8s.io/client-go/informers/apps/v1" 15 coreinformerv1 "k8s.io/client-go/informers/core/v1" 16 networkinginformerv1 "k8s.io/client-go/informers/networking/v1" 17 "k8s.io/client-go/kubernetes" 18 "k8s.io/client-go/tools/cache" 19 20 executorv1 "github.com/kubeshop/testkube-operator/api/executor/v1" 21 testsourcev1 "github.com/kubeshop/testkube-operator/api/testsource/v1" 22 "github.com/kubeshop/testkube/pkg/tcl/testworkflowstcl/testworkflowprocessor/constants" 23 24 testsv3 "github.com/kubeshop/testkube-operator/api/tests/v3" 25 26 testsuitev3 "github.com/kubeshop/testkube-operator/api/testsuite/v3" 27 testtriggersv1 "github.com/kubeshop/testkube-operator/api/testtriggers/v1" 28 "github.com/kubeshop/testkube-operator/pkg/clientset/versioned" 29 "github.com/kubeshop/testkube-operator/pkg/informers/externalversions" 30 testkubeexecutorinformerv1 "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/executor/v1" 31 testkubeinformerv1 "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/tests/v1" 32 33 testkubeinformerv3 "github.com/kubeshop/testkube-operator/pkg/informers/externalversions/tests/v3" 34 "github.com/kubeshop/testkube-operator/pkg/validation/tests/v1/testtrigger" 35 "github.com/kubeshop/testkube/pkg/api/v1/testkube" 36 "github.com/kubeshop/testkube/pkg/executor" 37 cexecutor "github.com/kubeshop/testkube/pkg/executor/containerexecutor" 38 ) 39 40 type k8sInformers struct { 41 podInformers []coreinformerv1.PodInformer 42 deploymentInformers []appsinformerv1.DeploymentInformer 43 daemonsetInformers []appsinformerv1.DaemonSetInformer 44 statefulsetInformers []appsinformerv1.StatefulSetInformer 45 serviceInformers []coreinformerv1.ServiceInformer 46 ingressInformers []networkinginformerv1.IngressInformer 47 clusterEventInformers []coreinformerv1.EventInformer 48 configMapInformers []coreinformerv1.ConfigMapInformer 49 50 testTriggerInformer testkubeinformerv1.TestTriggerInformer 51 testSuiteInformer testkubeinformerv3.TestSuiteInformer 52 testInformer testkubeinformerv3.TestInformer 53 executorInformer testkubeexecutorinformerv1.ExecutorInformer 54 webhookInformer testkubeexecutorinformerv1.WebhookInformer 55 testSourceInformer testkubeinformerv1.TestSourceInformer 56 } 57 58 func newK8sInformers(clientset kubernetes.Interface, testKubeClientset versioned.Interface, 59 testkubeNamespace string, watcherNamespaces []string) *k8sInformers { 60 var k8sInformers k8sInformers 61 if len(watcherNamespaces) == 0 { 62 watcherNamespaces = append(watcherNamespaces, metav1.NamespaceAll) 63 } 64 65 for _, namespace := range watcherNamespaces { 66 f := informers.NewSharedInformerFactoryWithOptions(clientset, 0, informers.WithNamespace(namespace)) 67 k8sInformers.podInformers = append(k8sInformers.podInformers, f.Core().V1().Pods()) 68 k8sInformers.deploymentInformers = append(k8sInformers.deploymentInformers, f.Apps().V1().Deployments()) 69 k8sInformers.daemonsetInformers = append(k8sInformers.daemonsetInformers, f.Apps().V1().DaemonSets()) 70 k8sInformers.statefulsetInformers = append(k8sInformers.statefulsetInformers, f.Apps().V1().StatefulSets()) 71 k8sInformers.serviceInformers = append(k8sInformers.serviceInformers, f.Core().V1().Services()) 72 k8sInformers.ingressInformers = append(k8sInformers.ingressInformers, f.Networking().V1().Ingresses()) 73 k8sInformers.clusterEventInformers = append(k8sInformers.clusterEventInformers, f.Core().V1().Events()) 74 k8sInformers.configMapInformers = append(k8sInformers.configMapInformers, f.Core().V1().ConfigMaps()) 75 } 76 77 testkubeInformerFactory := externalversions.NewSharedInformerFactoryWithOptions( 78 testKubeClientset, 0, externalversions.WithNamespace(testkubeNamespace)) 79 k8sInformers.testTriggerInformer = testkubeInformerFactory.Tests().V1().TestTriggers() 80 k8sInformers.testSuiteInformer = testkubeInformerFactory.Tests().V3().TestSuites() 81 k8sInformers.testInformer = testkubeInformerFactory.Tests().V3().Tests() 82 k8sInformers.executorInformer = testkubeInformerFactory.Executor().V1().Executor() 83 k8sInformers.webhookInformer = testkubeInformerFactory.Executor().V1().Webhook() 84 k8sInformers.testSourceInformer = testkubeInformerFactory.Tests().V1().TestSource() 85 86 return &k8sInformers 87 } 88 89 func (s *Service) runWatcher(ctx context.Context, leaseChan chan bool) { 90 running := false 91 var stopChan chan struct{} 92 93 for { 94 select { 95 case <-ctx.Done(): 96 s.logger.Infof("trigger service: stopping watcher component: context finished") 97 if _, ok := <-stopChan; ok { 98 close(stopChan) 99 } 100 return 101 case leased := <-leaseChan: 102 if !leased { 103 if running { 104 s.logger.Infof("trigger service: instance %s in cluster %s lost lease", s.identifier, s.clusterID) 105 close(stopChan) 106 s.informers = nil 107 running = false 108 } 109 } else { 110 if !running { 111 s.logger.Infof("trigger service: instance %s in cluster %s acquired lease", s.identifier, s.clusterID) 112 s.informers = newK8sInformers(s.clientset, s.testKubeClientset, s.testkubeNamespace, s.watcherNamespaces) 113 stopChan = make(chan struct{}) 114 s.runInformers(ctx, stopChan) 115 running = true 116 } 117 } 118 } 119 } 120 } 121 122 func (s *Service) runInformers(ctx context.Context, stop <-chan struct{}) { 123 if s.informers == nil { 124 s.logger.Errorf("trigger service: error running k8s informers: informers are nil") 125 return 126 } 127 128 for i := range s.informers.podInformers { 129 s.informers.podInformers[i].Informer().AddEventHandler(s.podEventHandler(ctx)) 130 } 131 132 for i := range s.informers.deploymentInformers { 133 s.informers.deploymentInformers[i].Informer().AddEventHandler(s.deploymentEventHandler(ctx)) 134 } 135 136 for i := range s.informers.daemonsetInformers { 137 s.informers.daemonsetInformers[i].Informer().AddEventHandler(s.daemonSetEventHandler(ctx)) 138 } 139 140 for i := range s.informers.statefulsetInformers { 141 s.informers.statefulsetInformers[i].Informer().AddEventHandler(s.statefulSetEventHandler(ctx)) 142 } 143 144 for i := range s.informers.serviceInformers { 145 s.informers.serviceInformers[i].Informer().AddEventHandler(s.serviceEventHandler(ctx)) 146 } 147 148 for i := range s.informers.ingressInformers { 149 s.informers.ingressInformers[i].Informer().AddEventHandler(s.ingressEventHandler(ctx)) 150 } 151 152 for i := range s.informers.clusterEventInformers { 153 s.informers.clusterEventInformers[i].Informer().AddEventHandler(s.clusterEventEventHandler(ctx)) 154 } 155 156 for i := range s.informers.configMapInformers { 157 s.informers.configMapInformers[i].Informer().AddEventHandler(s.configMapEventHandler(ctx)) 158 } 159 160 s.informers.testTriggerInformer.Informer().AddEventHandler(s.testTriggerEventHandler()) 161 s.informers.testSuiteInformer.Informer().AddEventHandler(s.testSuiteEventHandler()) 162 s.informers.testInformer.Informer().AddEventHandler(s.testEventHandler()) 163 s.informers.executorInformer.Informer().AddEventHandler(s.executorEventHandler()) 164 s.informers.webhookInformer.Informer().AddEventHandler(s.webhookEventHandler()) 165 s.informers.testSourceInformer.Informer().AddEventHandler(s.testSourceEventHandler()) 166 167 s.logger.Debugf("trigger service: starting pod informers") 168 for i := range s.informers.podInformers { 169 go s.informers.podInformers[i].Informer().Run(stop) 170 } 171 172 s.logger.Debugf("trigger service: starting deployment informers") 173 for i := range s.informers.deploymentInformers { 174 go s.informers.deploymentInformers[i].Informer().Run(stop) 175 } 176 177 s.logger.Debugf("trigger service: starting daemonset informers") 178 for i := range s.informers.daemonsetInformers { 179 go s.informers.daemonsetInformers[i].Informer().Run(stop) 180 } 181 182 s.logger.Debugf("trigger service: starting statefulset informers") 183 for i := range s.informers.statefulsetInformers { 184 go s.informers.statefulsetInformers[i].Informer().Run(stop) 185 } 186 187 s.logger.Debugf("trigger service: starting service informers") 188 for i := range s.informers.serviceInformers { 189 go s.informers.serviceInformers[i].Informer().Run(stop) 190 } 191 192 s.logger.Debugf("trigger service: starting ingress informers") 193 for i := range s.informers.ingressInformers { 194 go s.informers.ingressInformers[i].Informer().Run(stop) 195 } 196 197 s.logger.Debugf("trigger service: starting cluster event informers") 198 for i := range s.informers.clusterEventInformers { 199 go s.informers.clusterEventInformers[i].Informer().Run(stop) 200 } 201 202 s.logger.Debugf("trigger service: starting config map informers") 203 for i := range s.informers.configMapInformers { 204 go s.informers.configMapInformers[i].Informer().Run(stop) 205 } 206 207 s.logger.Debugf("trigger service: starting test trigger informer") 208 go s.informers.testTriggerInformer.Informer().Run(stop) 209 s.logger.Debugf("trigger service: starting test suite informer") 210 go s.informers.testSuiteInformer.Informer().Run(stop) 211 s.logger.Debugf("trigger service: starting test informer") 212 go s.informers.testInformer.Informer().Run(stop) 213 s.logger.Debugf("trigger service: starting executor informer") 214 go s.informers.executorInformer.Informer().Run(stop) 215 s.logger.Debugf("trigger service: starting webhook informer") 216 go s.informers.webhookInformer.Informer().Run(stop) 217 s.logger.Debugf("trigger service: starting test source informer") 218 go s.informers.testSourceInformer.Informer().Run(stop) 219 } 220 221 func (s *Service) podEventHandler(ctx context.Context) cache.ResourceEventHandlerFuncs { 222 getConditions := func(object metav1.Object) func() ([]testtriggersv1.TestTriggerCondition, error) { 223 return func() ([]testtriggersv1.TestTriggerCondition, error) { 224 return getPodConditions(ctx, s.clientset, object) 225 } 226 } 227 getAddrress := func(object metav1.Object) func(c context.Context, delay time.Duration) (string, error) { 228 return func(c context.Context, delay time.Duration) (string, error) { 229 return getPodAdress(c, s.clientset, object, delay) 230 } 231 } 232 return cache.ResourceEventHandlerFuncs{ 233 AddFunc: func(obj any) { 234 pod, ok := obj.(*corev1.Pod) 235 if !ok { 236 s.logger.Errorf("failed to process create pod event due to it being an unexpected type, received type %+v", obj) 237 return 238 } 239 if inPast(pod.CreationTimestamp.Time, s.watchFromDate) { 240 s.logger.Debugf( 241 "trigger service: watcher component: no-op create trigger: pod %s/%s was created in the past", 242 pod.Namespace, pod.Name, 243 ) 244 return 245 } 246 s.logger.Debugf("trigger service: watcher component: emiting event: pod %s/%s created", pod.Namespace, pod.Name) 247 event := newWatcherEvent(testtrigger.EventCreated, pod, testtrigger.ResourcePod, 248 withConditionsGetter(getConditions(pod)), withAddressGetter(getAddrress(pod))) 249 if err := s.match(ctx, event); err != nil { 250 s.logger.Errorf("event matcher returned an error while matching create pod event: %v", err) 251 } 252 253 }, 254 UpdateFunc: func(oldObj, newObj any) { 255 oldPod, ok := oldObj.(*corev1.Pod) 256 if !ok { 257 s.logger.Errorf("failed to process update pod event due to it being an unexpected type, received type %+v", oldObj) 258 return 259 } 260 if inPast(oldPod.CreationTimestamp.Time, s.watchFromDate) { 261 s.logger.Debugf( 262 "trigger service: watcher component: no-op update trigger: pod %s/%s was updated in the past", 263 oldPod.Namespace, oldPod.Name, 264 ) 265 return 266 } 267 268 newPod, ok := newObj.(*corev1.Pod) 269 if !ok { 270 s.logger.Errorf("failed to process update pod event due to it being an unexpected type, received type %+v", newObj) 271 return 272 } 273 if inPast(newPod.CreationTimestamp.Time, s.watchFromDate) { 274 s.logger.Debugf( 275 "trigger service: watcher component: no-op update trigger: pod %s/%s was updated in the past", 276 newPod.Namespace, newPod.Name, 277 ) 278 return 279 } 280 if oldPod.Namespace == s.testkubeNamespace && oldPod.Labels["job-name"] != "" && oldPod.Labels[testkube.TestLabelTestName] != "" && 281 newPod.Namespace == s.testkubeNamespace && newPod.Labels["job-name"] != "" && newPod.Labels[testkube.TestLabelTestName] != "" && 282 !(strings.HasSuffix(oldPod.Name, cexecutor.ScraperPodSuffix) || strings.HasSuffix(newPod.Name, cexecutor.ScraperPodSuffix)) && 283 oldPod.Labels["job-name"] == newPod.Labels["job-name"] { 284 s.checkExecutionPodStatus(ctx, oldPod.Labels["job-name"], []*corev1.Pod{oldPod, newPod}) 285 } 286 }, 287 DeleteFunc: func(obj interface{}) { 288 pod, ok := obj.(*corev1.Pod) 289 if !ok { 290 s.logger.Errorf("failed to process delete pod event due to it being an unexpected type, received type %+v", obj) 291 return 292 } 293 s.logger.Debugf("trigger service: watcher component: emiting event: pod %s/%s deleted", pod.Namespace, pod.Name) 294 if pod.Namespace == s.testkubeNamespace && pod.Labels["job-name"] != "" && !strings.HasSuffix(pod.Name, cexecutor.ScraperPodSuffix) && 295 pod.Labels[testkube.TestLabelTestName] != "" { 296 s.checkExecutionPodStatus(ctx, pod.Labels["job-name"], []*corev1.Pod{pod}) 297 } 298 event := newWatcherEvent(testtrigger.EventDeleted, pod, testtrigger.ResourcePod, 299 withConditionsGetter(getConditions(pod)), withAddressGetter(getAddrress(pod))) 300 if err := s.match(ctx, event); err != nil { 301 s.logger.Errorf("event matcher returned an error while matching delete pod event: %v", err) 302 } 303 }, 304 } 305 } 306 307 func (s *Service) checkExecutionPodStatus(ctx context.Context, executionID string, pods []*corev1.Pod) error { 308 if len(pods) > 0 && pods[0].Labels[constants.ExecutionIdLabelName] != "" { 309 return nil 310 } 311 execution, err := s.resultRepository.Get(ctx, executionID) 312 if err != nil { 313 s.logger.Errorf("get execution returned an error %v while looking for execution id: %s", err, executionID) 314 return err 315 } 316 317 if execution.ExecutionResult.IsRunning() || execution.ExecutionResult.IsQueued() { 318 errorMessage := "" 319 for _, pod := range pods { 320 if exitCode := executor.GetPodExitCode(pod); pod.Status.Phase == corev1.PodFailed || exitCode != 0 { 321 errorMessage = executor.GetPodErrorMessage(ctx, s.clientset, pod) 322 break 323 } 324 } 325 326 if errorMessage != "" { 327 s.logger.Infow("execution pod failed with error message", "executionId", executionID, "message", execution.ExecutionResult.ErrorMessage) 328 execution.ExecutionResult.Error() 329 if execution.ExecutionResult.ErrorMessage != "" { 330 execution.ExecutionResult.ErrorMessage += "\n" 331 } 332 333 execution.ExecutionResult.ErrorMessage += errorMessage 334 test, err := s.testsClient.Get(execution.TestName) 335 if err != nil { 336 s.logger.Errorf("get test returned an error %v while looking for test name: %s", err, execution.TestName) 337 return err 338 } 339 340 if test.Spec.ExecutionRequest != nil && test.Spec.ExecutionRequest.NegativeTest { 341 s.logger.Debugw("test run was expected to fail, and it failed as expected", "test", execution.TestName) 342 execution.ExecutionResult.Status = testkube.ExecutionStatusPassed 343 execution.ExecutionResult.ErrorMessage = "" 344 } 345 346 err = s.resultRepository.UpdateResult(ctx, executionID, execution) 347 if err != nil { 348 s.logger.Errorf("update execution result returned an error %v while storing for execution id: %s", err, executionID) 349 return err 350 } 351 } 352 } 353 354 return nil 355 } 356 357 func (s *Service) deploymentEventHandler(ctx context.Context) cache.ResourceEventHandlerFuncs { 358 getConditions := func(object metav1.Object) func() ([]testtriggersv1.TestTriggerCondition, error) { 359 return func() ([]testtriggersv1.TestTriggerCondition, error) { 360 return getDeploymentConditions(ctx, s.clientset, object) 361 } 362 } 363 return cache.ResourceEventHandlerFuncs{ 364 AddFunc: func(obj any) { 365 deployment, ok := obj.(*appsv1.Deployment) 366 if !ok { 367 s.logger.Errorf("failed to process create deployment event due to it being an unexpected type, received type %+v", obj) 368 return 369 } 370 if inPast(deployment.CreationTimestamp.Time, s.watchFromDate) { 371 s.logger.Debugf( 372 "trigger service: watcher component: no-op create trigger: deployment %s/%s was created in the past", 373 deployment.Namespace, deployment.Name, 374 ) 375 return 376 } 377 s.logger.Debugf("emiting event: deployment %s/%s created", deployment.Namespace, deployment.Name) 378 event := newWatcherEvent(testtrigger.EventCreated, deployment, testtrigger.ResourceDeployment, withConditionsGetter(getConditions(deployment))) 379 if err := s.match(ctx, event); err != nil { 380 s.logger.Errorf("event matcher returned an error while matching create deployment event: %v", err) 381 } 382 }, 383 UpdateFunc: func(oldObj, newObj interface{}) { 384 oldDeployment, ok := oldObj.(*appsv1.Deployment) 385 if !ok { 386 s.logger.Errorf( 387 "failed to process update deployment event for old object due to it being an unexpected type, received type %+v", 388 oldDeployment, 389 ) 390 return 391 } 392 newDeployment, ok := newObj.(*appsv1.Deployment) 393 if !ok { 394 s.logger.Errorf( 395 "failed to process update deployment event for new object due to it being an unexpected type, received type %+v", 396 newDeployment, 397 ) 398 return 399 } 400 if cmp.Equal(oldDeployment.Spec, newDeployment.Spec) { 401 s.logger.Debugf("trigger service: watcher component: no-op update trigger: deployment specs are equal") 402 return 403 } 404 s.logger.Debugf( 405 "trigger service: watcher component: emiting event: deployment %s/%s updated", 406 newDeployment.Namespace, newDeployment.Name, 407 ) 408 causes := diffDeployments(oldDeployment, newDeployment) 409 event := newWatcherEvent(testtrigger.EventModified, newDeployment, testtrigger.ResourceDeployment, withCauses(causes), withConditionsGetter(getConditions(newDeployment))) 410 if err := s.match(ctx, event); err != nil { 411 s.logger.Errorf("event matcher returned an error while matching update deployment event: %v", err) 412 } 413 }, 414 DeleteFunc: func(obj interface{}) { 415 deployment, ok := obj.(*appsv1.Deployment) 416 if !ok { 417 s.logger.Errorf("failed to process create deployment event due to it being an unexpected type, received type %+v", obj) 418 return 419 } 420 s.logger.Debugf("trigger service: watcher component: emiting event: deployment %s/%s deleted", deployment.Namespace, deployment.Name) 421 event := newWatcherEvent(testtrigger.EventDeleted, deployment, testtrigger.ResourceDeployment, withConditionsGetter(getConditions(deployment))) 422 if err := s.match(ctx, event); err != nil { 423 s.logger.Errorf("event matcher returned an error while matching delete deployment event: %v", err) 424 } 425 }, 426 } 427 } 428 429 func (s *Service) statefulSetEventHandler(ctx context.Context) cache.ResourceEventHandlerFuncs { 430 getConditions := func(object metav1.Object) func() ([]testtriggersv1.TestTriggerCondition, error) { 431 return func() ([]testtriggersv1.TestTriggerCondition, error) { 432 return getStatefulSetConditions(ctx, s.clientset, object) 433 } 434 } 435 return cache.ResourceEventHandlerFuncs{ 436 AddFunc: func(obj any) { 437 statefulset, ok := obj.(*appsv1.StatefulSet) 438 if !ok { 439 s.logger.Errorf("failed to process create statefulset event due to it being an unexpected type, received type %+v", obj) 440 return 441 } 442 if inPast(statefulset.CreationTimestamp.Time, s.watchFromDate) { 443 s.logger.Debugf( 444 "trigger service: watcher component: no-op create trigger: statefulset %s/%s was created in the past", 445 statefulset.Namespace, statefulset.Name, 446 ) 447 return 448 } 449 s.logger.Debugf("trigger service: watcher component: emiting event: statefulset %s/%s created", statefulset.Namespace, statefulset.Name) 450 event := newWatcherEvent(testtrigger.EventCreated, statefulset, testtrigger.ResourceStatefulSet, withConditionsGetter(getConditions(statefulset))) 451 if err := s.match(ctx, event); err != nil { 452 s.logger.Errorf("event matcher returned an error while matching create statefulset event: %v", err) 453 } 454 }, 455 UpdateFunc: func(oldObj, newObj interface{}) { 456 oldStatefulSet, ok := oldObj.(*appsv1.StatefulSet) 457 if !ok { 458 s.logger.Errorf( 459 "failed to process update statefulset event for old object due to it being an unexpected type, received type %+v", 460 oldStatefulSet, 461 ) 462 return 463 } 464 newStatefulSet, ok := newObj.(*appsv1.StatefulSet) 465 if !ok { 466 s.logger.Errorf( 467 "failed to process update statefulset event for new object due to it being an unexpected type, received type %+v", 468 newStatefulSet, 469 ) 470 return 471 } 472 if cmp.Equal(oldStatefulSet.Spec, newStatefulSet.Spec) { 473 s.logger.Debugf("trigger service: watcher component: no-op update trigger: statefulset specs are equal") 474 return 475 } 476 s.logger.Debugf( 477 "trigger service: watcher component: emiting event: statefulset %s/%s updated", 478 newStatefulSet.Namespace, newStatefulSet.Name, 479 ) 480 event := newWatcherEvent(testtrigger.EventModified, newStatefulSet, testtrigger.ResourceStatefulSet, withConditionsGetter(getConditions(newStatefulSet))) 481 if err := s.match(ctx, event); err != nil { 482 s.logger.Errorf("event matcher returned an error while matching update statefulset event: %v", err) 483 } 484 }, 485 DeleteFunc: func(obj interface{}) { 486 statefulset, ok := obj.(*appsv1.StatefulSet) 487 if !ok { 488 s.logger.Errorf("failed to process delete statefulset event due to it being an unexpected type, received type %+v", obj) 489 return 490 } 491 s.logger.Debugf("trigger service: watcher component: emiting event: statefulset %s/%s deleted", statefulset.Namespace, statefulset.Name) 492 event := newWatcherEvent(testtrigger.EventDeleted, statefulset, testtrigger.ResourceStatefulSet, withConditionsGetter(getConditions(statefulset))) 493 if err := s.match(ctx, event); err != nil { 494 s.logger.Errorf("event matcher returned an error while matching delete statefulset event: %v", err) 495 } 496 }, 497 } 498 } 499 500 func (s *Service) daemonSetEventHandler(ctx context.Context) cache.ResourceEventHandlerFuncs { 501 getConditions := func(object metav1.Object) func() ([]testtriggersv1.TestTriggerCondition, error) { 502 return func() ([]testtriggersv1.TestTriggerCondition, error) { 503 return getDaemonSetConditions(ctx, s.clientset, object) 504 } 505 } 506 return cache.ResourceEventHandlerFuncs{ 507 AddFunc: func(obj any) { 508 daemonset, ok := obj.(*appsv1.DaemonSet) 509 if !ok { 510 s.logger.Errorf("failed to process create daemonset event due to it being an unexpected type, received type %+v", obj) 511 return 512 } 513 if inPast(daemonset.CreationTimestamp.Time, s.watchFromDate) { 514 s.logger.Debugf( 515 "trigger service: watcher component: no-op create trigger: daemonset %s/%s was created in the past", 516 daemonset.Namespace, daemonset.Name, 517 ) 518 return 519 } 520 s.logger.Debugf("trigger service: watcher component: emiting event: daemonset %s/%s created", daemonset.Namespace, daemonset.Name) 521 event := newWatcherEvent(testtrigger.EventCreated, daemonset, testtrigger.ResourceDaemonSet, withConditionsGetter(getConditions(daemonset))) 522 if err := s.match(ctx, event); err != nil { 523 s.logger.Errorf("event matcher returned an error while matching create daemonset event: %v", err) 524 } 525 }, 526 UpdateFunc: func(oldObj, newObj interface{}) { 527 oldDaemonSet, ok := oldObj.(*appsv1.DaemonSet) 528 if !ok { 529 s.logger.Errorf( 530 "failed to process update daemonset event for old object due to it being an unexpected type, received type %+v", 531 oldDaemonSet, 532 ) 533 return 534 } 535 newDaemonSet, ok := newObj.(*appsv1.DaemonSet) 536 if !ok { 537 s.logger.Errorf( 538 "failed to process update daemonset event for new object due to it being an unexpected type, received type %+v", 539 newDaemonSet, 540 ) 541 return 542 } 543 if cmp.Equal(oldDaemonSet.Spec, newDaemonSet.Spec) { 544 s.logger.Debugf("trigger service: watcher component: no-op update trigger: daemonset specs are equal") 545 return 546 } 547 s.logger.Debugf( 548 "trigger service: watcher component: emiting event: daemonset %s/%s updated", 549 newDaemonSet.Namespace, newDaemonSet.Name, 550 ) 551 event := newWatcherEvent(testtrigger.EventModified, newDaemonSet, testtrigger.ResourceDaemonSet, withConditionsGetter(getConditions(newDaemonSet))) 552 if err := s.match(ctx, event); err != nil { 553 s.logger.Errorf("event matcher returned an error while matching update daemonset event: %v", err) 554 } 555 }, 556 DeleteFunc: func(obj interface{}) { 557 daemonset, ok := obj.(*appsv1.DaemonSet) 558 if !ok { 559 s.logger.Errorf("failed to process delete daemonset event due to it being an unexpected type, received type %+v", obj) 560 return 561 } 562 s.logger.Debugf("trigger service: watcher component: emiting event: daemonset %s/%s deleted", daemonset.Namespace, daemonset.Name) 563 event := newWatcherEvent(testtrigger.EventDeleted, daemonset, testtrigger.ResourceDaemonSet, withConditionsGetter(getConditions(daemonset))) 564 if err := s.match(ctx, event); err != nil { 565 s.logger.Errorf("event matcher returned an error while matching delete daemonset event: %v", err) 566 } 567 }, 568 } 569 } 570 571 func (s *Service) serviceEventHandler(ctx context.Context) cache.ResourceEventHandlerFuncs { 572 getConditions := func(object metav1.Object) func() ([]testtriggersv1.TestTriggerCondition, error) { 573 return func() ([]testtriggersv1.TestTriggerCondition, error) { 574 return getServiceConditions(ctx, s.clientset, object) 575 } 576 } 577 getAddrress := func(object metav1.Object) func(c context.Context, delay time.Duration) (string, error) { 578 return func(c context.Context, delay time.Duration) (string, error) { 579 return getServiceAdress(ctx, s.clientset, object) 580 } 581 } 582 return cache.ResourceEventHandlerFuncs{ 583 AddFunc: func(obj any) { 584 service, ok := obj.(*corev1.Service) 585 if !ok { 586 s.logger.Errorf("failed to process create service event due to it being an unexpected type, received type %+v", obj) 587 return 588 } 589 if inPast(service.CreationTimestamp.Time, s.watchFromDate) { 590 s.logger.Debugf( 591 "trigger service: watcher component: no-op create trigger: service %s/%s was created in the past", 592 service.Namespace, service.Name, 593 ) 594 return 595 } 596 s.logger.Debugf("trigger service: watcher component: emiting event: service %s/%s created", service.Namespace, service.Name) 597 event := newWatcherEvent(testtrigger.EventCreated, service, testtrigger.ResourceService, 598 withConditionsGetter(getConditions(service)), withAddressGetter(getAddrress(service))) 599 if err := s.match(ctx, event); err != nil { 600 s.logger.Errorf("event matcher returned an error while matching create service event: %v", err) 601 } 602 }, 603 UpdateFunc: func(oldObj, newObj interface{}) { 604 oldService, ok := oldObj.(*corev1.Service) 605 if !ok { 606 s.logger.Errorf( 607 "failed to process update service event for old object due to it being an unexpected type, received type %+v", 608 oldService, 609 ) 610 return 611 } 612 newService, ok := newObj.(*corev1.Service) 613 if !ok { 614 s.logger.Errorf( 615 "failed to process update service event for new object due to it being an unexpected type, received type %+v", 616 newService, 617 ) 618 return 619 } 620 if cmp.Equal(oldService.Spec, newService.Spec) { 621 s.logger.Debugf("trigger service: watcher component: no-op update trigger: service specs are equal") 622 return 623 } 624 s.logger.Debugf( 625 "trigger service: watcher component: emiting event: service %s/%s updated", 626 newService.Namespace, newService.Name, 627 ) 628 event := newWatcherEvent(testtrigger.EventModified, newService, testtrigger.ResourceService, 629 withConditionsGetter(getConditions(newService)), withAddressGetter(getAddrress(newService))) 630 if err := s.match(ctx, event); err != nil { 631 s.logger.Errorf("event matcher returned an error while matching update service event: %v", err) 632 } 633 }, 634 DeleteFunc: func(obj interface{}) { 635 service, ok := obj.(*corev1.Service) 636 if !ok { 637 s.logger.Errorf("failed to process delete service event due to it being an unexpected type, received type %+v", obj) 638 return 639 } 640 s.logger.Debugf("trigger service: watcher component: emiting event: service %s/%s deleted", service.Namespace, service.Name) 641 event := newWatcherEvent(testtrigger.EventDeleted, service, testtrigger.ResourceService, 642 withConditionsGetter(getConditions(service)), withAddressGetter(getAddrress(service))) 643 if err := s.match(ctx, event); err != nil { 644 s.logger.Errorf("event matcher returned an error while matching delete service event: %v", err) 645 } 646 }, 647 } 648 } 649 650 func (s *Service) ingressEventHandler(ctx context.Context) cache.ResourceEventHandlerFuncs { 651 return cache.ResourceEventHandlerFuncs{ 652 AddFunc: func(obj any) { 653 ingress, ok := obj.(*networkingv1.Ingress) 654 if !ok { 655 s.logger.Errorf("failed to process create ingress event due to it being an unexpected type, received type %+v", obj) 656 return 657 } 658 if inPast(ingress.CreationTimestamp.Time, s.watchFromDate) { 659 s.logger.Debugf( 660 "trigger service: watcher component: no-op create trigger: ingress %s/%s was created in the past", 661 ingress.Namespace, ingress.Name, 662 ) 663 return 664 } 665 s.logger.Debugf("trigger service: watcher component: emiting event: ingress %s/%s created", ingress.Namespace, ingress.Name) 666 event := newWatcherEvent(testtrigger.EventCreated, ingress, testtrigger.ResourceIngress) 667 if err := s.match(ctx, event); err != nil { 668 s.logger.Errorf("event matcher returned an error while matching create ingress event: %v", err) 669 } 670 }, 671 UpdateFunc: func(oldObj, newObj interface{}) { 672 oldIngress, ok := oldObj.(*networkingv1.Ingress) 673 if !ok { 674 s.logger.Errorf( 675 "failed to process update ingress event for old object due to it being an unexpected type, received type %+v", 676 oldIngress, 677 ) 678 return 679 } 680 newIngress, ok := newObj.(*networkingv1.Ingress) 681 if !ok { 682 s.logger.Errorf( 683 "failed to process update ingress event for new object due to it being an unexpected type, received type %+v", 684 newIngress, 685 ) 686 return 687 } 688 if cmp.Equal(oldIngress.Spec, newIngress.Spec) { 689 s.logger.Debugf("trigger service: watcher component: no-op update trigger: ingress specs are equal") 690 return 691 } 692 s.logger.Debugf( 693 "trigger service: watcher component: emiting event: ingress %s/%s updated", 694 oldIngress.Namespace, newIngress.Name, 695 ) 696 event := newWatcherEvent(testtrigger.EventModified, newIngress, testtrigger.ResourceIngress) 697 if err := s.match(ctx, event); err != nil { 698 s.logger.Errorf("event matcher returned an error while matching update ingress event: %v", err) 699 } 700 }, 701 DeleteFunc: func(obj interface{}) { 702 ingress, ok := obj.(*networkingv1.Ingress) 703 if !ok { 704 s.logger.Errorf("failed to process delete ingress event due to it being an unexpected type, received type %+v", obj) 705 return 706 } 707 s.logger.Debugf("trigger service: watcher component: emiting event: ingress %s/%s deleted", ingress.Namespace, ingress.Name) 708 event := newWatcherEvent(testtrigger.EventDeleted, ingress, testtrigger.ResourceIngress) 709 if err := s.match(ctx, event); err != nil { 710 s.logger.Errorf("event matcher returned an error while matching delete ingress event: %v", err) 711 } 712 }, 713 } 714 } 715 716 func (s *Service) clusterEventEventHandler(ctx context.Context) cache.ResourceEventHandlerFuncs { 717 return cache.ResourceEventHandlerFuncs{ 718 AddFunc: func(obj any) { 719 clusterEvent, ok := obj.(*corev1.Event) 720 if !ok { 721 s.logger.Errorf("failed to process create cluster event event due to it being an unexpected type, received type %+v", obj) 722 return 723 } 724 if inPast(clusterEvent.CreationTimestamp.Time, s.watchFromDate) { 725 s.logger.Debugf( 726 "trigger service: watcher component: no-op create trigger: cluster event %s/%s was created in the past", 727 clusterEvent.Namespace, clusterEvent.Name, 728 ) 729 return 730 } 731 s.logger.Debugf("trigger service: watcher component: emiting event: cluster event %s/%s created", clusterEvent.Namespace, clusterEvent.Name) 732 event := newWatcherEvent(testtrigger.EventCreated, clusterEvent, testtrigger.ResourceEvent) 733 if err := s.match(ctx, event); err != nil { 734 s.logger.Errorf("event matcher returned an error while matching create cluster event event: %v", err) 735 } 736 }, 737 } 738 } 739 740 func (s *Service) testTriggerEventHandler() cache.ResourceEventHandlerFuncs { 741 return cache.ResourceEventHandlerFuncs{ 742 AddFunc: func(obj interface{}) { 743 t, ok := obj.(*testtriggersv1.TestTrigger) 744 if !ok { 745 s.logger.Errorf("failed to process create testtrigger event due to it being an unexpected type, received type %+v", obj) 746 return 747 } 748 s.logger.Debugf( 749 "trigger service: watcher component: adding testtrigger %s/%s for resource %s on event %s", 750 t.Namespace, t.Name, t.Spec.Resource, t.Spec.Event, 751 ) 752 s.addTrigger(t) 753 754 s.logger.Debugf( 755 "trigger service: watcher component: emitting event for created testtrigger %s/%s for resource %s on event %s", 756 t.Namespace, t.Name, t.Spec.Resource, t.Spec.Event, 757 ) 758 s.eventsBus.Publish(testkube.NewEvent(testkube.EventCreated, testkube.EventResourceTrigger, t.Name)) 759 }, 760 UpdateFunc: func(oldObj, newObj interface{}) { 761 t, ok := newObj.(*testtriggersv1.TestTrigger) 762 if !ok { 763 s.logger.Errorf( 764 "failed to process update testtrigger event for new testtrigger due to it being an unexpected type, received type %+v", 765 newObj, 766 ) 767 return 768 } 769 s.logger.Debugf( 770 "trigger service: watcher component: updating testtrigger %s/%s for resource %s on event %s", 771 t.Namespace, t.Name, t.Spec.Resource, t.Spec.Event, 772 ) 773 s.updateTrigger(t) 774 775 s.logger.Debugf( 776 "trigger service: watcher component: emitting event for updated testtrigger %s/%s for resource %s on event %s", 777 t.Namespace, t.Name, t.Spec.Resource, t.Spec.Event, 778 ) 779 s.eventsBus.Publish(testkube.NewEvent(testkube.EventUpdated, testkube.EventResourceTrigger, t.Name)) 780 }, 781 DeleteFunc: func(obj interface{}) { 782 t, ok := obj.(*testtriggersv1.TestTrigger) 783 if !ok { 784 s.logger.Errorf("failed to process delete testtrigger event due to it being an unexpected type, received type %+v", obj) 785 return 786 } 787 s.logger.Debugf( 788 "trigger service: watcher component: deleting testtrigger %s/%s for resource %s on event %s", 789 t.Namespace, t.Name, t.Spec.Resource, t.Spec.Event, 790 ) 791 s.removeTrigger(t) 792 793 s.logger.Debugf( 794 "trigger service: watcher component: emitting event for deleted testtrigger %s/%s for resource %s on event %s", 795 t.Namespace, t.Name, t.Spec.Resource, t.Spec.Event, 796 ) 797 s.eventsBus.Publish(testkube.NewEvent(testkube.EventDeleted, testkube.EventResourceTrigger, t.Name)) 798 }, 799 } 800 } 801 802 func (s *Service) testSuiteEventHandler() cache.ResourceEventHandlerFuncs { 803 return cache.ResourceEventHandlerFuncs{ 804 AddFunc: func(obj interface{}) { 805 testSuite, ok := obj.(*testsuitev3.TestSuite) 806 if !ok { 807 s.logger.Errorf("failed to process create testsuite event due to it being an unexpected type, received type %+v", obj) 808 return 809 } 810 if inPast(testSuite.CreationTimestamp.Time, s.watchFromDate) { 811 s.logger.Debugf( 812 "trigger service: watcher component: no-op create test suite: test suite %s/%s was created in the past", 813 testSuite.Namespace, testSuite.Name, 814 ) 815 return 816 } 817 s.logger.Debugf( 818 "trigger service: watcher component: adding testsuite %s/%s", 819 testSuite.Namespace, testSuite.Name, 820 ) 821 s.addTestSuite(testSuite) 822 823 s.logger.Debugf( 824 "trigger service: watcher component: emitting event for creating testsuite %s/%s", 825 testSuite.Namespace, testSuite.Name, 826 ) 827 s.eventsBus.Publish(testkube.NewEvent(testkube.EventCreated, testkube.EventResourceTestsuite, testSuite.Name)) 828 }, 829 UpdateFunc: func(oldObj, newObj interface{}) { 830 testSuite, ok := newObj.(*testsuitev3.TestSuite) 831 if !ok { 832 s.logger.Errorf("failed to process update testsuite event due to it being an unexpected type, received type %+v", newObj) 833 return 834 } 835 s.logger.Debugf( 836 "trigger service: watcher component: emitting event for updating testsuite %s/%s", 837 testSuite.Namespace, testSuite.Name, 838 ) 839 s.eventsBus.Publish(testkube.NewEvent(testkube.EventUpdated, testkube.EventResourceTestsuite, testSuite.Name)) 840 }, 841 DeleteFunc: func(obj interface{}) { 842 testSuite, ok := obj.(*testsuitev3.TestSuite) 843 if !ok { 844 s.logger.Errorf("failed to process delete testsuite event due to it being an unexpected type, received type %+v", obj) 845 return 846 } 847 s.logger.Debugf( 848 "trigger service: watcher component: emitting event for deleting testsuite %s/%s", 849 testSuite.Namespace, testSuite.Name, 850 ) 851 s.eventsBus.Publish(testkube.NewEvent(testkube.EventDeleted, testkube.EventResourceTestsuite, testSuite.Name)) 852 }, 853 } 854 } 855 856 func (s *Service) testEventHandler() cache.ResourceEventHandlerFuncs { 857 return cache.ResourceEventHandlerFuncs{ 858 AddFunc: func(obj interface{}) { 859 test, ok := obj.(*testsv3.Test) 860 if !ok { 861 s.logger.Errorf("failed to process create test event due to it being an unexpected type, received type %+v", obj) 862 return 863 } 864 if inPast(test.CreationTimestamp.Time, s.watchFromDate) { 865 s.logger.Debugf( 866 "trigger service: watcher component: no-op create test: test %s/%s was created in the past", 867 test.Namespace, test.Name, 868 ) 869 return 870 } 871 s.logger.Debugf( 872 "trigger service: watcher component: adding test %s/%s", 873 test.Namespace, test.Name, 874 ) 875 s.addTest(test) 876 877 s.logger.Debugf( 878 "trigger service: watcher component: emitting event for test %s/%s", 879 test.Namespace, test.Name, 880 ) 881 s.eventsBus.Publish(testkube.NewEvent(testkube.EventCreated, testkube.EventResourceTest, test.Name)) 882 }, 883 UpdateFunc: func(oldObj, newObj interface{}) { 884 test, ok := newObj.(*testsv3.Test) 885 if !ok { 886 s.logger.Errorf("failed to process update test event due to it being an unexpected type, received type %+v", newObj) 887 return 888 } 889 s.logger.Debugf( 890 "trigger service: watcher component: updating test %s/%s", 891 test.Namespace, test.Name, 892 ) 893 s.updateTest(test) 894 895 s.logger.Debugf( 896 "trigger service: watcher component: emitting event for updating test %s/%s", 897 test.Namespace, test.Name, 898 ) 899 s.eventsBus.Publish(testkube.NewEvent(testkube.EventUpdated, testkube.EventResourceTest, test.Name)) 900 }, 901 DeleteFunc: func(obj interface{}) { 902 test, ok := obj.(*testsv3.Test) 903 if !ok { 904 s.logger.Errorf("failed to process delete test event due to it being an unexpected type, received type %+v", obj) 905 return 906 } 907 s.logger.Debugf( 908 "trigger service: watcher component: emitting event for deleting test %s/%s", 909 test.Namespace, test.Name, 910 ) 911 s.eventsBus.Publish(testkube.NewEvent(testkube.EventDeleted, testkube.EventResourceTest, test.Name)) 912 }, 913 } 914 } 915 916 func (s *Service) executorEventHandler() cache.ResourceEventHandlerFuncs { 917 return cache.ResourceEventHandlerFuncs{ 918 AddFunc: func(obj interface{}) { 919 executor, ok := obj.(*executorv1.Executor) 920 if !ok { 921 s.logger.Errorf("failed to process create executor event due to it being an unexpected type, received type %+v", obj) 922 return 923 } 924 s.logger.Debugf( 925 "trigger service: watcher component: emitting event for executor %s/%s", 926 executor.Namespace, executor.Name, 927 ) 928 s.eventsBus.Publish(testkube.NewEvent(testkube.EventCreated, testkube.EventResourceExecutor, executor.Name)) 929 }, 930 UpdateFunc: func(oldObj, newObj interface{}) { 931 executor, ok := newObj.(*executorv1.Executor) 932 if !ok { 933 s.logger.Errorf("failed to process update executor event due to it being an unexpected type, received type %+v", newObj) 934 return 935 } 936 937 s.logger.Debugf( 938 "trigger service: watcher component: emitting event for updating executor %s/%s", 939 executor.Namespace, executor.Name, 940 ) 941 s.eventsBus.Publish(testkube.NewEvent(testkube.EventUpdated, testkube.EventResourceExecutor, executor.Name)) 942 }, 943 DeleteFunc: func(obj interface{}) { 944 executor, ok := obj.(*executorv1.Executor) 945 if !ok { 946 s.logger.Errorf("failed to process delete executor event due to it being an unexpected type, received type %+v", obj) 947 return 948 } 949 s.logger.Debugf( 950 "trigger service: watcher component: emitting event for deleting executor %s/%s", 951 executor.Namespace, executor.Name, 952 ) 953 s.eventsBus.Publish(testkube.NewEvent(testkube.EventDeleted, testkube.EventResourceExecutor, executor.Name)) 954 }, 955 } 956 } 957 958 func (s *Service) webhookEventHandler() cache.ResourceEventHandlerFuncs { 959 return cache.ResourceEventHandlerFuncs{ 960 AddFunc: func(obj interface{}) { 961 webhook, ok := obj.(*executorv1.Webhook) 962 if !ok { 963 s.logger.Errorf("failed to process create webhook event due to it being an unexpected type, received type %+v", obj) 964 return 965 } 966 s.logger.Debugf( 967 "trigger service: watcher component: emitting event for webhook %s/%s", 968 webhook.Namespace, webhook.Name, 969 ) 970 s.eventsBus.Publish(testkube.NewEvent(testkube.EventCreated, testkube.EventResourceWebhook, webhook.Name)) 971 }, 972 UpdateFunc: func(oldObj, newObj interface{}) { 973 webhook, ok := newObj.(*executorv1.Webhook) 974 if !ok { 975 s.logger.Errorf("failed to process update webhook event due to it being an unexpected type, received type %+v", newObj) 976 return 977 } 978 979 s.logger.Debugf( 980 "trigger service: watcher component: emitting event for updating webhook %s/%s", 981 webhook.Namespace, webhook.Name, 982 ) 983 s.eventsBus.Publish(testkube.NewEvent(testkube.EventUpdated, testkube.EventResourceWebhook, webhook.Name)) 984 }, 985 DeleteFunc: func(obj interface{}) { 986 webhook, ok := obj.(*executorv1.Webhook) 987 if !ok { 988 s.logger.Errorf("failed to process delete webhook event due to it being an unexpected type, received type %+v", obj) 989 return 990 } 991 s.logger.Debugf( 992 "trigger service: watcher component: emitting event for deleting webhook %s/%s", 993 webhook.Namespace, webhook.Name, 994 ) 995 s.eventsBus.Publish(testkube.NewEvent(testkube.EventDeleted, testkube.EventResourceWebhook, webhook.Name)) 996 }, 997 } 998 } 999 1000 func (s *Service) testSourceEventHandler() cache.ResourceEventHandlerFuncs { 1001 return cache.ResourceEventHandlerFuncs{ 1002 AddFunc: func(obj interface{}) { 1003 testSource, ok := obj.(*testsourcev1.TestSource) 1004 if !ok { 1005 s.logger.Errorf("failed to process create test source event due to it being an unexpected type, received type %+v", obj) 1006 return 1007 } 1008 s.logger.Debugf( 1009 "trigger service: watcher component: emitting event for test source %s/%s", 1010 testSource.Namespace, testSource.Name, 1011 ) 1012 s.eventsBus.Publish(testkube.NewEvent(testkube.EventCreated, testkube.EventResourceTestsource, testSource.Name)) 1013 }, 1014 UpdateFunc: func(oldObj, newObj interface{}) { 1015 testSource, ok := newObj.(*testsourcev1.TestSource) 1016 if !ok { 1017 s.logger.Errorf("failed to process update test source event due to it being an unexpected type, received type %+v", newObj) 1018 return 1019 } 1020 1021 s.logger.Debugf( 1022 "trigger service: watcher component: emitting event for updating test source %s/%s", 1023 testSource.Namespace, testSource.Name, 1024 ) 1025 s.eventsBus.Publish(testkube.NewEvent(testkube.EventUpdated, testkube.EventResourceTestsource, testSource.Name)) 1026 }, 1027 DeleteFunc: func(obj interface{}) { 1028 testSource, ok := obj.(*testsourcev1.TestSource) 1029 if !ok { 1030 s.logger.Errorf("failed to process delete test source event due to it being an unexpected type, received type %+v", obj) 1031 return 1032 } 1033 s.logger.Debugf( 1034 "trigger service: watcher component: emitting event for deleting test source %s/%s", 1035 testSource.Namespace, testSource.Name, 1036 ) 1037 s.eventsBus.Publish(testkube.NewEvent(testkube.EventDeleted, testkube.EventResourceTestsource, testSource.Name)) 1038 }, 1039 } 1040 } 1041 1042 func (s *Service) configMapEventHandler(ctx context.Context) cache.ResourceEventHandlerFuncs { 1043 return cache.ResourceEventHandlerFuncs{ 1044 AddFunc: func(obj any) { 1045 configMap, ok := obj.(*corev1.ConfigMap) 1046 if !ok { 1047 s.logger.Errorf("failed to process create config map event due to it being an unexpected type, received type %+v", obj) 1048 return 1049 } 1050 if inPast(configMap.CreationTimestamp.Time, s.watchFromDate) { 1051 s.logger.Debugf( 1052 "trigger service: watcher component: no-op create trigger: config map %s/%s was created in the past", 1053 configMap.Namespace, configMap.Name, 1054 ) 1055 return 1056 } 1057 s.logger.Debugf("trigger service: watcher component: emiting event: config map %s/%s created", configMap.Namespace, configMap.Name) 1058 event := newWatcherEvent(testtrigger.EventCreated, configMap, testtrigger.ResourceConfigMap) 1059 if err := s.match(ctx, event); err != nil { 1060 s.logger.Errorf("event matcher returned an error while matching create config map event: %v", err) 1061 } 1062 }, 1063 UpdateFunc: func(oldObj, newObj interface{}) { 1064 oldConfigMap, ok := oldObj.(*corev1.ConfigMap) 1065 if !ok { 1066 s.logger.Errorf( 1067 "failed to process update config map event for old object due to it being an unexpected type, received type %+v", 1068 oldConfigMap, 1069 ) 1070 return 1071 } 1072 newConfigMap, ok := newObj.(*corev1.ConfigMap) 1073 if !ok { 1074 s.logger.Errorf( 1075 "failed to process update config map event for new object due to it being an unexpected type, received type %+v", 1076 newConfigMap, 1077 ) 1078 return 1079 } 1080 if cmp.Equal(oldConfigMap.Data, newConfigMap.Data) && cmp.Equal(oldConfigMap.BinaryData, newConfigMap.BinaryData) { 1081 s.logger.Debugf("trigger service: watcher component: no-op update trigger: config map data and binary data are equal") 1082 return 1083 } 1084 s.logger.Debugf( 1085 "trigger service: watcher component: emiting event: config map %s/%s updated", 1086 oldConfigMap.Namespace, newConfigMap.Name, 1087 ) 1088 event := newWatcherEvent(testtrigger.EventModified, newConfigMap, testtrigger.ResourceConfigMap) 1089 if err := s.match(ctx, event); err != nil { 1090 s.logger.Errorf("event matcher returned an error while matching update config map event: %v", err) 1091 } 1092 }, 1093 DeleteFunc: func(obj interface{}) { 1094 configMap, ok := obj.(*corev1.ConfigMap) 1095 if !ok { 1096 s.logger.Errorf("failed to process delete config map event due to it being an unexpected type, received type %+v", obj) 1097 return 1098 } 1099 s.logger.Debugf("trigger service: watcher component: emiting event: config map %s/%s deleted", configMap.Namespace, configMap.Name) 1100 event := newWatcherEvent(testtrigger.EventDeleted, configMap, testtrigger.ResourceConfigMap) 1101 if err := s.match(ctx, event); err != nil { 1102 s.logger.Errorf("event matcher returned an error while matching delete config map event: %v", err) 1103 } 1104 }, 1105 } 1106 }