カスタムエンティティの保存
すべてのプラグインがそれを必要とするわけではありませんが、プラグインは、データベースでの構成以上のものを保存する必要があるかもしれません 。その場合、Kongは プライマリデータストアに加えて、抽象化したものを提供し、カスタムエンティティを保存できるようにします。
前の章で説明したように、Kongは “DAO”と呼ばれ、”DAOファクトリー”と呼ばれるシングルトンで利用できるクラスをとおして モデルレイヤーと相互作用します。この章では、 独自のエンティティの抽象化を提供する方法を説明します。
モジュール
kong.plugins.<plugin_name id="sl-md0000000">.daos
kong.plugins.<plugin_name id="sl-md0000000">.migrations.init
kong.plugins.<plugin_name id="sl-md0000000">.migrations.000_base_<plugin_name id="sl-md0000000">
kong.plugins.<plugin_name id="sl-md0000000">.migrations.001_<from-version id="sl-md0000000">_to_<to_version id="sl-md0000000">
kong.plugins.<plugin_name id="sl-md0000000">.migrations.002_<from-version id="sl-md0000000">_to_<to_version id="sl-md0000000">
移行フォルダの作成
モデルの定義を終えたら、Kongにより実行されエンティティの記録が 保存されるテーブルを作成する、移行モジュールを作成する必要が あります。
プラグインにまだない場合は、<plugin_name id="sl-md0000000">/migrations
フォルダをプラグインに追加します。init.lua
ファイルがフォルダ内にない場合は、1つ作成します。
ここで、プラグインのすべての移行が参照されます。
お使いのmigrations/init.lua
ファイルの初回バージョンは単一の移行を指します。
この例では、その移行を000_base_my_plugin
と呼びます。
-- `migrations/init.lua`
return {
"000_base_my_plugin",
}
これは、初期移行を含むファイルが<plugin_name id="sl-md0000000">/migrations/000_base_my_plugin.lua
に存在することを意味します。これがどのように行われるかは、次で説明します。
既存のプラグインに新しい移行を追加
プラグインのバージョンがリリースされた後で、変更を導入する必要がある場合が あります。新しい機能が必要になる場合があります。データベーステーブルの行の変更が必要となる可能性があります。
この場合、新しい移行ファイルを作成する必要があります 。 既存のマイグレーションファイルが公開された後は、変更してはいけません(必要であれば、より堅牢で 防弾にすることはできます。例えば、マイグレーションを常にリエントラントに書くようにします)。
移行ファイルに命名するための厳密なルールはありませんが、最初のファイルに000
、次のファイルに001
というようにプレフィックスを付けるという規則があります。
前の例に続いて、データベースに変更を加えた新しいバージョンのプラグインをリリースする場合(例えば foo
というテーブルが必要でした)、<plugin_name id="sl-md0000000">/migrations/001_100_to_110.lua
というファイルを追加し、migrations init ファイルで次のように参照します(100
はプラグインの以前のバージョン 1.0.0
、110
はプラグインが 1.1.0
に移行されるバージョン)。
-- `<plugin_name id="sl-md0000000">/migrations/init.lua`
return {
"000_base_my_plugin",
"001_100_to_110",
}
移行ファイルの構文
移行ファイルは、次の構造を持つテーブルを返すLuaファイルです。
-- `<plugin_name id="sl-md0000000">/migrations/000_base_my_plugin.lua`
return {
postgres = {
up = [[
CREATE TABLE IF NOT EXISTS "my_plugin_table" (
"id" UUID PRIMARY KEY,
"created_at" TIMESTAMP WITHOUT TIME ZONE,
"col1" TEXT
);
DO $$
BEGIN
CREATE INDEX IF NOT EXISTS "my_plugin_table_col1"
ON "my_plugin_table" ("col1");
EXCEPTION WHEN UNDEFINED_COLUMN THEN
-- Do nothing, accept existing state
END$$;
]],
}
}
-- `<plugin_name id="sl-md0000000">/migrations/001_100_to_110.lua`
return {
postgres = {
up = [[
DO $$
BEGIN
ALTER TABLE IF EXISTS ONLY "my_plugin_table" ADD "cache_key" TEXT UNIQUE;
EXCEPTION WHEN DUPLICATE_COLUMN THEN
-- Do nothing, accept existing state
END;
$$;
]],
teardown = function(connector, helpers)
assert(connector:connect_migrations())
assert(connector:query([[
DO $$
BEGIN
ALTER TABLE IF EXISTS ONLY "my_plugin_table" DROP "col1";
EXCEPTION WHEN UNDEFINED_COLUMN THEN
-- Do nothing, accept existing state
END$$;
]])
end,
}
}
各ストラテジセクションには、 up
とteardown
2 つの部分があります。
-
up
は、生のSQLステートメントのオプション文字列です。これらのステートメントは、kong migrations up
が実行されたときに実行されます。新しいテーブルの作成や新規レコードの追加といったあらゆる非破壊的な操作は、
up
セクションで実行することをお勧めします。 -
teardown
はオプションの Lua 関数であり、connector
パラメータを受け取ります。コネクタ はquery
メソッドを呼び出して SQL クエリを実行できます。ティアダウンはkong migrations finish
によって引き起こされます。データの削除や行タイプの変更、新規データの挿入といった破壊的な操作は、
teardown
セクションで実行することをお勧めします。
すべての SQLステートメントは、可能な限り再入可能になるように記述する必要があります。たとえば、 DROP TABLE
の代わりにDROP TABLE IF EXISTS
を使用し、CREATE INDEX
の代わりにCREATE INDEX IF NOT EXIST
を使用するなど。移行が何らかの理由で失敗した場合、問題解決での最初の試行は、単純に移行のやりなおしとなることが考えられます。
schema
でunique
制約を使用している場合は、PostgreSQLの移行でこの制約を設定する必要があります。
実際の例を確認するには、Key-Auth プラグインの移行を参照してください。
スキーマを定義する
カスタムプラグインでカスタムエンティティを使用する最初のステップは、1つまたは複数の スキーマ を定義することです。
スキーマはエンティティを記述するLuaテーブルです。たとえば、エンティティのさまざまなフィールドの名前やタイプは何か、などの構造情報があります。 これは、プラグイン設定を説明するフィールドに似ています。 プラグイン設定スキーマと比較すると、カスタムエンティティスキーマには 追加のメタデータが必要です(たとえば、どのフィールドがエンティティのプライマリキーを構成するかなど)。
スキーマは、次の名前のモジュールで定義します。
kong.plugins.<plugin_name id="sl-md0000000">.daos
つまり、プラグインフォルダ内に <plugin_name id="sl-md0000000">/daos.lua
というファイルがあるはずです。daos.lua
ファイルは、1 つ以上のスキーマを含むテーブルを返します。以下に例を示します。
-- daos.lua
local typedefs = require "kong.db.schema.typedefs"
return {
-- this plugin only results in one custom DAO, named `keyauth_credentials`:
{
name = "keyauth_credentials", -- the actual table in the database
endpoint_key = "key",
primary_key = { "id" },
cache_key = { "key" },
generate_admin_api = true,
admin_api_name = "key-auths",
admin_api_nested_name = "key-auth",
fields = {
{
-- a value to be inserted by the DAO itself
-- (think of serial id and the uniqueness of such required here)
id = typedefs.uuid,
},
{
-- also interted by the DAO itself
created_at = typedefs.auto_timestamp_s,
},
{
-- a foreign key to a consumer's id
consumer = {
type = "foreign",
reference = "consumers",
default = ngx.null,
on_delete = "cascade",
},
},
{
-- a unique API key
key = {
type = "string",
required = false,
unique = true,
auto = true,
},
},
},
},
}
この例のdaos.lua
ファイルでは、 keyauth_credentials
と呼ばれる単一のスキーマを導入しています。
以下は、最上位プロパティの説明です。
名称 | タイプ | 説明 | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
name |
string (必須) | DAO名(kong.db.\[name\] )の決定に使用されます。 | ||||||||||||||||||||||||||||||
primary_key |
table (必須) | エンティティのプライマリキーを形成するフィールド名。 スキーマは、ほとんどのKongコアエンティティがid という名前のUUIDを使用している場合でも、複合キーをサポートします。 | ||||||||||||||||||||||||||||||
endpoint_key |
string \(オプション\) | Admin APIで代替識別子として使用されるフィールドの名前。上の例ではkey が endpoint\_key です。つまり、id = 123 と key = "foo" を持つ認証情報は、/keyauth_credentials/123 と /keyauth_credentials/foo の両方として参照できます。 | ||||||||||||||||||||||||||||||
cache_key |
table \(オプション\) |
cache_key の生成に使用されるフィールドの名前が含まれ、Kongのキャッシュ内のエンティティを明確に識別する必要がある文字列です。通常、例のkey のような一意のフィールドが適切な候補となります。その他の場合には、複数のフィールドを組み合わせることが望ましいです。 | ||||||||||||||||||||||||||||||
generate_admin_api |
boolean \(オプション\) | エンティティの管理apiを自動生成するかどうか。デフォルトでは、admin apiはカスタムのものを含むすべてのdaoに対して生成されます。dao用に完全にカスタマイズされた管理apiを作成する場合、またはdaoの自動生成を完全に無効にする場合は、このオプションを false に設定します。 | ||||||||||||||||||||||||||||||
admin_api_name |
boolean \(オプション\) | generate_admin_api が有効になっている場合、admin api 自動ジェネレーターは、自動生成された管理apiのコレクションURLを取得するためにname を使用します。コレクションURLにname とは異なる別の名前を付けたい場合もあるでしょう。例えば、DAO keyauth_credentials においては、実際に、自動生成ツールがこのDAOのためのエンドポイントを、別の、より分かりやすいURL名key-auths で生成してくれることを期待していました。(例:http://
|