* Use gometalinter and enforcing go fmt/lint/vet Before this PR go fmt is enabled, go lint is suggest only. From time to time we have to manually check for go lint and go vet for any issues. This fix uses gometalinter and enforcing go fmt/lint/vet. Several reasons: - gometalinter could handle multiple linters concurrently - gometalinter supports suppression with `// nolint[: <linter>]` Previously one reason we didn't enable go lint was due to the ``` warning: context.Context should be the first parameter of a function (golint) ``` this is now possible with gometalinter and `// nolint: golint` (See changes). This fix also discovered several go vet issues and fixes it. Signed-off-by: Yong Tang <yong.tang.github@outlook.com> * Fix several issues reported by gometalinter (go vet) This commit fixes several issues reported by gometalinter (go vet). Signed-off-by: Yong Tang <yong.tang.github@outlook.com> * Increase deadline Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
102 lines
3.3 KiB
Go
102 lines
3.3 KiB
Go
// Package plugin provides some types and functions common among plugin.
|
|
package plugin
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/miekg/dns"
|
|
ot "github.com/opentracing/opentracing-go"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
type (
|
|
// Plugin is a middle layer which represents the traditional
|
|
// idea of plugin: it chains one Handler to the next by being
|
|
// passed the next Handler in the chain.
|
|
Plugin func(Handler) Handler
|
|
|
|
// Handler is like dns.Handler except ServeDNS may return an rcode
|
|
// and/or error.
|
|
//
|
|
// If ServeDNS writes to the response body, it should return a status
|
|
// code. If the status code is not one of the following:
|
|
//
|
|
// * SERVFAIL (dns.RcodeServerFailure)
|
|
//
|
|
// * REFUSED (dns.RecodeRefused)
|
|
//
|
|
// * FORMERR (dns.RcodeFormatError)
|
|
//
|
|
// * NOTIMP (dns.RcodeNotImplemented)
|
|
//
|
|
// CoreDNS assumes *no* reply has yet been written. All other response
|
|
// codes signal other handlers above it that the response message is
|
|
// already written, and that they should not write to it also.
|
|
//
|
|
// If ServeDNS encounters an error, it should return the error value
|
|
// so it can be logged by designated error-handling plugin.
|
|
//
|
|
// If writing a response after calling another ServeDNS method, the
|
|
// returned rcode SHOULD be used when writing the response.
|
|
//
|
|
// If handling errors after calling another ServeDNS method, the
|
|
// returned error value SHOULD be logged or handled accordingly.
|
|
//
|
|
// Otherwise, return values should be propagated down the plugin
|
|
// chain by returning them unchanged.
|
|
Handler interface {
|
|
ServeDNS(context.Context, dns.ResponseWriter, *dns.Msg) (int, error)
|
|
Name() string
|
|
}
|
|
|
|
// HandlerFunc is a convenience type like dns.HandlerFunc, except
|
|
// ServeDNS returns an rcode and an error. See Handler
|
|
// documentation for more information.
|
|
HandlerFunc func(context.Context, dns.ResponseWriter, *dns.Msg) (int, error)
|
|
)
|
|
|
|
// ServeDNS implements the Handler interface.
|
|
func (f HandlerFunc) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
return f(ctx, w, r)
|
|
}
|
|
|
|
// Name implements the Handler interface.
|
|
func (f HandlerFunc) Name() string { return "handlerfunc" }
|
|
|
|
// Error returns err with 'plugin/name: ' prefixed to it.
|
|
func Error(name string, err error) error { return fmt.Errorf("%s/%s: %s", "plugin", name, err) }
|
|
|
|
// NextOrFailure calls next.ServeDNS when next is not nill, otherwise it will return, a ServerFailure
|
|
// and a nil error.
|
|
func NextOrFailure(name string, next Handler, ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { // nolint: golint
|
|
if next != nil {
|
|
if span := ot.SpanFromContext(ctx); span != nil {
|
|
child := span.Tracer().StartSpan(next.Name(), ot.ChildOf(span.Context()))
|
|
defer child.Finish()
|
|
ctx = ot.ContextWithSpan(ctx, child)
|
|
}
|
|
return next.ServeDNS(ctx, w, r)
|
|
}
|
|
|
|
return dns.RcodeServerFailure, Error(name, errors.New("no next plugin found"))
|
|
}
|
|
|
|
// ClientWrite returns true if the response has been written to the client.
|
|
// Each plugin to adhire to this protocol.
|
|
func ClientWrite(rcode int) bool {
|
|
switch rcode {
|
|
case dns.RcodeServerFailure:
|
|
fallthrough
|
|
case dns.RcodeRefused:
|
|
fallthrough
|
|
case dns.RcodeFormatError:
|
|
fallthrough
|
|
case dns.RcodeNotImplemented:
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Namespace is the namespace used for the metrics.
|
|
const Namespace = "coredns"
|