diff --git a/README.md b/README.md index 9022da3..b294f60 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,4 @@ helm upgrade --install --create-namespace -n netbird netbird-operator oci://ghcr | [NetworkRouter](docs/api-reference.md#networkrouter) | `netbird.io/v1alpha1` | | [SetupKey](docs/api-reference.md#setupkey) | `netbird.io/v1alpha1` | | [SidecarProfile](docs/api-reference.md#sidecarprofile) | `netbird.io/v1alpha1` | +| [ClusterProxy](docs/api-reference.md#clusterproxy) | `netbird.io/v1alpha1` | diff --git a/api/v1alpha1/clusterproxy_types.go b/api/v1alpha1/clusterproxy_types.go index e799bf2..2b51c50 100644 --- a/api/v1alpha1/clusterproxy_types.go +++ b/api/v1alpha1/clusterproxy_types.go @@ -21,6 +21,10 @@ type ClusterProxySpec struct { // ServiceAccountName is a reference to the service account used for impersonation. // +required 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. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 29058ee..fbf0304 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -17,7 +17,7 @@ func (in *ClusterProxy) DeepCopyInto(out *ClusterProxy) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) 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. func (in *ClusterProxySpec) DeepCopyInto(out *ClusterProxySpec) { *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. diff --git a/charts/netbird-operator/crds/netbird.io_clusterproxies.yaml b/charts/netbird-operator/crds/netbird.io_clusterproxies.yaml index 8ea4b4c..3acfea8 100644 --- a/charts/netbird-operator/crds/netbird.io_clusterproxies.yaml +++ b/charts/netbird-operator/crds/netbird.io_clusterproxies.yaml @@ -57,6 +57,37 @@ spec: x-kubernetes-validations: - message: Value is immutable 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: description: ServiceAccountName is a reference to the service account used for impersonation. diff --git a/config/crd/bases/netbird.io_clusterproxies.yaml b/config/crd/bases/netbird.io_clusterproxies.yaml index 8ea4b4c..3acfea8 100644 --- a/config/crd/bases/netbird.io_clusterproxies.yaml +++ b/config/crd/bases/netbird.io_clusterproxies.yaml @@ -57,6 +57,37 @@ spec: x-kubernetes-validations: - message: Value is immutable 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: description: ServiceAccountName is a reference to the service account used for impersonation. diff --git a/docs/api-reference.md b/docs/api-reference.md index 90c0493..b4d91d6 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -55,6 +55,7 @@ _Appears in:_ | `clusterName` _string_ | ClusterName is the name of the Kubernetes cluster. | | Required: \{\}
| | `apiServer` _string_ | APIServer is the URL of the Kubernetes API server to proxy requests to. | https://kubernetes.default.svc.cluster.local | Required: \{\}
| | `serviceAccountName` _string_ | ServiceAccountName is a reference to the service account used for impersonation. | | Required: \{\}
| +| `groups` _[GroupReference](#groupreference) array_ | Groups are references to groups that the peer will be a part of. | | Optional: \{\}
| #### ClusterProxyStatus @@ -158,6 +159,7 @@ Group is the Schema for the groups API. _Appears in:_ +- [ClusterProxySpec](#clusterproxyspec) - [NetworkResourceSpec](#networkresourcespec) - [SetupKeySpec](#setupkeyspec) diff --git a/examples/api-proxy/api-proxy.yaml b/examples/cluster-proxy/cluster-proxy.yaml similarity index 100% rename from examples/api-proxy/api-proxy.yaml rename to examples/cluster-proxy/cluster-proxy.yaml diff --git a/internal/controller/clusterproxy_controller.go b/internal/controller/clusterproxy_controller.go index b94fdb0..715f793 100644 --- a/internal/controller/clusterproxy_controller.go +++ b/internal/controller/clusterproxy_controller.go @@ -67,6 +67,16 @@ func (r *ClusterProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request WithEphemeral(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) if err != nil { return ctrl.Result{}, err diff --git a/pkg/applyconfigurations/api/v1alpha1/clusterproxyspec.go b/pkg/applyconfigurations/api/v1alpha1/clusterproxyspec.go index 5be3f70..0835750 100644 --- a/pkg/applyconfigurations/api/v1alpha1/clusterproxyspec.go +++ b/pkg/applyconfigurations/api/v1alpha1/clusterproxyspec.go @@ -15,6 +15,8 @@ type ClusterProxySpecApplyConfiguration struct { APIServer *string `json:"apiServer,omitempty"` // ServiceAccountName is a reference to the service account used for impersonation. 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 @@ -46,3 +48,16 @@ func (b *ClusterProxySpecApplyConfiguration) WithServiceAccountName(value string b.ServiceAccountName = &value 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 +}