Skip to content

feat: support plugins field in ApisixConsumer#412

Merged
AlinsRan merged 1 commit into
masterfrom
feat/apisixconsumer-plugins
May 13, 2026
Merged

feat: support plugins field in ApisixConsumer#412
AlinsRan merged 1 commit into
masterfrom
feat/apisixconsumer-plugins

Conversation

@AlinsRan
Copy link
Copy Markdown
Contributor

@AlinsRan AlinsRan commented May 8, 2026

Summary

Closes #397

Add a generic plugins field to ApisixConsumerSpec so that consumer-scoped plugins (e.g. limit-count, limit-req) can be attached to an ApisixConsumer resource directly, without being limited to the auth plugins exposed through authParameter.

Changes

API (api/v2/apisixconsumer_types.go)

  • authParameter is now optional (omitempty). Both authParameter and plugins are optional at the API level; the controller handles the case where neither is set.
  • New Plugins []ApisixRoutePlugin field, following the same pattern as ApisixRoute and ApisixGlobalRule.

Translator (internal/adc/translator/apisixconsumer.go)

  • After building the auth plugin from authParameter, iterates Spec.Plugins and merges enabled plugins into the consumer plugin map via the existing buildPluginConfig helper. An enabled plugin with the same name as the auth plugin derived from authParameter takes precedence.

Deepcopy (api/v2/zz_generated.deepcopy.go)

  • ApisixConsumerSpec.DeepCopyInto updated to handle the new Plugins slice and the now-optional AuthParameter pointer.

Example

Auth via authParameter + extra plugins (existing style, still works)

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: my-consumer
spec:
  authParameter:
    keyAuth:
      value:
        key: my-secret-key
  plugins:
    - name: limit-count
      enable: true
      config:
        count: 100
        time_window: 60
        rejected_code: 429

Auth configured directly in plugins (new style, authParameter omitted)

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: my-consumer
spec:
  plugins:
    - name: key-auth
      enable: true
      config:
        key: my-secret-key
    - name: limit-count
      enable: true
      config:
        count: 100
        time_window: 60

Copilot AI review requested due to automatic review settings May 8, 2026 20:34
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

ApisixConsumerSpec now marks AuthParameter as optional and adds an XValidation rule requiring at least one auth method or a non-empty plugins list. The CRD schema adds a consumer plugins array. Deep-copy logic nil-checks and copies Plugins; the translator merges enabled consumer-scoped plugins into the final plugins map.

Changes

Plugin Support for ApisixConsumer

Layer / File(s) Summary
Data Contract and Validation Rule
api/v2/apisixconsumer_types.go
AuthParameter marked optional with omitempty tags and validation:Optional. A struct-level XValidation rule enforces at least one auth method in authParameter or non-empty plugins.
CRD Schema: plugins & validations
config/crd/bases/apisix.apache.org_apisixconsumers.yaml
Adds spec.plugins (array of plugin objects with name, enable default true, config allowing unknown fields, and secretRef) and an x-kubernetes-validations rule requiring either an auth method in authParameter or non-empty plugins; removes unconditional authParameter requirement.
Generated Deep Copy Logic
api/v2/zz_generated.deepcopy.go
ApisixConsumerSpec.DeepCopyInto nil-checks Plugins; when present, allocates a new slice and deep-copies each ApisixRoutePlugin element.
Translator Plugin Merging
internal/adc/translator/apisixconsumer.go
TranslateApisixConsumer iterates enabled Spec.Plugins, builds plugin configs via buildPluginConfig(..., tctx.Secrets), and merges them into the plugins map, overwriting auth plugins by name if necessary.
Controller Secret Loading
internal/controller/apisixconsumer_controller.go
processSpec conditionally fetches auth secret only when present and additionally fetches/caches secrets referenced by enabled plugins; NotFound vs other errors handled differently.
Indexer
internal/controller/indexer/indexer.go
ApisixConsumerSecretIndexFunc indexes enabled plugin secretRef entries in addition to the auth-parameter secret reference.
Tests
test/e2e/crds/v2/consumer.go
Adds E2E tests: one for consumer-level limit-count combined with authParameter.keyAuth; one for plugins-only key-auth ensuring auth works without authParameter and stops after consumer deletion.
Docs
docs/en/latest/reference/api-reference.md
Updates authParameter docs to mention plugins alternative and adds ApisixConsumerSpec to ApisixRoutePlugin “Appears in”.

Sequence Diagram(s):

