Skip to content

Comprehensive PipelinePolicy test cases #976

@crstrn13

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 denypredicate: 'request.url_path == "/blocked"'/blocked returns 403, /get returns 200
  • Header-based denypredicate: '"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 codedeny with withStatus: 429 → denied request returns 429 instead of default
  • Deny with custom headersdeny with withHeaders: '[["x-deny-reason", "blocked"]]' → denied response includes custom headers
  • Deny with custom bodydeny with withBody: "Access denied" → denied response body is "Access denied"
  • Deny with all response fieldsdeny with withStatus, withHeaders, and withBody all set → all fields present in denied response

fail action

  • Fail terminates chainfail action with matching predicate and logMessage → request fails (503 or appropriate error), message logged
  • Fail does not triggerfail action with non-matching predicate → request passes through normally
  • Fail after gRPC callgrpc_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 callgrpc_method with a predicate → upstream is only called when predicate matches
  • gRPC upstream unavailableactionMethod points to a non-existent service → verify graceful failure (503 or appropriate error)
  • gRPC response var used in denygrpc_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 headerheadersToAdd: '[["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 headeradd_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 responsedeny in response phase with matching predicate and withStatus: 503 → backend response replaced with 503 before reaching client
  • Response deny with headers and bodydeny 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

Metadata

Metadata

Assignees

Labels

ExtensionsChanges related to Kuadrant's extension policiestest caseNew test case

Type

No type
No fields configured for issues without a type.

Projects

Status

🆕 New

Status

In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions