Skip to content

Commit bb13b90

Browse files
committed
Parse timeout annotation before UnpackBundle()
1 parent 5a3b64d commit bb13b90

File tree

6 files changed

+39
-29
lines changed

6 files changed

+39
-29
lines changed

cmd/catalog/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ var (
7171
"profiling", false, "serve profiling data (on port 8080)")
7272

7373
installPlanTimeout = flag.Duration("install-plan-retry-timeout", 1*time.Minute, "time since first attempt at which plan execution errors are considered fatal")
74-
bundleUnpackTimeout = flag.Duration("bundle-unpack-timeout", 10*time.Minute, "The time duration after which the bundle unpack Job for an installplan will be aborted and the installplan will be Failed. 0 is considered as having no timeout.")
74+
bundleUnpackTimeout = flag.Duration("bundle-unpack-timeout", 10*time.Minute, "The time limit for bundle unpacking, after which InstallPlan execution is considered to have failed. 0 is considered as having no timeout.")
7575
)
7676

7777
func init() {

pkg/controller/bundle/bundle_unpacker.go

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func newBundleUnpackResult(lookup *operatorsv1alpha1.BundleLookup) *BundleUnpack
8181
}
8282
}
8383

84-
func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string, secrets []corev1.LocalObjectReference, ipAnnotations map[string]string) *batchv1.Job {
84+
func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string, secrets []corev1.LocalObjectReference, annotationUnpackTimeout time.Duration) *batchv1.Job {
8585
job := &batchv1.Job{
8686
Spec: batchv1.JobSpec{
8787
//ttlSecondsAfterFinished: 0 // can use in the future to not have to clean up job
@@ -190,7 +190,6 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
190190
// We want to fail faster than that when we have repeated failures from the bundle unpack pod
191191
// so we set it to 3 which is ~1m of waiting time
192192
// See: https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-backoff-failure-policy
193-
// TODO (haseeb): Should this be configurable as well?
194193
backOffLimit := int32(3)
195194
job.Spec.BackoffLimit = &backOffLimit
196195

@@ -201,22 +200,18 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
201200
job.Spec.ActiveDeadlineSeconds = &t
202201
}
203202

204-
// The bundle timeout annotation if specified overrides the --bundle-unpack-timeout flag value
205-
timeoutStr, ok := ipAnnotations[BundleUnpackTimeoutAnnotationKey]
206-
if !ok {
203+
// Check annotationUnpackTimeout which is the annotation override for the default unpack timeout
204+
// A negative timeout means the annotation was unset or malformed so we ignore it
205+
if annotationUnpackTimeout < time.Duration(0) {
207206
return job
208207
}
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
208+
// // 0 means no timeout so we unset ActiveDeadlineSeconds
209+
if annotationUnpackTimeout == time.Duration(0) {
210+
job.Spec.ActiveDeadlineSeconds = nil
216211
return job
217212
}
218213

219-
timeoutSeconds := int64(d.Seconds())
214+
timeoutSeconds := int64(annotationUnpackTimeout.Seconds())
220215
job.Spec.ActiveDeadlineSeconds = &timeoutSeconds
221216

222217
return job
@@ -225,7 +220,7 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
225220
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Unpacker
226221

227222
type Unpacker interface {
228-
UnpackBundle(lookup *operatorsv1alpha1.BundleLookup, ipAnnotations map[string]string) (result *BundleUnpackResult, err error)
223+
UnpackBundle(lookup *operatorsv1alpha1.BundleLookup, annotationUnpackTimeout time.Duration) (result *BundleUnpackResult, err error)
229224
}
230225

231226
type ConfigMapUnpacker struct {
@@ -372,7 +367,7 @@ const (
372367
NotUnpackedMessage = "bundle contents have not yet been persisted to installplan status"
373368
)
374369

375-
func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup, ipAnnotations map[string]string) (result *BundleUnpackResult, err error) {
370+
func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup, annotationUnpackTimeout time.Duration) (result *BundleUnpackResult, err error) {
376371

377372
result = newBundleUnpackResult(lookup)
378373

@@ -435,7 +430,7 @@ func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup,
435430
secrets = append(secrets, corev1.LocalObjectReference{Name: secretName})
436431
}
437432
var job *batchv1.Job
438-
job, err = c.ensureJob(cmRef, result.Path, secrets, ipAnnotations)
433+
job, err = c.ensureJob(cmRef, result.Path, secrets, annotationUnpackTimeout)
439434
if err != nil {
440435
return
441436
}
@@ -559,8 +554,8 @@ func (c *ConfigMapUnpacker) ensureConfigmap(csRef *corev1.ObjectReference, name
559554
return
560555
}
561556

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)
557+
func (c *ConfigMapUnpacker) ensureJob(cmRef *corev1.ObjectReference, bundlePath string, secrets []corev1.LocalObjectReference, annotationUnpackTimeout time.Duration) (job *batchv1.Job, err error) {
558+
fresh := c.job(cmRef, bundlePath, secrets, annotationUnpackTimeout)
564559
job, err = c.jobLister.Jobs(fresh.GetNamespace()).Get(fresh.GetName())
565560
if err != nil {
566561
if apierrors.IsNotFound(err) {

pkg/controller/bundle/bundle_unpacker_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,8 @@ func TestConfigMapUnpacker(t *testing.T) {
795795
)
796796
require.NoError(t, err)
797797

798-
res, err := unpacker.UnpackBundle(tt.args.lookup, map[string]string{})
798+
// The annotationUnpackTimeout arg is negative so it is ignored for these tests
799+
res, err := unpacker.UnpackBundle(tt.args.lookup, -1*time.Minute)
799800
require.Equal(t, tt.expected.err, err)
800801

801802
if tt.expected.res == nil {

pkg/controller/bundle/bundlefakes/fake_unpacker.go

Lines changed: 7 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/controller/operators/catalog/operator.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1183,10 +1183,23 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.In
11831183
out := plan.DeepCopy()
11841184
unpacked := true
11851185

1186+
// The bundle timeout annotation if specified overrides the --bundle-unpack-timeout flag value
1187+
// If the timeout cannot be parsed it's set to < 0 and subsequently ignored
1188+
unpackTimeout := -1 * time.Minute
1189+
timeoutStr, ok := plan.GetAnnotations()[bundle.BundleUnpackTimeoutAnnotationKey]
1190+
if ok {
1191+
d, err := time.ParseDuration(timeoutStr)
1192+
if err != nil {
1193+
o.logger.Errorf("failed to parse unpack timeout annotation(%s: %s): %v", bundle.BundleUnpackTimeoutAnnotationKey, timeoutStr, err)
1194+
} else {
1195+
unpackTimeout = d
1196+
}
1197+
}
1198+
11861199
var errs []error
11871200
for i := 0; i < len(out.Status.BundleLookups); i++ {
11881201
lookup := out.Status.BundleLookups[i]
1189-
res, err := o.bundleUnpacker.UnpackBundle(&lookup, plan.GetAnnotations())
1202+
res, err := o.bundleUnpacker.UnpackBundle(&lookup, unpackTimeout)
11901203
if err != nil {
11911204
errs = append(errs, err)
11921205
continue

test/e2e/installplan_e2e_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3149,14 +3149,14 @@ var _ = Describe("Install Plan", func() {
31493149
Expect(ctx.Ctx().Client().Status().Update(context.Background(), ip)).To(Succeed())
31503150

31513151
// The InstallPlan should fail after the unpack pod keeps failing and exceeds the job's
3152-
// BackoffLimit(set to 3), which with an exponential backoff (10s + 20s + 40s)= 1m10s
3152+
// BackoffLimit(set to 3), which for 4 failures is an exponential backoff (10s + 20s + 40s + 80s)= 2m30s
31533153
// so we wait a little over that.
31543154
Eventually(
31553155
func() (*operatorsv1alpha1.InstallPlan, error) {
31563156
err := ctx.Ctx().Client().Get(context.Background(), client.ObjectKeyFromObject(ip), ip)
31573157
return ip, err
31583158
},
3159-
2*time.Minute,
3159+
5*time.Minute,
31603160
).Should(HavePhase(operatorsv1alpha1.InstallPlanPhaseFailed))
31613161
})
31623162

0 commit comments

Comments
 (0)