Created
May 17, 2024 08:14
-
-
Save mattfield/137ac95bc0221f1245048ddb61f38a74 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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