Skip to content

Conversation

@siddharth1036
Copy link

@siddharth1036 siddharth1036 commented Oct 28, 2025

What type of PR is this?

feat(api): add Kubernetes client-go style typed clients for Envoy Gateway resources

What this PR does / why we need it:

This PR adds Kubernetes-style typed clientsets, informers, and listers for Envoy Gateway's custom resources, enabling external users to programmatically interact with Envoy Gateway resources using familiar patterns from kubernetes/client-go.

Key Changes:

1. Client Generation Infrastructure

  • Added client-gen, lister-gen, and informer-gen from k8s.io/code-generator to tools
  • Created tools/src/update-codegen.sh script to generate typed clients
  • Created tools/src/verify-codegen.sh script to verify generated code is up-to-date
  • Integrated generation into Makefile with make kube-generate-clients and make kube-verify-clients

2. API Annotations

Added code-generator annotations to 8 CRD types in api/v1alpha1/:

  • Backend and BackendList
  • BackendTrafficPolicy and BackendTrafficPolicyList
  • ClientTrafficPolicy and ClientTrafficPolicyList
  • EnvoyExtensionPolicy and EnvoyExtensionPolicyList
  • EnvoyPatchPolicy and EnvoyPatchPolicyList
  • EnvoyProxy and EnvoyProxyList
  • HTTPRouteFilter and HTTPRouteFilterList
  • SecurityPolicy and SecurityPolicyList

Annotations added:

  • +genclient - Marks types for client generation
  • +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - Ensures runtime.Object interface compliance
  • +k8s:deepcopy-gen=package - Enables package-level deepcopy generation in doc.go

3. Scheme Registration Updates

Updated api/v1alpha1/groupversion_info.go:

  • Modified SchemeBuilder to use runtime.NewSchemeBuilder for code-generator compatibility
  • Introduced localSchemeBuilder for controller-runtime compatibility
  • Added SchemeGroupVersion alias for generated client compatibility
  • Updated addKnownTypes to register all 8 CRD types and their list types

4. Generated Client Code (49 files)

Clientsets (pkg/client/clientset/versioned/):

  • Versioned clientset with discovery support
  • Typed clients for all 8 resources
  • Fake clientset for testing

Informers (pkg/client/informers/externalversions/):

  • Shared informer factory
  • Per-resource informers with watch/cache capabilities
  • Efficient event handling for controllers

Listers (pkg/client/listers/api/v1alpha1/):

  • Cache-based listers for all resources
  • Namespace-scoped and cluster-scoped list operations

5. Testing

Added pkg/client/clientset_test.go:

  • Tests clientset instantiation
  • Tests fake clientset for user testing scenarios
  • Verifies all resource clients are accessible

6. CI/CD Integration

  • Added .github/workflows/verify-codegen.yaml workflow to enforce generated code is up-to-date
  • Updated .github/codecov.yml to exclude generated client code from coverage reports
  • Integrated verification into existing gen-check workflow

Benefits:

  1. Familiar API: Users can interact with Envoy Gateway resources using the same patterns as core Kubernetes resources
  2. Type Safety: Compile-time type checking for all operations
  3. Efficient Watching: Built-in informers provide efficient caching and event handling
  4. Controller Support: Enables building external controllers and operators
  5. Testing Support: Fake clients for unit testing
  6. Production Ready: Follows kubernetes/client-go conventions

Example Usage:

import (
    "context"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "github.com/envoyproxy/gateway/pkg/client/clientset/versioned"
)

// Create a clientset
clientset, err := versioned.NewForConfig(config)
if err != nil {
    panic(err)
}

// List SecurityPolicies
policies, err := clientset.GatewayV1alpha1().
    SecurityPolicies("default").
    List(context.TODO(), metav1.ListOptions{})

// Watch for changes using informers
informerFactory := informers.NewSharedInformerFactory(clientset, time.Minute)
policyInformer := informerFactory.Gateway().V1alpha1().SecurityPolicies()

policyInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
    AddFunc: func(obj interface{}) {
        policy := obj.(*v1alpha1.SecurityPolicy)
        fmt.Printf("SecurityPolicy added: %s\n", policy.Name)
    },
})

