- If a managed resource has the "crossplane.io/paused" annotation with its value
set to "true", then the managed reconciler emits an event indicating that
further reconciliations on that resource are paused and returns early after
setting a Synced status condition to false with the reason "ReconcilePaused".
Signed-off-by: Alper Rifat Ulucinar <ulucinar@users.noreply.github.com>
The primary functional change here is to avoid setting a status condition when a
deferred disconnect fails. We don't want to overwrite the original status
condition that may have been written if we're returning from Reconcile because
we hit an error. Emitting an event and a debug log should be sufficient.
This commit also tweaks a bit of grammar and updates the NopConnectDisconnecter
implementation to more closely match its docstring description.
Signed-off-by: Nic Cope <negz@rk0n.org>
I believe the Reconcile method started including a context in controller-runtime
v0.8.0, but it was never plumbed up. If I follow the contexts correctly the one
passed to Reconcile can be traced back to the one passed to mgr.Start, which is
typically a context that is cancelled on SIGTERM or SIGINT.
Signed-off-by: Nic Cope <negz@rk0n.org>
https://github.com/crossplane/crossplane-runtime/issues/285
This approach causes us to repeat ourselves a bit, but prevents issues like the
above, where refactoring caused us to accidentally overwrite a pending status
update that we hadn't committed.
Signed-off-by: Nic Cope <negz@rk0n.org>
The retry logic we use to persist critical annotations makes it difficult to
delete an annotation without potentially also deleting annotations added by
another controller (e.g. the composition logic). This commit therefore changes
the way we detect whether we might have created an external resource but not
recorded the result. Previously we relied on the presence of the 'pending'
annotation to detect this state. Now we check whether the 'pending' annotation
is newer than any 'succeeded' or 'failed' annotation.
Signed-off-by: Nic Cope <negz@rk0n.org>
This commit is intended to address two issues that we diagnosed while
investigating https://github.com/crossplane/provider-aws/issues/802.
The first issue is that controller-runtime does not guarantee reads from cache
will return the freshest version of a resource. It's possible we could create an
external resource in one reconcile, then shortly after trigger another in which
it appears that the managed resource was never created because we didn't record
its external-name. This only affects the subset of managed resources with
non-deterministic external-names that are assigned during creation.
The second issue is that some external APIs are eventually consistent. A newly
created external resource may take some time before our ExternalClient's observe
call can confirm it exists. AWS EC2 is an example of one such API.
This commit attempts to address the first issue by making an Update to a managed
resource immediately before Create it called. This Update call will be rejected
by the API server if the managed resource we read from cache was not the latest
version.
It attempts to address the second issue by allowing managed resource controller
authors to configure an optional grace period that begins when an external
resource is successfully created. During this grace period we'll requeue and
keep waiting if Observe determines that the external resource doesn't exist,
rather than (re)creating it.
Signed-off-by: Nic Cope <negz@rk0n.org>
Now that the managed reconciler will handle deletion with policy Orphan
early, there is no need to check that deletion policy is not orphan when
handling a managed resource with deletion timestamp set and external
resource exists.
Signed-off-by: hasheddan <georgedanielmangum@gmail.com>
Updates the status of managed resource to be set to deleting in the case
where an external resource does not exist, but we fail to unpublish
connection or remove finalizer.
Signed-off-by: hasheddan <georgedanielmangum@gmail.com>
Modifies managed reconciler to skip attempting to connect to external
client as well as initialize and resolve references when managed
resource has deletion timestamp and deletion policy is orphan.
Signed-off-by: hasheddan <georgedanielmangum@gmail.com>
Updates comments in managed reconciler to indicate requeues are not tied
to short wait but instead are explicit and trigger the configured
backoff strategy.
Signed-off-by: hasheddan <georgedanielmangum@gmail.com>
Updates managed reconciler to return Requeue: true instead of
RequeueAfter when encountering non-status update errors. This allows the
reconciler to make use of the controller rate limiter rather use a
constant value for requeuing after errors.
This also renames longWait to pollInterval to more accurately reflect
its behavior.
Signed-off-by: hasheddan <georgedanielmangum@gmail.com>
This updates the controller-runtime and all of its dependencies to the
latest release.
This includes a bunch of changes which break backwards compatibility
introduced by controller-runtime 0.7.0 and 0.8.0, for example:
> A number of methods that previously took runtime.Object & internally
> type-asserted them to metav1.Object now take client.Object (for non-list
> objects) or client.ObjectList (for lists). The practical upshot of this
> is more type-safety and clarity around what's required for particular
> methods.
> All concrete API types (anything that implements runtime.Object & has
> a metadata field) already implement client.Object or client.ObjectList,
> so practical impact should be limited to folks who pass around
> runtime.Object values instead of concrete types.
Signed-off-by: Sascha Grunert <mail@saschagrunert.de>
Updates all core/v1alpha1 imports to the common/v1, which is the new
home of these embedded API types.
Signed-off-by: hasheddan <georgedanielmangum@gmail.com>
A design goal of the managed.Reconciler implementation was to insulate folks who
are authoring an ExternalClient implementation from needing to interact with the
Kubernetes API directly. The separation of concerns is intended to be:
* ExternalClient accepts a managed resource struct and reconciles it with the
provider. It may update the struct it is passed, but otherwise does not
interact with the Kubernetes API.
* ExternalConnector interacts with the Kubernetes API in order to produce an
ExternalClient.
* Reconciler orchestrates the ExternalConnector and ExternalClient, propagating
updates from the ExeternalClient back to the Kubernetes API as necessary.
The desire to late initialize managed resources sullied this separation of
concern (or single responsibility) by plumbing a Kubernetes client down into the
ExternalClient implementations. I believe this was done because:
* We must update the resource spec before we update its status, or changes made
to the status will be overwritten.
* We don't want to update the resource spec on every reconcile if it's possible
to avoid doing so.
This small change to the managed resource reconciler allows an ExternalClient to
signal that it has late initialized a managed resource, and thus defer updating
that managed resource to the Reconciler. I believe this change is backward
compatible (ExternalClient implementations could continue to 'manually' late
initialize the resource and not return ResourceLateInitialized).
Signed-off-by: Nic Cope <negz@rk0n.org>