Skip to content

feat: support consumer labels from metadata labels#410

Merged
AlinsRan merged 5 commits into
masterfrom
feat/issue-398-consumer-metadata-labels
May 13, 2026
Merged

feat: support consumer labels from metadata labels#410
AlinsRan merged 5 commits into
masterfrom
feat/issue-398-consumer-metadata-labels

Conversation

@AlinsRan
Copy link
Copy Markdown
Contributor

@AlinsRan AlinsRan commented May 8, 2026

Closed: #398

Summary

  • reuse ApisixConsumer.metadata.labels and Consumer.metadata.labels as consumer labels
  • add a shared label helper so controller-generated labels always win on conflicts
  • align ApisixRoute with the same merge behavior and add coverage

Consumer labels

This change is mainly for propagating CRD labels into data plane resource labels.

Both ApisixConsumer.metadata.labels and Consumer.metadata.labels are propagated to the generated APISIX consumer as custom labels, so users can inject business metadata such as tenant, team, or plan from the Kubernetes CRD into the data plane resource.

If a user-defined label key conflicts with a controller-generated reserved label, the controller-generated value is preserved.

ApisixConsumer CRD example

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  namespace: ingress-apisix
  name: alice
  labels:
    team: payments
    plan: gold
spec:
  ingressClassName: apisix
  authParameter:
    keyAuth:
      value:
        key: alice-primary-key

Consumer CRD example

apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
  namespace: ingress-apisix
  name: bob
  labels:
    team: platform
    tenant: internal
spec:
  gatewayRef:
    name: apisix
  credentials:
  - type: key-auth
    name: bob-key
    config:
      key: bob-primary-key

Data plane result example

The generated APISIX consumer will carry the injected labels together with controller-managed labels, for example:

{
  "username": "ingress-apisix_alice",
  "labels": {
    "team": "payments",
    "plan": "gold",
    "k8s/name": "alice",
    "k8s/namespace": "ingress-apisix",
    "k8s/kind": "ApisixConsumer",
    "k8s/controller-name": "apisix.apache.org/apisix-ingress-controller",
    "manager-by": "apisix-ingress-controller",
    "k8s/resource-key": "ApisixConsumer/ingress-apisix/alice"
  }
}

The same merge behavior also applies to Consumer resources, so labels defined on either CRD can be consumed directly on the data plane side.

Testing

  • go test ./internal/controller/label ./internal/adc/translator
  • go test $(go list ./... | grep -v /e2e | grep -v /conformance)

Summary by CodeRabbit

  • Bug Fixes

    • Preserve custom metadata labels on APISIX consumers, routes, and general consumers so controller-generated labels are not overwritten.
  • Tests

    • Added unit tests to verify metadata labels are retained while controller-managed labels remain correct.

Review Change Stack

AlinsRan and others added 2 commits May 8, 2026 15:08
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 8, 2026 08:02
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d3e791f2-89a1-4ecd-a080-8dec5e45adc6

📥 Commits

Reviewing files that changed from the base of the PR and between 0d69dd0 and 7544a13.

📒 Files selected for processing (2)
  • internal/controller/label/label.go
  • internal/controller/label/label_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/controller/label/label_test.go
  • internal/controller/label/label.go

📝 Walkthrough

Walkthrough

Adds GenLabelWithObjectLabels to merge object metadata labels with controller-generated labels, and uses it in translators for ApisixConsumer, Consumer, and ApisixRoute so user metadata labels are preserved while controller labels remain set. Tests added for each affected translator and the label helper.

Changes

Custom Labels Support

