@@ -31,6 +31,13 @@ const (
31
31
// TODO: Move to operator-framework/api/pkg/operators/v1alpha1
32
32
// BundleLookupFailed describes conditions types for when BundleLookups fail
33
33
BundleLookupFailed operatorsv1alpha1.BundleLookupConditionType = "BundleLookupFailed"
34
+
35
+ // TODO: This can be a spec field
36
+ // BundleUnpackTimeoutAnnotationKey allows setting a bundle unpack timeout per InstallPlan
37
+ // and overrides the default specified by the --bundle-unpack-timeout flag
38
+ // The time duration should be in the same format as accepted by time.ParseDuration()
39
+ // e.g 1m30s
40
+ BundleUnpackTimeoutAnnotationKey = "bundle-unpack-timeout"
34
41
)
35
42
36
43
type BundleUnpackResult struct {
@@ -74,7 +81,7 @@ func newBundleUnpackResult(lookup *operatorsv1alpha1.BundleLookup) *BundleUnpack
74
81
}
75
82
}
76
83
77
- func (c * ConfigMapUnpacker ) job (cmRef * corev1.ObjectReference , bundlePath string , secrets []corev1.LocalObjectReference ) * batchv1.Job {
84
+ func (c * ConfigMapUnpacker ) job (cmRef * corev1.ObjectReference , bundlePath string , secrets []corev1.LocalObjectReference , ipAnnotations map [ string ] string ) * batchv1.Job {
78
85
job := & batchv1.Job {
79
86
Spec : batchv1.JobSpec {
80
87
//ttlSecondsAfterFinished: 0 // can use in the future to not have to clean up job
@@ -178,12 +185,6 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
178
185
job .SetName (cmRef .Name )
179
186
job .SetOwnerReferences ([]metav1.OwnerReference {ownerRef (cmRef )})
180
187
181
- // Don't set a timeout if it is 0
182
- if c .unpackTimeout != time .Duration (0 ) {
183
- t := int64 (c .unpackTimeout .Seconds ())
184
- job .Spec .ActiveDeadlineSeconds = & t
185
- }
186
-
187
188
// By default the BackoffLimit is set to 6 which with exponential backoff 10s + 20s + 40s ...
188
189
// translates to ~10m of waiting time.
189
190
// We want to fail faster than that when we have repeated failures from the bundle unpack pod
@@ -193,13 +194,38 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
193
194
backOffLimit := int32 (3 )
194
195
job .Spec .BackoffLimit = & backOffLimit
195
196
197
+ // Set ActiveDeadlineSeconds as the unpack timeout
198
+ // Don't set a timeout if it is 0
199
+ if c .unpackTimeout != time .Duration (0 ) {
200
+ t := int64 (c .unpackTimeout .Seconds ())
201
+ job .Spec .ActiveDeadlineSeconds = & t
202
+ }
203
+
204
+ // The bundle timeout annotation if specified overrides the --bundle-unpack-timeout flag value
205
+ timeoutStr , ok := ipAnnotations [BundleUnpackTimeoutAnnotationKey ]
206
+ if ! ok {
207
+ return job
208
+ }
209
+ d , err := time .ParseDuration (timeoutStr )
210
+ if err != nil {
211
+ // TODO(haseeb): log this error
212
+ return job
213
+ }
214
+ if d == time .Duration (0 ) {
215
+ // 0 means no timeout
216
+ return job
217
+ }
218
+
219
+ timeoutSeconds := int64 (d .Seconds ())
220
+ job .Spec .ActiveDeadlineSeconds = & timeoutSeconds
221
+
196
222
return job
197
223
}
198
224
199
225
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Unpacker
200
226
201
227
type Unpacker interface {
202
- UnpackBundle (lookup * operatorsv1alpha1.BundleLookup ) (result * BundleUnpackResult , err error )
228
+ UnpackBundle (lookup * operatorsv1alpha1.BundleLookup , ipAnnotations map [ string ] string ) (result * BundleUnpackResult , err error )
203
229
}
204
230
205
231
type ConfigMapUnpacker struct {
@@ -346,7 +372,8 @@ const (
346
372
NotUnpackedMessage = "bundle contents have not yet been persisted to installplan status"
347
373
)
348
374
349
- func (c * ConfigMapUnpacker ) UnpackBundle (lookup * operatorsv1alpha1.BundleLookup ) (result * BundleUnpackResult , err error ) {
375
+ func (c * ConfigMapUnpacker ) UnpackBundle (lookup * operatorsv1alpha1.BundleLookup , ipAnnotations map [string ]string ) (result * BundleUnpackResult , err error ) {
376
+
350
377
result = newBundleUnpackResult (lookup )
351
378
352
379
// if bundle lookup failed condition already present, then there is nothing more to do
@@ -355,26 +382,22 @@ func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup)
355
382
return result , nil
356
383
}
357
384
358
- // if pending condition is missing, bundle has already been unpacked
359
- cond := result .GetCondition (operatorsv1alpha1 .BundleLookupPending )
360
- if cond .Status == corev1 .ConditionUnknown {
361
- return result , nil
362
- }
363
- // if pending condition is false, bundle unpack has already failed so nothing more to do
364
- if cond .Status == corev1 .ConditionFalse {
385
+ // if pending condition is not true then bundle has already been unpacked(unknown) or failed(false)
386
+ pendingCond := result .GetCondition (operatorsv1alpha1 .BundleLookupPending )
387
+ if pendingCond .Status != corev1 .ConditionTrue {
365
388
return result , nil
366
389
}
367
390
368
391
now := c .now ()
369
392
370
393
var cs * operatorsv1alpha1.CatalogSource
371
394
if cs , err = c .csLister .CatalogSources (result .CatalogSourceRef .Namespace ).Get (result .CatalogSourceRef .Name ); err != nil {
372
- if apierrors .IsNotFound (err ) && cond .Reason != CatalogSourceMissingReason {
373
- cond .Status = corev1 .ConditionTrue
374
- cond .Reason = CatalogSourceMissingReason
375
- cond .Message = CatalogSourceMissingMessage
376
- cond .LastTransitionTime = & now
377
- result .SetCondition (cond )
395
+ if apierrors .IsNotFound (err ) && pendingCond .Reason != CatalogSourceMissingReason {
396
+ pendingCond .Status = corev1 .ConditionTrue
397
+ pendingCond .Reason = CatalogSourceMissingReason
398
+ pendingCond .Message = CatalogSourceMissingMessage
399
+ pendingCond .LastTransitionTime = & now
400
+ result .SetCondition (pendingCond )
378
401
err = nil
379
402
}
380
403
@@ -412,7 +435,7 @@ func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup)
412
435
secrets = append (secrets , corev1.LocalObjectReference {Name : secretName })
413
436
}
414
437
var job * batchv1.Job
415
- job , err = c .ensureJob (cmRef , result .Path , secrets )
438
+ job , err = c .ensureJob (cmRef , result .Path , secrets , ipAnnotations )
416
439
if err != nil {
417
440
return
418
441
}
@@ -429,18 +452,16 @@ func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup)
429
452
result .SetCondition (failedCond )
430
453
431
454
// BundleLookupPending is false with reason being job failed
432
- cond .Status = corev1 .ConditionFalse
433
- cond .Reason = JobFailedReason
434
- cond .Message = JobFailedMessage
435
- cond .LastTransitionTime = & now
436
- result .SetCondition (cond )
455
+ pendingCond .Status = corev1 .ConditionFalse
456
+ pendingCond .Reason = JobFailedReason
457
+ pendingCond .Message = JobFailedMessage
458
+ pendingCond .LastTransitionTime = & now
459
+ result .SetCondition (pendingCond )
437
460
438
461
return
439
462
}
440
463
441
- isComplete , _ := jobConditionTrue (job , batchv1 .JobComplete )
442
- if ! isComplete {
443
-
464
+ if isComplete , _ := jobConditionTrue (job , batchv1 .JobComplete ); ! isComplete {
444
465
// In the case of an image pull failure for a non-existent image the bundle unpack job
445
466
// can stay pending until the ActiveDeadlineSeconds timeout ~10m
446
467
// To indicate why it's pending we inspect the container statuses of the
@@ -457,12 +478,12 @@ func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup)
457
478
}
458
479
459
480
// Update BundleLookupPending condition if there are any changes
460
- if cond .Status != corev1 .ConditionTrue || cond .Reason != JobIncompleteReason || cond .Message != pendingMessage {
461
- cond .Status = corev1 .ConditionTrue
462
- cond .Reason = JobIncompleteReason
463
- cond .Message = pendingMessage
464
- cond .LastTransitionTime = & now
465
- result .SetCondition (cond )
481
+ if pendingCond .Status != corev1 .ConditionTrue || pendingCond .Reason != JobIncompleteReason || pendingCond .Message != pendingMessage {
482
+ pendingCond .Status = corev1 .ConditionTrue
483
+ pendingCond .Reason = JobIncompleteReason
484
+ pendingCond .Message = pendingMessage
485
+ pendingCond .LastTransitionTime = & now
486
+ result .SetCondition (pendingCond )
466
487
}
467
488
468
489
return
@@ -516,7 +537,7 @@ func (c *ConfigMapUnpacker) pendingContainerStatusMessages(job *batchv1.Job) (st
516
537
517
538
// Aggregate the wait reasons for all pending containers
518
539
containerStatusMessages = containerStatusMessages +
519
- fmt .Sprintf ("Unpack pod(%s/%s) container(%s) is pending. Reason: %s, Message: %s \n " ,
540
+ fmt .Sprintf ("Unpack pod(%s/%s) container(%s) is pending. Reason: %s, Message: %s | " ,
520
541
pod .Namespace , pod .Name , ic .Name , ic .State .Waiting .Reason , ic .State .Waiting .Message )
521
542
}
522
543
}
@@ -538,8 +559,8 @@ func (c *ConfigMapUnpacker) ensureConfigmap(csRef *corev1.ObjectReference, name
538
559
return
539
560
}
540
561
541
- func (c * ConfigMapUnpacker ) ensureJob (cmRef * corev1.ObjectReference , bundlePath string , secrets []corev1.LocalObjectReference ) (job * batchv1.Job , err error ) {
542
- fresh := c .job (cmRef , bundlePath , secrets )
562
+ func (c * ConfigMapUnpacker ) ensureJob (cmRef * corev1.ObjectReference , bundlePath string , secrets []corev1.LocalObjectReference , ipAnnotations map [ string ] string ) (job * batchv1.Job , err error ) {
563
+ fresh := c .job (cmRef , bundlePath , secrets , ipAnnotations )
543
564
job , err = c .jobLister .Jobs (fresh .GetNamespace ()).Get (fresh .GetName ())
544
565
if err != nil {
545
566
if apierrors .IsNotFound (err ) {
0 commit comments