Skip to content

Commit 45a21b9

Browse files
committed
Using subscription change to drive the installplan recreation
Signed-off-by: Vu Dinh <[email protected]>
1 parent 037e372 commit 45a21b9

File tree

3 files changed

+56
-35
lines changed

3 files changed

+56
-35
lines changed

pkg/controller/operators/catalog/operator.go

+46-16
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
2222
"k8s.io/apiextensions-apiserver/pkg/apiserver/validation"
2323
extinf "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
24-
k8serrors "k8s.io/apimachinery/pkg/api/errors"
2524
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2625
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2726
"k8s.io/apimachinery/pkg/labels"
@@ -832,6 +831,12 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
832831
return err
833832
}
834833

834+
ips, err := o.listInstallPlansMap(namespace)
835+
if err != nil {
836+
logger.WithError(err).Debug("couldn't list installplan")
837+
return err
838+
}
839+
835840
// TODO: parallel
836841
maxGeneration := 0
837842
subscriptionUpdated := false
@@ -848,7 +853,7 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error {
848853
}
849854

850855
// ensure the installplan reference is correct
851-
sub, changedIP, err := o.ensureSubscriptionInstallPlanState(logger, sub)
856+
sub, changedIP, err := o.ensureSubscriptionInstallPlanState(logger, sub, ips)
852857
if err != nil {
853858
logger.Debugf("error ensuring installplan state: %v", err)
854859
return err
@@ -941,30 +946,41 @@ func (o *Operator) syncSubscriptions(obj interface{}) error {
941946
}
942947

943948
func (o *Operator) nothingToUpdate(logger *logrus.Entry, sub *v1alpha1.Subscription) bool {
944-
if sub.Status.InstallPlanRef != nil && sub.Status.State == v1alpha1.SubscriptionStateUpgradePending {
945-
if o.isInstallPlanMissing(sub) {
946-
return false
947-
}
948-
logger.Debugf("skipping update: installplan already created")
949-
return true
950-
}
951949
// Only sync if catalog has been updated since last sync time
952950
if o.sourcesLastUpdate.Before(sub.Status.LastUpdated.Time) && sub.Status.State != v1alpha1.SubscriptionStateNone && sub.Status.State != v1alpha1.SubscriptionStateUpgradeAvailable {
953951
logger.Debugf("skipping update: no new updates to catalog since last sync at %s", sub.Status.LastUpdated.String())
954952
return true
955953
}
954+
if sub.Status.InstallPlanRef != nil && sub.Status.State == v1alpha1.SubscriptionStateUpgradePending {
955+
logger.Debugf("skipping update: installplan already created")
956+
return true
957+
}
956958
return false
957959
}
958960

959-
// isInstallPlanMissing checks if the installplan is missing or not
960-
func (o *Operator) isInstallPlanMissing(sub *v1alpha1.Subscription) bool {
961-
_, err := o.client.OperatorsV1alpha1().InstallPlans(sub.GetNamespace()).Get(context.TODO(), sub.Status.Install.Name, metav1.GetOptions{})
962-
return k8serrors.IsNotFound(err)
961+
// checkMissingInstallPlan checks if the installplan is missing or not when
962+
// the subscription is in pending upgrade state
963+
func (o *Operator) checkMissingInstallPlan(sub *v1alpha1.Subscription, ips map[string]struct{}) (*v1alpha1.Subscription, bool, error) {
964+
_, ok := ips[sub.Status.InstallPlanRef.Name]
965+
if !ok && sub.Status.State == v1alpha1.SubscriptionStateUpgradePending {
966+
out := sub.DeepCopy()
967+
out.Status.InstallPlanRef = nil
968+
out.Status.Install = nil
969+
out.Status.CurrentCSV = ""
970+
out.Status.State = v1alpha1.SubscriptionStateNone
971+
out.Status.LastUpdated = o.now()
972+
updated, err := o.client.OperatorsV1alpha1().Subscriptions(sub.GetNamespace()).UpdateStatus(context.TODO(), out, metav1.UpdateOptions{})
973+
if err != nil {
974+
return out, false, nil
975+
}
976+
return updated, true, nil
977+
}
978+
return sub, false, nil
963979
}
964980

965-
func (o *Operator) ensureSubscriptionInstallPlanState(logger *logrus.Entry, sub *v1alpha1.Subscription) (*v1alpha1.Subscription, bool, error) {
966-
if sub.Status.InstallPlanRef != nil {
967-
return sub, false, nil
981+
func (o *Operator) ensureSubscriptionInstallPlanState(logger *logrus.Entry, sub *v1alpha1.Subscription, ips map[string]struct{}) (*v1alpha1.Subscription, bool, error) {
982+
if sub.Status.InstallPlanRef != nil || sub.Status.Install != nil {
983+
return o.checkMissingInstallPlan(sub, ips)
968984
}
969985

970986
logger.Debug("checking for existing installplan")
@@ -2030,6 +2046,20 @@ func (o *Operator) listInstallPlans(namespace string) (ips []*v1alpha1.InstallPl
20302046
return
20312047
}
20322048

2049+
func (o *Operator) listInstallPlansMap(namespace string) (ips map[string]struct{}, err error) {
2050+
list, err := o.client.OperatorsV1alpha1().InstallPlans(namespace).List(context.TODO(), metav1.ListOptions{})
2051+
if err != nil {
2052+
return
2053+
}
2054+
2055+
ips = make(map[string]struct{})
2056+
for i := range list.Items {
2057+
ips[list.Items[i].GetName()] = struct{}{}
2058+
}
2059+
2060+
return
2061+
}
2062+
20332063
// competingCRDOwnersExist returns true if there exists a CSV that owns at least one of the given CSVs owned CRDs (that's not the given CSV)
20342064
func competingCRDOwnersExist(namespace string, csv *v1alpha1.ClusterServiceVersion, existingOwners map[string][]string) (bool, error) {
20352065
// Attempt to find a pre-existing owner in the namespace for any owned crd

pkg/controller/registry/resolver/step_resolver.go

+1-13
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) (
188188
}
189189

190190
// add steps for subscriptions for bundles that were added through resolution
191-
if existingSubscription != nil && (existingSubscription.Status.CurrentCSV != op.Identifier() || r.requireInstallPlanRecreate(existingSubscription)) {
191+
if existingSubscription != nil && existingSubscription.Status.CurrentCSV != op.Identifier() {
192192
// update existing subscription status
193193
existingSubscription.Status.CurrentCSV = op.Identifier()
194194
updatedSubs = append(updatedSubs, existingSubscription)
@@ -200,18 +200,6 @@ func (r *OperatorStepResolver) ResolveSteps(namespace string, _ SourceQuerier) (
200200
return steps, bundleLookups, updatedSubs, nil
201201
}
202202

203-
// requireInstallPlanRecreate checks for installplan present while subscription
204-
// is in pending state. If installplan is missing, return true. Otherwise, false.
205-
func (r *OperatorStepResolver) requireInstallPlanRecreate(sub *v1alpha1.Subscription) bool {
206-
if sub.Status.InstallPlanRef != nil && sub.Status.State == v1alpha1.SubscriptionStateUpgradePending {
207-
_, err := r.client.OperatorsV1alpha1().InstallPlans(sub.GetNamespace()).Get(context.TODO(), sub.Status.Install.Name, metav1.GetOptions{})
208-
if errors.IsNotFound(err) {
209-
return true
210-
}
211-
}
212-
return false
213-
}
214-
215203
func (r *OperatorStepResolver) hasExistingCurrentCSV(sub *v1alpha1.Subscription) (bool, error) {
216204
if sub.Status.CurrentCSV == "" {
217205
return false, nil

test/e2e/subscription_e2e_test.go

+9-6
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ var _ = Describe("Subscription", func() {
194194
})
195195

196196
// If installPlanApproval is set to manual, the installplans created should be created with approval: manual
197-
It("creation manual approval", func() {
197+
FIt("creation manual approval", func() {
198198

199199
c := newKubeClient()
200200
crc := newCRClient()
@@ -222,14 +222,17 @@ var _ = Describe("Subscription", func() {
222222
require.NoError(GinkgoT(), err)
223223

224224
var ipName string
225-
Eventually(func() (string, error) {
225+
Eventually(func() bool {
226226
fetched, err := crc.OperatorsV1alpha1().Subscriptions(testNamespace).Get(context.TODO(), "manual-subscription", metav1.GetOptions{})
227227
if err != nil {
228-
return "", err
228+
return false
229+
}
230+
if fetched.Status.Install != nil {
231+
ipName = fetched.Status.Install.Name
232+
return fetched.Status.Install.Name != installPlan.Name
229233
}
230-
ipName = fetched.Status.Install.Name
231-
return ipName, nil
232-
}).ShouldNot(Equal(installPlan.Name))
234+
return false
235+
}, 5*time.Minute, 10*time.Second).Should(BeTrue())
233236

234237
// Fetch new installplan
235238
newInstallPlan, err := fetchInstallPlan(GinkgoT(), crc, ipName, buildInstallPlanPhaseCheckFunc(v1alpha1.InstallPlanPhaseRequiresApproval))

0 commit comments

Comments
 (0)