Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions internal/controller/argo.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"log"
"os"
"slices"
"strconv"
"strings"

Expand Down Expand Up @@ -961,3 +962,25 @@ func updateHelmParameter(goal api.PatternParameter, actual []argoapi.HelmParamet
}
return false
}

// syncApplicationWithPrune syncs the application with prune and force options if such a sync is not already in progress.
// Returns true if a sync with prune and force is already in progress, false otherwise
func syncApplicationWithPrune(client argoclient.Interface, app *argoapi.Application, namespace string) (bool, error) {
if app.Operation != nil && app.Operation.Sync != nil && app.Operation.Sync.Prune && slices.Contains(app.Operation.Sync.SyncOptions, "Force=true") {
return true, nil
}

app.Operation = &argoapi.Operation{
Sync: &argoapi.SyncOperation{
Prune: true,
SyncOptions: []string{"Force=true"},
},
}

_, err := client.ArgoprojV1alpha1().Applications(namespace).Update(context.Background(), app, metav1.UpdateOptions{})
if err != nil {
return false, fmt.Errorf("failed to sync application %q with prune: %w", app.Name, err)
}

return true, nil
}
37 changes: 34 additions & 3 deletions internal/controller/pattern_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,14 @@ func (r *PatternReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct

// -- GitOps Subscription
targetSub, _ := newSubscriptionFromConfigMap(r.fullClient)
_ = controllerutil.SetOwnerReference(qualifiedInstance, targetSub, r.Scheme)
operatorConfigMap, err := GetOperatorConfigmap()
if err == nil {
if err := controllerutil.SetOwnerReference(operatorConfigMap, targetSub, r.Scheme); err != nil {
return r.actionPerformed(qualifiedInstance, "error setting owner of gitops subscription", err)
}
} else {
return r.actionPerformed(qualifiedInstance, "error getting operator configmap", err)
}

sub, _ := getSubscription(r.olmClient, targetSub.Name)
if sub == nil {
Expand All @@ -176,7 +183,20 @@ func (r *PatternReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return r.actionPerformed(qualifiedInstance, "update gitops subscription", errSub)
}
} else {
logOnce("The gitops subscription is not owned by us, leaving untouched")
// Historically the subscription was owned by the pattern, not the operator. If this is the case,
// we update the owner reference to the operator itself.
if err := controllerutil.RemoveOwnerReference(qualifiedInstance, sub, r.Scheme); err == nil {
if err := controllerutil.SetOwnerReference(operatorConfigMap, sub, r.Scheme); err != nil {
return r.actionPerformed(qualifiedInstance, "error setting patterns operator owner reference of gitops subscription", err)
}
// Persist the updated ownerReferences on the Subscription
if _, err := r.olmClient.OperatorsV1alpha1().Subscriptions(SubscriptionNamespace).Update(context.Background(), sub, metav1.UpdateOptions{}); err != nil {
return r.actionPerformed(qualifiedInstance, "error updating gitops subscription owner references", err)
}
return r.actionPerformed(qualifiedInstance, "updated patterns operator owner reference of gitops subscription", nil)
} else {
logOnce("The gitops subscription is not owned by us, leaving untouched")
}
}
logOnce("subscription found")

Expand Down Expand Up @@ -528,6 +548,16 @@ func (r *PatternReconciler) finalizeObject(instance *api.Pattern) error {
return fmt.Errorf("updated application %q for removal", app.Name)
}

if app.Status.Sync.Status == argoapi.SyncStatusCodeOutOfSync {
inProgress, err := syncApplicationWithPrune(r.argoClient, app, ns)
if err != nil {
return err
}
if inProgress {
return fmt.Errorf("sync with prune and force is already in progress for application %q", app.Name)
}
}

if haveACMHub(r) {
return fmt.Errorf("waiting for removal of that acm hub")
}
Expand Down Expand Up @@ -604,7 +634,8 @@ func (r *PatternReconciler) onReconcileErrorWithRequeue(p *api.Pattern, reason s
}
if duration != nil {
log.Printf("Requeueing\n")
return reconcile.Result{RequeueAfter: *duration}, err
// Return nil error when we have a duration to avoid exponential backoff
return reconcile.Result{RequeueAfter: *duration}, nil
}
return reconcile.Result{}, err
}
Expand Down
15 changes: 15 additions & 0 deletions internal/controller/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
ctrl "sigs.k8s.io/controller-runtime"

configv1 "github.com/openshift/api/config/v1"
)
Expand Down Expand Up @@ -404,3 +405,17 @@ func IsCommonSlimmed(patternPath string) bool {
}
return true
}

// Gets the configmap for the Patterns Operator. (Used as an owner reference for the operator itself.)
func GetOperatorConfigmap() (*corev1.ConfigMap, error) {
config, err := ctrl.GetConfig()
if err != nil {
return nil, fmt.Errorf("failed to get config: %s", err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("failed to call NewForConfig: %s", err)
}

return clientset.CoreV1().ConfigMaps(OperatorNamespace).Get(context.Background(), OperatorConfigMap, metav1.GetOptions{})
}