@@ -18,13 +18,16 @@ package plugin
18
18
19
19
import (
20
20
"errors"
21
+ "fmt"
22
+ "slices"
21
23
"sync"
22
24
)
23
25
24
26
// PluginsStore holds a list of DRA Plugins.
25
27
type pluginsStore struct {
26
28
sync.RWMutex
27
- store map [string ]* Plugin
29
+ // plugin name -> Plugin in the order in which they got added
30
+ store map [string ][]* Plugin
28
31
}
29
32
30
33
// draPlugins map keeps track of all registered DRA plugins on the node
@@ -37,43 +40,57 @@ func (s *pluginsStore) get(pluginName string) *Plugin {
37
40
s .RLock ()
38
41
defer s .RUnlock ()
39
42
40
- return s .store [pluginName ]
43
+ instances := s .store [pluginName ]
44
+ if len (instances ) == 0 {
45
+ return nil
46
+ }
47
+ // Heuristic: pick the most recent one. It's most likely
48
+ // the newest, except when kubelet got restarted and registered
49
+ // all running plugins in random order.
50
+ return instances [len (instances )- 1 ]
41
51
}
42
52
43
53
// Set lets you save a DRA Plugin to the list and give it a specific name.
44
54
// This method is protected by a mutex.
45
- func (s * pluginsStore ) add (p * Plugin ) ( replacedPlugin * Plugin , replaced bool ) {
55
+ func (s * pluginsStore ) add (p * Plugin ) error {
46
56
s .Lock ()
47
57
defer s .Unlock ()
48
58
49
59
if s .store == nil {
50
- s .store = make (map [string ]* Plugin )
60
+ s .store = make (map [string ][] * Plugin )
51
61
}
52
-
53
- replacedPlugin , exists := s .store [p .name ]
54
- s .store [p .name ] = p
55
-
56
- if replacedPlugin != nil && replacedPlugin .cancel != nil {
57
- replacedPlugin .cancel (errors .New ("plugin got replaced" ))
62
+ for _ , oldP := range s .store [p .name ] {
63
+ if oldP .endpoint == p .endpoint {
64
+ // One plugin instance cannot hijack the endpoint of another instance.
65
+ return fmt .Errorf ("endpoint %s already registered for plugin %s" , p .endpoint , p .name )
66
+ }
58
67
}
59
-
60
- return replacedPlugin , exists
68
+ s . store [ p . name ] = append ( s . store [ p . name ], p )
69
+ return nil
61
70
}
62
71
63
- // Delete lets you delete a DRA Plugin by name.
64
- // This method is protected by a mutex.
65
- func (s * pluginsStore ) delete (pluginName string ) * Plugin {
72
+ // remove lets you remove one endpoint for a DRA Plugin.
73
+ // This method is protected by a mutex. It returns the
74
+ // plugin if found and true if that was the last instance
75
+ func (s * pluginsStore ) remove (pluginName , endpoint string ) (* Plugin , bool ) {
66
76
s .Lock ()
67
77
defer s .Unlock ()
68
78
69
- p , exists := s .store [pluginName ]
70
- if ! exists {
71
- return nil
79
+ instances := s .store [pluginName ]
80
+ i := slices .IndexFunc (instances , func (p * Plugin ) bool { return p .endpoint == endpoint })
81
+ if i == - 1 {
82
+ return nil , false
83
+ }
84
+ p := instances [i ]
85
+ last := len (instances ) == 1
86
+ if last {
87
+ delete (s .store , pluginName )
88
+ } else {
89
+ s .store [pluginName ] = slices .Delete (instances , i , i + 1 )
72
90
}
91
+
73
92
if p .cancel != nil {
74
93
p .cancel (errors .New ("plugin got removed" ))
75
94
}
76
- delete (s .store , pluginName )
77
-
78
- return p
95
+ return p , last
79
96
}
0 commit comments