Add new resource for Kubernetes API proxy (#279)

This adds a new resource which deploys a Kubernetes API server proxy
that can be used to access the API server without tokens through
Netbird.

Part of #274 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added ClusterProxy custom resource for cluster API proxying
capabilities

* **Documentation**
  * Added ClusterProxy API reference documentation with schema details

* **Examples**
* Added example ClusterProxy configuration and RBAC setup for cluster
proxy targets

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/netbirdio/kubernetes-operator/pull/279?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Philip Laine
2026-06-01 11:41:48 +02:00
committed by GitHub
parent a3546e4804
commit 5dd73dcc80
19 changed files with 1177 additions and 31 deletions
@@ -0,0 +1,231 @@
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// ClusterProxyApplyConfiguration represents a declarative configuration of the ClusterProxy type for use
// with apply.
//
// ClusterProxy is the Schema for the clusterproxies API
type ClusterProxyApplyConfiguration struct {
v1.TypeMetaApplyConfiguration `json:",inline"`
*v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
Spec *ClusterProxySpecApplyConfiguration `json:"spec,omitempty"`
Status *ClusterProxyStatusApplyConfiguration `json:"status,omitempty"`
}
// ClusterProxy constructs a declarative configuration of the ClusterProxy type for use with
// apply.
func ClusterProxy(name, namespace string) *ClusterProxyApplyConfiguration {
b := &ClusterProxyApplyConfiguration{}
b.WithName(name)
b.WithNamespace(namespace)
b.WithKind("ClusterProxy")
b.WithAPIVersion("netbird.io/v1alpha1")
return b
}
func (b ClusterProxyApplyConfiguration) IsApplyConfiguration() {}
// WithKind sets the Kind field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Kind field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithKind(value string) *ClusterProxyApplyConfiguration {
b.TypeMetaApplyConfiguration.Kind = &value
return b
}
// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the APIVersion field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithAPIVersion(value string) *ClusterProxyApplyConfiguration {
b.TypeMetaApplyConfiguration.APIVersion = &value
return b
}
// WithName sets the Name field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Name field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithName(value string) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Name = &value
return b
}
// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the GenerateName field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithGenerateName(value string) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.GenerateName = &value
return b
}
// WithNamespace sets the Namespace field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Namespace field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithNamespace(value string) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Namespace = &value
return b
}
// WithUID sets the UID field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the UID field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithUID(value types.UID) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.UID = &value
return b
}
// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ResourceVersion field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithResourceVersion(value string) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.ResourceVersion = &value
return b
}
// WithGeneration sets the Generation field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Generation field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithGeneration(value int64) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Generation = &value
return b
}
// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CreationTimestamp field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.CreationTimestamp = &value
return b
}
// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.DeletionTimestamp = &value
return b
}
// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.DeletionGracePeriodSeconds = &value
return b
}
// WithLabels puts the entries into the Labels field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Labels field,
// overwriting an existing map entries in Labels field with the same key.
func (b *ClusterProxyApplyConfiguration) WithLabels(entries map[string]string) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.ObjectMetaApplyConfiguration.Labels == nil && len(entries) > 0 {
b.ObjectMetaApplyConfiguration.Labels = make(map[string]string, len(entries))
}
for k, v := range entries {
b.ObjectMetaApplyConfiguration.Labels[k] = v
}
return b
}
// WithAnnotations puts the entries into the Annotations field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Annotations field,
// overwriting an existing map entries in Annotations field with the same key.
func (b *ClusterProxyApplyConfiguration) WithAnnotations(entries map[string]string) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.ObjectMetaApplyConfiguration.Annotations == nil && len(entries) > 0 {
b.ObjectMetaApplyConfiguration.Annotations = make(map[string]string, len(entries))
}
for k, v := range entries {
b.ObjectMetaApplyConfiguration.Annotations[k] = v
}
return b
}
// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
func (b *ClusterProxyApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
if values[i] == nil {
panic("nil value passed to WithOwnerReferences")
}
b.ObjectMetaApplyConfiguration.OwnerReferences = append(b.ObjectMetaApplyConfiguration.OwnerReferences, *values[i])
}
return b
}
// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the Finalizers field.
func (b *ClusterProxyApplyConfiguration) WithFinalizers(values ...string) *ClusterProxyApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
b.ObjectMetaApplyConfiguration.Finalizers = append(b.ObjectMetaApplyConfiguration.Finalizers, values[i])
}
return b
}
func (b *ClusterProxyApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
if b.ObjectMetaApplyConfiguration == nil {
b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
}
}
// WithSpec sets the Spec field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Spec field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithSpec(value *ClusterProxySpecApplyConfiguration) *ClusterProxyApplyConfiguration {
b.Spec = value
return b
}
// WithStatus sets the Status field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Status field is set to the value of the last call.
func (b *ClusterProxyApplyConfiguration) WithStatus(value *ClusterProxyStatusApplyConfiguration) *ClusterProxyApplyConfiguration {
b.Status = value
return b
}
// GetKind retrieves the value of the Kind field in the declarative configuration.
func (b *ClusterProxyApplyConfiguration) GetKind() *string {
return b.TypeMetaApplyConfiguration.Kind
}
// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration.
func (b *ClusterProxyApplyConfiguration) GetAPIVersion() *string {
return b.TypeMetaApplyConfiguration.APIVersion
}
// GetName retrieves the value of the Name field in the declarative configuration.
func (b *ClusterProxyApplyConfiguration) GetName() *string {
b.ensureObjectMetaApplyConfigurationExists()
return b.ObjectMetaApplyConfiguration.Name
}
// GetNamespace retrieves the value of the Namespace field in the declarative configuration.
func (b *ClusterProxyApplyConfiguration) GetNamespace() *string {
b.ensureObjectMetaApplyConfigurationExists()
return b.ObjectMetaApplyConfiguration.Namespace
}
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha1
// ClusterProxySpecApplyConfiguration represents a declarative configuration of the ClusterProxySpec type for use
// with apply.
//
// ClusterProxySpec defines the desired state of ClusterProxy.
type ClusterProxySpecApplyConfiguration struct {
// ClusterName is the name of the Kubernetes cluster.
ClusterName *string `json:"clusterName,omitempty"`
// APIServer is the URL of the Kubernetes API server to proxy requests to.
APIServer *string `json:"apiServer,omitempty"`
// ServiceAccountName is a reference to the service account used for impersonation.
ServiceAccountName *string `json:"serviceAccountName,omitempty"`
}
// ClusterProxySpecApplyConfiguration constructs a declarative configuration of the ClusterProxySpec type for use with
// apply.
func ClusterProxySpec() *ClusterProxySpecApplyConfiguration {
return &ClusterProxySpecApplyConfiguration{}
}
// WithClusterName sets the ClusterName field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ClusterName field is set to the value of the last call.
func (b *ClusterProxySpecApplyConfiguration) WithClusterName(value string) *ClusterProxySpecApplyConfiguration {
b.ClusterName = &value
return b
}
// WithAPIServer sets the APIServer field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the APIServer field is set to the value of the last call.
func (b *ClusterProxySpecApplyConfiguration) WithAPIServer(value string) *ClusterProxySpecApplyConfiguration {
b.APIServer = &value
return b
}
// WithServiceAccountName sets the ServiceAccountName field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ServiceAccountName field is set to the value of the last call.
func (b *ClusterProxySpecApplyConfiguration) WithServiceAccountName(value string) *ClusterProxySpecApplyConfiguration {
b.ServiceAccountName = &value
return b
}
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: BSD-3-Clause
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha1
import (
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// ClusterProxyStatusApplyConfiguration represents a declarative configuration of the ClusterProxyStatus type for use
// with apply.
//
// ClusterProxyStatus defines the observed state of ClusterProxy.
type ClusterProxyStatusApplyConfiguration struct {
// ObservedGeneration is the last reconciled generation.
ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
// Conditions holds the conditions for the ClusterProxy.
Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
}
// ClusterProxyStatusApplyConfiguration constructs a declarative configuration of the ClusterProxyStatus type for use with
// apply.
func ClusterProxyStatus() *ClusterProxyStatusApplyConfiguration {
return &ClusterProxyStatusApplyConfiguration{}
}
// WithObservedGeneration sets the ObservedGeneration field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ObservedGeneration field is set to the value of the last call.
func (b *ClusterProxyStatusApplyConfiguration) WithObservedGeneration(value int64) *ClusterProxyStatusApplyConfiguration {
b.ObservedGeneration = &value
return b
}
// WithConditions adds the given value to the Conditions field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the Conditions field.
func (b *ClusterProxyStatusApplyConfiguration) WithConditions(values ...*v1.ConditionApplyConfiguration) *ClusterProxyStatusApplyConfiguration {
for i := range values {
if values[i] == nil {
panic("nil value passed to WithConditions")
}
b.Conditions = append(b.Conditions, *values[i])
}
return b
}