@@ -18,10 +18,14 @@ package controllers
18
18
19
19
import (
20
20
"context"
21
+ "errors"
21
22
"fmt"
23
+ "sort"
24
+ "strings"
22
25
23
26
"github.com/go-logr/logr"
24
27
catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1"
28
+ "github.com/operator-framework/deppy/pkg/deppy"
25
29
"github.com/operator-framework/deppy/pkg/deppy/solver"
26
30
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
27
31
"k8s.io/apimachinery/pkg/api/equality"
@@ -136,6 +140,21 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
136
140
return ctrl.Result {}, err
137
141
}
138
142
143
+ // TODO: Checking for unsat is awkward using the current version of deppy.
144
+ // This awkwardness has been fixed in an unreleased version of deppy.
145
+ // When there is a new minor release of deppy, we can revisit this and
146
+ // simplify this to a normal error check.
147
+ // See https://github.com/operator-framework/deppy/issues/139.
148
+ unsat := deppy.NotSatisfiable {}
149
+ if ok := errors .As (solution .Error (), & unsat ); ok && len (unsat ) > 0 {
150
+ op .Status .InstalledBundleResource = ""
151
+ setInstalledStatusConditionUnknown (& op .Status .Conditions , "installation has not been attempted as resolution is unsatisfiable" , op .GetGeneration ())
152
+ op .Status .ResolvedBundleResource = ""
153
+ msg := prettyUnsatMessage (unsat )
154
+ setResolvedStatusConditionFailed (& op .Status .Conditions , msg , op .GetGeneration ())
155
+ return ctrl.Result {}, unsat
156
+ }
157
+
139
158
// lookup the bundle entity in the solution that corresponds to the
140
159
// Operator's desired package name.
141
160
bundleEntity , err := r .getBundleEntityFromSolution (solution , op .Spec .PackageName )
@@ -459,3 +478,23 @@ func operatorRequestsForCatalog(ctx context.Context, c client.Reader, logger log
459
478
return requests
460
479
}
461
480
}
481
+
482
+ // TODO: This can be removed when operator controller bumps to a
483
+ // version of deppy that contains a fix for this issue:
484
+ // https://github.com/operator-framework/deppy/issues/142
485
+
486
+ // prettyUnsatMessage ensures that the unsat message is deterministic and
487
+ // human-readable. It sorts the individual constraint strings lexicographically
488
+ // and joins them with a semicolon (rather than a comma, which the unsat.Error()
489
+ // function does). This function also has the side effect of sorting the items
490
+ // in the unsat slice.
491
+ func prettyUnsatMessage (unsat deppy.NotSatisfiable ) string {
492
+ sort .Slice (unsat , func (i , j int ) bool {
493
+ return unsat [i ].String () < unsat [j ].String ()
494
+ })
495
+ msgs := make ([]string , 0 , len (unsat ))
496
+ for _ , c := range unsat {
497
+ msgs = append (msgs , c .String ())
498
+ }
499
+ return fmt .Sprintf ("constraints not satisfiable: %s" , strings .Join (msgs , "; " ))
500
+ }
0 commit comments