sequenceDiagram
  participant Client
  participant Translator
  participant AuthSelector
  participant SpecPlugins
  participant APISIX_Plugins
  Client->>Translator: request consumer translation
  Translator->>AuthSelector: select auth plugin(s) from authParameter
  AuthSelector->>APISIX_Plugins: insert auth-derived plugin(s)
  Translator->>SpecPlugins: iterate enabled consumer plugins
  SpecPlugins->>Translator: buildPluginConfig(..., tctx.Secrets)
  Translator->>APISIX_Plugins: insert/overwrite by plugin.Name
  APISIX_Plugins->>Translator: final plugins set used for Consumer
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error)

Check name Status Explanation Resolution
Security Check ❌ Error CRITICAL: ApisixConsumer controller logs full objects containing plaintext credentials from authParameter and plugin configs at lines 78, 107, 112. Implement String()/MarshalLogObject() on ApisixConsumer to redact credentials, or log only Namespace/Name in errors instead of full object.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: support plugins field in ApisixConsumer' is fully related to the main change, clearly summarizing the addition of a generic plugins field to ApisixConsumer.
Linked Issues check ✅ Passed The PR implements all primary coding objectives from issue #397: adds generic plugins field, makes authParameter optional, implements CEL validation, updates translator to merge plugins, and ensures deepcopy handles the new field.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #397: plugins field support, optional authParameter, CEL validation, translator changes, deepcopy updates, indexer updates, and E2E tests—no unrelated changes detected.
E2e Test Quality Review ✅ Passed E2E tests validate plugins feature end-to-end. Two tests: authParameter+plugins and plugins-only auth. Real APISIX tested. Error handling sound. Implements all requirements from issue #397 correctly.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/apisixconsumer-plugins

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the ApisixConsumer v2 API to support a generic plugins field so consumer-scoped APISIX plugins can be attached directly to an ApisixConsumer, in addition to (or instead of) the existing authParameter mechanism.

Changes:

  • Updates ApisixConsumerSpec to make authParameter optional (pointer) and adds plugins []ApisixRoutePlugin, with an intended CEL constraint requiring at least one of them.
  • Extends the ADC translator to merge enabled spec.plugins into the translated consumer plugin map (with plugins overriding auth plugin name collisions).
  • Updates the v1 webhook warning collector and tests to handle authParameter being optional; adds a plugins-only admission warning test.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
