mirror of
				https://github.com/traefik/traefik.git
				synced 2025-10-31 00:11:38 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			111 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package k8s
 | |
| 
 | |
| import (
 | |
| 	corev1 "k8s.io/api/core/v1"
 | |
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | |
| )
 | |
| 
 | |
| // ResourceEventHandler handles Add, Update or Delete Events for resources.
 | |
| type ResourceEventHandler struct {
 | |
| 	Ev chan<- interface{}
 | |
| }
 | |
| 
 | |
| // OnAdd is called on Add Events.
 | |
| func (reh *ResourceEventHandler) OnAdd(obj interface{}) {
 | |
| 	eventHandlerFunc(reh.Ev, obj)
 | |
| }
 | |
| 
 | |
| // OnUpdate is called on Update Events.
 | |
| // Ignores useless changes.
 | |
| func (reh *ResourceEventHandler) OnUpdate(oldObj, newObj interface{}) {
 | |
| 	if objChanged(oldObj, newObj) {
 | |
| 		eventHandlerFunc(reh.Ev, newObj)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // OnDelete is called on Delete Events.
 | |
| func (reh *ResourceEventHandler) OnDelete(obj interface{}) {
 | |
| 	eventHandlerFunc(reh.Ev, obj)
 | |
| }
 | |
| 
 | |
| // eventHandlerFunc will pass the obj on to the events channel or drop it.
 | |
| // This is so passing the events along won't block in the case of high volume.
 | |
| // The events are only used for signaling anyway so dropping a few is ok.
 | |
| func eventHandlerFunc(events chan<- interface{}, obj interface{}) {
 | |
| 	select {
 | |
| 	case events <- obj:
 | |
| 	default:
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func objChanged(oldObj, newObj interface{}) bool {
 | |
| 	if oldObj == nil || newObj == nil {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	if oldObj.(metav1.Object).GetResourceVersion() == newObj.(metav1.Object).GetResourceVersion() {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	if _, ok := oldObj.(*corev1.Endpoints); ok {
 | |
| 		return endpointsChanged(oldObj.(*corev1.Endpoints), newObj.(*corev1.Endpoints))
 | |
| 	}
 | |
| 
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func endpointsChanged(a, b *corev1.Endpoints) bool {
 | |
| 	if len(a.Subsets) != len(b.Subsets) {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	for i, sa := range a.Subsets {
 | |
| 		sb := b.Subsets[i]
 | |
| 		if subsetsChanged(sa, sb) {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func subsetsChanged(sa, sb corev1.EndpointSubset) bool {
 | |
| 	if len(sa.Addresses) != len(sb.Addresses) {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	if len(sa.Ports) != len(sb.Ports) {
 | |
| 		return true
 | |
| 	}
 | |
| 
 | |
| 	// in Addresses and Ports, we should be able to rely on
 | |
| 	// these being sorted and able to be compared
 | |
| 	// they are supposed to be in a canonical format
 | |
| 	for addr, aaddr := range sa.Addresses {
 | |
| 		baddr := sb.Addresses[addr]
 | |
| 		if aaddr.IP != baddr.IP {
 | |
| 			return true
 | |
| 		}
 | |
| 
 | |
| 		if aaddr.Hostname != baddr.Hostname {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	for port, aport := range sa.Ports {
 | |
| 		bport := sb.Ports[port]
 | |
| 		if aport.Name != bport.Name {
 | |
| 			return true
 | |
| 		}
 | |
| 		if aport.Port != bport.Port {
 | |
| 			return true
 | |
| 		}
 | |
| 
 | |
| 		if aport.Protocol != bport.Protocol {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return false
 | |
| }
 |