プラグインは CoreDNS に機能を追加します。たとえば、*キャッシング*、*メトリクス*、基本的な *ゾーン* ファイルの提供はすべてプラグインです。
新しいプラグインを作成し、デフォルトで組み込みたい場合、つまりコードベースにマージしたい場合は、最初に Issue を作成して、初期設計やその他の問題について話し合ってください。ユーザーの視点から仕組みを説明する README ファイルから始めるのが通常は良い考えです。
プラグインの構造、記述、テスト方法の例については、サンプルプラグイン を参照してください。コードには、理解を深めるためのコメントが多数含まれています。
CoreDNS プラグインの登録方法
プラグインコードを記述する際には、CoreDNS に登録する必要があります。これは、次の関数を呼び出すことで実行できます。
func init() { plugin.Register("foo", setup) }
すべてのプラグインには、この場合は `foo` という名前が必要です。設定で `foo` が検出されると、このパッケージで `setup` 関数が呼び出されます。
セットアップ関数
`setup` 関数(名前は異なる場合がありますが、ほとんどすべてのプラグインは `setup` と呼んでいます)は、設定を解析し、内部データ構造を設定します。
setup 関数は `caddy.Controller` を受け取り、エラーを返します。(エラー報告を改善するために、返されたエラーの前に `plugin/foo:` を付けるために plugin.Error を使用します)。
func setup(c *caddy.Controller) error {
if err != nil {
return plugin.Error("foo", err)
}
// various other code
return nil
}
Corefile に次のような行がある場合
foo gizmo
最初の引数("gizmo")の値は次のように取得できます。
for c.Next() { // Skip the plugin name, "foo" in this case.
if !c.NextArg() { // Expect at least one value.
return c.ArgErr() // Otherwise it's an error.
}
value := c.Val() // Use the value.
}
プラグインのトークンを解析するには、解析するトークンが残っている限り true を返す `c.Next()` を反復処理します。プラグインは複数回出現する可能性があるため、プラグインのすべての出現を取得してトークンを消費するには、`c.Next()` を反復処理する必要があります。
CoreDNS への追加
プラグインを CoreDNS に組み込むには、`plugin.cfg` に配置し、`go generate` を実行します。
コアではない外部プラグインを使用している場合は、プラグインディレクトリからプラグインへのシンボリックリンクを作成するのが最も簡単です。つまり、
cd plugin
ln -s ../../example .
cd ..
vi plugin.cfg # add example:example
go generate
go build
CoreDNS でのプラグインの仕組み
プラグインパッケージの godoc を確認してください。最も重要なタイプは plugin.Handler です。
`Handler` は、DNS リクエストを処理する関数です。CoreDNS は DNS サーバーの設定に関するすべての処理を行いますが、これらの 2 つのタイプを実装する必要があります。
ハンドラの作成
`plugin.Handler` は、DNS を処理し、`ServeDNS` メソッドが `(int, error)` を返すことを除いて、`http.Handler` と同様のインターフェースです。`int` はステータスコード、`error` はログに記録されます(nil でない場合)。これらの戻り値の詳細については、plugin.md を参照してください。
ハンドラは通常、少なくとも 1 つのフィールドを持つ構造体であり、チェーン内の次のハンドラです。
type MyHandler struct {
Next plugin.Handler
}
`plugin.Handler` インターフェースを実装するには、`ServeDNS` というメソッドを記述します。このメソッドは実際のハンドラ関数であり、リクエストを単独で完全に処理しない限り、チェーン内の次のハンドラを呼び出す必要があります。
func (h MyHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
return h.Next.ServeDNS(ctx, w, r)
}
インターフェースには、`func Name() string` というメソッドも必要です。
func (h MyHandler) Name() string { return "foo" }
これで完了です(もちろん、DNS リクエストで実際に何かを行うすべてのコードを記述する必要があります)。
参考文献
CoreDNS に含まれるプラグインの簡単な例は次のとおりです。