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

bakito / k8s-event-logger-operator / 12003917968

25 Nov 2024 05:32AM UTC coverage: 62.725%. Remained the same
12003917968

Pull #484

github

web-flow
Bump sigs.k8s.io/controller-runtime from 0.19.1 to 0.19.2

Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.19.1 to 0.19.2.
- [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases)
- [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.19.1...v0.19.2)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/controller-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #484: Bump sigs.k8s.io/controller-runtime from 0.19.1 to 0.19.2

732 of 1167 relevant lines covered (62.72%)

0.71 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(ctx context.Context, cr *eventloggerv1.EventLogger, logger logr.Logger, err error) (reconcile.Result, error) {
1✔
99
        if err != nil {
1✔
100
                logger.Error(err, "")
×
101
        }
×
102
        if r.LoggerMode {
2✔
103
                // return only, no update
1✔
104
                return reconcile.Result{}, err
1✔
105
        }
1✔
106
        cr.Apply(err)
1✔
107
        err = r.Update(ctx, cr)
1✔
108
        return reconcile.Result{}, err
1✔
109
}
110

111
type loggingPredicate struct {
112
        predicate.Funcs
113
        lastVersion string
114
        Config      *Config
115
}
116

117
// Create implements Predicate
118
func (p *loggingPredicate) Create(e event.CreateEvent) bool {
1✔
119
        if _, ok := e.Object.(*eventloggerv1.EventLogger); ok {
2✔
120
                return p.Config.matches(e.Object)
1✔
121
        }
1✔
122
        return p.logEvent(e.Object)
1✔
123
}
124

125
// Update implements Predicate
126
func (p *loggingPredicate) Update(e event.UpdateEvent) bool {
1✔
127
        if _, ok := e.ObjectNew.(*eventloggerv1.EventLogger); ok {
2✔
128
                return p.Config.matches(e.ObjectNew)
1✔
129
        }
1✔
130
        return p.logEvent(e.ObjectNew)
1✔
131
}
132

133
// Delete implements Predicate
134
func (p *loggingPredicate) Delete(e event.DeleteEvent) bool {
1✔
135
        if _, ok := e.Object.(*eventloggerv1.EventLogger); ok {
2✔
136
                return p.Config.matches(e.Object)
1✔
137
        }
1✔
138
        return false
1✔
139
}
140

141
func (p *loggingPredicate) logEvent(e runtime.Object) bool {
1✔
142
        if p.Config == nil || p.Config.filter == nil {
2✔
143
                return false
1✔
144
        }
1✔
145

146
        evt, ok := e.(*corev1.Event)
1✔
147
        if !ok {
2✔
148
                return false
1✔
149
        }
1✔
150
        if evt.ResourceVersion <= p.lastVersion {
2✔
151
                return false
1✔
152
        }
1✔
153
        p.lastVersion = evt.ResourceVersion // SA4005:
1✔
154

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

182
                eventLogger.Info(evt.Message)
1✔
183
        }
184
        return false
1✔
185
}
186

187
func getLatestRevision(ctx context.Context, cl client.Client, namespace string) (string, error) {
1✔
188
        eventList := &corev1.EventList{}
1✔
189
        opts := []client.ListOption{
1✔
190
                client.Limit(0),
1✔
191
                client.InNamespace(namespace),
1✔
192
        }
1✔
193

1✔
194
        err := cl.List(ctx, eventList, opts...)
1✔
195
        if err != nil {
1✔
196
                return "", err
×
197
        }
×
198
        return eventList.ResourceVersion, nil
1✔
199
}
200

201
// SetupWithManager setup with manager
202
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager, namespace string) error {
×
203
        cl, err := client.New(mgr.GetConfig(), client.Options{})
×
204
        if err != nil {
×
205
                return err
×
206
        }
×
207

208
        lv, err := getLatestRevision(context.Background(), cl, namespace)
×
209
        if err != nil {
×
210
                return err
×
211
        }
×
212
        return ctrl.NewControllerManagedBy(mgr).
×
213
                For(&eventloggerv1.EventLogger{}).
×
214
                Watches(&corev1.Event{}, &handler.Funcs{}).
×
215
                WithEventFilter(&loggingPredicate{Config: r.Config, lastVersion: lv}).
×
216
                Complete(r)
×
217
}
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