Skip to content

Commit ece5805

Browse files
committed
Bug 1822396: Delete subscription metric when an operator is uninstalled
When an operator was subscribed to using a Subscription Object, the subscription_sync_total metric was emitted whenever the Subscription Object was created/updated/deleted. This PR updates that behaviour to emit the metric only when the Subscription object is created/updated, and deletes the time series for that particular subscription when the subscription object is deleted.
1 parent 8ad4341 commit ece5805

File tree

4 files changed

+56
-15
lines changed

4 files changed

+56
-15
lines changed

pkg/controller/operators/catalog/subscription/syncer.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func (s *subscriptionSyncer) Sync(ctx context.Context, event kubestate.ResourceE
5050
return err
5151
}
5252

53-
s.recordMetrics(res)
53+
metrics.EmitSubMetric(res)
5454

5555
logger := s.logger.WithFields(logrus.Fields{
5656
"reconciling": fmt.Sprintf("%T", res),
@@ -70,6 +70,7 @@ func (s *subscriptionSyncer) Sync(ctx context.Context, event kubestate.ResourceE
7070
initial = initial.Update()
7171
case kubestate.ResourceDeleted:
7272
initial = initial.Delete()
73+
metrics.DeleteSubsMetric(res)
7374
}
7475

7576
reconciled, err := s.reconcilers.Reconcile(ctx, initial)
@@ -85,15 +86,6 @@ func (s *subscriptionSyncer) Sync(ctx context.Context, event kubestate.ResourceE
8586
return nil
8687
}
8788

88-
func (s *subscriptionSyncer) recordMetrics(sub *v1alpha1.Subscription) {
89-
// sub.Spec is not a required field.
90-
if sub.Spec == nil {
91-
return
92-
}
93-
94-
metrics.CounterForSubscription(sub.GetName(), sub.Status.InstalledCSV, sub.Spec.Channel, sub.Spec.Package).Inc()
95-
}
96-
9789
func (s *subscriptionSyncer) Notify(event kubestate.ResourceEvent) {
9890
s.notify(event)
9991
}

pkg/controller/operators/catalog/subscription/syncer_test.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,19 @@ import (
66

77
"github.com/sirupsen/logrus"
88
"github.com/stretchr/testify/require"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
910

1011
"github.com/operator-framework/api/pkg/operators/v1alpha1"
1112
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubestate"
1213
)
1314

15+
const (
16+
name = "test-subscription"
17+
packageName = "test-package"
18+
channel = "test-channel"
19+
installedCSVName = "test-csv"
20+
)
21+
1422
func TestSync(t *testing.T) {
1523
type fields struct {
1624
syncer kubestate.Syncer
@@ -39,7 +47,22 @@ func TestSync(t *testing.T) {
3947
args: args{
4048
event: kubestate.NewResourceEvent(
4149
kubestate.ResourceAdded,
42-
&v1alpha1.Subscription{},
50+
&v1alpha1.Subscription{
51+
TypeMeta: metav1.TypeMeta{
52+
Kind: v1alpha1.SubscriptionKind,
53+
APIVersion: v1alpha1.SubscriptionCRDAPIVersion,
54+
},
55+
ObjectMeta: metav1.ObjectMeta{
56+
Name: name,
57+
},
58+
Spec: &v1alpha1.SubscriptionSpec{
59+
Package: packageName,
60+
Channel: channel,
61+
},
62+
Status: v1alpha1.SubscriptionStatus{
63+
InstalledCSV: installedCSVName,
64+
},
65+
},
4366
),
4467
},
4568
want: want{

pkg/metrics/metrics.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package metrics
22

33
import (
44
"context"
5+
56
"github.com/prometheus/client_golang/prometheus"
67
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
78
"k8s.io/apimachinery/pkg/labels"
@@ -217,3 +218,11 @@ func EmitCSVMetric(oldCSV *olmv1alpha1.ClusterServiceVersion, newCSV *olmv1alpha
217218
csvAbnormal.WithLabelValues(newCSV.Namespace, newCSV.Name, newCSV.Spec.Version.String(), string(newCSV.Status.Phase), string(newCSV.Status.Reason)).Set(1)
218219
}
219220
}
221+
222+
func EmitSubMetric(sub *olmv1alpha1.Subscription) {
223+
SubscriptionSyncCount.WithLabelValues(sub.GetName(), sub.Status.InstalledCSV, sub.Spec.Channel, sub.Spec.Package).Inc()
224+
}
225+
226+
func DeleteSubsMetric(sub *olmv1alpha1.Subscription) {
227+
SubscriptionSyncCount.DeleteLabelValues(sub.GetName(), sub.Status.InstalledCSV, sub.Spec.Channel, sub.Spec.Package)
228+
}

test/e2e/metrics_e2e_test.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
"github.com/operator-framework/api/pkg/operators/v1alpha1"
1818
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
19+
"github.com/operator-framework/operator-lifecycle-manager/pkg/metrics"
1920
)
2021

2122
var _ = Describe("Metrics", func() {
@@ -49,7 +50,7 @@ var _ = Describe("Metrics", func() {
4950
Expect(err).ToNot(HaveOccurred())
5051

5152
// Verify metrics have been emitted for packageserver csv
52-
Expect(getMetricsFromPod(c, getOLMPod(c), "8081")).To(And(
53+
Expect(getMetricsFromPod(c, getPodWithLabel(c, "app=olm-operator"), "8081")).To(And(
5354
ContainSubstring("csv_abnormal"),
5455
ContainSubstring(fmt.Sprintf("name=\"%s\"", failingCSV.Name)),
5556
ContainSubstring("phase=\"Failed\""),
@@ -61,15 +62,31 @@ var _ = Describe("Metrics", func() {
6162
cleanupCSV()
6263

6364
// Verify that when the csv has been deleted, it deletes the corresponding CSV metrics
64-
Expect(getMetricsFromPod(c, getOLMPod(c), "8081")).ToNot(And(
65+
Expect(getMetricsFromPod(c, getPodWithLabel(c, "app=olm-operator"), "8081")).ToNot(And(
6566
ContainSubstring("csv_abnormal{name=\"%s\"", failingCSV.Name),
6667
ContainSubstring("csv_succeeded{name=\"%s\"", failingCSV.Name),
6768
))
69+
70+
subscriptionCleanup := createSubscription(GinkgoT(), crc, testNamespace, "metric-subscription", testPackageName, stableChannel, v1alpha1.ApprovalManual)
71+
72+
// Verify metrics have been emitted for subscription
73+
Expect(getMetricsFromPod(c, getPodWithLabel(c, "app=catalog-operator"), "8081")).To(And(
74+
ContainSubstring("subscription_sync_total"),
75+
ContainSubstring(fmt.Sprintf("%s=\"%s\"", metrics.NAME_LABEL, "metric-subscription")),
76+
ContainSubstring(fmt.Sprintf("%s=\"%s\"", metrics.CHANNEL_LABEL, stableChannel)),
77+
ContainSubstring(fmt.Sprintf("%s=\"%s\"", metrics.PACKAGE_LABEL, testPackageName)),
78+
))
79+
80+
subscriptionCleanup()
81+
82+
Expect(getMetricsFromPod(c, getPodWithLabel(c, "app=catalog-operator"), "8081")).ToNot(And(
83+
ContainSubstring("subscription_sync_total{name=\"metric-subscription\""),
84+
))
6885
})
6986
})
7087

71-
func getOLMPod(client operatorclient.ClientInterface) *corev1.Pod {
72-
listOptions := metav1.ListOptions{LabelSelector: "app=olm-operator"}
88+
func getPodWithLabel(client operatorclient.ClientInterface, label string) *corev1.Pod {
89+
listOptions := metav1.ListOptions{LabelSelector: label}
7390
var podList *corev1.PodList
7491
Eventually(func() (err error) {
7592
podList, err = client.KubernetesInterface().CoreV1().Pods(operatorNamespace).List(context.TODO(), listOptions)

0 commit comments

Comments
 (0)