aboutsummaryrefslogtreecommitdiff
path: root/plugin/metadata/provider.go
diff options
context:
space:
mode:
authorGravatar Miek Gieben <miek@miek.nl> 2018-07-01 20:01:17 +0100
committerGravatar GitHub <noreply@github.com> 2018-07-01 20:01:17 +0100
commit99800a687c5da6b5b9c42ad0431e21151828612a (patch)
tree447d777a8e9c3763cb418de2e9c065c7d91e43bc /plugin/metadata/provider.go
parent0b326e26865af91474703322d5d9b1eb1e45a8ff (diff)
downloadcoredns-99800a687c5da6b5b9c42ad0431e21151828612a.tar.gz
coredns-99800a687c5da6b5b9c42ad0431e21151828612a.tar.zst
coredns-99800a687c5da6b5b9c42ad0431e21151828612a.zip
plugin/metadata: metadata is just label=value (#1914)
This revert 17d807f0 and re-adds the metadata plugin as a plugin that just sets a label to a value function. Add package documentation on how to use the metadata package. Make it clear that any caching is up to the Func implemented. There are now - no in tree users. We could add the request metadata by default under names that copy request.Request, i.e request/ip - remote IP request/port - remote port Variables.go has been deleted. Signed-off-by: Miek Gieben <miek@miek.nl>
Diffstat (limited to 'plugin/metadata/provider.go')
-rw-r--r--plugin/metadata/provider.go102
1 files changed, 77 insertions, 25 deletions
diff --git a/plugin/metadata/provider.go b/plugin/metadata/provider.go
index e13f9c896..eb7bb9755 100644
--- a/plugin/metadata/provider.go
+++ b/plugin/metadata/provider.go
@@ -1,3 +1,33 @@
+// Package metadata provides an API that allows plugins to add metadata to the context.
+// Each metadata is stored under a label that has the form <plugin>/<name>. Each metadata
+// is returned as a Func. When Func is called the metadata is returned. If Func is expensive to
+// execute it is its responsibility to provide some form of caching. During the handling of a
+// query it is expected the metadata stays constant.
+//
+// Basic example:
+//
+// Implement the Provder interface for a plugin:
+//
+// func (p P) Metadata(ctx context.Context, state request.Request) context.Context {
+// cached := ""
+// f := func() string {
+// if cached != "" {
+// return cached
+// }
+// cached = expensiveFunc()
+// return cached
+// }
+// metadata.SetValueFunc(ctx, "test/something", f)
+// return ctx
+// }
+//
+// Check the metadata from another plugin:
+//
+// // ...
+// valueFunc := metadata.ValueFunc(ctx, "test/something")
+// value := valueFunc()
+// // use 'value'
+//
package metadata
import (
@@ -8,40 +38,62 @@ import (
// Provider interface needs to be implemented by each plugin willing to provide
// metadata information for other plugins.
-// Note: this method should work quickly, because it is called for every request
-// from the metadata plugin.
type Provider interface {
- // List of variables which are provided by current Provider. Must remain constant.
- MetadataVarNames() []string
- // Metadata is expected to return a value with metadata information by the key
- // from 4th argument. Value can be later retrieved from context by any other plugin.
- // If value is not available by some reason returned boolean value should be false.
- Metadata(ctx context.Context, state request.Request, variable string) (interface{}, bool)
+ // Metadata adds metadata to the context and returns a (potentially) new context.
+ // Note: this method should work quickly, because it is called for every request
+ // from the metadata plugin.
+ Metadata(ctx context.Context, state request.Request) context.Context
}
-// M is metadata information storage.
-type M map[string]interface{}
+// Func is the type of function in the metadata, when called they return the value of the label.
+type Func func() string
-// FromContext retrieves the metadata from the context.
-func FromContext(ctx context.Context) (M, bool) {
- if metadata := ctx.Value(metadataKey{}); metadata != nil {
- if m, ok := metadata.(M); ok {
- return m, true
+// Labels returns all metadata keys stored in the context. These label names should be named
+// as: plugin/NAME, where NAME is something descriptive.
+func Labels(ctx context.Context) []string {
+ if metadata := ctx.Value(key{}); metadata != nil {
+ if m, ok := metadata.(md); ok {
+ return keys(m)
}
}
- return M{}, false
+ return nil
}
-// Value returns metadata value by key.
-func (m M) Value(key string) (value interface{}, ok bool) {
- value, ok = m[key]
- return value, ok
+// ValueFunc returns the value function of label. If none can be found nil is returned. Calling the
+// function returns the value of the label.
+func ValueFunc(ctx context.Context, label string) Func {
+ if metadata := ctx.Value(key{}); metadata != nil {
+ if m, ok := metadata.(md); ok {
+ return m[label]
+ }
+ }
+ return nil
}
-// SetValue sets the metadata value under key.
-func (m M) SetValue(key string, val interface{}) {
- m[key] = val
+// SetValueFunc set the metadata label to the value function. If no metadata can be found this is a noop and
+// false is returned. Any existing value is overwritten.
+func SetValueFunc(ctx context.Context, label string, f Func) bool {
+ if metadata := ctx.Value(key{}); metadata != nil {
+ if m, ok := metadata.(md); ok {
+ m[label] = f
+ return true
+ }
+ }
+ return false
}
-// metadataKey defines the type of key that is used to save metadata into the context.
-type metadataKey struct{}
+// md is metadata information storage.
+type md map[string]Func
+
+// key defines the type of key that is used to save metadata into the context.
+type key struct{}
+
+func keys(m map[string]Func) []string {
+ s := make([]string, len(m))
+ i := 0
+ for k := range m {
+ s[i] = k
+ i++
+ }
+ return s
+}