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