- Fix parameter encoding for CRDs by using core v1 GroupVersion
- Add AbsPath-based request construction for CRD operations (Get, Inform, UpdateStatus)
- Make WatchOwned generic over owned resource type O
- Rename ReconcileKind -> Reconcile in controller interface
For CRDs, NewClientGVR now sets APIPath to full path (/apis/group/version) and GroupVersion to core v1, ensuring metav1 types like ListOptions encode correctly while still accessing the correct CRD endpoint.
Signed-off-by: Jason Hall <jason@chainguard.dev>
* Fix controller example to implement correct interface method
- Change ReconcileKind to Reconcile to match the Reconciler interface
- Add nil check for secretLister to handle initialization timing
- Fix OnError handler in e2e test to not fail immediately on expected errors
This allows the controller-owned-lister example to compile and run correctly.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update examples/controller-owned-lister/main.go
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- Add Lister and NamespaceLister as concrete structs (not interfaces)
- Implement cache-backed List/Get operations with type safety
- Add lister support to Inform method, returning (*Lister[T], error)
- Update controller to store owned resource listers
- Add example showing how to use listers with controllers
- Fix error logging in examples to use log.Fatal instead of log.Printf
- Fix flaky e2e test by changing OnError handler to not fail immediately
- Update WatchOwned to automatically get owner GVK from client
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This PR introduces a new controller package that provides a simple, type-safe
framework for building Kubernetes controllers. The implementation is inspired
by Knative's controller patterns but optimized for simplicity.
Key features:
- Simple reconciler interface with just one method (ReconcileKind)
- Automatic detection and persistence of object changes
- Built-in conflict resolution with retry logic
- Owner reference support for watching owned resources
- Error handling patterns (RequeueAfter, RequeueImmediately, PermanentError)
- Context-aware logging with clog integration
- Full test coverage including e2e tests
The framework handles the complexity of update detection, conflict resolution,
and status updates automatically, allowing users to focus on their business logic.
Also includes:
- Comprehensive documentation in controller/README.md
- Example controller implementation in examples/controller/
- Updates to use errors.Is pattern for error checking
- Minor refactoring to use "if err := ..." idiom where appropriate
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This change updates the ProxyGet implementations for both PodClient and
ServiceClient to use k8s.io/apimachinery/pkg/util/net.JoinSchemeNamePort,
matching the behavior of the official client-go library.
The function properly handles empty ports and scheme values:
- Empty scheme and port: returns just the name
- Empty scheme with port: returns "name:port"
- With scheme and port: returns "scheme:name:port"
This ensures compatibility with Kubernetes proxy endpoints and allows
users to omit the port when not needed.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
This PR adds support for resource-specific expansion methods and implements
missing standard client-go operations to achieve feature parity.
## New Features
### Expansion Methods
- Added PodClient with methods: GetLogs, Bind, Evict, ProxyGet
- Added ServiceClient with method: ProxyGet
- Both clients implement the official k8s.io/client-go expansion interfaces
- Runtime type assertions ensure type safety (panic if wrong type)
### Missing Standard Methods
- Watch: Watch resources with optional label/field selectors
- DeleteCollection: Delete multiple resources matching criteria
- UpdateStatus: Update only the status subresource
### Other Improvements
- Refactored all tests to use inline configuration pattern
- Added comprehensive e2e tests for new functionality
- Updated documentation with examples
- Fixed linting error in stream.Close() handling
## Design Decisions
The expansion methods follow a namespace-scoped pattern where calling
`client.PodClient("namespace")` returns a client that implements the
standard client-go PodExpansion interface. This maintains full API
compatibility while providing type safety through runtime assertions.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
- Configure weekly updates for Go modules
- Configure weekly updates for GitHub Actions
- Group Kubernetes dependencies (k8s.io/*) together
- Set update schedule for Mondays at 10:00 UTC
- Add appropriate labels for dependency PRs
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add InformOptions struct with ListOptions and ResyncPeriod fields
- Update all client methods to accept options parameters
- Add comprehensive examples in main.go demonstrating:
- Label selector filtering (test=example)
- Field selector filtering (status.phase=Running)
- Custom resync periods
- Add tests for label and field selectors with mock query parameter support
- Fix nil pointer handling in all client methods
- Update mock transport to handle query parameters correctly
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This major refactoring eliminates the dependency on the dynamic client
and unstructured types, using rest.RESTClient directly for all operations.
Key changes:
- Replace dynamic.Interface with rest.RESTClient in client struct
- Remove all unstructured.Unstructured conversions
- Use direct JSON marshaling/unmarshaling for type conversions
- Update all CRUD methods (List, Get, Create, Update, Delete, Patch)
- Reimplement Inform to use cache.ListWatch with rest client
- Export Client type and update method signatures
- Add proper GroupVersion and APIPath configuration in NewClientGVR
- Update all tests to use mock HTTP transport instead of fake dynamic client
- Fix informer event handler to use new InformerHandler type
- Update example code to demonstrate new API
Benefits:
- More efficient: eliminates unnecessary type conversions
- Cleaner code: direct use of REST client
- Better performance: reduced JSON marshaling overhead
- Type safety maintained through generics
All unit tests and e2e tests pass against a real Kubernetes cluster.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Provides comprehensive guidance for Claude Code when working with this
repository, including build/test commands, architecture overview, and
important coding rules.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace gotip with stable Go in GitHub Actions
- Add automatic GVR inference for Kubernetes types
- Rename API: NewClient (inferred GVR) and NewClientGVR (explicit)
- Add comprehensive test coverage including e2e tests
- Update CI to include linting, unit tests, and e2e tests with kind
- Add .gitignore for common Go development files
- Update README with usage examples and features
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix syntax error in Inform method (< to ,)
- Add missing CRUD operations: Update, Delete, and Patch methods
- Add comprehensive test coverage for all client operations
- Update Kubernetes dependencies from v0.21.1 to v0.31.11
- Update Go version requirement to 1.22.0
- Update README to remove outdated Go 1.18 beta references
- Improve error handling and logging
The client now provides full CRUD functionality with type-safe generic
operations for any Kubernetes resource type, significantly reducing
boilerplate compared to traditional client-go usage.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>