Flex Gateway新着情報
Governance新着情報
Monitoring API ManagerFlex Gateway ポリシー開発キット (PDK) には、カスタムポリシーのインテグレーション回帰を検出するための自動化テストフレームワークが用意されています。
PDK が提供するインテグレーションテストフレームワークは、Docker コンテナのローカルモードで実行されている Flex Gateway のみをサポートします。接続モードで動作する Flex Gateway や別のプラットフォームにポリシーをデプロイする場合でも、まず Docker コンテナのローカルモードで実行されている Flex Gateway を使用して PDK でポリシーをテストしてください。
| ポリシーの開発とテストのみが目的であれば、Windows の Docker で Flex Gateway をローカルモードで実行することもできます。ただし、Flex Gateway は本番環境では Windows をサポートしていません。 |
ポリシーをテストするには、次のタスクを実行します。
始める前にを確認します。
インテグレーションテストのディレクトリ構造を確認します。
デフォルトでは、<root-directory>/tests ディレクトリには以下のファイルが保存されます。
tests
├── common.rs
├── requests.rs
└── common
└── logging.yaml
└── registration.yaml
/tests ディレクトリにはインテグレーションテストが保存されます。デフォルトでは以下のファイルが保存されます。
requests.rs ファイル: 個別のテストモジュールと実行ファイル。
commons.rs ファイル: すべてのインテグレーションテストモジュールに含める必要がある機能、API 設定、ポリシー設定が含まれたテストモジュール。
make test コマンドを使用してカスタムポリシーのデバッグを開始するには、ローカルモードで Flex Gateway を登録します。
make test コマンドが動作するためには、<root-directory>/tests/common ディレクトリに Flex Gateway の registration.yaml ファイルが存在する必要があります。このディレクトリで登録コマンドを実行してこのファイルを作成するか、または以前に登録してある Flex Gateway の registration.yaml ファイルをこのディレクトリに移動します。
Flex Gateway の登録については、以下を参照してください。
登録コマンドのみを実行してください。Docker の開始コマンドは、make test コマンドがこのステップを完了するため、実行しないでください。
|
ポリシーをテストするデバイスごとに異なる登録ファイルを作成してください。
登録ファイルはリモートリポジトリへの保存では無視され、プロジェクトディレクトリのルートにある .gitignore ファイルにリストされます。
各テスト関数では、その要求の API とポリシーの設定が必要です。
カスタムポリシーを設定する手順は、次のとおりです。
show-policy-ref-name を実行してポリシー ID を表示します。
make show-policy-ref-name
結果をコピーします。
commons.rs の {{project-name}} を自分のポリシー ID で上書きします。例:
pub const POLICY_NAME: &str = "<custom-policy-id>";
ポリシーの設定パラメーターを定義します。
設定パラメーターは、definition/gcl.yaml ファイルにあります。
既存のテストモジュール (/tests/requests.rs など) に新しいテスト関数を配置して、新しいテストモジュールを追加します。
PDK テスト関数は、#[pdk_test] 属性がつけられた非同期関数です。
use pdk_test::pdk_test;
#[pdk_test]
async fn say_hello() {
}
ボディが空であるため、この関数がエラーとなることはありません。make test を実行してすべてが正常に動作することを確認します。
|
/tests フォルダーのインテグレーションテストを実行するには、make test コマンドを実行します。
make test
インテグレーションテストに機能を追加するたびにこのテストを実行して、正しく設定されていることを確認してください。
make test コマンドは、インテグレーションテストを実行する前にポリシーをコンパイルします。
|
PDK インテグレーションテストには、Docker ネットワーク内で実行されるサービスの複合体が含まれます。サービスインスタンスは TestComposite オブジェクトに登録できます。すべてのサービスには、設定、ホスト名、インスタンスがあります。
Cargo.toml ファイルの [dev-dependencies] セクションにある pdk-test クレートは PDK のカスタムポリシーのインテグレーションテストを作成するためのすべての機能を提供します。
PDK のテストライブラリは以下のサービスをサポートします。
| サービス | 説明 |
|---|---|
|
Flex Gateway サービスインスタンス。 |
|
Rust の httpmock サーバーへのサービスバインド。 |
サポートされるサービスにより、インテグレーションテストの大半のユースケースがカバーされます。異なる種別のサービスを定義することはできません。
httpmock は、Rust で要求のモックを作成できるようにするモックサーバーです。 httpmock サービスは、HttpMockConfig 値を使用して設定します。テスト関数から結果を返すようにするのがベストプラクティスです。Rust の anyhow クレートは、異なるデフォルトエラー種別を返せるようにします。
httpmock サービスの設定は、次のコード例を参照してください。
use pdk_test::{pdk_test, TestComposite};
use pdk_test::services::httpmock::HttpMockConfig;
#[pdk_test]
async fn say_hello() -> anyhow::Result<()> {
// Configure HttpMock service
let backend_config = HttpMockConfig::builder()
.hostname("backend")
.port(80) // Port where the service will accept requests
.build();
// Register HTTPBin service and start the docker network
let composite = TestComposite::builder()
.with_service(backend_config)
.build()
.await?;
Ok(())
}
Docker エンジンが正しく設定されていれば、このテストは合格します。make test を実行して設定が正しいことを確認してください。
|
提供されるデフォルトの代わりに別のソースの httpmock Docker イメージを使用するには、設定ビルダーで提供される image_name() メソッドを使用して明示的に定義します。
代替 httpmock Docker イメージを設定するには、次の例のように HttpMockConfig::builder() 定義を更新します。
// Configure HttpMock service
let backend_config = HttpMockConfig::builder()
.image_name("myrepo/httpmock") // Custom image name setting
.hostname("backend")
.port(80) // Port where the service will accept requests
.build();
サービスの複合体で設定されているすべてのサービスインスタンスには、カスタムインタラクション用のハンドルがあります。このハンドルはサービスエンドポイントを使用できるようにするためのソケットを返します。
サービスのハンドルを見つけるには、次のコード例を参照してください。
use pdk_test::{pdk_test, TestComposite};
use pdk_test::services::httpmock::{HttpMock, HttpMockConfig};
#[pdk_test]
async fn say_hello() -> anyhow::Result<()> {
// Configure HTTPMock service
let backend_config = HttpMockConfig::builder()
.hostname("backend")
.build();
// Register HTTPMock service and start the docker network
let composite = TestComposite::builder()
.with_service(backend_config)
.port(80) // Port where the service accepts requests
.build()
.await?;
// Get the httpmock handle
let httpmock: HttpMock = composite.service()?;
Ok(())
}
httpmock インスタンスが正しく設定されていれば、このテストは合格します。make test を実行して設定が正しいことを確認してください。
|
エンドポイントをモックするには httpmock When/Then API を使用します。
エンドポイントをモックしたら、HTTP クライアントを使用してエンドポイント要求を実行します。
reqwest クレートは、最も包括的で柔軟な Rust HTTP クライアントを提供します。
エンドポイントをモックして要求を実行するには、次のコード例を参照してください。
use pdk_test::{pdk_test, TestComposite};
use pdk_test::services::httpmock::{HttpMock, HttpMockConfig};
#[pdk_test]
async fn say_hello() -> anyhow::Result<()> {
// Configure HttpMock service
let backend_config = HttpMockConfig::builder()
.hostname("backend")
.port(80) // Port where the service will accept requests
.build();
// Register HTTPBin service and start the docker network
let composite = TestComposite::builder()
.with_service(backend_config)
.build()
.await?;
// Get the httpmock handle
let httpmock: HttpMock = composite.service()?;
// Connect the mock server
let mock_server = httpmock::MockServer::connect_async(httpmock.socket()).await;
// Configure the endpoint mocks
mock_server.mock_async(|when, then| {
when.path_contains("/hello");
then.status(202).body("World!");
}).await;
let base_url = mock_server.base_url();
// Hit the endpoint
let response = reqwest::get(format!("{base_url}/hello")).await?;
// Assert on response
assert_eq!(response.status(), 202);
assert_eq!(response.text().await?, "World!");
Ok(())
}
make test を実行して設定が正しいことを確認してください。
|
Flex サービスは、TestComposite で FlexConfig 構造のインスタンスを登録して設定します。FlexConfig インスタンスを完了するには、ApiConfig および PolicyConfig インスタンスも定義する必要があります。
FlexConfig 構造には次のプロパティがあります。
| プロパティ | コンテンツ |
|---|---|
|
テストする Flex Gateway バージョン。 |
|
Flex Gateway Docker イメージ名 (デフォルトは「mulesoft/flex-gateway」)。 |
|
|
|
|
|
|
|
|
ApiConfig には次のプロパティがあります。
| プロパティ | コンテンツ |
|---|---|
|
API の名前。 |
|
アップストリームサービスへの参照。 |
|
アップストリーム要求の送信先パス。 |
|
API が要求をリスンするポート。 |
|
API に適用される |
PolicyConfig には次のプロパティがあります。
| プロパティ | コンテンツ |
|---|---|
|
適用するポリシー。 |
|
ポリシーのパラメーター。 |
次のコード例では、完全な Flex サービスを定義しています。
mod common;
use common::*;
use pdk_test::{pdk_test, TestComposite};
use pdk_test::port::Port;
use pdk_test::services::flex::FlexConfig;
// Port where Flex listens for requests
const FLEX_PORT: Port = 8081;
#[pdk_test]
async fn say_hello() -> anyhow::Result<()> {
// Configure an upstream service for the API
let httpmock_config = HttpMockConfig::builder()
.port(80)
.version("latest")
.hostname("backend")
.build();
// Configure a policy for the API
let policy_config = PolicyConfig::builder()
.name(POLICY_NAME)
.configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60}))
.build();
// Configure the API to deploy to the Flex
let api_config = ApiConfig::builder()
.name("ingress-http")
.upstream(&httpmock_config)
.path("/anything/echo/")
.port(FLEX_PORT)
.policies([policy_config])
.build();
// Configure the Flex service
let flex_config = FlexConfig::builder()
.version("1.6.1")
.hostname("local-flex")
.config_mounts([
(POLICY_DIR, "policy"),
(COMMON_CONFIG_DIR, "common")
])
.with_api(api_config)
.build();
let composite = TestComposite::builder()
.with_service(flex_config)
.with_service(httpmock_config)
.build()
.await?;
}
提供されるデフォルトの代わりに別のソースの flex Docker イメージを使用するには、設定ビルダーで提供される image_name() メソッドを使用して明示的に定義します。
代替 Flex Docker イメージを設定するには、次の例のように FlexConfig::builder() 定義を更新します。
// Configure the Flex service
let flex_config = FlexConfig::builder()
.image_name("myrepo/flex-gateway") // Custom image name setting
.version("1.6.1")
.hostname("local-flex")
.config_mounts([
(POLICY_DIR, "policy"),
(COMMON_CONFIG_DIR, "common")
])
.with_api(api_config)
.build();
|
|
Flex サービスは、ポートに応じた外部ベース URL でエンドポイントを表示します。これらの URL にアクセスするには、ポートごとにインデックス付けされた external_url() メソッドを Flex サービスインスタンスハンドルで指定する必要があります。例:
use pdk_test::{pdk_test, TestComposite, port::Port};
use pdk_test::services::flex::Flex;
const FLEX_PORT: Port = 8081;
async fn build_composite() -> anyhow::Result<TestComposite> {
todo!("Configuration stuff comes here")
}
#[pdk_test]
async fn say_hello() -> anyhow::Result<()> {
// Invoke a helper composite builder function for simplicity
let composite = build_composite().await?;
// Get the Flex service handle
let flex: Flex = composite.service()?;
// Get the URL for our configured port
let flex_url = flex.external_url(FLEX_PORT).unwrap();
let response = reqwest::get(format!("{flex_url}/hello")).await?;
// Make assertions
Ok(())
}
通常、PDK のインテグレーションテストには、Flex サービスと、1 つ以上のバックエンドサービスが含まれます。
次のコードは、カスタムポリシーの作成時に生成されるデフォルトのテストです。
mod common;
use httpmock::MockServer;
use pdk_test::{pdk_test, TestComposite};
use pdk_test::port::Port;
use pdk_test::services::flex::{FlexConfig, Flex};
use pdk_test::services::httpmock::{HttpMockConfig, HttpMock};
use common::*;
// Directory with the configurations for the `hello` test.
const HELLO_CONFIG_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/requests/hello");
// Flex port for the internal test network
const FLEX_PORT: Port = 8081;
// This integration test shows how to build a test to compose a local-flex instance
// with a MockServer backend
#[pdk_test]
async fn hello() -> anyhow::Result<()> {
// Configure an HttpMock service
let httpmock_config = HttpMockConfig::builder()
.port(80)
.version("latest")
.hostname("backend")
.build();
// Configure a policy for the API
let policy_config = PolicyConfig::builder()
.name(POLICY_NAME)
.configuration(serde_json::json!({"source": "http://backend/blocked", "frequency": 60}))
.build();
// Configure the API to deploy to the Flex
let api_config = ApiConfig::builder()
.name("ingress-http")
.upstream(&httpmock_config)
.path("/anything/echo/")
.port(FLEX_PORT)
.policies([policy_config])
.build();
// Configure the Flex service
let flex_config = FlexConfig::builder()
.version("1.6.1")
.hostname("local-flex")
.config_mounts([
(POLICY_DIR, "policy"),
(COMMON_CONFIG_DIR, "common")
])
.with_api(api_config)
.build();
// Compose the services
let composite = TestComposite::builder()
.with_service(flex_config)
.with_service(httpmock_config)
.build()
.await?;
// Get a handle to the Flex service
let flex: Flex = composite.service()?;
// Get an external URL to point the Flex service
let flex_url = flex.external_url(FLEX_PORT).unwrap();
// Get a handle to the HttpMock service
let httpmock: HttpMock = composite.service()?;
// Create a MockServer
let mock_server = MockServer::connect_async(httpmock.socket()).await;
// Mock a /hello request
mock_server.mock_async(|when, then| {
when.path_contains("/hello");
then.status(202).body("World!");
}).await;
// Perform an actual request
let response = reqwest::get(format!("{flex_url}/hello")).await?;
// Assert on the response
assert_eq!(response.status(), 202);
Ok(())
}
インテグレーションテストでエラーが発生した場合は、サービスログで原因を特定します。効率的にデバッグできるように、各テストフォルダーに専用のサービスログ (<root-directory>/target/pdk-test/<module-name>/<test>/<service>.log) があります。
たとえば、say_hello テストには次のサービスログがあります。
<root-directory>
├── Cargo.lock
├── Cargo.toml
├── playground
├── src
├── tests
└── target
└── pdk-test
└── requests
└── say_hello
└── <service>.log