Layer / File(s) Summary
Label Helper Function
internal/controller/label/label.go internal/controller/label/label_test.go
New GenLabelWithObjectLabels merges object metadata labels with controller-generated labels; GenLabel now ignores dangling key args. Tests validate merging and dangling-arg behavior.
Consumer Translators & Tests
internal/adc/translator/apisixconsumer.go, internal/adc/translator/apisixconsumer_test.go, internal/adc/translator/consumer.go, internal/adc/translator/consumer_test.go
TranslateApisixConsumer and TranslateConsumerV1alpha1 now call GenLabelWithObjectLabels so translated consumers preserve user metadata labels; tests assert preservation and expected controller resource-key.
Route Translator & Test
internal/adc/translator/apisixroute.go, internal/adc/translator/apisixroute_test.go
buildRoute now uses GenLabelWithObjectLabels; test verifies route preserves metadata labels and controller label values like k8s/name and k8s/resource-key.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
E2e Test Quality Review ⚠️ Warning No E2E tests verifying labels propagate to actual APISIX API. Unit tests exist but lack coverage for empty labels and boundary cases. Add E2E tests in test/e2e/ verifying consumer labels appear in APISIX. Add unit tests for nil/empty labels and edge cases.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: support consumer labels from metadata labels' clearly summarizes the main change: enabling consumer labels from CRD metadata labels.
Linked Issues check ✅ Passed Code changes fully address issue #398 objectives: support user-defined consumer labels on ApisixConsumer/Consumer via metadata labels and merge them with controller labels while preserving controller-reserved keys on conflict.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue: label generation for ApisixConsumer, Consumer, and ApisixRoute; addition of GenLabelWithObjectLabels function; and corresponding test coverage.
Security Check ✅ Passed No security vulnerabilities found. PR safely merges user metadata labels with controller-managed labels. Bounds checking prevents out-of-bounds access. No credential exposure or auth bypass.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-398-consumer-metadata-labels

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 adds support for propagating Kubernetes metadata.labels into APISIX Consumer labels (via ApisixConsumer) while ensuring controller-generated labels take precedence on key conflicts. It also refactors label merging into a shared helper and updates ApisixRoute route label merging to use the same precedence rule, with added unit coverage.

Changes:

  • Add label.GenLabelWithObjectLabels to merge object metadata labels with controller-generated labels (controller wins on conflicts).
  • Use the new helper when translating ApisixConsumer and ApisixRoute routes, removing the previous manual merge for routes.
  • Add unit tests covering merge precedence for the label helper, ApisixRoute route labels, and ApisixConsumer consumer labels.

Reviewed changes

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

Show a summary per file
File Description
internal/controller/label/label.go Adds a helper to merge object labels with controller labels, preserving controller precedence.
internal/controller/label/label_test.go Adds coverage for label merge precedence behavior.
internal/adc/translator/apisixroute.go Switches route label generation to the shared merge helper; removes manual label merge loop.
internal/adc/translator/apisixroute_test.go Adds coverage to ensure metadata labels don’t override controller labels on routes.
internal/adc/translator/apisixconsumer.go Switches consumer label generation to include metadata labels with controller precedence.
internal/adc/translator/apisixconsumer_test.go Adds coverage to ensure consumer metadata labels are included without overriding controller labels.

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

Comment thread internal/controller/label/label.go
Comment thread internal/adc/translator/apisixroute_test.go
@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-11T06:41:31Z"
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:
    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.
- core:
    result: partial
    skippedTests:
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 10
      Skipped: 1
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 1 test skips.

@AlinsRan AlinsRan closed this May 8, 2026
@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-11T06:41:05Z"
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

apiVersion: gateway.networking.k8s.io/v1
date: "2026-05-11T07:02:08Z"
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 and others added 2 commits May 11, 2026 10:25
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 11, 2026 06:27
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 8 out of 8 changed files in this pull request and generated 1 comment.

Comment on lines +97 to +101
Labels: map[string]string{
"team": "payments",
"k8s/name": "user-value",
"k8s/resource-key": "user-resource-key",
},
@AlinsRan AlinsRan merged commit 382cc0f into master May 13, 2026
30 of 32 checks passed
@AlinsRan AlinsRan deleted the feat/issue-398-consumer-metadata-labels branch May 13, 2026 06:20
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 consumer custom labels in ApisixConsumer

3 participants