Design Decisions:

  1. No applyconfiguration-gen: Not needed yet; can be added when users request Server-Side Apply support
  2. No openapi-gen: controller-gen already generates OpenAPI schemas in CRDs (modern approach)
  3. No conversion-gen: Only have v1alpha1; will add when promoting APIs to v1beta1/v1
  4. Manual scheme registration: More explicit than register-gen; suitable for <10 API groups

This approach follows kubernetes/sample-controller and matches what other projects like cert-manager and external-dns use.

Which issue(s) this PR fixes:

Fixes #

Release Notes: Yes

# release-notes/current.yaml
feature:
  - area: api
    change: |
      Added Kubernetes-style typed clientsets, informers, and listers for programmatic access to Envoy Gateway resources.
      External users can now interact with Envoy Gateway CRDs using familiar client-go patterns.
    prNumber: <7356>

Checklist:

  • Code generated using k8s.io/code-generator tools (client-gen, informer-gen, lister-gen)
  • All 8 CRD types annotated with +genclient tags
  • Scheme registration updated for both controller-runtime and code-generator compatibility
  • Generation scripts created (update-codegen.sh, verify-codegen.sh)
  • Makefile targets added (kube-generate-clients, kube-verify-clients)
  • CI workflow added to enforce generated code is up-to-date
  • Basic smoke tests added (pkg/client/clientset_test.go)
  • Generated code excluded from code coverage
  • Documentation inline with generated code
  • Follows kubernetes/client-go conventions

@siddharth1036 siddharth1036 marked this pull request as ready for review October 28, 2025 13:12
@siddharth1036 siddharth1036 requested a review from a team as a code owner October 28, 2025 13:12
cd ..
- name: Verify generated code
run: make kube-verify-clients
Copy link
Contributor

Choose a reason for hiding this comment

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

instead if a new action, can we reuse make geo-check thats part of CI already ?

set -o nounset
set -o pipefail

SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/../..
Copy link
Contributor

Choose a reason for hiding this comment

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

can this be represented in the make target similar to what was being done in the previous PR

&ClientTrafficPolicyList{},
&EnvoyExtensionPolicy{},
&EnvoyExtensionPolicyList{},
&EnvoyGateway{},
Copy link
Member

Choose a reason for hiding this comment

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

this seems not right, EnvoyGateway is not a CRD.

Copy link
Author

Choose a reason for hiding this comment

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

Sure, let me check on this

Copy link
Author

Choose a reason for hiding this comment

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

Hi @zirain I checked on this, it seems like the type is required to decode EnvoyGateway resource here:

gvk.Kind != egv1a1.KindEnvoyGateway {

I tried to check a way around this but didn't find a cleaner way to do this, can you suggest if something can be worked out for the same?

Copy link
Member

Choose a reason for hiding this comment

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

it's stored in configmap, it won't be submitted to apiserver.
it's meaningless to add it to scheme.

Copy link
Author

Choose a reason for hiding this comment

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

Hi @zirain ! I've investigated a few different approaches to address your concern about EnvoyGateway not being a CRD.
I've implemented a solution that uses a separate decoder scheme specifically for configuration decoding. This way, the decoder scheme can include the EnvoyGateway type for YAML deserialization purposes, while the main runtime scheme (used for CRDs) remains clean and only contains actual Kubernetes API resources.
When you have a moment, would you mind reviewing the changes in commit here ? I'd really appreciate your feedback on whether this approach addresses your concerns or if you'd like me to explore a different solution.

@codecov
Copy link

codecov bot commented Oct 29, 2025

Codecov Report

❌ Patch coverage is 93.33333% with 2 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@5a95a04). Learn more about missing BASE report.
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
api/v1alpha1/groupversion_info.go 91.30% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7356   +/-   ##
=======================================
  Coverage        ?   72.38%           
=======================================
  Files           ?      232           
  Lines           ?    34030           
  Branches        ?        0           
=======================================
  Hits            ?    24631           
  Misses          ?     7628           
  Partials        ?     1771           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

3 participants