Skip to content

Comprehensive PipelinePolicy test cases #976

Description

@crstrn13

Parent

Part of #974 — Extensions SDK testing: PipelinePolicy
Depends on #975 — PipelinePolicy model, fixtures, and basic happy-path test

Context

Once the model class, fixtures, and basic happy path are in place (#975), we need thorough test coverage for PipelinePolicy's features. PipelinePolicy is a generic, declarative extension — different scenarios are different YAML specs — so the test matrix naturally covers the SDK's action types, CEL predicates, pipeline ordering, and targeting modes.

The extension is pre-installed on the test cluster via the helm chart — these tests assume it is already available.

Test cases

Request actions

deny action

  • CEL predicate denies request — Policy with deny action where predicate evaluates to true → request returns 403
  • CEL predicate does not deny request — Policy with deny action where predicate evaluates to false → request returns 200
  • Path-based deny — predicate: 'request.url_path == "/blocked"' → /blocked returns 403, /get returns 200
  • Header-based deny — predicate: '"x-blocked" in request.headers' → requests with header get denied, without header pass
  • Multiple deny actions (OR behavior) — Two deny actions in sequence; request is denied if either predicate matches
  • Deny with custom status code — deny with withStatus: 429 → denied request returns 429 instead of default
  • Deny with custom headers — deny with withHeaders: '[["x-deny-reason", "blocked"]]' → denied response includes custom headers
  • Deny with custom body — deny with withBody: "Access denied" → denied response body is "Access denied"
  • Deny with all response fields — deny with withStatus, withHeaders, and withBody all set → all fields present in denied response

fail action

  • Fail terminates chain — fail action with matching predicate and logMessage → request fails (503 or appropriate error), message logged
  • Fail does not trigger — fail action with non-matching predicate → request passes through normally
  • Fail after gRPC call — grpc_method populates variable, fail checks variable for invalid state → chain terminates on bad response

grpc_method action

  • Basic gRPC upstream call — Register an actionMethod pointing to a gRPC service, use grpc_method request action with var → verify the upstream is called (use the response var in a subsequent action)
  • Conditional gRPC call — grpc_method with a predicate → upstream is only called when predicate matches
  • gRPC upstream unavailable — actionMethod points to a non-existent service → verify graceful failure (503 or appropriate error)
  • gRPC response var used in deny — grpc_method stores response in var, subsequent deny action uses that var in predicate → deny decision based on gRPC response

Response actions

add_headers action

  • Single header — headersToAdd: '[["x-custom", "value"]]' → response contains x-custom: value
  • Multiple headers — Add multiple headers in a single action via CEL array → all present in response
  • Multiple add_headers actions — Two separate response actions each adding headers → all headers present
  • Conditional header — add_headers with predicate → header only added when predicate matches
  • Mutually exclusive headers via predicates — Two add_headers actions with opposite predicates → only one set of headers appears depending on request

deny action in response phase

  • Override response — deny in response phase with matching predicate and withStatus: 503 → backend response replaced with 503 before reaching client
  • Response deny with headers and body — deny in response phase with withStatus, withHeaders, and withBody → client receives the deny response instead of backend response

Pipeline ordering and composition

  • Request action ordering matters — A deny action before a grpc_method action: if deny triggers, gRPC is never called
  • Fail before gRPC — A fail action before a grpc_method action: if fail triggers, gRPC is never called
  • Response action ordering — Multiple response actions execute in spec order
  • Empty pipeline — PipelinePolicy with targetRef but no actions → requests pass through unmodified (200, no extra headers)
  • Request-only pipeline — Only request actions, no response actions → deny/fail works, no header modifications
  • Response-only pipeline — Only response actions, no request actions → all requests pass, headers modified
  • Mixed pipeline — Request actions (grpc_method + deny) followed by response actions (add_headers) → full pipeline executes in order

Pipeline validation

  • Variable forward reference rejected — Action references a var before the grpc_method that populates it → pipeline should fail to commit/enforce
  • Duplicate variable name rejected — Two grpc_method actions with the same var name → pipeline should fail to commit/enforce
  • Request after response phase rejected — Request actions defined after response actions → pipeline should fail to commit/enforce

TargetRef variations

  • Target HTTPRoute — PipelinePolicy targeting an HTTPRoute → only traffic through that route is affected
  • Target Gateway — PipelinePolicy targeting a Gateway → all routes on the gateway are affected
  • Target with sectionName — PipelinePolicy targeting a specific Gateway listener or HTTPRoute rule

Policy lifecycle

  • Policy status conditions — After commit, PipelinePolicy status shows Accepted: True and Enforced: True
  • Delete policy — After deleting the PipelinePolicy, traffic flows without pipeline actions (no headers, no blocking). Mark flaky(reruns=0) since it deletes a module-scoped fixture
  • Update policy — Modify the policy spec (e.g., change the deny predicate) and verify the new behavior takes effect

Interaction with other Kuadrant policies

  • PipelinePolicy + AuthPolicy — Both policies target the same route; verify both are enforced (auth identity + pipeline actions)
  • PipelinePolicy + RateLimitPolicy — Both policies target the same route; verify rate limits apply alongside pipeline actions

Error and edge cases

  • Invalid targetRef — PipelinePolicy targeting a non-existent HTTPRoute → policy should not reach Enforced state
  • Invalid CEL expression — Malformed predicate in deny action → policy behavior (should fail to enforce or reject)

Notes

  • These tests assume the extension is already installed on the cluster via the helm chart.
  • Use the PipelinePolicy class from PipelinePolicy model, fixtures, and basic happy-path test #975.
  • For gRPC upstream tests, a mock gRPC service will need to be deployed. Consider using Mockserver or a simple test gRPC server.

Test location

testsuite/tests/singlecluster/extensions/pipeline_policy/
  ├── conftest.py
  ├── test_pipeline_policy_basic.py         # (from #975)
  ├── test_pipeline_policy_deny.py          # deny action variants (request + response phase)
  ├── test_pipeline_policy_fail.py          # fail action tests
  ├── test_pipeline_policy_grpc.py          # grpc_method action tests
  ├── test_pipeline_policy_response.py      # add_headers response actions
  ├── test_pipeline_policy_composition.py   # pipeline ordering, empty/partial pipelines
  ├── test_pipeline_policy_validation.py    # pipeline validation (forward refs, dup vars, phase ordering)
  ├── test_pipeline_policy_targeting.py     # HTTPRoute vs Gateway vs sectionName
  ├── test_pipeline_policy_lifecycle.py     # create/update/delete, status conditions
  └── test_pipeline_policy_interactions.py  # interaction with AuthPolicy, RateLimitPolicy

Acceptance criteria

  • Test coverage for all request action types (deny, fail, grpc_method)
  • Test coverage for response action types (add_headers, deny in response phase)
  • Deny action response customization (withStatus, withHeaders, withBody)
  • Pipeline validation tests (forward references, duplicate vars, phase ordering)
  • Pipeline ordering and composition tests
  • TargetRef variations (HTTPRoute, Gateway, sectionName)
  • Policy lifecycle tests (status, delete, update)
  • Interaction tests with AuthPolicy and RateLimitPolicy
  • make commit-acceptance passes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

ExtensionsChanges related to Kuadrant's extension policiestest-caseNew test case

Type

No type

Projects

  • Status
    🆕 New
  • Status
    In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions