• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bakito / k8s-event-logger-operator / 12875505390

20 Jan 2025 08:51PM UTC coverage: 62.219% (-0.03%) from 62.248%
12875505390

Pull #497

github

bakito
migrate validator
Pull Request #497: chore(deps): bump sigs.k8s.io/controller-runtime from 0.19.4 to 0.20.0

9 of 12 new or added lines in 1 file covered. (75.0%)

746 of 1199 relevant lines covered (62.22%)

0.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.74
/controllers/logging/event_controller.go
1
/*
2

3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
    http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16

17
package logging
18

19
import (
20
        "context"
21
        "reflect"
22

23
        eventloggerv1 "github.com/bakito/k8s-event-logger-operator/api/v1"
24
        "github.com/fatih/structs"
25
        "github.com/go-logr/logr"
26
        corev1 "k8s.io/api/core/v1"
27
        "k8s.io/apimachinery/pkg/api/errors"
28
        "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29
        "k8s.io/apimachinery/pkg/runtime"
30
        ctrl "sigs.k8s.io/controller-runtime"
31
        "sigs.k8s.io/controller-runtime/pkg/client"
32
        "sigs.k8s.io/controller-runtime/pkg/event"
33
        "sigs.k8s.io/controller-runtime/pkg/handler"
34
        "sigs.k8s.io/controller-runtime/pkg/predicate"
35
        "sigs.k8s.io/controller-runtime/pkg/reconcile"
36
)
37

38
var eventLog = ctrl.Log.WithName("event")
39

40
// Reconciler reconciles a Event object
41
type Reconciler struct {
42
        client.Client
43
        Log    logr.Logger
44
        Scheme *runtime.Scheme
45
        Config *Config
46
        // LoggerMode if enabled, the controller does only logging and no update on the custom resource
47
        LoggerMode bool
48
}
49

50
// +kubebuilder:rbac:groups=eventlogger.bakito.ch,resources=eventloggers,verbs=get;list;watch;create;update;patch;delete
51

52
// Reconcile EventLogger to update the current config
53
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
1✔
54
        reqLogger := r.Log.WithValues("namespace", req.Namespace, "name", req.Name)
1✔
55
        if r.Config.name == "" {
2✔
56
                r.Config.name = req.Name
1✔
57
        }
1✔
58

59
        reqLogger.V(2).Info("Reconciling event logger")
1✔
60

1✔
61
        // Fetch the EventLogger cr
1✔
62
        cr := &eventloggerv1.EventLogger{}
1✔
63
        err := r.Get(ctx, req.NamespacedName, cr)
1✔
64
        if err != nil {
2✔
65
                if errors.IsNotFound(err) {
2✔
66
                        // Request object not found, could have been deleted after reconcile request.
1✔
67
                        // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
1✔
68
                        // Return and don't requeue
1✔
69
                        r.Config.filter = nil
1✔
70
                        reqLogger.Info("cr was deleted, removing filter")
1✔
71
                        return reconcile.Result{}, nil
1✔
72
                }
1✔
73
                // Error reading the object - requeue the request.
74
                return r.updateCR(ctx, cr, reqLogger, err)
×
75
        }
76

77
        needUpdate := false
1✔
78
        if !reflect.DeepEqual(r.Config.logFields, cr.Spec.LogFields) {
1✔
79
                r.Config.logFields = cr.Spec.LogFields
×
80
                reqLogger.WithValues("logFields", r.Config.logFields).Info("apply new log fields")
×
81
                needUpdate = true
×
82
        }
×
83

84
        newFilter := newFilter(cr.Spec)
1✔
85
        if r.Config.filter == nil || !r.Config.filter.Equals(newFilter) {
2✔
86
                r.Config.filter = newFilter
1✔
87
                reqLogger.WithValues("filter", r.Config.filter.String()).Info("apply new filter")
1✔
88
                needUpdate = true
1✔
89
        }
1✔
90

91
        if needUpdate {
2✔
92
                return r.updateCR(ctx, cr, reqLogger, nil)
1✔
93
        }
1✔
94

95
        return reconcile.Result{}, nil
×
96
}
97

98
func (r *Reconciler) updateCR(
99
        ctx context.Context,
100
        cr *eventloggerv1.EventLogger,
101
        logger logr.Logger,
102
        err error,
103
) (reconcile.Result, error) {
1✔
104
        if err != nil {
1✔
105
                logger.Error(err, "")
×
106
        }
×
107
        if r.LoggerMode {
2✔
108
                // return only, no update
1✔
109
                return reconcile.Result{}, err
1✔
110
        }
1✔
111
        cr.Apply(err)
1✔
112
        err = r.Update(ctx, cr)
1✔
113
        return reconcile.Result{}, err
1✔
114
}
115

116
type loggingPredicate struct {
117
        predicate.Funcs
118
        lastVersion string
119
        Config      *Config
120
}
121

122
// Create implements Predicate
123
func (p *loggingPredicate) Create(e event.CreateEvent) bool {
1✔
124
        if _, ok := e.Object.(*eventloggerv1.EventLogger); ok {
2✔
125
                return p.Config.matches(e.Object)
1✔
126
        }
1✔
127
        return p.logEvent(e.Object)
1✔
128
}
129

130
// Update implements Predicate
131
func (p *loggingPredicate) Update(e event.UpdateEvent) bool {
1✔
132
        if _, ok := e.ObjectNew.(*eventloggerv1.EventLogger); ok {
2✔
133
                return p.Config.matches(e.ObjectNew)
1✔
134
        }
1✔
135
        return p.logEvent(e.ObjectNew)
1✔
136
}
137

138
// Delete implements Predicate
139
func (p *loggingPredicate) Delete(e event.DeleteEvent) bool {
1✔
140
        if _, ok := e.Object.(*eventloggerv1.EventLogger); ok {
2✔
141
                return p.Config.matches(e.Object)
1✔
142
        }
1✔
143
        return false
1✔
144
}
145

146
func (p *loggingPredicate) logEvent(e runtime.Object) bool {
1✔
147
        if p.Config == nil || p.Config.filter == nil {
2✔
148
                return false
1✔
149
        }
1✔
150

151
        evt, ok := e.(*corev1.Event)
1✔
152
        if !ok {
2✔
153
                return false
1✔
154
        }
1✔
155
        if evt.ResourceVersion <= p.lastVersion {
2✔
156
                return false
1✔
157
        }
1✔
158
        p.lastVersion = evt.ResourceVersion // SA4005:
1✔
159

1✔
160
        if p.Config.filter.Match(evt) {
2✔
161
                var eventLogger logr.Logger
1✔
162
                if len(p.Config.logFields) == 0 {
2✔
163
                        eventLogger = eventLog.WithValues(
1✔
164
                                "namespace", evt.ObjectMeta.Namespace,
1✔
165
                                "name", evt.ObjectMeta.Name,
1✔
166
                                "reason", evt.Reason,
1✔
167
                                "timestamp", evt.LastTimestamp,
1✔
168
                                "type", evt.Type,
1✔
169
                                "involvedObject", evt.InvolvedObject,
1✔
170
                                "source", evt.Source,
1✔
171
                        )
1✔
172
                } else {
2✔
173
                        m := structs.Map(evt)
1✔
174
                        eventLogger = eventLog
1✔
175
                        for _, lf := range p.Config.logFields {
2✔
176
                                if len(lf.Path) > 0 {
2✔
177
                                        val, ok, err := unstructured.NestedFieldNoCopy(m, lf.Path...)
1✔
178
                                        if ok && err == nil {
2✔
179
                                                eventLogger = eventLogger.WithValues(lf.Name, val)
1✔
180
                                        }
1✔
181
                                } else if lf.Value != nil {
×
182
                                        eventLogger = eventLogger.WithValues(lf.Name, *lf.Value)
×
183
                                }
×
184
                        }
185
                }
186

187
                eventLogger.Info(evt.Message)
1✔
188
        }
189
        return false
1✔
190
}
191

192
func getLatestRevision(ctx context.Context, cl client.Client, namespace string) (string, error) {
1✔
193
        eventList := &corev1.EventList{}
1✔
194
        opts := []client.ListOption{
1✔
195
                client.Limit(0),
1✔
196
                client.InNamespace(namespace),
1✔
197
        }
1✔
198

1✔
199
        err := cl.List(ctx, eventList, opts...)
1✔
200
        if err != nil {
1✔
201
                return "", err
×
202
        }
×
203
        return eventList.ResourceVersion, nil
1✔
204
}
205

206
// SetupWithManager setup with manager
207
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager, namespace string) error {
×
208
        cl, err := client.New(mgr.GetConfig(), client.Options{})
×
209
        if err != nil {
×
210
                return err
×
211
        }
×
212

213
        lv, err := getLatestRevision(context.Background(), cl, namespace)
×
214
        if err != nil {
×
215
                return err
×
216
        }
×
217
        return ctrl.NewControllerManagedBy(mgr).
×
218
                For(&eventloggerv1.EventLogger{}).
×
219
                Watches(&corev1.Event{}, &handler.Funcs{}).
×
220
                WithEventFilter(&loggingPredicate{Config: r.Config, lastVersion: lv}).
×
221
                Complete(r)
×
222
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc