@@ -6,12 +6,11 @@ import (
6
6
corev1 "k8s.io/api/core/v1"
7
7
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8
8
"k8s.io/apimachinery/pkg/types"
9
- utilruntime "k8s.io/apimachinery/pkg/util/runtime"
10
9
11
10
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
12
11
clientv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned/typed/operators/v1alpha1"
12
+ "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/comparison"
13
13
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubestate"
14
- "github.com/pkg/errors"
15
14
)
16
15
17
16
// SubscriptionState describes subscription states.
@@ -57,7 +56,7 @@ type SubscriptionDeletedState interface {
57
56
58
57
// CatalogHealthState describes subscription states that represent a subscription with respect to catalog health.
59
58
type CatalogHealthState interface {
60
- SubscriptionState
59
+ SubscriptionExistsState
61
60
62
61
isCatalogHealthState ()
63
62
@@ -87,6 +86,61 @@ type CatalogUnhealthyState interface {
87
86
isCatalogUnhealthyState ()
88
87
}
89
88
89
+ // InstallPlanState describes Subscription states with respect to an InstallPlan.
90
+ type InstallPlanState interface {
91
+ SubscriptionExistsState
92
+
93
+ isInstallPlanState ()
94
+
95
+ CheckReference () InstallPlanState
96
+ }
97
+
98
+ type NoInstallPlanReferencedState interface {
99
+ InstallPlanState
100
+
101
+ isNoInstallPlanReferencedState ()
102
+ }
103
+
104
+ type InstallPlanReferencedState interface {
105
+ InstallPlanState
106
+
107
+ isInstallPlanReferencedState ()
108
+
109
+ InstallPlanNotFound (now * metav1.Time , client clientv1alpha1.SubscriptionInterface ) (InstallPlanReferencedState , error )
110
+
111
+ CheckInstallPlanStatus (now * metav1.Time , client clientv1alpha1.SubscriptionInterface , status * v1alpha1.InstallPlanStatus ) (InstallPlanReferencedState , error )
112
+ }
113
+
114
+ type InstallPlanKnownState interface {
115
+ InstallPlanReferencedState
116
+
117
+ isInstallPlanKnownState ()
118
+ }
119
+
120
+ type InstallPlanMissingState interface {
121
+ InstallPlanKnownState
122
+
123
+ isInstallPlanMissingState ()
124
+ }
125
+
126
+ type InstallPlanPendingState interface {
127
+ InstallPlanKnownState
128
+
129
+ isInstallPlanPendingState ()
130
+ }
131
+
132
+ type InstallPlanFailedState interface {
133
+ InstallPlanKnownState
134
+
135
+ isInstallPlanFailedState ()
136
+ }
137
+
138
+ type InstallPlanInstalledState interface {
139
+ InstallPlanKnownState
140
+
141
+ isInstallPlanInstalledState ()
142
+ }
143
+
90
144
type subscriptionState struct {
91
145
kubestate.State
92
146
@@ -236,7 +290,6 @@ func (c *catalogHealthState) UpdateHealth(now *metav1.Time, client clientv1alpha
236
290
}
237
291
238
292
if ! update && cond .Equals (in .Status .GetCondition (v1alpha1 .SubscriptionCatalogSourcesUnhealthy )) {
239
- utilruntime .HandleError (errors .New ("nothing has changed, returning same state" ))
240
293
// Nothing to do, transition to self
241
294
return known , nil
242
295
}
@@ -285,3 +338,191 @@ type catalogUnhealthyState struct {
285
338
}
286
339
287
340
func (c * catalogUnhealthyState ) isCatalogUnhealthyState () {}
341
+
342
+ type installPlanState struct {
343
+ SubscriptionExistsState
344
+ }
345
+
346
+ func (i * installPlanState ) isInstallPlanState () {}
347
+
348
+ func (i * installPlanState ) CheckReference () InstallPlanState {
349
+ if i .Subscription ().Status .InstallPlanRef != nil {
350
+ return & installPlanReferencedState {
351
+ InstallPlanState : i ,
352
+ }
353
+ }
354
+
355
+ return & noInstallPlanReferencedState {
356
+ InstallPlanState : i ,
357
+ }
358
+ }
359
+
360
+ func newInstallPlanState (s SubscriptionExistsState ) InstallPlanState {
361
+ return & installPlanState {
362
+ SubscriptionExistsState : s ,
363
+ }
364
+ }
365
+
366
+ type noInstallPlanReferencedState struct {
367
+ InstallPlanState
368
+ }
369
+
370
+ func (n * noInstallPlanReferencedState ) isNoInstallPlanReferencedState () {}
371
+
372
+ type installPlanReferencedState struct {
373
+ InstallPlanState
374
+ }
375
+
376
+ func (i * installPlanReferencedState ) isInstallPlanReferencedState () {}
377
+
378
+ var hashEqual = comparison .NewHashEqualitor ()
379
+
380
+ func (i * installPlanReferencedState ) InstallPlanNotFound (now * metav1.Time , client clientv1alpha1.SubscriptionInterface ) (InstallPlanReferencedState , error ) {
381
+ in := i .Subscription ()
382
+ out := in .DeepCopy ()
383
+
384
+ // Remove pending and failed conditions
385
+ out .Status .RemoveConditions (v1alpha1 .SubscriptionInstallPlanPending , v1alpha1 .SubscriptionInstallPlanFailed )
386
+
387
+ // Set missing condition to true
388
+ missingCond := out .Status .GetCondition (v1alpha1 .SubscriptionInstallPlanMissing )
389
+ missingCond .Status = corev1 .ConditionTrue
390
+ missingCond .Reason = v1alpha1 .ReferencedInstallPlanNotFound
391
+ missingCond .LastTransitionTime = now
392
+ out .Status .SetCondition (missingCond )
393
+
394
+ // Build missing state
395
+ missingState := & installPlanMissingState {
396
+ InstallPlanKnownState : & installPlanKnownState {
397
+ InstallPlanReferencedState : i ,
398
+ },
399
+ }
400
+
401
+ // Bail out if the conditions haven't changed (using select fields included in a hash)
402
+ if hashEqual (out .Status .Conditions , in .Status .Conditions ) {
403
+ return missingState , nil
404
+ }
405
+
406
+ // Update the Subscription
407
+ out .Status .LastUpdated = * now
408
+ updated , err := client .UpdateStatus (out )
409
+ if err != nil {
410
+ return i , err
411
+ }
412
+
413
+ // Stuff updated Subscription into state
414
+ missingState .setSubscription (updated )
415
+
416
+ return missingState , nil
417
+ }
418
+
419
+ func (i * installPlanReferencedState ) CheckInstallPlanStatus (now * metav1.Time , client clientv1alpha1.SubscriptionInterface , status * v1alpha1.InstallPlanStatus ) (InstallPlanReferencedState , error ) {
420
+ in := i .Subscription ()
421
+ out := in .DeepCopy ()
422
+
423
+ // Remove missing, pending, and failed conditions
424
+ out .Status .RemoveConditions (v1alpha1 .SubscriptionInstallPlanMissing , v1alpha1 .SubscriptionInstallPlanPending , v1alpha1 .SubscriptionInstallPlanFailed )
425
+
426
+ // Build and set the InstallPlan condition, if any
427
+ cond := v1alpha1.SubscriptionCondition {
428
+ Status : corev1 .ConditionUnknown ,
429
+ LastTransitionTime : now ,
430
+ }
431
+
432
+ // TODO: Use InstallPlan conditions instead of phases
433
+ // Get the status of the InstallPlan and create the appropriate condition and state
434
+ var known InstallPlanKnownState
435
+ switch phase := status .Phase ; phase {
436
+ case v1alpha1 .InstallPlanPhaseNone :
437
+ // Set reason and let the following case fill out the pending condition
438
+ cond .Reason = v1alpha1 .InstallPlanNotYetReconciled
439
+ fallthrough
440
+ case v1alpha1 .InstallPlanPhasePlanning , v1alpha1 .InstallPlanPhaseInstalling , v1alpha1 .InstallPlanPhaseRequiresApproval :
441
+ if cond .Reason == "" {
442
+ cond .Reason = string (phase )
443
+ }
444
+
445
+ cond .Type = v1alpha1 .SubscriptionInstallPlanPending
446
+ cond .Status = corev1 .ConditionTrue
447
+ out .Status .SetCondition (cond )
448
+
449
+ // Build pending state
450
+ known = & installPlanPendingState {
451
+ InstallPlanKnownState : & installPlanKnownState {
452
+ InstallPlanReferencedState : i ,
453
+ },
454
+ }
455
+ case v1alpha1 .InstallPlanPhaseFailed :
456
+ // Attempt to project reason from failed InstallPlan condition
457
+ if installedCond := status .GetCondition (v1alpha1 .InstallPlanInstalled ); installedCond .Status == corev1 .ConditionFalse {
458
+ cond .Reason = string (installedCond .Reason )
459
+ } else {
460
+ cond .Reason = v1alpha1 .InstallPlanFailed
461
+ }
462
+
463
+ cond .Type = v1alpha1 .SubscriptionInstallPlanFailed
464
+ cond .Status = corev1 .ConditionTrue
465
+ out .Status .SetCondition (cond )
466
+
467
+ // Build failed state
468
+ known = & installPlanFailedState {
469
+ InstallPlanKnownState : & installPlanKnownState {
470
+ InstallPlanReferencedState : i ,
471
+ },
472
+ }
473
+ default :
474
+ // Build installed state
475
+ known = & installPlanInstalledState {
476
+ InstallPlanKnownState : & installPlanKnownState {
477
+ InstallPlanReferencedState : i ,
478
+ },
479
+ }
480
+ }
481
+
482
+ // Bail out if the conditions haven't changed (using select fields included in a hash)
483
+ if hashEqual (out .Status .Conditions , in .Status .Conditions ) {
484
+ return known , nil
485
+ }
486
+
487
+ // Update the Subscription
488
+ out .Status .LastUpdated = * now
489
+ updated , err := client .UpdateStatus (out )
490
+ if err != nil {
491
+ return i , err
492
+ }
493
+
494
+ // Stuff updated Subscription into state
495
+ known .setSubscription (updated )
496
+
497
+ return known , nil
498
+ }
499
+
500
+ type installPlanKnownState struct {
501
+ InstallPlanReferencedState
502
+ }
503
+
504
+ func (i * installPlanKnownState ) isInstallPlanKnownState () {}
505
+
506
+ type installPlanMissingState struct {
507
+ InstallPlanKnownState
508
+ }
509
+
510
+ func (i * installPlanMissingState ) isInstallPlanMissingState () {}
511
+
512
+ type installPlanPendingState struct {
513
+ InstallPlanKnownState
514
+ }
515
+
516
+ func (i * installPlanPendingState ) isInstallPlanPendingState () {}
517
+
518
+ type installPlanFailedState struct {
519
+ InstallPlanKnownState
520
+ }
521
+
522
+ func (i * installPlanFailedState ) isInstallPlanFailedState () {}
523
+
524
+ type installPlanInstalledState struct {
525
+ InstallPlanKnownState
526
+ }
527
+
528
+ func (i * installPlanInstalledState ) isInstallPlanInstalledState () {}
0 commit comments