github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/k8s/handlers.go (about) 1 package k8s 2 3 import ( 4 "reflect" 5 "sort" 6 7 "github.com/golang/glog" 8 "github.com/nginxinc/kubernetes-ingress/internal/k8s/secrets" 9 v1 "k8s.io/api/core/v1" 10 networking "k8s.io/api/networking/v1beta1" 11 "k8s.io/client-go/tools/cache" 12 13 "fmt" 14 15 conf_v1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1" 16 conf_v1alpha1 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1alpha1" 17 18 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 19 ) 20 21 // createConfigMapHandlers builds the handler funcs for config maps 22 func createConfigMapHandlers(lbc *LoadBalancerController, name string) cache.ResourceEventHandlerFuncs { 23 return cache.ResourceEventHandlerFuncs{ 24 AddFunc: func(obj interface{}) { 25 configMap := obj.(*v1.ConfigMap) 26 if configMap.Name == name { 27 glog.V(3).Infof("Adding ConfigMap: %v", configMap.Name) 28 lbc.AddSyncQueue(obj) 29 } 30 }, 31 DeleteFunc: func(obj interface{}) { 32 configMap, isConfigMap := obj.(*v1.ConfigMap) 33 if !isConfigMap { 34 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 35 if !ok { 36 glog.V(3).Infof("Error received unexpected object: %v", obj) 37 return 38 } 39 configMap, ok = deletedState.Obj.(*v1.ConfigMap) 40 if !ok { 41 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-ConfigMap object: %v", deletedState.Obj) 42 return 43 } 44 } 45 if configMap.Name == name { 46 glog.V(3).Infof("Removing ConfigMap: %v", configMap.Name) 47 lbc.AddSyncQueue(obj) 48 } 49 }, 50 UpdateFunc: func(old, cur interface{}) { 51 if !reflect.DeepEqual(old, cur) { 52 configMap := cur.(*v1.ConfigMap) 53 if configMap.Name == name { 54 glog.V(3).Infof("ConfigMap %v changed, syncing", cur.(*v1.ConfigMap).Name) 55 lbc.AddSyncQueue(cur) 56 } 57 } 58 }, 59 } 60 } 61 62 // createEndpointHandlers builds the handler funcs for endpoints 63 func createEndpointHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 64 return cache.ResourceEventHandlerFuncs{ 65 AddFunc: func(obj interface{}) { 66 endpoint := obj.(*v1.Endpoints) 67 glog.V(3).Infof("Adding endpoints: %v", endpoint.Name) 68 lbc.AddSyncQueue(obj) 69 }, 70 DeleteFunc: func(obj interface{}) { 71 endpoint, isEndpoint := obj.(*v1.Endpoints) 72 if !isEndpoint { 73 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 74 if !ok { 75 glog.V(3).Infof("Error received unexpected object: %v", obj) 76 return 77 } 78 endpoint, ok = deletedState.Obj.(*v1.Endpoints) 79 if !ok { 80 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Endpoints object: %v", deletedState.Obj) 81 return 82 } 83 } 84 glog.V(3).Infof("Removing endpoints: %v", endpoint.Name) 85 lbc.AddSyncQueue(obj) 86 }, 87 UpdateFunc: func(old, cur interface{}) { 88 if !reflect.DeepEqual(old, cur) { 89 glog.V(3).Infof("Endpoints %v changed, syncing", cur.(*v1.Endpoints).Name) 90 lbc.AddSyncQueue(cur) 91 } 92 }, 93 } 94 } 95 96 // createIngressHandlers builds the handler funcs for ingresses 97 func createIngressHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 98 return cache.ResourceEventHandlerFuncs{ 99 AddFunc: func(obj interface{}) { 100 ingress := obj.(*networking.Ingress) 101 glog.V(3).Infof("Adding Ingress: %v", ingress.Name) 102 lbc.AddSyncQueue(obj) 103 }, 104 DeleteFunc: func(obj interface{}) { 105 ingress, isIng := obj.(*networking.Ingress) 106 if !isIng { 107 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 108 if !ok { 109 glog.V(3).Infof("Error received unexpected object: %v", obj) 110 return 111 } 112 ingress, ok = deletedState.Obj.(*networking.Ingress) 113 if !ok { 114 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Ingress object: %v", deletedState.Obj) 115 return 116 } 117 } 118 glog.V(3).Infof("Removing Ingress: %v", ingress.Name) 119 lbc.AddSyncQueue(obj) 120 }, 121 UpdateFunc: func(old, current interface{}) { 122 c := current.(*networking.Ingress) 123 o := old.(*networking.Ingress) 124 if hasChanges(o, c) { 125 glog.V(3).Infof("Ingress %v changed, syncing", c.Name) 126 lbc.AddSyncQueue(c) 127 } 128 }, 129 } 130 } 131 132 // createSecretHandlers builds the handler funcs for secrets 133 func createSecretHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 134 return cache.ResourceEventHandlerFuncs{ 135 AddFunc: func(obj interface{}) { 136 secret := obj.(*v1.Secret) 137 if !secrets.IsSupportedSecretType(secret.Type) { 138 glog.V(3).Infof("Ignoring Secret %v of unsupported type %v", secret.Name, secret.Type) 139 return 140 } 141 glog.V(3).Infof("Adding Secret: %v", secret.Name) 142 lbc.AddSyncQueue(obj) 143 }, 144 DeleteFunc: func(obj interface{}) { 145 secret, isSecr := obj.(*v1.Secret) 146 if !isSecr { 147 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 148 if !ok { 149 glog.V(3).Infof("Error received unexpected object: %v", obj) 150 return 151 } 152 secret, ok = deletedState.Obj.(*v1.Secret) 153 if !ok { 154 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Secret object: %v", deletedState.Obj) 155 return 156 } 157 } 158 if !secrets.IsSupportedSecretType(secret.Type) { 159 glog.V(3).Infof("Ignoring Secret %v of unsupported type %v", secret.Name, secret.Type) 160 return 161 } 162 163 glog.V(3).Infof("Removing Secret: %v", secret.Name) 164 lbc.AddSyncQueue(obj) 165 }, 166 UpdateFunc: func(old, cur interface{}) { 167 // A secret cannot change its type. That's why we only need to check the type of the current secret. 168 curSecret := cur.(*v1.Secret) 169 if !secrets.IsSupportedSecretType(curSecret.Type) { 170 glog.V(3).Infof("Ignoring Secret %v of unsupported type %v", curSecret.Name, curSecret.Type) 171 return 172 } 173 174 if !reflect.DeepEqual(old, cur) { 175 glog.V(3).Infof("Secret %v changed, syncing", cur.(*v1.Secret).Name) 176 lbc.AddSyncQueue(cur) 177 } 178 }, 179 } 180 } 181 182 // createServiceHandlers builds the handler funcs for services. 183 // 184 // In the update handlers below we catch two cases: 185 // (1) the service is the external service 186 // (2) the service had a change like a change of the port field of a service port (for such a change Kubernetes doesn't 187 // update the corresponding endpoints resource, that we monitor as well) 188 // or a change of the externalName field of an ExternalName service. 189 // 190 // In both cases we enqueue the service to be processed by syncService 191 func createServiceHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 192 return cache.ResourceEventHandlerFuncs{ 193 AddFunc: func(obj interface{}) { 194 svc := obj.(*v1.Service) 195 196 glog.V(3).Infof("Adding service: %v", svc.Name) 197 lbc.AddSyncQueue(svc) 198 }, 199 DeleteFunc: func(obj interface{}) { 200 svc, isSvc := obj.(*v1.Service) 201 if !isSvc { 202 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 203 if !ok { 204 glog.V(3).Infof("Error received unexpected object: %v", obj) 205 return 206 } 207 svc, ok = deletedState.Obj.(*v1.Service) 208 if !ok { 209 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Service object: %v", deletedState.Obj) 210 return 211 } 212 } 213 214 glog.V(3).Infof("Removing service: %v", svc.Name) 215 lbc.AddSyncQueue(svc) 216 }, 217 UpdateFunc: func(old, cur interface{}) { 218 if !reflect.DeepEqual(old, cur) { 219 curSvc := cur.(*v1.Service) 220 if lbc.IsExternalServiceForStatus(curSvc) { 221 lbc.AddSyncQueue(curSvc) 222 return 223 } 224 oldSvc := old.(*v1.Service) 225 if hasServiceChanges(oldSvc, curSvc) { 226 glog.V(3).Infof("Service %v changed, syncing", curSvc.Name) 227 lbc.AddSyncQueue(curSvc) 228 } 229 } 230 }, 231 } 232 } 233 234 type portSort []v1.ServicePort 235 236 func (a portSort) Len() int { 237 return len(a) 238 } 239 240 func (a portSort) Swap(i, j int) { 241 a[i], a[j] = a[j], a[i] 242 } 243 244 func (a portSort) Less(i, j int) bool { 245 if a[i].Name == a[j].Name { 246 return a[i].Port < a[j].Port 247 } 248 return a[i].Name < a[j].Name 249 } 250 251 // hasServicedChanged checks if the service has changed based on custom rules we define (eg. port). 252 func hasServiceChanges(oldSvc, curSvc *v1.Service) bool { 253 if hasServicePortChanges(oldSvc.Spec.Ports, curSvc.Spec.Ports) { 254 return true 255 } 256 if hasServiceExternalNameChanges(oldSvc, curSvc) { 257 return true 258 } 259 return false 260 } 261 262 // hasServiceExternalNameChanges only compares Service.Spec.Externalname for Type ExternalName services. 263 func hasServiceExternalNameChanges(oldSvc, curSvc *v1.Service) bool { 264 return curSvc.Spec.Type == v1.ServiceTypeExternalName && oldSvc.Spec.ExternalName != curSvc.Spec.ExternalName 265 } 266 267 // hasServicePortChanges only compares ServicePort.Name and .Port. 268 func hasServicePortChanges(oldServicePorts []v1.ServicePort, curServicePorts []v1.ServicePort) bool { 269 if len(oldServicePorts) != len(curServicePorts) { 270 return true 271 } 272 273 sort.Sort(portSort(oldServicePorts)) 274 sort.Sort(portSort(curServicePorts)) 275 276 for i := range oldServicePorts { 277 if oldServicePorts[i].Port != curServicePorts[i].Port || 278 oldServicePorts[i].Name != curServicePorts[i].Name { 279 return true 280 } 281 } 282 return false 283 } 284 285 func createVirtualServerHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 286 return cache.ResourceEventHandlerFuncs{ 287 AddFunc: func(obj interface{}) { 288 vs := obj.(*conf_v1.VirtualServer) 289 glog.V(3).Infof("Adding VirtualServer: %v", vs.Name) 290 lbc.AddSyncQueue(vs) 291 }, 292 DeleteFunc: func(obj interface{}) { 293 vs, isVs := obj.(*conf_v1.VirtualServer) 294 if !isVs { 295 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 296 if !ok { 297 glog.V(3).Infof("Error received unexpected object: %v", obj) 298 return 299 } 300 vs, ok = deletedState.Obj.(*conf_v1.VirtualServer) 301 if !ok { 302 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-VirtualServer object: %v", deletedState.Obj) 303 return 304 } 305 } 306 glog.V(3).Infof("Removing VirtualServer: %v", vs.Name) 307 lbc.AddSyncQueue(vs) 308 }, 309 UpdateFunc: func(old, cur interface{}) { 310 curVs := cur.(*conf_v1.VirtualServer) 311 oldVs := old.(*conf_v1.VirtualServer) 312 if !reflect.DeepEqual(oldVs.Spec, curVs.Spec) { 313 glog.V(3).Infof("VirtualServer %v changed, syncing", curVs.Name) 314 lbc.AddSyncQueue(curVs) 315 } 316 }, 317 } 318 } 319 320 func createVirtualServerRouteHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 321 return cache.ResourceEventHandlerFuncs{ 322 AddFunc: func(obj interface{}) { 323 vsr := obj.(*conf_v1.VirtualServerRoute) 324 glog.V(3).Infof("Adding VirtualServerRoute: %v", vsr.Name) 325 lbc.AddSyncQueue(vsr) 326 }, 327 DeleteFunc: func(obj interface{}) { 328 vsr, isVsr := obj.(*conf_v1.VirtualServerRoute) 329 if !isVsr { 330 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 331 if !ok { 332 glog.V(3).Infof("Error received unexpected object: %v", obj) 333 return 334 } 335 vsr, ok = deletedState.Obj.(*conf_v1.VirtualServerRoute) 336 if !ok { 337 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-VirtualServerRoute object: %v", deletedState.Obj) 338 return 339 } 340 } 341 glog.V(3).Infof("Removing VirtualServerRoute: %v", vsr.Name) 342 lbc.AddSyncQueue(vsr) 343 }, 344 UpdateFunc: func(old, cur interface{}) { 345 curVsr := cur.(*conf_v1.VirtualServerRoute) 346 oldVsr := old.(*conf_v1.VirtualServerRoute) 347 if !reflect.DeepEqual(oldVsr.Spec, curVsr.Spec) { 348 glog.V(3).Infof("VirtualServerRoute %v changed, syncing", curVsr.Name) 349 lbc.AddSyncQueue(curVsr) 350 } 351 }, 352 } 353 } 354 355 func createGlobalConfigurationHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 356 return cache.ResourceEventHandlerFuncs{ 357 AddFunc: func(obj interface{}) { 358 gc := obj.(*conf_v1alpha1.GlobalConfiguration) 359 glog.V(3).Infof("Adding GlobalConfiguration: %v", gc.Name) 360 lbc.AddSyncQueue(gc) 361 }, 362 DeleteFunc: func(obj interface{}) { 363 gc, isGc := obj.(*conf_v1alpha1.GlobalConfiguration) 364 if !isGc { 365 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 366 if !ok { 367 glog.V(3).Infof("Error received unexpected object: %v", obj) 368 return 369 } 370 gc, ok = deletedState.Obj.(*conf_v1alpha1.GlobalConfiguration) 371 if !ok { 372 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-GlobalConfiguration object: %v", deletedState.Obj) 373 return 374 } 375 } 376 glog.V(3).Infof("Removing GlobalConfiguration: %v", gc.Name) 377 lbc.AddSyncQueue(gc) 378 }, 379 UpdateFunc: func(old, cur interface{}) { 380 curGc := cur.(*conf_v1alpha1.GlobalConfiguration) 381 if !reflect.DeepEqual(old, cur) { 382 glog.V(3).Infof("GlobalConfiguration %v changed, syncing", curGc.Name) 383 lbc.AddSyncQueue(curGc) 384 } 385 }, 386 } 387 } 388 389 func createTransportServerHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 390 return cache.ResourceEventHandlerFuncs{ 391 AddFunc: func(obj interface{}) { 392 ts := obj.(*conf_v1alpha1.TransportServer) 393 glog.V(3).Infof("Adding TransportServer: %v", ts.Name) 394 lbc.AddSyncQueue(ts) 395 }, 396 DeleteFunc: func(obj interface{}) { 397 ts, isTs := obj.(*conf_v1alpha1.TransportServer) 398 if !isTs { 399 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 400 if !ok { 401 glog.V(3).Infof("Error received unexpected object: %v", obj) 402 return 403 } 404 ts, ok = deletedState.Obj.(*conf_v1alpha1.TransportServer) 405 if !ok { 406 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-TransportServer object: %v", deletedState.Obj) 407 return 408 } 409 } 410 glog.V(3).Infof("Removing TransportServer: %v", ts.Name) 411 lbc.AddSyncQueue(ts) 412 }, 413 UpdateFunc: func(old, cur interface{}) { 414 curTs := cur.(*conf_v1alpha1.TransportServer) 415 if !reflect.DeepEqual(old, cur) { 416 glog.V(3).Infof("TransportServer %v changed, syncing", curTs.Name) 417 lbc.AddSyncQueue(curTs) 418 } 419 }, 420 } 421 } 422 423 func createPolicyHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 424 return cache.ResourceEventHandlerFuncs{ 425 AddFunc: func(obj interface{}) { 426 pol := obj.(*conf_v1.Policy) 427 glog.V(3).Infof("Adding Policy: %v", pol.Name) 428 lbc.AddSyncQueue(pol) 429 }, 430 DeleteFunc: func(obj interface{}) { 431 pol, isPol := obj.(*conf_v1.Policy) 432 if !isPol { 433 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 434 if !ok { 435 glog.V(3).Infof("Error received unexpected object: %v", obj) 436 return 437 } 438 pol, ok = deletedState.Obj.(*conf_v1.Policy) 439 if !ok { 440 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Policy object: %v", deletedState.Obj) 441 return 442 } 443 } 444 glog.V(3).Infof("Removing Policy: %v", pol.Name) 445 lbc.AddSyncQueue(pol) 446 }, 447 UpdateFunc: func(old, cur interface{}) { 448 curPol := cur.(*conf_v1.Policy) 449 if !reflect.DeepEqual(old, cur) { 450 glog.V(3).Infof("Policy %v changed, syncing", curPol.Name) 451 lbc.AddSyncQueue(curPol) 452 } 453 }, 454 } 455 } 456 457 func createIngressLinkHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 458 return cache.ResourceEventHandlerFuncs{ 459 AddFunc: func(obj interface{}) { 460 link := obj.(*unstructured.Unstructured) 461 glog.V(3).Infof("Adding IngressLink: %v", link.GetName()) 462 lbc.AddSyncQueue(link) 463 }, 464 DeleteFunc: func(obj interface{}) { 465 link, isUnstructured := obj.(*unstructured.Unstructured) 466 467 if !isUnstructured { 468 deletedState, ok := obj.(cache.DeletedFinalStateUnknown) 469 if !ok { 470 glog.V(3).Infof("Error received unexpected object: %v", obj) 471 return 472 } 473 link, ok = deletedState.Obj.(*unstructured.Unstructured) 474 if !ok { 475 glog.V(3).Infof("Error DeletedFinalStateUnknown contained non-Unstructured object: %v", deletedState.Obj) 476 return 477 } 478 } 479 480 glog.V(3).Infof("Removing IngressLink: %v", link.GetName()) 481 lbc.AddSyncQueue(link) 482 }, 483 UpdateFunc: func(old, cur interface{}) { 484 oldLink := old.(*unstructured.Unstructured) 485 curLink := cur.(*unstructured.Unstructured) 486 different, err := areResourcesDifferent(oldLink, curLink) 487 if err != nil { 488 glog.V(3).Infof("Error when comparing IngressLinks: %v", err) 489 lbc.AddSyncQueue(curLink) 490 } 491 if different { 492 glog.V(3).Infof("IngressLink %v changed, syncing", oldLink.GetName()) 493 lbc.AddSyncQueue(curLink) 494 } 495 }, 496 } 497 } 498 499 func createAppProtectPolicyHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 500 handlers := cache.ResourceEventHandlerFuncs{ 501 AddFunc: func(obj interface{}) { 502 pol := obj.(*unstructured.Unstructured) 503 glog.V(3).Infof("Adding AppProtectPolicy: %v", pol.GetName()) 504 lbc.AddSyncQueue(pol) 505 }, 506 UpdateFunc: func(oldObj, obj interface{}) { 507 oldPol := oldObj.(*unstructured.Unstructured) 508 newPol := obj.(*unstructured.Unstructured) 509 different, err := areResourcesDifferent(oldPol, newPol) 510 if err != nil { 511 glog.V(3).Infof("Error when comparing policy %v", err) 512 lbc.AddSyncQueue(newPol) 513 } 514 if different { 515 glog.V(3).Infof("ApPolicy %v changed, syncing", oldPol.GetName()) 516 lbc.AddSyncQueue(newPol) 517 } 518 }, 519 DeleteFunc: func(obj interface{}) { 520 lbc.AddSyncQueue(obj) 521 }, 522 } 523 return handlers 524 } 525 526 // areResourcesDifferent returns true if the resources are different based on their spec. 527 func areResourcesDifferent(oldresource, resource *unstructured.Unstructured) (bool, error) { 528 oldSpec, found, err := unstructured.NestedMap(oldresource.Object, "spec") 529 if !found { 530 glog.V(3).Infof("Warning, oldspec has unexpected format") 531 } 532 if err != nil { 533 return false, err 534 } 535 spec, found, err := unstructured.NestedMap(resource.Object, "spec") 536 if !found { 537 return false, fmt.Errorf("Error, spec has unexpected format") 538 } 539 if err != nil { 540 return false, err 541 } 542 eq := reflect.DeepEqual(oldSpec, spec) 543 if eq { 544 glog.V(3).Infof("New spec of %v same as old spec", oldresource.GetName()) 545 } 546 return !eq, nil 547 } 548 549 func createAppProtectLogConfHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 550 handlers := cache.ResourceEventHandlerFuncs{ 551 AddFunc: func(obj interface{}) { 552 conf := obj.(*unstructured.Unstructured) 553 glog.V(3).Infof("Adding AppProtectLogConf: %v", conf.GetName()) 554 lbc.AddSyncQueue(conf) 555 }, 556 UpdateFunc: func(oldObj, obj interface{}) { 557 oldConf := oldObj.(*unstructured.Unstructured) 558 newConf := obj.(*unstructured.Unstructured) 559 different, err := areResourcesDifferent(oldConf, newConf) 560 if err != nil { 561 glog.V(3).Infof("Error when comparing LogConfs %v", err) 562 lbc.AddSyncQueue(newConf) 563 } 564 if different { 565 glog.V(3).Infof("ApLogConf %v changed, syncing", oldConf.GetName()) 566 lbc.AddSyncQueue(newConf) 567 } 568 }, 569 DeleteFunc: func(obj interface{}) { 570 lbc.AddSyncQueue(obj) 571 }, 572 } 573 return handlers 574 } 575 576 func createAppProtectUserSigHandlers(lbc *LoadBalancerController) cache.ResourceEventHandlerFuncs { 577 handlers := cache.ResourceEventHandlerFuncs{ 578 AddFunc: func(obj interface{}) { 579 sig := obj.(*unstructured.Unstructured) 580 glog.V(3).Infof("Adding AppProtectUserSig: %v", sig.GetName()) 581 lbc.AddSyncQueue(sig) 582 }, 583 UpdateFunc: func(oldObj, obj interface{}) { 584 oldSig := oldObj.(*unstructured.Unstructured) 585 newSig := obj.(*unstructured.Unstructured) 586 different, err := areResourcesDifferent(oldSig, newSig) 587 if err != nil { 588 glog.V(3).Infof("Error when comparing UserSigs %v", err) 589 lbc.AddSyncQueue(newSig) 590 } 591 if different { 592 glog.V(3).Infof("ApUserSig %v changed, syncing", oldSig.GetName()) 593 lbc.AddSyncQueue(newSig) 594 } 595 }, 596 DeleteFunc: func(obj interface{}) { 597 lbc.AddSyncQueue(obj) 598 }, 599 } 600 return handlers 601 }