3
3
package e2e
4
4
5
5
import (
6
+ "bytes"
6
7
"context"
7
- "fmt"
8
8
"regexp"
9
- "time "
9
+ "strings "
10
10
11
11
. "github.com/onsi/ginkgo"
12
12
. "github.com/onsi/gomega"
13
+ io_prometheus_client "github.com/prometheus/client_model/go"
14
+ "github.com/prometheus/common/expfmt"
13
15
corev1 "k8s.io/api/core/v1"
14
16
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15
17
"k8s.io/apimachinery/pkg/util/net"
16
18
17
19
"github.com/operator-framework/api/pkg/operators/v1alpha1"
18
20
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
19
21
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
20
- "github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
21
22
"github.com/operator-framework/operator-lifecycle-manager/test/e2e/ctx"
22
23
)
23
24
@@ -71,14 +72,19 @@ var _ = Describe("Metrics are generated for OLM managed resources", func() {
71
72
72
73
It ("generates csv_abnormal metric for OLM pod" , func () {
73
74
74
- // Verify metrics have been emitted for packageserver csv
75
75
Expect (getMetricsFromPod (c , getPodWithLabel (c , "app=olm-operator" ), "8081" )).To (And (
76
- ContainSubstring ("csv_abnormal" ),
77
- ContainSubstring (fmt .Sprintf ("name=\" %s\" " , failingCSV .Name )),
78
- ContainSubstring ("phase=\" Failed\" " ),
79
- ContainSubstring ("reason=\" UnsupportedOperatorGroup\" " ),
80
- ContainSubstring ("version=\" 0.0.0\" " ),
81
- ContainSubstring ("csv_succeeded" ),
76
+ ContainElement (LikeMetric (
77
+ WithFamily ("csv_abnormal" ),
78
+ WithLabel ("name" , failingCSV .Name ),
79
+ WithLabel ("phase" , "Failed" ),
80
+ WithLabel ("reason" , "UnsupportedOperatorGroup" ),
81
+ WithLabel ("version" , "0.0.0" ),
82
+ )),
83
+ ContainElement (LikeMetric (
84
+ WithFamily ("csv_succeeded" ),
85
+ WithValue (0 ),
86
+ WithLabel ("name" , failingCSV .Name ),
87
+ )),
82
88
))
83
89
84
90
cleanupCSV ()
@@ -95,8 +101,8 @@ var _ = Describe("Metrics are generated for OLM managed resources", func() {
95
101
It ("deletes its associated CSV metrics" , func () {
96
102
// Verify that when the csv has been deleted, it deletes the corresponding CSV metrics
97
103
Expect (getMetricsFromPod (c , getPodWithLabel (c , "app=olm-operator" ), "8081" )).ToNot (And (
98
- ContainSubstring ( "csv_abnormal{name= \" %s \" " , failingCSV .Name ),
99
- ContainSubstring ( "csv_succeeded{name= \" %s \" " , failingCSV .Name ),
104
+ ContainElement ( LikeMetric ( WithFamily ( "csv_abnormal" ), WithLabel ( "name " , failingCSV .Name )) ),
105
+ ContainElement ( LikeMetric ( WithFamily ( "csv_succeeded" ), WithLabel ( "name " , failingCSV .Name )) ),
100
106
))
101
107
})
102
108
})
@@ -108,68 +114,98 @@ var _ = Describe("Metrics are generated for OLM managed resources", func() {
108
114
subscriptionCleanup cleanupFunc
109
115
subscription * v1alpha1.Subscription
110
116
)
111
- When ("A subscription object is created" , func () {
112
117
118
+ When ("A subscription object is created" , func () {
113
119
BeforeEach (func () {
114
120
subscriptionCleanup , _ = createSubscription (GinkgoT (), crc , testNamespace , "metric-subscription-for-create" , testPackageName , stableChannel , v1alpha1 .ApprovalManual )
115
121
})
116
122
123
+ AfterEach (func () {
124
+ if subscriptionCleanup != nil {
125
+ subscriptionCleanup ()
126
+ }
127
+ })
128
+
117
129
It ("generates subscription_sync_total metric" , func () {
118
130
119
131
// Verify metrics have been emitted for subscription
120
- Eventually (func () string {
132
+ Eventually (func () [] Metric {
121
133
return getMetricsFromPod (c , getPodWithLabel (c , "app=catalog-operator" ), "8081" )
122
- }, time .Minute , 5 * time .Second ).Should (And (
123
- ContainSubstring ("subscription_sync_total" ),
124
- ContainSubstring (fmt .Sprintf ("%s=\" %s\" " , metrics .NAME_LABEL , "metric-subscription-for-create" )),
125
- ContainSubstring (fmt .Sprintf ("%s=\" %s\" " , metrics .CHANNEL_LABEL , stableChannel )),
126
- ContainSubstring (fmt .Sprintf ("%s=\" %s\" " , metrics .PACKAGE_LABEL , testPackageName ))))
134
+ }).Should (ContainElement (LikeMetric (
135
+ WithFamily ("subscription_sync_total" ),
136
+ WithLabel ("name" , "metric-subscription-for-create" ),
137
+ WithLabel ("channel" , stableChannel ),
138
+ WithLabel ("package" , testPackageName ),
139
+ )))
127
140
})
128
- if subscriptionCleanup != nil {
129
- subscriptionCleanup ()
130
- }
131
141
})
132
- When ("A subscription object is updated" , func () {
142
+
143
+ When ("A subscription object is updated after emitting metrics" , func () {
133
144
134
145
BeforeEach (func () {
135
146
subscriptionCleanup , subscription = createSubscription (GinkgoT (), crc , testNamespace , "metric-subscription-for-update" , testPackageName , stableChannel , v1alpha1 .ApprovalManual )
136
- subscription .Spec .Channel = "beta"
137
- updateSubscription (GinkgoT (), crc , subscription )
147
+ Eventually (func () []Metric {
148
+ return getMetricsFromPod (c , getPodWithLabel (c , "app=catalog-operator" ), "8081" )
149
+ }).Should (ContainElement (LikeMetric (WithFamily ("subscription_sync_total" ), WithLabel ("name" , "metric-subscription-for-update" ))))
150
+ Eventually (func () error {
151
+ s , err := crc .OperatorsV1alpha1 ().Subscriptions (subscription .GetNamespace ()).Get (context .TODO (), subscription .GetName (), metav1.GetOptions {})
152
+ if err != nil {
153
+ return err
154
+ }
155
+ s .Spec .Channel = "beta"
156
+ _ , err = crc .OperatorsV1alpha1 ().Subscriptions (s .GetNamespace ()).Update (context .TODO (), s , metav1.UpdateOptions {})
157
+ return err
158
+ }).Should (Succeed ())
138
159
})
139
160
140
- It ("deletes the old Subscription metric and emits the new metric" , func () {
141
- Eventually (func () string {
142
- return getMetricsFromPod (c , getPodWithLabel (c , "app=catalog-operator" ), "8081" )
143
- }, time .Minute , 5 * time .Second ).ShouldNot (And (
144
- ContainSubstring ("subscription_sync_total{name=\" metric-subscription-for-update\" " ),
145
- ContainSubstring (fmt .Sprintf ("%s=\" %s\" " , metrics .CHANNEL_LABEL , stableChannel ))))
161
+ AfterEach (func () {
162
+ if subscriptionCleanup != nil {
163
+ subscriptionCleanup ()
164
+ }
165
+ })
146
166
147
- Eventually (func () string {
167
+ It ("deletes the old Subscription metric and emits the new metric" , func () {
168
+ Eventually (func () []Metric {
148
169
return getMetricsFromPod (c , getPodWithLabel (c , "app=catalog-operator" ), "8081" )
149
- }, time .Minute , 5 * time .Second ).Should (And (
150
- ContainSubstring ("subscription_sync_total" ),
151
- ContainSubstring (fmt .Sprintf ("%s=\" %s\" " , metrics .NAME_LABEL , "metric-subscription-for-update" )),
152
- ContainSubstring (fmt .Sprintf ("%s=\" %s\" " , metrics .CHANNEL_LABEL , "beta" )),
153
- ContainSubstring (fmt .Sprintf ("%s=\" %s\" " , metrics .PACKAGE_LABEL , testPackageName ))))
170
+ }).Should (And (
171
+ Not (ContainElement (LikeMetric (
172
+ WithFamily ("subscription_sync_total" ),
173
+ WithLabel ("name" , "metric-subscription-for-update" ),
174
+ WithLabel ("channel" , stableChannel ),
175
+ ))),
176
+ ContainElement (LikeMetric (
177
+ WithFamily ("subscription_sync_total" ),
178
+ WithLabel ("name" , "metric-subscription-for-update" ),
179
+ WithLabel ("channel" , "beta" ),
180
+ WithLabel ("package" , testPackageName ),
181
+ )),
182
+ ))
154
183
})
155
- if subscriptionCleanup != nil {
156
- subscriptionCleanup ()
157
- }
158
184
})
159
185
160
- When ("A subscription object is deleted" , func () {
186
+ When ("A subscription object is deleted after emitting metrics " , func () {
161
187
162
188
BeforeEach (func () {
163
189
subscriptionCleanup , subscription = createSubscription (GinkgoT (), crc , testNamespace , "metric-subscription-for-delete" , testPackageName , stableChannel , v1alpha1 .ApprovalManual )
190
+ Eventually (func () []Metric {
191
+ return getMetricsFromPod (c , getPodWithLabel (c , "app=catalog-operator" ), "8081" )
192
+ }).Should (ContainElement (LikeMetric (WithFamily ("subscription_sync_total" ), WithLabel ("name" , "metric-subscription-for-delete" ))))
193
+ if subscriptionCleanup != nil {
194
+ subscriptionCleanup ()
195
+ subscriptionCleanup = nil
196
+ }
197
+ })
198
+
199
+ AfterEach (func () {
164
200
if subscriptionCleanup != nil {
165
201
subscriptionCleanup ()
166
202
}
167
203
})
168
204
169
205
It ("deletes the Subscription metric" , func () {
170
- Eventually (func () string {
206
+ Eventually (func () [] Metric {
171
207
return getMetricsFromPod (c , getPodWithLabel (c , "app=catalog-operator" ), "8081" )
172
- }, time . Minute , 5 * time . Second ).ShouldNot (ContainSubstring ( "subscription_sync_total{ name= \" metric-subscription-for-update \" " ))
208
+ }).ShouldNot (ContainElement ( LikeMetric ( WithFamily ( "subscription_sync_total" ), WithLabel ( " name" , " metric-subscription-for-delete" )) ))
173
209
})
174
210
})
175
211
})
@@ -178,7 +214,7 @@ var _ = Describe("Metrics are generated for OLM managed resources", func() {
178
214
func getPodWithLabel (client operatorclient.ClientInterface , label string ) * corev1.Pod {
179
215
listOptions := metav1.ListOptions {LabelSelector : label }
180
216
var podList * corev1.PodList
181
- Eventually ( func () (err error ) {
217
+ EventuallyWithOffset ( 1 , func () (err error ) {
182
218
podList , err = client .KubernetesInterface ().CoreV1 ().Pods (operatorNamespace ).List (context .TODO (), listOptions )
183
219
return
184
220
}).Should (Succeed (), "Failed to list OLM pods" )
@@ -187,8 +223,8 @@ func getPodWithLabel(client operatorclient.ClientInterface, label string) *corev
187
223
return & podList .Items [0 ]
188
224
}
189
225
190
- func getMetricsFromPod (client operatorclient.ClientInterface , pod * corev1.Pod , port string ) string {
191
- By ( fmt . Sprintf ("querying pod %s/%s" , pod .GetNamespace (), pod .GetName () ))
226
+ func getMetricsFromPod (client operatorclient.ClientInterface , pod * corev1.Pod , port string ) [] Metric {
227
+ ctx . Ctx (). Logf ("querying pod %s/%s\n " , pod .GetNamespace (), pod .GetName ())
192
228
193
229
// assuming -tls-cert and -tls-key aren't used anywhere else as a parameter value
194
230
var foundCert , foundKey bool
@@ -210,17 +246,61 @@ func getMetricsFromPod(client operatorclient.ClientInterface, pod *corev1.Pod, p
210
246
}
211
247
ctx .Ctx ().Logf ("Retrieving metrics using scheme %v\n " , scheme )
212
248
213
- var raw [] byte
214
- Eventually ( func () ( err error ) {
215
- raw , err = client .KubernetesInterface ().CoreV1 ().RESTClient ().Get ().
249
+ mfs := make ( map [ string ] * io_prometheus_client. MetricFamily )
250
+ EventuallyWithOffset ( 1 , func () error {
251
+ raw , err : = client .KubernetesInterface ().CoreV1 ().RESTClient ().Get ().
216
252
Namespace (pod .GetNamespace ()).
217
253
Resource ("pods" ).
218
254
SubResource ("proxy" ).
219
255
Name (net .JoinSchemeNamePort (scheme , pod .GetName (), port )).
220
256
Suffix ("metrics" ).
221
257
Do (context .Background ()).Raw ()
222
- return
258
+ if err != nil {
259
+ return err
260
+ }
261
+ var p expfmt.TextParser
262
+ mfs , err = p .TextToMetricFamilies (bytes .NewReader (raw ))
263
+ if err != nil {
264
+ return err
265
+ }
266
+ return nil
223
267
}).Should (Succeed ())
224
268
225
- return string (raw )
269
+ var metrics []Metric
270
+ for family , mf := range mfs {
271
+ var ignore bool
272
+ for _ , ignoredPrefix := range []string {"go_" , "process_" , "promhttp_" } {
273
+ ignore = ignore || strings .HasPrefix (family , ignoredPrefix )
274
+ }
275
+ if ignore {
276
+ // Metrics with these prefixes shouldn't be
277
+ // relevant to these tests, so they can be
278
+ // stripped out to make test failures easier
279
+ // to understand.
280
+ continue
281
+ }
282
+
283
+ for _ , metric := range mf .Metric {
284
+ m := Metric {
285
+ Family : family ,
286
+ }
287
+ if len (metric .GetLabel ()) > 0 {
288
+ m .Labels = make (map [string ][]string )
289
+ }
290
+ for _ , pair := range metric .GetLabel () {
291
+ m .Labels [pair .GetName ()] = append (m .Labels [pair .GetName ()], pair .GetValue ())
292
+ }
293
+ if u := metric .GetUntyped (); u != nil {
294
+ m .Value = u .GetValue ()
295
+ }
296
+ if g := metric .GetGauge (); g != nil {
297
+ m .Value = g .GetValue ()
298
+ }
299
+ if c := metric .GetCounter (); c != nil {
300
+ m .Value = c .GetValue ()
301
+ }
302
+ metrics = append (metrics , m )
303
+ }
304
+ }
305
+ return metrics
226
306
}
0 commit comments