...
1
16
17 package main
18
19 import (
20 "context"
21 "math/rand"
22 "os"
23 "time"
24
25 corev1 "k8s.io/api/core/v1"
26 apierrors "k8s.io/apimachinery/pkg/api/errors"
27 "k8s.io/apimachinery/pkg/runtime"
28 _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
29 ctrl "sigs.k8s.io/controller-runtime"
30 api "sigs.k8s.io/controller-runtime/examples/crd/pkg"
31 "sigs.k8s.io/controller-runtime/pkg/client"
32 "sigs.k8s.io/controller-runtime/pkg/log"
33 "sigs.k8s.io/controller-runtime/pkg/log/zap"
34 )
35
36 var (
37 setupLog = ctrl.Log.WithName("setup")
38 )
39
40 type reconciler struct {
41 client.Client
42 scheme *runtime.Scheme
43 }
44
45 func (r *reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
46 log := log.FromContext(ctx).WithValues("chaospod", req.NamespacedName)
47 log.V(1).Info("reconciling chaos pod")
48
49 var chaospod api.ChaosPod
50 if err := r.Get(ctx, req.NamespacedName, &chaospod); err != nil {
51 log.Error(err, "unable to get chaosctl")
52 return ctrl.Result{}, err
53 }
54
55 var pod corev1.Pod
56 podFound := true
57 if err := r.Get(ctx, req.NamespacedName, &pod); err != nil {
58 if !apierrors.IsNotFound(err) {
59 log.Error(err, "unable to get pod")
60 return ctrl.Result{}, err
61 }
62 podFound = false
63 }
64
65 if podFound {
66 shouldStop := chaospod.Spec.NextStop.Time.Before(time.Now())
67 if !shouldStop {
68 return ctrl.Result{RequeueAfter: chaospod.Spec.NextStop.Sub(time.Now()) + 1*time.Second}, nil
69 }
70
71 if err := r.Delete(ctx, &pod); err != nil {
72 log.Error(err, "unable to delete pod")
73 return ctrl.Result{}, err
74 }
75
76 return ctrl.Result{Requeue: true}, nil
77 }
78
79 templ := chaospod.Spec.Template.DeepCopy()
80 pod.ObjectMeta = templ.ObjectMeta
81 pod.Name = req.Name
82 pod.Namespace = req.Namespace
83 pod.Spec = templ.Spec
84
85 if err := ctrl.SetControllerReference(&chaospod, &pod, r.scheme); err != nil {
86 log.Error(err, "unable to set pod's owner reference")
87 return ctrl.Result{}, err
88 }
89
90 if err := r.Create(ctx, &pod); err != nil {
91 log.Error(err, "unable to create pod")
92 return ctrl.Result{}, err
93 }
94
95 chaospod.Spec.NextStop.Time = time.Now().Add(time.Duration(10*(rand.Int63n(2)+1)) * time.Second)
96 chaospod.Status.LastRun = pod.CreationTimestamp
97 if err := r.Update(ctx, &chaospod); err != nil {
98 log.Error(err, "unable to update chaosctl status")
99 return ctrl.Result{}, err
100 }
101 return ctrl.Result{}, nil
102 }
103
104 func main() {
105 ctrl.SetLogger(zap.New())
106
107 mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{})
108 if err != nil {
109 setupLog.Error(err, "unable to start manager")
110 os.Exit(1)
111 }
112
113
114 err = api.AddToScheme(mgr.GetScheme())
115 if err != nil {
116 setupLog.Error(err, "unable to add scheme")
117 os.Exit(1)
118 }
119
120 err = ctrl.NewControllerManagedBy(mgr).
121 For(&api.ChaosPod{}).
122 Owns(&corev1.Pod{}).
123 Complete(&reconciler{
124 Client: mgr.GetClient(),
125 scheme: mgr.GetScheme(),
126 })
127 if err != nil {
128 setupLog.Error(err, "unable to create controller")
129 os.Exit(1)
130 }
131
132 err = ctrl.NewWebhookManagedBy(mgr).
133 For(&api.ChaosPod{}).
134 Complete()
135 if err != nil {
136 setupLog.Error(err, "unable to create webhook")
137 os.Exit(1)
138 }
139
140 setupLog.Info("starting manager")
141 if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
142 setupLog.Error(err, "problem running manager")
143 os.Exit(1)
144 }
145 }
146
View as plain text