Skip to content

Commit 6262378

Browse files
committed
Extend Volume Runtime Interface for cross-cluster Events
1 parent f0a0d85 commit 6262378

File tree

23 files changed

+2276
-133
lines changed

23 files changed

+2276
-133
lines changed

broker/machinebroker/server/event_list_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
computev1alpha1 "github.com/ironcore-dev/ironcore/api/compute/v1alpha1"
1010
networkingv1alpha1 "github.com/ironcore-dev/ironcore/api/networking/v1alpha1"
11+
irievent "github.com/ironcore-dev/ironcore/iri/apis/event/v1alpha1"
1112
iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1"
1213
irimeta "github.com/ironcore-dev/ironcore/iri/apis/meta/v1alpha1"
1314
machinepoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/machinepoollet/api/v1alpha1"
@@ -71,11 +72,11 @@ var _ = Describe("ListEvents", func() {
7172
eventRecorder.Event(ironcoreMachine, corev1.EventTypeNormal, "testing", "this is test event")
7273

7374
By("listing the machine events with no filters")
74-
resp, err := srv.ListEvents(ctx, &iri.ListEventsRequest{})
75-
76-
Expect(err).NotTo(HaveOccurred())
77-
78-
Expect(resp.Events).To(ConsistOf(
75+
Eventually(func(g Gomega) []*irievent.Event {
76+
resp, err := srv.ListEvents(ctx, &iri.ListEventsRequest{})
77+
g.Expect(err).NotTo(HaveOccurred())
78+
return resp.Events
79+
}).Should(ConsistOf(
7980
HaveField("Spec", SatisfyAll(
8081
HaveField("InvolvedObjectMeta.Id", Equal(ironcoreMachine.Name)),
8182
HaveField("Reason", Equal("testing")),
@@ -86,7 +87,7 @@ var _ = Describe("ListEvents", func() {
8687
)
8788

8889
By("listing the machine events with matching label and time filters")
89-
resp, err = srv.ListEvents(ctx, &iri.ListEventsRequest{Filter: &iri.EventFilter{
90+
resp, err := srv.ListEvents(ctx, &iri.ListEventsRequest{Filter: &iri.EventFilter{
9091
LabelSelector: map[string]string{machinepoolletv1alpha1.MachineUIDLabel: "foobar"},
9192
EventsFromTime: eventGeneratedTime.Unix(),
9293
EventsToTime: time.Now().Unix(),
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package server
5+
6+
import (
7+
"context"
8+
"fmt"
9+
10+
v1 "k8s.io/api/core/v1"
11+
"k8s.io/apimachinery/pkg/fields"
12+
"k8s.io/apimachinery/pkg/labels"
13+
ctrl "sigs.k8s.io/controller-runtime"
14+
"sigs.k8s.io/controller-runtime/pkg/client"
15+
16+
storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1"
17+
"github.com/ironcore-dev/ironcore/broker/volumebroker/apiutils"
18+
irievent "github.com/ironcore-dev/ironcore/iri/apis/event/v1alpha1"
19+
iri "github.com/ironcore-dev/ironcore/iri/apis/volume/v1alpha1"
20+
)
21+
22+
const (
23+
InvolvedObjectKind = "Volume"
24+
InvolvedObjectKindSelector = "involvedObject.kind"
25+
InvolvedObjectAPIVersionSelector = "involvedObject.apiVersion"
26+
)
27+
28+
func (s *Server) listEvents(ctx context.Context) ([]*irievent.Event, error) {
29+
log := ctrl.LoggerFrom(ctx)
30+
volumeEventList := &v1.EventList{}
31+
selectorField := fields.Set{
32+
InvolvedObjectKindSelector: InvolvedObjectKind,
33+
InvolvedObjectAPIVersionSelector: storagev1alpha1.SchemeGroupVersion.String(),
34+
}
35+
if err := s.client.List(ctx, volumeEventList,
36+
client.InNamespace(s.namespace), client.MatchingFieldsSelector{Selector: selectorField.AsSelector()},
37+
); err != nil {
38+
return nil, err
39+
}
40+
41+
var iriEvents []*irievent.Event
42+
for _, volumeEvent := range volumeEventList.Items {
43+
ironcoreVolume, err := s.getIronCoreVolume(ctx, volumeEvent.InvolvedObject.Name)
44+
if err != nil {
45+
log.V(1).Info("Unable to get ironcore volume", "VolumeName", volumeEvent.InvolvedObject.Name)
46+
continue
47+
}
48+
volumeObjectMetadata, err := apiutils.GetObjectMetadata(&ironcoreVolume.ObjectMeta)
49+
if err != nil {
50+
continue
51+
}
52+
iriEvent := &irievent.Event{
53+
Spec: &irievent.EventSpec{
54+
InvolvedObjectMeta: volumeObjectMetadata,
55+
Reason: volumeEvent.Reason,
56+
Message: volumeEvent.Message,
57+
Type: volumeEvent.Type,
58+
EventTime: volumeEvent.LastTimestamp.Unix(),
59+
},
60+
}
61+
iriEvents = append(iriEvents, iriEvent)
62+
}
63+
return iriEvents, nil
64+
}
65+
66+
func (s *Server) filterEvents(events []*irievent.Event, filter *iri.EventFilter) []*irievent.Event {
67+
if filter == nil {
68+
return events
69+
}
70+
71+
var (
72+
res []*irievent.Event
73+
sel = labels.SelectorFromSet(filter.LabelSelector)
74+
)
75+
for _, iriEvent := range events {
76+
if !sel.Matches(labels.Set(iriEvent.Spec.InvolvedObjectMeta.Labels)) {
77+
continue
78+
}
79+
80+
if filter.EventsFromTime > 0 && filter.EventsToTime > 0 {
81+
if iriEvent.Spec.EventTime < filter.EventsFromTime || iriEvent.Spec.EventTime > filter.EventsToTime {
82+
continue
83+
}
84+
}
85+
86+
res = append(res, iriEvent)
87+
}
88+
return res
89+
}
90+
91+
func (s *Server) ListEvents(ctx context.Context, req *iri.ListEventsRequest) (*iri.ListEventsResponse, error) {
92+
iriEvents, err := s.listEvents(ctx)
93+
if err != nil {
94+
return nil, fmt.Errorf("error listing volume events : %w", err)
95+
}
96+
97+
iriEvents = s.filterEvents(iriEvents, req.Filter)
98+
99+
return &iri.ListEventsResponse{
100+
Events: iriEvents,
101+
}, nil
102+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package server_test
5+
6+
import (
7+
"time"
8+
9+
storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1"
10+
irievent "github.com/ironcore-dev/ironcore/iri/apis/event/v1alpha1"
11+
iri "github.com/ironcore-dev/ironcore/iri/apis/volume/v1alpha1"
12+
13+
irimeta "github.com/ironcore-dev/ironcore/iri/apis/meta/v1alpha1"
14+
volumepoolletv1alpha1 "github.com/ironcore-dev/ironcore/poollet/volumepoollet/api/v1alpha1"
15+
. "github.com/onsi/ginkgo/v2"
16+
. "github.com/onsi/gomega"
17+
18+
corev1 "k8s.io/api/core/v1"
19+
"k8s.io/client-go/kubernetes/scheme"
20+
ctrl "sigs.k8s.io/controller-runtime"
21+
"sigs.k8s.io/controller-runtime/pkg/client"
22+
)
23+
24+
var _ = Describe("ListEvents", func() {
25+
ns, srv := SetupTest()
26+
volumeClass := SetupVolumeClass()
27+
28+
It("should correctly list events", func(ctx SpecContext) {
29+
By("creating volume")
30+
Expect(storagev1alpha1.AddToScheme(scheme.Scheme)).To(Succeed())
31+
32+
k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{
33+
Scheme: scheme.Scheme,
34+
})
35+
Expect(err).ToNot(HaveOccurred())
36+
37+
res, err := srv.CreateVolume(ctx, &iri.CreateVolumeRequest{
38+
Volume: &iri.Volume{
39+
Metadata: &irimeta.ObjectMetadata{
40+
Labels: map[string]string{
41+
volumepoolletv1alpha1.VolumeUIDLabel: "foobar",
42+
},
43+
},
44+
Spec: &iri.VolumeSpec{
45+
Class: volumeClass.Name,
46+
Resources: &iri.VolumeResources{
47+
StorageBytes: 100,
48+
},
49+
},
50+
},
51+
})
52+
53+
Expect(err).NotTo(HaveOccurred())
54+
Expect(res).NotTo(BeNil())
55+
56+
By("getting the ironcore volume")
57+
ironcoreVolume := &storagev1alpha1.Volume{}
58+
ironcoreVolumeKey := client.ObjectKey{Namespace: ns.Name, Name: res.Volume.Metadata.Id}
59+
Expect(k8sClient.Get(ctx, ironcoreVolumeKey, ironcoreVolume)).To(Succeed())
60+
61+
By("generating the volume events")
62+
eventGeneratedTime := time.Now()
63+
eventRecorder := k8sManager.GetEventRecorderFor("test-recorder")
64+
eventRecorder.Event(ironcoreVolume, corev1.EventTypeNormal, "testing", "this is test event")
65+
66+
By("listing the volume events with no filters")
67+
Eventually(func(g Gomega) []*irievent.Event {
68+
resp, err := srv.ListEvents(ctx, &iri.ListEventsRequest{})
69+
g.Expect(err).NotTo(HaveOccurred())
70+
return resp.Events
71+
}).Should(ConsistOf(
72+
HaveField("Spec", SatisfyAll(
73+
HaveField("InvolvedObjectMeta.Id", Equal(ironcoreVolume.Name)),
74+
HaveField("Reason", Equal("testing")),
75+
HaveField("Message", Equal("this is test event")),
76+
HaveField("Type", Equal(corev1.EventTypeNormal)),
77+
)),
78+
),
79+
)
80+
81+
By("listing the volume events with matching label and time filters")
82+
resp, err := srv.ListEvents(ctx, &iri.ListEventsRequest{Filter: &iri.EventFilter{
83+
LabelSelector: map[string]string{volumepoolletv1alpha1.VolumeUIDLabel: "foobar"},
84+
EventsFromTime: eventGeneratedTime.Unix(),
85+
EventsToTime: time.Now().Unix(),
86+
}})
87+
88+
Expect(err).NotTo(HaveOccurred())
89+
90+
Expect(resp.Events).To(ConsistOf(
91+
HaveField("Spec", SatisfyAll(
92+
HaveField("InvolvedObjectMeta.Id", Equal(ironcoreVolume.Name)),
93+
HaveField("Reason", Equal("testing")),
94+
HaveField("Message", Equal("this is test event")),
95+
HaveField("Type", Equal(corev1.EventTypeNormal)),
96+
)),
97+
),
98+
)
99+
100+
By("listing the volume events with non matching label filter")
101+
resp, err = srv.ListEvents(ctx, &iri.ListEventsRequest{Filter: &iri.EventFilter{
102+
LabelSelector: map[string]string{"foo": "bar"},
103+
EventsFromTime: eventGeneratedTime.Unix(),
104+
EventsToTime: time.Now().Unix(),
105+
}})
106+
Expect(err).NotTo(HaveOccurred())
107+
108+
Expect(resp.Events).To(BeEmpty())
109+
110+
By("listing the volume events with matching label filter and non matching time filter")
111+
resp, err = srv.ListEvents(ctx, &iri.ListEventsRequest{Filter: &iri.EventFilter{
112+
LabelSelector: map[string]string{volumepoolletv1alpha1.VolumeUIDLabel: "foobar"},
113+
EventsFromTime: eventGeneratedTime.Add(-10 * time.Minute).Unix(),
114+
EventsToTime: eventGeneratedTime.Add(-5 * time.Minute).Unix(),
115+
}})
116+
Expect(err).NotTo(HaveOccurred())
117+
118+
Expect(resp.Events).To(BeEmpty())
119+
})
120+
})

broker/volumebroker/server/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ func setOptionsDefaults(o *Options) {
8888

8989
var _ iri.VolumeRuntimeServer = (*Server)(nil)
9090

91+
//+kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch
9192
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch;delete
9293
//+kubebuilder:rbac:groups=storage.ironcore.dev,resources=volumes,verbs=get;list;watch;create;update;patch;delete
9394

0 commit comments

Comments
 (0)