api/v2/apisixconsumer_types.go Makes authParameter optional, adds plugins, and attempts to enforce “authParameter or plugins required” via XValidation.
api/v2/zz_generated.deepcopy.go Regenerates deepcopy logic for the new pointer field and plugins slice.
internal/adc/translator/apisixconsumer.go Adds nil-guard for authParameter and merges enabled generic plugins into the consumer plugin map.
internal/webhook/v1/apisixconsumer_webhook.go Adds nil-guard for authParameter when collecting secret-reference warnings.
internal/webhook/v1/apisixconsumer_webhook_test.go Updates tests for pointer authParameter and adds a plugins-only consumer test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread api/v2/apisixconsumer_types.go
Comment thread internal/adc/translator/apisixconsumer.go Outdated
Comment thread internal/webhook/v1/apisixconsumer_webhook.go
Comment thread api/v2/apisixconsumer_types.go Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/v2/apisixconsumer_types.go`:
- Around line 25-26: Update the CEL x-validation rule so it checks specific auth
method fields inside authParameter rather than only the presence of
authParameter; replace has(self.authParameter) with a disjunction that checks
has(self.authParameter.basicAuth) || has(self.authParameter.keyAuth) ||
has(self.authParameter.wolfRBAC) || has(self.authParameter.jwtAuth) ||
has(self.authParameter.hmacAuth) || has(self.authParameter.ldapAuth), and keep
the existing plugins clause (has(self.plugins) && size(self.plugins) > 0);
modify the kubebuilder validation annotation that currently references
has(self.authParameter) to use this combined check so empty authParameter
objects are rejected.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 54736f2f-5cec-4e5b-8103-a81726a116bc

📥 Commits

Reviewing files that changed from the base of the PR and between e5a51c9 and d9a35d7.

📒 Files selected for processing (5)
  • api/v2/apisixconsumer_types.go
  • api/v2/zz_generated.deepcopy.go
  • internal/adc/translator/apisixconsumer.go
  • internal/webhook/v1/apisixconsumer_webhook.go
  • internal/webhook/v1/apisixconsumer_webhook_test.go

Comment thread api/v2/apisixconsumer_types.go Outdated
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from d9a35d7 to b810022 Compare May 8, 2026 20:40
Copilot AI review requested due to automatic review settings May 8, 2026 20:44
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from b810022 to 6ad3c41 Compare May 8, 2026 20:44
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from 6ad3c41 to 24d08ad Compare May 8, 2026 20:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment thread api/v2/apisixconsumer_types.go Outdated
Comment thread internal/adc/translator/apisixconsumer.go Outdated
Comment thread internal/adc/translator/apisixconsumer.go
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
test/e2e/crds/v2/consumer.go (1)

727-779: ⚡ Quick win

Make cleanup failure-safe to prevent leaked resources on assertion failures.

Move cleanup registration to immediately after resource creation using DeferCleanup, so cleanup still runs when an earlier assertion fails.

Suggested patch
 It("consumer-level limit-count plugin is enforced", func() {
   By("apply ApisixRoute")
   applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "plugin-route"},
     &apiv2.ApisixRoute{}, fmt.Sprintf(pluginRoute, s.Namespace()))
+  DeferCleanup(func() {
+    err := s.DeleteResource("ApisixRoute", "plugin-route")
+    Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixRoute")
+  })

   By("apply ApisixConsumer with plugins")
   applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "consumer-with-plugins"},
     &apiv2.ApisixConsumer{}, fmt.Sprintf(consumerWithPlugins, s.Namespace()))
+  DeferCleanup(func() {
+    err := s.DeleteResource("ApisixConsumer", "consumer-with-plugins")
+    Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixConsumer")
+  })
@@
-  By("delete ApisixConsumer")
-  err := s.DeleteResource("ApisixConsumer", "consumer-with-plugins")
-  Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixConsumer")
-
-  By("delete ApisixRoute")
-  err = s.DeleteResource("ApisixRoute", "plugin-route")
-  Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixRoute")
 })

 It("auth plugin configured via plugins field only", func() {
   By("apply ApisixRoute")
   applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "plugins-only-route"},
     &apiv2.ApisixRoute{}, fmt.Sprintf(pluginsOnlyRoute, s.Namespace()))
+  DeferCleanup(func() {
+    err := s.DeleteResource("ApisixRoute", "plugins-only-route")
+    Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixRoute")
+  })

   By("apply ApisixConsumer with plugins only (no authParameter)")
   applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "consumer-plugins-only"},
     &apiv2.ApisixConsumer{}, fmt.Sprintf(consumerPluginsOnly, s.Namespace()))
+  DeferCleanup(func() {
+    err := s.DeleteResource("ApisixConsumer", "consumer-plugins-only")
+    Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixConsumer")
+  })
@@
-  By("delete ApisixConsumer")
-  err := s.DeleteResource("ApisixConsumer", "consumer-plugins-only")
-  Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixConsumer")
@@
-  By("delete ApisixRoute")
-  err = s.DeleteResource("ApisixRoute", "plugins-only-route")
-  Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixRoute")
 })

Also applies to: 822-862

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/crds/v2/consumer.go` around lines 727 - 779, The test registers
explicit deletions at the end which won't run if an earlier assertion fails;
after each applier.MustApplyAPIv2 call that creates the ApisixRoute
("plugin-route") and the ApisixConsumer ("consumer-with-plugins"), immediately
call DeferCleanup to register
s.DeleteResource("ApisixConsumer","consumer-with-plugins") and
s.DeleteResource("ApisixRoute","plugin-route") (or equivalent cleanup closures)
so resources are removed on test teardown; update the same pattern in the other
test block (lines around the second occurrence) as well.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/e2e/crds/v2/consumer.go`:
- Around line 727-779: The test registers explicit deletions at the end which
won't run if an earlier assertion fails; after each applier.MustApplyAPIv2 call
that creates the ApisixRoute ("plugin-route") and the ApisixConsumer
("consumer-with-plugins"), immediately call DeferCleanup to register
s.DeleteResource("ApisixConsumer","consumer-with-plugins") and
s.DeleteResource("ApisixRoute","plugin-route") (or equivalent cleanup closures)
so resources are removed on test teardown; update the same pattern in the other
test block (lines around the second occurrence) as well.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 78b1e6e2-99e7-4415-9ab7-c11378b94481

📥 Commits

Reviewing files that changed from the base of the PR and between 6ad3c41 and 24d08ad.

📒 Files selected for processing (5)
  • api/v2/apisixconsumer_types.go
  • api/v2/zz_generated.deepcopy.go
  • config/crd/bases/apisix.apache.org_apisixconsumers.yaml
  • internal/adc/translator/apisixconsumer.go
  • test/e2e/crds/v2/consumer.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • api/v2/zz_generated.deepcopy.go
  • config/crd/bases/apisix.apache.org_apisixconsumers.yaml
  • api/v2/apisixconsumer_types.go
  • internal/adc/translator/apisixconsumer.go

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

conformance test report - apisix-standalone mode

apiVersion: gateway.networking.k8s.io/v1
date: "2026-05-11T21:17:18Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    result: success
    statistics:
      Failed: 0
      Passed: 12
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests succeeded.
- core:
    result: partial
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 0
      Passed: 32
      Skipped: 1
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 11
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests partially succeeded with 1 test skips. Extended tests partially
    succeeded with 1 test skips.
- core:
    result: partial
    skippedTests:
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 10
      Skipped: 1
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 1 test skips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

conformance test report - apisix mode

apiVersion: gateway.networking.k8s.io/v1
date: "2026-05-11T21:17:57Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    result: partial
    skippedTests:
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 10
      Skipped: 1
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 1 test skips.
- core:
    result: success
    statistics:
      Failed: 0
      Passed: 12
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests succeeded.
- core:
    failedTests:
    - HTTPRouteInvalidBackendRefUnknownKind
    result: failure
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 1
      Passed: 31
      Skipped: 1
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 11
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests failed with 1 test failures. Extended tests partially succeeded
    with 1 test skips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 8, 2026

conformance test report

apiVersion: gateway.networking.k8s.io/v1
date: "2026-05-11T21:37:53Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    failedTests:
    - GRPCExactMethodMatching
    - GRPCRouteHeaderMatching
    - GRPCRouteListenerHostnameMatching
    - GatewayModifyListeners
    result: failure
    statistics:
      Failed: 4
      Passed: 8
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests failed with 4 test failures.
- core:
    failedTests:
    - GatewayModifyListeners
    result: failure
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 1
      Passed: 31
      Skipped: 1
  extended:
    failedTests:
    - HTTPRouteBackendProtocolWebSocket
    result: failure
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 1
      Passed: 10
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests failed with 1 test failures. Extended tests failed with 1 test
    failures.
- core:
    failedTests:
    - GatewayModifyListeners
    - TLSRouteSimpleSameNamespace
    result: failure
    statistics:
      Failed: 2
      Passed: 9
      Skipped: 0
  name: GATEWAY-TLS
  summary: Core tests failed with 2 test failures.

@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from 24d08ad to 13443e0 Compare May 9, 2026 00:58
Copilot AI review requested due to automatic review settings May 10, 2026 20:04
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from 13443e0 to 4f470a6 Compare May 10, 2026 20:04
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from 4f470a6 to 483108a Compare May 10, 2026 20:07
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (3)

docs/en/latest/reference/api-reference.md:794

  • The docs now state JWT algorithm can only be HS256, HS512, RS256, or ES256, but the ApisixConsumer API/schema does not enforce an enum and the translator passes the value through unchanged. If this is meant to be a real restriction, add kubebuilder enum validation for ApisixConsumerJwtAuthValue.Algorithm; otherwise, keep the docs consistent with the actual accepted values/behavior.
| `key` _string_ | Key is the unique identifier for the JWT credential. |
| `secret` _string_ | Secret is the shared secret used to sign the JWT (for symmetric algorithms). |
| `public_key` _string_ | PublicKey is the public key used to verify JWT signatures (for asymmetric algorithms). |
| `private_key` _string_ | PrivateKey is the private key used to sign the JWT (for asymmetric algorithms). |
| `algorithm` _string_ | Algorithm specifies the signing algorithm. Can be `HS256`, `HS384`, `HS512`, `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, `ES512`, `PS256`, `PS384`, `PS512`, or `EdDSA`. Currently APISIX only supports `HS256`, `HS512`, `RS256`, and `ES256`. API7 Enterprise supports all algorithms. |
| `exp` _integer_ | Exp is the token expiration period in seconds. |

