@@ -37,9 +37,10 @@ import (
37
37
// not actually need to do this).
38
38
type Context struct {
39
39
context.Context
40
- moduleInstances map [string ][]any
40
+ moduleInstances map [string ][]Module
41
41
cfg * Config
42
42
cleanupFuncs []func ()
43
+ ancestry []Module
43
44
}
44
45
45
46
// NewContext provides a new context derived from the given
@@ -51,7 +52,7 @@ type Context struct {
51
52
// modules which are loaded will be properly unloaded.
52
53
// See standard library context package's documentation.
53
54
func NewContext (ctx Context ) (Context , context.CancelFunc ) {
54
- newCtx := Context {moduleInstances : make (map [string ][]any ), cfg : ctx .cfg }
55
+ newCtx := Context {moduleInstances : make (map [string ][]Module ), cfg : ctx .cfg }
55
56
c , cancel := context .WithCancel (ctx .Context )
56
57
wrappedCancel := func () {
57
58
cancel ()
@@ -90,15 +91,15 @@ func (ctx *Context) OnCancel(f func()) {
90
91
// ModuleMap may be used in place of map[string]json.RawMessage. The return value's
91
92
// underlying type mirrors the input field's type:
92
93
//
93
- // json.RawMessage => any
94
- // []json.RawMessage => []any
95
- // [][]json.RawMessage => [][]any
96
- // map[string]json.RawMessage => map[string]any
97
- // []map[string]json.RawMessage => []map[string]any
94
+ // json.RawMessage => any
95
+ // []json.RawMessage => []any
96
+ // [][]json.RawMessage => [][]any
97
+ // map[string]json.RawMessage => map[string]any
98
+ // []map[string]json.RawMessage => []map[string]any
98
99
//
99
100
// The field must have a "caddy" struct tag in this format:
100
101
//
101
- // caddy:"key1=val1 key2=val2"
102
+ // caddy:"key1=val1 key2=val2"
102
103
//
103
104
// To load modules, a "namespace" key is required. For example, to load modules
104
105
// in the "http.handlers" namespace, you'd put: `namespace=http.handlers` in the
@@ -115,7 +116,7 @@ func (ctx *Context) OnCancel(f func()) {
115
116
// meaning the key containing the module's name that is defined inline with the module
116
117
// itself. You must specify the inline key in a struct tag, along with the namespace:
117
118
//
118
- // caddy:"namespace=http.handlers inline_key=handler"
119
+ // caddy:"namespace=http.handlers inline_key=handler"
119
120
//
120
121
// This will look for a key/value pair like `"handler": "..."` in the json.RawMessage
121
122
// in order to know the module name.
@@ -301,17 +302,17 @@ func (ctx Context) loadModuleMap(namespace string, val reflect.Value) (map[strin
301
302
// like from embedded scripts, etc.
302
303
func (ctx Context ) LoadModuleByID (id string , rawMsg json.RawMessage ) (any , error ) {
303
304
modulesMu .RLock ()
304
- mod , ok := modules [id ]
305
+ modInfo , ok := modules [id ]
305
306
modulesMu .RUnlock ()
306
307
if ! ok {
307
308
return nil , fmt .Errorf ("unknown module: %s" , id )
308
309
}
309
310
310
- if mod .New == nil {
311
- return nil , fmt .Errorf ("module '%s' has no constructor" , mod .ID )
311
+ if modInfo .New == nil {
312
+ return nil , fmt .Errorf ("module '%s' has no constructor" , modInfo .ID )
312
313
}
313
314
314
- val := mod .New ().( any )
315
+ val := modInfo .New ()
315
316
316
317
// value must be a pointer for unmarshaling into concrete type, even if
317
318
// the module's concrete type is a slice or map; New() *should* return
@@ -327,7 +328,7 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
327
328
if len (rawMsg ) > 0 {
328
329
err := strictUnmarshalJSON (rawMsg , & val )
329
330
if err != nil {
330
- return nil , fmt .Errorf ("decoding module config: %s: %v" , mod , err )
331
+ return nil , fmt .Errorf ("decoding module config: %s: %v" , modInfo , err )
331
332
}
332
333
}
333
334
@@ -340,6 +341,8 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
340
341
return nil , fmt .Errorf ("module value cannot be null" )
341
342
}
342
343
344
+ ctx .ancestry = append (ctx .ancestry , val )
345
+
343
346
if prov , ok := val .(Provisioner ); ok {
344
347
err := prov .Provision (ctx )
345
348
if err != nil {
@@ -351,7 +354,7 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
351
354
err = fmt .Errorf ("%v; additionally, cleanup: %v" , err , err2 )
352
355
}
353
356
}
354
- return nil , fmt .Errorf ("provision %s: %v" , mod , err )
357
+ return nil , fmt .Errorf ("provision %s: %v" , modInfo , err )
355
358
}
356
359
}
357
360
@@ -365,7 +368,7 @@ func (ctx Context) LoadModuleByID(id string, rawMsg json.RawMessage) (any, error
365
368
err = fmt .Errorf ("%v; additionally, cleanup: %v" , err , err2 )
366
369
}
367
370
}
368
- return nil , fmt .Errorf ("%s: invalid configuration: %v" , mod , err )
371
+ return nil , fmt .Errorf ("%s: invalid configuration: %v" , modInfo , err )
369
372
}
370
373
}
371
374
@@ -439,8 +442,10 @@ func (ctx Context) Storage() certmagic.Storage {
439
442
return ctx .cfg .storage
440
443
}
441
444
445
+ // TODO: aw man, can I please change this?
442
446
// Logger returns a logger that can be used by mod.
443
447
func (ctx Context ) Logger (mod Module ) * zap.Logger {
448
+ // TODO: if mod is nil, use ctx.Module() instead...
444
449
if ctx .cfg == nil {
445
450
// often the case in tests; just use a dev logger
446
451
l , err := zap .NewDevelopment ()
@@ -451,3 +456,34 @@ func (ctx Context) Logger(mod Module) *zap.Logger {
451
456
}
452
457
return ctx .cfg .Logging .Logger (mod )
453
458
}
459
+
460
+ // TODO: use this
461
+ // // Logger returns a logger that can be used by the current module.
462
+ // func (ctx Context) Log() *zap.Logger {
463
+ // if ctx.cfg == nil {
464
+ // // often the case in tests; just use a dev logger
465
+ // l, err := zap.NewDevelopment()
466
+ // if err != nil {
467
+ // panic("config missing, unable to create dev logger: " + err.Error())
468
+ // }
469
+ // return l
470
+ // }
471
+ // return ctx.cfg.Logging.Logger(ctx.Module())
472
+ // }
473
+
474
+ // Modules returns the lineage of modules that this context provisioned,
475
+ // with the most recent/current module being last in the list.
476
+ func (ctx Context ) Modules () []Module {
477
+ mods := make ([]Module , len (ctx .ancestry ))
478
+ copy (mods , ctx .ancestry )
479
+ return mods
480
+ }
481
+
482
+ // Module returns the current module, or the most recent one
483
+ // provisioned by the context.
484
+ func (ctx Context ) Module () Module {
485
+ if len (ctx .ancestry ) == 0 {
486
+ return nil
487
+ }
488
+ return ctx .ancestry [len (ctx .ancestry )- 1 ]
489
+ }
0 commit comments