Skip to content

fix: convert internal types to external before unstructured conversion in quota admission#526

Merged
zachsmith1 merged 1 commit intomainfrom
test/endpointslice-quota-e2e
Mar 19, 2026
Merged

fix: convert internal types to external before unstructured conversion in quota admission#526
zachsmith1 merged 1 commit intomainfrom
test/endpointslice-quota-e2e

Conversation

@zachsmith1
Copy link
Copy Markdown
Contributor

@zachsmith1 zachsmith1 commented Mar 18, 2026

Summary

The API server's admission handler decodes native Kubernetes types as internal Go types (e.g. pkg/apis/discovery.EndpointSlice), not external versioned types (e.g. api/discovery/v1.EndpointSlice). Internal types inline ObjectMeta without a metadata JSON wrapper, so both json.Marshal and runtime.DefaultUnstructuredConverter.ToUnstructured produce maps without a metadata key. This breaks CEL template expressions like trigger.metadata.name used in ClaimCreationPolicies.

Changes

  • Admission plugin: Use legacyscheme.Scheme.ConvertToVersion to convert internal types to their external versioned form before calling ToUnstructured. Falls back to direct ToUnstructured if the type isn't registered in the scheme (e.g. unit tests with external types).
  • E2E test: Add chainsaw test for EndpointSlice quota enforcement in a project control plane with deterministic claim names using trigger.metadata.name — the exact pattern that fails without this fix.

Root cause investigation

  1. EndpointSlice CREATE in project control plane triggers quota admission
  2. Admission plugin receives *discovery.EndpointSlice (internal type, not *discoveryv1.EndpointSlice)
  3. Internal type has ObjectMeta with json:",inline" — no metadata wrapper
  4. ToUnstructured produces objectMeta key; json.Marshal flattens metadata fields to top level
  5. CEL expression trigger.metadata.name fails with no such key: metadata
  6. Error surfaces as "Insufficient quota resources available"

Production impact

This blocked EndpointSlice creation in project control planes for the network-services-operator, preventing HTTPProxy resources from being fully programmed (no backend EndpointSlice → gateway controller errors).

Test plan

  • Unit test: TestStructuredEndpointSliceCELTemplateRendering — verifies both structured and unstructured objects produce correct CEL evaluation
  • E2E test: structured-type-enforcement — full quota lifecycle with EndpointSlice in project control plane (passes locally against kind cluster)
  • All existing admission unit tests pass
  • CI e2e test suite passes

🤖 Generated with Claude Code

@joggrbot
Copy link
Copy Markdown
Contributor

joggrbot bot commented Mar 18, 2026

📝 Documentation Analysis

All docs are up to date! 🎉


✅ Latest commit analyzed: 2659b98 | Powered by Joggr

@zachsmith1 zachsmith1 changed the title test: add e2e test for EndpointSlice quota enforcement with structured types fix: convert internal types to external before unstructured conversion in quota admission Mar 19, 2026
@zachsmith1 zachsmith1 requested a review from scotwells March 19, 2026 20:52
…n in quota admission

The API server's admission handler decodes native Kubernetes types as
internal Go types (e.g. pkg/apis/discovery.EndpointSlice), not external
versioned types (e.g. api/discovery/v1.EndpointSlice). Internal types
inline ObjectMeta without a "metadata" JSON wrapper, so both json.Marshal
and runtime.DefaultUnstructuredConverter.ToUnstructured produce maps
without a "metadata" key. This breaks CEL template expressions like
trigger.metadata.name used in ClaimCreationPolicies.

Use legacyscheme.Scheme.ConvertToVersion to convert internal types to
their external versioned form before calling ToUnstructured. Falls back
to direct ToUnstructured if the type isn't registered in the scheme.

Add chainsaw e2e test for EndpointSlice quota enforcement in a project
control plane with deterministic claim names using trigger.metadata.name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@zachsmith1 zachsmith1 force-pushed the test/endpointslice-quota-e2e branch from 621c819 to 2659b98 Compare March 19, 2026 20:52
@zachsmith1 zachsmith1 merged commit 88d64c0 into main Mar 19, 2026
8 checks passed
@zachsmith1 zachsmith1 deleted the test/endpointslice-quota-e2e branch March 19, 2026 21:00
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.

2 participants