docs/en/latest/reference/api-reference.md:1091

  • The filter_func field description no longer mentions the API7 Enterprise limitation, but the source type comment still says "supported in APISIX but not in API7 Enterprise" (see api/v2/apisixroute_types.go). Please keep the API reference consistent with the source-of-truth (either update the Go type comment/CRD generation or revert this doc change) to avoid misleading users about support.
| `remoteAddrs` _string array_ | RemoteAddrs is a list of source IP addresses or CIDR ranges to match. Supports both IPv4 and IPv6 formats. |
| `exprs` _[ApisixRouteHTTPMatchExprs](#apisixroutehttpmatchexprs)_ | NginxVars defines match conditions based on Nginx variables. |
| `filter_func` _string_ | FilterFunc is a user-defined function for advanced request filtering. The function can use Nginx variables through the `vars` parameter. This field is supported in APISIX but not in API7 Enterprise. |

config/crd/bases/apisix.apache.org_apisixconsumers.yaml:181

  • In the generated CRD, the JWT algorithm description was narrowed to HS256, HS512, RS256, or ES256, but the Go API type (ApisixConsumerJwtAuthValue.Algorithm) still documents broader support and there is no enum validation restricting the field. Either add explicit schema validation (enum) and update the Go type comment to match, or revert this description change to avoid drifting generated manifests from the actual API behavior.
                        properties:
                          algorithm:
                            description: |-
                              Algorithm specifies the signing algorithm.
                              Can be `HS256`, `HS384`, `HS512`, `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, `ES512`, `PS256`, `PS384`, `PS512`, or `EdDSA`.
                              Currently APISIX only supports `HS256`, `HS512`, `RS256`, and `ES256`. API7 Enterprise supports all algorithms.

Comment thread api/v2/apisixconsumer_types.go Outdated
Comment thread config/crd/bases/apisix.apache.org_apisixconsumers.yaml Outdated
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from 483108a to 5200f36 Compare May 10, 2026 20:27
Copilot AI review requested due to automatic review settings May 11, 2026 02:36
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from 5200f36 to ead00a5 Compare May 11, 2026 02:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

api/v2/apisixconsumer_validation_test.go:123

  • The schema validation tests in this file were updated for the AuthParameter pointer change, but there are no tests covering the new ApisixConsumerSpec XValidation that requires either an auth method or enabled plugins. Adding tests for (1) missing authParameter + empty plugins (should fail), (2) authParameter with no methods (should fail), and (3) plugins-only with an enabled plugin (should pass) would prevent regressions in the CRD/CEL rule.
func TestApisixConsumer_JwtAuth_SymmetricHS256(t *testing.T) {
	v := loadApisixConsumerSchema(t)
	ac := &apisixv2.ApisixConsumer{
		Spec: apisixv2.ApisixConsumerSpec{
			AuthParameter: &apisixv2.ApisixConsumerAuthParameter{
				JwtAuth: &apisixv2.ApisixConsumerJwtAuth{
					Value: &apisixv2.ApisixConsumerJwtAuthValue{
						Key:       "my-key",
						Secret:    "my-secret",
						Algorithm: "HS256",
					},
				},
			},
		},
	}
	assert.NoError(t, v.Validate(t, ac))

Comment thread api/v2/apisixconsumer_types.go
Comment thread config/crd/bases/apisix.apache.org_apisixconsumers.yaml Outdated
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from ead00a5 to c08ac1f Compare May 11, 2026 04:02
Copilot AI review requested due to automatic review settings May 11, 2026 05:44
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from c08ac1f to c61f413 Compare May 11, 2026 05:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Comment thread internal/adc/translator/apisixconsumer.go
Comment thread internal/controller/apisixconsumer_controller.go Outdated
Comment thread internal/controller/indexer/indexer.go Outdated
Add a generic `plugins` field to ApisixConsumerSpec so that
consumer-scoped plugins (e.g. limit-count, limit-req) can be
attached to an ApisixConsumer resource directly, without being
limited to the auth plugins exposed through authParameter.

Key changes:
- ApisixConsumerSpec gains a Plugins []ApisixRoutePlugin field,
  following the same pattern as ApisixRoute and ApisixGlobalRule.
  Plugins entries are merged after the auth plugin derived from
  authParameter; a name collision means the Plugins entry wins.
- authParameter is now optional (omitempty). A CEL rule enforces
  that at least one auth method within authParameter OR at least
  one plugin in plugins must be specified:
    has(self.authParameter.basicAuth) || has(self.authParameter.keyAuth)
    || ... || (has(self.plugins) && size(self.plugins) > 0)
- Translator updated to process the new Plugins slice via the
  existing buildPluginConfig helper.
- deepcopy updated for the new Plugins slice.
- No webhook changes required; validation is handled entirely
  by the CRD-level CEL rule (x-kubernetes-validations).

Closes #397

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@AlinsRan AlinsRan force-pushed the feat/apisixconsumer-plugins branch from c61f413 to cc4d278 Compare May 11, 2026 21:03
@AlinsRan AlinsRan merged commit 79db059 into master May 13, 2026
24 of 26 checks passed
@AlinsRan AlinsRan deleted the feat/apisixconsumer-plugins branch May 13, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

enhancement: support plugins in ApisixConsumer

4 participants