|
3 | 3 | package registry |
4 | 4 |
|
5 | 5 | import ( |
| 6 | + "fmt" |
6 | 7 | "strings" |
7 | 8 | "sync" |
8 | 9 |
|
9 | 10 | gofig "github.com/akutz/gofig/types" |
10 | 11 | "github.com/akutz/goof" |
11 | 12 |
|
12 | 13 | "github.com/codedellemc/libstorage/api/types" |
| 14 | + apitypesV1 "github.com/codedellemc/libstorage/api/types/v1" |
13 | 15 | ) |
14 | 16 |
|
15 | 17 | var ( |
| 18 | + modTypeCtors = map[string]func() interface{}{} |
| 19 | + modTypeCtorsRWL = &sync.RWMutex{} |
| 20 | + |
16 | 21 | storExecsCtors = map[string]types.NewStorageExecutor{} |
17 | 22 | storExecsCtorsRWL = &sync.RWMutex{} |
18 | 23 |
|
@@ -44,6 +49,13 @@ func RegisterConfigReg(name string, f types.NewConfigReg) { |
44 | 49 | cfgRegs = append(cfgRegs, &cregW{name, f}) |
45 | 50 | } |
46 | 51 |
|
| 52 | +// RegisterModType registers a type from a plug-in mod. |
| 53 | +func RegisterModType(name string, ctor func() interface{}) { |
| 54 | + modTypeCtorsRWL.Lock() |
| 55 | + defer modTypeCtorsRWL.Unlock() |
| 56 | + modTypeCtors[strings.ToLower(name)] = ctor |
| 57 | +} |
| 58 | + |
47 | 59 | // RegisterRouter registers a Router. |
48 | 60 | func RegisterRouter(router types.Router) { |
49 | 61 | routersRWL.Lock() |
@@ -80,6 +92,31 @@ func RegisterIntegrationDriver(name string, ctor types.NewIntegrationDriver) { |
80 | 92 | intDriverCtors[strings.ToLower(name)] = ctor |
81 | 93 | } |
82 | 94 |
|
| 95 | +// NewModType returns a new instance of the specified module type. |
| 96 | +func NewModType(name string) (apitypesV1.Driver, error) { |
| 97 | + |
| 98 | + var ok bool |
| 99 | + var ctor func() interface{} |
| 100 | + |
| 101 | + func() { |
| 102 | + modTypeCtorsRWL.RLock() |
| 103 | + defer modTypeCtorsRWL.RUnlock() |
| 104 | + ctor, ok = modTypeCtors[name] |
| 105 | + }() |
| 106 | + |
| 107 | + if !ok { |
| 108 | + return nil, goof.WithField("modType", name, "invalid type name") |
| 109 | + } |
| 110 | + |
| 111 | + d, ok := ctor().(apitypesV1.Driver) |
| 112 | + if !ok { |
| 113 | + return nil, goof.WithField( |
| 114 | + "modType", fmt.Sprintf("%T", d), "invalid type") |
| 115 | + } |
| 116 | + |
| 117 | + return d, nil |
| 118 | +} |
| 119 | + |
83 | 120 | // NewStorageExecutor returns a new instance of the executor specified by the |
84 | 121 | // executor name. |
85 | 122 | func NewStorageExecutor(name string) (types.StorageExecutor, error) { |
@@ -177,6 +214,23 @@ func ConfigRegs(ctx types.Context) <-chan gofig.ConfigRegistration { |
177 | 214 | return c |
178 | 215 | } |
179 | 216 |
|
| 217 | +// ModTypes returns a channel on which new instances of all registered |
| 218 | +// module types. |
| 219 | +func ModTypes() <-chan apitypesV1.Driver { |
| 220 | + c := make(chan apitypesV1.Driver) |
| 221 | + go func() { |
| 222 | + modTypeCtorsRWL.RLock() |
| 223 | + defer modTypeCtorsRWL.RUnlock() |
| 224 | + for _, ctor := range modTypeCtors { |
| 225 | + if d, ok := ctor().(apitypesV1.Driver); ok { |
| 226 | + c <- d |
| 227 | + } |
| 228 | + } |
| 229 | + close(c) |
| 230 | + }() |
| 231 | + return c |
| 232 | +} |
| 233 | + |
180 | 234 | // StorageExecutors returns a channel on which new instances of all registered |
181 | 235 | // storage executors can be received. |
182 | 236 | func StorageExecutors() <-chan types.StorageExecutor { |
|
0 commit comments