1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package collector
17
18 import (
19 "context"
20 "encoding/json"
21
22 "github.com/go-logr/logr"
23 "github.com/jinzhu/gorm"
24 "github.com/pkg/errors"
25 apierrors "k8s.io/apimachinery/pkg/api/errors"
26 "k8s.io/apimachinery/pkg/runtime"
27 ctrl "sigs.k8s.io/controller-runtime"
28 "sigs.k8s.io/controller-runtime/pkg/client"
29
30 "github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
31 "github.com/chaos-mesh/chaos-mesh/pkg/dashboard/core"
32 )
33
34
35 type ScheduleCollector struct {
36 client.Client
37 Log logr.Logger
38 apiType runtime.Object
39 archive core.ScheduleStore
40 }
41
42
43 func (r *ScheduleCollector) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
44 if r.apiType == nil {
45 r.Log.Error(nil, "apiType has not been initialized")
46 return ctrl.Result{}, nil
47 }
48
49 schedule := &v1alpha1.Schedule{}
50 err := r.Get(ctx, req.NamespacedName, schedule)
51 if apierrors.IsNotFound(err) {
52 if err = r.archiveSchedule(req.Namespace, req.Name); err != nil {
53 r.Log.Error(err, "failed to archive schedule")
54 }
55 return ctrl.Result{}, nil
56 }
57 if err != nil {
58 r.Log.Error(err, "failed to get schedule object", "request", req.NamespacedName)
59 return ctrl.Result{}, nil
60 }
61
62 if err := r.setUnarchivedSchedule(req, *schedule); err != nil {
63 r.Log.Error(err, "failed to archive schedule")
64
65 }
66
67 return ctrl.Result{}, nil
68 }
69
70
71 func (r *ScheduleCollector) Setup(mgr ctrl.Manager, apiType client.Object) error {
72 r.apiType = apiType
73
74 return ctrl.NewControllerManagedBy(mgr).
75 For(apiType).
76 Complete(r)
77 }
78
79 func (r *ScheduleCollector) setUnarchivedSchedule(req ctrl.Request, schedule v1alpha1.Schedule) error {
80 archive := &core.Schedule{
81 ScheduleMeta: core.ScheduleMeta{
82 Namespace: req.Namespace,
83 Name: req.Name,
84 Kind: schedule.Kind,
85 UID: string(schedule.UID),
86 Archived: false,
87 },
88 }
89
90 switch schedule.Spec.Type {
91 case v1alpha1.ScheduleTypePodChaos:
92 archive.Action = string(schedule.Spec.ScheduleItem.PodChaos.Action)
93 case v1alpha1.ScheduleTypeNetworkChaos:
94 archive.Action = string(schedule.Spec.ScheduleItem.NetworkChaos.Action)
95 case v1alpha1.ScheduleTypeIOChaos:
96 archive.Action = string(schedule.Spec.ScheduleItem.IOChaos.Action)
97 case v1alpha1.ScheduleTypeTimeChaos, v1alpha1.ScheduleTypeKernelChaos, v1alpha1.ScheduleTypeStressChaos, v1alpha1.ScheduleTypeHTTPChaos:
98 archive.Action = ""
99 case v1alpha1.ScheduleTypeDNSChaos:
100 archive.Action = string(schedule.Spec.ScheduleItem.DNSChaos.Action)
101 case v1alpha1.ScheduleTypeAWSChaos:
102 archive.Action = string(schedule.Spec.ScheduleItem.AWSChaos.Action)
103 case v1alpha1.ScheduleTypeGCPChaos:
104 archive.Action = string(schedule.Spec.ScheduleItem.GCPChaos.Action)
105 case v1alpha1.ScheduleTypeJVMChaos:
106 archive.Action = string(schedule.Spec.ScheduleItem.JVMChaos.Action)
107 case v1alpha1.ScheduleTypePhysicalMachineChaos:
108 archive.Action = string(schedule.Spec.ScheduleItem.PhysicalMachineChaos.Action)
109 default:
110 return errors.New("unsupported chaos type " + string(schedule.Spec.Type))
111 }
112
113 archive.StartTime = schedule.GetCreationTimestamp().Time
114 if schedule.GetDeletionTimestamp() != nil {
115 archive.FinishTime = &schedule.GetDeletionTimestamp().Time
116 }
117
118 data, err := json.Marshal(schedule)
119 if err != nil {
120 r.Log.Error(err, "failed to marshal schedule", "kind", archive.Kind,
121 "namespace", archive.Namespace, "name", archive.Name)
122 return err
123 }
124
125 archive.Schedule = string(data)
126
127 find, err := r.archive.FindByUID(context.Background(), string(schedule.UID))
128 if err != nil && !gorm.IsRecordNotFoundError(err) {
129 r.Log.Error(err, "failed to find schedule", "UID", schedule.UID)
130 return err
131 }
132
133 if find != nil {
134 archive.ID = find.ID
135 archive.CreatedAt = find.CreatedAt
136 archive.UpdatedAt = find.UpdatedAt
137 }
138
139 if err := r.archive.Set(context.Background(), archive); err != nil {
140 r.Log.Error(err, "failed to update schedule", "archive", archive)
141 return err
142 }
143
144 return nil
145 }
146
147 func (r *ScheduleCollector) archiveSchedule(ns, name string) error {
148 if err := r.archive.Archive(context.Background(), ns, name); err != nil {
149 r.Log.Error(err, "failed to archive schedule", "namespace", ns, "name", name)
150 return err
151 }
152
153 return nil
154 }
155