Skip to content

Commit 4b98bf9

Browse files
Add feature to add default labels to all resources (#62)
Fixes #41 Thanks to @mhartmann-jaconi for the Helm changes in #42
1 parent 1b36287 commit 4b98bf9

File tree

10 files changed

+94
-10
lines changed

10 files changed

+94
-10
lines changed

cmd/main.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"fmt"
2323
"os"
2424
"path/filepath"
25+
"strings"
2526

2627
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
2728
// to ensure that exec-entrypoint and run can make use of them.
@@ -74,6 +75,7 @@ func main() {
7475
clusterDNS string
7576
netbirdAPIKey string
7677
allowAutomaticPolicyCreation bool
78+
defaultLabels string
7779
)
7880
flag.StringVar(&managementURL, "netbird-management-url", "https://api.netbird.io", "Management service URL")
7981
flag.StringVar(&clientImage, "netbird-client-image", "netbirdio/netbird:latest", "Image for netbird client container")
@@ -97,6 +99,12 @@ func main() {
9799
false,
98100
"Allow creating NBPolicy resources from annotations on Services",
99101
)
102+
flag.StringVar(
103+
&defaultLabels,
104+
"default-labels",
105+
"",
106+
"Default labels used for all resources, in format key=value,key=value",
107+
)
100108

101109
// Controller generic flags
102110
var (
@@ -129,6 +137,17 @@ func main() {
129137
opts.BindFlags(flag.CommandLine)
130138
flag.Parse()
131139

140+
defaultLabelsMap := make(map[string]string)
141+
if defaultLabels != "" {
142+
for _, s := range strings.Split(defaultLabels, ",") {
143+
kv := strings.Split(s, "=")
144+
if len(kv) != 2 {
145+
panic(fmt.Errorf("invalid label format: %s", s))
146+
}
147+
defaultLabelsMap[kv[0]] = kv[1]
148+
}
149+
}
150+
132151
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
133152

134153
disableHTTP2 := func(c *tls.Config) {
@@ -216,6 +235,7 @@ func main() {
216235
APIKey: netbirdAPIKey,
217236
ManagementURL: managementURL,
218237
NamespacedNetworks: namespacedNetworks,
238+
DefaultLabels: defaultLabelsMap,
219239
}).SetupWithManager(mgr); err != nil {
220240
setupLog.Error(err, "unable to create controller", "controller", "NBRoutingPeer")
221241
os.Exit(1)
@@ -234,6 +254,7 @@ func main() {
234254
ClusterDNS: clusterDNS,
235255
NamespacedNetworks: namespacedNetworks,
236256
ControllerNamespace: controllerNamespace,
257+
DefaultLabels: defaultLabelsMap,
237258
}).SetupWithManager(mgr); err != nil {
238259
setupLog.Error(err, "unable to create controller", "controller", "Service")
239260
os.Exit(1)
@@ -246,6 +267,7 @@ func main() {
246267
ManagementURL: managementURL,
247268
AllowAutomaticPolicyCreation: allowAutomaticPolicyCreation,
248269
ClusterName: clusterName,
270+
DefaultLabels: defaultLabelsMap,
249271
}).SetupWithManager(mgr); err != nil {
250272
setupLog.Error(err, "unable to create controller", "controller", "NBResource")
251273
os.Exit(1)

helm/kubernetes-operator/templates/_helpers.tpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ helm.sh/chart: {{ include "kubernetes-operator.chart" . }}
4040
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
4141
{{- end }}
4242
app.kubernetes.io/managed-by: {{ .Release.Service }}
43+
{{- if .Values.general.labels }}
44+
{{- range $key, $val := .Values.general.labels }}
45+
{{ $key }}: "{{ $val }}"
46+
{{- end }}
47+
{{- end }}
4348
{{- end }}
4449

4550
{{/*

helm/kubernetes-operator/templates/deployment.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ spec:
6666
{{- if .Values.routingClientImage }}
6767
- --netbird-client-image={{.Values.routingClientImage}}
6868
{{- end }}
69+
{{- if .Values.general.labels }}
70+
{{- $list := list }}
71+
{{- range $k, $v := .Values.general.labels }}
72+
{{- $list = append $list (printf "%s=%s" $k $v) }}
73+
{{- end }}
74+
- --default-labels="{{ join ", " $list }}"
75+
{{- end }}
6976
ports:
7077
- name: webhook-server
7178
containerPort: {{ .Values.webhook.service.port }}

helm/kubernetes-operator/values.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,9 @@ netbirdAPI: {}
198198
# key: "NB_API_KEY"
199199

200200
#routingClientImage: "netbirdio/netbird:latest"
201+
202+
general:
203+
# General labels, applied to all created K8s resources
204+
labels: {}
205+
# acme_com_managed_by: platform-engineering
206+
# acme_com_owned_by: release-engineering

internal/controller/nbresource_controller.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type NBResourceReconciler struct {
3131
ManagementURL string
3232
AllowAutomaticPolicyCreation bool
3333
ClusterName string
34+
DefaultLabels map[string]string
3435
netbird *netbird.Client
3536
}
3637

@@ -128,6 +129,7 @@ func (r *NBResourceReconciler) handlePolicyCreate(ctx context.Context, nbResourc
128129
Name: generatedName,
129130
Annotations: map[string]string{"netbird.io/generated-by": req.NamespacedName.String()},
130131
Finalizers: []string{"netbird.io/cleanup"},
132+
Labels: r.DefaultLabels,
131133
},
132134
Spec: netbirdiov1.NBPolicySpec{
133135
Name: name,
@@ -148,6 +150,7 @@ func (r *NBResourceReconciler) handlePolicyCreate(ctx context.Context, nbResourc
148150
if nbPolicy.Annotations == nil {
149151
nbPolicy.Annotations = make(map[string]string)
150152
}
153+
nbPolicy.Labels = r.DefaultLabels
151154
nbPolicy.Annotations["netbird.io/generated-by"] = req.NamespacedName.String()
152155
nbPolicy.Spec = netbirdiov1.NBPolicySpec{
153156
Name: name,
@@ -505,6 +508,7 @@ func (r *NBResourceReconciler) handleGroups(ctx context.Context, req ctrl.Reques
505508
},
506509
},
507510
Finalizers: []string{"netbird.io/group-cleanup", "netbird.io/resource-cleanup"},
511+
Labels: r.DefaultLabels,
508512
},
509513
Spec: netbirdiov1.NBGroupSpec{
510514
Name: groupName,

internal/controller/nbresource_controller_test.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ var _ = Describe("NBResource Controller", func() {
4646
server = httptest.NewServer(mux)
4747
netbirdClient = netbird.New(server.URL, "ABC")
4848
controllerReconciler = &NBResourceReconciler{
49-
Client: k8sClient,
50-
Scheme: k8sClient.Scheme(),
51-
netbird: netbirdClient,
52-
ClusterName: "kubernetes",
49+
Client: k8sClient,
50+
Scheme: k8sClient.Scheme(),
51+
netbird: netbirdClient,
52+
ClusterName: "kubernetes",
53+
DefaultLabels: map[string]string{"dog": "bark"},
5354
}
5455

5556
By("creating the custom resource for the Kind NBResource")
@@ -125,6 +126,7 @@ var _ = Describe("NBResource Controller", func() {
125126
Expect(err).NotTo(HaveOccurred())
126127
nbGroup := &netbirdiov1.NBGroup{}
127128
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: "default", Name: "meow"}, nbGroup)).To(Succeed())
129+
Expect(nbGroup.Labels).To(HaveKeyWithValue("dog", "bark"))
128130
nbGroup.Status.GroupID = util.Ptr("test")
129131
Expect(k8sClient.Status().Update(ctx, nbGroup)).To(Succeed())
130132
})
@@ -453,6 +455,7 @@ var _ = Describe("NBResource Controller", func() {
453455
nbPolicy := &netbirdiov1.NBPolicy{}
454456
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: nbresource.Status.PolicyNameMapping[policyGenName]}, nbPolicy)).To(Succeed())
455457
Expect(nbPolicy.Status.ManagedServiceList).To(ContainElement("default/test-resource"))
458+
Expect(nbPolicy.Labels).To(HaveKeyWithValue("dog", "bark"))
456459
})
457460

458461
When("Source groups is not defined", func() {

internal/controller/nbroutingpeer_controller.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type NBRoutingPeerReconciler struct {
3131
APIKey string
3232
ManagementURL string
3333
NamespacedNetworks bool
34+
DefaultLabels map[string]string
3435
netbird *netbird.Client
3536
}
3637

@@ -122,6 +123,13 @@ func (r *NBRoutingPeerReconciler) handleDeployment(ctx context.Context, req ctrl
122123
return err
123124
}
124125

126+
labels := r.DefaultLabels
127+
for k, v := range nbrp.Spec.Labels {
128+
labels[k] = v
129+
}
130+
podLabels := labels
131+
podLabels["app.kubernetes.io/name"] = "netbird-router"
132+
125133
// Create deployment
126134
if errors.IsNotFound(err) {
127135
var replicas int32 = 3
@@ -141,7 +149,7 @@ func (r *NBRoutingPeerReconciler) handleDeployment(ctx context.Context, req ctrl
141149
BlockOwnerDeletion: util.Ptr(true),
142150
},
143151
},
144-
Labels: nbrp.Spec.Labels,
152+
Labels: labels,
145153
Annotations: nbrp.Spec.Annotations,
146154
},
147155
Spec: appsv1.DeploymentSpec{
@@ -153,9 +161,7 @@ func (r *NBRoutingPeerReconciler) handleDeployment(ctx context.Context, req ctrl
153161
},
154162
Template: corev1.PodTemplateSpec{
155163
ObjectMeta: v1.ObjectMeta{
156-
Labels: map[string]string{
157-
"app.kubernetes.io/name": "netbird-router",
158-
},
164+
Labels: podLabels,
159165
},
160166
Spec: corev1.PodSpec{
161167
NodeSelector: nbrp.Spec.NodeSelector,
@@ -217,7 +223,7 @@ func (r *NBRoutingPeerReconciler) handleDeployment(ctx context.Context, req ctrl
217223
BlockOwnerDeletion: util.Ptr(true),
218224
},
219225
}
220-
updatedDeployment.ObjectMeta.Labels = nbrp.Spec.Labels
226+
updatedDeployment.ObjectMeta.Labels = labels
221227
for k, v := range nbrp.Spec.Annotations {
222228
updatedDeployment.ObjectMeta.Annotations[k] = nbrp.Spec.Annotations[v]
223229
}
@@ -233,6 +239,7 @@ func (r *NBRoutingPeerReconciler) handleDeployment(ctx context.Context, req ctrl
233239
}
234240
updatedDeployment.Spec.Template.Spec.Tolerations = nbrp.Spec.Tolerations
235241
updatedDeployment.Spec.Template.Spec.NodeSelector = nbrp.Spec.NodeSelector
242+
updatedDeployment.Spec.Template.ObjectMeta.Labels = podLabels
236243
updatedDeployment.Spec.Template.Spec.Volumes = nbrp.Spec.Volumes
237244
updatedDeployment.Spec.Template.ObjectMeta.Labels = map[string]string{
238245
"app.kubernetes.io/name": "netbird-router",
@@ -378,6 +385,7 @@ func (r *NBRoutingPeerReconciler) handleSetupKey(ctx context.Context, req ctrl.R
378385
BlockOwnerDeletion: util.Ptr(true),
379386
},
380387
},
388+
Labels: r.DefaultLabels,
381389
},
382390
StringData: map[string]string{
383391
"setupKey": setupKey.Key,
@@ -402,7 +410,7 @@ func (r *NBRoutingPeerReconciler) handleSetupKey(ctx context.Context, req ctrl.R
402410
return &ctrl.Result{}, err
403411
}
404412

405-
if (err != nil && strings.Contains(err.Error(), "not found")) || setupKey.Revoked {
413+
if err != nil || setupKey.Revoked {
406414
if setupKey != nil && setupKey.Revoked {
407415
err = r.netbird.SetupKeys.Delete(ctx, *nbrp.Status.SetupKeyID)
408416

@@ -480,6 +488,7 @@ func (r *NBRoutingPeerReconciler) handleGroup(ctx context.Context, req ctrl.Requ
480488
},
481489
},
482490
Finalizers: []string{"netbird.io/group-cleanup", "netbird.io/routing-peer-cleanup"},
491+
Labels: r.DefaultLabels,
483492
},
484493
Spec: netbirdiov1.NBGroupSpec{
485494
Name: networkName,

internal/controller/nbroutingpeer_controller_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ var _ = Describe("NBRoutingPeer Controller", func() {
5252
netbird: netbirdClient,
5353
ClientImage: "netbirdio/netbird:latest",
5454
ClusterName: "kubernetes",
55+
DefaultLabels: make(map[string]string),
5556
NamespacedNetworks: false,
5657
}
5758

@@ -436,6 +437,7 @@ var _ = Describe("NBRoutingPeer Controller", func() {
436437
Expect(k8sClient.Create(ctx, secret)).To(Succeed())
437438
})
438439
It("should create group and requeue to get its ID", func() {
440+
controllerReconciler.DefaultLabels = map[string]string{"dog": "bark"}
439441
res, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
440442
NamespacedName: typeNamespacedName,
441443
})
@@ -445,6 +447,7 @@ var _ = Describe("NBRoutingPeer Controller", func() {
445447
group := &netbirdiov1.NBGroup{}
446448
Expect(k8sClient.Get(ctx, typeNamespacedName, group)).To(Succeed())
447449
Expect(group.Spec.Name).To(Equal(controllerReconciler.ClusterName))
450+
Expect(group.Labels).To(HaveKeyWithValue("dog", "bark"))
448451

449452
group.Status.GroupID = util.Ptr("test")
450453
Expect(k8sClient.Status().Update(ctx, group)).To(Succeed())
@@ -846,6 +849,25 @@ var _ = Describe("NBRoutingPeer Controller", func() {
846849
Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(Equal(controllerReconciler.ClientImage))
847850
})
848851
})
852+
853+
When("Default labels exist", func() {
854+
It("should add labels to Deployment and Pod metadata", func() {
855+
controllerReconciler.DefaultLabels = map[string]string{
856+
"cat": "meow",
857+
"dog": "bark",
858+
}
859+
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
860+
NamespacedName: typeNamespacedName,
861+
})
862+
Expect(err).NotTo(HaveOccurred())
863+
864+
deployment := &appsv1.Deployment{}
865+
Expect(k8sClient.Get(ctx, typeNamespacedName, deployment)).To(Succeed())
866+
Expect(deployment.Labels).To(HaveKeyWithValue("cat", "meow"))
867+
Expect(deployment.Labels).To(HaveKeyWithValue("dog", "bark"))
868+
})
869+
})
870+
849871
When("Deployment is out-of-date", func() {
850872
It("should update deployment", func() {
851873
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{

internal/controller/service_controller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type ServiceReconciler struct {
2727
ClusterDNS string
2828
NamespacedNetworks bool
2929
ControllerNamespace string
30+
DefaultLabels map[string]string
3031
}
3132

3233
const (
@@ -138,6 +139,7 @@ func (r *ServiceReconciler) exposeService(ctx context.Context, req ctrl.Request,
138139
Name: "router",
139140
Namespace: routerNamespace,
140141
Finalizers: []string{"netbird.io/cleanup"},
142+
Labels: r.DefaultLabels,
141143
},
142144
Spec: netbirdiov1.NBRoutingPeerSpec{},
143145
}
@@ -205,6 +207,7 @@ func (r *ServiceReconciler) reconcileNBResource(nbResource *netbirdiov1.NBResour
205207

206208
nbResource.ObjectMeta.Name = req.Name
207209
nbResource.ObjectMeta.Namespace = req.Namespace
210+
nbResource.ObjectMeta.Labels = r.DefaultLabels
208211
nbResource.Finalizers = []string{"netbird.io/cleanup"}
209212
nbResource.Spec.Name = resourceName
210213
nbResource.Spec.NetworkID = *routingPeer.Status.NetworkID

internal/controller/service_controller_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ var _ = Describe("Service Controller", func() {
6767
NamespacedNetworks: false,
6868
ClusterDNS: "svc.cluster.local",
6969
ControllerNamespace: "default",
70+
DefaultLabels: map[string]string{"dog": "bark"},
7071
}
7172
})
7273

@@ -144,6 +145,7 @@ var _ = Describe("Service Controller", func() {
144145
Expect(res.RequeueAfter).NotTo(BeZero())
145146
nbrp := &netbirdiov1.NBRoutingPeer{}
146147
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: typeNamespacedName.Namespace, Name: "router"}, nbrp)).To(Succeed())
148+
Expect(nbrp.Labels).To(HaveKeyWithValue("dog", "bark"))
147149
res, err = controllerReconciler.Reconcile(ctx, reconcile.Request{
148150
NamespacedName: typeNamespacedName,
149151
})
@@ -203,6 +205,7 @@ var _ = Describe("Service Controller", func() {
203205
Expect(nbResource.Spec.PolicyName).To(BeEmpty())
204206
Expect(nbResource.Spec.TCPPorts).To(BeEmpty())
205207
Expect(nbResource.Spec.UDPPorts).To(BeEmpty())
208+
Expect(nbResource.Labels).To(HaveKeyWithValue("dog", "bark"))
206209
})
207210
})
208211
When("policy is specified", func() {

0 commit comments

Comments
 (0)