diff options
author | 2018-07-01 20:01:17 +0100 | |
---|---|---|
committer | 2018-07-01 20:01:17 +0100 | |
commit | 99800a687c5da6b5b9c42ad0431e21151828612a (patch) | |
tree | 447d777a8e9c3763cb418de2e9c065c7d91e43bc /plugin/metadata/provider.go | |
parent | 0b326e26865af91474703322d5d9b1eb1e45a8ff (diff) | |
download | coredns-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.go | 102 |
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 +} |