Skip to content

Commit

Permalink
pkg/ansible/controller: Update api reader to use client (operator-fra…
Browse files Browse the repository at this point in the history
…mework#1054)

* Handle case when CR is changed while we are working on it.
  To handle this we will return and just re-run the reconcile
  this should be fine due to eventually consistent model.
  • Loading branch information
Shawn Hurley committed Mar 8, 2019
1 parent 90afe95 commit c366d2a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 10 deletions.
10 changes: 6 additions & 4 deletions pkg/ansible/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ func Add(mgr manager.Manager, options Options) *controller.Controller {
options.EventHandlers = []events.EventHandler{}
}
eventHandlers := append(options.EventHandlers, events.NewLoggingEventHandler(options.LoggingLevel))
apiReader, err := client.New(mgr.GetConfig(), client.Options{})
if err != nil {
log.Error(err, "Unable to get new api client")
}

aor := &AnsibleOperatorReconciler{
// The default client will use the DelegatingReader for reads
Expand All @@ -65,9 +69,7 @@ func Add(mgr manager.Manager, options Options) *controller.Controller {
Writer: mgr.GetClient(),
StatusClient: mgr.GetClient(),
},
// This works because unstrucutred calls will go to the
// API by default.
APIReader: mgr.GetClient(),
APIReader: apiReader,
GVK: options.GVK,
Runner: options.Runner,
EventHandlers: eventHandlers,
Expand All @@ -76,7 +78,7 @@ func Add(mgr manager.Manager, options Options) *controller.Controller {
}

scheme := mgr.GetScheme()
_, err := scheme.New(options.GVK)
_, err = scheme.New(options.GVK)
if runtime.IsNotRegisteredError(err) {
// Register the GVK with the schema
scheme.AddKnownTypeWithName(options.GVK, &unstructured.Unstructured{})
Expand Down
33 changes: 27 additions & 6 deletions pkg/ansible/controller/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(request reconcile.Request) (reconc
finalizers := append(pendingFinalizers, finalizer)
u.SetFinalizers(finalizers)
err := r.Client.Update(context.TODO(), u)
if err != nil {
if exit, err := determineReturn(err); exit {
return reconcileResult, err
}
}
Expand All @@ -111,14 +111,14 @@ func (r *AnsibleOperatorReconciler) Reconcile(request reconcile.Request) (reconc
logger.V(1).Info("Spec was not found")
u.Object["spec"] = map[string]interface{}{}
err = r.Client.Update(context.TODO(), u)
if err != nil {
if exit, err := determineReturn(err); exit {
return reconcileResult, err
}
}

if r.ManageStatus {
err = r.markRunning(u, request.NamespacedName)
if err != nil {
if exit, err := determineReturn(err); exit {
return reconcileResult, err
}
}
Expand Down Expand Up @@ -179,6 +179,7 @@ func (r *AnsibleOperatorReconciler) Reconcile(request reconcile.Request) (reconc

err = r.APIReader.Get(context.TODO(), request.NamespacedName, u)
if err != nil {
log.Error(err, "Unable to get updated object from api")
return reconcile.Result{}, err
}

Expand All @@ -194,16 +195,17 @@ func (r *AnsibleOperatorReconciler) Reconcile(request reconcile.Request) (reconc
}
u.SetFinalizers(finalizers)
err := r.Client.Update(context.TODO(), u)
if err != nil {
if exit, err := determineReturn(err); exit {
return reconcileResult, err
}
return reconcileResult, nil
}
if r.ManageStatus {
err = r.markDone(u, request.NamespacedName, statusEvent, failureMessages)
if err != nil {
logger.Error(err, "Failed to mark status done")
if exit, err := determineReturn(err); exit {
return reconcileResult, err
}

}
return reconcileResult, err
}
Expand Down Expand Up @@ -235,6 +237,7 @@ func (r *AnsibleOperatorReconciler) markRunning(u *unstructured.Unstructured, na
if err != nil {
return err
}

}
return nil
}
Expand Down Expand Up @@ -285,3 +288,21 @@ func contains(l []string, s string) bool {
}
return false
}

// determineReturn - if the object was updated outside of our controller
// this means that the current reconcilation is over and we should use the
// latest version. To do this, we just exit without error because the
// latest version should be queued for update.
func determineReturn(err error) (bool, error) {
exit := false
if err == nil {
return exit, err
}
exit = true

if apierrors.IsConflict(err) {
log.V(1).Info("Conflict found during an update; re-running reconcilation")
return exit, nil
}
return exit, err
}

0 comments on commit c366d2a

Please sign in to comment.