github.com/iter8-tools/iter8@v1.1.2/controllers/routemaps.go (about) 1 package controllers 2 3 import ( 4 "reflect" 5 6 "github.com/iter8-tools/iter8/base/log" 7 corev1 "k8s.io/api/core/v1" 8 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 9 ) 10 11 // AllRoutemaps contains all the routemaps known to the controller 12 var AllRoutemaps = routemaps{ 13 nsRoutemap: make(map[string]routemapsByName), 14 } 15 16 // getRoutemapFromObj extracts a routemap which contains the given object as a version resource 17 // ToDo: this function assumes that there is at most one routemap that contains a source; 18 // a more general idea would be to return a routemap list instead 19 func (s *routemaps) getRoutemapFromObj(obj interface{}, gvrShort string) *routemap { 20 // lock for reading and later unlock 21 s.mutex.RLock() 22 defer s.mutex.RUnlock() 23 24 // get unstructured object 25 u := obj.(*unstructured.Unstructured) 26 27 // attempt to return the routemap 28 // ToDo: speed up this quadruple-nested for loop 29 for _, rmByName := range s.nsRoutemap { 30 for _, rm := range rmByName { 31 for _, v := range rm.Versions { 32 for _, r := range v.Resources { 33 // go through every resource in every version in every routemap in every namespace 34 // check for name match between routemap-resource and unstructured-resource 35 // check for gvrShort match between routemap-resource and unstructured-resource 36 if r.GVRShort == gvrShort && r.Name == u.GetName() { 37 // if routemap specifies the resource namespace 38 // check for namespace match between routemap-resource and unstructured-resource 39 if r.Namespace == nil || *r.Namespace == u.GetNamespace() { 40 return rm 41 } 42 } 43 } 44 } 45 } 46 } 47 return nil 48 } 49 50 // GetRoutemapFromNamespaceName extracts a routemap which contains the given object as a version resource 51 func (s *routemaps) GetRoutemapFromNamespaceName(namespace string, name string) RoutemapInterface { 52 // lock for reading and later unlock 53 s.mutex.RLock() 54 defer s.mutex.RUnlock() 55 56 rmByName, ok := s.nsRoutemap[namespace] 57 if ok { 58 s := rmByName[name] 59 if s == nil || reflect.ValueOf(s).IsNil() { 60 // try concatenating "-routemap" to name 61 s = rmByName[name+"-routemap"] 62 if s == nil || reflect.ValueOf(s).IsNil() { 63 return nil 64 } 65 } 66 return s 67 } 68 69 return nil 70 } 71 72 // delete a routemap from routemaps 73 func (s *routemaps) delete(cm *corev1.ConfigMap) { 74 // lock for writing and later unlock 75 s.mutex.Lock() 76 defer s.mutex.Unlock() 77 78 // delete from nsRoutemap first 79 if m, ok1 := s.nsRoutemap[cm.Namespace]; ok1 { 80 _, ok2 := m[cm.Name] 81 if ok2 { 82 delete(m, cm.Name) 83 if len(m) == 0 { 84 log.Logger.Debug("no routemaps in namespace ", cm.Namespace) 85 delete(s.nsRoutemap, cm.Namespace) 86 log.Logger.Debug("deleted namespace ", cm.Namespace, " from routemaps") 87 } 88 } 89 } 90 } 91 92 // makeAndUpdateWith makes a routemap from a configmap and updates routemaps with it 93 func (s *routemaps) makeAndUpdateWith(cm *corev1.ConfigMap, config *Config) *routemap { 94 // lock for writing and later unlock 95 s.mutex.Lock() 96 defer s.mutex.Unlock() 97 98 // validate the configmap 99 if err := validateRoutemapCM(cm); err != nil { 100 return nil 101 } 102 103 log.Logger.Trace("routemap cm is valid") 104 105 // make/update routemap with uninitialized status 106 var rm *routemap 107 var err error 108 if rm, err = extractRoutemap(cm, config); err != nil { 109 return nil 110 } 111 112 // insert into nsRoutemap 113 if _, ok := s.nsRoutemap[cm.Namespace]; !ok { 114 s.nsRoutemap[cm.Namespace] = make(routemapsByName) 115 } 116 s.nsRoutemap[cm.Namespace][cm.Name] = rm 117 118 return rm 119 }