Skip to content

Commit c1a02fd

Browse files
nixpanicmergify[bot]
authored andcommitted
sidecar: Add VolumeCondition recorders (klog and Events)
Signed-off-by: Niels de Vos <ndevos@ibm.com>
1 parent c34d0ad commit c1a02fd

File tree

3 files changed

+206
-0
lines changed

3 files changed

+206
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
Copyright 2025 The Kubernetes-CSI-Addons Authors.
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 condition
18+
19+
import (
20+
"context"
21+
"fmt"
22+
23+
corev1 "k8s.io/api/core/v1"
24+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
"k8s.io/client-go/kubernetes"
26+
"k8s.io/client-go/kubernetes/scheme"
27+
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
28+
"k8s.io/client-go/tools/record"
29+
30+
"github.com/csi-addons/kubernetes-csi-addons/sidecar/internal/volume-condition/volume"
31+
)
32+
33+
type eventRecorder struct {
34+
client *kubernetes.Clientset
35+
recorder record.EventRecorder
36+
}
37+
38+
// assert on conditionRecorder interface
39+
var _ conditionRecorder = &eventRecorder{}
40+
41+
// WithEventRecorder can be passed to the VolumeConditionRecorder so that it
42+
// will create an Event for the PersistentVolumeClaim with the volume
43+
// condition.
44+
func WithEventRecorder() RecorderOption {
45+
return RecorderOption{
46+
newRecorder: newEventRecorder,
47+
}
48+
}
49+
50+
func newEventRecorder(client *kubernetes.Clientset, hostname string) (conditionRecorder, error) {
51+
eventBroadcaster := record.NewBroadcaster()
52+
eventBroadcaster.StartRecordingToSink(
53+
&typedcorev1.EventSinkImpl{
54+
Interface: client.CoreV1().Events(""),
55+
},
56+
)
57+
recorder := eventBroadcaster.NewRecorder(
58+
scheme.Scheme,
59+
corev1.EventSource{
60+
Component: "CSI-Addons",
61+
Host: hostname,
62+
},
63+
)
64+
65+
return &eventRecorder{
66+
client: client,
67+
recorder: recorder,
68+
}, nil
69+
}
70+
71+
func (er *eventRecorder) record(
72+
ctx context.Context,
73+
pv *corev1.PersistentVolume,
74+
vc volume.VolumeCondition,
75+
) error {
76+
claim := pv.Spec.ClaimRef
77+
if claim == nil {
78+
return fmt.Errorf("persistent volume %q does not have a claim (unused?)", pv.Name)
79+
}
80+
81+
pvc, err := er.client.CoreV1().PersistentVolumeClaims(claim.Namespace).Get(
82+
ctx,
83+
claim.Name,
84+
metav1.GetOptions{},
85+
)
86+
if err != nil {
87+
return fmt.Errorf(
88+
"failed to get persistent volume claim %q in namespace %q: %w",
89+
claim.Name,
90+
claim.Namespace,
91+
err,
92+
)
93+
}
94+
95+
severity := corev1.EventTypeNormal
96+
if !vc.IsHealthy() {
97+
severity = corev1.EventTypeWarning
98+
}
99+
100+
er.recorder.Event(pvc, severity, vc.GetReason(), vc.GetMessage())
101+
102+
return nil
103+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
Copyright 2025 The Kubernetes-CSI-Addons Authors.
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 condition
18+
19+
import (
20+
"context"
21+
22+
corev1 "k8s.io/api/core/v1"
23+
"k8s.io/client-go/kubernetes"
24+
"k8s.io/klog/v2"
25+
26+
"github.com/csi-addons/kubernetes-csi-addons/sidecar/internal/volume-condition/volume"
27+
)
28+
29+
type logRecorder struct{}
30+
31+
// assert on conditionRecorder interface
32+
var _ conditionRecorder = &logRecorder{}
33+
34+
// WithLogRecorder can be passed to the VolumeConditionReporter so that it
35+
// will report the volume condition in the logs of the CSI-Addons sidecar.
36+
func WithLogRecorder() RecorderOption {
37+
return RecorderOption{
38+
newRecorder: func(client *kubernetes.Clientset, hostname string) (conditionRecorder, error) {
39+
return &logRecorder{}, nil
40+
},
41+
}
42+
}
43+
44+
func (lr *logRecorder) record(
45+
ctx context.Context,
46+
pv *corev1.PersistentVolume,
47+
vc volume.VolumeCondition,
48+
) error {
49+
if vc.IsHealthy() {
50+
msg := vc.GetMessage()
51+
if msg != "" {
52+
msg = ": " + msg
53+
}
54+
klog.Infof("persistent volume %q is healthy"+msg, pv.GetName())
55+
} else {
56+
klog.Warningf(
57+
"persistent volume %q is not healthy: %v",
58+
pv.GetName(),
59+
vc.GetMessage(),
60+
)
61+
}
62+
63+
return nil
64+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
Copyright 2025 The Kubernetes-CSI-Addons Authors.
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 condition
18+
19+
import (
20+
"context"
21+
22+
corev1 "k8s.io/api/core/v1"
23+
"k8s.io/client-go/kubernetes"
24+
25+
"github.com/csi-addons/kubernetes-csi-addons/sidecar/internal/volume-condition/volume"
26+
)
27+
28+
// conditionRecorder provides the interface for recorders that will record the
29+
// volume condition.
30+
type conditionRecorder interface {
31+
record(ctx context.Context, pv *corev1.PersistentVolume, vc volume.VolumeCondition) error
32+
}
33+
34+
// RecorderOption is the interface for creating new recorders. The
35+
// VolumeConditionReporter will use this interface to configure a recorder
36+
// and uses it to report the volume condition.
37+
type RecorderOption struct {
38+
newRecorder func(client *kubernetes.Clientset, hostname string) (conditionRecorder, error)
39+
}

0 commit comments

Comments
 (0)