Skip to content

Commit a38aa95

Browse files
authored
Merge pull request #848 from fluxcd/rfc-0008
[RFC-0008] Custom Event Metadata from Annotations
2 parents d54623a + 1747288 commit a38aa95

File tree

3 files changed

+94
-36
lines changed

3 files changed

+94
-36
lines changed

apis/event/v1beta1/event.go

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import (
2121
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2222
)
2323

24+
// Group is the API Group for the Event API.
25+
const Group = "event.toolkit.fluxcd.io"
26+
2427
// These constants define valid event severity values.
2528
const (
2629
// EventSeverityTrace represents a trace event, usually

runtime/events/recorder.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ import (
2121
"encoding/json"
2222
"errors"
2323
"fmt"
24+
"maps"
2425
"net/http"
2526
"net/url"
2627
"os"
28+
"strings"
2729
"time"
2830

2931
"github.com/go-logr/logr"
@@ -145,7 +147,7 @@ func (r *Recorder) Eventf(object runtime.Object, eventtype, reason, messageFmt s
145147
// It also logs the event if debug logs are enabled in the logger.
146148
func (r *Recorder) AnnotatedEventf(
147149
object runtime.Object,
148-
annotations map[string]string,
150+
inputAnnotations map[string]string,
149151
eventtype, reason string,
150152
messageFmt string, args ...interface{}) {
151153

@@ -154,6 +156,16 @@ func (r *Recorder) AnnotatedEventf(
154156
r.Log.Error(err, "failed to get object reference")
155157
}
156158

159+
// Add object annotations to the annotations.
160+
annotations := maps.Clone(inputAnnotations)
161+
if annotatedObject, ok := object.(interface{ GetAnnotations() map[string]string }); ok {
162+
for k, v := range annotatedObject.GetAnnotations() {
163+
if strings.HasPrefix(k, eventv1.Group+"/") {
164+
annotations[k] = v
165+
}
166+
}
167+
}
168+
157169
// Add object info in the logger.
158170
log := r.Log.WithValues("name", ref.Name, "namespace", ref.Namespace, "reconciler kind", ref.Kind)
159171

runtime/events/recorder_test.go

+78-35
Original file line numberDiff line numberDiff line change
@@ -25,48 +25,91 @@ import (
2525

2626
"github.com/stretchr/testify/require"
2727
corev1 "k8s.io/api/core/v1"
28+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+
"k8s.io/apimachinery/pkg/runtime"
2830
ctrl "sigs.k8s.io/controller-runtime"
2931

3032
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
3133
)
3234

3335
func TestEventRecorder_AnnotatedEventf(t *testing.T) {
34-
requestCount := 0
35-
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
36-
requestCount++
37-
b, err := io.ReadAll(r.Body)
38-
require.NoError(t, err)
39-
40-
var payload eventv1.Event
41-
err = json.Unmarshal(b, &payload)
42-
require.NoError(t, err)
43-
44-
require.Equal(t, "ConfigMap", payload.InvolvedObject.Kind)
45-
require.Equal(t, "webapp", payload.InvolvedObject.Name)
46-
require.Equal(t, "gitops-system", payload.InvolvedObject.Namespace)
47-
require.Equal(t, "true", payload.Metadata["test"])
48-
require.Equal(t, "sync", payload.Reason)
49-
50-
}))
51-
defer ts.Close()
52-
53-
eventRecorder, err := NewRecorder(env, ctrl.Log, ts.URL, "test-controller")
54-
require.NoError(t, err)
55-
56-
obj := &corev1.ConfigMap{}
57-
obj.Namespace = "gitops-system"
58-
obj.Name = "webapp"
59-
60-
meta := map[string]string{
61-
"test": "true",
36+
for _, tt := range []struct {
37+
name string
38+
object runtime.Object
39+
expectedMetadata map[string]string
40+
}{
41+
{
42+
name: "event with ConfigMap",
43+
object: &corev1.ConfigMap{
44+
ObjectMeta: metav1.ObjectMeta{
45+
Name: "webapp",
46+
Namespace: "gitops-system",
47+
Annotations: map[string]string{
48+
"event.toolkit.fluxcd.io/deploymentID": "e076e315-5a48-41c3-81c8-8d8bdee7d74d",
49+
"event.toolkit.fluxcd.io/image": "ghcr.io/stefanprodan/podinfo:6.5.0",
50+
},
51+
},
52+
},
53+
expectedMetadata: map[string]string{
54+
"test": "true",
55+
"event.toolkit.fluxcd.io/deploymentID": "e076e315-5a48-41c3-81c8-8d8bdee7d74d",
56+
"event.toolkit.fluxcd.io/image": "ghcr.io/stefanprodan/podinfo:6.5.0",
57+
},
58+
},
59+
{
60+
name: "event with ObjectReference for ConfigMap (does not panic with runtime.Object without annotations)",
61+
object: &corev1.ObjectReference{
62+
Name: "webapp",
63+
Namespace: "gitops-system",
64+
Kind: "ConfigMap",
65+
},
66+
expectedMetadata: map[string]string{
67+
"test": "true",
68+
},
69+
},
70+
} {
71+
t.Run(tt.name, func(t *testing.T) {
72+
requestCount := 0
73+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
74+
requestCount++
75+
b, err := io.ReadAll(r.Body)
76+
require.NoError(t, err)
77+
78+
var payload eventv1.Event
79+
err = json.Unmarshal(b, &payload)
80+
require.NoError(t, err)
81+
82+
require.Equal(t, "ConfigMap", payload.InvolvedObject.Kind)
83+
require.Equal(t, "webapp", payload.InvolvedObject.Name)
84+
require.Equal(t, "gitops-system", payload.InvolvedObject.Namespace)
85+
require.Equal(t, "sync", payload.Reason)
86+
require.Equal(t, "sync object", payload.Message)
87+
88+
for k, v := range tt.expectedMetadata {
89+
require.Equal(t, v, payload.Metadata[k])
90+
}
91+
}))
92+
defer ts.Close()
93+
94+
eventRecorder, err := NewRecorder(env, ctrl.Log, ts.URL, "test-controller")
95+
require.NoError(t, err)
96+
97+
obj := tt.object
98+
99+
meta := map[string]string{
100+
"test": "true",
101+
}
102+
103+
const msg = "sync object"
104+
105+
eventRecorder.AnnotatedEventf(obj, meta, corev1.EventTypeNormal, "sync", "%s", msg)
106+
require.Equal(t, 2, requestCount)
107+
108+
// When a trace event is sent, it's dropped, no new request.
109+
eventRecorder.AnnotatedEventf(obj, meta, eventv1.EventTypeTrace, "sync", "%s", msg)
110+
require.Equal(t, 2, requestCount)
111+
})
62112
}
63-
64-
eventRecorder.AnnotatedEventf(obj, meta, corev1.EventTypeNormal, "sync", "sync %s", obj.Name)
65-
require.Equal(t, 2, requestCount)
66-
67-
// When a trace event is sent, it's dropped, no new request.
68-
eventRecorder.AnnotatedEventf(obj, meta, eventv1.EventTypeTrace, "sync", "sync %s", obj.Name)
69-
require.Equal(t, 2, requestCount)
70113
}
71114

72115
func TestEventRecorder_AnnotatedEventf_Retry(t *testing.T) {

0 commit comments

Comments
 (0)