Skip to content

Instantly share code, notes, and snippets.

@mattfield
Created May 17, 2024 08:14
Show Gist options
  • Save mattfield/137ac95bc0221f1245048ddb61f38a74 to your computer and use it in GitHub Desktop.
Save mattfield/137ac95bc0221f1245048ddb61f38a74 to your computer and use it in GitHub Desktop.
func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) {
cr, ok := mg.(*v1alpha1.MyType)
if !ok {
return managed.ExternalObservation{}, errors.New(errNotMyType)
}
// Fetch the current external resource by whatever unique identifier you
// use for it's name (cr.Status.PipelineID is just an example), or do
// c.client.List to get a list of all external resources that, say, have
// a field that matches a certain value or whatever fields that, when
// changed in your CR, would require starting a new pipeline
//
// Fetch the existing external resource based on pipelineID used as its name
existing, err := c.client.Get(ctx, cr.Status.PipelineID)
// or, list potentially multiple external resources based on field, labels, whatever
// makes sense for your use case. You can then iterate over these results and decide
// whether a new external object/pipeline needs creating. These fields might not necessarily
// be searchable by default, so if they aren't then look at `mgr.GetFieldIndexer().IndexField`,
// but again this just an example
crList, ok := mg.(*v1alpha1.MyTypeList)
err := c.client.List(ctx, crList, &client.ListOptions{
FieldSelector: fields.OneTermEqualSelector(".spec.importantField", cr.Status.PipelineID), // or whatever
Namespace: cr.GetNamespace(),
})
// This won't be `client.IsNotFound`, it'll probably be a check that
// the API client provides. The important thing is to return
// `ResourceExists: false` if the lookup above fails.
if client.IsNotFound(err) {
return managed.ExternalObservation{ResourceExists: false}, nil
}
// Any other errors are wrapped and returned to the
// managed.Reconciler. It will update the "Synced" status condition
// of the managed resource to reflect that the most recent reconcile failed
// and ensure the reconcile is reattempted after a brief wait.
if err != nil {
return managed.ExternalObservation{}, errors.Wrap(err, "cannot get pipeline")
}
// If you are creating pipelines based on a given field or
// set of fields, you need to compare those fields in your CR to the fields
// This is where you'd decide whether `existing` or `crList` was different to any
// external resource, and then return managed.ExternalObservation{ResourceExists: false}
// to prompt a new `Create` call
// These fmt statements should be removed in the real implementation.
fmt.Printf("Observing: %+v", cr)
return managed.ExternalObservation{
// Return false when the external resource does not exist. This lets
// the managed resource reconciler know that it needs to call Create to
// (re)create the resource, or that it has successfully been deleted.
ResourceExists: true,
// Return false when the external resource exists, but it not up to date
// with the desired managed resource state. This lets the managed
// resource reconciler know that it needs to call Update.
ResourceUpToDate: true,
// Return any details that may be required to connect to the external
// resource. These will be stored as the connection secret.
ConnectionDetails: managed.ConnectionDetails{},
}, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment