Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add deploymentID to telemetry object collector #1597

Merged
merged 16 commits into from
Feb 22, 2024
Merged
53 changes: 45 additions & 8 deletions internal/mode/static/telemetry/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ type ProjectMetadata struct {
type Data struct {
ProjectMetadata ProjectMetadata
ClusterID string
ImageSource string
Arch string
DeploymentID string
ImageSource string
NGFResourceCounts NGFResourceCounts
NodeCount int
NGFReplicaCount int
Expand Down Expand Up @@ -101,11 +102,21 @@ func (c DataCollectorImpl) Collect(ctx context.Context) (Data, error) {
return Data{}, fmt.Errorf("failed to collect NGF resource counts: %w", err)
}

ngfReplicaCount, err := collectNGFReplicaCount(ctx, c.cfg.K8sClientReader, c.cfg.PodNSName)
replicaSet, err := getPodReplicaSet(ctx, c.cfg.K8sClientReader, c.cfg.PodNSName)
if err != nil {
return Data{}, fmt.Errorf("failed to get replica set for pod %s: %w", c.cfg.PodNSName, err)
}

replicaCount, err := getReplicas(replicaSet)
if err != nil {
return Data{}, fmt.Errorf("failed to collect NGF replica count: %w", err)
}

deploymentID, err := getDeploymentID(replicaSet)
if err != nil {
return Data{}, fmt.Errorf("failed to get NGF deploymentID: %w", err)
}

var clusterID string
if clusterID, err = CollectClusterID(ctx, c.cfg.K8sClientReader); err != nil {
return Data{}, fmt.Errorf("failed to collect clusterID: %w", err)
Expand All @@ -118,10 +129,11 @@ func (c DataCollectorImpl) Collect(ctx context.Context) (Data, error) {
Name: "NGF",
Version: c.cfg.Version,
},
NGFReplicaCount: ngfReplicaCount,
NGFReplicaCount: replicaCount,
ClusterID: clusterID,
ImageSource: c.cfg.ImageSource,
Arch: runtime.GOARCH,
DeploymentID: deploymentID,
}

return data, nil
Expand Down Expand Up @@ -175,23 +187,27 @@ func collectGraphResourceCount(
return ngfResourceCounts, nil
}

func collectNGFReplicaCount(ctx context.Context, k8sClient client.Reader, podNSName types.NamespacedName) (int, error) {
func getPodReplicaSet(
ctx context.Context,
k8sClient client.Reader,
podNSName types.NamespacedName,
) (*appsv1.ReplicaSet, error) {
var pod v1.Pod
if err := k8sClient.Get(
ctx,
types.NamespacedName{Namespace: podNSName.Namespace, Name: podNSName.Name},
&pod,
); err != nil {
return 0, fmt.Errorf("failed to get NGF Pod: %w", err)
return nil, fmt.Errorf("failed to get NGF Pod: %w", err)
}

podOwnerRefs := pod.GetOwnerReferences()
if len(podOwnerRefs) != 1 {
return 0, fmt.Errorf("expected one owner reference of the NGF Pod, got %d", len(podOwnerRefs))
return nil, fmt.Errorf("expected one owner reference of the NGF Pod, got %d", len(podOwnerRefs))
}

if podOwnerRefs[0].Kind != "ReplicaSet" {
return 0, fmt.Errorf("expected pod owner reference to be ReplicaSet, got %s", podOwnerRefs[0].Kind)
return nil, fmt.Errorf("expected pod owner reference to be ReplicaSet, got %s", podOwnerRefs[0].Kind)
}

var replicaSet appsv1.ReplicaSet
Expand All @@ -200,16 +216,37 @@ func collectNGFReplicaCount(ctx context.Context, k8sClient client.Reader, podNSN
types.NamespacedName{Namespace: podNSName.Namespace, Name: podOwnerRefs[0].Name},
&replicaSet,
); err != nil {
return 0, fmt.Errorf("failed to get NGF Pod's ReplicaSet: %w", err)
return nil, fmt.Errorf("failed to get NGF Pod's ReplicaSet: %w", err)
}

return &replicaSet, nil
}

func getReplicas(replicaSet *appsv1.ReplicaSet) (int, error) {
if replicaSet.Spec.Replicas == nil {
return 0, errors.New("replica set replicas was nil")
}

return int(*replicaSet.Spec.Replicas), nil
}

func getDeploymentID(replicaSet *appsv1.ReplicaSet) (string, error) {
replicaOwnerRefs := replicaSet.GetOwnerReferences()
if len(replicaOwnerRefs) != 1 {
return "", fmt.Errorf("expected one owner reference of the NGF ReplicaSet, got %d", len(replicaOwnerRefs))
}

if replicaOwnerRefs[0].Kind != "Deployment" {
return "", fmt.Errorf("expected replicaSet owner reference to be Deployment, got %s", replicaOwnerRefs[0].Kind)
}

if replicaOwnerRefs[0].UID == "" {
return "", fmt.Errorf("expected replicaSet to have a UID")
salonichf5 marked this conversation as resolved.
Show resolved Hide resolved
}

return string(replicaOwnerRefs[0].UID), nil
}

// CollectClusterID gets the UID of the kube-system namespace.
func CollectClusterID(ctx context.Context, k8sClient client.Reader) (string, error) {
key := types.NamespacedName{
Expand Down
78 changes: 78 additions & 0 deletions internal/mode/static/telemetry/collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ var _ = Describe("Collector", Ordered, func() {
Spec: appsv1.ReplicaSetSpec{
Replicas: &replicas,
},
ObjectMeta: metav1.ObjectMeta{
Name: "replica",
OwnerReferences: []metav1.OwnerReference{
{
Kind: "Deployment",
Name: "Deployment1",
UID: "test-uid-replicaSet",
},
},
},
}

podNSName = types.NamespacedName{
Expand All @@ -126,6 +136,7 @@ var _ = Describe("Collector", Ordered, func() {
ClusterID: string(kubeNamespace.GetUID()),
ImageSource: "local",
Arch: runtime.GOARCH,
DeploymentID: string(ngfReplicaSet.ObjectMeta.OwnerReferences[0].UID),
}

k8sClientReader = &eventsfakes.FakeReader{}
Expand Down Expand Up @@ -588,4 +599,71 @@ var _ = Describe("Collector", Ordered, func() {
})
})
})

Describe("DeploymentID collector", func() {
When("collecting deploymentID", func() {
When("it encounters an error while collecting data", func() {
It("should error if the replicaSet's owner reference is nil", func() {
replicas := int32(1)
k8sClientReader.GetCalls(mergeGetCallsWithBase(createGetCallsFunc(
&appsv1.ReplicaSet{
Spec: appsv1.ReplicaSetSpec{
Replicas: &replicas,
},
},
)))

expectedErr := errors.New("expected one owner reference of the NGF ReplicaSet, got 0")
_, err := dataCollector.Collect(ctx)
Expect(err).To(MatchError(expectedErr))
})

It("should error if the replicaSet's owner reference kind is not deployment", func() {
replicas := int32(1)
k8sClientReader.GetCalls(mergeGetCallsWithBase(createGetCallsFunc(
&appsv1.ReplicaSet{
Spec: appsv1.ReplicaSetSpec{
Replicas: &replicas,
},
ObjectMeta: metav1.ObjectMeta{
OwnerReferences: []metav1.OwnerReference{
{
Name: "replica",
Kind: "ReplicaSet",
UID: "replica-uid",
},
},
},
},
)))

expectedErr := errors.New("expected replicaSet owner reference to be Deployment, got ReplicaSet")
_, err := dataCollector.Collect(ctx)
Expect(err).To(MatchError(expectedErr))
})
It("should error if the replicaSet's owner reference has empty UID", func() {
replicas := int32(1)
k8sClientReader.GetCalls(mergeGetCallsWithBase(createGetCallsFunc(
&appsv1.ReplicaSet{
Spec: appsv1.ReplicaSetSpec{
Replicas: &replicas,
},
ObjectMeta: metav1.ObjectMeta{
OwnerReferences: []metav1.OwnerReference{
{
Name: "replica",
Kind: "Deployment",
},
},
},
},
)))

expectedErr := errors.New("expected replicaSet to have a UID")
_, err := dataCollector.Collect(ctx)
Expect(err).To(MatchError(expectedErr))
})
})
})
})
})
Loading