-
Notifications
You must be signed in to change notification settings - Fork 54
/
cronanything.go
375 lines (310 loc) · 16.3 KB
/
cronanything.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
Copyright 2018 Google LLC.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
const (
// CronAnythingCreatedByLabel is the name of the label used by CronAnything to
// denote the entity which created the resource.
CronAnythingCreatedByLabel = "db.anthosapis.com/created-by"
// CronAnythingScheduleTimeLabel is the name of the label used by CronAnything
// to denote the schedule time.
CronAnythingScheduleTimeLabel = "db.anthosapis.com/schedule-time"
// TriggerHistoryMaxLength defines the maximum number of trigger history to
// keep track of by CronAnything.
TriggerHistoryMaxLength = 10
)
//+kubebuilder:object:generate=true
// CronAnythingSpec defines the desired state of CronAnything.
type CronAnythingSpec struct {
// Schedule defines a time-based schedule, e.g., a standard cron schedule such
// as “@every 10m”. This field is mandatory and mutable. If it is changed,
// resources will simply be created at the new interval from then on.
Schedule string `json:"schedule"`
// TriggerDeadlineSeconds defines Deadline in seconds for creating the
// resource if it missed the scheduled time. If no deadline is provided, the
// resource will be created no matter how far after the scheduled time.
// If multiple triggers were missed, only the last will be triggered and only
// one resource will be created. This field is mutable and changing it
// will affect the creation of new resources from that point in time.
// +optional
TriggerDeadlineSeconds *int64 `json:"triggerDeadlineSeconds,omitempty"`
// ConcurrencyPolicy specifies how to treat concurrent resources if the
// resource provides a status path that exposes completion.
// The default policy if not provided is to allow a new resource to be created
// even if an active resource already exists.
// If the resource doesn’t have an active/completed status, the only supported
// concurrency policy is to allow creating new resources.
// This field is mutable. If the policy is changed to a more stringent policy
// while multiple resources are active, it will not delete any existing
// resources. The exception is if a creation of a new resource is triggered
// and the policy has been changed to Replace. If multiple resources are
// active, they will all be deleted and replaced by a new resource.
// +optional
ConcurrencyPolicy ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"`
// Suspend tells the controller to suspend creation of additional resources.
// The default value is false. This field is mutable. It will not affect any
// existing resources, but only affect creation of additional resources.
// +optional
Suspend *bool `json:"suspend,omitempty"`
// FinishableStrategy defines how the CronAnything controller an decide if a
// resource has completed.
// Some resources will do some work after they have been created and at some
// point be finished. Jobs are the most common example.
// If no strategy is defined, it is assumed that the resources never finish.
// +optional
FinishableStrategy *FinishableStrategy `json:"finishableStrategy,omitempty"`
// Template is a template of a resource type for which instances are to
// be created on the given schedule.
// This field is mandatory and it must contain a valid template for an
// existing apiVersion and kind in the cluster.
// It is immutable, so if the template needs to change, the whole CronAnything
// resource should be replaced.
// +kubebuilder:validation:EmbeddedResource
// +kubebuilder:pruning:PreserveUnknownFields
Template runtime.RawExtension `json:"template"`
// TotalResourceLimit specifies the total number of children allowed for a
// particular CronAnything resource. If this limit is reached, no additional
// resources will be created.
// This limit is mostly meant to avoid runaway creation of resources that
// could bring down the cluster. Both finished and unfinished resources count
// against this limit.
// This field is mutable. If it is changed to a lower value than the existing
// number of resources, none of the existing resources will be deleted as a
// result, but no additional resources will be created until the number of
// child resources goes below the limit.
// The field is optional with a default value of 100.
// +optional
TotalResourceLimit *int32 `json:"totalResourceLimit,omitempty"`
// Retention defines the retention policy for resources created by
// CronAnything. If no retention policy is defined, CronAnything will never
// delete resources, so cleanup must be handled through some other process.
// +optional
Retention *ResourceRetention `json:"retention,omitempty"`
// CascadeDelete tells CronAnything to set up owner references from the
// created resources to the CronAnything resource. This means that if the
// CronAnything resource is deleted, all resources created by it will also be
// deleted. This is an optional field that defaults to false.
// +optional
CascadeDelete *bool `json:"cascadeDelete,omitempty"`
// ResourceBaseName specifies the base name for the resources created by
// CronAnything, which will be named using the format
// <ResourceBaseName>-<Timestamp>. This field is optional, and the default
// is to use the name of the CronAnything resource as the ResourceBaseName.
// +optional
ResourceBaseName *string `json:"resourceBaseName,omitempty"`
// ResourceTimestampFormat defines the format of the timestamp in the name of
// Resources created by CronAnything <ResourceBaseName>-<Timestamp>.
// This field is optional, and the default is to format the timestamp as unix
// time. If provided, it must be compatible with time.Format in golang.
// +optional
ResourceTimestampFormat *string `json:"resourceTimestampFormat,omitempty"`
}
//+kubebuilder:object:generate=true
// ResourceRetention specifies the retention policy for resources.
type ResourceRetention struct {
// The number of completed resources to keep before deleting them. This
// only affects finishable resources and the default value is 3.
// This field is mutable and if it is changed to a number lower than
// the current number of finished resources, the oldest ones will
// eventually be deleted until the number of finished resources matches
// the limit.
// +optional
HistoryCountLimit *int32 `json:"historyCountLimit,omitempty"`
// The time since completion that a resource is kept before deletion. This
// only affects finishable resources. This does not have any default value and
// if it is not provided, HistoryCountLimit will be used to prune completed
// resources.
// If both HistoryCountLimit and HistoryTimeLimitSeconds are set, it is treated
// as an OR operation.
// +optional
HistoryTimeLimitSeconds *uint64 `json:"historyTimeLimitSeconds,omitempty"`
// ResourceTimestampStrategy specifies how the CronAnything controller
// can find the age of a resource. This is needed to support retention.
ResourceTimestampStrategy ResourceTimestampStrategy `json:"resourceTimestampStrategy"`
}
// FinishableStrategyType specifies the type of the field which tells whether
// a resource is finished.
type FinishableStrategyType string
const (
// FinishableStrategyTimestampField specifies deriving whether a resource is
// finished from a timestamp field.
FinishableStrategyTimestampField FinishableStrategyType = "TimestampField"
// FinishableStrategyStringField specifies deriving whether a resource is
// finished from a string field.
FinishableStrategyStringField FinishableStrategyType = "StringField"
)
//+kubebuilder:object:generate=true
// FinishableStrategy specifies how the CronAnything controller can decide
// whether a created resource has completed. This is needed for any concurrency
// policies other than AllowConcurrent.
type FinishableStrategy struct {
// Type tells which strategy should be used.
Type FinishableStrategyType `json:"type"`
// TimestampField contains the details for how the CronAnything controller
// can find the timestamp field on the resource in order to decide if the
// resource has completed.
// +optional
TimestampField *TimestampFieldStrategy `json:"timestampField,omitempty"`
// StringField contains the details for how the CronAnything controller
// can find the string field on the resource needed to decide if the resource
// has completed. It also lists the values that mean the resource has completed.
// +optional
StringField *StringFieldStrategy `json:"stringField,omitempty"`
}
//+kubebuilder:object:generate=true
// TimestampFieldStrategy defines how the CronAnything controller can find
// a field on the resource that contains a timestamp. The contract here is that
// if the field contains a valid timestamp the resource is considered finished.
type TimestampFieldStrategy struct {
// The path to the field on the resource that contains the timestamp.
FieldPath string `json:"fieldPath"`
}
//+kubebuilder:object:generate=true
// StringFieldStrategy defines how the CronAnything controller can find and
// use the value of a field on the resource to decide if it has finished.
type StringFieldStrategy struct {
// The path to the field on the resource that contains a string value.
FieldPath string `json:"fieldPath"`
// The values of the field that means the resource has completed.
FinishedValues []string `json:"finishedValues"`
}
// ResourceTimestampStrategyType specifies the strategy to use for getting
// the resource timestamp.
type ResourceTimestampStrategyType string
const (
// ResourceTimestampStrategyField specifies getting the timestamp for the
// resource from a field on the resource.
ResourceTimestampStrategyField ResourceTimestampStrategyType = "Field"
)
//+kubebuilder:object:generate=true
// ResourceTimestampStrategy specifies how the CronAnything controller can find
// the timestamp on the resource that will again decide the order in which
// resources are deleted based on the retention policy.
type ResourceTimestampStrategy struct {
// Type tells which strategy should be used.
Type ResourceTimestampStrategyType `json:"type"`
// FieldResourceTimestampStrategy specifies how the CronAnything controller
// can find the timestamp for the resource from a field.
// +optional
FieldResourceTimestampStrategy *FieldResourceTimestampStrategy `json:"field,omitempty"`
}
//+kubebuilder:object:generate=true
// FieldResourceTimestampStrategy defines how the CronAnything controller can
// find the timestamp for a resource.
type FieldResourceTimestampStrategy struct {
// The path to the field on the resource that contains the timestamp.
FieldPath string `json:"fieldPath"`
}
// ConcurrencyPolicy specifies the policy to use for concurrency control.
type ConcurrencyPolicy string
const (
// AllowConcurrent policy specifies allowing creation of new resources
// regardless of how many other currently active resources exist.
AllowConcurrent ConcurrencyPolicy = "Allow"
// ForbidConcurrent policy specifies not allowing creation of a new resource
// if any existing resources are active.
ForbidConcurrent ConcurrencyPolicy = "Forbid"
// ReplaceConcurrent policy specifies deleting any existing, active resources
// before creating a new one.
ReplaceConcurrent ConcurrencyPolicy = "Replace"
)
//+kubebuilder:object:generate=true
// CronAnythingStatus defines the observed state of CronAnything.
type CronAnythingStatus struct {
// LastScheduleTime keeps track of the scheduled time for the last
// successfully completed creation of a resource.
// This is used by the controller to determine when the next resource creation
// should happen. If creation of a resource is delayed for any reason but
// eventually does happen, this value will still be updated to the time when
// it was originally scheduled to happen.
// +optional
LastScheduleTime *metav1.Time `json:"lastScheduleTime,omitempty"`
// TriggerHistory keeps track of the status for the last 10 triggers. This
// allows users of CronAnything to see whether any triggers failed. It is
// important to know that this only keeps track of whether a trigger was
// successfully executed (as in creating the given resource), not whether the
// created resource was itself successful. For this information, any users
// of CronAnything should observe the resources created.
// +optional
TriggerHistory []TriggerHistoryRecord `json:"triggerHistory,omitempty"`
// PendingTrigger keeps track of any triggers that are past their trigger time,
// but for some reason have not been completed yet. This is typically a result
// of the create operation failing.
// +optional
PendingTrigger *PendingTrigger `json:"pendingTrigger,omitempty"`
}
//+kubebuilder:object:generate=true
// PendingTrigger keeps information about triggers that should have been
// completed, but due to some kind of error, is still pending. They will
// typically remain in this state until either the issue has been resolved and
// the resource in question can be created, the triggerDeadlineSeconds is
// reached and we stop trying, or the next trigger time is reached at which time
// we consider the previous trigger as failed.
type PendingTrigger struct {
// ScheduleTime is the time when this trigger was scheduled to be executed.
ScheduleTime metav1.Time `json:"scheduleTime"`
// Result tells why this trigger is in the pending state, i.e. what prevented
// it from completing successfully.
Result TriggerResult `json:"result"`
}
//+kubebuilder:object:generate=true
// TriggerHistoryRecord contains information about the result of a trigger. It
// can either have completed successfully, and if it did not, the record will
// provide information about what is the cause of the failure.
type TriggerHistoryRecord struct {
// ScheduleTime is the time when this trigger was scheduled to be executed.
ScheduleTime metav1.Time `json:"scheduleTime"`
// CreationTimestamp is the time when this record was created. This is thus
// also the time at which the final result of the trigger was decided.
CreationTimestamp metav1.Time `json:"creationTimestamp"`
// Result contains the outcome of a trigger. It can either be CreateSucceeded,
// which means the given resource was created as intended, or it can be one
// of several error messages.
Result TriggerResult `json:"result"`
}
// TriggerResult specifies the result of a trigger.
type TriggerResult string
const (
// TriggerResultMissed means the trigger was not able to complete until the
// next trigger fired. Thus the trigger missed its window for being executed.
TriggerResultMissed TriggerResult = "MissedSchedule"
// TriggerResultCreateFailed means the create operation for a resource failed.
// This itself doesn't cause the trigger to fail, but this status will be
// reported if failing create operations are the reason a trigger misses its
// window for being executed.
TriggerResultCreateFailed TriggerResult = "CreateFailed"
// TriggerResultCreateSucceeded means the trigger was successful.
TriggerResultCreateSucceeded TriggerResult = "CreateSucceeded"
// TriggerResultResourceLimitReached means the trigger could not be completed
// as the resource limit was reached and it is not possible to create
// additional resources.
TriggerResultResourceLimitReached TriggerResult = "ResourceLimitReached"
// TriggerResultForbidConcurrent means the trigger could not be completed as
// there is already an unfinished resource and the concurrency policy forbid
// any concurrently running resources.
TriggerResultForbidConcurrent TriggerResult = "ForbidConcurrent"
// TriggerResultDeadlineExceeded means the trigger could not be completed as
// the deadline for how delayed a trigger can be was reached.
TriggerResultDeadlineExceeded TriggerResult = "DeadlineExceeded"
)
// CronAnything represent the contract for the Anthos DB Operator compliant
// database operator providers to abide by.
type CronAnything interface {
runtime.Object
metav1.Object
CronAnythingSpec() *CronAnythingSpec
CronAnythingStatus() *CronAnythingStatus
}