summaryrefslogtreecommitdiff
path: root/context.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-05-17 08:48:12 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-05-17 08:48:12 -0600
commit1a20fe330ecc39e8b98b5669b836f3b1b185f622 (patch)
treea728bbf310d112d7b54b14111717fea04b96d528 /context.go
parent1f0c061ce30f218e63fcc17e0fdfc8b90d754ba5 (diff)
Improve godoc for contexts
Diffstat (limited to 'context.go')
-rw-r--r--context.go39
1 files changed, 38 insertions, 1 deletions
diff --git a/context.go b/context.go
index ca2f44c..cfb183a 100644
--- a/context.go
+++ b/context.go
@@ -10,12 +10,30 @@ import (
"github.com/mholt/certmagic"
)
+// Context is a type which defines the lifetime of modules that
+// are loaded and provides access to the parent configuration
+// that spawned the modules which are loaded. It should be used
+// with care and only wrapped with derivation functions from
+// the standard context package if you don't need the Caddy
+// specific features. These contexts are cancelled when the
+// lifetime of the modules loaded from it are over.
+//
+// Use NewContext() to get a valid value (but most modules will
+// not actually need to do this).
type Context struct {
context.Context
moduleInstances map[string][]interface{}
cfg *Config
}
+// NewContext provides a new context derived from the given
+// context ctx. Normally, you will not need to call this
+// function unless you are loading modules which have a
+// different lifespan than the ones for the context the
+// module was provisioned with. Be sure to call the cancel
+// func when the context is to be cleaned up so that
+// modules which are loaded will be properly unloaded.
+// See standard library context package's documentation.
func NewContext(ctx Context) (Context, context.CancelFunc) {
newCtx := Context{moduleInstances: make(map[string][]interface{}), cfg: ctx.cfg}
c, cancel := context.WithCancel(ctx.Context)
@@ -36,6 +54,14 @@ func NewContext(ctx Context) (Context, context.CancelFunc) {
return newCtx, wrappedCancel
}
+// LoadModule decodes rawMsg into a new instance of mod and
+// returns the value. If mod.New() does not return a pointer
+// value, it is converted to one so that it is unmarshaled
+// into the underlying concrete type. If mod.New is nil, an
+// error is returned. If the module implements Validator or
+// Provisioner interfaces, those methods are invoked to
+// ensure the module is fully configured and valid before
+// being used.
func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{}, error) {
modulesMu.Lock()
mod, ok := modules[name]
@@ -74,7 +100,7 @@ func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{},
}
if validator, ok := val.(Validator); ok {
- err := validator.Validate(ctx)
+ err := validator.Validate()
if err != nil {
if cleanerUpper, ok := val.(CleanerUpper); ok {
err2 := cleanerUpper.Cleanup()
@@ -91,6 +117,17 @@ func (ctx Context) LoadModule(name string, rawMsg json.RawMessage) (interface{},
return val, nil
}
+// LoadModuleInline loads a module from a JSON raw message which decodes
+// to a map[string]interface{}, where one of the keys is moduleNameKey
+// and the corresponding value is the module name as a string, which
+// can be found in the given scope.
+//
+// This allows modules to be decoded into their concrete types and
+// used when their names cannot be the unique key in a map, such as
+// when there are multiple instances in the map or it appears in an
+// array (where there are no custom keys). In other words, the key
+// containing the module name is treated special/separate from all
+// the other keys.
func (ctx Context) LoadModuleInline(moduleNameKey, moduleScope string, raw json.RawMessage) (interface{}, error) {
moduleName, err := getModuleNameInline(moduleNameKey, raw)
if err != nil {