mirror of
https://github.com/YuzuZensai/netbird-kubernetes-operator.git
synced 2026-09-13 10:49:15 +00:00
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 --> [](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:
@@ -57,6 +57,8 @@ linters:
|
|||||||
alias: metav1
|
alias: metav1
|
||||||
- pkg: k8s.io/api/core/v1
|
- pkg: k8s.io/api/core/v1
|
||||||
alias: corev1
|
alias: corev1
|
||||||
|
- pkg: k8s.io/api/rbac/v1
|
||||||
|
alias: rbacv1
|
||||||
- pkg: k8s.io/api/apps/v1
|
- pkg: k8s.io/api/apps/v1
|
||||||
alias: appsv1
|
alias: appsv1
|
||||||
- pkg: k8s.io/api/admission/v1
|
- pkg: k8s.io/api/admission/v1
|
||||||
@@ -67,6 +69,8 @@ linters:
|
|||||||
alias: metav1ac
|
alias: metav1ac
|
||||||
- pkg: k8s.io/client-go/applyconfigurations/core/v1
|
- pkg: k8s.io/client-go/applyconfigurations/core/v1
|
||||||
alias: corev1ac
|
alias: corev1ac
|
||||||
|
- pkg: k8s.io/client-go/applyconfigurations/rbac/v1
|
||||||
|
alias: rbacv1ac
|
||||||
- pkg: k8s.io/client-go/applyconfigurations/apps/v1
|
- pkg: k8s.io/client-go/applyconfigurations/apps/v1
|
||||||
alias: appsv1ac
|
alias: appsv1ac
|
||||||
- pkg: k8s.io/client-go/applyconfigurations/policy/v1
|
- pkg: k8s.io/client-go/applyconfigurations/policy/v1
|
||||||
|
|||||||
@@ -115,4 +115,12 @@ resources:
|
|||||||
kind: SidecarProfile
|
kind: SidecarProfile
|
||||||
path: github.com/netbirdio/kubernetes-operator/api/v1alpha1
|
path: github.com/netbirdio/kubernetes-operator/api/v1alpha1
|
||||||
version: v1alpha1
|
version: v1alpha1
|
||||||
|
- api:
|
||||||
|
crdVersion: v1
|
||||||
|
namespaced: true
|
||||||
|
controller: true
|
||||||
|
domain: netbird.io
|
||||||
|
kind: ClusterProxy
|
||||||
|
path: github.com/netbirdio/kubernetes-operator/api/v1alpha1
|
||||||
|
version: v1alpha1
|
||||||
version: "3"
|
version: "3"
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClusterProxySpec defines the desired state of ClusterProxy.
|
||||||
|
type ClusterProxySpec struct {
|
||||||
|
// ClusterName is the name of the Kubernetes cluster.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable"
|
||||||
|
ClusterName string `json:"clusterName"`
|
||||||
|
|
||||||
|
// APIServer is the URL of the Kubernetes API server to proxy requests to.
|
||||||
|
// +required
|
||||||
|
// +kubebuilder:default="https://kubernetes.default.svc.cluster.local"
|
||||||
|
APIServer string `json:"apiServer"`
|
||||||
|
|
||||||
|
// ServiceAccountName is a reference to the service account used for impersonation.
|
||||||
|
// +required
|
||||||
|
ServiceAccountName string `json:"serviceAccountName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClusterProxyStatus defines the observed state of ClusterProxy.
|
||||||
|
type ClusterProxyStatus struct {
|
||||||
|
// ObservedGeneration is the last reconciled generation.
|
||||||
|
// +optional
|
||||||
|
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||||
|
|
||||||
|
// Conditions holds the conditions for the ClusterProxy.
|
||||||
|
// +listType=map
|
||||||
|
// +listMapKey=type
|
||||||
|
// +optional
|
||||||
|
Conditions []metav1.Condition `json:"conditions,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
// +kubebuilder:subresource:status
|
||||||
|
// +kubebuilder:resource
|
||||||
|
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description=""
|
||||||
|
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description=""
|
||||||
|
|
||||||
|
// ClusterProxy is the Schema for the clusterproxies API
|
||||||
|
type ClusterProxy struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||||
|
|
||||||
|
// +required
|
||||||
|
Spec ClusterProxySpec `json:"spec"`
|
||||||
|
|
||||||
|
// +kubebuilder:default={"observedGeneration":-1}
|
||||||
|
Status ClusterProxyStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConditions returns the status conditions of the object.
|
||||||
|
func (n *ClusterProxy) GetConditions() []metav1.Condition {
|
||||||
|
return n.Status.Conditions
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConditions sets the status conditions on the object.
|
||||||
|
func (n *ClusterProxy) SetConditions(conditions []metav1.Condition) {
|
||||||
|
n.Status.Conditions = conditions
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:object:root=true
|
||||||
|
|
||||||
|
// ClusterProxyList contains a list of ClusterProxy
|
||||||
|
type ClusterProxyList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
metav1.ListMeta `json:"metadata,omitzero"`
|
||||||
|
Items []ClusterProxy `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
SchemeBuilder.Register(&ClusterProxy{}, &ClusterProxyList{})
|
||||||
|
}
|
||||||
@@ -7,39 +7,135 @@
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ClusterProxy) DeepCopyInto(out *ClusterProxy) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
in.Status.DeepCopyInto(&out.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProxy.
|
||||||
|
func (in *ClusterProxy) DeepCopy() *ClusterProxy {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ClusterProxy)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ClusterProxy) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ClusterProxyList) DeepCopyInto(out *ClusterProxyList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]ClusterProxy, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProxyList.
|
||||||
|
func (in *ClusterProxyList) DeepCopy() *ClusterProxyList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ClusterProxyList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *ClusterProxyList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ClusterProxySpec) DeepCopyInto(out *ClusterProxySpec) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProxySpec.
|
||||||
|
func (in *ClusterProxySpec) DeepCopy() *ClusterProxySpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ClusterProxySpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *ClusterProxyStatus) DeepCopyInto(out *ClusterProxyStatus) {
|
||||||
|
*out = *in
|
||||||
|
if in.Conditions != nil {
|
||||||
|
in, out := &in.Conditions, &out.Conditions
|
||||||
|
*out = make([]v1.Condition, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProxyStatus.
|
||||||
|
func (in *ClusterProxyStatus) DeepCopy() *ClusterProxyStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(ClusterProxyStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *ContainerOverride) DeepCopyInto(out *ContainerOverride) {
|
func (in *ContainerOverride) DeepCopyInto(out *ContainerOverride) {
|
||||||
*out = *in
|
*out = *in
|
||||||
if in.Env != nil {
|
if in.Env != nil {
|
||||||
in, out := &in.Env, &out.Env
|
in, out := &in.Env, &out.Env
|
||||||
*out = make([]v1.EnvVar, len(*in))
|
*out = make([]corev1.EnvVar, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.SecurityContext != nil {
|
if in.SecurityContext != nil {
|
||||||
in, out := &in.SecurityContext, &out.SecurityContext
|
in, out := &in.SecurityContext, &out.SecurityContext
|
||||||
*out = new(v1.SecurityContext)
|
*out = new(corev1.SecurityContext)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.StartupProbe != nil {
|
if in.StartupProbe != nil {
|
||||||
in, out := &in.StartupProbe, &out.StartupProbe
|
in, out := &in.StartupProbe, &out.StartupProbe
|
||||||
*out = new(v1.Probe)
|
*out = new(corev1.Probe)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.LivenessProbe != nil {
|
if in.LivenessProbe != nil {
|
||||||
in, out := &in.LivenessProbe, &out.LivenessProbe
|
in, out := &in.LivenessProbe, &out.LivenessProbe
|
||||||
*out = new(v1.Probe)
|
*out = new(corev1.Probe)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.ReadinessProbe != nil {
|
if in.ReadinessProbe != nil {
|
||||||
in, out := &in.ReadinessProbe, &out.ReadinessProbe
|
in, out := &in.ReadinessProbe, &out.ReadinessProbe
|
||||||
*out = new(v1.Probe)
|
*out = new(corev1.Probe)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,7 +254,7 @@ func (in *GroupReference) DeepCopyInto(out *GroupReference) {
|
|||||||
}
|
}
|
||||||
if in.LocalRef != nil {
|
if in.LocalRef != nil {
|
||||||
in, out := &in.LocalRef, &out.LocalRef
|
in, out := &in.LocalRef, &out.LocalRef
|
||||||
*out = new(v1.LocalObjectReference)
|
*out = new(corev1.LocalObjectReference)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,7 +289,7 @@ func (in *GroupStatus) DeepCopyInto(out *GroupStatus) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]metav1.Condition, len(*in))
|
*out = make([]v1.Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@@ -298,7 +394,7 @@ func (in *NetworkResourceStatus) DeepCopyInto(out *NetworkResourceStatus) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]metav1.Condition, len(*in))
|
*out = make([]v1.Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@@ -400,7 +496,7 @@ func (in *NetworkRouterStatus) DeepCopyInto(out *NetworkRouterStatus) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]metav1.Condition, len(*in))
|
*out = make([]v1.Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@@ -481,7 +577,7 @@ func (in *SetupKeySpec) DeepCopyInto(out *SetupKeySpec) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Duration != nil {
|
if in.Duration != nil {
|
||||||
in, out := &in.Duration, &out.Duration
|
in, out := &in.Duration, &out.Duration
|
||||||
*out = new(metav1.Duration)
|
*out = new(v1.Duration)
|
||||||
**out = **in
|
**out = **in
|
||||||
}
|
}
|
||||||
if in.AutoGroups != nil {
|
if in.AutoGroups != nil {
|
||||||
@@ -508,7 +604,7 @@ func (in *SetupKeyStatus) DeepCopyInto(out *SetupKeyStatus) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]metav1.Condition, len(*in))
|
*out = make([]v1.Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@@ -590,7 +686,7 @@ func (in *SidecarProfileSpec) DeepCopyInto(out *SidecarProfileSpec) {
|
|||||||
out.SetupKeyRef = in.SetupKeyRef
|
out.SetupKeyRef = in.SetupKeyRef
|
||||||
if in.PodSelector != nil {
|
if in.PodSelector != nil {
|
||||||
in, out := &in.PodSelector, &out.PodSelector
|
in, out := &in.PodSelector, &out.PodSelector
|
||||||
*out = new(metav1.LabelSelector)
|
*out = new(v1.LabelSelector)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
if in.ExtraDNSLabels != nil {
|
if in.ExtraDNSLabels != nil {
|
||||||
@@ -620,7 +716,7 @@ func (in *SidecarProfileStatus) DeepCopyInto(out *SidecarProfileStatus) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
if in.Conditions != nil {
|
if in.Conditions != nil {
|
||||||
in, out := &in.Conditions, &out.Conditions
|
in, out := &in.Conditions, &out.Conditions
|
||||||
*out = make([]metav1.Condition, len(*in))
|
*out = make([]v1.Condition, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
@@ -661,7 +757,7 @@ func (in *WorkloadOverride) DeepCopyInto(out *WorkloadOverride) {
|
|||||||
}
|
}
|
||||||
if in.PodTemplate != nil {
|
if in.PodTemplate != nil {
|
||||||
in, out := &in.PodTemplate, &out.PodTemplate
|
in, out := &in.PodTemplate, &out.PodTemplate
|
||||||
*out = new(v1.PodTemplateSpec)
|
*out = new(corev1.PodTemplateSpec)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.20.1
|
||||||
|
name: clusterproxies.netbird.io
|
||||||
|
spec:
|
||||||
|
group: netbird.io
|
||||||
|
names:
|
||||||
|
kind: ClusterProxy
|
||||||
|
listKind: ClusterProxyList
|
||||||
|
plural: clusterproxies
|
||||||
|
singular: clusterproxy
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||||
|
name: Ready
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ClusterProxy is the Schema for the clusterproxies API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: |-
|
||||||
|
APIVersion defines the versioned schema of this representation of an object.
|
||||||
|
Servers should convert recognized schemas to the latest internal value, and
|
||||||
|
may reject unrecognized values.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: |-
|
||||||
|
Kind is a string value representing the REST resource this object represents.
|
||||||
|
Servers may infer this from the endpoint the client submits requests to.
|
||||||
|
Cannot be updated.
|
||||||
|
In CamelCase.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ClusterProxySpec defines the desired state of ClusterProxy.
|
||||||
|
properties:
|
||||||
|
apiServer:
|
||||||
|
default: https://kubernetes.default.svc.cluster.local
|
||||||
|
description: APIServer is the URL of the Kubernetes API server to
|
||||||
|
proxy requests to.
|
||||||
|
type: string
|
||||||
|
clusterName:
|
||||||
|
description: ClusterName is the name of the Kubernetes cluster.
|
||||||
|
type: string
|
||||||
|
x-kubernetes-validations:
|
||||||
|
- message: Value is immutable
|
||||||
|
rule: self == oldSelf
|
||||||
|
serviceAccountName:
|
||||||
|
description: ServiceAccountName is a reference to the service account
|
||||||
|
used for impersonation.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- apiServer
|
||||||
|
- clusterName
|
||||||
|
- serviceAccountName
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
default:
|
||||||
|
observedGeneration: -1
|
||||||
|
description: ClusterProxyStatus defines the observed state of ClusterProxy.
|
||||||
|
properties:
|
||||||
|
conditions:
|
||||||
|
description: Conditions holds the conditions for the ClusterProxy.
|
||||||
|
items:
|
||||||
|
description: Condition contains details for one aspect of the current
|
||||||
|
state of this API Resource.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: |-
|
||||||
|
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: |-
|
||||||
|
message is a human readable message indicating details about the transition.
|
||||||
|
This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: |-
|
||||||
|
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
with respect to the current state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: |-
|
||||||
|
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
and whether the values are considered a guaranteed API.
|
||||||
|
The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- type
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
observedGeneration:
|
||||||
|
description: ObservedGeneration is the last reconciled generation.
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
@@ -39,6 +39,7 @@ rules:
|
|||||||
- networkrouters
|
- networkrouters
|
||||||
- networkresources
|
- networkresources
|
||||||
- sidecarprofiles
|
- sidecarprofiles
|
||||||
|
- clusterproxies
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- patch
|
- patch
|
||||||
@@ -59,6 +60,7 @@ rules:
|
|||||||
- networkrouters/status
|
- networkrouters/status
|
||||||
- networkresources/status
|
- networkresources/status
|
||||||
- sidecarprofiles/status
|
- sidecarprofiles/status
|
||||||
|
- clusterproxies/status
|
||||||
verbs:
|
verbs:
|
||||||
- get
|
- get
|
||||||
- patch
|
- patch
|
||||||
|
|||||||
+14
-7
@@ -60,7 +60,7 @@ func main() {
|
|||||||
var (
|
var (
|
||||||
runtimeNamespace string
|
runtimeNamespace string
|
||||||
managementURL string
|
managementURL string
|
||||||
clientImage string
|
netbirdClientImage string
|
||||||
clusterName string
|
clusterName string
|
||||||
namespacedNetworks bool
|
namespacedNetworks bool
|
||||||
clusterDNS string
|
clusterDNS string
|
||||||
@@ -71,7 +71,7 @@ func main() {
|
|||||||
)
|
)
|
||||||
flag.StringVar(&runtimeNamespace, "runtime-namespace", "", "Namespace the controller is running in")
|
flag.StringVar(&runtimeNamespace, "runtime-namespace", "", "Namespace the controller is running in")
|
||||||
flag.StringVar(&managementURL, "netbird-management-url", "https://api.netbird.io", "Management service URL")
|
flag.StringVar(&managementURL, "netbird-management-url", "https://api.netbird.io", "Management service URL")
|
||||||
flag.StringVar(&clientImage, "netbird-client-image", "", "Image for netbird client container")
|
flag.StringVar(&netbirdClientImage, "netbird-client-image", "", "Image for netbird client container")
|
||||||
flag.StringVar(
|
flag.StringVar(
|
||||||
&clusterName,
|
&clusterName,
|
||||||
"cluster-name",
|
"cluster-name",
|
||||||
@@ -139,8 +139,8 @@ func main() {
|
|||||||
setupLog.Error(err, "unable to get runtime namespace")
|
setupLog.Error(err, "unable to get runtime namespace")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if clientImage == "" {
|
if netbirdClientImage == "" {
|
||||||
clientImage = version.ClientImage()
|
netbirdClientImage = version.NetbirdClientImage
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultLabelsMap := make(map[string]string)
|
defaultLabelsMap := make(map[string]string)
|
||||||
@@ -210,7 +210,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if enableWebhooks {
|
if enableWebhooks {
|
||||||
if err = nbwebhookv1.SetupPodWebhookWithManager(mgr, managementURL, clientImage); err != nil {
|
if err = nbwebhookv1.SetupPodWebhookWithManager(mgr, managementURL, netbirdClientImage); err != nil {
|
||||||
setupLog.Error(err, "unable to create webhook", "webhook", "Pod")
|
setupLog.Error(err, "unable to create webhook", "webhook", "Pod")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ func main() {
|
|||||||
if err = (&controller.NBRoutingPeerReconciler{
|
if err = (&controller.NBRoutingPeerReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Netbird: nbClient,
|
Netbird: nbClient,
|
||||||
ClientImage: clientImage,
|
ClientImage: netbirdClientImage,
|
||||||
ClusterName: clusterName,
|
ClusterName: clusterName,
|
||||||
ManagementURL: managementURL,
|
ManagementURL: managementURL,
|
||||||
NamespacedNetworks: namespacedNetworks,
|
NamespacedNetworks: namespacedNetworks,
|
||||||
@@ -299,7 +299,7 @@ func main() {
|
|||||||
if err := (&controller.NetworkRouterReconciler{
|
if err := (&controller.NetworkRouterReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Netbird: nbClient,
|
Netbird: nbClient,
|
||||||
ClientImage: clientImage,
|
ClientImage: netbirdClientImage,
|
||||||
ManagementURL: managementURL,
|
ManagementURL: managementURL,
|
||||||
}).SetupWithManager(mgr); err != nil {
|
}).SetupWithManager(mgr); err != nil {
|
||||||
setupLog.Error(err, "Failed to create controller", "controller", "NetworkRouter")
|
setupLog.Error(err, "Failed to create controller", "controller", "NetworkRouter")
|
||||||
@@ -312,6 +312,13 @@ func main() {
|
|||||||
setupLog.Error(err, "Failed to create controller", "controller", "NetworkResource")
|
setupLog.Error(err, "Failed to create controller", "controller", "NetworkResource")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
if err := (&controller.ClusterProxyReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
ApiKey: netbirdAPIKey,
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
setupLog.Error(err, "Failed to create controller", "controller", "ClusterProxy")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
if gatewayAPIEnabled {
|
if gatewayAPIEnabled {
|
||||||
if err = (&controller.GatewayClassReconciler{
|
if err = (&controller.GatewayClassReconciler{
|
||||||
|
|||||||
@@ -0,0 +1,145 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
controller-gen.kubebuilder.io/version: v0.20.1
|
||||||
|
name: clusterproxies.netbird.io
|
||||||
|
spec:
|
||||||
|
group: netbird.io
|
||||||
|
names:
|
||||||
|
kind: ClusterProxy
|
||||||
|
listKind: ClusterProxyList
|
||||||
|
plural: clusterproxies
|
||||||
|
singular: clusterproxy
|
||||||
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||||
|
name: Ready
|
||||||
|
type: string
|
||||||
|
- jsonPath: .metadata.creationTimestamp
|
||||||
|
name: Age
|
||||||
|
type: date
|
||||||
|
name: v1alpha1
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
description: ClusterProxy is the Schema for the clusterproxies API
|
||||||
|
properties:
|
||||||
|
apiVersion:
|
||||||
|
description: |-
|
||||||
|
APIVersion defines the versioned schema of this representation of an object.
|
||||||
|
Servers should convert recognized schemas to the latest internal value, and
|
||||||
|
may reject unrecognized values.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
|
type: string
|
||||||
|
kind:
|
||||||
|
description: |-
|
||||||
|
Kind is a string value representing the REST resource this object represents.
|
||||||
|
Servers may infer this from the endpoint the client submits requests to.
|
||||||
|
Cannot be updated.
|
||||||
|
In CamelCase.
|
||||||
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
|
type: string
|
||||||
|
metadata:
|
||||||
|
type: object
|
||||||
|
spec:
|
||||||
|
description: ClusterProxySpec defines the desired state of ClusterProxy.
|
||||||
|
properties:
|
||||||
|
apiServer:
|
||||||
|
default: https://kubernetes.default.svc.cluster.local
|
||||||
|
description: APIServer is the URL of the Kubernetes API server to
|
||||||
|
proxy requests to.
|
||||||
|
type: string
|
||||||
|
clusterName:
|
||||||
|
description: ClusterName is the name of the Kubernetes cluster.
|
||||||
|
type: string
|
||||||
|
x-kubernetes-validations:
|
||||||
|
- message: Value is immutable
|
||||||
|
rule: self == oldSelf
|
||||||
|
serviceAccountName:
|
||||||
|
description: ServiceAccountName is a reference to the service account
|
||||||
|
used for impersonation.
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- apiServer
|
||||||
|
- clusterName
|
||||||
|
- serviceAccountName
|
||||||
|
type: object
|
||||||
|
status:
|
||||||
|
default:
|
||||||
|
observedGeneration: -1
|
||||||
|
description: ClusterProxyStatus defines the observed state of ClusterProxy.
|
||||||
|
properties:
|
||||||
|
conditions:
|
||||||
|
description: Conditions holds the conditions for the ClusterProxy.
|
||||||
|
items:
|
||||||
|
description: Condition contains details for one aspect of the current
|
||||||
|
state of this API Resource.
|
||||||
|
properties:
|
||||||
|
lastTransitionTime:
|
||||||
|
description: |-
|
||||||
|
lastTransitionTime is the last time the condition transitioned from one status to another.
|
||||||
|
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
|
||||||
|
format: date-time
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
description: |-
|
||||||
|
message is a human readable message indicating details about the transition.
|
||||||
|
This may be an empty string.
|
||||||
|
maxLength: 32768
|
||||||
|
type: string
|
||||||
|
observedGeneration:
|
||||||
|
description: |-
|
||||||
|
observedGeneration represents the .metadata.generation that the condition was set based upon.
|
||||||
|
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
|
||||||
|
with respect to the current state of the instance.
|
||||||
|
format: int64
|
||||||
|
minimum: 0
|
||||||
|
type: integer
|
||||||
|
reason:
|
||||||
|
description: |-
|
||||||
|
reason contains a programmatic identifier indicating the reason for the condition's last transition.
|
||||||
|
Producers of specific condition types may define expected values and meanings for this field,
|
||||||
|
and whether the values are considered a guaranteed API.
|
||||||
|
The value should be a CamelCase string.
|
||||||
|
This field may not be empty.
|
||||||
|
maxLength: 1024
|
||||||
|
minLength: 1
|
||||||
|
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
|
||||||
|
type: string
|
||||||
|
status:
|
||||||
|
description: status of the condition, one of True, False, Unknown.
|
||||||
|
enum:
|
||||||
|
- "True"
|
||||||
|
- "False"
|
||||||
|
- Unknown
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: type of condition in CamelCase or in foo.example.com/CamelCase.
|
||||||
|
maxLength: 316
|
||||||
|
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- lastTransitionTime
|
||||||
|
- message
|
||||||
|
- reason
|
||||||
|
- status
|
||||||
|
- type
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
x-kubernetes-list-map-keys:
|
||||||
|
- type
|
||||||
|
x-kubernetes-list-type: map
|
||||||
|
observedGeneration:
|
||||||
|
description: ObservedGeneration is the last reconciled generation.
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
required:
|
||||||
|
- spec
|
||||||
|
type: object
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
@@ -11,4 +11,5 @@ resources:
|
|||||||
- bases/netbird.io_networkrouters.yaml
|
- bases/netbird.io_networkrouters.yaml
|
||||||
- bases/netbird.io_setupkeys.yaml
|
- bases/netbird.io_setupkeys.yaml
|
||||||
- bases/netbird.io_sidecarprofiles.yaml
|
- bases/netbird.io_sidecarprofiles.yaml
|
||||||
|
- bases/netbird.io_clusterproxies.yaml
|
||||||
# +kubebuilder:scaffold:crdkustomizeresource
|
# +kubebuilder:scaffold:crdkustomizeresource
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# This file is for teaching kustomize how to substitute name and namespace reference in CRD
|
||||||
|
nameReference:
|
||||||
|
- kind: Service
|
||||||
|
version: v1
|
||||||
|
fieldSpecs:
|
||||||
|
- kind: CustomResourceDefinition
|
||||||
|
version: v1
|
||||||
|
group: apiextensions.k8s.io
|
||||||
|
path: spec/conversion/webhook/clientConfig/service/name
|
||||||
|
|
||||||
|
varReference:
|
||||||
|
- path: metadata/annotations
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
Package v1alpha1 contains API Schema definitions for the v1alpha1 API group.
|
Package v1alpha1 contains API Schema definitions for the v1alpha1 API group.
|
||||||
|
|
||||||
### Resource Types
|
### Resource Types
|
||||||
|
- [ClusterProxy](#clusterproxy)
|
||||||
- [Group](#group)
|
- [Group](#group)
|
||||||
- [NetworkResource](#networkresource)
|
- [NetworkResource](#networkresource)
|
||||||
- [NetworkRouter](#networkrouter)
|
- [NetworkRouter](#networkrouter)
|
||||||
@@ -17,6 +18,62 @@ Package v1alpha1 contains API Schema definitions for the v1alpha1 API group.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### ClusterProxy
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ClusterProxy is the Schema for the clusterproxies API
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
| Field | Description | Default | Validation |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `apiVersion` _string_ | `netbird.io/v1alpha1` | | |
|
||||||
|
| `kind` _string_ | `ClusterProxy` | | |
|
||||||
|
| `kind` _string_ | Kind is a string value representing the REST resource this object represents.<br />Servers may infer this from the endpoint the client submits requests to.<br />Cannot be updated.<br />In CamelCase.<br />More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds | | Optional: \{\} <br /> |
|
||||||
|
| `apiVersion` _string_ | APIVersion defines the versioned schema of this representation of an object.<br />Servers should convert recognized schemas to the latest internal value, and<br />may reject unrecognized values.<br />More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources | | Optional: \{\} <br /> |
|
||||||
|
| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | | |
|
||||||
|
| `spec` _[ClusterProxySpec](#clusterproxyspec)_ | | | Required: \{\} <br /> |
|
||||||
|
| `status` _[ClusterProxyStatus](#clusterproxystatus)_ | | \{ observedGeneration:-1 \} | |
|
||||||
|
|
||||||
|
|
||||||
|
#### ClusterProxySpec
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ClusterProxySpec defines the desired state of ClusterProxy.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_Appears in:_
|
||||||
|
- [ClusterProxy](#clusterproxy)
|
||||||
|
|
||||||
|
| Field | Description | Default | Validation |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `clusterName` _string_ | ClusterName is the name of the Kubernetes cluster. | | Required: \{\} <br /> |
|
||||||
|
| `apiServer` _string_ | APIServer is the URL of the Kubernetes API server to proxy requests to. | https://kubernetes.default.svc.cluster.local | Required: \{\} <br /> |
|
||||||
|
| `serviceAccountName` _string_ | ServiceAccountName is a reference to the service account used for impersonation. | | Required: \{\} <br /> |
|
||||||
|
|
||||||
|
|
||||||
|
#### ClusterProxyStatus
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ClusterProxyStatus defines the observed state of ClusterProxy.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_Appears in:_
|
||||||
|
- [ClusterProxy](#clusterproxy)
|
||||||
|
|
||||||
|
| Field | Description | Default | Validation |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `observedGeneration` _integer_ | ObservedGeneration is the last reconciled generation. | | Optional: \{\} <br /> |
|
||||||
|
| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.35/#condition-v1-meta) array_ | Conditions holds the conditions for the ClusterProxy. | | Optional: \{\} <br /> |
|
||||||
|
|
||||||
|
|
||||||
#### ContainerOverride
|
#### ContainerOverride
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
apiVersion: netbird.io/v1alpha1
|
||||||
|
kind: ClusterProxy
|
||||||
|
metadata:
|
||||||
|
name: prod
|
||||||
|
namespace: netbird
|
||||||
|
spec:
|
||||||
|
clusterName: prod
|
||||||
|
serviceAccountName: clusterproxy-prod
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: clusterproxy-prod
|
||||||
|
namespace: netbird
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: clusterproxy-prod
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- users
|
||||||
|
- groups
|
||||||
|
verbs:
|
||||||
|
- impersonate
|
||||||
|
|
||||||
|
- apiGroups:
|
||||||
|
- authentication.k8s.io
|
||||||
|
resources:
|
||||||
|
- userextras/*
|
||||||
|
- uids
|
||||||
|
verbs:
|
||||||
|
- impersonate
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: clusterproxy-prod
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: clusterproxy-prod
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: clusterproxy-prod
|
||||||
|
namespace: netbird
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRole
|
||||||
|
metadata:
|
||||||
|
name: netbird-cluster-reader
|
||||||
|
rules:
|
||||||
|
- apiGroups: ["*"]
|
||||||
|
resources: ["*"]
|
||||||
|
verbs: ["get", "list", "watch"]
|
||||||
|
---
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: netbird-cluster-reader
|
||||||
|
subjects:
|
||||||
|
- kind: Group
|
||||||
|
name: kubernetes-read
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
roleRef:
|
||||||
|
kind: ClusterRole
|
||||||
|
name: netbird-cluster-reader
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fluxcd/pkg/runtime/conditions"
|
||||||
|
"github.com/fluxcd/pkg/runtime/patch"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
appsv1ac "k8s.io/client-go/applyconfigurations/apps/v1"
|
||||||
|
corev1ac "k8s.io/client-go/applyconfigurations/core/v1"
|
||||||
|
metav1ac "k8s.io/client-go/applyconfigurations/meta/v1"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
|
||||||
|
nbv1alpha1 "github.com/netbirdio/kubernetes-operator/api/v1alpha1"
|
||||||
|
"github.com/netbirdio/kubernetes-operator/internal/k8sutil"
|
||||||
|
"github.com/netbirdio/kubernetes-operator/internal/version"
|
||||||
|
nbv1alpha1ac "github.com/netbirdio/kubernetes-operator/pkg/applyconfigurations/api/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClusterProxyReconciler reconciles a ClusterProxy object
|
||||||
|
type ClusterProxyReconciler struct {
|
||||||
|
client.Client
|
||||||
|
|
||||||
|
ApiKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
// +kubebuilder:rbac:groups=netbird.io,resources=clusterproxies,verbs=get;list;watch;create;update;patch;delete
|
||||||
|
// +kubebuilder:rbac:groups=netbird.io,resources=clusterproxies/status,verbs=get;update;patch
|
||||||
|
// +kubebuilder:rbac:groups=netbird.io,resources=clusterproxies/finalizers,verbs=update
|
||||||
|
|
||||||
|
func (r *ClusterProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
|
||||||
|
clusterProxy := &nbv1alpha1.ClusterProxy{}
|
||||||
|
err := r.Get(ctx, req.NamespacedName, clusterProxy)
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||||
|
}
|
||||||
|
sp := patch.NewSerialPatcher(clusterProxy, r.Client)
|
||||||
|
|
||||||
|
if !clusterProxy.DeletionTimestamp.IsZero() {
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
ownerRef, err := k8sutil.ControllerReference(clusterProxy, r.Scheme())
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate unique suffix used for Netbird resources.
|
||||||
|
sum := sha256.Sum256([]byte(clusterProxy.UID))
|
||||||
|
uniqueSuffix := fmt.Sprintf("%x", sum[:4])[:8]
|
||||||
|
|
||||||
|
// Create the setup key used by routing peers.
|
||||||
|
setupKeyAC := nbv1alpha1ac.SetupKey(fmt.Sprintf("clusterproxy-%s", clusterProxy.Name), req.Namespace).
|
||||||
|
WithOwnerReferences(ownerRef).
|
||||||
|
WithSpec(
|
||||||
|
nbv1alpha1ac.SetupKeySpec().
|
||||||
|
WithName(fmt.Sprintf("clusterproxy-%s", uniqueSuffix)).
|
||||||
|
WithEphemeral(true).
|
||||||
|
WithAllowExtraDnsLabels(true),
|
||||||
|
)
|
||||||
|
err = r.Client.Apply(ctx, setupKeyAC)
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
setupKey := nbv1alpha1.SetupKey{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: *setupKeyAC.Name,
|
||||||
|
Namespace: *setupKeyAC.Namespace,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err = r.Get(ctx, client.ObjectKeyFromObject(&setupKey), &setupKey)
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, client.IgnoreNotFound(err)
|
||||||
|
}
|
||||||
|
if setupKey.Status.SetupKeyID == "" {
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create secret for api token.
|
||||||
|
secretAC := corev1ac.Secret(fmt.Sprintf("clusterproxy-%s", req.Name), req.Namespace).
|
||||||
|
WithOwnerReferences(ownerRef).
|
||||||
|
WithStringData(map[string]string{"api-key": r.ApiKey})
|
||||||
|
err = r.Client.Apply(ctx, secretAC)
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the API proxy deployment.
|
||||||
|
selectorLabels := map[string]string{
|
||||||
|
"app.kubernetes.io/name": "clusterproxy",
|
||||||
|
"app.kubernetes.io/instance": req.Name,
|
||||||
|
}
|
||||||
|
podTemplateSpecAC := corev1ac.PodTemplateSpec().
|
||||||
|
WithLabels(selectorLabels).
|
||||||
|
WithSpec(corev1ac.PodSpec().
|
||||||
|
WithTopologySpreadConstraints(
|
||||||
|
corev1ac.TopologySpreadConstraint().
|
||||||
|
WithMaxSkew(1).
|
||||||
|
WithTopologyKey(corev1.LabelHostname).
|
||||||
|
WithWhenUnsatisfiable(corev1.ScheduleAnyway).
|
||||||
|
WithLabelSelector(metav1ac.LabelSelector().
|
||||||
|
WithMatchLabels(selectorLabels),
|
||||||
|
),
|
||||||
|
).
|
||||||
|
WithServiceAccountName(clusterProxy.Spec.ServiceAccountName).
|
||||||
|
WithContainers(corev1ac.Container().
|
||||||
|
WithName("proxy").
|
||||||
|
WithImage(version.KubeApiProxyImage).
|
||||||
|
WithArgs(
|
||||||
|
"--setup-key",
|
||||||
|
"$(SETUP_KEY)",
|
||||||
|
"--api-key",
|
||||||
|
"$(API_KEY)",
|
||||||
|
"--instance-name",
|
||||||
|
"$(POD_NAME)",
|
||||||
|
"--cluster-name",
|
||||||
|
clusterProxy.Spec.ClusterName,
|
||||||
|
"--kubernetes-api-server",
|
||||||
|
clusterProxy.Spec.APIServer,
|
||||||
|
).
|
||||||
|
WithEnv(
|
||||||
|
corev1ac.EnvVar().
|
||||||
|
WithName("POD_NAME").
|
||||||
|
WithValueFrom(corev1ac.EnvVarSource().
|
||||||
|
WithFieldRef(corev1ac.ObjectFieldSelector().WithFieldPath("metadata.name")),
|
||||||
|
),
|
||||||
|
corev1ac.EnvVar().
|
||||||
|
WithName("SETUP_KEY").
|
||||||
|
WithValueFrom(corev1ac.EnvVarSource().
|
||||||
|
WithSecretKeyRef(corev1ac.SecretKeySelector().
|
||||||
|
WithName(setupKey.SecretName()).
|
||||||
|
WithKey(SetupKeySecretKey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
corev1ac.EnvVar().
|
||||||
|
WithName("API_KEY").
|
||||||
|
WithValueFrom(corev1ac.EnvVarSource().
|
||||||
|
WithSecretKeyRef(corev1ac.SecretKeySelector().
|
||||||
|
WithName(*secretAC.Name).
|
||||||
|
WithKey("api-key"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).
|
||||||
|
WithSecurityContext(corev1ac.SecurityContext().
|
||||||
|
WithAllowPrivilegeEscalation(false).
|
||||||
|
WithReadOnlyRootFilesystem(true).
|
||||||
|
WithRunAsNonRoot(true).
|
||||||
|
WithCapabilities(corev1ac.Capabilities().WithDrop("ALL")),
|
||||||
|
).
|
||||||
|
WithResources(corev1ac.ResourceRequirements().
|
||||||
|
WithRequests(corev1.ResourceList{
|
||||||
|
corev1.ResourceCPU: resource.MustParse("100m"),
|
||||||
|
corev1.ResourceMemory: resource.MustParse("128Mi"),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
depAC := appsv1ac.Deployment(fmt.Sprintf("clusterproxy-%s", req.Name), req.Namespace).
|
||||||
|
WithOwnerReferences(ownerRef).
|
||||||
|
WithLabels(selectorLabels).
|
||||||
|
WithSpec(appsv1ac.DeploymentSpec().WithReplicas(1).WithSelector(metav1ac.LabelSelector().WithMatchLabels(selectorLabels)).WithTemplate(podTemplateSpecAC))
|
||||||
|
err = r.Client.Apply(ctx, depAC)
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
conditions.MarkTrue(clusterProxy, nbv1alpha1.ReadyCondition, nbv1alpha1.ReconciledReason, "")
|
||||||
|
err = sp.Patch(ctx, clusterProxy, patch.WithStatusObservedGeneration{})
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ClusterProxyReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||||
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
|
For(&nbv1alpha1.ClusterProxy{}).
|
||||||
|
Owns(&nbv1alpha1.SetupKey{}).
|
||||||
|
Owns(&appsv1.Deployment{}).
|
||||||
|
Complete(r)
|
||||||
|
}
|
||||||
@@ -6,9 +6,10 @@ import (
|
|||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ClientImage() string {
|
const (
|
||||||
return "ghcr.io/netbirdio/netbird:0.71.4@sha256:c4195811bf9999544db5176950a0d6513c880d0195450b59eb156c254e0dd3b5"
|
NetbirdClientImage = "ghcr.io/netbirdio/netbird:0.71.4@sha256:c4195811bf9999544db5176950a0d6513c880d0195450b59eb156c254e0dd3b5"
|
||||||
}
|
KubeApiProxyImage = "ghcr.io/netbirdio/netbird-kubeapi-proxy:v0.0.1@sha256:aa5bbdfc2eca51438f3d50ed4441d61388e9a8d2d5dc886cc4988dacd36ad648"
|
||||||
|
)
|
||||||
|
|
||||||
func BuildVersion() string {
|
func BuildVersion() string {
|
||||||
bi, ok := debug.ReadBuildInfo()
|
bi, ok := debug.ReadBuildInfo()
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/go-openapi/testify/v2/require"
|
"github.com/go-openapi/testify/v2/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestClientImage(t *testing.T) {
|
func TestNetbirdClientImage(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
b, err := os.ReadFile("../../go.mod")
|
b, err := os.ReadFile("../../go.mod")
|
||||||
@@ -26,10 +26,9 @@ func TestClientImage(t *testing.T) {
|
|||||||
require.GreaterT(t, idx, -1)
|
require.GreaterT(t, idx, -1)
|
||||||
modVersion := strings.TrimPrefix(f.Require[idx].Mod.Version, "v")
|
modVersion := strings.TrimPrefix(f.Require[idx].Mod.Version, "v")
|
||||||
|
|
||||||
clientImg := ClientImage()
|
start := strings.Index(NetbirdClientImage, ":") + 1
|
||||||
start := strings.Index(clientImg, ":") + 1
|
end := strings.Index(NetbirdClientImage, "@")
|
||||||
end := strings.Index(clientImg, "@")
|
imgVersion := NetbirdClientImage[start:end]
|
||||||
imgVersion := clientImg[start:end]
|
|
||||||
|
|
||||||
require.EqualT(t, modVersion, imgVersion)
|
require.EqualT(t, modVersion, imgVersion)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -18,6 +18,12 @@ import (
|
|||||||
func ForKind(kind schema.GroupVersionKind) interface{} {
|
func ForKind(kind schema.GroupVersionKind) interface{} {
|
||||||
switch kind {
|
switch kind {
|
||||||
// Group=netbird.io, Version=v1alpha1
|
// Group=netbird.io, Version=v1alpha1
|
||||||
|
case v1alpha1.SchemeGroupVersion.WithKind("ClusterProxy"):
|
||||||
|
return &apiv1alpha1.ClusterProxyApplyConfiguration{}
|
||||||
|
case v1alpha1.SchemeGroupVersion.WithKind("ClusterProxySpec"):
|
||||||
|
return &apiv1alpha1.ClusterProxySpecApplyConfiguration{}
|
||||||
|
case v1alpha1.SchemeGroupVersion.WithKind("ClusterProxyStatus"):
|
||||||
|
return &apiv1alpha1.ClusterProxyStatusApplyConfiguration{}
|
||||||
case v1alpha1.SchemeGroupVersion.WithKind("ContainerOverride"):
|
case v1alpha1.SchemeGroupVersion.WithKind("ContainerOverride"):
|
||||||
return &apiv1alpha1.ContainerOverrideApplyConfiguration{}
|
return &apiv1alpha1.ContainerOverrideApplyConfiguration{}
|
||||||
case v1alpha1.SchemeGroupVersion.WithKind("CrossNamespaceReference"):
|
case v1alpha1.SchemeGroupVersion.WithKind("CrossNamespaceReference"):
|
||||||
|
|||||||
Reference in New Issue
Block a user