Skip to content

Commit acdbaff

Browse files
committed
fix: prevent nil pointer dereference and silent error handling in overcommit logic
- Return safe no-op values (1.0, 1.0) when errors occur instead of continuing with zero values or crashing on nil pointer dereference - Remove unused getNamespaceYAML function and YAML roundtrip - Properly handle all error paths in getNamespaceOvercommit and checkOvercommitType to avoid mutating pods with incorrect values - Use direct client.Get for namespace instead of YAML marshal/unmarshal
1 parent 1e57315 commit acdbaff

1 file changed

Lines changed: 22 additions & 48 deletions

File tree

pkg/overcommit/calculate_values_from_labels.go

Lines changed: 22 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,24 @@ package overcommit
77

88
import (
99
"context"
10-
"fmt"
1110

1211
"github.com/InditexTech/k8s-overcommit-operator/internal/metrics"
1312
"github.com/InditexTech/k8s-overcommit-operator/internal/utils"
1413
corev1 "k8s.io/api/core/v1"
1514
"sigs.k8s.io/controller-runtime/pkg/client"
16-
"sigs.k8s.io/yaml"
15+
k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
1716
)
1817

19-
// GetLabelValue gets the value of a label in the pod or in the namespace of the pod
18+
// getNamespaceOvercommit gets the overcommit values from the namespace label or falls back to the default class.
19+
// Returns (1.0, 1.0) as safe no-op values when any error occurs to avoid mutating pods incorrectly.
2020
func getNamespaceOvercommit(ctx context.Context, pod *corev1.Pod, client client.Client, label, ownerName, ownerKind string) (float64, float64) {
2121
// Get the namespace of the pod
2222
namespaceName := pod.ObjectMeta.Namespace
2323
var ns corev1.Namespace
24-
namespace, err := getNamespaceYAML(ctx, namespaceName, client)
24+
err := client.Get(ctx, k8sclient.ObjectKey{Name: namespaceName}, &ns)
2525
if err != nil {
26-
podlog.Error(err, "Error getting the namespace yaml", "namespace", namespaceName)
27-
}
28-
err = yaml.Unmarshal([]byte(namespace), &ns)
29-
if err != nil {
30-
podlog.Error(err, "Error unmarshaling the namespace", "namespace", namespaceName)
26+
podlog.Error(err, "Error getting the namespace", "namespace", namespaceName)
27+
return 1.0, 1.0
3128
}
3229

3330
// Check if the overcommit class label is in the namespace
@@ -36,53 +33,33 @@ func getNamespaceOvercommit(ctx context.Context, pod *corev1.Pod, client client.
3633
overcommitClass, err := utils.GetOvercommitClassSpec(ctx, val, client)
3734
if err != nil {
3835
podlog.Error(err, "Error getting the overcommit class", "overcommitClassLabel", val)
36+
return 1.0, 1.0
3937
}
4038
metrics.K8sOvercommitPodMutated.WithLabelValues(val, ownerKind, ownerName, pod.Namespace).Inc()
4139
return overcommitClass.CpuOvercommit, overcommitClass.MemoryOvercommit
42-
} else {
43-
podlog.Info("Overcommit class not found in the namespace, using the default", "namespace", ns.Name)
44-
defaultClass, error := utils.GetDefaultSpec(client)
45-
if error != nil {
46-
podlog.Error(error, "Error getting the default overcommit class")
47-
}
48-
metrics.K8sOvercommitPodMutated.WithLabelValues("default", ownerKind, ownerName, pod.Namespace).Inc()
49-
return defaultClass.CpuOvercommit, defaultClass.MemoryOvercommit
50-
}
51-
}
52-
53-
// getNamespaceYAML gets the YAML of a namespace using the ServiceAccount token
54-
func getNamespaceYAML(ctx context.Context, namespaceName string, k8sClient client.Client) (string, error) {
55-
// Create a variable to store the Namespace object
56-
var namespace corev1.Namespace
57-
58-
// Get the Namespace object from the API server
59-
err := k8sClient.Get(ctx, client.ObjectKey{
60-
Name: namespaceName,
61-
}, &namespace)
62-
if err != nil {
63-
return "", fmt.Errorf("error getting the namespace: %v", err)
6440
}
6541

66-
// Convert the Namespace object to YAML
67-
nsYAML, err := yaml.Marshal(namespace)
42+
podlog.Info("Overcommit class not found in the namespace, using the default", "namespace", ns.Name)
43+
defaultClass, err := utils.GetDefaultSpec(client)
6844
if err != nil {
69-
return "", fmt.Errorf("error converting the namespace to YAML: %v", err)
45+
podlog.Error(err, "Error getting the default overcommit class")
46+
return 1.0, 1.0
7047
}
71-
72-
return string(nsYAML), nil
48+
metrics.K8sOvercommitPodMutated.WithLabelValues("default", ownerKind, ownerName, pod.Namespace).Inc()
49+
return defaultClass.CpuOvercommit, defaultClass.MemoryOvercommit
7350
}
7451

7552
func checkOvercommitType(ctx context.Context, pod corev1.Pod, client client.Client) (float64, float64) {
76-
var cpuValue float64
77-
var memoryValue float64
7853
ownerName, ownerKind, err := utils.GetPodOwner(ctx, client, &pod)
7954
if err != nil {
8055
podlog.Error(err, "Error getting the pod owner")
56+
// Non-fatal: continue with empty owner info
8157
}
8258

8359
label, err := utils.GetOvercommitLabel(ctx, client)
8460
if err != nil {
8561
podlog.Error(err, "Error getting the overcommit label")
62+
return 1.0, 1.0
8663
}
8764
// Check if the pod has the overcommit class label
8865
value, exists := pod.Labels[label]
@@ -96,17 +73,14 @@ func checkOvercommitType(ctx context.Context, pod corev1.Pod, client client.Clie
9673
overcommitClass, err := utils.GetOvercommitClassSpec(ctx, value, client)
9774
if err != nil {
9875
podlog.Error(err, "Error getting the overcommit class", "overcommitClassLabel", value)
99-
// Overcommit class not found or some error
100-
cpuValue, memoryValue = getNamespaceOvercommit(ctx, &pod, client, label, ownerName, ownerKind)
101-
} else {
102-
cpuValue, memoryValue = overcommitClass.CpuOvercommit, overcommitClass.MemoryOvercommit
76+
// Overcommit class not found or some error, fall back to namespace/default
77+
return getNamespaceOvercommit(ctx, &pod, client, label, ownerName, ownerKind)
10378
}
10479
metrics.K8sOvercommitPodMutated.WithLabelValues(value, ownerKind, ownerName, pod.Namespace).Inc()
105-
} else {
106-
// Overcommit class not found, checking the overcommit labels
107-
podlog.Info("Overcommit class label not found in pod, checking the namespace")
108-
cpuValue, memoryValue = getNamespaceOvercommit(ctx, &pod, client, label, ownerName, ownerKind)
109-
80+
return overcommitClass.CpuOvercommit, overcommitClass.MemoryOvercommit
11081
}
111-
return cpuValue, memoryValue
82+
83+
// Overcommit class not found, checking the namespace
84+
podlog.Info("Overcommit class label not found in pod, checking the namespace")
85+
return getNamespaceOvercommit(ctx, &pod, client, label, ownerName, ownerKind)
11286
}

0 commit comments

Comments
 (0)