generated from cybozu-go/neco-template
-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathpod_watcher.go
92 lines (80 loc) · 2.83 KB
/
pod_watcher.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package controllers
import (
"context"
mocov1beta2 "github.com/cybozu-go/moco/api/v1beta2"
"github.com/cybozu-go/moco/clustering"
"github.com/cybozu-go/moco/pkg/constants"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
crlog "sigs.k8s.io/controller-runtime/pkg/log"
)
// PodWatcher watches MySQL pods and informs the cluster manager of the event.
type PodWatcher struct {
client.Client
ClusterManager clustering.ClusterManager
MaxConcurrentReconciles int
}
//+kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch
//+kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch
// Reconcile implements Reconciler interface.
// See https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile#Reconciler
func (r *PodWatcher) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := crlog.FromContext(ctx)
pod := &corev1.Pod{}
if err := r.Get(ctx, req.NamespacedName, pod); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
if pod.DeletionTimestamp == nil && pod.Annotations[constants.AnnDemote] != "true" {
return ctrl.Result{}, nil
}
ref := metav1.GetControllerOfNoCopy(pod)
if ref == nil {
return ctrl.Result{}, nil
}
refGV, err := schema.ParseGroupVersion(ref.APIVersion)
if err != nil {
//lint:ignore nilerr intentional
return ctrl.Result{}, nil
}
if ref.Kind != "StatefulSet" || refGV.Group != appsv1.GroupName {
return ctrl.Result{}, nil
}
sts := &appsv1.StatefulSet{}
if err := r.Get(ctx, client.ObjectKey{Namespace: pod.Namespace, Name: ref.Name}, sts); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
ref = metav1.GetControllerOfNoCopy(sts)
if ref == nil {
return ctrl.Result{}, nil
}
refGV, err = schema.ParseGroupVersion(ref.APIVersion)
if err != nil {
//lint:ignore nilerr intentional
return ctrl.Result{}, nil
}
if ref.Kind != "MySQLCluster" || refGV.Group != mocov1beta2.GroupVersion.Group {
return ctrl.Result{}, nil
}
if pod.DeletionTimestamp != nil {
log.Info("detected mysql pod deletion", "name", pod.Name)
} else {
log.Info("detected demote annotation", "name", pod.Name)
}
r.ClusterManager.UpdateNoStart(types.NamespacedName{Namespace: pod.Namespace, Name: ref.Name}, string(controller.ReconcileIDFromContext(ctx)))
return ctrl.Result{}, nil
}
// SetupWithManager sets up the controller with the Manager.
func (r *PodWatcher) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&corev1.Pod{}).
WithOptions(
controller.Options{MaxConcurrentReconciles: r.MaxConcurrentReconciles},
).
Complete(r)
}