Skip to content

Instantly share code, notes, and snippets.

@jayunit100
Created January 17, 2022 17:05
Show Gist options
  • Save jayunit100/8aaf0271dc64f3f023637bd417f331b7 to your computer and use it in GitHub Desktop.
Save jayunit100/8aaf0271dc64f3f023637bd417f331b7 to your computer and use it in GitHub Desktop.
some comments on the diff function, which will be increasingly the backbone for kpng
func (sl *ServicesListener) diff(prevSvc, currSvc *localnetv1.Service) {
// 0) make PortsListener calls by leveraging the SlicesLen iterator
// name, protoc, port, nodeport, targetport, targetportname
var prevPorts, currPorts []*localnetv1.PortMapping
if prevSvc != nil {
prevPorts = prevSvc.Ports
}
if currSvc != nil {
currPorts = currSvc.Ports
}
if sl.PortsListener != nil {
Diff{
SameKey: func(pi, ci int) bool {
return samePort(prevPorts[pi], currPorts[ci])
},
Added: func(ci int) { sl.PortsListener.AddPort(currSvc, currPorts[ci]) },
Updated: func(_, _ int) {},
Deleted: func(pi int) { sl.PortsListener.DeletePort(prevSvc, prevPorts[pi]) },
}.SlicesLen(len(prevPorts), len(currPorts))
}
// there are 3 kinds of IPs: ClusterIP, ExternalIP, and LoadBalancerIP. we build a array
// which we'll use below
ipsExtractors := []struct {
ipKind IPKind
getIPs func(svc *localnetv1.Service) *localnetv1.IPSet
}{
{ClusterIP, func(svc *localnetv1.Service) *localnetv1.IPSet {
if svc.IPs == nil {
return nil
}
return svc.IPs.ClusterIPs
}},
{ExternalIP, func(svc *localnetv1.Service) *localnetv1.IPSet {
if svc.IPs == nil {
return nil
}
return svc.IPs.ExternalIPs
}},
{LoadBalancerIP, func(svc *localnetv1.Service) *localnetv1.IPSet {
if svc.IPs == nil {
return nil
}
return svc.IPs.LoadBalancerIPs
}},
}
// We defer the "delete" calls, but decide which calls to make right now...
deferredCalls := make([]func(), 0)
// 1) make internal IPsListener calls based on the diffs
if sl.IPsListener != nil {
for _, ext := range ipsExtractors {
ext := ext
var prevIPs, currIPs []string
if prevSvc != nil {
prevIPs = ext.getIPs(prevSvc).All()
}
if currSvc != nil {
currIPs = ext.getIPs(currSvc).All()
}
// Create a new "Diff". Then iterate through the every "previous/current" tuple
// inside of the SlicesLen method. This method will ultimately call
// Added
// Updated
// Deleted
// these functions, respectively will
// call IP on the IPsListener
// call delete IP (deferred) on the IPListener
Diff{
SameKey: func(pi, ci int) bool {
return prevIPs[pi] == currIPs[ci]
},
Added: func(ci int) {
sl.IPsListener.AddIP(currSvc, currIPs[ci], ext.ipKind)
},
Updated: func(_, _ int) {}, // <-- how come we dont do anything when Updated() ???
Deleted: func(pi int) {
deferredCalls = append(deferredCalls, func() { sl.IPsListener.DeleteIP(prevSvc, prevIPs[pi], ext.ipKind) })
},
}.SlicesLen(len(prevIPs), len(currIPs))
}
}
// 2) Now make IPPortsListener calls based on the diffs ...............
if sl.IPPortsListener != nil {
for _, ext := range ipsExtractors {
ext := ext
type ipPort struct {
ip string
port *localnetv1.PortMapping
}
// compbine makes an array of ipPorts from a service ....
combine := func(svc *localnetv1.Service) []ipPort {
if svc == nil {
return nil
}
ips := ext.getIPs(svc).All()
pairs := make([]ipPort, 0, len(ips)*len(svc.Ports))
for _, ip := range ips {
for _, port := range svc.Ports {
pairs = append(pairs, ipPort{ip, port})
}
}
return pairs
}
// make prev and current list of ip port tuples....
prevs := combine(prevSvc)
currs := combine(currSvc)
Diff{
SameKey: func(pi, ci int) bool {
return prevs[pi].ip == currs[ci].ip && samePort(prevs[pi].port, currs[ci].port)
},
Added: func(ci int) { sl.IPPortsListener.AddIPPort(currSvc, currs[ci].ip, ext.ipKind, currs[ci].port) },
Updated: func(_, _ int) {},
Deleted: func(pi int) { sl.IPPortsListener.DeleteIPPort(currSvc, prevs[pi].ip, ext.ipKind, prevs[pi].port) },
}.SlicesLen(len(prevs), len(currs))
}
}
// now issue the deferred delete calls from (1)
for _, deferredCall := range deferredCalls {
deferredCall()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment