mirror of
https://github.com/YuzuZensai/netbird-kubernetes-operator.git
synced 2026-09-13 10:49:15 +00:00
Add groups option to cluster proxy (#297)
This change adds an option to specify groups a cluster proxy peer is a member of. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added optional `spec.groups` to the ClusterProxy custom resource to associate group references by `id`, `name`, or `localRef`. * CRD schema includes OpenAPI validation to enforce that each group reference specifies exactly one selector. * **Bug Fixes** * Improved deep-copy behavior for ClusterProxy spec so group references are copied safely and don’t share underlying slices. * **Documentation** * Updated API reference docs and README API table to include the new `groups` field. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -28,3 +28,4 @@ helm upgrade --install --create-namespace -n netbird netbird-operator oci://ghcr
|
|||||||
| [NetworkRouter](docs/api-reference.md#networkrouter) | `netbird.io/v1alpha1` |
|
| [NetworkRouter](docs/api-reference.md#networkrouter) | `netbird.io/v1alpha1` |
|
||||||
| [SetupKey](docs/api-reference.md#setupkey) | `netbird.io/v1alpha1` |
|
| [SetupKey](docs/api-reference.md#setupkey) | `netbird.io/v1alpha1` |
|
||||||
| [SidecarProfile](docs/api-reference.md#sidecarprofile) | `netbird.io/v1alpha1` |
|
| [SidecarProfile](docs/api-reference.md#sidecarprofile) | `netbird.io/v1alpha1` |
|
||||||
|
| [ClusterProxy](docs/api-reference.md#clusterproxy) | `netbird.io/v1alpha1` |
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ type ClusterProxySpec struct {
|
|||||||
// ServiceAccountName is a reference to the service account used for impersonation.
|
// ServiceAccountName is a reference to the service account used for impersonation.
|
||||||
// +required
|
// +required
|
||||||
ServiceAccountName string `json:"serviceAccountName"`
|
ServiceAccountName string `json:"serviceAccountName"`
|
||||||
|
|
||||||
|
// Groups are references to groups that the peer will be a part of.
|
||||||
|
// +optional
|
||||||
|
Groups []GroupReference `json:"groups,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClusterProxyStatus defines the observed state of ClusterProxy.
|
// ClusterProxyStatus defines the observed state of ClusterProxy.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func (in *ClusterProxy) DeepCopyInto(out *ClusterProxy) {
|
|||||||
*out = *in
|
*out = *in
|
||||||
out.TypeMeta = in.TypeMeta
|
out.TypeMeta = in.TypeMeta
|
||||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
out.Spec = in.Spec
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
in.Status.DeepCopyInto(&out.Status)
|
in.Status.DeepCopyInto(&out.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +74,13 @@ func (in *ClusterProxyList) DeepCopyObject() runtime.Object {
|
|||||||
// 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 *ClusterProxySpec) DeepCopyInto(out *ClusterProxySpec) {
|
func (in *ClusterProxySpec) DeepCopyInto(out *ClusterProxySpec) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.Groups != nil {
|
||||||
|
in, out := &in.Groups, &out.Groups
|
||||||
|
*out = make([]GroupReference, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProxySpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProxySpec.
|
||||||
|
|||||||
@@ -57,6 +57,37 @@ spec:
|
|||||||
x-kubernetes-validations:
|
x-kubernetes-validations:
|
||||||
- message: Value is immutable
|
- message: Value is immutable
|
||||||
rule: self == oldSelf
|
rule: self == oldSelf
|
||||||
|
groups:
|
||||||
|
description: Groups are references to groups that the peer will be
|
||||||
|
a part of.
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
description: ID is the id of the group.
|
||||||
|
type: string
|
||||||
|
localRef:
|
||||||
|
description: LocalReference is a reference to a group in the
|
||||||
|
same namespace.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
default: ""
|
||||||
|
description: |-
|
||||||
|
Name of the referent.
|
||||||
|
This field is effectively required, but due to backwards compatibility is
|
||||||
|
allowed to be empty. Instances of this type with an empty value here are
|
||||||
|
almost certainly wrong.
|
||||||
|
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
name:
|
||||||
|
description: Name is the name of the group.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-validations:
|
||||||
|
- message: Exactly one of id, name, or localRef must be set
|
||||||
|
rule: (has(self.id)?1:0)+(has(self.name)?1:0)+(has(self.localRef)?1:0)==1
|
||||||
|
type: array
|
||||||
serviceAccountName:
|
serviceAccountName:
|
||||||
description: ServiceAccountName is a reference to the service account
|
description: ServiceAccountName is a reference to the service account
|
||||||
used for impersonation.
|
used for impersonation.
|
||||||
|
|||||||
@@ -57,6 +57,37 @@ spec:
|
|||||||
x-kubernetes-validations:
|
x-kubernetes-validations:
|
||||||
- message: Value is immutable
|
- message: Value is immutable
|
||||||
rule: self == oldSelf
|
rule: self == oldSelf
|
||||||
|
groups:
|
||||||
|
description: Groups are references to groups that the peer will be
|
||||||
|
a part of.
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
description: ID is the id of the group.
|
||||||
|
type: string
|
||||||
|
localRef:
|
||||||
|
description: LocalReference is a reference to a group in the
|
||||||
|
same namespace.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
default: ""
|
||||||
|
description: |-
|
||||||
|
Name of the referent.
|
||||||
|
This field is effectively required, but due to backwards compatibility is
|
||||||
|
allowed to be empty. Instances of this type with an empty value here are
|
||||||
|
almost certainly wrong.
|
||||||
|
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-map-type: atomic
|
||||||
|
name:
|
||||||
|
description: Name is the name of the group.
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
x-kubernetes-validations:
|
||||||
|
- message: Exactly one of id, name, or localRef must be set
|
||||||
|
rule: (has(self.id)?1:0)+(has(self.name)?1:0)+(has(self.localRef)?1:0)==1
|
||||||
|
type: array
|
||||||
serviceAccountName:
|
serviceAccountName:
|
||||||
description: ServiceAccountName is a reference to the service account
|
description: ServiceAccountName is a reference to the service account
|
||||||
used for impersonation.
|
used for impersonation.
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ _Appears in:_
|
|||||||
| `clusterName` _string_ | ClusterName is the name of the Kubernetes cluster. | | Required: \{\} <br /> |
|
| `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 /> |
|
| `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 /> |
|
| `serviceAccountName` _string_ | ServiceAccountName is a reference to the service account used for impersonation. | | Required: \{\} <br /> |
|
||||||
|
| `groups` _[GroupReference](#groupreference) array_ | Groups are references to groups that the peer will be a part of. | | Optional: \{\} <br /> |
|
||||||
|
|
||||||
|
|
||||||
#### ClusterProxyStatus
|
#### ClusterProxyStatus
|
||||||
@@ -158,6 +159,7 @@ Group is the Schema for the groups API.
|
|||||||
|
|
||||||
|
|
||||||
_Appears in:_
|
_Appears in:_
|
||||||
|
- [ClusterProxySpec](#clusterproxyspec)
|
||||||
- [NetworkResourceSpec](#networkresourcespec)
|
- [NetworkResourceSpec](#networkresourcespec)
|
||||||
- [SetupKeySpec](#setupkeyspec)
|
- [SetupKeySpec](#setupkeyspec)
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,16 @@ func (r *ClusterProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request
|
|||||||
WithEphemeral(true).
|
WithEphemeral(true).
|
||||||
WithAllowExtraDnsLabels(true),
|
WithAllowExtraDnsLabels(true),
|
||||||
)
|
)
|
||||||
|
for _, group := range clusterProxy.Spec.Groups {
|
||||||
|
switch {
|
||||||
|
case group.ID != nil:
|
||||||
|
setupKeyAC.Spec.AutoGroups = append(setupKeyAC.Spec.AutoGroups, *nbv1alpha1ac.GroupReference().WithID(*group.ID))
|
||||||
|
case group.Name != nil:
|
||||||
|
setupKeyAC.Spec.AutoGroups = append(setupKeyAC.Spec.AutoGroups, *nbv1alpha1ac.GroupReference().WithName(*group.Name))
|
||||||
|
case group.LocalRef != nil:
|
||||||
|
setupKeyAC.Spec.AutoGroups = append(setupKeyAC.Spec.AutoGroups, *nbv1alpha1ac.GroupReference().WithLocalRef(*group.LocalRef))
|
||||||
|
}
|
||||||
|
}
|
||||||
err = r.Client.Apply(ctx, setupKeyAC, client.ForceOwnership)
|
err = r.Client.Apply(ctx, setupKeyAC, client.ForceOwnership)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ type ClusterProxySpecApplyConfiguration struct {
|
|||||||
APIServer *string `json:"apiServer,omitempty"`
|
APIServer *string `json:"apiServer,omitempty"`
|
||||||
// ServiceAccountName is a reference to the service account used for impersonation.
|
// ServiceAccountName is a reference to the service account used for impersonation.
|
||||||
ServiceAccountName *string `json:"serviceAccountName,omitempty"`
|
ServiceAccountName *string `json:"serviceAccountName,omitempty"`
|
||||||
|
// Groups are references to groups that the peer will be a part of.
|
||||||
|
Groups []GroupReferenceApplyConfiguration `json:"groups,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClusterProxySpecApplyConfiguration constructs a declarative configuration of the ClusterProxySpec type for use with
|
// ClusterProxySpecApplyConfiguration constructs a declarative configuration of the ClusterProxySpec type for use with
|
||||||
@@ -46,3 +48,16 @@ func (b *ClusterProxySpecApplyConfiguration) WithServiceAccountName(value string
|
|||||||
b.ServiceAccountName = &value
|
b.ServiceAccountName = &value
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithGroups adds the given value to the Groups 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 Groups field.
|
||||||
|
func (b *ClusterProxySpecApplyConfiguration) WithGroups(values ...*GroupReferenceApplyConfiguration) *ClusterProxySpecApplyConfiguration {
|
||||||
|
for i := range values {
|
||||||
|
if values[i] == nil {
|
||||||
|
panic("nil value passed to WithGroups")
|
||||||
|
}
|
||||||
|
b.Groups = append(b.Groups, *values[i])
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user