Skip to content

Commit 501f8f9

Browse files
authored
Collects ClusterId for Telemetry Object Collector (#1565)
* feat: add clusterID to telemetry objects
1 parent 9e719b0 commit 501f8f9

File tree

2 files changed

+99
-52
lines changed

2 files changed

+99
-52
lines changed

internal/mode/static/telemetry/collector.go

+19
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
appsv1 "k8s.io/api/apps/v1"
99
v1 "k8s.io/api/core/v1"
10+
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
1011
"k8s.io/apimachinery/pkg/types"
1112
"sigs.k8s.io/controller-runtime/pkg/client"
1213

@@ -49,6 +50,7 @@ type ProjectMetadata struct {
4950
// Note: this type might change once https://github.com/nginxinc/nginx-gateway-fabric/issues/1318 is implemented.
5051
type Data struct {
5152
ProjectMetadata ProjectMetadata
53+
ClusterID string
5254
NodeCount int
5355
NGFResourceCounts NGFResourceCounts
5456
NGFReplicaCount int
@@ -99,6 +101,11 @@ func (c DataCollectorImpl) Collect(ctx context.Context) (Data, error) {
99101
return Data{}, fmt.Errorf("failed to collect NGF replica count: %w", err)
100102
}
101103

104+
var clusterID string
105+
if clusterID, err = collectClusterID(ctx, c.cfg.K8sClientReader); err != nil {
106+
return Data{}, fmt.Errorf("failed to collect clusterID: %w", err)
107+
}
108+
102109
data := Data{
103110
NodeCount: nodeCount,
104111
NGFResourceCounts: graphResourceCount,
@@ -107,6 +114,7 @@ func (c DataCollectorImpl) Collect(ctx context.Context) (Data, error) {
107114
Version: c.cfg.Version,
108115
},
109116
NGFReplicaCount: ngfReplicaCount,
117+
ClusterID: clusterID,
110118
}
111119

112120
return data, nil
@@ -193,3 +201,14 @@ func collectNGFReplicaCount(ctx context.Context, k8sClient client.Reader, podNSN
193201

194202
return int(*replicaSet.Spec.Replicas), nil
195203
}
204+
205+
func collectClusterID(ctx context.Context, k8sClient client.Reader) (string, error) {
206+
key := types.NamespacedName{
207+
Name: meta.NamespaceSystem,
208+
}
209+
var kubeNamespace v1.Namespace
210+
if err := k8sClient.Get(ctx, key, &kubeNamespace); err != nil {
211+
return "", fmt.Errorf("failed to get kube-system namespace: %w", err)
212+
}
213+
return string(kubeNamespace.GetUID()), nil
214+
}

internal/mode/static/telemetry/collector_test.go

+80-52
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
. "github.com/onsi/gomega"
1111
appsv1 "k8s.io/api/apps/v1"
1212
v1 "k8s.io/api/core/v1"
13+
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
1314
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1415
"k8s.io/apimachinery/pkg/types"
1516
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -41,12 +42,14 @@ func createListCallsFunc(nodes []v1.Node) func(
4142
}
4243
}
4344

44-
func createGetCallsFunc(objects ...client.Object) func(
45+
type getCallsFunc = func(
4546
context.Context,
4647
types.NamespacedName,
4748
client.Object,
4849
...client.GetOption,
49-
) error {
50+
) error
51+
52+
func createGetCallsFunc(objects ...client.Object) getCallsFunc {
5053
return func(_ context.Context, _ types.NamespacedName, object client.Object, option ...client.GetOption) error {
5154
Expect(option).To(BeEmpty())
5255

@@ -57,7 +60,6 @@ func createGetCallsFunc(objects ...client.Object) func(
5760
}
5861
}
5962

60-
Fail(fmt.Sprintf("unknown type: %T", object))
6163
return nil
6264
}
6365
}
@@ -74,6 +76,9 @@ var _ = Describe("Collector", Ordered, func() {
7476
podNSName types.NamespacedName
7577
ngfPod *v1.Pod
7678
ngfReplicaSet *appsv1.ReplicaSet
79+
kubeNamespace *v1.Namespace
80+
81+
baseGetCalls getCallsFunc
7782
)
7883

7984
BeforeAll(func() {
@@ -103,6 +108,13 @@ var _ = Describe("Collector", Ordered, func() {
103108
Namespace: "nginx-gateway",
104109
Name: "ngf-pod",
105110
}
111+
112+
kubeNamespace = &v1.Namespace{
113+
ObjectMeta: metav1.ObjectMeta{
114+
Name: meta.NamespaceSystem,
115+
UID: "test-uid",
116+
},
117+
}
106118
})
107119

108120
BeforeEach(func() {
@@ -111,6 +123,7 @@ var _ = Describe("Collector", Ordered, func() {
111123
NodeCount: 0,
112124
NGFResourceCounts: telemetry.NGFResourceCounts{},
113125
NGFReplicaCount: 1,
126+
ClusterID: string(kubeNamespace.GetUID()),
114127
}
115128

116129
k8sClientReader = &eventsfakes.FakeReader{}
@@ -127,21 +140,43 @@ var _ = Describe("Collector", Ordered, func() {
127140
Version: version,
128141
PodNSName: podNSName,
129142
})
130-
k8sClientReader.GetCalls(createGetCallsFunc(ngfPod, ngfReplicaSet))
143+
144+
baseGetCalls = createGetCallsFunc(ngfPod, ngfReplicaSet, kubeNamespace)
145+
k8sClientReader.GetCalls(baseGetCalls)
131146
})
132147

148+
mergeGetCallsWithBase := func(f getCallsFunc) getCallsFunc {
149+
return func(
150+
ctx context.Context,
151+
nsName types.NamespacedName,
152+
object client.Object,
153+
option ...client.GetOption,
154+
) error {
155+
err := baseGetCalls(ctx, nsName, object, option...)
156+
Expect(err).ToNot(HaveOccurred())
157+
158+
return f(ctx, nsName, object, option...)
159+
}
160+
}
161+
133162
Describe("Normal case", func() {
134163
When("collecting telemetry data", func() {
135164
It("collects all fields", func() {
136165
nodes := []v1.Node{
137166
{
138-
ObjectMeta: metav1.ObjectMeta{Name: "node1"},
167+
ObjectMeta: metav1.ObjectMeta{
168+
Name: "node1",
169+
},
139170
},
140171
{
141-
ObjectMeta: metav1.ObjectMeta{Name: "node2"},
172+
ObjectMeta: metav1.ObjectMeta{
173+
Name: "node2",
174+
},
142175
},
143176
{
144-
ObjectMeta: metav1.ObjectMeta{Name: "node3"},
177+
ObjectMeta: metav1.ObjectMeta{
178+
Name: "node3",
179+
},
145180
},
146181
}
147182

@@ -239,6 +274,27 @@ var _ = Describe("Collector", Ordered, func() {
239274
})
240275
})
241276

277+
Describe("clusterID collector", func() {
278+
When("collecting clusterID", func() {
279+
When("it encounters an error while collecting data", func() {
280+
It("should error if the kubernetes client errored when getting the namespace", func() {
281+
expectedError := errors.New("there was an error getting clusterID")
282+
k8sClientReader.GetCalls(mergeGetCallsWithBase(
283+
func(_ context.Context, _ types.NamespacedName, object client.Object, _ ...client.GetOption) error {
284+
switch object.(type) {
285+
case *v1.Namespace:
286+
return expectedError
287+
}
288+
return nil
289+
}))
290+
291+
_, err := dataCollector.Collect(ctx)
292+
Expect(err).To(MatchError(expectedError))
293+
})
294+
})
295+
})
296+
})
297+
242298
Describe("node count collector", func() {
243299
When("collecting node count data", func() {
244300
It("collects correct data for no nodes", func() {
@@ -425,41 +481,38 @@ var _ = Describe("Collector", Ordered, func() {
425481
When("it encounters an error while collecting data", func() {
426482
It("should error if the kubernetes client errored when getting the Pod", func() {
427483
expectedErr := errors.New("there was an error getting the Pod")
428-
k8sClientReader.GetCalls(
429-
func(_ context.Context, _ client.ObjectKey, object client.Object, option ...client.GetOption) error {
430-
Expect(option).To(BeEmpty())
431-
432-
switch typedObj := object.(type) {
484+
k8sClientReader.GetCalls(mergeGetCallsWithBase(
485+
func(_ context.Context, _ client.ObjectKey, object client.Object, _ ...client.GetOption) error {
486+
switch object.(type) {
433487
case *v1.Pod:
434488
return expectedErr
435-
default:
436-
Fail(fmt.Sprintf("unknown type: %T", typedObj))
437489
}
438490
return nil
439-
})
491+
},
492+
))
440493

441494
_, err := dataCollector.Collect(ctx)
442495
Expect(err).To(MatchError(expectedErr))
443496
})
444497

445498
It("should error if the Pod's owner reference is nil", func() {
446499
expectedErr := errors.New("expected one owner reference of the NGF Pod, got 0")
447-
k8sClientReader.GetCalls(createGetCallsFunc(
500+
k8sClientReader.GetCalls(mergeGetCallsWithBase(createGetCallsFunc(
448501
&v1.Pod{
449502
ObjectMeta: metav1.ObjectMeta{
450503
Name: "pod1",
451504
OwnerReferences: nil,
452505
},
453506
},
454-
))
507+
)))
455508

456509
_, err := dataCollector.Collect(ctx)
457510
Expect(err).To(MatchError(expectedErr))
458511
})
459512

460513
It("should error if the Pod has multiple owner references", func() {
461514
expectedErr := errors.New("expected one owner reference of the NGF Pod, got 2")
462-
k8sClientReader.GetCalls(createGetCallsFunc(
515+
k8sClientReader.GetCalls(mergeGetCallsWithBase(createGetCallsFunc(
463516
&v1.Pod{
464517
ObjectMeta: metav1.ObjectMeta{
465518
Name: "pod1",
@@ -475,15 +528,15 @@ var _ = Describe("Collector", Ordered, func() {
475528
},
476529
},
477530
},
478-
))
531+
)))
479532

480533
_, err := dataCollector.Collect(ctx)
481534
Expect(err).To(MatchError(expectedErr))
482535
})
483536

484537
It("should error if the Pod's owner reference is not a ReplicaSet", func() {
485538
expectedErr := errors.New("expected pod owner reference to be ReplicaSet, got Deployment")
486-
k8sClientReader.GetCalls(createGetCallsFunc(
539+
k8sClientReader.GetCalls(mergeGetCallsWithBase(createGetCallsFunc(
487540
&v1.Pod{
488541
ObjectMeta: metav1.ObjectMeta{
489542
Name: "pod1",
@@ -495,61 +548,36 @@ var _ = Describe("Collector", Ordered, func() {
495548
},
496549
},
497550
},
498-
))
551+
)))
499552

500553
_, err := dataCollector.Collect(ctx)
501554
Expect(err).To(MatchError(expectedErr))
502555
})
503556

504557
It("should error if the replica set's replicas is nil", func() {
505558
expectedErr := errors.New("replica set replicas was nil")
506-
k8sClientReader.GetCalls(createGetCallsFunc(
507-
&v1.Pod{
508-
ObjectMeta: metav1.ObjectMeta{
509-
Name: "pod1",
510-
OwnerReferences: []metav1.OwnerReference{
511-
{
512-
Kind: "ReplicaSet",
513-
Name: "replicaset1",
514-
},
515-
},
516-
},
517-
},
559+
k8sClientReader.GetCalls(mergeGetCallsWithBase(createGetCallsFunc(
518560
&appsv1.ReplicaSet{
519561
Spec: appsv1.ReplicaSetSpec{
520562
Replicas: nil,
521563
},
522564
},
523-
))
565+
)))
524566

525567
_, err := dataCollector.Collect(ctx)
526568
Expect(err).To(MatchError(expectedErr))
527569
})
528570

529571
It("should error if the kubernetes client errored when getting the ReplicaSet", func() {
530572
expectedErr := errors.New("there was an error getting the ReplicaSet")
531-
k8sClientReader.GetCalls(
532-
func(_ context.Context, _ client.ObjectKey, object client.Object, option ...client.GetOption) error {
533-
Expect(option).To(BeEmpty())
534-
535-
switch typedObj := object.(type) {
536-
case *v1.Pod:
537-
typedObj.ObjectMeta = metav1.ObjectMeta{
538-
Name: "pod1",
539-
OwnerReferences: []metav1.OwnerReference{
540-
{
541-
Kind: "ReplicaSet",
542-
Name: "replicaset1",
543-
},
544-
},
545-
}
573+
k8sClientReader.GetCalls(mergeGetCallsWithBase(
574+
func(_ context.Context, _ client.ObjectKey, object client.Object, _ ...client.GetOption) error {
575+
switch object.(type) {
546576
case *appsv1.ReplicaSet:
547577
return expectedErr
548-
default:
549-
Fail(fmt.Sprintf("unknown type: %T", typedObj))
550578
}
551579
return nil
552-
})
580+
}))
553581

554582
_, err := dataCollector.Collect(ctx)
555583
Expect(err).To(MatchError(expectedErr))

0 commit comments

Comments
 (0)