11package metrics
22
33import (
4+ "context"
45 "fmt"
56 "testing"
67 "time"
@@ -11,10 +12,26 @@ import (
1112
1213 "github.com/stretchr/testify/assert"
1314 "github.com/stretchr/testify/require"
15+
16+ "github.com/sirupsen/logrus"
17+ "github.com/stretchr/testify/assert"
18+ "github.com/stretchr/testify/require"
19+
20+ "k8s.io/apimachinery/pkg/runtime"
21+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
22+
23+ "github.com/prometheus/client_golang/prometheus"
24+ "github.com/prometheus/client_golang/prometheus/testutil"
25+
26+ corev1 "k8s.io/api/core/v1"
27+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+ types "k8s.io/apimachinery/pkg/types"
1429)
1530
31+ var fakek8s = fake .NewFakeClient ()
32+
1633func TestCache (t * testing.T ) {
17- m := New (logrus .NewEntry (logrus .New ()), prometheus .NewRegistry ())
34+ m := New (logrus .NewEntry (logrus .New ()), prometheus .NewRegistry (), fakek8s )
1835
1936 // Lets add some Images/Metrics...
2037 for i , typ := range []string {"init" , "container" } {
@@ -25,8 +42,9 @@ func TestCache(t *testing.T) {
2542 // Check and ensure that the metrics are available...
2643 for i , typ := range []string {"init" , "container" } {
2744 version := fmt .Sprintf ("0.1.%d" , i )
28- mt , err := m .containerImageVersion .GetMetricWith (m .buildFullLabels ("namespace" , "pod" , "container" , typ , "url" , version , version ))
29- require .NoError (t , err )
45+ mt , _ := m .containerImageVersion .GetMetricWith (
46+ m .buildFullLabels ("namespace" , "pod" , "container" , typ , "url" , version , version ),
47+ )
3048 count := testutil .ToFloat64 (mt )
3149 assert .Equal (t , count , float64 (1 ), "Expected to get a metric for containerImageVersion" )
3250 }
@@ -46,10 +64,11 @@ func TestCache(t *testing.T) {
4664 // Ensure metrics and values return 0
4765 for i , typ := range []string {"init" , "container" } {
4866 version := fmt .Sprintf ("0.1.%d" , i )
49- mt , err := m .containerImageVersion .GetMetricWith (m .buildFullLabels ("namespace" , "pod" , "container" , typ , "url" , version , version ))
50- require .NoError (t , err )
67+ mt , _ := m .containerImageVersion .GetMetricWith (
68+ m .buildFullLabels ("namespace" , "pod" , "container" , typ , "url" , version , version ),
69+ )
5170 count := testutil .ToFloat64 (mt )
52- assert .Equal (t , count , float64 (0 ), "Expected to get a metric for containerImageVersion" )
71+ assert .Equal (t , count , float64 (0 ), "Expected NOT to get a metric for containerImageVersion" )
5372 }
5473 // And the Last Updated is removed too
5574 for _ , typ := range []string {"init" , "container" } {
@@ -62,7 +81,7 @@ func TestCache(t *testing.T) {
6281
6382// TestErrorsReporting verifies that the error metric increments correctly
6483func TestErrorsReporting (t * testing.T ) {
65- m := New (logrus .NewEntry (logrus .New ()), prometheus .NewRegistry ())
84+ m := New (logrus .NewEntry (logrus .New ()), prometheus .NewRegistry (), fakek8s )
6685
6786 // Reset the metrics before testing
6887 m .containerImageErrors .Reset ()
@@ -81,6 +100,16 @@ func TestErrorsReporting(t *testing.T) {
81100
82101 for i , tc := range testCases {
83102 t .Run (fmt .Sprintf ("Case %d" , i + 1 ), func (t * testing.T ) {
103+ err := fakek8s .DeleteAllOf (context .Background (), & corev1.Pod {})
104+ require .NoError (t , err )
105+
106+ // We need to ensure that the pod Exists!
107+ err = fakek8s .Create (context .Background (), & corev1.Pod {
108+ ObjectMeta : metav1.ObjectMeta {Name : tc .pod , Namespace : tc .namespace },
109+ Spec : corev1.PodSpec {Containers : []corev1.Container {{Name : tc .container , Image : tc .image }}},
110+ })
111+ require .NoError (t , err )
112+
84113 // Report an error
85114 m .ReportError (tc .namespace , tc .pod , tc .container , tc .image )
86115
@@ -99,3 +128,66 @@ func TestErrorsReporting(t *testing.T) {
99128 })
100129 }
101130}
131+
132+ func Test_Metrics_SkipOnDeletedPod (t * testing.T ) {
133+ scheme := runtime .NewScheme ()
134+ _ = corev1 .AddToScheme (scheme )
135+
136+ // Step 1: Create fake client with Pod
137+ pod := & corev1.Pod {
138+ ObjectMeta : metav1.ObjectMeta {
139+ Name : "mypod" ,
140+ Namespace : "default" ,
141+ UID : types .UID ("test-uid" ),
142+ },
143+ }
144+ client := fake .NewClientBuilder ().WithScheme (scheme ).WithObjects (pod ).Build ()
145+
146+ // Step 2: Create Metrics with fake registry
147+ reg := prometheus .NewRegistry ()
148+ log := logrus .NewEntry (logrus .New ())
149+ metrics := New (log , reg , client )
150+
151+ // verify Pod exists!
152+ require .True (t ,
153+ metrics .PodExists (context .Background (), "default" , "mypod" ),
154+ "Pod should exist at this point!" ,
155+ )
156+
157+ // Register some metrics....
158+ metrics .RegisterImageDuration ("default" , "mypod" , "mycontainer" , "nginx:latest" , time .Now ())
159+
160+ // Step 3: Simulate a Delete occuring, Whilst still Reconciling...
161+ _ = client .Delete (context .Background (), pod )
162+ metrics .RemovePod ("default" , "mypod" )
163+
164+ // Step 4: Validate that all metrics have been removed...
165+ metricFamilies , err := reg .Gather ()
166+ assert .NoError (t , err )
167+ for _ , mf := range metricFamilies {
168+ assert .NotContains (t , * mf .Name , "is_latest_version" , "Should not have been found: %+v" , mf )
169+ assert .NotContains (t , * mf .Name , "image_lookup_duration" , "Should not have been found: %+v" , mf )
170+ assert .NotContains (t , * mf .Name , "image_failures_total" , "Should not have been found: %+v" , mf )
171+ }
172+
173+ // Register Error _after_ sync has completed!
174+ metrics .ReportError ("default" , "mypod" , "mycontianer" , "nginx:latest" )
175+
176+ // Step 5: Attempt to register metrics (should not register anything)
177+ require .False (t ,
178+ metrics .PodExists (context .Background (), "default" , "mypod" ),
179+ "Pod should NOT exist at this point!" ,
180+ )
181+
182+ metrics .RegisterImageDuration ("default" , "mypod" , "mycontainer" , "nginx:latest" , time .Now ())
183+ metrics .ReportError ("default" , "mypod" , "mycontianer" , "nginx:latest" )
184+
185+ // Step 6: Gather metrics and assert none were registered
186+ metricFamilies , err = reg .Gather ()
187+ assert .NoError (t , err )
188+ for _ , mf := range metricFamilies {
189+ assert .NotContains (t , * mf .Name , "is_latest_version" , "Should not have been found: %+v" , mf )
190+ assert .NotContains (t , * mf .Name , "image_lookup_duration" , "Should not have been found: %+v" , mf )
191+ assert .NotContains (t , * mf .Name , "image_failures_total" , "Should not have been found: %+v" , mf )
192+ }
193+ }
0 commit comments